From 7ac2d983ac4cfa73b8364c5a14bd0c5295c7cbc6 Mon Sep 17 00:00:00 2001 From: Roger Jungemann Date: Mon, 12 Jul 2021 12:44:43 -0700 Subject: [PATCH 01/96] Add xgtvm to xgt --- Rakefile | 16 + libraries/plugins/witness/CMakeLists.txt | 6 +- .../xgt/plugins/witness/witness_plugin.hpp | 1 + libraries/vendor/xgtvm/.gitignore | 3 + libraries/vendor/xgtvm/CMakeLists.txt | 22 + libraries/vendor/xgtvm/README.md | 43 + libraries/vendor/xgtvm/Rakefile | 54 + libraries/vendor/xgtvm/libraries/machine.cpp | 2511 +++++++++++++++++ libraries/vendor/xgtvm/libraries/machine.hpp | 274 ++ libraries/vendor/xgtvm/programs/xgtvm.cpp | 110 + .../vendor/xgtvm/programs/xgtvm_tests.cpp | 66 + 11 files changed, 3105 insertions(+), 1 deletion(-) create mode 100644 libraries/vendor/xgtvm/.gitignore create mode 100644 libraries/vendor/xgtvm/CMakeLists.txt create mode 100644 libraries/vendor/xgtvm/README.md create mode 100644 libraries/vendor/xgtvm/Rakefile create mode 100644 libraries/vendor/xgtvm/libraries/machine.cpp create mode 100644 libraries/vendor/xgtvm/libraries/machine.hpp create mode 100644 libraries/vendor/xgtvm/programs/xgtvm.cpp create mode 100644 libraries/vendor/xgtvm/programs/xgtvm_tests.cpp diff --git a/Rakefile b/Rakefile index 040f9708..beaf3e8b 100644 --- a/Rakefile +++ b/Rakefile @@ -403,3 +403,19 @@ namespace :contracts do p response end end + +namespace :machine do + src_dir = File.join(File.dirname(__FILE__), %(../xgtvm)) + dest_dir = File.join(File.dirname(__FILE__), %(libraries/vendor/xgtvm)) + dest_git_dir = File.join(dest_dir, '.git') + + task :clean do + FileUtils.rm_r(dest_dir) if Dir.exist?(dest_dir) + end + + task :vendor => [:clean] do + raise %(Directory #{src_dir} doesn't exist!) unless Dir.exist?(src_dir) + FileUtils.cp_r(src_dir, dest_dir) + FileUtils.rm_r(dest_git_dir) if File.exists?(dest_git_dir) + end +end diff --git a/libraries/plugins/witness/CMakeLists.txt b/libraries/plugins/witness/CMakeLists.txt index 003d0b57..feaf8517 100644 --- a/libraries/plugins/witness/CMakeLists.txt +++ b/libraries/plugins/witness/CMakeLists.txt @@ -1,5 +1,6 @@ file(GLOB HEADERS "include/xgt/plugins/witness/*.hpp") + add_library( witness_plugin witness_plugin.cpp block_producer.cpp @@ -13,9 +14,12 @@ target_link_libraries( witness_plugin xgt_chain xgt_utilities graphene_time + xgtvm ) target_include_directories( witness_plugin - PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" ) + PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" + "${CMAKE_CURRENT_SOURCE_DIR}/../../vendor/xgtvm/libraries" + ) if( CLANG_TIDY_EXE ) set_target_properties( diff --git a/libraries/plugins/witness/include/xgt/plugins/witness/witness_plugin.hpp b/libraries/plugins/witness/include/xgt/plugins/witness/witness_plugin.hpp index ef99a161..12823fdc 100644 --- a/libraries/plugins/witness/include/xgt/plugins/witness/witness_plugin.hpp +++ b/libraries/plugins/witness/include/xgt/plugins/witness/witness_plugin.hpp @@ -5,6 +5,7 @@ #include #include #include +#include #include diff --git a/libraries/vendor/xgtvm/.gitignore b/libraries/vendor/xgtvm/.gitignore new file mode 100644 index 00000000..4d1fa76a --- /dev/null +++ b/libraries/vendor/xgtvm/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +build/ +*.un~ diff --git a/libraries/vendor/xgtvm/CMakeLists.txt b/libraries/vendor/xgtvm/CMakeLists.txt new file mode 100644 index 00000000..ae896875 --- /dev/null +++ b/libraries/vendor/xgtvm/CMakeLists.txt @@ -0,0 +1,22 @@ +cmake_minimum_required( VERSION 3.2 ) +project(Xgtvm) + +#set(CMAKE_CXX_STANDARD 14) +#set(CMAKE_CXX_STANDARD_REQUIRED ON) +#set(CMAKE_CXX_EXTENSIONS OFF) + +find_package( Boost REQUIRED ) +include_directories( ${Boost_INCLUDE_DIR} ) + +# Library +add_library(xgtvm libraries/machine.cpp libraries/machine.hpp) +target_link_libraries( xgtvm LINK_PUBLIC ${Boost_LIBRARIES} ) +target_include_directories(xgtvm PRIVATE libraries) +# Executable +add_executable(xgtvmd programs/xgtvm.cpp libraries/machine.cpp libraries/machine.hpp) +target_link_libraries( xgtvmd LINK_PUBLIC ${Boost_LIBRARIES} ) +target_include_directories(xgtvmd PRIVATE libraries) +# Tests +add_executable(xgtvm_tests programs/xgtvm_tests.cpp libraries/machine.cpp libraries/machine.hpp) +target_link_libraries( xgtvm_tests LINK_PUBLIC ${Boost_LIBRARIES} ) +target_include_directories(xgtvm_tests PRIVATE libraries) diff --git a/libraries/vendor/xgtvm/README.md b/libraries/vendor/xgtvm/README.md new file mode 100644 index 00000000..43019e82 --- /dev/null +++ b/libraries/vendor/xgtvm/README.md @@ -0,0 +1,43 @@ +## TODO + +* Disable-able debug logging +* Variants on stack + +```sh +sudo apt-get install -y build-essential cmake jq libboost-all-dev +``` + +```sh +brew install cmake jq +``` + +```sh +rm -rf build # removes build artifacts +mkdir -p build # create the build directory +(cd build && cmake ..) # configure the project +(cd build && cmake --build .) # build the project +(cd build && ./xgtvm -e'60 01 00' # runs the project +``` + +To manage the project more easily, if you have Ruby installed: + +```sh +rake -T # list tasks that can be run +rake clean # removes build artifacts +rake configure # configures the project +rake make # builds the project +rake test # runs the project +rake # configures and makes the project +``` + +Example finished machine data: + +```json +{ + "returnValue": "", + "finalState": { + "pc": 5, + "stack": ["8"] + } +} +``` diff --git a/libraries/vendor/xgtvm/Rakefile b/libraries/vendor/xgtvm/Rakefile new file mode 100644 index 00000000..1732f0ba --- /dev/null +++ b/libraries/vendor/xgtvm/Rakefile @@ -0,0 +1,54 @@ +require 'json' + +def which?(cmd_name) + return false + %x([ -x "$(command -v #{cmd_name})" ] && echo yes).length > 0 +end + +def xgtvm_eval(string) + # cmd = %(cd build && ./xgtvm -e'#{string}') + cmd = %(cd build && echo '#{string}' | ./xgtvmd) + $stderr.puts(cmd) + result = %x(#{cmd}) + JSON.load(result) +end + +desc 'removes build artifacts' +task :clean do + sh %(rm -rf build) +end + +desc 'configures the project' +task :configure do + sh %(mkdir -p build) + sh %(cd build && cmake ..) +end + +desc 'builds the project' +task :make do + sh %(mkdir -p build) + sh %(cd build && cmake --build .) +end + +desc 'runs the project' +task :test do + sh %(cd build && ./xgtvm_tests) + + # result = xgtvm_eval('60 03 60 08 01 00') + result = xgtvm_eval('42 00') + p result + # stack = result.fetch('finalState').fetch('stack') + # raise 'fail' unless stack == ['11'] + + # result = xgtvm_eval('60 00 60 01 5B 60 04 57 00') + # p result + # stack = result.fetch('finalState').fetch('stack') + # raise 'fail' unless stack == [] + + # result = xgtvm_eval('42 00') + # p result + # stack = result.fetch('finalState').fetch('stack') + # raise 'fail' unless stack == [] +end + +task :default => [:configure, :make, :test] diff --git a/libraries/vendor/xgtvm/libraries/machine.cpp b/libraries/vendor/xgtvm/libraries/machine.cpp new file mode 100644 index 00000000..ac8a1c9c --- /dev/null +++ b/libraries/vendor/xgtvm/libraries/machine.cpp @@ -0,0 +1,2511 @@ +#include "machine.hpp" + +namespace machine +{ + + // void emit_log(const evmc::address& _addr, const uint8_t* _data, size_t _dataSize, + // const evmc::bytes32 _topics[], size_t _numTopics); + + boost::multiprecision::uint256_t alias_to_uint256_t(boost::multiprecision::int256_t i) + { + return (boost::multiprecision::uint256_t)i; + } + + boost::multiprecision::int256_t alias_to_int256_t(boost::multiprecision::uint256_t u) + { + return (boost::multiprecision::int256_t)u; + } + + uint8_t get_byte(boost::multiprecision::uint256_t x, int n) + { + std::vector bytes; + boost::multiprecision::export_bits(x, std::back_inserter(bytes), 8); + return bytes[n]; + } + + void set_byte(boost::multiprecision::uint256_t& x, int n, int v) + { + std::vector bytes; + boost::multiprecision::export_bits(x, std::back_inserter(bytes), 8); + bytes[n] = v; + boost::multiprecision::import_bits(x, bytes.begin(), bytes.end()); + } + + size_t uint256_t_to_size_t(boost::multiprecision::uint256_t& x) + { + return x.convert_to(); + } + + big_word to_big_word(word a) + { + return a; + } + + big_word to_big_word(word a, word b) + { + big_word va = 0; + set_byte(va, 0, a); + set_byte(va, 1, b); + return va; + } + + big_word to_big_word(word a, word b, word c, word d) + { + big_word va = 0; + set_byte(va, 0, a); + set_byte(va, 1, b); + set_byte(va, 2, c); + set_byte(va, 3, d); + return va; + } + + big_word to_big_word(word a, word b, word c, word d, word e, word f, word g, word h) + { + big_word va = 0; + set_byte(va, 0, a); + set_byte(va, 1, b); + set_byte(va, 2, c); + set_byte(va, 3, d); + set_byte(va, 4, e); + set_byte(va, 5, f); + set_byte(va, 6, g); + set_byte(va, 7, h); + return va; + } + + big_word to_big_word(word a, word b, word c, word d, word e, word f, word g, + word h, word i, word j, word k, word l, word m, word n, word o, word p) + { + big_word va = 0; + set_byte(va, 0, a); + set_byte(va, 1, b); + set_byte(va, 2, c); + set_byte(va, 3, d); + set_byte(va, 4, e); + set_byte(va, 5, f); + set_byte(va, 6, g); + set_byte(va, 7, h); + set_byte(va, 8, i); + set_byte(va, 9, j); + set_byte(va, 10, k); + set_byte(va, 11, l); + set_byte(va, 12, m); + set_byte(va, 13, n); + set_byte(va, 14, o); + set_byte(va, 15, p); + return va; + } + + big_word to_big_word(word a, word b, word c, word d, word e, word f, word g, + word h, word i, word j, word k, word l, word m, word n, word o, word p, + word q, word r, word s, word t, word u, word v, word w, word x, word y, + word z, word aa, word ab, word ac, word ad, word ae, word af) + { + big_word va = 0; + set_byte(va, 0, a); + set_byte(va, 1, b); + set_byte(va, 2, c); + set_byte(va, 3, d); + set_byte(va, 4, e); + set_byte(va, 5, f); + set_byte(va, 6, g); + set_byte(va, 7, h); + set_byte(va, 8, i); + set_byte(va, 9, j); + set_byte(va, 10, k); + set_byte(va, 11, l); + set_byte(va, 12, m); + set_byte(va, 13, n); + set_byte(va, 14, o); + set_byte(va, 15, p); + set_byte(va, 16, q); + set_byte(va, 17, r); + set_byte(va, 18, s); + set_byte(va, 19, t); + set_byte(va, 20, u); + set_byte(va, 21, v); + set_byte(va, 22, w); + set_byte(va, 23, x); + set_byte(va, 24, y); + set_byte(va, 25, z); + set_byte(va, 26, aa); + set_byte(va, 27, ab); + set_byte(va, 28, ac); + set_byte(va, 29, ad); + set_byte(va, 30, ae); + set_byte(va, 31, af); + return va; + } + + std::string inspect(std::vector words) + { + std::stringstream ss; + ss << "["; + for (size_t i = 0; i < words.size(); i++) + { + // TODO: Print hex + ss << std::to_string(words.at(i)); + if (i != words.size() - 1) + ss << ", "; + } + ss << "]"; + return ss.str(); + } + + void machine::push_word(stack_variant v) + { + stack.push_front(v); + } + + big_word machine::pop_word() + { + stack_variant& stack_object = stack.front(); + if (big_word* it = boost::get(&stack_object)) + { + stack.pop_front(); + return *it; + } + throw; + } + + big_word machine::peek_word() + { + stack_variant& stack_object = stack.front(); + if (big_word* it = boost::get(&stack_object)) + { + stack.pop_front(); + return *it; + } + else { + throw; + } + } + + // TODO: Make better + // TODO: Return string instead? + void machine::print_stack() + { + for (auto it = stack.cbegin(); it != stack.cend(); ++it) + { + stack_variant w = *it; + logger << w; + if (it + 1 != stack.cend()) + logger << " "; + } + logger << std::endl; + } + + size_t machine::stack_length() + { + return stack.size(); + } + + void machine::step() + { + if (code.size() == 0 || pc > code.size()) + { + logger << "stop" << std::endl; + state = machine_state::stopped; + return; + } + word current_instruction = code[pc]; + opcode op = (opcode)current_instruction; + pc++; + + logger << "step pc " << std::to_string(pc) << " opcode " << std::hex << op << std::dec << std::endl; + + // Allow to skip evaluation by throwing exception. + // TODO: Verify this behavior. + word a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, + y, z, aa, ab, ac, ad, ae, af; + big_word va, vb, vc, vd, ve, vf, vg, vh, vi, vj, vk, vl, vm, vn, vo, vp, vq; + stack_variant sv; + signed_big_word sa, sb, sc; + switch (op) + { + case stop_opcode: + logger << "op stop" << std::endl; + state = machine_state::stopped; + break; + case add_opcode: + logger << "op add" << std::endl; + va = pop_word(); + vb = pop_word(); + vc = va + vb; + push_word(vc); + break; + case mul_opcode: + logger << "op mul" << std::endl; + va = pop_word(); + vb = pop_word(); + vc = va * vb; + push_word(vc); + break; + case sub_opcode: + logger << "op sub" << std::endl; + va = pop_word(); + vb = pop_word(); + vc = va - vb; + push_word(vc); + break; + case div_opcode: + logger << "op div" << std::endl; + va = pop_word(); + vb = pop_word(); + vc = va / vb; + push_word(vc); + break; + case sdiv_opcode: + logger << "op sdiv" << std::endl; + sa = alias_to_int256_t( pop_word() ); + sb = alias_to_int256_t( pop_word() ); + sc = sa / sb; + push_word( alias_to_uint256_t(sc) ); + break; + case mod_opcode: + logger << "op mod" << std::endl; + va = pop_word(); + vb = pop_word(); + vc = va % vb; + push_word(vc); + break; + case smod_opcode: + logger << "op smod" << std::endl; + sa = alias_to_int256_t( pop_word() ); + sb = alias_to_int256_t( pop_word() ); + sc = sa % sb; + push_word( alias_to_uint256_t(sc) ); + break; + case addmod_opcode: + logger << "op addmod" << std::endl; + va = pop_word(); + vb = pop_word(); + vc = pop_word(); + vd = va + vb; + ve = vd % vc; + push_word(ve); + break; + case mulmod_opcode: + logger << "op addmod" << std::endl; + va = pop_word(); + vb = pop_word(); + vc = pop_word(); + vd = va * vb; + ve = vd % vc; + push_word(ve); + break; + case exp_opcode: + // TODO Implement using boost::multiprecision::pow + logger << "op exp" << std::endl; + va = pop_word(); // base + vb = pop_word(); // exponent + vc = 1; + for (int i = 0; i < vb; i++) { + vc *= va; + } + push_word(vc); + break; + case signextend_opcode: + logger << "op signextend" << std::endl; + sa = alias_to_int256_t( pop_word() ); // b + sb = alias_to_int256_t( pop_word() ); // x + + if (sa < 31) + { + unsigned testBit = static_cast(sa) * 8 + 7; + big_word one = 1; + big_word mask = ((one << testBit) - 1); + if (sb & (one << testBit)) + sc = sb | ~mask; + else + sc = sb & mask; + } + + push_word( alias_to_uint256_t(sc) ); + break; + case lt_opcode: + logger << "op lt" << std::endl; + va = pop_word(); + vb = pop_word(); + vc = va < vb; + push_word(vc); + break; + case gt_opcode: + logger << "op gt" << std::endl; + va = pop_word(); + vb = pop_word(); + vc = va > vb; + push_word(vc); + break; + case slt_opcode: + logger << "op stl" << std::endl; + sa = alias_to_int256_t( pop_word() ); + sb = alias_to_int256_t( pop_word() ); + sc = sa < sb; + push_word( alias_to_uint256_t(sc) ); + break; + case sgt_opcode: + logger << "op sgt" << std::endl; + sa = alias_to_int256_t( pop_word() ); + sb = alias_to_int256_t( pop_word() ); + sc = sa > sb; + push_word( alias_to_uint256_t(sc) ); + break; + case eq_opcode: + logger << "op eq" << std::endl; + va = pop_word(); + vb = pop_word(); + vc = va == vb; + push_word(vc); + break; + case iszero_opcode: + logger << "op iszero" << std::endl; + va = pop_word(); + vb = va == 0; + push_word(vb); + break; + case and_opcode: + logger << "op and" << std::endl; + va = pop_word(); + vb = pop_word(); + vc = va & vb; + push_word(vc); + break; + case or_opcode: + logger << "op or" << std::endl; + va = pop_word(); + vb = pop_word(); + vc = va | vb; + push_word(vc); + break; + case xor_opcode: + logger << "op xor" << std::endl; + va = pop_word(); + vb = pop_word(); + vc = va ^ vb; + push_word(vc); + break; + case not_opcode: + logger << "op not" << std::endl; + va = pop_word(); + vb = ~va; + push_word(vb); + break; + case byte_opcode: + logger << "op byte" << std::endl; + + sa = pop_word(); // index + sb = pop_word(); // num + + sc = sa < 32 ? (sb >> (unsigned)(8 * (31 - sa))) & 0xff : 0; + + push_word( alias_to_uint256_t(sc) ); + break; + case shl_opcode: + logger << "op shl" << std::endl; + + va = pop_word(); // shift + vb = pop_word(); // value + + vc = vb << va.convert_to(); + + push_word(vc); + break; + case shr_opcode: + logger << "op shr" << std::endl; + va = pop_word(); // shift + vb = pop_word(); // value + + vc = vb >> va.convert_to(); + push_word(vc); + + break; + case sar_opcode: + logger << "op sar" << std::endl; + sa = alias_to_int256_t( pop_word() ); // shift + sb = pop_word(); // value + + sc = sb >> sa.convert_to(); + push_word( alias_to_uint256_t(sc) ); + + break; + case sha3_opcode: + logger << "op sha3" << std::endl; + va = pop_word(); // offset + vb = pop_word(); // length + break; + case address_opcode: + logger << "op address" << std::endl; + push_word( msg.destination ); + break; + case balance_opcode: + logger << "op balance" << std::endl; + // TODO + break; + case origin_opcode: + logger << "op origin" << std::endl; + // TODO + break; + case caller_opcode: + logger << "op caller" << std::endl; + push_word( msg.sender ); + break; + case callvalue_opcode: + logger << "op callvalue" << std::endl; + push_word( msg.value ); + break; + case calldataload_opcode: + logger << "op calldataload" << std::endl; + // TODO + break; + case calldatasize_opcode: + logger << "op calldatasize" << std::endl; + push_word( msg.input_size ); + break; + case calldatacopy_opcode: + logger << "op calldatacopy" << std::endl; + // TODO + break; + case codesize_opcode: + logger << "op codesize" << std::endl; + push_word( msg.code_size ); + break; + case codecopy_opcode: + logger << "op codecopy" << std::endl; + // TODO + break; + case gasprice_opcode: + logger << "op gasprice" << std::endl; + push_word( ctx.tx_gasprice ); + break; + case extcodesize_opcode: + logger << "op extcodesize" << std::endl; + // TODO + break; + case extcodecopy_opcode: + logger << "op extcodecopy" << std::endl; + // TODO + break; + case returndatasize_opcode: + logger << "op returndatasize" << std::endl; + // TODO + break; + case returndatacopy_opcode: + logger << "op returndatacopy" << std::endl; + // TODO + break; + case extcodehash_opcode: + logger << "op extcodehash" << std::endl; + // TODO + break; + case blockhash_opcode: + logger << "op blockhash" << std::endl; + // TODO + break; + case coinbase_opcode: + logger << "op coinbase" << std::endl; + // TODO convert address datatype to big_word + push_word(ctx.block_coinbase); + break; + case timestamp_opcode: + logger << "op timestamp" << std::endl; + push_word(ctx.block_timestamp); + break; + case number_opcode: + logger << "op number" << std::endl; + push_word(ctx.block_number); + break; + case difficulty_opcode: + logger << "op difficulty" << std::endl; + push_word(ctx.block_difficulty); + break; + case gaslimit_opcode: + logger << "op gaslimit" << std::endl; + push_word(ctx.block_gaslimit); + break; + case pop_opcode: + logger << "op pop" << std::endl; + pop_word(); + break; + case mload_opcode: + logger << "op mload" << std::endl; + // va = pop_word(); // offset + // if (va + 8 >= memory.size()) + // { + // state = machine_state::error; + // error_message.emplace("Memory overflow"); + // } + // // TODO: Verify order + // vb = to_big_word( + // memory[va + 7], + // memory[va + 6], + // memory[va + 5], + // memory[va + 4], + // memory[va + 3], + // memory[va + 2], + // memory[va + 1], + // memory[va + 0] + // ); + // push_word(vb); + break; + case mstore_opcode: + logger << "op mstore" << std::endl; + // va = pop_word(); // offset + // vb = pop_word(); // value + // logger << "memory before: " << inspect(memory) << std::endl; + // if (va + 8 >= memory.size()) + // memory.resize(va + 8); + // // TODO: Verify order + // memory[va + 0] = get_byte(vb, 7); + // memory[va + 1] = get_byte(vb, 6); + // memory[va + 2] = get_byte(vb, 5); + // memory[va + 3] = get_byte(vb, 4); + // memory[va + 4] = get_byte(vb, 3); + // memory[va + 5] = get_byte(vb, 2); + // memory[va + 6] = get_byte(vb, 1); + // memory[va + 7] = get_byte(vb, 0); + // logger << "memory after: " << inspect(memory) << std::endl; + break; + case mstore8_opcode: + logger << "op mstore8" << std::endl; + // TODO + break; + case sload_opcode: + logger << "op sload" << std::endl; + // TODO + break; + case sstore_opcode: + logger << "op sstore" << std::endl; + // TODO + break; + case jump_opcode: + logger << "op jump" << std::endl; + va = pop_word(); // destination + if (code[get_byte(va, 0)] == jumpdest_opcode) + pc = get_byte(va, 0); + break; + case jumpi_opcode: + logger << "op jumpi" << std::endl; + print_stack(); + va = pop_word(); + vb = pop_word(); + if (vb != 0) + if (code[get_byte(va, 0)] == jumpdest_opcode) + pc = get_byte(va, 0); + break; + case pc_opcode: + logger << "op pc" << std::endl; + va = pc; + push_word(va); + break; + case msize_opcode: + logger << "op msize" << std::endl; + // TODO + break; + case gas_opcode: + logger << "op gas" << std::endl; + // TODO + break; + case jumpdest_opcode: + logger << "op jumpdest" << std::endl; + break; + case push1_opcode: + logger << "op push1" << std::endl; + a = code[pc]; + pc++; + push_word(a); + break; + case push2_opcode: + logger << "op push2" << std::endl; + a = code[pc]; + pc++; + b = code[pc]; + pc++; + va = to_big_word(0, 0, a, b); // TODO: Verify + push_word(va); + break; + case push3_opcode: + logger << "op push3" << std::endl; + a = code[pc]; + pc++; + b = code[pc]; + pc++; + c = code[pc]; + pc++; + va = to_big_word(0, a, b, c); // TODO: Verify + push_word(va); + break; + case push4_opcode: + logger << "op push4" << std::endl; + a = code[pc]; + pc++; + b = code[pc]; + pc++; + c = code[pc]; + pc++; + d = code[pc]; + pc++; + va = to_big_word(a, b, c, d); // TODO: Verify + push_word(va); + break; + case push5_opcode: + logger << "op push5" << std::endl; + a = code[pc]; + pc++; + b = code[pc]; + pc++; + c = code[pc]; + pc++; + d = code[pc]; + pc++; + e = code[pc]; + pc++; + va = to_big_word(0, 0, 0, a, b, c, d, e); // TODO: Verify + push_word(va); + break; + case push6_opcode: + logger << "op push6" << std::endl; + a = code[pc]; + pc++; + b = code[pc]; + pc++; + c = code[pc]; + pc++; + d = code[pc]; + pc++; + e = code[pc]; + pc++; + f = code[pc]; + pc++; + va = to_big_word(0, 0, a, b, c, d, e, f); // TODO: Verify + push_word(va); + break; + case push7_opcode: + logger << "op push7" << std::endl; + a = code[pc]; + pc++; + b = code[pc]; + pc++; + c = code[pc]; + pc++; + d = code[pc]; + pc++; + e = code[pc]; + pc++; + f = code[pc]; + pc++; + g = code[pc]; + pc++; + va = to_big_word(0, a, b, c, d, e, f, g); // TODO: Verify + push_word(va); + break; + case push8_opcode: + logger << "op push8" << std::endl; + a = code[pc]; + pc++; + b = code[pc]; + pc++; + c = code[pc]; + pc++; + d = code[pc]; + pc++; + e = code[pc]; + pc++; + f = code[pc]; + pc++; + g = code[pc]; + pc++; + h = code[pc]; + pc++; + va = to_big_word(a, b, c, d, e, f, g, h); // TODO: Verify + push_word(va); + break; + case push9_opcode: + logger << "op push9" << std::endl; + a = code[pc]; + pc++; + b = code[pc]; + pc++; + c = code[pc]; + pc++; + d = code[pc]; + pc++; + e = code[pc]; + pc++; + f = code[pc]; + pc++; + g = code[pc]; + pc++; + h = code[pc]; + pc++; + i = code[pc]; + pc++; + va = to_big_word(0, 0, 0, 0, 0, 0, 0, a, b, c, d, e, f, g, h, i); // TODO: Verify + push_word(va); + break; + case push10_opcode: + logger << "op push10" << std::endl; + a = code[pc]; + pc++; + b = code[pc]; + pc++; + c = code[pc]; + pc++; + d = code[pc]; + pc++; + e = code[pc]; + pc++; + f = code[pc]; + pc++; + g = code[pc]; + pc++; + h = code[pc]; + pc++; + i = code[pc]; + pc++; + j = code[pc]; + pc++; + va = to_big_word(0, 0, 0, 0, 0, 0, a, b, c, d, e, f, g, h, i, j); // TODO: Verify + push_word(va); + break; + case push11_opcode: + logger << "op push11" << std::endl; + a = code[pc]; + pc++; + b = code[pc]; + pc++; + c = code[pc]; + pc++; + d = code[pc]; + pc++; + e = code[pc]; + pc++; + f = code[pc]; + pc++; + g = code[pc]; + pc++; + h = code[pc]; + pc++; + i = code[pc]; + pc++; + j = code[pc]; + pc++; + k = code[pc]; + pc++; + va = to_big_word(0, 0, 0, 0, 0, a, b, c, d, e, f, g, h, i, j, k); // TODO: Verify + push_word(va); + break; + case push12_opcode: + logger << "op push12" << std::endl; + a = code[pc]; + pc++; + b = code[pc]; + pc++; + c = code[pc]; + pc++; + d = code[pc]; + pc++; + e = code[pc]; + pc++; + f = code[pc]; + pc++; + g = code[pc]; + pc++; + h = code[pc]; + pc++; + i = code[pc]; + pc++; + j = code[pc]; + pc++; + k = code[pc]; + pc++; + l = code[pc]; + pc++; + va = to_big_word(0, 0, 0, 0, a, b, c, d, e, f, g, h, i, j, k, l); // TODO: Verify + push_word(va); + break; + case push13_opcode: + logger << "op push13" << std::endl; + a = code[pc]; + pc++; + b = code[pc]; + pc++; + c = code[pc]; + pc++; + d = code[pc]; + pc++; + e = code[pc]; + pc++; + f = code[pc]; + pc++; + g = code[pc]; + pc++; + h = code[pc]; + pc++; + i = code[pc]; + pc++; + j = code[pc]; + pc++; + k = code[pc]; + pc++; + l = code[pc]; + pc++; + m = code[pc]; + pc++; + va = to_big_word(0, 0, 0, a, b, c, d, e, f, g, h, i, j, k, l, m); // TODO: Verify + push_word(va); + break; + case push14_opcode: + logger << "op push14" << std::endl; + a = code[pc]; + pc++; + b = code[pc]; + pc++; + c = code[pc]; + pc++; + d = code[pc]; + pc++; + e = code[pc]; + pc++; + f = code[pc]; + pc++; + g = code[pc]; + pc++; + h = code[pc]; + pc++; + i = code[pc]; + pc++; + j = code[pc]; + pc++; + k = code[pc]; + pc++; + l = code[pc]; + pc++; + m = code[pc]; + pc++; + n = code[pc]; + pc++; + va = to_big_word(0, 0, a, b, c, d, e, f, g, h, i, j, k, l, m, n); // TODO: Verify + push_word(va); + break; + case push15_opcode: + logger << "op push15" << std::endl; + a = code[pc]; + pc++; + b = code[pc]; + pc++; + c = code[pc]; + pc++; + d = code[pc]; + pc++; + e = code[pc]; + pc++; + f = code[pc]; + pc++; + g = code[pc]; + pc++; + h = code[pc]; + pc++; + i = code[pc]; + pc++; + j = code[pc]; + pc++; + k = code[pc]; + pc++; + l = code[pc]; + pc++; + m = code[pc]; + pc++; + n = code[pc]; + pc++; + o = code[pc]; + pc++; + va = to_big_word(0, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o); // TODO: Verify + push_word(va); + break; + case push16_opcode: + logger << "op push16" << std::endl; + a = code[pc]; + pc++; + b = code[pc]; + pc++; + c = code[pc]; + pc++; + d = code[pc]; + pc++; + e = code[pc]; + pc++; + f = code[pc]; + pc++; + g = code[pc]; + pc++; + h = code[pc]; + pc++; + i = code[pc]; + pc++; + j = code[pc]; + pc++; + k = code[pc]; + pc++; + l = code[pc]; + pc++; + m = code[pc]; + pc++; + n = code[pc]; + pc++; + o = code[pc]; + pc++; + p = code[pc]; + pc++; + va = to_big_word(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p); // TODO: Verify + push_word(va); + break; + case push17_opcode: + logger << "op push17" << std::endl; + a = code[pc]; + pc++; + b = code[pc]; + pc++; + c = code[pc]; + pc++; + d = code[pc]; + pc++; + e = code[pc]; + pc++; + f = code[pc]; + pc++; + g = code[pc]; + pc++; + h = code[pc]; + pc++; + i = code[pc]; + pc++; + j = code[pc]; + pc++; + k = code[pc]; + pc++; + l = code[pc]; + pc++; + m = code[pc]; + pc++; + n = code[pc]; + pc++; + o = code[pc]; + pc++; + p = code[pc]; + pc++; + q = code[pc]; + pc++; + va = to_big_word(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d, + e, f, g, h, i, j, k, l, m, n, o, p, q); // TODO: Verify + push_word(va); + break; + case push18_opcode: + logger << "op push18" << std::endl; + a = code[pc]; + pc++; + b = code[pc]; + pc++; + c = code[pc]; + pc++; + d = code[pc]; + pc++; + e = code[pc]; + pc++; + f = code[pc]; + pc++; + g = code[pc]; + pc++; + h = code[pc]; + pc++; + i = code[pc]; + pc++; + j = code[pc]; + pc++; + k = code[pc]; + pc++; + l = code[pc]; + pc++; + m = code[pc]; + pc++; + n = code[pc]; + pc++; + o = code[pc]; + pc++; + p = code[pc]; + pc++; + q = code[pc]; + pc++; + r = code[pc]; + pc++; + va = to_big_word(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d, e, + f, g, h, i, j, k, l, m, n, o, p, q, r); // TODO: Verify + push_word(va); + break; + case push19_opcode: + logger << "op push19" << std::endl; + a = code[pc]; + pc++; + b = code[pc]; + pc++; + c = code[pc]; + pc++; + d = code[pc]; + pc++; + e = code[pc]; + pc++; + f = code[pc]; + pc++; + g = code[pc]; + pc++; + h = code[pc]; + pc++; + i = code[pc]; + pc++; + j = code[pc]; + pc++; + k = code[pc]; + pc++; + l = code[pc]; + pc++; + m = code[pc]; + pc++; + n = code[pc]; + pc++; + o = code[pc]; + pc++; + p = code[pc]; + pc++; + q = code[pc]; + pc++; + r = code[pc]; + pc++; + s = code[pc]; + pc++; + va = to_big_word(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d, e, f, + g, h, i, j, k, l, m, n, o, p, q, r, s); // TODO: Verify + push_word(va); + break; + case push20_opcode: + logger << "op push20" << std::endl; + a = code[pc]; + pc++; + b = code[pc]; + pc++; + c = code[pc]; + pc++; + d = code[pc]; + pc++; + e = code[pc]; + pc++; + f = code[pc]; + pc++; + g = code[pc]; + pc++; + h = code[pc]; + pc++; + i = code[pc]; + pc++; + j = code[pc]; + pc++; + k = code[pc]; + pc++; + l = code[pc]; + pc++; + m = code[pc]; + pc++; + n = code[pc]; + pc++; + o = code[pc]; + pc++; + p = code[pc]; + pc++; + q = code[pc]; + pc++; + r = code[pc]; + pc++; + s = code[pc]; + pc++; + t = code[pc]; + pc++; + va = to_big_word(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d, e, f, g, + h, i, j, k, l, m, n, o, p, q, r, s, t); // TODO: Verify + push_word(va); + break; + case push21_opcode: + logger << "op push21" << std::endl; + a = code[pc]; + pc++; + b = code[pc]; + pc++; + c = code[pc]; + pc++; + d = code[pc]; + pc++; + e = code[pc]; + pc++; + f = code[pc]; + pc++; + g = code[pc]; + pc++; + h = code[pc]; + pc++; + i = code[pc]; + pc++; + j = code[pc]; + pc++; + k = code[pc]; + pc++; + l = code[pc]; + pc++; + m = code[pc]; + pc++; + n = code[pc]; + pc++; + o = code[pc]; + pc++; + p = code[pc]; + pc++; + q = code[pc]; + pc++; + r = code[pc]; + pc++; + s = code[pc]; + pc++; + t = code[pc]; + pc++; + u = code[pc]; + pc++; + va = to_big_word(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d, e, f, g, h, + i, j, k, l, m, n, o, p, q, r, s, t, u); // TODO: Verify + push_word(va); + break; + case push22_opcode: + logger << "op push22" << std::endl; + a = code[pc]; + pc++; + b = code[pc]; + pc++; + c = code[pc]; + pc++; + d = code[pc]; + pc++; + e = code[pc]; + pc++; + f = code[pc]; + pc++; + g = code[pc]; + pc++; + h = code[pc]; + pc++; + i = code[pc]; + pc++; + j = code[pc]; + pc++; + k = code[pc]; + pc++; + l = code[pc]; + pc++; + m = code[pc]; + pc++; + n = code[pc]; + pc++; + o = code[pc]; + pc++; + p = code[pc]; + pc++; + q = code[pc]; + pc++; + r = code[pc]; + pc++; + s = code[pc]; + pc++; + t = code[pc]; + pc++; + u = code[pc]; + pc++; + v = code[pc]; + pc++; + va = to_big_word(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d, e, f, g, h, i, + j, k, l, m, n, o, p, q, r, s, t, u, v); // TODO: Verify + push_word(va); + break; + case push23_opcode: + logger << "op push23" << std::endl; + a = code[pc]; + pc++; + b = code[pc]; + pc++; + c = code[pc]; + pc++; + d = code[pc]; + pc++; + e = code[pc]; + pc++; + f = code[pc]; + pc++; + g = code[pc]; + pc++; + h = code[pc]; + pc++; + i = code[pc]; + pc++; + j = code[pc]; + pc++; + k = code[pc]; + pc++; + l = code[pc]; + pc++; + m = code[pc]; + pc++; + n = code[pc]; + pc++; + o = code[pc]; + pc++; + p = code[pc]; + pc++; + q = code[pc]; + pc++; + r = code[pc]; + pc++; + s = code[pc]; + pc++; + t = code[pc]; + pc++; + u = code[pc]; + pc++; + v = code[pc]; + pc++; + w = code[pc]; + pc++; + va = to_big_word(0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d, e, f, g, h, i, j, + k, l, m, n, o, p, q, r, s, t, u, v, w); // TODO: Verify + push_word(va); + break; + case push24_opcode: + logger << "op push24" << std::endl; + a = code[pc]; + pc++; + b = code[pc]; + pc++; + c = code[pc]; + pc++; + d = code[pc]; + pc++; + e = code[pc]; + pc++; + f = code[pc]; + pc++; + g = code[pc]; + pc++; + h = code[pc]; + pc++; + i = code[pc]; + pc++; + j = code[pc]; + pc++; + k = code[pc]; + pc++; + l = code[pc]; + pc++; + m = code[pc]; + pc++; + n = code[pc]; + pc++; + o = code[pc]; + pc++; + p = code[pc]; + pc++; + q = code[pc]; + pc++; + r = code[pc]; + pc++; + s = code[pc]; + pc++; + t = code[pc]; + pc++; + u = code[pc]; + pc++; + v = code[pc]; + pc++; + w = code[pc]; + pc++; + x = code[pc]; + pc++; + va = to_big_word(0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d, e, f, g, h, i, j, k, + l, m, n, o, p, q, r, s, t, u, v, w, x); // TODO: Verify + push_word(va); + break; + case push25_opcode: + logger << "op push25" << std::endl; + a = code[pc]; + pc++; + b = code[pc]; + pc++; + c = code[pc]; + pc++; + d = code[pc]; + pc++; + e = code[pc]; + pc++; + f = code[pc]; + pc++; + g = code[pc]; + pc++; + h = code[pc]; + pc++; + i = code[pc]; + pc++; + j = code[pc]; + pc++; + k = code[pc]; + pc++; + l = code[pc]; + pc++; + m = code[pc]; + pc++; + n = code[pc]; + pc++; + o = code[pc]; + pc++; + p = code[pc]; + pc++; + q = code[pc]; + pc++; + r = code[pc]; + pc++; + s = code[pc]; + pc++; + t = code[pc]; + pc++; + u = code[pc]; + pc++; + v = code[pc]; + pc++; + w = code[pc]; + pc++; + x = code[pc]; + pc++; + y = code[pc]; + pc++; + va = to_big_word(0, 0, 0, 0, 0, 0, 0, a, b, c, d, e, f, g, h, i, j, k, l, + m, n, o, p, q, r, s, t, u, v, w, x, y); // TODO: Verify + push_word(va); + break; + case push26_opcode: + logger << "op push26" << std::endl; + a = code[pc]; + pc++; + b = code[pc]; + pc++; + c = code[pc]; + pc++; + d = code[pc]; + pc++; + e = code[pc]; + pc++; + f = code[pc]; + pc++; + g = code[pc]; + pc++; + h = code[pc]; + pc++; + i = code[pc]; + pc++; + j = code[pc]; + pc++; + k = code[pc]; + pc++; + l = code[pc]; + pc++; + m = code[pc]; + pc++; + n = code[pc]; + pc++; + o = code[pc]; + pc++; + p = code[pc]; + pc++; + q = code[pc]; + pc++; + r = code[pc]; + pc++; + s = code[pc]; + pc++; + t = code[pc]; + pc++; + u = code[pc]; + pc++; + v = code[pc]; + pc++; + w = code[pc]; + pc++; + x = code[pc]; + pc++; + y = code[pc]; + pc++; + z = code[pc]; + pc++; + va = to_big_word(0, 0, 0, 0, 0, 0, a, b, c, d, e, f, g, h, i, j, k, l, m, + n, o, p, q, r, s, t, u, v, w, x, y, z); // TODO: Verify + push_word(va); + break; + case push27_opcode: + logger << "op push27" << std::endl; + a = code[pc]; + pc++; + b = code[pc]; + pc++; + c = code[pc]; + pc++; + d = code[pc]; + pc++; + e = code[pc]; + pc++; + f = code[pc]; + pc++; + g = code[pc]; + pc++; + h = code[pc]; + pc++; + i = code[pc]; + pc++; + j = code[pc]; + pc++; + k = code[pc]; + pc++; + l = code[pc]; + pc++; + m = code[pc]; + pc++; + n = code[pc]; + pc++; + o = code[pc]; + pc++; + p = code[pc]; + pc++; + q = code[pc]; + pc++; + r = code[pc]; + pc++; + s = code[pc]; + pc++; + t = code[pc]; + pc++; + u = code[pc]; + pc++; + v = code[pc]; + pc++; + w = code[pc]; + pc++; + x = code[pc]; + pc++; + y = code[pc]; + pc++; + z = code[pc]; + pc++; + aa = code[pc]; + pc++; + va = to_big_word(0, 0, 0, 0, 0, a, b, c, d, e, f, g, h, i, j, k, l, m, n, + o, p, q, r, s, t, u, v, w, x, y, z, aa); // TODO: Verify + push_word(va); + break; + case push28_opcode: + logger << "op push28" << std::endl; + a = code[pc]; + pc++; + b = code[pc]; + pc++; + c = code[pc]; + pc++; + d = code[pc]; + pc++; + e = code[pc]; + pc++; + f = code[pc]; + pc++; + g = code[pc]; + pc++; + h = code[pc]; + pc++; + i = code[pc]; + pc++; + j = code[pc]; + pc++; + k = code[pc]; + pc++; + l = code[pc]; + pc++; + m = code[pc]; + pc++; + n = code[pc]; + pc++; + o = code[pc]; + pc++; + p = code[pc]; + pc++; + q = code[pc]; + pc++; + r = code[pc]; + pc++; + s = code[pc]; + pc++; + t = code[pc]; + pc++; + u = code[pc]; + pc++; + v = code[pc]; + pc++; + w = code[pc]; + pc++; + x = code[pc]; + pc++; + y = code[pc]; + pc++; + z = code[pc]; + pc++; + aa = code[pc]; + pc++; + ab = code[pc]; + pc++; + va = to_big_word(0, 0, 0, 0, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, + p, q, r, s, t, u, v, w, x, y, z, aa, ab); // TODO: Verify + push_word(va); + break; + case push29_opcode: + logger << "op push29" << std::endl; + a = code[pc]; + pc++; + b = code[pc]; + pc++; + c = code[pc]; + pc++; + d = code[pc]; + pc++; + e = code[pc]; + pc++; + f = code[pc]; + pc++; + g = code[pc]; + pc++; + h = code[pc]; + pc++; + i = code[pc]; + pc++; + j = code[pc]; + pc++; + k = code[pc]; + pc++; + l = code[pc]; + pc++; + m = code[pc]; + pc++; + n = code[pc]; + pc++; + o = code[pc]; + pc++; + p = code[pc]; + pc++; + q = code[pc]; + pc++; + r = code[pc]; + pc++; + s = code[pc]; + pc++; + t = code[pc]; + pc++; + u = code[pc]; + pc++; + v = code[pc]; + pc++; + w = code[pc]; + pc++; + x = code[pc]; + pc++; + y = code[pc]; + pc++; + z = code[pc]; + pc++; + aa = code[pc]; + pc++; + ab = code[pc]; + pc++; + ac = code[pc]; + pc++; + va = to_big_word(0, 0, 0, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, + q, r, s, t, u, v, w, x, y, z, aa, ab, ac); // TODO: Verify + push_word(va); + break; + case push30_opcode: + logger << "op push30" << std::endl; + a = code[pc]; + pc++; + b = code[pc]; + pc++; + c = code[pc]; + pc++; + d = code[pc]; + pc++; + e = code[pc]; + pc++; + f = code[pc]; + pc++; + g = code[pc]; + pc++; + h = code[pc]; + pc++; + i = code[pc]; + pc++; + j = code[pc]; + pc++; + k = code[pc]; + pc++; + l = code[pc]; + pc++; + m = code[pc]; + pc++; + n = code[pc]; + pc++; + o = code[pc]; + pc++; + p = code[pc]; + pc++; + q = code[pc]; + pc++; + r = code[pc]; + pc++; + s = code[pc]; + pc++; + t = code[pc]; + pc++; + u = code[pc]; + pc++; + v = code[pc]; + pc++; + w = code[pc]; + pc++; + x = code[pc]; + pc++; + y = code[pc]; + pc++; + z = code[pc]; + pc++; + aa = code[pc]; + pc++; + ab = code[pc]; + pc++; + ac = code[pc]; + pc++; + ad = code[pc]; + pc++; + va = to_big_word(0, 0, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, + q, r, s, t, u, v, w, x, y, z, aa, ab, ac, ad); // TODO: Verify + push_word(va); + break; + case push31_opcode: + logger << "op push31" << std::endl; + a = code[pc]; + pc++; + b = code[pc]; + pc++; + c = code[pc]; + pc++; + d = code[pc]; + pc++; + e = code[pc]; + pc++; + f = code[pc]; + pc++; + g = code[pc]; + pc++; + h = code[pc]; + pc++; + i = code[pc]; + pc++; + j = code[pc]; + pc++; + k = code[pc]; + pc++; + l = code[pc]; + pc++; + m = code[pc]; + pc++; + n = code[pc]; + pc++; + o = code[pc]; + pc++; + p = code[pc]; + pc++; + q = code[pc]; + pc++; + r = code[pc]; + pc++; + s = code[pc]; + pc++; + t = code[pc]; + pc++; + u = code[pc]; + pc++; + v = code[pc]; + pc++; + w = code[pc]; + pc++; + x = code[pc]; + pc++; + y = code[pc]; + pc++; + z = code[pc]; + pc++; + aa = code[pc]; + pc++; + ab = code[pc]; + pc++; + ac = code[pc]; + pc++; + ad = code[pc]; + pc++; + ae = code[pc]; + pc++; + va = to_big_word(0, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, + q, r, s, t, u, v, w, x, y, z, aa, ab, ac, ad, ae); // TODO: Verify + push_word(va); + break; + case push32_opcode: + logger << "op push32" << std::endl; + a = code[pc]; + pc++; + b = code[pc]; + pc++; + c = code[pc]; + pc++; + d = code[pc]; + pc++; + e = code[pc]; + pc++; + f = code[pc]; + pc++; + g = code[pc]; + pc++; + h = code[pc]; + pc++; + i = code[pc]; + pc++; + j = code[pc]; + pc++; + k = code[pc]; + pc++; + l = code[pc]; + pc++; + m = code[pc]; + pc++; + n = code[pc]; + pc++; + o = code[pc]; + pc++; + p = code[pc]; + pc++; + q = code[pc]; + pc++; + r = code[pc]; + pc++; + s = code[pc]; + pc++; + t = code[pc]; + pc++; + u = code[pc]; + pc++; + v = code[pc]; + pc++; + w = code[pc]; + pc++; + x = code[pc]; + pc++; + y = code[pc]; + pc++; + z = code[pc]; + pc++; + aa = code[pc]; + pc++; + ab = code[pc]; + pc++; + ac = code[pc]; + pc++; + ad = code[pc]; + pc++; + ae = code[pc]; + pc++; + af = code[pc]; + pc++; + va = to_big_word(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, + q, r, s, t, u, v, w, x, y, z, aa, ab, ac, ad, ae, af); // TODO: Verify + push_word(va); + break; + case dup1_opcode: + logger << "op dup1" << std::endl; + sv = stack.front(); + push_word(sv); + break; + case dup2_opcode: + logger << "op dup2" << std::endl; + sv = stack.at(1); + push_word(va); + break; + case dup3_opcode: + logger << "op dup3" << std::endl; + sv = stack.at(2); + push_word(sv); + break; + case dup4_opcode: + logger << "op dup4" << std::endl; + sv = stack.at(3); + push_word(sv); + break; + case dup5_opcode: + logger << "op dup5" << std::endl; + sv = stack.at(4); + push_word(sv); + break; + case dup6_opcode: + logger << "op dup6" << std::endl; + sv = stack.at(5); + push_word(sv); + break; + case dup7_opcode: + logger << "op dup7" << std::endl; + sv = stack.at(6); + push_word(sv); + break; + case dup8_opcode: + logger << "op dup8" << std::endl; + sv = stack.at(7); + push_word(sv); + break; + case dup9_opcode: + logger << "op dup9" << std::endl; + sv = stack.at(8); + push_word(sv); + break; + case dup10_opcode: + logger << "op dup10" << std::endl; + sv = stack.at(9); + push_word(sv); + break; + case dup11_opcode: + logger << "op dup11" << std::endl; + sv = stack.at(10); + push_word(sv); + break; + case dup12_opcode: + logger << "op dup12" << std::endl; + sv = stack.at(11); + push_word(sv); + break; + case dup13_opcode: + logger << "op dup13" << std::endl; + sv = stack.at(12); + push_word(sv); + break; + case dup14_opcode: + logger << "op dup14" << std::endl; + sv = stack.at(13); + push_word(sv); + break; + case dup15_opcode: + logger << "op dup15" << std::endl; + sv = stack.at(14); + push_word(sv); + break; + case dup16_opcode: + logger << "op dup16" << std::endl; + sv = stack.at(15); + push_word(sv); + break; + case swap1_opcode: + logger << "op swap1" << std::endl; + va = pop_word(); + vb = pop_word(); + push_word(a); + push_word(b); + break; + case swap2_opcode: + logger << "op swap2" << std::endl; + va = pop_word(); + vb = pop_word(); + vc = pop_word(); + push_word(va); + push_word(vb); + push_word(vc); + break; + case swap3_opcode: + logger << "op swap3" << std::endl; + va = pop_word(); + vb = pop_word(); + vc = pop_word(); + vd = pop_word(); + push_word(va); + push_word(vc); + push_word(vb); + push_word(vd); + break; + case swap4_opcode: + logger << "op swap4" << std::endl; + va = pop_word(); + vb = pop_word(); + vc = pop_word(); + vd = pop_word(); + ve = pop_word(); + push_word(va); + push_word(vd); + push_word(vc); + push_word(vb); + push_word(ve); + break; + case swap5_opcode: + logger << "op swap5" << std::endl; + va = pop_word(); + vb = pop_word(); + vc = pop_word(); + vd = pop_word(); + ve = pop_word(); + vf = pop_word(); + push_word(va); + push_word(ve); + push_word(vd); + push_word(vc); + push_word(vb); + push_word(vf); + break; + case swap6_opcode: + logger << "op swap6" << std::endl; + va = pop_word(); + vb = pop_word(); + vc = pop_word(); + vd = pop_word(); + ve = pop_word(); + vf = pop_word(); + vg = pop_word(); + push_word(va); + push_word(vf); + push_word(ve); + push_word(vd); + push_word(vc); + push_word(vb); + push_word(vg); + break; + case swap7_opcode: + logger << "op swap7" << std::endl; + va = pop_word(); + vb = pop_word(); + vc = pop_word(); + vd = pop_word(); + ve = pop_word(); + vf = pop_word(); + vg = pop_word(); + vh = pop_word(); + push_word(va); + push_word(vg); + push_word(vf); + push_word(ve); + push_word(vd); + push_word(vc); + push_word(vb); + push_word(vh); + break; + case swap8_opcode: + logger << "op swap8" << std::endl; + va = pop_word(); + vb = pop_word(); + vc = pop_word(); + vd = pop_word(); + ve = pop_word(); + vf = pop_word(); + vg = pop_word(); + vh = pop_word(); + vi = pop_word(); + push_word(va); + push_word(vh); + push_word(vg); + push_word(vf); + push_word(ve); + push_word(vd); + push_word(vc); + push_word(vb); + push_word(vi); + break; + case swap9_opcode: + logger << "op swap9" << std::endl; + va = pop_word(); + vb = pop_word(); + vc = pop_word(); + vd = pop_word(); + ve = pop_word(); + vf = pop_word(); + vg = pop_word(); + vh = pop_word(); + vi = pop_word(); + vj = pop_word(); + push_word(va); + push_word(vi); + push_word(vh); + push_word(vg); + push_word(vf); + push_word(ve); + push_word(vd); + push_word(vc); + push_word(vb); + push_word(vj); + break; + case swap10_opcode: + logger << "op swap10" << std::endl; + va = pop_word(); + vb = pop_word(); + vc = pop_word(); + vd = pop_word(); + ve = pop_word(); + vf = pop_word(); + vg = pop_word(); + vh = pop_word(); + vi = pop_word(); + vj = pop_word(); + vk = pop_word(); + push_word(va); + push_word(vj); + push_word(vi); + push_word(vh); + push_word(vg); + push_word(vf); + push_word(ve); + push_word(vd); + push_word(vc); + push_word(vb); + push_word(vk); + break; + case swap11_opcode: + logger << "op swap11" << std::endl; + va = pop_word(); + vb = pop_word(); + vc = pop_word(); + vd = pop_word(); + ve = pop_word(); + vf = pop_word(); + vg = pop_word(); + vh = pop_word(); + vi = pop_word(); + vj = pop_word(); + vk = pop_word(); + vl = pop_word(); + push_word(va); + push_word(vk); + push_word(vj); + push_word(vi); + push_word(vh); + push_word(vg); + push_word(vf); + push_word(ve); + push_word(vd); + push_word(vc); + push_word(vb); + push_word(vl); + break; + case swap12_opcode: + logger << "op swap12" << std::endl; + va = pop_word(); + vb = pop_word(); + vc = pop_word(); + vd = pop_word(); + ve = pop_word(); + vf = pop_word(); + vg = pop_word(); + vh = pop_word(); + vi = pop_word(); + vj = pop_word(); + vk = pop_word(); + vl = pop_word(); + vm = pop_word(); + push_word(va); + push_word(vl); + push_word(vk); + push_word(vj); + push_word(vi); + push_word(vh); + push_word(vg); + push_word(vf); + push_word(ve); + push_word(vd); + push_word(vc); + push_word(vb); + push_word(vm); + break; + case swap13_opcode: + logger << "op swap13" << std::endl; + va = pop_word(); + vb = pop_word(); + vc = pop_word(); + vd = pop_word(); + ve = pop_word(); + vf = pop_word(); + vg = pop_word(); + vh = pop_word(); + vi = pop_word(); + vj = pop_word(); + vk = pop_word(); + vl = pop_word(); + vm = pop_word(); + vn = pop_word(); + push_word(va); + push_word(vm); + push_word(vl); + push_word(vk); + push_word(vj); + push_word(vi); + push_word(vh); + push_word(vg); + push_word(vf); + push_word(ve); + push_word(vd); + push_word(vc); + push_word(vb); + push_word(vn); + break; + case swap14_opcode: + logger << "op swap14" << std::endl; + va = pop_word(); + vb = pop_word(); + vc = pop_word(); + vd = pop_word(); + ve = pop_word(); + vf = pop_word(); + vg = pop_word(); + vh = pop_word(); + vi = pop_word(); + vj = pop_word(); + vk = pop_word(); + vl = pop_word(); + vm = pop_word(); + vn = pop_word(); + vo = pop_word(); + push_word(va); + push_word(vn); + push_word(vm); + push_word(vl); + push_word(vk); + push_word(vj); + push_word(vi); + push_word(vh); + push_word(vg); + push_word(vf); + push_word(ve); + push_word(vd); + push_word(vc); + push_word(vb); + push_word(vo); + break; + case swap15_opcode: + logger << "op swap15" << std::endl; + va = pop_word(); + vb = pop_word(); + vc = pop_word(); + vd = pop_word(); + ve = pop_word(); + vf = pop_word(); + vg = pop_word(); + vh = pop_word(); + vi = pop_word(); + vj = pop_word(); + vk = pop_word(); + vl = pop_word(); + vm = pop_word(); + vn = pop_word(); + vo = pop_word(); + vp = pop_word(); + push_word(va); + push_word(vo); + push_word(vn); + push_word(vm); + push_word(vl); + push_word(vk); + push_word(vj); + push_word(vi); + push_word(vh); + push_word(vg); + push_word(vf); + push_word(ve); + push_word(vd); + push_word(vc); + push_word(vb); + push_word(vp); + break; + case swap16_opcode: + logger << "op swap16" << std::endl; + va = pop_word(); + vb = pop_word(); + vc = pop_word(); + vd = pop_word(); + ve = pop_word(); + vf = pop_word(); + vg = pop_word(); + vh = pop_word(); + vi = pop_word(); + vj = pop_word(); + vk = pop_word(); + vl = pop_word(); + vm = pop_word(); + vn = pop_word(); + vo = pop_word(); + vp = pop_word(); + vq = pop_word(); + push_word(va); + push_word(vp); + push_word(vo); + push_word(vn); + push_word(vm); + push_word(vl); + push_word(vk); + push_word(vj); + push_word(vi); + push_word(vh); + push_word(vg); + push_word(vf); + push_word(ve); + push_word(vd); + push_word(vc); + push_word(vb); + push_word(vq); + break; + case log0_opcode: + { + logger << "op log0" << std::endl; + va = pop_word(); // offset + vb = pop_word(); // length + word data = memory[size_t(va)]; + const log_object o = { data, uint8_t(vb), {} }; + this->emit_log(o); + + // Ex: + // log_object& o = { 0 /* data */, { 1, 2 } /* topics, 2 of them */ }; + break; + } + case log1_opcode: + { + logger << "op log1" << std::endl; + va = pop_word(); // offset + vb = pop_word(); // length + + std::vector topics; + + stack_variant& stack_object = stack.front(); + if (big_word* it = boost::get(&stack_object)) + { + stack.pop_front(); + topics.push_back(*it); + } + else { + throw; + } + + word data = memory[size_t(va)]; + const log_object o = { data, uint8_t(vb), topics }; + this->emit_log(o); + break; + } + case log2_opcode: + { + logger << "op log2" << std::endl; + va = pop_word(); // offset + vb = pop_word(); // length + + std::vector topics; + + stack_variant& stack_object = stack.front(); + if (big_word* it = boost::get(&stack_object)) + { + stack.pop_front(); + topics.push_back(*it); + } + else { + throw; + } + + stack_object = stack.front(); + if (big_word* it = boost::get(&stack_object)) + { + stack.pop_front(); + topics.push_back(*it); + } + else { + throw; + } + + word data = memory[size_t(va)]; + const log_object o = { data, uint8_t(vb), topics }; + this->emit_log(o); + break; + } + case log3_opcode: + { + logger << "op log3" << std::endl; + va = pop_word(); // offset + vb = pop_word(); // length + + std::vector topics; + + stack_variant& stack_object = stack.front(); + if (big_word* it = boost::get(&stack_object)) + { + stack.pop_front(); + topics.push_back(*it); + } + else { + throw; + } + + stack_object = stack.front(); + if (big_word* it = boost::get(&stack_object)) + { + stack.pop_front(); + topics.push_back(*it); + } + else { + throw; + } + + stack_object = stack.front(); + if (big_word* it = boost::get(&stack_object)) + { + stack.pop_front(); + topics.push_back(*it); + } + else { + throw; + } + + word data = memory[size_t(va)]; + const log_object o = { data, uint8_t(vb), topics }; + this->emit_log(o); + break; + } + case log4_opcode: + { + logger << "op log4" << std::endl; + va = pop_word(); // offset + vb = pop_word(); // length + + std::vector topics; + + stack_variant& stack_object = stack.front(); + if (big_word* it = boost::get(&stack_object)) + { + stack.pop_front(); + topics.push_back(*it); + } + else { + throw; + } + + stack_object = stack.front(); + if (big_word* it = boost::get(&stack_object)) + { + stack.pop_front(); + topics.push_back(*it); + } + else { + throw; + } + + stack_object = stack.front(); + if (big_word* it = boost::get(&stack_object)) + { + stack.pop_front(); + topics.push_back(*it); + } + else { + throw; + } + + stack_object = stack.front(); + if (big_word* it = boost::get(&stack_object)) + { + stack.pop_front(); + topics.push_back(*it); + } + else { + throw; + } + + word data = memory[size_t(va)]; + const log_object o = { data, uint8_t(vb), topics }; + this->emit_log(o); + break; + } + case return_opcode: + logger << "op return" << std::endl; + // a = pop_word(); // offset + // b = pop_word(); // length + // logger << std::to_string(a) << std::endl; + // logger << std::to_string(b) << std::endl; // return_value.resize(b); + // // TODO: Bounds checking + // // TODO: Check if size needs to be capped + // // TODO: Optimize + // for (int i = 0; i < return_value.size(); i++) + // return_value[i] = memory[a + i]; + // state = machine_state::stopped; + break; + } + } + + machine_state machine::get_state() + { + return state; + } + + std::stringstream& machine::get_logger() + { + return logger; + } + + bool machine::is_running() + { + return state == machine_state::running; + } + + std::string machine::to_json() + { + std::stringstream s; + s << "{"; + { + s << "\"finalState\":" << "{"; + { + s << "\"pc\":" << pc << ","; + s << "\"stack\":" << "["; + for (auto it = stack.cbegin(); it != stack.cend(); ++it) + { + stack_variant sv = *it; + s << sv; + if (it + 1 != stack.cend()) + s << ","; + } + s << "],"; + s << "\"returnValue\":" << "["; + for (auto it = return_value.cbegin(); it != return_value.cend(); ++it) + { + word w = *it; + s << std::to_string(w); + if (it + 1 != return_value.cend()) + s << ","; + } + s << "],"; + if (error_message == boost::none) + s << "\"exceptionError\":" << "null"; + else + s << "\"exceptionError\":" << "\"" << error_message.value() << "\""; + } + s << "}"; + } + s << "}"; + return s.str(); + } + + void machine::emit_log(const log_object& o) + { + } +} diff --git a/libraries/vendor/xgtvm/libraries/machine.hpp b/libraries/vendor/xgtvm/libraries/machine.hpp new file mode 100644 index 00000000..23ab6eb3 --- /dev/null +++ b/libraries/vendor/xgtvm/libraries/machine.hpp @@ -0,0 +1,274 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace machine +{ + +typedef uint8_t word; +typedef boost::multiprecision::uint256_t big_word; +typedef boost::multiprecision::int256_t signed_big_word; +typedef boost::variant stack_variant; + +enum opcode +{ + // ARITHMETIC + stop_opcode = 0x00, + add_opcode = 0x01, + mul_opcode = 0x02, + sub_opcode = 0x03, + div_opcode = 0x04, + sdiv_opcode = 0x05, + mod_opcode = 0x06, + smod_opcode = 0x07, + addmod_opcode = 0x08, + mulmod_opcode = 0x09, + exp_opcode = 0x0a, + + signextend_opcode = 0x0b, + + // COMPARISON + lt_opcode = 0x10, + gt_opcode = 0x11, + slt_opcode = 0x12, + sgt_opcode = 0x13, + eq_opcode = 0x14, + iszero_opcode = 0x15, + + // BITWISE + and_opcode = 0x16, + or_opcode = 0x17, + xor_opcode = 0x18, + not_opcode = 0x19, + byte_opcode = 0x1A, + shl_opcode = 0x1B, + shr_opcode = 0x1C, + sar_opcode = 0x1D, + + sha3_opcode = 0x20, // XXX depends on crypto++ -- needs cmake integration + address_opcode = 0x30, + balance_opcode = 0x31, // XXX Look up balance for address on top of stack. Is this an rpc call to the chain? + origin_opcode = 0x32, // XXX Transaction origin address + caller_opcode = 0x33, + callvalue_opcode = 0x34, + calldataload_opcode = 0x35, // XXX Reads a uint256 from message data + calldatasize_opcode = 0x36, // XXX Message data length in bytes + calldatacopy_opcode = 0x37, // XXX Copy message data to memory + codesize_opcode = 0x38, + codecopy_opcode = 0x39, // XXX Copy executing contract's bytecode to memory + gasprice_opcode = 0x3A, // XXX Price of executing contract. Energyprice? + extcodesize_opcode = 0x3B, // XXX Length of the contract bytecode at addr (top of stack) in bytes + extcodecopy_opcode = 0x3C, // XXX Copy contract's code to memory + returndatasize_opcode = 0x3D, // XXX Size of returned data from last external call in bytes + returndatacopy_opcode = 0x3E, // XXX Copy returned data to memory + extcodehash_opcode = 0x3F, // XXX Hash of contract bytecode at addr (top of stack) + blockhash_opcode = 0x40, // XXX Hash of specific block (blocknumber is top of stack) + coinbase_opcode = 0x41, // TODO REVIEW + timestamp_opcode = 0x42, + number_opcode = 0x43, + difficulty_opcode = 0x44, + gaslimit_opcode = 0x45, + pop_opcode = 0x50, + mload_opcode = 0x51, // TODO + mstore_opcode = 0x52, // TODO + mstore8_opcode = 0x53, // TODO + sload_opcode = 0x54, // TODO + sstore_opcode = 0x55, // TODO + jump_opcode = 0x56, + jumpi_opcode = 0x57, + pc_opcode = 0x58, + msize_opcode = 0x59, // TODO + gas_opcode = 0x5A, // TODO energy? + jumpdest_opcode = 0x5B, + + // PUSH + push1_opcode = 0x60, + push2_opcode = 0x61, + push3_opcode = 0x62, + push4_opcode = 0x63, + push5_opcode = 0x64, + push6_opcode = 0x65, + push7_opcode = 0x66, + push8_opcode = 0x67, + push9_opcode = 0x68, + push10_opcode = 0x69, + push11_opcode = 0x6A, + push12_opcode = 0x6B, + push13_opcode = 0x6C, + push14_opcode = 0x6D, + push15_opcode = 0x6E, + push16_opcode = 0x6F, + push17_opcode = 0x70, + push18_opcode = 0x71, + push19_opcode = 0x72, + push20_opcode = 0x73, + push21_opcode = 0x74, + push22_opcode = 0x75, + push23_opcode = 0x76, + push24_opcode = 0x77, + push25_opcode = 0x78, + push26_opcode = 0x79, + push27_opcode = 0x7A, + push28_opcode = 0x7B, + push29_opcode = 0x7C, + push30_opcode = 0x7D, + push31_opcode = 0x7E, + push32_opcode = 0x7F, + + // DUP + dup1_opcode = 0x80, + dup2_opcode = 0x81, + dup3_opcode = 0x82, + dup4_opcode = 0x83, + dup5_opcode = 0x84, + dup6_opcode = 0x85, + dup7_opcode = 0x86, + dup8_opcode = 0x87, + dup9_opcode = 0x88, + dup10_opcode = 0x89, + dup11_opcode = 0x8A, + dup12_opcode = 0x8B, + dup13_opcode = 0x8C, + dup14_opcode = 0x8D, + dup15_opcode = 0x8E, + dup16_opcode = 0x8F, + + // SWAP + swap1_opcode = 0x90, + swap2_opcode = 0x91, + swap3_opcode = 0x92, + swap4_opcode = 0x93, + swap5_opcode = 0x94, + swap6_opcode = 0x95, + swap7_opcode = 0x96, + swap8_opcode = 0x97, + swap9_opcode = 0x98, + swap10_opcode = 0x99, + swap11_opcode = 0x9A, + swap12_opcode = 0x9B, + swap13_opcode = 0x9C, + swap14_opcode = 0x9D, + swap15_opcode = 0x9E, + swap16_opcode = 0x9F, + + // LOG + log0_opcode = 0xA0, // TODO + log1_opcode = 0xA1, // TODO + log2_opcode = 0xA2, // TODO + log3_opcode = 0xA3, // TODO + log4_opcode = 0xA4, // TODO + + // Generic push/dup/swap opcodes + //push_opcode = 0xB0, // TODO + //dup_opcode = 0xB1, // TODO + //swap_opcode = 0xB2, // TODO + + //create_opcode = 0xF0, // TODO + //call_opcode = 0xF1, // TODO + //callcode_opcode = 0xF2, // TODO + return_opcode = 0xF3, + //delegatecall_opcode = 0xF4, // TODO + //create2_opcode = 0xF5, // TODO + //staticcall_opcode = 0xFA, // TODO + //revert_opcode = 0xFD, // TODO + //selfdestruct_opcode = 0xFF, // TODO +}; + +enum class machine_state +{ + stopped, + running, + error +}; + +struct log_object +{ + uint8_t data; + uint8_t data_size; + std::vector topics; +}; + + +struct message +{ + uint32_t flags; + int32_t depth; + int64_t gas; + + // TODO Need address datatype + // address sender; + big_word sender; + // address destination; + big_word destination; + + big_word value; + size_t input_size; + const uint8_t* input_data; + size_t code_size; +}; + +struct context +{ + bool is_debug; + uint64_t block_timestamp; + uint64_t block_number; + uint64_t block_difficulty; + uint64_t block_gaslimit; + uint64_t tx_gasprice; + // Should be address datatype + uint64_t block_coinbase; +}; + +/* TODO switch stack to variant implementing this pattern + + if (stack_variant* it = std::get_if(from)) + { + stack_variant& stack_object = std::get(from); + // Use `stack_object` as normal + } + */ + +class machine +{ + size_t pc = 0; + std::deque stack; + machine_state state = machine_state::running; + std::vector memory; + std::vector return_value; + context ctx; + std::vector code; + message msg; + boost::optional error_message; + std::stringstream logger; + + void push_word(stack_variant v); + big_word pop_word(); + void log(std::string output); + + public: + machine(context ctx, std::vector code, message msg) + : ctx(ctx), code(code), msg(msg) + { + } + + big_word peek_word(); + void print_stack(); + size_t stack_length(); + void step(); + bool is_running(); + machine_state get_state(); + std::stringstream& get_logger(); + std::string to_json(); + + void emit_log(const log_object& o); +}; + +} diff --git a/libraries/vendor/xgtvm/programs/xgtvm.cpp b/libraries/vendor/xgtvm/programs/xgtvm.cpp new file mode 100644 index 00000000..06d2cfa3 --- /dev/null +++ b/libraries/vendor/xgtvm/programs/xgtvm.cpp @@ -0,0 +1,110 @@ +#include +#include +#include +#include +#include +#include +#include "machine.hpp" +#include "unistd.h" + +std::string process_stdin() +{ + std::cin >> std::noskipws; + std::istream_iterator it(std::cin); + std::istream_iterator end; + std::string results(it, end); + return results; +} + +machine::word to_hex(std::string str) +{ + return std::stoi(str, 0, 16); +} + +std::vector process_eval(const std::string& str) +{ + char delim = ' '; + std::size_t current, previous = 0; + std::string token; + std::vector tokens; + current = str.find(delim); + while (current != std::string::npos) { + tokens.push_back( to_hex( str.substr(previous, current - previous) ) ); + previous = current + 1; + current = str.find(delim, previous); + } + token = str.substr(previous, current - previous); + tokens.push_back( to_hex(token) ); + return tokens; +} + +// Set by --debug or -d +static int debug_flag; +// Set by --eval or -e +static int eval_flag; +static char* eval_cstr; +// Set by --help or -h +static int help_flag; +static struct option long_options[] = { + {"eval", required_argument, 0, 'e'}, + {"debug", no_argument, &debug_flag, 'd'}, + {"help", no_argument, &help_flag, 1}, + {0, 0, 0, 0} +}; + +int main(int argc, char** argv) +{ + int c; + for (;;) + { + int option_index = 0; + c = getopt_long(argc, argv, "de:h", long_options, &option_index); + if (c == -1) + break; + switch(c) + { + case 'd': + debug_flag = 1; + break; + case 'e': + eval_flag = 1; + eval_cstr = optarg; + break; + case 'h': + help_flag = 1; + break; + } + } + + // TODO: Add a help message + if (help_flag) + {} + + std::string input = process_stdin(); + if(eval_flag) + input = std::string(eval_cstr); + if (input.size() > 0) + { + machine::context ctx = {true, 0x5c477758}; + machine::message msg = {}; + std::vector code = process_eval(input); + machine::machine m(ctx, code, msg); + std::string line; + while (m.is_running()) + { + std::cerr << "step\n"; + m.step(); + // Print out any logging that was generated + if (debug_flag) + { + while ( std::getline(m.get_logger(), line) ) + std::cerr << "\e[36m" << "LOG: " << line << "\e[0m" << std::endl; + } + } + while ( std::getline(m.get_logger(), line) ) + std::cerr << "\e[36m" << "LOG: " << line << "\e[0m" << std::endl; + std::cout << m.to_json() << std::endl; + } + + return 0; +} diff --git a/libraries/vendor/xgtvm/programs/xgtvm_tests.cpp b/libraries/vendor/xgtvm/programs/xgtvm_tests.cpp new file mode 100644 index 00000000..72d802e2 --- /dev/null +++ b/libraries/vendor/xgtvm/programs/xgtvm_tests.cpp @@ -0,0 +1,66 @@ +#include +#include "machine.hpp" + +#define test_that(message) \ + std::cerr << "\e[34m" << ( message ) << "\e[0m" << std::endl; +#define assert_message(message, assertion) \ + { \ + bool result = ( assertion ); \ + std::cerr << " " << ( result ? "\e[32m" : "\e[31m" ) << ( message ) << "\e[0m" << std::endl; \ + } + +int main(int argc, char** argv) +{ + test_that("machine runs and halts") + { + std::vector input = {0x00}; + machine::context ctx = {true, 0x00}; + machine::message msg = {}; + machine::machine m(ctx, input, msg); + assert_message( "machine should start running", m.get_state() == machine::machine_state::running ); + while (m.is_running()) + m.step(); + assert_message( "machine should stop when done executing", m.get_state() == machine::machine_state::stopped ); + assert_message( "stack has correct length", m.stack_length() == 0 ); + } + + test_that("machine halts when nothing else to do") + { + std::vector input = {}; + machine::context ctx = {true, 0x00}; + machine::message msg = {}; + machine::machine m(ctx, input, msg); + while (m.is_running()) + m.step(); + assert_message( "machine should stop when done executing", m.get_state() == machine::machine_state::stopped ); + assert_message( "stack has correct length", m.stack_length() == 0 ); + } + + test_that("machine returns a timestamp") + { + std::vector input = {0x42, 0x00}; + machine::context ctx = {true, 0x5c477758}; + machine::message msg = {}; + machine::machine m(ctx, input, msg); + while (m.is_running()) + m.step(); + assert_message( "machine should stop when done executing", m.get_state() == machine::machine_state::stopped ); + assert_message( "stack has correct length", m.stack_length() == 1 ); + assert_message( "top of stack has correct value", m.peek_word() == 0x5c477758 ); + } + + test_that("machine adds unsigned 8-bit values") + { + std::vector input = {0x60, 0x02, 0x60, 0x03, 0x01, 0x00}; + machine::context ctx = {true, 0x00}; + machine::message msg = {}; + machine::machine m(ctx, input, msg); + while (m.is_running()) + m.step(); + assert_message( "machine should stop when done executing", m.get_state() == machine::machine_state::stopped ); + assert_message( "stack has correct length", m.stack_length() == 1 ); + assert_message( "top of stack has correct value", m.peek_word() == 5 ); + } + + return 0; +} From 7a2b2ca9f997683ba23d8d3a6193606ffb82aadb Mon Sep 17 00:00:00 2001 From: Roger Jungemann Date: Mon, 12 Jul 2021 13:18:54 -0700 Subject: [PATCH 02/96] Add xgtvm to xgt --- libraries/vendor/xgtvm/CMakeLists.txt | 10 +++------- libraries/vendor/xgtvm/Rakefile | 2 +- libraries/vendor/xgtvm/libraries/machine.hpp | 4 ++-- 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/libraries/vendor/xgtvm/CMakeLists.txt b/libraries/vendor/xgtvm/CMakeLists.txt index ae896875..49eb0840 100644 --- a/libraries/vendor/xgtvm/CMakeLists.txt +++ b/libraries/vendor/xgtvm/CMakeLists.txt @@ -1,18 +1,14 @@ -cmake_minimum_required( VERSION 3.2 ) +cmake_minimum_required(VERSION 2.8.9) project(Xgtvm) -#set(CMAKE_CXX_STANDARD 14) -#set(CMAKE_CXX_STANDARD_REQUIRED ON) -#set(CMAKE_CXX_EXTENSIONS OFF) - find_package( Boost REQUIRED ) include_directories( ${Boost_INCLUDE_DIR} ) # Library -add_library(xgtvm libraries/machine.cpp libraries/machine.hpp) +add_library(xgtvm programs/xgtvm.cpp libraries/machine.cpp libraries/machine.hpp) target_link_libraries( xgtvm LINK_PUBLIC ${Boost_LIBRARIES} ) target_include_directories(xgtvm PRIVATE libraries) -# Executable +# Binary add_executable(xgtvmd programs/xgtvm.cpp libraries/machine.cpp libraries/machine.hpp) target_link_libraries( xgtvmd LINK_PUBLIC ${Boost_LIBRARIES} ) target_include_directories(xgtvmd PRIVATE libraries) diff --git a/libraries/vendor/xgtvm/Rakefile b/libraries/vendor/xgtvm/Rakefile index 1732f0ba..ebe86323 100644 --- a/libraries/vendor/xgtvm/Rakefile +++ b/libraries/vendor/xgtvm/Rakefile @@ -6,7 +6,7 @@ def which?(cmd_name) end def xgtvm_eval(string) - # cmd = %(cd build && ./xgtvm -e'#{string}') + # cmd = %(cd build && ./xgtvmd -e'#{string}') cmd = %(cd build && echo '#{string}' | ./xgtvmd) $stderr.puts(cmd) result = %x(#{cmd}) diff --git a/libraries/vendor/xgtvm/libraries/machine.hpp b/libraries/vendor/xgtvm/libraries/machine.hpp index 23ab6eb3..45273519 100644 --- a/libraries/vendor/xgtvm/libraries/machine.hpp +++ b/libraries/vendor/xgtvm/libraries/machine.hpp @@ -241,11 +241,11 @@ class machine size_t pc = 0; std::deque stack; machine_state state = machine_state::running; - std::vector memory; - std::vector return_value; context ctx; std::vector code; message msg; + std::vector memory; + std::vector return_value; boost::optional error_message; std::stringstream logger; From b4342fc33671b14c135f26a116481b7552a877bd Mon Sep 17 00:00:00 2001 From: Liam Noroian Date: Tue, 13 Jul 2021 11:19:25 -0700 Subject: [PATCH 03/96] Adding machine api --- .../plugins/apis/machine_api/CMakeLists.txt | 24 +++++++ .../xgt/plugins/machine_api/machine_api.hpp | 45 ++++++++++++ .../machine_api/machine_api_plugin.hpp | 37 ++++++++++ .../plugins/apis/machine_api/machine_api.cpp | 68 +++++++++++++++++++ .../apis/machine_api/machine_api_plugin.cpp | 20 ++++++ .../plugins/apis/machine_api/plugin.json | 5 ++ 6 files changed, 199 insertions(+) create mode 100644 libraries/plugins/apis/machine_api/CMakeLists.txt create mode 100644 libraries/plugins/apis/machine_api/include/xgt/plugins/machine_api/machine_api.hpp create mode 100644 libraries/plugins/apis/machine_api/include/xgt/plugins/machine_api/machine_api_plugin.hpp create mode 100644 libraries/plugins/apis/machine_api/machine_api.cpp create mode 100644 libraries/plugins/apis/machine_api/machine_api_plugin.cpp create mode 100644 libraries/plugins/apis/machine_api/plugin.json diff --git a/libraries/plugins/apis/machine_api/CMakeLists.txt b/libraries/plugins/apis/machine_api/CMakeLists.txt new file mode 100644 index 00000000..069b4c52 --- /dev/null +++ b/libraries/plugins/apis/machine_api/CMakeLists.txt @@ -0,0 +1,24 @@ +file(GLOB HEADERS "include/xgt/plugins/machine_api/*.hpp") +add_library( machine_api_plugin + machine_api_plugin.cpp + machine_api.cpp + ${HEADERS} + ) + +target_link_libraries( machine_api_plugin chain_plugin json_rpc_plugin ) +target_include_directories( machine_api_plugin PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" ) + +if( CLANG_TIDY_EXE ) + set_target_properties( + machine_api_plugin PROPERTIES + CXX_CLANG_TIDY "${DO_CLANG_TIDY}" + ) +endif( CLANG_TIDY_EXE ) + +install( TARGETS + machine_api_plugin + + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib +) diff --git a/libraries/plugins/apis/machine_api/include/xgt/plugins/machine_api/machine_api.hpp b/libraries/plugins/apis/machine_api/include/xgt/plugins/machine_api/machine_api.hpp new file mode 100644 index 00000000..2f32a686 --- /dev/null +++ b/libraries/plugins/apis/machine_api/include/xgt/plugins/machine_api/machine_api.hpp @@ -0,0 +1,45 @@ +#pragma once +#include + +#include + +#include +#include +#include + +namespace xgt { namespace plugins { namespace machine { + +namespace detail +{ + class machine_api_impl; +} + +struct adjure_args +{ + std::vector bytecode; +}; + +struct adjure_return +{ + int return_code; +}; + +class machine_api +{ + public: + machine_api(); + ~machine_api(); + + DECLARE_API( (adjure) ) + + private: + std::unique_ptr< detail::machine_api_impl > my; +}; + +} } } // xgt::plugins::machine + +FC_REFLECT( xgt::plugins::machine::adjure_args, + (bytecode) ) + +FC_REFLECT( xgt::plugins::machine::adjure_return, + (return_code) ) diff --git a/libraries/plugins/apis/machine_api/include/xgt/plugins/machine_api/machine_api_plugin.hpp b/libraries/plugins/apis/machine_api/include/xgt/plugins/machine_api/machine_api_plugin.hpp new file mode 100644 index 00000000..157f0568 --- /dev/null +++ b/libraries/plugins/apis/machine_api/include/xgt/plugins/machine_api/machine_api_plugin.hpp @@ -0,0 +1,37 @@ +#pragma once +#include +// #include +#include + +#include + +#define XGT_MACHINE_API_PLUGIN_NAME "machine_api" + + +namespace xgt { namespace plugins { namespace machine { + +using namespace appbase; + +class machine_api_plugin : public appbase::plugin< machine_api_plugin > +{ +public: + APPBASE_PLUGIN_REQUIRES( + // (xgt::plugins::machine::machine_plugin) + (xgt::plugins::json_rpc::json_rpc_plugin) + ) + + machine_api_plugin(); + virtual ~machine_api_plugin(); + + static const std::string& name() { static std::string name = XGT_MACHINE_API_PLUGIN_NAME; return name; } + + virtual void set_program_options( options_description& cli, options_description& cfg ) override; + + virtual void plugin_initialize( const variables_map& options ) override; + virtual void plugin_startup() override; + virtual void plugin_shutdown() override; + + std::shared_ptr< class machine_api > api; +}; + +} } } // xgt::plugins::machine diff --git a/libraries/plugins/apis/machine_api/machine_api.cpp b/libraries/plugins/apis/machine_api/machine_api.cpp new file mode 100644 index 00000000..b2ccaaea --- /dev/null +++ b/libraries/plugins/apis/machine_api/machine_api.cpp @@ -0,0 +1,68 @@ +#include + +#include +#include + +#include +#include +// #include + +// TODO: Remove this later +#include "iomanip" + +namespace xgt { namespace plugins { namespace machine { + +namespace detail { + +class machine_api_impl +{ + public: + machine_api_impl() : _db( appbase::app().get_plugin< xgt::plugins::chain::chain_plugin >().db() ) {} + + adjure_return adjure( const adjure_args& args )const; + + chain::database& _db; +}; + +adjure_return machine_api_impl::adjure( const adjure_args& args )const +{ + adjure_return final_result; + + // std::cout << "====="; + // std::cout << std::endl; + // std::cout << "args.bytecode.size(): "; + // std::cout << args.bytecode.size(); + // std::cout << std::endl; + // std::stringstream stream; + // for (size_t i = 0; i < args.bytecode.size(); ++i) + // { + // uint8_t byte = args.bytecode[i]; + // std::cout << unsigned(byte) << std::endl; + // } + // std::cout << std::endl; + + machine m(args.bytecode); + // m.register_listener(std::move(std::unique_ptr(new stub_listener()))); + m.register_instruction(noop_opcode, std::move(std::unique_ptr(new noop_instruction()))); + m.register_instruction(push_opcode, std::move(std::unique_ptr(new push_instruction()))); + m.register_instruction(add_opcode, std::move(std::unique_ptr(new add_instruction()))); + m.register_instruction(display_opcode, std::move(std::unique_ptr(new display_instruction()))); + while (m.is_running()) + m.step(); + + final_result.return_code = 0; + return final_result; +} + +} // detail + +machine_api::machine_api(): my( new detail::machine_api_impl() ) +{ + JSON_RPC_REGISTER_API( XGT_MACHINE_API_PLUGIN_NAME ); +} + +machine_api::~machine_api() {} + +DEFINE_READ_APIS( machine_api, (adjure) ) + +} } } // xgt::plugins::machine diff --git a/libraries/plugins/apis/machine_api/machine_api_plugin.cpp b/libraries/plugins/apis/machine_api/machine_api_plugin.cpp new file mode 100644 index 00000000..f39fae6d --- /dev/null +++ b/libraries/plugins/apis/machine_api/machine_api_plugin.cpp @@ -0,0 +1,20 @@ +#include +#include + + +namespace xgt { namespace plugins { namespace machine { + +machine_api_plugin::machine_api_plugin() {} +machine_api_plugin::~machine_api_plugin() {} + +void machine_api_plugin::set_program_options( options_description& cli, options_description& cfg ) {} + +void machine_api_plugin::plugin_initialize( const variables_map& options ) +{ + api = std::make_shared< machine_api >(); +} + +void machine_api_plugin::plugin_startup() {} +void machine_api_plugin::plugin_shutdown() {} + +} } } // xgt::plugins::machine diff --git a/libraries/plugins/apis/machine_api/plugin.json b/libraries/plugins/apis/machine_api/plugin.json new file mode 100644 index 00000000..916bbf48 --- /dev/null +++ b/libraries/plugins/apis/machine_api/plugin.json @@ -0,0 +1,5 @@ +{ + "plugin_name": "machine_api", + "plugin_namespace": "machine", + "plugin_project": "machine_api_plugin" +} From 6fb2d4877f8281ff2ca9518d90356347cde67554 Mon Sep 17 00:00:00 2001 From: Liam Noroian Date: Tue, 13 Jul 2021 11:25:23 -0700 Subject: [PATCH 04/96] Adding plugins to rakefile --- Rakefile | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Rakefile b/Rakefile index beaf3e8b..4e1d887b 100644 --- a/Rakefile +++ b/Rakefile @@ -99,6 +99,13 @@ end desc 'Runs a basic example instance locally' task :run do + + plugins = %w( + chain p2p webserver witness database_api network_broadcast_api block_api + account_by_key account_history account_history_api condenser_api + transaction_status_api account_by_key_api rc_api machine_api + ) + data_dir = "../xgt-build/chain-data-#{instance_index}" if flush_testnet? From b5837f483b440fc8afb7cb748a47518b70508965 Mon Sep 17 00:00:00 2001 From: Liam Noroian Date: Wed, 14 Jul 2021 10:05:35 -0700 Subject: [PATCH 05/96] Committing changes to cmakelists for chain-tests --- tests/CMakeLists.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 7dd77a7d..a84ef8c8 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -68,6 +68,7 @@ add_boost_test( chain_test automated_action_tests/reject_optional_action basic_tests/parse_size_test basic_tests/valid_name_test + block_tests/generate_empty_blocks basic_tests/merkle_root operation_tests/account_create_validate operation_tests/account_create_authorities @@ -283,7 +284,7 @@ add_boost_test( chain_test undo_tests/undo_generate_blocks ) -target_link_libraries( chain_test db_fixture chainbase xgt_chain xgt_protocol wallet_history_plugin witness_plugin debug_node_plugin fc ${PLATFORM_SPECIFIC_LIBS} ) +target_link_libraries( chain_test db_fixture chainbase xgt_chain xgt_protocol chain_plugin wallet_history_plugin witness_plugin debug_node_plugin fc ${PLATFORM_SPECIFIC_LIBS} ) file(GLOB PLUGIN_TESTS "plugin_tests/*.cpp") @@ -302,7 +303,7 @@ add_boost_test( plugin_test transaction_status/transaction_status_test ) -target_link_libraries( plugin_test db_fixture xgt_chain xgt_protocol wallet_history_plugin witness_plugin debug_node_plugin transaction_status_plugin transaction_status_api_plugin fc ${PLATFORM_SPECIFIC_LIBS} ) +target_link_libraries( plugin_test db_fixture xgt_chain xgt_protocol wallet_history_plugin witness_plugin debug_node_plugin transaction_status_plugin transaction_status_api_plugin xgt_utilities xgt_plugins ${PLATFORM_SPECIFIC_LIBS} ) if(MSVC) set_source_files_properties( tests/serialization_tests.cpp PROPERTIES COMPILE_FLAGS "/bigobj" ) From 71f1d7d8bbd078e7c7d75cb6c2a95090974b2ee5 Mon Sep 17 00:00:00 2001 From: Liam Noroian Date: Mon, 19 Jul 2021 14:31:31 -0700 Subject: [PATCH 06/96] Busting through errors to build machine_api --- .../plugins/apis/machine_api/machine_api.cpp | 5 +- xgt-tests-build/libraries/fc/git_revision.cpp | 11 +++ .../tmp/project_secp256k1-cfgcmd.txt | 1 + .../tmp/project_secp256k1-cfgcmd.txt.in | 1 + .../manifest/gensrc/plugins/CMakeLists.txt | 53 +++++++++++ .../plugins/include/xgt/manifest/plugins.hpp | 12 +++ .../manifest/gensrc/plugins/mf_plugins.cpp | 79 +++++++++++++++++ .../manifest/gensrc/plugins/plugins.cpp | 1 + .../manifest/template_context/plugins.json | 1 + .../libraries/utilities/git_revision.cpp | 14 +++ .../vendor/rocksdb/RocksDBConfig.cmake | 88 +++++++++++++++++++ .../vendor/rocksdb/RocksDBConfigVersion.cmake | 51 +++++++++++ 12 files changed, 316 insertions(+), 1 deletion(-) create mode 100644 xgt-tests-build/libraries/fc/git_revision.cpp create mode 100644 xgt-tests-build/libraries/fc/vendor/secp256k1-zkp/tmp/project_secp256k1-cfgcmd.txt create mode 100644 xgt-tests-build/libraries/fc/vendor/secp256k1-zkp/tmp/project_secp256k1-cfgcmd.txt.in create mode 100644 xgt-tests-build/libraries/manifest/gensrc/plugins/CMakeLists.txt create mode 100644 xgt-tests-build/libraries/manifest/gensrc/plugins/include/xgt/manifest/plugins.hpp create mode 100644 xgt-tests-build/libraries/manifest/gensrc/plugins/mf_plugins.cpp create mode 100644 xgt-tests-build/libraries/manifest/gensrc/plugins/plugins.cpp create mode 100644 xgt-tests-build/libraries/manifest/template_context/plugins.json create mode 100644 xgt-tests-build/libraries/utilities/git_revision.cpp create mode 100644 xgt-tests-build/libraries/vendor/rocksdb/RocksDBConfig.cmake create mode 100644 xgt-tests-build/libraries/vendor/rocksdb/RocksDBConfigVersion.cmake diff --git a/libraries/plugins/apis/machine_api/machine_api.cpp b/libraries/plugins/apis/machine_api/machine_api.cpp index b2ccaaea..a51ea87e 100644 --- a/libraries/plugins/apis/machine_api/machine_api.cpp +++ b/libraries/plugins/apis/machine_api/machine_api.cpp @@ -41,7 +41,10 @@ adjure_return machine_api_impl::adjure( const adjure_args& args )const // } // std::cout << std::endl; - machine m(args.bytecode); + ctx = {} + msg = {} + + machine m(ctx, args.bytecode, msg); // m.register_listener(std::move(std::unique_ptr(new stub_listener()))); m.register_instruction(noop_opcode, std::move(std::unique_ptr(new noop_instruction()))); m.register_instruction(push_opcode, std::move(std::unique_ptr(new push_instruction()))); diff --git a/xgt-tests-build/libraries/fc/git_revision.cpp b/xgt-tests-build/libraries/fc/git_revision.cpp new file mode 100644 index 00000000..06068832 --- /dev/null +++ b/xgt-tests-build/libraries/fc/git_revision.cpp @@ -0,0 +1,11 @@ +#include + +#define FC_GIT_REVISION_SHA "30ccdd98a05bbc4c7393868627dc569eb532ac66" +#define FC_GIT_REVISION_UNIX_TIMESTAMP 1625816327 + +namespace fc { + +const char* const git_revision_sha = FC_GIT_REVISION_SHA; +const uint32_t git_revision_unix_timestamp = FC_GIT_REVISION_UNIX_TIMESTAMP; + +} // end namespace fc diff --git a/xgt-tests-build/libraries/fc/vendor/secp256k1-zkp/tmp/project_secp256k1-cfgcmd.txt b/xgt-tests-build/libraries/fc/vendor/secp256k1-zkp/tmp/project_secp256k1-cfgcmd.txt new file mode 100644 index 00000000..472131d5 --- /dev/null +++ b/xgt-tests-build/libraries/fc/vendor/secp256k1-zkp/tmp/project_secp256k1-cfgcmd.txt @@ -0,0 +1 @@ +cmd='/home/lnoroian/xgt/libraries/fc/vendor/secp256k1-zkp/configure;--prefix=/home/lnoroian/xgt/xgt-tests-build/libraries/fc/vendor/secp256k1-zkp;--with-bignum=no' diff --git a/xgt-tests-build/libraries/fc/vendor/secp256k1-zkp/tmp/project_secp256k1-cfgcmd.txt.in b/xgt-tests-build/libraries/fc/vendor/secp256k1-zkp/tmp/project_secp256k1-cfgcmd.txt.in new file mode 100644 index 00000000..b3f09efc --- /dev/null +++ b/xgt-tests-build/libraries/fc/vendor/secp256k1-zkp/tmp/project_secp256k1-cfgcmd.txt.in @@ -0,0 +1 @@ +cmd='@cmd@' diff --git a/xgt-tests-build/libraries/manifest/gensrc/plugins/CMakeLists.txt b/xgt-tests-build/libraries/manifest/gensrc/plugins/CMakeLists.txt new file mode 100644 index 00000000..6c4eb962 --- /dev/null +++ b/xgt-tests-build/libraries/manifest/gensrc/plugins/CMakeLists.txt @@ -0,0 +1,53 @@ + +add_library( xgt_plugins + mf_plugins.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/include/xgt/manifest/plugins.hpp +) + +target_link_libraries( xgt_plugins appbase fc + + wallet_by_key_plugin + + wallet_history_rocksdb_plugin + + transaction_status_plugin + + chain_plugin + + webserver_plugin + + chain_api_plugin + + transaction_api_plugin + + wallet_by_key_api_plugin + + contract_api_plugin + + wallet_history_api_plugin + + database_api_plugin + + block_api_plugin + + debug_node_plugin + + p2p_plugin + + wallet_history_plugin + + witness_plugin + +) + +target_include_directories( xgt_plugins + PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" + ) + +INSTALL( TARGETS + xgt_plugins + + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib +) \ No newline at end of file diff --git a/xgt-tests-build/libraries/manifest/gensrc/plugins/include/xgt/manifest/plugins.hpp b/xgt-tests-build/libraries/manifest/gensrc/plugins/include/xgt/manifest/plugins.hpp new file mode 100644 index 00000000..b4164761 --- /dev/null +++ b/xgt-tests-build/libraries/manifest/gensrc/plugins/include/xgt/manifest/plugins.hpp @@ -0,0 +1,12 @@ + +#pragma once + +#include +#include +#include + +namespace xgt { namespace plugins { + +void register_plugins(); + +} } diff --git a/xgt-tests-build/libraries/manifest/gensrc/plugins/mf_plugins.cpp b/xgt-tests-build/libraries/manifest/gensrc/plugins/mf_plugins.cpp new file mode 100644 index 00000000..6de9c7ba --- /dev/null +++ b/xgt-tests-build/libraries/manifest/gensrc/plugins/mf_plugins.cpp @@ -0,0 +1,79 @@ +#include +#include + +#include + + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + + +namespace xgt { namespace plugins { + +void register_plugins() +{ + + appbase::app().register_plugin< xgt::plugins::wallet_by_key::wallet_by_key_plugin >(); + + appbase::app().register_plugin< xgt::plugins::wallet_history_rocksdb::wallet_history_rocksdb_plugin >(); + + appbase::app().register_plugin< xgt::plugins::transaction_status::transaction_status_plugin >(); + + appbase::app().register_plugin< xgt::plugins::chain::chain_plugin >(); + + appbase::app().register_plugin< xgt::plugins::webserver::webserver_plugin >(); + + appbase::app().register_plugin< xgt::plugins::chain::chain_api_plugin >(); + + appbase::app().register_plugin< xgt::plugins::transaction_api::transaction_api_plugin >(); + + appbase::app().register_plugin< xgt::plugins::wallet_by_key::wallet_by_key_api_plugin >(); + + appbase::app().register_plugin< xgt::plugins::contract::contract_api_plugin >(); + + appbase::app().register_plugin< xgt::plugins::wallet_history::wallet_history_api_plugin >(); + + appbase::app().register_plugin< xgt::plugins::database_api::database_api_plugin >(); + + appbase::app().register_plugin< xgt::plugins::block_api::block_api_plugin >(); + + appbase::app().register_plugin< xgt::plugins::debug_node::debug_node_plugin >(); + + appbase::app().register_plugin< xgt::plugins::p2p::p2p_plugin >(); + + appbase::app().register_plugin< xgt::plugins::wallet_history::wallet_history_plugin >(); + + appbase::app().register_plugin< xgt::plugins::witness::witness_plugin >(); + +} + +} } \ No newline at end of file diff --git a/xgt-tests-build/libraries/manifest/gensrc/plugins/plugins.cpp b/xgt-tests-build/libraries/manifest/gensrc/plugins/plugins.cpp new file mode 100644 index 00000000..34b39c98 --- /dev/null +++ b/xgt-tests-build/libraries/manifest/gensrc/plugins/plugins.cpp @@ -0,0 +1 @@ +// empty cpp file for plugin project diff --git a/xgt-tests-build/libraries/manifest/template_context/plugins.json b/xgt-tests-build/libraries/manifest/template_context/plugins.json new file mode 100644 index 00000000..6e42d767 --- /dev/null +++ b/xgt-tests-build/libraries/manifest/template_context/plugins.json @@ -0,0 +1 @@ +{"plugins": [{"plugin_name": "wallet_by_key", "plugin_namespace": "wallet_by_key", "plugin_project": "wallet_by_key_plugin"}, {"plugin_name": "wallet_history_rocksdb", "plugin_namespace": "wallet_history_rocksdb", "plugin_project": "wallet_history_rocksdb_plugin"}, {"plugin_name": "transaction_status", "plugin_namespace": "transaction_status", "plugin_project": "transaction_status_plugin"}, {"plugin_name": "chain", "plugin_namespace": "chain", "plugin_project": "chain_plugin"}, {"plugin_name": "webserver", "plugin_namespace": "webserver", "plugin_project": "webserver_plugin"}, {"plugin_name": "chain_api", "plugin_namespace": "chain", "plugin_project": "chain_api_plugin"}, {"plugin_name": "transaction_api", "plugin_namespace": "transaction_api", "plugin_project": "transaction_api_plugin"}, {"plugin_name": "wallet_by_key_api", "plugin_namespace": "wallet_by_key", "plugin_project": "wallet_by_key_api_plugin"}, {"plugin_name": "contract_api", "plugin_namespace": "contract", "plugin_project": "contract_api_plugin"}, {"plugin_name": "wallet_history_api", "plugin_namespace": "wallet_history", "plugin_project": "wallet_history_api_plugin"}, {"plugin_name": "database_api", "plugin_namespace": "database_api", "plugin_project": "database_api_plugin"}, {"plugin_name": "block_api", "plugin_namespace": "block_api", "plugin_project": "block_api_plugin"}, {"plugin_name": "debug_node", "plugin_namespace": "debug_node", "plugin_project": "debug_node_plugin"}, {"plugin_name": "p2p", "plugin_namespace": "p2p", "plugin_project": "p2p_plugin"}, {"plugin_name": "wallet_history", "plugin_namespace": "wallet_history", "plugin_project": "wallet_history_plugin"}, {"plugin_name": "witness", "plugin_namespace": "witness", "plugin_project": "witness_plugin"}], "index_extensions": []} diff --git a/xgt-tests-build/libraries/utilities/git_revision.cpp b/xgt-tests-build/libraries/utilities/git_revision.cpp new file mode 100644 index 00000000..65d5e532 --- /dev/null +++ b/xgt-tests-build/libraries/utilities/git_revision.cpp @@ -0,0 +1,14 @@ +#include +#include + +#define XGT_GIT_REVISION_SHA "30ccdd98a05bbc4c7393868627dc569eb532ac66" +#define XGT_GIT_REVISION_UNIX_TIMESTAMP 1625816327 +#define XGT_GIT_REVISION_DESCRIPTION "1.3.1-16-g30ccdd9" + +namespace xgt { namespace utilities { + +const char* const git_revision_sha = XGT_GIT_REVISION_SHA; +const uint32_t git_revision_unix_timestamp = XGT_GIT_REVISION_UNIX_TIMESTAMP; +const char* const git_revision_description = XGT_GIT_REVISION_DESCRIPTION; + +} } // end namespace xgt::utilities diff --git a/xgt-tests-build/libraries/vendor/rocksdb/RocksDBConfig.cmake b/xgt-tests-build/libraries/vendor/rocksdb/RocksDBConfig.cmake new file mode 100644 index 00000000..0422f83d --- /dev/null +++ b/xgt-tests-build/libraries/vendor/rocksdb/RocksDBConfig.cmake @@ -0,0 +1,88 @@ + +####### Expanded from @PACKAGE_INIT@ by configure_package_config_file() ####### +####### Any changes to this file will be overwritten by the next CMake run #### +####### The input file was RocksDBConfig.cmake.in ######## + +get_filename_component(PACKAGE_PREFIX_DIR "${CMAKE_CURRENT_LIST_DIR}/../../../../" ABSOLUTE) + +# Use original install prefix when loaded through a "/usr move" +# cross-prefix symbolic link such as /lib -> /usr/lib. +get_filename_component(_realCurr "${CMAKE_CURRENT_LIST_DIR}" REALPATH) +get_filename_component(_realOrig "/usr/lib/x86_64-linux-gnu/cmake/rocksdb" REALPATH) +if(_realCurr STREQUAL _realOrig) + set(PACKAGE_PREFIX_DIR "/usr") +endif() +unset(_realOrig) +unset(_realCurr) + +macro(set_and_check _var _file) + set(${_var} "${_file}") + if(NOT EXISTS "${_file}") + message(FATAL_ERROR "File or directory ${_file} referenced by variable ${_var} does not exist !") + endif() +endmacro() + +macro(check_required_components _NAME) + foreach(comp ${${_NAME}_FIND_COMPONENTS}) + if(NOT ${_NAME}_${comp}_FOUND) + if(${_NAME}_FIND_REQUIRED_${comp}) + set(${_NAME}_FOUND FALSE) + endif() + endif() + endforeach() +endmacro() + +#################################################################################### + +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/modules") + +include(CMakeFindDependencyMacro) + +set(GFLAGS_USE_TARGET_NAMESPACE ) + +if(OFF) + find_dependency(JeMalloc) +endif() + +if(OFF) + find_dependency(gflags CONFIG) + if(NOT gflags_FOUND) + find_dependency(gflags) + endif() +endif() + +if(ON) + find_dependency(Snappy CONFIG) + if(NOT Snappy_FOUND) + find_dependency(Snappy) + endif() +endif() + +if(OFF) + find_dependency(ZLIB) +endif() + +if(OFF) + find_dependency(BZip2) +endif() + +if(OFF) + find_dependency(lz4) +endif() + +if(OFF) + find_dependency(zstd) +endif() + +if(OFF) + find_dependency(NUMA) +endif() + +if(OFF) + find_dependency(TBB) +endif() + +find_dependency(Threads) + +include("${CMAKE_CURRENT_LIST_DIR}/RocksDBTargets.cmake") +check_required_components(RocksDB) diff --git a/xgt-tests-build/libraries/vendor/rocksdb/RocksDBConfigVersion.cmake b/xgt-tests-build/libraries/vendor/rocksdb/RocksDBConfigVersion.cmake new file mode 100644 index 00000000..7258cb8a --- /dev/null +++ b/xgt-tests-build/libraries/vendor/rocksdb/RocksDBConfigVersion.cmake @@ -0,0 +1,51 @@ +# This is a basic version file for the Config-mode of find_package(). +# It is used by write_basic_package_version_file() as input file for configure_file() +# to create a version-file which can be installed along a config.cmake file. +# +# The created file sets PACKAGE_VERSION_EXACT if the current version string and +# the requested version string are exactly the same and it sets +# PACKAGE_VERSION_COMPATIBLE if the current version is >= requested version, +# but only if the requested major version is the same as the current one. +# The variable CVF_VERSION must be set before calling configure_file(). + + +set(PACKAGE_VERSION "6.22.0") + +if(PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION) + set(PACKAGE_VERSION_COMPATIBLE FALSE) +else() + + if("6.22.0" MATCHES "^([0-9]+)\\.") + set(CVF_VERSION_MAJOR "${CMAKE_MATCH_1}") + else() + set(CVF_VERSION_MAJOR "6.22.0") + endif() + + if(PACKAGE_FIND_VERSION_MAJOR STREQUAL CVF_VERSION_MAJOR) + set(PACKAGE_VERSION_COMPATIBLE TRUE) + else() + set(PACKAGE_VERSION_COMPATIBLE FALSE) + endif() + + if(PACKAGE_FIND_VERSION STREQUAL PACKAGE_VERSION) + set(PACKAGE_VERSION_EXACT TRUE) + endif() +endif() + + +# if the installed project requested no architecture check, don't perform the check +if("FALSE") + return() +endif() + +# if the installed or the using project don't have CMAKE_SIZEOF_VOID_P set, ignore it: +if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "" OR "8" STREQUAL "") + return() +endif() + +# check that the installed version has the same 32/64bit-ness as the one which is currently searching: +if(NOT CMAKE_SIZEOF_VOID_P STREQUAL "8") + math(EXPR installedBits "8 * 8") + set(PACKAGE_VERSION "${PACKAGE_VERSION} (${installedBits}bit)") + set(PACKAGE_VERSION_UNSUITABLE TRUE) +endif() From 632edbf43dce6e1881c244bf31ebe81d2dd6782d Mon Sep 17 00:00:00 2001 From: Liam Noroian Date: Tue, 20 Jul 2021 10:27:33 -0700 Subject: [PATCH 07/96] Revert "Busting through errors to build machine_api" This reverts commit 71f1d7d8bbd078e7c7d75cb6c2a95090974b2ee5. --- .../plugins/apis/machine_api/machine_api.cpp | 5 +- xgt-tests-build/libraries/fc/git_revision.cpp | 11 --- .../tmp/project_secp256k1-cfgcmd.txt | 1 - .../tmp/project_secp256k1-cfgcmd.txt.in | 1 - .../manifest/gensrc/plugins/CMakeLists.txt | 53 ----------- .../plugins/include/xgt/manifest/plugins.hpp | 12 --- .../manifest/gensrc/plugins/mf_plugins.cpp | 79 ----------------- .../manifest/gensrc/plugins/plugins.cpp | 1 - .../manifest/template_context/plugins.json | 1 - .../libraries/utilities/git_revision.cpp | 14 --- .../vendor/rocksdb/RocksDBConfig.cmake | 88 ------------------- .../vendor/rocksdb/RocksDBConfigVersion.cmake | 51 ----------- 12 files changed, 1 insertion(+), 316 deletions(-) delete mode 100644 xgt-tests-build/libraries/fc/git_revision.cpp delete mode 100644 xgt-tests-build/libraries/fc/vendor/secp256k1-zkp/tmp/project_secp256k1-cfgcmd.txt delete mode 100644 xgt-tests-build/libraries/fc/vendor/secp256k1-zkp/tmp/project_secp256k1-cfgcmd.txt.in delete mode 100644 xgt-tests-build/libraries/manifest/gensrc/plugins/CMakeLists.txt delete mode 100644 xgt-tests-build/libraries/manifest/gensrc/plugins/include/xgt/manifest/plugins.hpp delete mode 100644 xgt-tests-build/libraries/manifest/gensrc/plugins/mf_plugins.cpp delete mode 100644 xgt-tests-build/libraries/manifest/gensrc/plugins/plugins.cpp delete mode 100644 xgt-tests-build/libraries/manifest/template_context/plugins.json delete mode 100644 xgt-tests-build/libraries/utilities/git_revision.cpp delete mode 100644 xgt-tests-build/libraries/vendor/rocksdb/RocksDBConfig.cmake delete mode 100644 xgt-tests-build/libraries/vendor/rocksdb/RocksDBConfigVersion.cmake diff --git a/libraries/plugins/apis/machine_api/machine_api.cpp b/libraries/plugins/apis/machine_api/machine_api.cpp index a51ea87e..b2ccaaea 100644 --- a/libraries/plugins/apis/machine_api/machine_api.cpp +++ b/libraries/plugins/apis/machine_api/machine_api.cpp @@ -41,10 +41,7 @@ adjure_return machine_api_impl::adjure( const adjure_args& args )const // } // std::cout << std::endl; - ctx = {} - msg = {} - - machine m(ctx, args.bytecode, msg); + machine m(args.bytecode); // m.register_listener(std::move(std::unique_ptr(new stub_listener()))); m.register_instruction(noop_opcode, std::move(std::unique_ptr(new noop_instruction()))); m.register_instruction(push_opcode, std::move(std::unique_ptr(new push_instruction()))); diff --git a/xgt-tests-build/libraries/fc/git_revision.cpp b/xgt-tests-build/libraries/fc/git_revision.cpp deleted file mode 100644 index 06068832..00000000 --- a/xgt-tests-build/libraries/fc/git_revision.cpp +++ /dev/null @@ -1,11 +0,0 @@ -#include - -#define FC_GIT_REVISION_SHA "30ccdd98a05bbc4c7393868627dc569eb532ac66" -#define FC_GIT_REVISION_UNIX_TIMESTAMP 1625816327 - -namespace fc { - -const char* const git_revision_sha = FC_GIT_REVISION_SHA; -const uint32_t git_revision_unix_timestamp = FC_GIT_REVISION_UNIX_TIMESTAMP; - -} // end namespace fc diff --git a/xgt-tests-build/libraries/fc/vendor/secp256k1-zkp/tmp/project_secp256k1-cfgcmd.txt b/xgt-tests-build/libraries/fc/vendor/secp256k1-zkp/tmp/project_secp256k1-cfgcmd.txt deleted file mode 100644 index 472131d5..00000000 --- a/xgt-tests-build/libraries/fc/vendor/secp256k1-zkp/tmp/project_secp256k1-cfgcmd.txt +++ /dev/null @@ -1 +0,0 @@ -cmd='/home/lnoroian/xgt/libraries/fc/vendor/secp256k1-zkp/configure;--prefix=/home/lnoroian/xgt/xgt-tests-build/libraries/fc/vendor/secp256k1-zkp;--with-bignum=no' diff --git a/xgt-tests-build/libraries/fc/vendor/secp256k1-zkp/tmp/project_secp256k1-cfgcmd.txt.in b/xgt-tests-build/libraries/fc/vendor/secp256k1-zkp/tmp/project_secp256k1-cfgcmd.txt.in deleted file mode 100644 index b3f09efc..00000000 --- a/xgt-tests-build/libraries/fc/vendor/secp256k1-zkp/tmp/project_secp256k1-cfgcmd.txt.in +++ /dev/null @@ -1 +0,0 @@ -cmd='@cmd@' diff --git a/xgt-tests-build/libraries/manifest/gensrc/plugins/CMakeLists.txt b/xgt-tests-build/libraries/manifest/gensrc/plugins/CMakeLists.txt deleted file mode 100644 index 6c4eb962..00000000 --- a/xgt-tests-build/libraries/manifest/gensrc/plugins/CMakeLists.txt +++ /dev/null @@ -1,53 +0,0 @@ - -add_library( xgt_plugins - mf_plugins.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/include/xgt/manifest/plugins.hpp -) - -target_link_libraries( xgt_plugins appbase fc - - wallet_by_key_plugin - - wallet_history_rocksdb_plugin - - transaction_status_plugin - - chain_plugin - - webserver_plugin - - chain_api_plugin - - transaction_api_plugin - - wallet_by_key_api_plugin - - contract_api_plugin - - wallet_history_api_plugin - - database_api_plugin - - block_api_plugin - - debug_node_plugin - - p2p_plugin - - wallet_history_plugin - - witness_plugin - -) - -target_include_directories( xgt_plugins - PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" - ) - -INSTALL( TARGETS - xgt_plugins - - RUNTIME DESTINATION bin - LIBRARY DESTINATION lib - ARCHIVE DESTINATION lib -) \ No newline at end of file diff --git a/xgt-tests-build/libraries/manifest/gensrc/plugins/include/xgt/manifest/plugins.hpp b/xgt-tests-build/libraries/manifest/gensrc/plugins/include/xgt/manifest/plugins.hpp deleted file mode 100644 index b4164761..00000000 --- a/xgt-tests-build/libraries/manifest/gensrc/plugins/include/xgt/manifest/plugins.hpp +++ /dev/null @@ -1,12 +0,0 @@ - -#pragma once - -#include -#include -#include - -namespace xgt { namespace plugins { - -void register_plugins(); - -} } diff --git a/xgt-tests-build/libraries/manifest/gensrc/plugins/mf_plugins.cpp b/xgt-tests-build/libraries/manifest/gensrc/plugins/mf_plugins.cpp deleted file mode 100644 index 6de9c7ba..00000000 --- a/xgt-tests-build/libraries/manifest/gensrc/plugins/mf_plugins.cpp +++ /dev/null @@ -1,79 +0,0 @@ -#include -#include - -#include - - -#include - -#include - -#include - -#include - -#include - -#include - -#include - -#include - -#include - -#include - -#include - -#include - -#include - -#include - -#include - -#include - - -namespace xgt { namespace plugins { - -void register_plugins() -{ - - appbase::app().register_plugin< xgt::plugins::wallet_by_key::wallet_by_key_plugin >(); - - appbase::app().register_plugin< xgt::plugins::wallet_history_rocksdb::wallet_history_rocksdb_plugin >(); - - appbase::app().register_plugin< xgt::plugins::transaction_status::transaction_status_plugin >(); - - appbase::app().register_plugin< xgt::plugins::chain::chain_plugin >(); - - appbase::app().register_plugin< xgt::plugins::webserver::webserver_plugin >(); - - appbase::app().register_plugin< xgt::plugins::chain::chain_api_plugin >(); - - appbase::app().register_plugin< xgt::plugins::transaction_api::transaction_api_plugin >(); - - appbase::app().register_plugin< xgt::plugins::wallet_by_key::wallet_by_key_api_plugin >(); - - appbase::app().register_plugin< xgt::plugins::contract::contract_api_plugin >(); - - appbase::app().register_plugin< xgt::plugins::wallet_history::wallet_history_api_plugin >(); - - appbase::app().register_plugin< xgt::plugins::database_api::database_api_plugin >(); - - appbase::app().register_plugin< xgt::plugins::block_api::block_api_plugin >(); - - appbase::app().register_plugin< xgt::plugins::debug_node::debug_node_plugin >(); - - appbase::app().register_plugin< xgt::plugins::p2p::p2p_plugin >(); - - appbase::app().register_plugin< xgt::plugins::wallet_history::wallet_history_plugin >(); - - appbase::app().register_plugin< xgt::plugins::witness::witness_plugin >(); - -} - -} } \ No newline at end of file diff --git a/xgt-tests-build/libraries/manifest/gensrc/plugins/plugins.cpp b/xgt-tests-build/libraries/manifest/gensrc/plugins/plugins.cpp deleted file mode 100644 index 34b39c98..00000000 --- a/xgt-tests-build/libraries/manifest/gensrc/plugins/plugins.cpp +++ /dev/null @@ -1 +0,0 @@ -// empty cpp file for plugin project diff --git a/xgt-tests-build/libraries/manifest/template_context/plugins.json b/xgt-tests-build/libraries/manifest/template_context/plugins.json deleted file mode 100644 index 6e42d767..00000000 --- a/xgt-tests-build/libraries/manifest/template_context/plugins.json +++ /dev/null @@ -1 +0,0 @@ -{"plugins": [{"plugin_name": "wallet_by_key", "plugin_namespace": "wallet_by_key", "plugin_project": "wallet_by_key_plugin"}, {"plugin_name": "wallet_history_rocksdb", "plugin_namespace": "wallet_history_rocksdb", "plugin_project": "wallet_history_rocksdb_plugin"}, {"plugin_name": "transaction_status", "plugin_namespace": "transaction_status", "plugin_project": "transaction_status_plugin"}, {"plugin_name": "chain", "plugin_namespace": "chain", "plugin_project": "chain_plugin"}, {"plugin_name": "webserver", "plugin_namespace": "webserver", "plugin_project": "webserver_plugin"}, {"plugin_name": "chain_api", "plugin_namespace": "chain", "plugin_project": "chain_api_plugin"}, {"plugin_name": "transaction_api", "plugin_namespace": "transaction_api", "plugin_project": "transaction_api_plugin"}, {"plugin_name": "wallet_by_key_api", "plugin_namespace": "wallet_by_key", "plugin_project": "wallet_by_key_api_plugin"}, {"plugin_name": "contract_api", "plugin_namespace": "contract", "plugin_project": "contract_api_plugin"}, {"plugin_name": "wallet_history_api", "plugin_namespace": "wallet_history", "plugin_project": "wallet_history_api_plugin"}, {"plugin_name": "database_api", "plugin_namespace": "database_api", "plugin_project": "database_api_plugin"}, {"plugin_name": "block_api", "plugin_namespace": "block_api", "plugin_project": "block_api_plugin"}, {"plugin_name": "debug_node", "plugin_namespace": "debug_node", "plugin_project": "debug_node_plugin"}, {"plugin_name": "p2p", "plugin_namespace": "p2p", "plugin_project": "p2p_plugin"}, {"plugin_name": "wallet_history", "plugin_namespace": "wallet_history", "plugin_project": "wallet_history_plugin"}, {"plugin_name": "witness", "plugin_namespace": "witness", "plugin_project": "witness_plugin"}], "index_extensions": []} diff --git a/xgt-tests-build/libraries/utilities/git_revision.cpp b/xgt-tests-build/libraries/utilities/git_revision.cpp deleted file mode 100644 index 65d5e532..00000000 --- a/xgt-tests-build/libraries/utilities/git_revision.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include -#include - -#define XGT_GIT_REVISION_SHA "30ccdd98a05bbc4c7393868627dc569eb532ac66" -#define XGT_GIT_REVISION_UNIX_TIMESTAMP 1625816327 -#define XGT_GIT_REVISION_DESCRIPTION "1.3.1-16-g30ccdd9" - -namespace xgt { namespace utilities { - -const char* const git_revision_sha = XGT_GIT_REVISION_SHA; -const uint32_t git_revision_unix_timestamp = XGT_GIT_REVISION_UNIX_TIMESTAMP; -const char* const git_revision_description = XGT_GIT_REVISION_DESCRIPTION; - -} } // end namespace xgt::utilities diff --git a/xgt-tests-build/libraries/vendor/rocksdb/RocksDBConfig.cmake b/xgt-tests-build/libraries/vendor/rocksdb/RocksDBConfig.cmake deleted file mode 100644 index 0422f83d..00000000 --- a/xgt-tests-build/libraries/vendor/rocksdb/RocksDBConfig.cmake +++ /dev/null @@ -1,88 +0,0 @@ - -####### Expanded from @PACKAGE_INIT@ by configure_package_config_file() ####### -####### Any changes to this file will be overwritten by the next CMake run #### -####### The input file was RocksDBConfig.cmake.in ######## - -get_filename_component(PACKAGE_PREFIX_DIR "${CMAKE_CURRENT_LIST_DIR}/../../../../" ABSOLUTE) - -# Use original install prefix when loaded through a "/usr move" -# cross-prefix symbolic link such as /lib -> /usr/lib. -get_filename_component(_realCurr "${CMAKE_CURRENT_LIST_DIR}" REALPATH) -get_filename_component(_realOrig "/usr/lib/x86_64-linux-gnu/cmake/rocksdb" REALPATH) -if(_realCurr STREQUAL _realOrig) - set(PACKAGE_PREFIX_DIR "/usr") -endif() -unset(_realOrig) -unset(_realCurr) - -macro(set_and_check _var _file) - set(${_var} "${_file}") - if(NOT EXISTS "${_file}") - message(FATAL_ERROR "File or directory ${_file} referenced by variable ${_var} does not exist !") - endif() -endmacro() - -macro(check_required_components _NAME) - foreach(comp ${${_NAME}_FIND_COMPONENTS}) - if(NOT ${_NAME}_${comp}_FOUND) - if(${_NAME}_FIND_REQUIRED_${comp}) - set(${_NAME}_FOUND FALSE) - endif() - endif() - endforeach() -endmacro() - -#################################################################################### - -list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/modules") - -include(CMakeFindDependencyMacro) - -set(GFLAGS_USE_TARGET_NAMESPACE ) - -if(OFF) - find_dependency(JeMalloc) -endif() - -if(OFF) - find_dependency(gflags CONFIG) - if(NOT gflags_FOUND) - find_dependency(gflags) - endif() -endif() - -if(ON) - find_dependency(Snappy CONFIG) - if(NOT Snappy_FOUND) - find_dependency(Snappy) - endif() -endif() - -if(OFF) - find_dependency(ZLIB) -endif() - -if(OFF) - find_dependency(BZip2) -endif() - -if(OFF) - find_dependency(lz4) -endif() - -if(OFF) - find_dependency(zstd) -endif() - -if(OFF) - find_dependency(NUMA) -endif() - -if(OFF) - find_dependency(TBB) -endif() - -find_dependency(Threads) - -include("${CMAKE_CURRENT_LIST_DIR}/RocksDBTargets.cmake") -check_required_components(RocksDB) diff --git a/xgt-tests-build/libraries/vendor/rocksdb/RocksDBConfigVersion.cmake b/xgt-tests-build/libraries/vendor/rocksdb/RocksDBConfigVersion.cmake deleted file mode 100644 index 7258cb8a..00000000 --- a/xgt-tests-build/libraries/vendor/rocksdb/RocksDBConfigVersion.cmake +++ /dev/null @@ -1,51 +0,0 @@ -# This is a basic version file for the Config-mode of find_package(). -# It is used by write_basic_package_version_file() as input file for configure_file() -# to create a version-file which can be installed along a config.cmake file. -# -# The created file sets PACKAGE_VERSION_EXACT if the current version string and -# the requested version string are exactly the same and it sets -# PACKAGE_VERSION_COMPATIBLE if the current version is >= requested version, -# but only if the requested major version is the same as the current one. -# The variable CVF_VERSION must be set before calling configure_file(). - - -set(PACKAGE_VERSION "6.22.0") - -if(PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION) - set(PACKAGE_VERSION_COMPATIBLE FALSE) -else() - - if("6.22.0" MATCHES "^([0-9]+)\\.") - set(CVF_VERSION_MAJOR "${CMAKE_MATCH_1}") - else() - set(CVF_VERSION_MAJOR "6.22.0") - endif() - - if(PACKAGE_FIND_VERSION_MAJOR STREQUAL CVF_VERSION_MAJOR) - set(PACKAGE_VERSION_COMPATIBLE TRUE) - else() - set(PACKAGE_VERSION_COMPATIBLE FALSE) - endif() - - if(PACKAGE_FIND_VERSION STREQUAL PACKAGE_VERSION) - set(PACKAGE_VERSION_EXACT TRUE) - endif() -endif() - - -# if the installed project requested no architecture check, don't perform the check -if("FALSE") - return() -endif() - -# if the installed or the using project don't have CMAKE_SIZEOF_VOID_P set, ignore it: -if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "" OR "8" STREQUAL "") - return() -endif() - -# check that the installed version has the same 32/64bit-ness as the one which is currently searching: -if(NOT CMAKE_SIZEOF_VOID_P STREQUAL "8") - math(EXPR installedBits "8 * 8") - set(PACKAGE_VERSION "${PACKAGE_VERSION} (${installedBits}bit)") - set(PACKAGE_VERSION_UNSUITABLE TRUE) -endif() From 06ea7db189f72fa66735f43e296d7a34b8ddfb63 Mon Sep 17 00:00:00 2001 From: Roger Jungemann Date: Thu, 22 Jul 2021 10:33:12 -0700 Subject: [PATCH 08/96] Integrate chain adapter --- Rakefile | 2 + .../plugins/apis/contract_api/CMakeLists.txt | 11 ++++- .../apis/contract_api/contract_api.cpp | 6 +++ libraries/vendor/xgtvm/libraries/machine.cpp | 27 ++++++++++- libraries/vendor/xgtvm/libraries/machine.hpp | 14 ++++-- libraries/vendor/xgtvm/programs/xgtvm.cpp | 17 ++++++- .../vendor/xgtvm/programs/xgtvm_tests.cpp | 45 +++++++++++++++++-- 7 files changed, 111 insertions(+), 11 deletions(-) diff --git a/Rakefile b/Rakefile index 4e1d887b..c8abc623 100644 --- a/Rakefile +++ b/Rakefile @@ -416,10 +416,12 @@ namespace :machine do dest_dir = File.join(File.dirname(__FILE__), %(libraries/vendor/xgtvm)) dest_git_dir = File.join(dest_dir, '.git') + desc 'Remove machine-related files' task :clean do FileUtils.rm_r(dest_dir) if Dir.exist?(dest_dir) end + desc 'Vendor machine-related files' task :vendor => [:clean] do raise %(Directory #{src_dir} doesn't exist!) unless Dir.exist?(src_dir) FileUtils.cp_r(src_dir, dest_dir) diff --git a/libraries/plugins/apis/contract_api/CMakeLists.txt b/libraries/plugins/apis/contract_api/CMakeLists.txt index 7dea6497..5eea5ad6 100644 --- a/libraries/plugins/apis/contract_api/CMakeLists.txt +++ b/libraries/plugins/apis/contract_api/CMakeLists.txt @@ -3,8 +3,15 @@ set( SOURCES contract_api.cpp contract_api_plugin.cpp ) add_library( contract_api_plugin ${SOURCES} ${HEADERS} ) -target_link_libraries( contract_api_plugin chain_plugin json_rpc_plugin ) -target_include_directories( contract_api_plugin PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" ) +target_link_libraries( contract_api_plugin + chain_plugin + json_rpc_plugin + xgtvm + ) +target_include_directories( contract_api_plugin + PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" + "${CMAKE_CURRENT_SOURCE_DIR}/../../../vendor/xgtvm/libraries" + ) if( CLANG_TIDY_EXE ) set_target_properties( diff --git a/libraries/plugins/apis/contract_api/contract_api.cpp b/libraries/plugins/apis/contract_api/contract_api.cpp index e2186eb5..96b55d4a 100644 --- a/libraries/plugins/apis/contract_api/contract_api.cpp +++ b/libraries/plugins/apis/contract_api/contract_api.cpp @@ -7,6 +7,8 @@ #include #include +#include + namespace xgt { namespace plugins { namespace contract { namespace detail { @@ -26,6 +28,10 @@ class contract_api_impl DEFINE_API_IMPL( contract_api_impl, get_contract ) { + // TODO: Temporary + machine::message msg = {}; + ilog( "machine::message msg.flags ${f}", ("f",msg.flags) ); + get_contract_return result; result.example = true; return result; diff --git a/libraries/vendor/xgtvm/libraries/machine.cpp b/libraries/vendor/xgtvm/libraries/machine.cpp index ac8a1c9c..2299e47c 100644 --- a/libraries/vendor/xgtvm/libraries/machine.cpp +++ b/libraries/vendor/xgtvm/libraries/machine.cpp @@ -181,6 +181,11 @@ namespace machine } } + void machine::push_string(std::string s) + { + stack.push_front(s); + } + // TODO: Make better // TODO: Return string instead? void machine::print_stack() @@ -221,6 +226,7 @@ namespace machine big_word va, vb, vc, vd, ve, vf, vg, vh, vi, vj, vk, vl, vm, vn, vo, vp, vq; stack_variant sv; signed_big_word sa, sb, sc; + std::string* ss; switch (op) { case stop_opcode: @@ -439,8 +445,22 @@ namespace machine push_word( msg.destination ); break; case balance_opcode: + std::cout << 1 << std::endl; logger << "op balance" << std::endl; - // TODO + { + sv = stack.front(); // wallet_name + stack.pop_front(); + ss = boost::get(&sv); + if (ss) + { + push_word( adapter.get_balance(*ss) ); + } + else + { + state = machine_state::error; + error_message.emplace("Balance operation type error"); + } + } break; case origin_opcode: logger << "op origin" << std::endl; @@ -2458,6 +2478,11 @@ namespace machine return state; } + boost::optional machine::get_error_message() + { + return error_message; + } + std::stringstream& machine::get_logger() { return logger; diff --git a/libraries/vendor/xgtvm/libraries/machine.hpp b/libraries/vendor/xgtvm/libraries/machine.hpp index 45273519..73ded1aa 100644 --- a/libraries/vendor/xgtvm/libraries/machine.hpp +++ b/libraries/vendor/xgtvm/libraries/machine.hpp @@ -16,7 +16,7 @@ namespace machine typedef uint8_t word; typedef boost::multiprecision::uint256_t big_word; typedef boost::multiprecision::int256_t signed_big_word; -typedef boost::variant stack_variant; +typedef boost::variant stack_variant; enum opcode { @@ -236,6 +236,11 @@ struct context } */ +struct chain_adapter +{ + std::function< uint64_t(std::string) > get_balance; +}; + class machine { size_t pc = 0; @@ -248,23 +253,26 @@ class machine std::vector return_value; boost::optional error_message; std::stringstream logger; + chain_adapter adapter; void push_word(stack_variant v); big_word pop_word(); void log(std::string output); public: - machine(context ctx, std::vector code, message msg) - : ctx(ctx), code(code), msg(msg) + machine(context ctx, std::vector code, message msg, chain_adapter adapter) + : ctx(ctx), code(code), msg(msg), adapter(adapter) { } big_word peek_word(); + void push_string(std::string s); void print_stack(); size_t stack_length(); void step(); bool is_running(); machine_state get_state(); + boost::optional get_error_message(); std::stringstream& get_logger(); std::string to_json(); diff --git a/libraries/vendor/xgtvm/programs/xgtvm.cpp b/libraries/vendor/xgtvm/programs/xgtvm.cpp index 06d2cfa3..fbcd026d 100644 --- a/libraries/vendor/xgtvm/programs/xgtvm.cpp +++ b/libraries/vendor/xgtvm/programs/xgtvm.cpp @@ -52,6 +52,20 @@ static struct option long_options[] = { {0, 0, 0, 0} }; +machine::chain_adapter make_chain_adapter() +{ + std::function< uint64_t(std::string) > get_balance = [](std::string wallet_name) -> uint64_t + { + return 0; + }; + + machine::chain_adapter adapter = { + get_balance + }; + + return adapter; +} + int main(int argc, char** argv) { int c; @@ -88,7 +102,8 @@ int main(int argc, char** argv) machine::context ctx = {true, 0x5c477758}; machine::message msg = {}; std::vector code = process_eval(input); - machine::machine m(ctx, code, msg); + machine::chain_adapter adapter = make_chain_adapter(); + machine::machine m(ctx, code, msg, adapter); std::string line; while (m.is_running()) { diff --git a/libraries/vendor/xgtvm/programs/xgtvm_tests.cpp b/libraries/vendor/xgtvm/programs/xgtvm_tests.cpp index 72d802e2..a4dd95ac 100644 --- a/libraries/vendor/xgtvm/programs/xgtvm_tests.cpp +++ b/libraries/vendor/xgtvm/programs/xgtvm_tests.cpp @@ -9,6 +9,20 @@ std::cerr << " " << ( result ? "\e[32m" : "\e[31m" ) << ( message ) << "\e[0m" << std::endl; \ } +machine::chain_adapter make_chain_adapter() +{ + std::function< uint64_t(std::string) > get_balance = [](std::string wallet_name) -> uint64_t + { + return 0; + }; + + machine::chain_adapter adapter = { + get_balance + }; + + return adapter; +} + int main(int argc, char** argv) { test_that("machine runs and halts") @@ -16,7 +30,8 @@ int main(int argc, char** argv) std::vector input = {0x00}; machine::context ctx = {true, 0x00}; machine::message msg = {}; - machine::machine m(ctx, input, msg); + machine::chain_adapter adapter = make_chain_adapter(); + machine::machine m(ctx, input, msg, adapter); assert_message( "machine should start running", m.get_state() == machine::machine_state::running ); while (m.is_running()) m.step(); @@ -29,7 +44,8 @@ int main(int argc, char** argv) std::vector input = {}; machine::context ctx = {true, 0x00}; machine::message msg = {}; - machine::machine m(ctx, input, msg); + machine::chain_adapter adapter = make_chain_adapter(); + machine::machine m(ctx, input, msg, adapter); while (m.is_running()) m.step(); assert_message( "machine should stop when done executing", m.get_state() == machine::machine_state::stopped ); @@ -41,7 +57,8 @@ int main(int argc, char** argv) std::vector input = {0x42, 0x00}; machine::context ctx = {true, 0x5c477758}; machine::message msg = {}; - machine::machine m(ctx, input, msg); + machine::chain_adapter adapter = make_chain_adapter(); + machine::machine m(ctx, input, msg, adapter); while (m.is_running()) m.step(); assert_message( "machine should stop when done executing", m.get_state() == machine::machine_state::stopped ); @@ -54,7 +71,8 @@ int main(int argc, char** argv) std::vector input = {0x60, 0x02, 0x60, 0x03, 0x01, 0x00}; machine::context ctx = {true, 0x00}; machine::message msg = {}; - machine::machine m(ctx, input, msg); + machine::chain_adapter adapter = make_chain_adapter(); + machine::machine m(ctx, input, msg, adapter); while (m.is_running()) m.step(); assert_message( "machine should stop when done executing", m.get_state() == machine::machine_state::stopped ); @@ -62,5 +80,24 @@ int main(int argc, char** argv) assert_message( "top of stack has correct value", m.peek_word() == 5 ); } + test_that("machine can get a wallet's balance via the chain adapter") + { + std::vector input = {0x31, 0x00}; + machine::context ctx = {true, 0x00}; + machine::message msg = {}; + machine::chain_adapter adapter = make_chain_adapter(); + adapter.get_balance = [](std::string wallet_name) -> uint64_t + { + return 2; + }; + machine::machine m(ctx, input, msg, adapter); + m.push_string("alice"); + while (m.is_running()) + m.step(); + assert_message( "machine should stop when done executing", m.get_state() == machine::machine_state::stopped ); + assert_message( "stack has correct length", m.stack_length() == 1 ); + assert_message( "top of stack has correct value", m.peek_word() == 2 ); + } + return 0; } From e8fe352d33fc81ae3553e9634ee20c30cb074f3c Mon Sep 17 00:00:00 2001 From: Liam Noroian Date: Thu, 22 Jul 2021 11:23:13 -0700 Subject: [PATCH 09/96] Setting up contract invocation --- Rakefile | 20 ++++++++ .../apis/contract_api/contract_api.cpp | 47 ++++++++++++++++++- .../xgt/plugins/contract_api/contract_api.hpp | 18 ++++++- .../plugins/apis/machine_api/CMakeLists.txt | 4 +- .../plugins/apis/machine_api/machine_api.cpp | 15 +++--- libraries/plugins/witness/CMakeLists.txt | 1 - 6 files changed, 93 insertions(+), 12 deletions(-) diff --git a/Rakefile b/Rakefile index db41a9a8..854d7616 100644 --- a/Rakefile +++ b/Rakefile @@ -536,6 +536,26 @@ namespace :contracts do $stderr.puts(%(Received response contract... #{response})) end + desc 'Invoke a sample contract' + task :invoke do + txn = { + 'extensions' => [], + 'operations' => [ + { + 'type' => 'contract_invoke_operation', + 'value' => { + 'owner' => wallet, + 'code' => [0x00], + } + } + ] + } + signed = Xgt::Ruby::Auth.sign_transaction(rpc, txn, [wif], chain_id) + $stderr.puts(%(Registering contract... #{signed.to_json})) + response = rpc.call('transaction_api.broadcast_transaction', [signed]) + $stderr.puts(%(Received response contract... #{response})) + end + desc 'View sample contracts' task :list do response = rpc.call('contract_api.list_owner_contracts', { 'owner' => wallet }) || {} diff --git a/libraries/plugins/apis/contract_api/contract_api.cpp b/libraries/plugins/apis/contract_api/contract_api.cpp index 96b55d4a..b4f9f3c5 100644 --- a/libraries/plugins/apis/contract_api/contract_api.cpp +++ b/libraries/plugins/apis/contract_api/contract_api.cpp @@ -21,7 +21,8 @@ class contract_api_impl DECLARE_API_IMPL( (get_contract) - (list_owner_contracts) ) + (list_owner_contracts) + (invoke) ) chain::database& _db; }; @@ -56,6 +57,49 @@ DEFINE_API_IMPL( contract_api_impl, list_owner_contracts ) return result; } +machine::chain_adapter make_chain_adapter() +{ + std::function< uint64_t(std::string) > get_balance = [](std::string wallet_name) -> uint64_t + { + return 0; + }; + + machine::chain_adapter adapter = { + get_balance + }; + + return adapter; +} + +DEFINE_API_IMPL( contract_api_impl, invoke ) +{ + // TODO: Temporary + machine::message msg = {}; + ilog( "machine::message msg.flags ${f}", ("f",msg.flags) ); + + machine::context ctx = {true, 0x5c477758}; + machine::chain_adapter adapter = make_chain_adapter(); + machine::machine m(ctx, args.code, msg, adapter); + m.print_stack(); + + std::string line; + while (m.is_running()) + { + std::cerr << "step\n"; + m.step(); + // Print out any logging that was generated + while ( std::getline(m.get_logger(), line) ) + std::cerr << "\e[36m" << "LOG: " << line << "\e[0m" << std::endl; + } + while ( std::getline(m.get_logger(), line) ) + std::cerr << "\e[36m" << "LOG: " << line << "\e[0m" << std::endl; + std::cout << m.to_json() << std::endl; + + invoke_return result; + + return result; +} + } // detail contract_api::contract_api(): my( new detail::contract_api_impl() ) @@ -68,6 +112,7 @@ contract_api::~contract_api() {} DEFINE_LOCKLESS_APIS( contract_api, (get_contract) (list_owner_contracts) + (invoke) ) } } } //xgt::plugins::contract diff --git a/libraries/plugins/apis/contract_api/include/xgt/plugins/contract_api/contract_api.hpp b/libraries/plugins/apis/contract_api/include/xgt/plugins/contract_api/contract_api.hpp index f626fe21..cf19c170 100644 --- a/libraries/plugins/apis/contract_api/include/xgt/plugins/contract_api/contract_api.hpp +++ b/libraries/plugins/apis/contract_api/include/xgt/plugins/contract_api/contract_api.hpp @@ -36,6 +36,19 @@ struct list_owner_contracts_return }; +struct invoke_args +{ + protocol::wallet_name_type owner; + vector< uint8_t > code; +}; + + +struct invoke_return +{ + protocol::wallet_name_type owner; +}; + + class contract_api { public: @@ -44,7 +57,8 @@ class contract_api DECLARE_API( (get_contract) - (list_owner_contracts) ) + (list_owner_contracts) + (invoke) ) private: std::unique_ptr< detail::contract_api_impl > my; }; @@ -55,3 +69,5 @@ FC_REFLECT( xgt::plugins::contract::get_contract_args, (example) ) FC_REFLECT( xgt::plugins::contract::get_contract_return, (example) ) FC_REFLECT( xgt::plugins::contract::list_owner_contracts_args, (owner) ) FC_REFLECT( xgt::plugins::contract::list_owner_contracts_return, (contracts) ) +FC_REFLECT( xgt::plugins::contract::invoke_args, (owner) (code) ) +FC_REFLECT( xgt::plugins::contract::invoke_return, (owner) ) diff --git a/libraries/plugins/apis/machine_api/CMakeLists.txt b/libraries/plugins/apis/machine_api/CMakeLists.txt index 069b4c52..fcf86508 100644 --- a/libraries/plugins/apis/machine_api/CMakeLists.txt +++ b/libraries/plugins/apis/machine_api/CMakeLists.txt @@ -5,8 +5,8 @@ add_library( machine_api_plugin ${HEADERS} ) -target_link_libraries( machine_api_plugin chain_plugin json_rpc_plugin ) -target_include_directories( machine_api_plugin PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" ) +target_link_libraries( machine_api_plugin chain_plugin json_rpc_plugin xgtvm ) +target_include_directories( machine_api_plugin PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" "${CMAKE_CURRENT_SOURCE_DIR}/../../../vendor/xgtvm/libraries" ) if( CLANG_TIDY_EXE ) set_target_properties( diff --git a/libraries/plugins/apis/machine_api/machine_api.cpp b/libraries/plugins/apis/machine_api/machine_api.cpp index b2ccaaea..0e10ec9d 100644 --- a/libraries/plugins/apis/machine_api/machine_api.cpp +++ b/libraries/plugins/apis/machine_api/machine_api.cpp @@ -9,6 +9,7 @@ // TODO: Remove this later #include "iomanip" +#include namespace xgt { namespace plugins { namespace machine { @@ -41,14 +42,14 @@ adjure_return machine_api_impl::adjure( const adjure_args& args )const // } // std::cout << std::endl; - machine m(args.bytecode); + // machine::machine m(args.bytecode); // m.register_listener(std::move(std::unique_ptr(new stub_listener()))); - m.register_instruction(noop_opcode, std::move(std::unique_ptr(new noop_instruction()))); - m.register_instruction(push_opcode, std::move(std::unique_ptr(new push_instruction()))); - m.register_instruction(add_opcode, std::move(std::unique_ptr(new add_instruction()))); - m.register_instruction(display_opcode, std::move(std::unique_ptr(new display_instruction()))); - while (m.is_running()) - m.step(); + // m.register_instruction(noop_opcode, std::move(std::unique_ptr(new noop_instruction()))); + // m.register_instruction(push_opcode, std::move(std::unique_ptr(new push_instruction()))); + // m.register_instruction(add_opcode, std::move(std::unique_ptr(new add_instruction()))); + // m.register_instruction(display_opcode, std::move(std::unique_ptr(new display_instruction()))); + // while (m.is_running()) + // m.step(); final_result.return_code = 0; return final_result; diff --git a/libraries/plugins/witness/CMakeLists.txt b/libraries/plugins/witness/CMakeLists.txt index feaf8517..29cb8e69 100644 --- a/libraries/plugins/witness/CMakeLists.txt +++ b/libraries/plugins/witness/CMakeLists.txt @@ -13,7 +13,6 @@ target_link_libraries( witness_plugin appbase xgt_chain xgt_utilities - graphene_time xgtvm ) target_include_directories( witness_plugin From 4b126ff0b0611cc880d836ca7f9f4138e52650a1 Mon Sep 17 00:00:00 2001 From: Liam Noroian Date: Thu, 22 Jul 2021 11:27:16 -0700 Subject: [PATCH 10/96] Adding placeholder wallet to rakefile --- Rakefile | 10 +++++----- temp.txt | 10 ++++++++++ 2 files changed, 15 insertions(+), 5 deletions(-) create mode 100644 temp.txt diff --git a/Rakefile b/Rakefile index 854d7616..aea8b8da 100644 --- a/Rakefile +++ b/Rakefile @@ -43,23 +43,23 @@ def mining_error(message) end def wallet - ENV['XGT_WALLET'] || mining_error("Wallet not specificed, please specify a wallet with 'XGT_WALLET'") + 'XGTFnjnrACfmLLi4fZSK5TfRi6NvFCLrukk4ZfZBZXQ' end def wif - ENV['XGT_WIF'] || mining_error("XGT_WIF not specified") + '5KDxgvTZ17SZeiAzUv87vAxMwQ9T9jvakYurSdc1zHGdSdXJZCF' end def recovery_private_key - ENV['XGT_RECOVERY_PRIVATE_KEY'] || mining_error("XGT_RECOVERY_PRIVATE_KEY not specified") + '5KDxgvTZ17SZeiAzUv87vAxMwQ9T9jvakYurSdc1zHGdSdXJZCF' end def witness_private_key - ENV['XGT_WITNESS_PRIVATE_KEY'] || mining_error("XGT_WITNESS_PRIVATE_KEY not specified") + '5KDxgvTZ17SZeiAzUv87vAxMwQ9T9jvakYurSdc1zHGdSdXJZCF' end def host - ENV['XGT_HOST'] || 'http://localhost:8751' + ENV['XGT_HOST'] || 'http://xgt.rag.pub:8751' end def seed_hosts diff --git a/temp.txt b/temp.txt new file mode 100644 index 00000000..3fd6db4e --- /dev/null +++ b/temp.txt @@ -0,0 +1,10 @@ +master 5KKXW4SrwihYQaKnbTEp5uXvKFs26zs4PbqnYJbF8vfDCWpUUBk +recovery_private 5KDxgvTZ17SZeiAzUv87vAxMwQ9T9jvakYurSdc1zHGdSdXJZCF +recovery_public XGT6dfSiYnACaq3xWc1txTvoWN5td8VRWkaphYD9WesxiBEGL9TQz +money_private 5KS5wwV3qiezKB6VnsPpMCVUL9C418zaDSaHjA5dLGxZEjCNmC8 +money_public XGT5c7krPv7qm9AUpm9PpLosjL31Q4DkJNWJf6veZaCjGX2LsR3x3 +social_private 5JkfetxX2hJUnUdqknuEcnrha46bzVcHcC3CBkuKTHkyEw3bHm2 +social_public XGT6CNSdP78Yev11WozNSbi9x5rvw5sHzftpx1n8CsJRNnsRWz51Y +memo_private 5KKMpo3y3aiuvygo7AtoDp14Hh5Kg2HMXNATTDUAdFqAwauc3jo +memo_public XGT7ZWLwEdFFXyeDYrbS6j5hei7m6Ri6jWhzr9CKWeBr1ZqE9KGJg +wallet_name XGTFnjnrACfmLLi4fZSK5TfRi6NvFCLrukk4ZfZBZXQ From 490c5de38c75b7427303503e1f82fa77f5796269 Mon Sep 17 00:00:00 2001 From: Roger Jungemann Date: Fri, 30 Jul 2021 20:26:48 -0700 Subject: [PATCH 11/96] Do not immediately reject peers with bad blocks --- libraries/net/node.cpp | 35 ++++++----------------------------- 1 file changed, 6 insertions(+), 29 deletions(-) diff --git a/libraries/net/node.cpp b/libraries/net/node.cpp index 0a27b22d..72a37767 100644 --- a/libraries/net/node.cpp +++ b/libraries/net/node.cpp @@ -3100,7 +3100,6 @@ namespace graphene { namespace net { dlog("in send_sync_block_to_node_delegate()"); bool client_accepted_block = false; - bool discontinue_fetching_blocks_from_peer = false; fc::oexception handle_message_exception; @@ -3139,7 +3138,6 @@ namespace graphene { namespace net { ("id", block_message_to_send.block_id) ("e", (fc::exception)e)); handle_message_exception = e; - discontinue_fetching_blocks_from_peer = true; } catch (const fc::canceled_exception&) { @@ -3242,35 +3240,14 @@ namespace graphene { namespace net { } else { - // invalid message received - for (const peer_connection_ptr& peer : _active_connections) - { - ASSERT_TASK_NOT_PREEMPTED(); // don't yield while iterating over _active_connections - - if (peer->ids_of_items_being_processed.find(block_message_to_send.block_id) != peer->ids_of_items_being_processed.end()) - { - if (discontinue_fetching_blocks_from_peer) - { - wlog("inhibiting fetching sync blocks from peer ${endpoint} because it is on a fork that's too old", - ("endpoint", peer->get_remote_endpoint())); - peer->inhibit_fetching_sync_blocks = true; - } - else - peers_to_disconnect[peer] = std::make_pair(std::string("You offered us a block that we reject as invalid"), fc::oexception(handle_message_exception)); - } - } + // Invalid message received + for (const peer_connection_ptr& peer : _active_connections) + { + wlog("Invalid message received from peer ${endpoint}, ignoring", + ("endpoint", peer->get_remote_endpoint())); + } } - for (auto& peer_to_disconnect : peers_to_disconnect) - { - const peer_connection_ptr& peer = peer_to_disconnect.first; - std::string reason_string; - fc::oexception reason_exception; - std::tie(reason_string, reason_exception) = peer_to_disconnect.second; - wlog("disconnecting client ${endpoint} because it offered us the rejected block", - ("endpoint", peer->get_remote_endpoint())); - disconnect_from_peer(peer.get(), reason_string, true, reason_exception); - } for (const peer_connection_ptr& peer : peers_with_newly_empty_item_lists) fetch_next_batch_of_item_ids_from_peer(peer.get()); From 144f3d759914cc172d1d798a72e9a4e01d7226b6 Mon Sep 17 00:00:00 2001 From: James Tucker Date: Thu, 5 Aug 2021 18:44:28 -0700 Subject: [PATCH 12/96] api: include human readable version string --- libraries/plugins/apis/database_api/database_api.cpp | 2 +- .../xgt/plugins/database_api/database_api_args.hpp | 8 ++++---- programs/xgtd/main.cpp | 5 ++--- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/libraries/plugins/apis/database_api/database_api.cpp b/libraries/plugins/apis/database_api/database_api.cpp index c024d24d..32af673c 100644 --- a/libraries/plugins/apis/database_api/database_api.cpp +++ b/libraries/plugins/apis/database_api/database_api.cpp @@ -139,9 +139,9 @@ DEFINE_API_IMPL( database_api_impl, get_version ) { return get_version_return ( + fc::string( xgt::utilities::git_revision_description ), fc::string( XGT_BLOCKCHAIN_VERSION ), fc::string( xgt::utilities::git_revision_sha ), - fc::string( fc::git_revision_sha ), _db.get_chain_id() ); } diff --git a/libraries/plugins/apis/database_api/include/xgt/plugins/database_api/database_api_args.hpp b/libraries/plugins/apis/database_api/include/xgt/plugins/database_api/database_api_args.hpp index 82134223..36c68542 100644 --- a/libraries/plugins/apis/database_api/include/xgt/plugins/database_api/database_api_args.hpp +++ b/libraries/plugins/apis/database_api/include/xgt/plugins/database_api/database_api_args.hpp @@ -86,12 +86,12 @@ typedef void_type get_version_args; struct get_version_return { get_version_return() {} - get_version_return( fc::string bc_v, fc::string s_v, fc::string fc_v, chain_id_type c_id ) - :blockchain_version( bc_v ), xgt_revision( s_v ), fc_revision( fc_v ), chain_id( c_id ) {} + get_version_return( fc::string xgt_v, fc::string bc_v, fc::string s_v, chain_id_type c_id ) + :xgt_version(xgt_v), blockchain_version( bc_v ), xgt_revision( s_v ), chain_id( c_id ) {} + fc::string xgt_version; fc::string blockchain_version; fc::string xgt_revision; - fc::string fc_revision; chain_id_type chain_id; }; @@ -351,7 +351,7 @@ typedef find_xtt_token_balances_return list_xtt_token_balances_return; } } } // xgt::database_api FC_REFLECT( xgt::plugins::database_api::get_version_return, - (blockchain_version)(xgt_revision)(fc_revision)(chain_id) ) + (xgt_version)(blockchain_version)(xgt_revision)(chain_id) ) FC_REFLECT_ENUM( xgt::plugins::database_api::sort_order_type, (by_name) diff --git a/programs/xgtd/main.cpp b/programs/xgtd/main.cpp index 05b075cb..f629d0ff 100644 --- a/programs/xgtd/main.cpp +++ b/programs/xgtd/main.cpp @@ -27,7 +27,6 @@ #include #include #include -#include #include #include @@ -45,9 +44,9 @@ using std::vector; string& version_string() { static string v_str = + "xgt_version: " + fc::string( xgt::utilities::git_revision_description ) + "\n" + "xgt_blockchain_version: " + fc::string( XGT_BLOCKCHAIN_VERSION ) + "\n" + - "xgt_git_revision: " + fc::string( xgt::utilities::git_revision_sha ) + "\n" + - "fc_git_revision: " + fc::string( fc::git_revision_sha ) + "\n"; + "xgt_git_revision: " + fc::string( xgt::utilities::git_revision_sha ) + "\n"; return v_str; } From 6dbfd9467f8bb750a69d143ac0cec769b2d5647b Mon Sep 17 00:00:00 2001 From: Roger Jungemann Date: Thu, 12 Aug 2021 13:39:02 -0700 Subject: [PATCH 13/96] Fix merge --- .../apis/contract_api/contract_api.cpp | 19 ++++-- .../xgt/plugins/contract_api/contract_api.hpp | 17 ++++- .../plugins/apis/machine_api/CMakeLists.txt | 24 ------- .../xgt/plugins/machine_api/machine_api.hpp | 45 ------------ .../machine_api/machine_api_plugin.hpp | 37 ---------- .../plugins/apis/machine_api/machine_api.cpp | 68 ------------------- .../apis/machine_api/machine_api_plugin.cpp | 20 ------ .../plugins/apis/machine_api/plugin.json | 5 -- 8 files changed, 30 insertions(+), 205 deletions(-) delete mode 100644 libraries/plugins/apis/machine_api/CMakeLists.txt delete mode 100644 libraries/plugins/apis/machine_api/include/xgt/plugins/machine_api/machine_api.hpp delete mode 100644 libraries/plugins/apis/machine_api/include/xgt/plugins/machine_api/machine_api_plugin.hpp delete mode 100644 libraries/plugins/apis/machine_api/machine_api.cpp delete mode 100644 libraries/plugins/apis/machine_api/machine_api_plugin.cpp delete mode 100644 libraries/plugins/apis/machine_api/plugin.json diff --git a/libraries/plugins/apis/contract_api/contract_api.cpp b/libraries/plugins/apis/contract_api/contract_api.cpp index 96b55d4a..3ddc6ad0 100644 --- a/libraries/plugins/apis/contract_api/contract_api.cpp +++ b/libraries/plugins/apis/contract_api/contract_api.cpp @@ -21,17 +21,14 @@ class contract_api_impl DECLARE_API_IMPL( (get_contract) - (list_owner_contracts) ) + (list_owner_contracts) + (debug_invoke) ) chain::database& _db; }; DEFINE_API_IMPL( contract_api_impl, get_contract ) { - // TODO: Temporary - machine::message msg = {}; - ilog( "machine::message msg.flags ${f}", ("f",msg.flags) ); - get_contract_return result; result.example = true; return result; @@ -56,6 +53,17 @@ DEFINE_API_IMPL( contract_api_impl, list_owner_contracts ) return result; } +DEFINE_API_IMPL( contract_api_impl, debug_invoke ) +{ + debug_invoke_return result{false}; + + // TODO: Add machine here + machine::message msg = {}; + ilog( "machine::message msg.flags ${f}", ("f",msg.flags) ); + + return result; +} + } // detail contract_api::contract_api(): my( new detail::contract_api_impl() ) @@ -68,6 +76,7 @@ contract_api::~contract_api() {} DEFINE_LOCKLESS_APIS( contract_api, (get_contract) (list_owner_contracts) + (debug_invoke) ) } } } //xgt::plugins::contract diff --git a/libraries/plugins/apis/contract_api/include/xgt/plugins/contract_api/contract_api.hpp b/libraries/plugins/apis/contract_api/include/xgt/plugins/contract_api/contract_api.hpp index f626fe21..cf2627e8 100644 --- a/libraries/plugins/apis/contract_api/include/xgt/plugins/contract_api/contract_api.hpp +++ b/libraries/plugins/apis/contract_api/include/xgt/plugins/contract_api/contract_api.hpp @@ -36,6 +36,18 @@ struct list_owner_contracts_return }; +struct debug_invoke_args +{ + bool example; // TODO: Change me +}; + + +struct debug_invoke_return +{ + bool example; // TODO: Change me +}; + + class contract_api { public: @@ -44,7 +56,8 @@ class contract_api DECLARE_API( (get_contract) - (list_owner_contracts) ) + (list_owner_contracts) + (debug_invoke) ) private: std::unique_ptr< detail::contract_api_impl > my; }; @@ -55,3 +68,5 @@ FC_REFLECT( xgt::plugins::contract::get_contract_args, (example) ) FC_REFLECT( xgt::plugins::contract::get_contract_return, (example) ) FC_REFLECT( xgt::plugins::contract::list_owner_contracts_args, (owner) ) FC_REFLECT( xgt::plugins::contract::list_owner_contracts_return, (contracts) ) +FC_REFLECT( xgt::plugins::contract::debug_invoke_args, (example) ) +FC_REFLECT( xgt::plugins::contract::debug_invoke_return, (example) ) diff --git a/libraries/plugins/apis/machine_api/CMakeLists.txt b/libraries/plugins/apis/machine_api/CMakeLists.txt deleted file mode 100644 index 069b4c52..00000000 --- a/libraries/plugins/apis/machine_api/CMakeLists.txt +++ /dev/null @@ -1,24 +0,0 @@ -file(GLOB HEADERS "include/xgt/plugins/machine_api/*.hpp") -add_library( machine_api_plugin - machine_api_plugin.cpp - machine_api.cpp - ${HEADERS} - ) - -target_link_libraries( machine_api_plugin chain_plugin json_rpc_plugin ) -target_include_directories( machine_api_plugin PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" ) - -if( CLANG_TIDY_EXE ) - set_target_properties( - machine_api_plugin PROPERTIES - CXX_CLANG_TIDY "${DO_CLANG_TIDY}" - ) -endif( CLANG_TIDY_EXE ) - -install( TARGETS - machine_api_plugin - - RUNTIME DESTINATION bin - LIBRARY DESTINATION lib - ARCHIVE DESTINATION lib -) diff --git a/libraries/plugins/apis/machine_api/include/xgt/plugins/machine_api/machine_api.hpp b/libraries/plugins/apis/machine_api/include/xgt/plugins/machine_api/machine_api.hpp deleted file mode 100644 index 2f32a686..00000000 --- a/libraries/plugins/apis/machine_api/include/xgt/plugins/machine_api/machine_api.hpp +++ /dev/null @@ -1,45 +0,0 @@ -#pragma once -#include - -#include - -#include -#include -#include - -namespace xgt { namespace plugins { namespace machine { - -namespace detail -{ - class machine_api_impl; -} - -struct adjure_args -{ - std::vector bytecode; -}; - -struct adjure_return -{ - int return_code; -}; - -class machine_api -{ - public: - machine_api(); - ~machine_api(); - - DECLARE_API( (adjure) ) - - private: - std::unique_ptr< detail::machine_api_impl > my; -}; - -} } } // xgt::plugins::machine - -FC_REFLECT( xgt::plugins::machine::adjure_args, - (bytecode) ) - -FC_REFLECT( xgt::plugins::machine::adjure_return, - (return_code) ) diff --git a/libraries/plugins/apis/machine_api/include/xgt/plugins/machine_api/machine_api_plugin.hpp b/libraries/plugins/apis/machine_api/include/xgt/plugins/machine_api/machine_api_plugin.hpp deleted file mode 100644 index 157f0568..00000000 --- a/libraries/plugins/apis/machine_api/include/xgt/plugins/machine_api/machine_api_plugin.hpp +++ /dev/null @@ -1,37 +0,0 @@ -#pragma once -#include -// #include -#include - -#include - -#define XGT_MACHINE_API_PLUGIN_NAME "machine_api" - - -namespace xgt { namespace plugins { namespace machine { - -using namespace appbase; - -class machine_api_plugin : public appbase::plugin< machine_api_plugin > -{ -public: - APPBASE_PLUGIN_REQUIRES( - // (xgt::plugins::machine::machine_plugin) - (xgt::plugins::json_rpc::json_rpc_plugin) - ) - - machine_api_plugin(); - virtual ~machine_api_plugin(); - - static const std::string& name() { static std::string name = XGT_MACHINE_API_PLUGIN_NAME; return name; } - - virtual void set_program_options( options_description& cli, options_description& cfg ) override; - - virtual void plugin_initialize( const variables_map& options ) override; - virtual void plugin_startup() override; - virtual void plugin_shutdown() override; - - std::shared_ptr< class machine_api > api; -}; - -} } } // xgt::plugins::machine diff --git a/libraries/plugins/apis/machine_api/machine_api.cpp b/libraries/plugins/apis/machine_api/machine_api.cpp deleted file mode 100644 index b2ccaaea..00000000 --- a/libraries/plugins/apis/machine_api/machine_api.cpp +++ /dev/null @@ -1,68 +0,0 @@ -#include - -#include -#include - -#include -#include -// #include - -// TODO: Remove this later -#include "iomanip" - -namespace xgt { namespace plugins { namespace machine { - -namespace detail { - -class machine_api_impl -{ - public: - machine_api_impl() : _db( appbase::app().get_plugin< xgt::plugins::chain::chain_plugin >().db() ) {} - - adjure_return adjure( const adjure_args& args )const; - - chain::database& _db; -}; - -adjure_return machine_api_impl::adjure( const adjure_args& args )const -{ - adjure_return final_result; - - // std::cout << "====="; - // std::cout << std::endl; - // std::cout << "args.bytecode.size(): "; - // std::cout << args.bytecode.size(); - // std::cout << std::endl; - // std::stringstream stream; - // for (size_t i = 0; i < args.bytecode.size(); ++i) - // { - // uint8_t byte = args.bytecode[i]; - // std::cout << unsigned(byte) << std::endl; - // } - // std::cout << std::endl; - - machine m(args.bytecode); - // m.register_listener(std::move(std::unique_ptr(new stub_listener()))); - m.register_instruction(noop_opcode, std::move(std::unique_ptr(new noop_instruction()))); - m.register_instruction(push_opcode, std::move(std::unique_ptr(new push_instruction()))); - m.register_instruction(add_opcode, std::move(std::unique_ptr(new add_instruction()))); - m.register_instruction(display_opcode, std::move(std::unique_ptr(new display_instruction()))); - while (m.is_running()) - m.step(); - - final_result.return_code = 0; - return final_result; -} - -} // detail - -machine_api::machine_api(): my( new detail::machine_api_impl() ) -{ - JSON_RPC_REGISTER_API( XGT_MACHINE_API_PLUGIN_NAME ); -} - -machine_api::~machine_api() {} - -DEFINE_READ_APIS( machine_api, (adjure) ) - -} } } // xgt::plugins::machine diff --git a/libraries/plugins/apis/machine_api/machine_api_plugin.cpp b/libraries/plugins/apis/machine_api/machine_api_plugin.cpp deleted file mode 100644 index f39fae6d..00000000 --- a/libraries/plugins/apis/machine_api/machine_api_plugin.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include -#include - - -namespace xgt { namespace plugins { namespace machine { - -machine_api_plugin::machine_api_plugin() {} -machine_api_plugin::~machine_api_plugin() {} - -void machine_api_plugin::set_program_options( options_description& cli, options_description& cfg ) {} - -void machine_api_plugin::plugin_initialize( const variables_map& options ) -{ - api = std::make_shared< machine_api >(); -} - -void machine_api_plugin::plugin_startup() {} -void machine_api_plugin::plugin_shutdown() {} - -} } } // xgt::plugins::machine diff --git a/libraries/plugins/apis/machine_api/plugin.json b/libraries/plugins/apis/machine_api/plugin.json deleted file mode 100644 index 916bbf48..00000000 --- a/libraries/plugins/apis/machine_api/plugin.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "plugin_name": "machine_api", - "plugin_namespace": "machine", - "plugin_project": "machine_api_plugin" -} From f7739b6f7802a478097df26aedf25a0c68f01390 Mon Sep 17 00:00:00 2001 From: Liam Noroian Date: Fri, 13 Aug 2021 14:47:19 -0700 Subject: [PATCH 14/96] Pulling recent changes --- libraries/plugins/witness/CMakeLists.txt | 35 ------------------------ 1 file changed, 35 deletions(-) delete mode 100644 libraries/plugins/witness/CMakeLists.txt diff --git a/libraries/plugins/witness/CMakeLists.txt b/libraries/plugins/witness/CMakeLists.txt deleted file mode 100644 index a2bcb00d..00000000 --- a/libraries/plugins/witness/CMakeLists.txt +++ /dev/null @@ -1,35 +0,0 @@ -file(GLOB HEADERS "include/xgt/plugins/witness/*.hpp") - - -add_library( witness_plugin - witness_plugin.cpp - block_producer.cpp - ${HEADERS} - ) - -target_link_libraries( witness_plugin - p2p_plugin - chain_plugin - appbase - xgt_chain - xgt_utilities - ) -target_include_directories( witness_plugin - PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" - "${CMAKE_CURRENT_SOURCE_DIR}/../../vendor/xgtvm/libraries" - ) - -if( CLANG_TIDY_EXE ) - set_target_properties( - witness_plugin PROPERTIES - CXX_CLANG_TIDY "${DO_CLANG_TIDY}" - ) -endif( CLANG_TIDY_EXE ) - -install( TARGETS - witness_plugin - - RUNTIME DESTINATION bin - LIBRARY DESTINATION lib - ARCHIVE DESTINATION lib -) From ce9270c7b80423d53dbbc1b2b24887d10d2846f1 Mon Sep 17 00:00:00 2001 From: Liam Noroian Date: Fri, 13 Aug 2021 14:51:32 -0700 Subject: [PATCH 15/96] Removing random piece of code --- libraries/plugins/apis/contract_api/contract_api.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/plugins/apis/contract_api/contract_api.cpp b/libraries/plugins/apis/contract_api/contract_api.cpp index 2331a906..f4867009 100644 --- a/libraries/plugins/apis/contract_api/contract_api.cpp +++ b/libraries/plugins/apis/contract_api/contract_api.cpp @@ -165,7 +165,6 @@ DEFINE_API_IMPL( contract_api_impl, invoke ) std::string tx_origin = "XGT0000000000000000000000000000000000000000"; std::string block_coinbase = "XGT0000000000000000000000000000000000000000"; - 0x00 // machine::context ctx = {true, 0x5c477758}; machine::context ctx = { is_debug, From 653dea39341ce7028ec20cfa94fe0254ea2d9516 Mon Sep 17 00:00:00 2001 From: Roger Jungemann Date: Mon, 16 Aug 2021 10:13:51 -0700 Subject: [PATCH 16/96] Remove diff artifacts --- .../include/xgt/plugins/contract_api/contract_api.hpp | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/libraries/plugins/apis/contract_api/include/xgt/plugins/contract_api/contract_api.hpp b/libraries/plugins/apis/contract_api/include/xgt/plugins/contract_api/contract_api.hpp index 35ac6d52..787b3f0a 100644 --- a/libraries/plugins/apis/contract_api/include/xgt/plugins/contract_api/contract_api.hpp +++ b/libraries/plugins/apis/contract_api/include/xgt/plugins/contract_api/contract_api.hpp @@ -36,7 +36,6 @@ struct list_owner_contracts_return }; -<<<<<<< HEAD struct invoke_args { protocol::wallet_name_type owner; @@ -58,11 +57,7 @@ class contract_api DECLARE_API( (get_contract) (list_owner_contracts) -<<<<<<< HEAD (invoke) ) -======= - (debug_invoke) ) ->>>>>>> 6dbfd9467f8bb750a69d143ac0cec769b2d5647b private: std::unique_ptr< detail::contract_api_impl > my; }; @@ -73,10 +68,5 @@ FC_REFLECT( xgt::plugins::contract::get_contract_args, (example) ) FC_REFLECT( xgt::plugins::contract::get_contract_return, (example) ) FC_REFLECT( xgt::plugins::contract::list_owner_contracts_args, (owner) ) FC_REFLECT( xgt::plugins::contract::list_owner_contracts_return, (contracts) ) -<<<<<<< HEAD FC_REFLECT( xgt::plugins::contract::invoke_args, (owner) (code) ) FC_REFLECT( xgt::plugins::contract::invoke_return, (owner) ) -======= -FC_REFLECT( xgt::plugins::contract::debug_invoke_args, (example) ) -FC_REFLECT( xgt::plugins::contract::debug_invoke_return, (example) ) ->>>>>>> 6dbfd9467f8bb750a69d143ac0cec769b2d5647b From 5179f9d42d23a5e6a5b4d394b26c0d81b77e032f Mon Sep 17 00:00:00 2001 From: Roger Jungemann Date: Mon, 16 Aug 2021 10:45:00 -0700 Subject: [PATCH 17/96] Get building --- Rakefile | 10 +- .../apis/contract_api/contract_api.cpp | 17 +- libraries/plugins/witness/CMakeLists.txt | 32 ++ .../xgt/plugins/witness/witness_plugin.hpp | 1 - libraries/vendor/xgtvm/libraries/machine.cpp | 377 +++++++++++++++--- libraries/vendor/xgtvm/libraries/machine.hpp | 154 ++++--- libraries/vendor/xgtvm/programs/xgtvm.cpp | 83 +++- .../vendor/xgtvm/programs/xgtvm_tests.cpp | 82 +++- 8 files changed, 609 insertions(+), 147 deletions(-) create mode 100644 libraries/plugins/witness/CMakeLists.txt diff --git a/Rakefile b/Rakefile index e228c791..308a2e8d 100644 --- a/Rakefile +++ b/Rakefile @@ -47,23 +47,23 @@ def mining_error(message) end def wallet - 'XGTFnjnrACfmLLi4fZSK5TfRi6NvFCLrukk4ZfZBZXQ' + ENV['XGT_WALLET'] || mining_error("Wallet not specificed, please specify a wallet with 'XGT_WALLET'") end def wif - '5KDxgvTZ17SZeiAzUv87vAxMwQ9T9jvakYurSdc1zHGdSdXJZCF' + ENV['XGT_WIF'] || mining_error("XGT_WIF not specified") end def recovery_private_key - '5KDxgvTZ17SZeiAzUv87vAxMwQ9T9jvakYurSdc1zHGdSdXJZCF' + ENV['XGT_RECOVERY_PRIVATE_KEY'] || mining_error("XGT_RECOVERY_PRIVATE_KEY not specified") end def witness_private_key - '5KDxgvTZ17SZeiAzUv87vAxMwQ9T9jvakYurSdc1zHGdSdXJZCF' + ENV['XGT_WITNESS_PRIVATE_KEY'] || mining_error("XGT_WITNESS_PRIVATE_KEY not specified") end def host - ENV['XGT_HOST'] || 'http://xgt.rag.pub:8751' + ENV['XGT_HOST'] || 'http://localhost:8751' end def seed_hosts diff --git a/libraries/plugins/apis/contract_api/contract_api.cpp b/libraries/plugins/apis/contract_api/contract_api.cpp index f4867009..af81a1e6 100644 --- a/libraries/plugins/apis/contract_api/contract_api.cpp +++ b/libraries/plugins/apis/contract_api/contract_api.cpp @@ -57,17 +57,17 @@ DEFINE_API_IMPL( contract_api_impl, list_owner_contracts ) return result; } -machine::chain_adapter make_chain_adapter() +machine::chain_adapter make_chain_adapter(chain::database& _db) { std::function< std::string(std::vector) > sha3 = [](std::vector memory) -> std::string { return 0; }; - std::function< uint64_t(std::string) > get_balance = [](std::string address) -> uint64_t + std::function< uint64_t(std::string) > get_balance = [&_db](std::string address) -> uint64_t { const auto& wallet = _db.get_account(address); - return static_cast(wallet.balance.amount); + return static_cast(wallet.balance.amount.value); }; std::function< std::string(std::string) > get_code_hash = [](std::string address) -> std::string @@ -156,10 +156,10 @@ DEFINE_API_IMPL( contract_api_impl, invoke ) machine::message msg = {}; ilog( "machine::message msg.flags ${f}", ("f",msg.flags) ); - const is_debug = true; - const uint64_t block_timestamp = _db.head_block_time(); + const bool is_debug = true; + const uint64_t block_timestamp = static_cast( _db.head_block_time().sec_since_epoch() ); const uint64_t block_number = _db.head_block_num(); - const uint64_t block_difficulty = static_cast( database::get_pow_summary_target() ); + const uint64_t block_difficulty = static_cast( _db.get_pow_summary_target() ); const uint64_t block_energylimit = 0; const uint64_t tx_energyprice = 0; std::string tx_origin = "XGT0000000000000000000000000000000000000000"; @@ -179,13 +179,12 @@ DEFINE_API_IMPL( contract_api_impl, invoke ) std::vector code = {0x31, 0x00}; - machine::chain_adapter adapter = make_chain_adapter(); + machine::chain_adapter adapter = make_chain_adapter(_db); // machine::machine m(ctx, args.code, msg, adapter); machine::machine m(ctx, code, msg, adapter); std::string init_miner = "XGT0000000000000000000000000000000000000000"; - machine::stack_variant variant(init_miner); - m.push_word(variant); + m.push_string(init_miner); m.print_stack(); diff --git a/libraries/plugins/witness/CMakeLists.txt b/libraries/plugins/witness/CMakeLists.txt new file mode 100644 index 00000000..6c88872b --- /dev/null +++ b/libraries/plugins/witness/CMakeLists.txt @@ -0,0 +1,32 @@ +file(GLOB HEADERS "include/xgt/plugins/witness/*.hpp") + +add_library( witness_plugin + witness_plugin.cpp + block_producer.cpp + ${HEADERS} + ) + +target_link_libraries( witness_plugin + p2p_plugin + chain_plugin + appbase + xgt_chain + xgt_utilities + ) +target_include_directories( witness_plugin + PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" ) + +if( CLANG_TIDY_EXE ) + set_target_properties( + witness_plugin PROPERTIES + CXX_CLANG_TIDY "${DO_CLANG_TIDY}" + ) +endif( CLANG_TIDY_EXE ) + +install( TARGETS + witness_plugin + + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib +) diff --git a/libraries/plugins/witness/include/xgt/plugins/witness/witness_plugin.hpp b/libraries/plugins/witness/include/xgt/plugins/witness/witness_plugin.hpp index 12823fdc..ef99a161 100644 --- a/libraries/plugins/witness/include/xgt/plugins/witness/witness_plugin.hpp +++ b/libraries/plugins/witness/include/xgt/plugins/witness/witness_plugin.hpp @@ -5,7 +5,6 @@ #include #include #include -#include #include diff --git a/libraries/vendor/xgtvm/libraries/machine.cpp b/libraries/vendor/xgtvm/libraries/machine.cpp index 2299e47c..35182e20 100644 --- a/libraries/vendor/xgtvm/libraries/machine.cpp +++ b/libraries/vendor/xgtvm/libraries/machine.cpp @@ -36,6 +36,11 @@ namespace machine return x.convert_to(); } + big_word to_big_word(size_t a) + { + return a; + } + big_word to_big_word(word a) { return a; @@ -226,6 +231,10 @@ namespace machine big_word va, vb, vc, vd, ve, vf, vg, vh, vi, vj, vk, vl, vm, vn, vo, vp, vq; stack_variant sv; signed_big_word sa, sb, sc; + size_t offset, dest_offset, length, code_size; + std::vector contract_args; + std::vector ext_contract_code; + std::vector::const_iterator first, last; std::string* ss; switch (op) { @@ -439,6 +448,12 @@ namespace machine logger << "op sha3" << std::endl; va = pop_word(); // offset vb = pop_word(); // length + + first = memory.begin() + static_cast(va); + last = memory.begin() + static_cast(va) + static_cast(vb); + + push_word( adapter.sha3( std::vector(first, last) ) ); // hash + break; case address_opcode: logger << "op address" << std::endl; @@ -448,7 +463,7 @@ namespace machine std::cout << 1 << std::endl; logger << "op balance" << std::endl; { - sv = stack.front(); // wallet_name + sv = stack.front(); // addr stack.pop_front(); ss = boost::get(&sv); if (ss) @@ -464,7 +479,7 @@ namespace machine break; case origin_opcode: logger << "op origin" << std::endl; - // TODO + push_word( ctx.tx_origin ); break; case caller_opcode: logger << "op caller" << std::endl; @@ -476,72 +491,172 @@ namespace machine break; case calldataload_opcode: logger << "op calldataload" << std::endl; - // TODO + offset = static_cast( pop_word() ); + + if (offset > msg.input_size) { + logger << "calldataload start index is larger than message input_size"; + break; + } + + va = to_big_word( + msg.input_data[offset + 7], + msg.input_data[offset + 6], + msg.input_data[offset + 5], + msg.input_data[offset + 4], + msg.input_data[offset + 3], + msg.input_data[offset + 2], + msg.input_data[offset + 1], + msg.input_data[offset + 0] + ); + push_word(va); break; case calldatasize_opcode: logger << "op calldatasize" << std::endl; - push_word( msg.input_size ); + push_word( to_big_word(msg.input_size) ); break; case calldatacopy_opcode: logger << "op calldatacopy" << std::endl; - // TODO + + dest_offset = static_cast( pop_word() ); + offset = static_cast( pop_word() ); + length = static_cast( pop_word() ); + + if ((offset + length) > msg.input_size) { + logger << "calldatacopy end index is larger than message input_size"; + break; + } + + for (size_t i = 0; i < length; ++i) + memory[dest_offset + i] = msg.input_data[offset + i]; + break; case codesize_opcode: logger << "op codesize" << std::endl; - push_word( msg.code_size ); + push_word( to_big_word( code.size() ) ); break; case codecopy_opcode: logger << "op codecopy" << std::endl; - // TODO + + dest_offset = static_cast( pop_word() ); + offset = static_cast( pop_word() ); + length = static_cast( pop_word() ); + + if ((offset + length) > msg.input_size) { + logger << "Codecopy end index is larger than message input_size"; + break; + } + + for (size_t i = 0; i < length; ++i) + memory[dest_offset + i] = code[offset + i]; + break; - case gasprice_opcode: - logger << "op gasprice" << std::endl; - push_word( ctx.tx_gasprice ); + case energyprice_opcode: + logger << "op energyprice" << std::endl; + push_word( to_big_word( ctx.tx_energyprice ) ); break; case extcodesize_opcode: logger << "op extcodesize" << std::endl; - // TODO + sv = stack.front(); // addr + ss = boost::get(&sv); + if (ss) + { + stack.pop_front(); + ext_contract_code = adapter.get_code_at_addr(*ss); + push_word( sizeof(ext_contract_code) / sizeof(ext_contract_code[0]) ); + } + else + { + state = machine_state::error; + error_message.emplace("Extcodesize operation type error"); + } break; case extcodecopy_opcode: logger << "op extcodecopy" << std::endl; - // TODO + sv = stack.front(); // addr + ss = boost::get(&sv); + if (ss) + { + stack.pop_front(); + ext_contract_code = adapter.get_code_at_addr(*ss); + code_size = sizeof(ext_contract_code) / sizeof(ext_contract_code[0]); + } + else + { + state = machine_state::error; + error_message.emplace("Extcodecopy operation type error"); + } + + dest_offset = static_cast( pop_word() ); + offset = static_cast( pop_word() ); + length = static_cast( pop_word() ); + + if ((offset + length) > code_size) { + logger << "codecopy end index exceeds external contract code length"; + break; + } + + for (size_t i = 0; i < length; ++i) + memory[dest_offset + i] = ext_contract_code[offset + i]; + break; case returndatasize_opcode: logger << "op returndatasize" << std::endl; - // TODO + push_word( ext_return_data.size() ); break; case returndatacopy_opcode: logger << "op returndatacopy" << std::endl; - // TODO + dest_offset = static_cast( pop_word() ); + offset = static_cast( pop_word() ); + length = static_cast( pop_word() ); + + if ( (offset + length) > ext_return_data.size() ) { + logger << "returndatacopy end index exceeds return data size"; + break; + } + + for (size_t i = 0; i < length; ++i) + memory[dest_offset + i] = ext_return_data[offset + i]; + break; case extcodehash_opcode: logger << "op extcodehash" << std::endl; - // TODO + sv = stack.front(); // addr + ss = boost::get(&sv); + if (ss) + { + stack.pop_front(); + push_word( adapter.get_code_hash(*ss) ); + } + else + { + state = machine_state::error; + error_message.emplace("Extcodehash operation type error"); + } break; case blockhash_opcode: logger << "op blockhash" << std::endl; - // TODO + va = pop_word(); + push_word( adapter.get_block_hash( static_cast(va) ) ); break; case coinbase_opcode: logger << "op coinbase" << std::endl; - // TODO convert address datatype to big_word - push_word(ctx.block_coinbase); + push_word( ctx.block_coinbase ); break; case timestamp_opcode: logger << "op timestamp" << std::endl; - push_word(ctx.block_timestamp); + push_word( ctx.block_timestamp ); break; case number_opcode: logger << "op number" << std::endl; - push_word(ctx.block_number); + push_word( ctx.block_number ); break; case difficulty_opcode: logger << "op difficulty" << std::endl; - push_word(ctx.block_difficulty); + push_word( ctx.block_difficulty ); break; - case gaslimit_opcode: - logger << "op gaslimit" << std::endl; - push_word(ctx.block_gaslimit); + case energylimit_opcode: + logger << "op energylimit" << std::endl; + push_word( ctx.block_energylimit ); break; case pop_opcode: logger << "op pop" << std::endl; @@ -549,55 +664,80 @@ namespace machine break; case mload_opcode: logger << "op mload" << std::endl; - // va = pop_word(); // offset - // if (va + 8 >= memory.size()) - // { - // state = machine_state::error; - // error_message.emplace("Memory overflow"); - // } - // // TODO: Verify order - // vb = to_big_word( - // memory[va + 7], - // memory[va + 6], - // memory[va + 5], - // memory[va + 4], - // memory[va + 3], - // memory[va + 2], - // memory[va + 1], - // memory[va + 0] - // ); - // push_word(vb); + va = pop_word(); // offset + if (va + 8 >= memory.size()) + { + state = machine_state::error; + error_message.emplace("Memory overflow"); + } + // TODO: Verify order + vb = to_big_word( + memory[static_cast(va) + 7], + memory[static_cast(va) + 6], + memory[static_cast(va) + 5], + memory[static_cast(va) + 4], + memory[static_cast(va) + 3], + memory[static_cast(va) + 2], + memory[static_cast(va) + 1], + memory[static_cast(va) + 0] + ); + push_word(vb); break; case mstore_opcode: logger << "op mstore" << std::endl; - // va = pop_word(); // offset - // vb = pop_word(); // value - // logger << "memory before: " << inspect(memory) << std::endl; - // if (va + 8 >= memory.size()) - // memory.resize(va + 8); - // // TODO: Verify order - // memory[va + 0] = get_byte(vb, 7); - // memory[va + 1] = get_byte(vb, 6); - // memory[va + 2] = get_byte(vb, 5); - // memory[va + 3] = get_byte(vb, 4); - // memory[va + 4] = get_byte(vb, 3); - // memory[va + 5] = get_byte(vb, 2); - // memory[va + 6] = get_byte(vb, 1); - // memory[va + 7] = get_byte(vb, 0); - // logger << "memory after: " << inspect(memory) << std::endl; + va = pop_word(); // offset + vb = pop_word(); // value + logger << "memory before: " << inspect(memory) << std::endl; + if (va + 8 >= memory.size()) + memory.resize(static_cast(va) + 8); + // TODO: Verify order + memory[static_cast(va) + 0] = get_byte(vb, 7); + memory[static_cast(va) + 1] = get_byte(vb, 6); + memory[static_cast(va) + 2] = get_byte(vb, 5); + memory[static_cast(va) + 3] = get_byte(vb, 4); + memory[static_cast(va) + 4] = get_byte(vb, 3); + memory[static_cast(va) + 5] = get_byte(vb, 2); + memory[static_cast(va) + 6] = get_byte(vb, 1); + memory[static_cast(va) + 7] = get_byte(vb, 0); + logger << "memory after: " << inspect(memory) << std::endl; break; case mstore8_opcode: logger << "op mstore8" << std::endl; - // TODO + va = pop_word(); // offset + vb = pop_word(); // value + logger << "memory before: " << inspect(memory) << std::endl; + if (va + 1 >= memory.size()) + memory.resize(static_cast(va) + 1); + // TODO: Verify order + memory[static_cast(va)] = get_byte(vb, 0); // TODO verify byte of big_word vb + logger << "memory after: " << inspect(memory) << std::endl; break; case sload_opcode: logger << "op sload" << std::endl; - // TODO + sv = stack.front(); + if (std::string* it = boost::get(&sv)) + { + stack.pop_front(); + va = adapter.access_storage(*it); + push_word(va); + } + else { + throw; // TODO + } break; case sstore_opcode: logger << "op sstore" << std::endl; - // TODO - break; + sv = stack.front(); + if (std::string* it = boost::get(&sv)) + { + stack.pop_front(); + va = pop_word(); + adapter.set_storage(msg.destination, *it, va); + } + else { + throw; // TODO + } + break; case jump_opcode: logger << "op jump" << std::endl; va = pop_word(); // destination @@ -620,11 +760,11 @@ namespace machine break; case msize_opcode: logger << "op msize" << std::endl; - // TODO + push_word( to_big_word( memory.size() ) ); break; - case gas_opcode: - logger << "op gas" << std::endl; - // TODO + case energy_opcode: + logger << "op energy" << std::endl; + push_word(energy_left); break; case jumpdest_opcode: logger << "op jumpdest" << std::endl; @@ -2457,8 +2597,58 @@ namespace machine this->emit_log(o); break; } + case create_opcode: + logger << "op create" << std::endl; + // TODO REVIEW + va = pop_word(); // value + vb = pop_word(); // offset + vc = pop_word(); // length + + first = memory.begin() + static_cast(vb); + last = memory.begin() + static_cast(vb) + static_cast(vc); + + push_word( adapter.contract_create( std::vector(first, last), va ) ); // addr + break; + case call_opcode: + logger << "op call" << std::endl; + va = pop_word(); // energy + + sv = stack.front(); // addr + ss = boost::get(&sv); + if (ss) + { + stack.pop_front(); + vb = pop_word(); // value + vc = pop_word(); // argsOffset + vd = pop_word(); // argsLength + ve = pop_word(); // retOffset + vf = pop_word(); // retLength + + first = memory.begin() + static_cast(vc); + last = memory.begin() + static_cast(vc) + static_cast(vd); + + contract_args = std::vector(first, last); + + adapter.contract_call(*ss, static_cast(va), vb, contract_args); + } + + // TODO + break; + case callcode_opcode: + logger << "op callcode" << std::endl; + va = pop_word(); // energy + vb = pop_word(); // addr + vc = pop_word(); // value + vd = pop_word(); // argsOffset + ve = pop_word(); // argsLength + vf = pop_word(); // retOffset + vg = pop_word(); // retLength + + // TODO + break; case return_opcode: logger << "op return" << std::endl; + // TODO REVIEW // a = pop_word(); // offset // b = pop_word(); // length // logger << std::to_string(a) << std::endl; @@ -2469,6 +2659,63 @@ namespace machine // for (int i = 0; i < return_value.size(); i++) // return_value[i] = memory[a + i]; // state = machine_state::stopped; + + va = pop_word(); // offset + vb = pop_word(); // length + + first = memory.begin() + static_cast(va); + last = memory.begin() + static_cast(va) + static_cast(vb); + + adapter.contract_return( std::vector(first, last) ); + break; + case delegatecall_opcode: + logger << "op delegatecall" << std::endl; + va = pop_word(); // energy + vb = pop_word(); // addr + vc = pop_word(); // argsOffset + vd = pop_word(); // argsLength + ve = pop_word(); // retOffset + vf = pop_word(); // retLength + + // TODO + break; + case create2_opcode: + logger << "op create2" << std::endl; + va = pop_word(); // value + vb = pop_word(); // offset + vc = pop_word(); //length + vd = pop_word(); // salt + // TODO + break; + case staticcall_opcode: + logger << "op staticcall" << std::endl; + va = pop_word(); // energy + vb = pop_word(); // addr + vc = pop_word(); // argsOffset + vd = pop_word(); // argsLength + ve = pop_word(); // retOffset + vf = pop_word(); // retLength + + // TODO + break; + case revert_opcode: + logger << "op revert" << std::endl; + va = pop_word(); // offset + vb = pop_word(); // length + + first = memory.begin() + static_cast(va); + last = memory.begin() + static_cast(va) + static_cast(vb); + + adapter.revert( std::vector(first, last) ); + break; + case selfdestruct_opcode: + logger << "op selfdestruct" << std::endl; + sv = stack.front(); // addr + ss = boost::get(&sv); + if (ss) + { + adapter.self_destruct(*ss); + } break; } } diff --git a/libraries/vendor/xgtvm/libraries/machine.hpp b/libraries/vendor/xgtvm/libraries/machine.hpp index 73ded1aa..50cf01cd 100644 --- a/libraries/vendor/xgtvm/libraries/machine.hpp +++ b/libraries/vendor/xgtvm/libraries/machine.hpp @@ -53,40 +53,40 @@ enum opcode shr_opcode = 0x1C, sar_opcode = 0x1D, - sha3_opcode = 0x20, // XXX depends on crypto++ -- needs cmake integration + sha3_opcode = 0x20, address_opcode = 0x30, - balance_opcode = 0x31, // XXX Look up balance for address on top of stack. Is this an rpc call to the chain? - origin_opcode = 0x32, // XXX Transaction origin address + balance_opcode = 0x31, + origin_opcode = 0x32, caller_opcode = 0x33, callvalue_opcode = 0x34, - calldataload_opcode = 0x35, // XXX Reads a uint256 from message data - calldatasize_opcode = 0x36, // XXX Message data length in bytes - calldatacopy_opcode = 0x37, // XXX Copy message data to memory + calldataload_opcode = 0x35, + calldatasize_opcode = 0x36, + calldatacopy_opcode = 0x37, codesize_opcode = 0x38, - codecopy_opcode = 0x39, // XXX Copy executing contract's bytecode to memory - gasprice_opcode = 0x3A, // XXX Price of executing contract. Energyprice? - extcodesize_opcode = 0x3B, // XXX Length of the contract bytecode at addr (top of stack) in bytes - extcodecopy_opcode = 0x3C, // XXX Copy contract's code to memory - returndatasize_opcode = 0x3D, // XXX Size of returned data from last external call in bytes - returndatacopy_opcode = 0x3E, // XXX Copy returned data to memory - extcodehash_opcode = 0x3F, // XXX Hash of contract bytecode at addr (top of stack) - blockhash_opcode = 0x40, // XXX Hash of specific block (blocknumber is top of stack) - coinbase_opcode = 0x41, // TODO REVIEW + codecopy_opcode = 0x39, + energyprice_opcode = 0x3A, + extcodesize_opcode = 0x3B, + extcodecopy_opcode = 0x3C, + returndatasize_opcode = 0x3D, + returndatacopy_opcode = 0x3E, + extcodehash_opcode = 0x3F, + blockhash_opcode = 0x40, + coinbase_opcode = 0x41, timestamp_opcode = 0x42, number_opcode = 0x43, difficulty_opcode = 0x44, - gaslimit_opcode = 0x45, + energylimit_opcode = 0x45, pop_opcode = 0x50, - mload_opcode = 0x51, // TODO - mstore_opcode = 0x52, // TODO - mstore8_opcode = 0x53, // TODO - sload_opcode = 0x54, // TODO - sstore_opcode = 0x55, // TODO + mload_opcode = 0x51, + mstore_opcode = 0x52, + mstore8_opcode = 0x53, + sload_opcode = 0x54, + sstore_opcode = 0x55, jump_opcode = 0x56, - jumpi_opcode = 0x57, + jumpi_opcode = 0x57, pc_opcode = 0x58, - msize_opcode = 0x59, // TODO - gas_opcode = 0x5A, // TODO energy? + msize_opcode = 0x59, + energy_opcode = 0x5A, jumpdest_opcode = 0x5B, // PUSH @@ -160,26 +160,21 @@ enum opcode swap16_opcode = 0x9F, // LOG - log0_opcode = 0xA0, // TODO - log1_opcode = 0xA1, // TODO - log2_opcode = 0xA2, // TODO - log3_opcode = 0xA3, // TODO - log4_opcode = 0xA4, // TODO - - // Generic push/dup/swap opcodes - //push_opcode = 0xB0, // TODO - //dup_opcode = 0xB1, // TODO - //swap_opcode = 0xB2, // TODO - - //create_opcode = 0xF0, // TODO - //call_opcode = 0xF1, // TODO - //callcode_opcode = 0xF2, // TODO + log0_opcode = 0xA0, + log1_opcode = 0xA1, + log2_opcode = 0xA2, + log3_opcode = 0xA3, + log4_opcode = 0xA4, + + create_opcode = 0xF0, + call_opcode = 0xF1, // TODO + callcode_opcode = 0xF2, // TODO return_opcode = 0xF3, - //delegatecall_opcode = 0xF4, // TODO - //create2_opcode = 0xF5, // TODO - //staticcall_opcode = 0xFA, // TODO - //revert_opcode = 0xFD, // TODO - //selfdestruct_opcode = 0xFF, // TODO + delegatecall_opcode = 0xF4, // TODO + create2_opcode = 0xF5, // TODO + staticcall_opcode = 0xFA, // TODO + revert_opcode = 0xFD, + selfdestruct_opcode = 0xFF, }; enum class machine_state @@ -201,44 +196,74 @@ struct message { uint32_t flags; int32_t depth; - int64_t gas; + int64_t energy; - // TODO Need address datatype - // address sender; - big_word sender; - // address destination; - big_word destination; + std::string sender; + std::string destination; big_word value; size_t input_size; - const uint8_t* input_data; + std::vector input_data = {}; size_t code_size; }; +// TODO replace with correct data types struct context { bool is_debug; uint64_t block_timestamp; uint64_t block_number; uint64_t block_difficulty; - uint64_t block_gaslimit; - uint64_t tx_gasprice; - // Should be address datatype - uint64_t block_coinbase; + uint64_t block_energylimit; + uint64_t tx_energyprice; + std::string tx_origin; + std::string block_coinbase; }; -/* TODO switch stack to variant implementing this pattern - - if (stack_variant* it = std::get_if(from)) - { - stack_variant& stack_object = std::get(from); - // Use `stack_object` as normal - } - */ - struct chain_adapter { + // TODO sha3 opcode + std::function< std::string(std::vector) > sha3; + + // TODO retrieves balance at addr -- used for balance opcode std::function< uint64_t(std::string) > get_balance; + + // TODO for hashing address -- extcodehash opcode + std::function< std::string(std::string) > get_code_hash; + + // TODO for hashing block number -- blockhash opcode + std::function< std::string(uint64_t) > get_block_hash; + + // TODO get contract bytecode at address + std::function< std::vector(std::string) > get_code_at_addr; + + // TODO creates a child contract -- create opcode + std::function< std::string(std::vector, big_word) > contract_create; + + // TODO call a method from another contract -- call opcode -- address, energy, value, args + std::function< std::string(std::string, uint64_t, big_word, std::vector) > contract_call; + + // TODO creates a child contract -- create2 opcode + std::function< std::string(big_word, std::vector, std::string) > contract_create2; + + // TODO revert opcode + std::function< bool(std::vector) > revert; + + // TODO load opcode -- takes key as a parameter and returns value + std::function< big_word(std::string) > access_storage; + + // TODO sstore opcode -- destination, key, value + std::function< bool(std::string, std::string, big_word) > set_storage; + + // TODO return opcode + std::function< bool(std::vector) > contract_return; + + // TODO selfdestruct opcode + std::function< bool(std::string) > self_destruct; + + // TODO used to initialize message data + std::function< std::vector(std::string) > get_input_data; + }; class machine @@ -250,10 +275,13 @@ class machine std::vector code; message msg; std::vector memory; + std::vector< std::map > storage; std::vector return_value; + std::vector ext_return_data; boost::optional error_message; std::stringstream logger; chain_adapter adapter; + big_word energy_left; void push_word(stack_variant v); big_word pop_word(); diff --git a/libraries/vendor/xgtvm/programs/xgtvm.cpp b/libraries/vendor/xgtvm/programs/xgtvm.cpp index fbcd026d..7f93dec8 100644 --- a/libraries/vendor/xgtvm/programs/xgtvm.cpp +++ b/libraries/vendor/xgtvm/programs/xgtvm.cpp @@ -52,15 +52,94 @@ static struct option long_options[] = { {0, 0, 0, 0} }; +// chain_adapter is state.host equivalent in evmone machine::chain_adapter make_chain_adapter() { - std::function< uint64_t(std::string) > get_balance = [](std::string wallet_name) -> uint64_t + std::function< std::string(std::vector) > sha3 = [](std::vector memory) -> std::string { return 0; }; + std::function< uint64_t(std::string) > get_balance = [](std::string address) -> uint64_t + { + return 0; + }; + + std::function< std::string(std::string) > get_code_hash = [](std::string address) -> std::string + { + return ""; + }; + + std::function< std::string(uint64_t) > get_block_hash = [](uint64_t block_num) -> std::string + { + return ""; + }; + + std::function< std::vector(std::string) > get_code_at_addr = [](std::string address) -> std::vector + { + return {}; + }; + + std::function< std::string(std::vector, machine::big_word) > contract_create = [](std::vector memory, machine::big_word value) -> std::string + { + return {}; + }; + + std::function< std::string(std::string, uint64_t, machine::big_word, std::vector) > contract_call = [](std::string address, uint64_t energy, machine::big_word value, std::vector args) -> std::string + { + return {}; + }; + + std::function< std::string(machine::big_word, std::vector, std::string) > contract_create2 = [](machine::big_word value, std::vector memory, std::string salt) -> std::string + { + return {}; + }; + + std::function< bool(std::vector) > revert = [](std::vector memory) -> bool + { + return {}; + }; + + std::function< machine::big_word(std::string) > access_storage = [](std::string key) -> machine::big_word + { + return {}; + }; + + std::function< bool(std::string, std::string, machine::big_word) > set_storage = [](std::string destination, std::string key, machine::big_word value) -> bool + { + return {}; + }; + + std::function< bool(std::vector) > contract_return = [](std::vector memory) -> bool + { + return {}; + }; + + std::function< bool(std::string) > self_destruct = [](std::string address) -> bool + { + return {}; + }; + + std::function< std::vector(std::string) > get_input_data = [](std::string address) -> std::vector + { + return {}; + }; + machine::chain_adapter adapter = { - get_balance + sha3, + get_balance, + get_code_hash, + get_block_hash, + get_code_at_addr, + contract_create, + contract_call, + contract_create2, + revert, + access_storage, + set_storage, + contract_return, + self_destruct, + get_input_data }; return adapter; diff --git a/libraries/vendor/xgtvm/programs/xgtvm_tests.cpp b/libraries/vendor/xgtvm/programs/xgtvm_tests.cpp index a4dd95ac..4a4d0aa4 100644 --- a/libraries/vendor/xgtvm/programs/xgtvm_tests.cpp +++ b/libraries/vendor/xgtvm/programs/xgtvm_tests.cpp @@ -11,13 +11,91 @@ machine::chain_adapter make_chain_adapter() { - std::function< uint64_t(std::string) > get_balance = [](std::string wallet_name) -> uint64_t + std::function< std::string(std::vector) > sha3 = [](std::vector memory) -> std::string { return 0; }; + std::function< uint64_t(std::string) > get_balance = [](std::string address) -> uint64_t + { + return 0; + }; + + std::function< std::string(std::string) > get_code_hash = [](std::string address) -> std::string + { + return ""; + }; + + std::function< std::string(uint64_t) > get_block_hash = [](uint64_t block_num) -> std::string + { + return ""; + }; + + std::function< std::vector(std::string) > get_code_at_addr = [](std::string address) -> std::vector + { + return {}; + }; + + std::function< std::string(std::vector, machine::big_word) > contract_create = [](std::vector memory, machine::big_word value) -> std::string + { + return {}; + }; + + std::function< std::string(std::string, uint64_t, machine::big_word, std::vector) > contract_call = [](std::string address, uint64_t energy, machine::big_word value, std::vector args) -> std::string + { + return {}; + }; + + std::function< std::string(machine::big_word, std::vector, std::string) > contract_create2 = [](machine::big_word value, std::vector memory, std::string salt) -> std::string + { + return {}; + }; + + std::function< bool(std::vector) > revert = [](std::vector memory) -> bool + { + return {}; + }; + + std::function< machine::big_word(std::string) > access_storage = [](std::string key) -> machine::big_word + { + return {}; + }; + + std::function< bool(std::string, std::string, machine::big_word) > set_storage = [](std::string destination, std::string key, machine::big_word value) -> bool + { + return {}; + }; + + std::function< bool(std::vector) > contract_return = [](std::vector memory) -> bool + { + return {}; + }; + + std::function< bool(std::string) > self_destruct = [](std::string address) -> bool + { + return {}; + }; + + std::function< std::vector(std::string) > get_input_data = [](std::string address) -> std::vector + { + return {}; + }; + machine::chain_adapter adapter = { - get_balance + sha3, + get_balance, + get_code_hash, + get_block_hash, + get_code_at_addr, + contract_create, + contract_call, + contract_create2, + revert, + access_storage, + set_storage, + contract_return, + self_destruct, + get_input_data }; return adapter; From 6e56ca032c0bd8edcdd36dc4d58d2d123619c9f2 Mon Sep 17 00:00:00 2001 From: Roger Jungemann Date: Tue, 17 Aug 2021 10:31:26 -0700 Subject: [PATCH 18/96] Add a debug invoke task to Rakefile --- Rakefile | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Rakefile b/Rakefile index 308a2e8d..66c96c02 100644 --- a/Rakefile +++ b/Rakefile @@ -558,6 +558,12 @@ namespace :contracts do response = rpc.call('contract_api.list_owner_contracts', { 'owner' => wallet }) || {} p response end + + desc 'View sample contracts' + task :debug_invoke do + response = rpc.call('contract_api.invoke', { 'owner' => wallet, 'code' => [] }) || {} + p response + end end namespace :machine do From b2bdf979b14b89e729ef34518f25238a6457201d Mon Sep 17 00:00:00 2001 From: Roger Jungemann Date: Tue, 17 Aug 2021 13:22:55 -0700 Subject: [PATCH 19/96] Allow starting from genesis using a command-line flag --- Rakefile | 14 ++++++++++++-- libraries/plugins/p2p/p2p_plugin.cpp | 7 +++++-- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/Rakefile b/Rakefile index 66c96c02..38825581 100644 --- a/Rakefile +++ b/Rakefile @@ -19,6 +19,10 @@ end directory "../xgt-build" +def from_genesis? + ENV['FROM_GENESIS']&.upcase == 'TRUE' +end + def mining_disabled? ENV['MINING_DISABLED']&.upcase == 'TRUE' end @@ -291,13 +295,19 @@ task :run do enable-stale-production = #{mining_disabled? ? 'false' : 'true'} ))) - if seed_hosts && seed_hosts.any? + if from_genesis? + f.puts "p2p-seed-node = " + elsif seed_hosts && seed_hosts.any? f.puts "p2p-seed-node = #{seed_hosts.join(" ")}" end end $stderr.puts(File.read("#{data_dir}/config.ini")) - sh %(cd #{data_dir} && ../xgt-build/programs/xgtd/xgtd --data-dir=.) + flags = ['--data-dir=.'] + if from_genesis? + flags << '--from-genesis' + end + sh %(cd #{data_dir} && ../xgt-build/programs/xgtd/xgtd #{flags.join(' ')}) end desc 'Get approximate C++ LoC' diff --git a/libraries/plugins/p2p/p2p_plugin.cpp b/libraries/plugins/p2p/p2p_plugin.cpp index 32094175..21af6f18 100644 --- a/libraries/plugins/p2p/p2p_plugin.cpp +++ b/libraries/plugins/p2p/p2p_plugin.cpp @@ -111,6 +111,7 @@ class p2p_plugin_impl : public graphene::net::node_delegate uint32_t max_connections = 0; bool force_validate = false; bool block_producer = false; + bool from_genesis = false; std::atomic_bool ready_to_mine; std::atomic_bool running; std::atomic_bool activeHandleBlock; @@ -569,6 +570,7 @@ void p2p_plugin::set_program_options( bpo::options_description& cli, bpo::option cli.add_options() ("force-validate", bpo::bool_switch()->default_value(false), "Force validation of all transactions. Deprecated in favor of p2p-force-validate" ) ("p2p-force-validate", bpo::bool_switch()->default_value(false), "Force validation of all transactions." ) + ("from-genesis", bpo::bool_switch()->default_value(false), "Start chain from genesis." ) ; } @@ -576,8 +578,6 @@ void p2p_plugin::plugin_initialize(const boost::program_options::variables_map& { my = std::make_unique< detail::p2p_plugin_impl >( appbase::app().get_plugin< plugins::chain::chain_plugin >() ); - my->ready_to_mine = false; - if( options.count( "p2p-endpoint" ) ) my->endpoint = fc::ip::endpoint::from_string( options.at( "p2p-endpoint" ).as< string >() ); @@ -633,6 +633,9 @@ void p2p_plugin::plugin_initialize(const boost::program_options::variables_map& } my->force_validate = options.at( "p2p-force-validate" ).as< bool >(); + my->from_genesis = options.at( "from-genesis" ).as< bool >(); + + my->ready_to_mine = my->from_genesis; if( !my->force_validate && options.at( "force-validate" ).as< bool >() ) { From 77448ad3694aab5a891696ecb45bebf0c14b0c87 Mon Sep 17 00:00:00 2001 From: Liam Noroian Date: Wed, 18 Aug 2021 10:16:01 -0700 Subject: [PATCH 20/96] adding to_big_word type, reformatting stack variant accessors --- libraries/vendor/xgtvm/libraries/machine.cpp | 143 ++++++++++++++---- libraries/vendor/xgtvm/libraries/machine.hpp | 25 ++- libraries/vendor/xgtvm/programs/xgtvm.cpp | 22 ++- .../vendor/xgtvm/programs/xgtvm_tests.cpp | 22 ++- 4 files changed, 174 insertions(+), 38 deletions(-) diff --git a/libraries/vendor/xgtvm/libraries/machine.cpp b/libraries/vendor/xgtvm/libraries/machine.cpp index 35182e20..6eca5e97 100644 --- a/libraries/vendor/xgtvm/libraries/machine.cpp +++ b/libraries/vendor/xgtvm/libraries/machine.cpp @@ -41,6 +41,11 @@ namespace machine return a; } + big_word to_big_word(uint64_t a) + { + return a; + } + big_word to_big_word(word a) { return a; @@ -460,7 +465,6 @@ namespace machine push_word( msg.destination ); break; case balance_opcode: - std::cout << 1 << std::endl; logger << "op balance" << std::endl; { sv = stack.front(); // addr @@ -2629,22 +2633,53 @@ namespace machine contract_args = std::vector(first, last); - adapter.contract_call(*ss, static_cast(va), vb, contract_args); - } + std::vector contract_call_return = adapter.contract_call(*ss, static_cast(va), vb, contract_args); - // TODO + for (size_t i = 0; i < static_cast(vf); i++) + memory[static_cast(ve) + i] = contract_call_return[i]; + + // TODO revise stack return value? + push_word("Success"); // success + } + else { + push_word("Failure"); // success + state = machine_state::error; + error_message.emplace("Call operation type error"); + } break; case callcode_opcode: logger << "op callcode" << std::endl; va = pop_word(); // energy - vb = pop_word(); // addr - vc = pop_word(); // value - vd = pop_word(); // argsOffset - ve = pop_word(); // argsLength - vf = pop_word(); // retOffset - vg = pop_word(); // retLength - // TODO + sv = stack.front(); // addr + ss = boost::get(&sv); + if (ss) + { + stack.pop_front(); + vb = pop_word(); // value + vc = pop_word(); // argsOffset + vd = pop_word(); // argsLength + ve = pop_word(); // retOffset + vf = pop_word(); // retLength + + first = memory.begin() + static_cast(vc); + last = memory.begin() + static_cast(vc) + static_cast(vd); + + contract_args = std::vector(first, last); + + std::vector contract_callcode_return = adapter.contract_callcode(*ss, static_cast(va), vb, contract_args); + + for (size_t i = 0; i < static_cast(vf); i++) + memory[static_cast(ve) + i] = contract_callcode_return[i]; + + // TODO revise stack return value? + push_word("Success"); // success + } + else { + push_word("Failure"); // success + state = machine_state::error; + error_message.emplace("Callcode operation type error"); + } break; case return_opcode: logger << "op return" << std::endl; @@ -2671,32 +2706,88 @@ namespace machine case delegatecall_opcode: logger << "op delegatecall" << std::endl; va = pop_word(); // energy - vb = pop_word(); // addr - vc = pop_word(); // argsOffset - vd = pop_word(); // argsLength - ve = pop_word(); // retOffset - vf = pop_word(); // retLength - // TODO + sv = stack.front(); // addr + ss = boost::get(&sv); + if (ss) + { + stack.pop_front(); + vb = pop_word(); // argsOffset + vc = pop_word(); // argsLength + vd = pop_word(); // retOffset + ve = pop_word(); // retLength + + first = memory.begin() + static_cast(vb); + last = memory.begin() + static_cast(vb) + static_cast(vc); + + contract_args = std::vector(first, last); + + std::vector contract_delegatecall_return = adapter.contract_delegatecall(*ss, static_cast(va), contract_args); + + for (size_t i = 0; i < static_cast(ve); i++) + memory[static_cast(vd) + i] = contract_delegatecall_return[i]; + + // TODO revise stack return value? + push_word("Success"); // success + } + else { + push_word("Failure"); // success + state = machine_state::error; + error_message.emplace("Delegatecall operation type error"); + } break; case create2_opcode: logger << "op create2" << std::endl; va = pop_word(); // value vb = pop_word(); // offset - vc = pop_word(); //length - vd = pop_word(); // salt - // TODO + vc = pop_word(); // length + + sv = stack.front(); // salt + ss = boost::get(&sv); + if (ss) + { + first = memory.begin() + static_cast(vb); + last = memory.begin() + static_cast(vb) + static_cast(vc); + + push_word( adapter.contract_create2( std::vector(first, last), va, *ss ) ); + } + else { + state = machine_state::error; + error_message.emplace("Create2 operation type error"); + } break; case staticcall_opcode: logger << "op staticcall" << std::endl; va = pop_word(); // energy - vb = pop_word(); // addr - vc = pop_word(); // argsOffset - vd = pop_word(); // argsLength - ve = pop_word(); // retOffset - vf = pop_word(); // retLength - // TODO + sv = stack.front(); // addr + ss = boost::get(&sv); + if (ss) + { + stack.pop_front(); + vb = pop_word(); // argsOffset + vc = pop_word(); // argsLength + vd = pop_word(); // retOffset + ve = pop_word(); // retLength + + first = memory.begin() + static_cast(vb); + last = memory.begin() + static_cast(vb) + static_cast(vc); + + contract_args = std::vector(first, last); + + std::vector contract_staticcall_return = adapter.contract_staticcall(*ss, static_cast(va), contract_args); + + for (size_t i = 0; i < static_cast(ve); i++) + memory[static_cast(vd) + i] = contract_staticcall_return[i]; + + // TODO revise stack return value? + push_word("Success"); // success + } + else { + push_word("Failure"); // success + state = machine_state::error; + error_message.emplace("Staticcall operation type error"); + } break; case revert_opcode: logger << "op revert" << std::endl; diff --git a/libraries/vendor/xgtvm/libraries/machine.hpp b/libraries/vendor/xgtvm/libraries/machine.hpp index 50cf01cd..f542e470 100644 --- a/libraries/vendor/xgtvm/libraries/machine.hpp +++ b/libraries/vendor/xgtvm/libraries/machine.hpp @@ -167,12 +167,12 @@ enum opcode log4_opcode = 0xA4, create_opcode = 0xF0, - call_opcode = 0xF1, // TODO - callcode_opcode = 0xF2, // TODO + call_opcode = 0xF1, + callcode_opcode = 0xF2, return_opcode = 0xF3, - delegatecall_opcode = 0xF4, // TODO - create2_opcode = 0xF5, // TODO - staticcall_opcode = 0xFA, // TODO + delegatecall_opcode = 0xF4, + create2_opcode = 0xF5, + staticcall_opcode = 0xFA, revert_opcode = 0xFD, selfdestruct_opcode = 0xFF, }; @@ -225,7 +225,6 @@ struct chain_adapter // TODO sha3 opcode std::function< std::string(std::vector) > sha3; - // TODO retrieves balance at addr -- used for balance opcode std::function< uint64_t(std::string) > get_balance; // TODO for hashing address -- extcodehash opcode @@ -241,10 +240,20 @@ struct chain_adapter std::function< std::string(std::vector, big_word) > contract_create; // TODO call a method from another contract -- call opcode -- address, energy, value, args - std::function< std::string(std::string, uint64_t, big_word, std::vector) > contract_call; + std::function< std::vector(std::string, uint64_t, big_word, std::vector) > contract_call; + + // TODO call a method from another contract(?) -- callcode opcode -- address, energy, value, args + std::function< std::vector(std::string, uint64_t, big_word, std::vector) > contract_callcode; + + // TODO call a method from another contract using the storage of the current + // opcode -- delegatecall opcode -- address, energy, args + std::function< std::vector(std::string, uint64_t, std::vector) > contract_delegatecall; + + // TODO call a method from another contract with state changes disallowed -- staticcall opcode -- address, energy, args + std::function< std::vector(std::string, uint64_t, std::vector) > contract_staticcall; // TODO creates a child contract -- create2 opcode - std::function< std::string(big_word, std::vector, std::string) > contract_create2; + std::function< std::string(std::vector, big_word, std::string) > contract_create2; // TODO revert opcode std::function< bool(std::vector) > revert; diff --git a/libraries/vendor/xgtvm/programs/xgtvm.cpp b/libraries/vendor/xgtvm/programs/xgtvm.cpp index 7f93dec8..73ba64e3 100644 --- a/libraries/vendor/xgtvm/programs/xgtvm.cpp +++ b/libraries/vendor/xgtvm/programs/xgtvm.cpp @@ -85,12 +85,27 @@ machine::chain_adapter make_chain_adapter() return {}; }; - std::function< std::string(std::string, uint64_t, machine::big_word, std::vector) > contract_call = [](std::string address, uint64_t energy, machine::big_word value, std::vector args) -> std::string + std::function< std::vector(std::string, uint64_t, machine::big_word, std::vector) > contract_call = [](std::string address, uint64_t energy, machine::big_word value, std::vector args) -> std::vector { return {}; }; - std::function< std::string(machine::big_word, std::vector, std::string) > contract_create2 = [](machine::big_word value, std::vector memory, std::string salt) -> std::string + std::function< std::vector(std::string, uint64_t, machine::big_word, std::vector) > contract_callcode = [](std::string address, uint64_t energy, machine::big_word value, std::vector args) -> std::vector + { + return {}; + }; + + std::function< std::vector(std::string, uint64_t, std::vector) > contract_delegatecall = [](std::string address, uint64_t energy, std::vector args) -> std::vector + { + return {}; + }; + + std::function< std::vector(std::string, uint64_t, std::vector) > contract_staticcall = [](std::string address, uint64_t energy, std::vector args) -> std::vector + { + return {}; + }; + + std::function< std::string(std::vector, machine::big_word, std::string) > contract_create2 = [](std::vector memory, machine::big_word value, std::string salt) -> std::string { return {}; }; @@ -133,6 +148,9 @@ machine::chain_adapter make_chain_adapter() get_code_at_addr, contract_create, contract_call, + contract_callcode, + contract_delegatecall, + contract_staticcall, contract_create2, revert, access_storage, diff --git a/libraries/vendor/xgtvm/programs/xgtvm_tests.cpp b/libraries/vendor/xgtvm/programs/xgtvm_tests.cpp index 4a4d0aa4..62b21d19 100644 --- a/libraries/vendor/xgtvm/programs/xgtvm_tests.cpp +++ b/libraries/vendor/xgtvm/programs/xgtvm_tests.cpp @@ -41,12 +41,27 @@ machine::chain_adapter make_chain_adapter() return {}; }; - std::function< std::string(std::string, uint64_t, machine::big_word, std::vector) > contract_call = [](std::string address, uint64_t energy, machine::big_word value, std::vector args) -> std::string + std::function< std::vector(std::string, uint64_t, machine::big_word, std::vector) > contract_call = [](std::string address, uint64_t energy, machine::big_word value, std::vector args) -> std::vector { return {}; }; - std::function< std::string(machine::big_word, std::vector, std::string) > contract_create2 = [](machine::big_word value, std::vector memory, std::string salt) -> std::string + std::function< std::vector(std::string, uint64_t, machine::big_word, std::vector) > contract_callcode = [](std::string address, uint64_t energy, machine::big_word value, std::vector args) -> std::vector + { + return {}; + }; + + std::function< std::vector(std::string, uint64_t, std::vector) > contract_delegatecall = [](std::string address, uint64_t energy, std::vector args) -> std::vector + { + return {}; + }; + + std::function< std::vector(std::string, uint64_t, std::vector) > contract_staticcall = [](std::string address, uint64_t energy, std::vector args) -> std::vector + { + return {}; + }; + + std::function< std::string(std::vector, machine::big_word, std::string) > contract_create2 = [](std::vector memory, machine::big_word value, std::string salt) -> std::string { return {}; }; @@ -89,6 +104,9 @@ machine::chain_adapter make_chain_adapter() get_code_at_addr, contract_create, contract_call, + contract_callcode, + contract_delegatecall, + contract_staticcall, contract_create2, revert, access_storage, From 2cf3b163f580d26f33d49a41bcf85c6b6f409d7b Mon Sep 17 00:00:00 2001 From: Liam Noroian Date: Wed, 18 Aug 2021 10:36:00 -0700 Subject: [PATCH 21/96] Fixing build issues in vendored machine --- libraries/vendor/xgtvm/libraries/machine.cpp | 29 ++++++++++---------- libraries/vendor/xgtvm/libraries/machine.hpp | 2 +- 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/libraries/vendor/xgtvm/libraries/machine.cpp b/libraries/vendor/xgtvm/libraries/machine.cpp index 6eca5e97..07da075e 100644 --- a/libraries/vendor/xgtvm/libraries/machine.cpp +++ b/libraries/vendor/xgtvm/libraries/machine.cpp @@ -36,12 +36,12 @@ namespace machine return x.convert_to(); } - big_word to_big_word(size_t a) + big_word to_big_word(int64_t a) { return a; } - big_word to_big_word(uint64_t a) + big_word to_big_word(size_t a) { return a; } @@ -236,7 +236,7 @@ namespace machine big_word va, vb, vc, vd, ve, vf, vg, vh, vi, vj, vk, vl, vm, vn, vo, vp, vq; stack_variant sv; signed_big_word sa, sb, sc; - size_t offset, dest_offset, length, code_size; + size_t offset, dest_offset, length, code_size = 0; std::vector contract_args; std::vector ext_contract_code; std::vector::const_iterator first, last; @@ -583,6 +583,17 @@ namespace machine stack.pop_front(); ext_contract_code = adapter.get_code_at_addr(*ss); code_size = sizeof(ext_contract_code) / sizeof(ext_contract_code[0]); + dest_offset = static_cast( pop_word() ); + offset = static_cast( pop_word() ); + length = static_cast( pop_word() ); + + if ((offset + length) > code_size) { + logger << "codecopy end index exceeds external contract code length"; + break; + } + + for (size_t i = 0; i < length; ++i) + memory[dest_offset + i] = ext_contract_code[offset + i]; } else { @@ -590,18 +601,6 @@ namespace machine error_message.emplace("Extcodecopy operation type error"); } - dest_offset = static_cast( pop_word() ); - offset = static_cast( pop_word() ); - length = static_cast( pop_word() ); - - if ((offset + length) > code_size) { - logger << "codecopy end index exceeds external contract code length"; - break; - } - - for (size_t i = 0; i < length; ++i) - memory[dest_offset + i] = ext_contract_code[offset + i]; - break; case returndatasize_opcode: logger << "op returndatasize" << std::endl; diff --git a/libraries/vendor/xgtvm/libraries/machine.hpp b/libraries/vendor/xgtvm/libraries/machine.hpp index f542e470..244c6cf9 100644 --- a/libraries/vendor/xgtvm/libraries/machine.hpp +++ b/libraries/vendor/xgtvm/libraries/machine.hpp @@ -215,7 +215,7 @@ struct context uint64_t block_number; uint64_t block_difficulty; uint64_t block_energylimit; - uint64_t tx_energyprice; + int64_t tx_energyprice; std::string tx_origin; std::string block_coinbase; }; From 5936e5e539d1e6fee505a29a72d70803aab32979 Mon Sep 17 00:00:00 2001 From: Liam Noroian Date: Wed, 18 Aug 2021 13:17:07 -0700 Subject: [PATCH 22/96] Updating adapter methods --- .../apis/contract_api/contract_api.cpp | 27 +++++++++++++++---- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/libraries/plugins/apis/contract_api/contract_api.cpp b/libraries/plugins/apis/contract_api/contract_api.cpp index af81a1e6..f42d2955 100644 --- a/libraries/plugins/apis/contract_api/contract_api.cpp +++ b/libraries/plugins/apis/contract_api/contract_api.cpp @@ -64,10 +64,9 @@ machine::chain_adapter make_chain_adapter(chain::database& _db) return 0; }; - std::function< uint64_t(std::string) > get_balance = [&_db](std::string address) -> uint64_t + std::function< uint64_t(std::string) > get_balance = [](std::string address) -> uint64_t { - const auto& wallet = _db.get_account(address); - return static_cast(wallet.balance.amount.value); + return 0; }; std::function< std::string(std::string) > get_code_hash = [](std::string address) -> std::string @@ -90,12 +89,27 @@ machine::chain_adapter make_chain_adapter(chain::database& _db) return {}; }; - std::function< std::string(std::string, uint64_t, machine::big_word, std::vector) > contract_call = [](std::string address, uint64_t energy, machine::big_word value, std::vector args) -> std::string + std::function< std::vector(std::string, uint64_t, machine::big_word, std::vector) > contract_call = [](std::string address, uint64_t energy, machine::big_word value, std::vector args) -> std::vector + { + return {}; + }; + + std::function< std::vector(std::string, uint64_t, machine::big_word, std::vector) > contract_callcode = [](std::string address, uint64_t energy, machine::big_word value, std::vector args) -> std::vector + { + return {}; + }; + + std::function< std::vector(std::string, uint64_t, std::vector) > contract_delegatecall = [](std::string address, uint64_t energy, std::vector args) -> std::vector + { + return {}; + }; + + std::function< std::vector(std::string, uint64_t, std::vector) > contract_staticcall = [](std::string address, uint64_t energy, std::vector args) -> std::vector { return {}; }; - std::function< std::string(machine::big_word, std::vector, std::string) > contract_create2 = [](machine::big_word value, std::vector memory, std::string salt) -> std::string + std::function< std::string(std::vector, machine::big_word, std::string) > contract_create2 = [](std::vector memory, machine::big_word value, std::string salt) -> std::string { return {}; }; @@ -138,6 +152,9 @@ machine::chain_adapter make_chain_adapter(chain::database& _db) get_code_at_addr, contract_create, contract_call, + contract_callcode, + contract_delegatecall, + contract_staticcall, contract_create2, revert, access_storage, From b11acfe8157f59765142f60a359d15f47fa11093 Mon Sep 17 00:00:00 2001 From: Roger Jungemann Date: Fri, 20 Aug 2021 09:23:25 -0700 Subject: [PATCH 23/96] Link keccak library --- .../plugins/apis/contract_api/CMakeLists.txt | 4 +- .../apis/contract_api/contract_api.cpp | 10 + .../apis/contract_api/include/keccak256.h | 54 ++++ .../plugins/apis/contract_api/keccak256.c | 245 ++++++++++++++++++ 4 files changed, 311 insertions(+), 2 deletions(-) create mode 100644 libraries/plugins/apis/contract_api/include/keccak256.h create mode 100644 libraries/plugins/apis/contract_api/keccak256.c diff --git a/libraries/plugins/apis/contract_api/CMakeLists.txt b/libraries/plugins/apis/contract_api/CMakeLists.txt index 5eea5ad6..26c97202 100644 --- a/libraries/plugins/apis/contract_api/CMakeLists.txt +++ b/libraries/plugins/apis/contract_api/CMakeLists.txt @@ -1,5 +1,5 @@ -file( GLOB HEADERS "include/xgt/plugins/contract_api/*.hpp" ) -set( SOURCES contract_api.cpp contract_api_plugin.cpp ) +file( GLOB HEADERS "include/xgt/plugins/contract_api/*.hpp" "include/keccak256.h" ) +set( SOURCES contract_api.cpp contract_api_plugin.cpp keccak256.c ) add_library( contract_api_plugin ${SOURCES} ${HEADERS} ) diff --git a/libraries/plugins/apis/contract_api/contract_api.cpp b/libraries/plugins/apis/contract_api/contract_api.cpp index af81a1e6..351090cc 100644 --- a/libraries/plugins/apis/contract_api/contract_api.cpp +++ b/libraries/plugins/apis/contract_api/contract_api.cpp @@ -7,6 +7,8 @@ #include #include +#include "keccak256.h" + #include namespace xgt { namespace plugins { namespace contract { @@ -33,6 +35,14 @@ DEFINE_API_IMPL( contract_api_impl, get_contract ) machine::message msg = {}; ilog( "machine::message msg.flags ${f}", ("f",msg.flags) ); + // TODO: Temporary + std::string message = "testing"; + unsigned char output[32]; + SHA3_CTX ctx; + keccak_init(&ctx); + keccak_update(&ctx, (unsigned char*)message.c_str(), message.size()); + keccak_final(&ctx, output); + get_contract_return result; result.example = true; return result; diff --git a/libraries/plugins/apis/contract_api/include/keccak256.h b/libraries/plugins/apis/contract_api/include/keccak256.h new file mode 100644 index 00000000..c09b5e02 --- /dev/null +++ b/libraries/plugins/apis/contract_api/include/keccak256.h @@ -0,0 +1,54 @@ +/* sha3 - an implementation of Secure Hash Algorithm 3 (Keccak). + * based on the + * The Keccak SHA-3 submission. Submission to NIST (Round 3), 2011 + * by Guido Bertoni, Joan Daemen, Michaël Peeters and Gilles Van Assche + * + * Copyright: 2013 Aleksey Kravchenko + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so. + * + * 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. Use this program at your own risk! + */ + +#ifndef __KECCAK256_H_ +#define __KECCAK256_H_ + +#include + +#define sha3_max_permutation_size 25 +#define sha3_max_rate_in_qwords 24 + +typedef struct SHA3_CTX { + /* 1600 bits algorithm hashing state */ + uint64_t hash[sha3_max_permutation_size]; + /* 1536-bit buffer for leftovers */ + uint64_t message[sha3_max_rate_in_qwords]; + /* count of bytes in the message[] buffer */ + uint16_t rest; + /* size of a message block processed at once */ + //unsigned block_size; +} SHA3_CTX; + + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +void keccak_init(SHA3_CTX *ctx); +void keccak_update(SHA3_CTX *ctx, const unsigned char *msg, uint16_t size); +void keccak_final(SHA3_CTX *ctx, unsigned char* result); + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __KECCAK256_H_ */ diff --git a/libraries/plugins/apis/contract_api/keccak256.c b/libraries/plugins/apis/contract_api/keccak256.c new file mode 100644 index 00000000..f4e1f1de --- /dev/null +++ b/libraries/plugins/apis/contract_api/keccak256.c @@ -0,0 +1,245 @@ +/* sha3 - an implementation of Secure Hash Algorithm 3 (Keccak). + * based on the + * The Keccak SHA-3 submission. Submission to NIST (Round 3), 2011 + * by Guido Bertoni, Joan Daemen, Michaël Peeters and Gilles Van Assche + * + * Copyright: 2013 Aleksey Kravchenko + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so. + * + * 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. Use this program at your own risk! + */ + +#include "keccak256.h" + +//#include + +#include +#include + +#define BLOCK_SIZE ((1600 - 256 * 2) / 8) + +#define I64(x) x##LL +#define ROTL64(qword, n) ((qword) << (n) ^ ((qword) >> (64 - (n)))) +#define le2me_64(x) (x) +#define IS_ALIGNED_64(p) (0 == (7 & ((const char*)(p) - (const char*)0))) +#define me64_to_le_str(to, from, length) memcpy((to), (from), (length)) + +/* constants */ + +//const uint8_t round_constant_info[] PROGMEM = { +//const uint8_t constants[] PROGMEM = { +const uint8_t constants[] = { + + 1, 26, 94, 112, 31, 33, 121, 85, 14, 12, 53, 38, 63, 79, 93, 83, 82, 72, 22, 102, 121, 88, 33, 116, +//}; + +//const uint8_t pi_transform[] PROGMEM = { + 1, 6, 9, 22, 14, 20, 2, 12, 13, 19, 23, 15, 4, 24, 21, 8, 16, 5, 3, 18, 17, 11, 7, 10, +//}; + +//const uint8_t rhoTransforms[] PROGMEM = { + 1, 62, 28, 27, 36, 44, 6, 55, 20, 3, 10, 43, 25, 39, 41, 45, 15, 21, 8, 18, 2, 61, 56, 14, +}; + +#define TYPE_ROUND_INFO 0 +#define TYPE_PI_TRANSFORM 24 +#define TYPE_RHO_TRANSFORM 48 + +uint8_t getConstant(uint8_t type, uint8_t index) { + return constants[type + index]; + //return pgm_read_byte(&constants[type + index]); +} + +static uint64_t get_round_constant(uint8_t round) { + uint64_t result = 0; + + //uint8_t roundInfo = pgm_read_byte(&round_constant_info[round]); + uint8_t roundInfo = getConstant(TYPE_ROUND_INFO, round); + if (roundInfo & (1 << 6)) { result |= ((uint64_t)1 << 63); } + if (roundInfo & (1 << 5)) { result |= ((uint64_t)1 << 31); } + if (roundInfo & (1 << 4)) { result |= ((uint64_t)1 << 15); } + if (roundInfo & (1 << 3)) { result |= ((uint64_t)1 << 7); } + if (roundInfo & (1 << 2)) { result |= ((uint64_t)1 << 3); } + if (roundInfo & (1 << 1)) { result |= ((uint64_t)1 << 1); } + if (roundInfo & (1 << 0)) { result |= ((uint64_t)1 << 0); } + + return result; +} + + +/* Initializing a sha3 context for given number of output bits */ +void keccak_init(SHA3_CTX *ctx) { + /* NB: The Keccak capacity parameter = bits * 2 */ + + memset(ctx, 0, sizeof(SHA3_CTX)); +} + +/* Keccak theta() transformation */ +static void keccak_theta(uint64_t *A) { + uint64_t C[5], D[5]; + + for (uint8_t i = 0; i < 5; i++) { + C[i] = A[i]; + for (uint8_t j = 5; j < 25; j += 5) { C[i] ^= A[i + j]; } + } + + for (uint8_t i = 0; i < 5; i++) { + D[i] = ROTL64(C[(i + 1) % 5], 1) ^ C[(i + 4) % 5]; + } + + for (uint8_t i = 0; i < 5; i++) { + //for (uint8_t j = 0; j < 25; j += 5) { + for (uint8_t j = 0; j < 25; j += 5) { A[i + j] ^= D[i]; } + } +} + + +/* Keccak pi() transformation */ +static void keccak_pi(uint64_t *A) { + uint64_t A1 = A[1]; + //for (uint8_t i = 1; i < sizeof(pi_transform); i++) { + for (uint8_t i = 1; i < 24; i++) { + //A[pgm_read_byte(&pi_transform[i - 1])] = A[pgm_read_byte(&pi_transform[i])]; + A[getConstant(TYPE_PI_TRANSFORM, i - 1)] = A[getConstant(TYPE_PI_TRANSFORM, i)]; + } + A[10] = A1; + /* note: A[ 0] is left as is */ +} + +/* +ketch uses 30084 bytes (93%) of program storage space. Maximum is 32256 bytes. +Global variables use 743 bytes (36%) of dynamic memory, leaving 1305 bytes for local variables. Maximum is 2048 bytes. + +*/ +/* Keccak chi() transformation */ +static void keccak_chi(uint64_t *A) { + for (uint8_t i = 0; i < 25; i += 5) { + uint64_t A0 = A[0 + i], A1 = A[1 + i]; + A[0 + i] ^= ~A1 & A[2 + i]; + A[1 + i] ^= ~A[2 + i] & A[3 + i]; + A[2 + i] ^= ~A[3 + i] & A[4 + i]; + A[3 + i] ^= ~A[4 + i] & A0; + A[4 + i] ^= ~A0 & A1; + } +} + + +static void sha3_permutation(uint64_t *state) { + //for (uint8_t round = 0; round < sizeof(round_constant_info); round++) { + for (uint8_t round = 0; round < 24; round++) { + keccak_theta(state); + + /* apply Keccak rho() transformation */ + for (uint8_t i = 1; i < 25; i++) { + //state[i] = ROTL64(state[i], pgm_read_byte(&rhoTransforms[i - 1])); + state[i] = ROTL64(state[i], getConstant(TYPE_RHO_TRANSFORM, i - 1)); + } + + keccak_pi(state); + keccak_chi(state); + + /* apply iota(state, round) */ + *state ^= get_round_constant(round); + } +} + +/** + * The core transformation. Process the specified block of data. + * + * @param hash the algorithm state + * @param block the message block to process + * @param block_size the size of the processed block in bytes + */ +static void sha3_process_block(uint64_t hash[25], const uint64_t *block) { + for (uint8_t i = 0; i < 17; i++) { + hash[i] ^= le2me_64(block[i]); + } + + /* make a permutation of the hash */ + sha3_permutation(hash); +} + +//#define SHA3_FINALIZED 0x80000000 +//#define SHA3_FINALIZED 0x8000 + +/** + * Calculate message hash. + * Can be called repeatedly with chunks of the message to be hashed. + * + * @param ctx the algorithm context containing current hashing state + * @param msg message chunk + * @param size length of the message chunk + */ +void keccak_update(SHA3_CTX *ctx, const unsigned char *msg, uint16_t size) +{ + uint16_t idx = (uint16_t)ctx->rest; + + //if (ctx->rest & SHA3_FINALIZED) return; /* too late for additional input */ + ctx->rest = (unsigned)((ctx->rest + size) % BLOCK_SIZE); + + /* fill partial block */ + if (idx) { + uint16_t left = BLOCK_SIZE - idx; + memcpy((char*)ctx->message + idx, msg, (size < left ? size : left)); + if (size < left) return; + + /* process partial block */ + sha3_process_block(ctx->hash, ctx->message); + msg += left; + size -= left; + } + + while (size >= BLOCK_SIZE) { + uint64_t* aligned_message_block; + if (IS_ALIGNED_64(msg)) { + // the most common case is processing of an already aligned message without copying it + aligned_message_block = (uint64_t*)(void*)msg; + } else { + memcpy(ctx->message, msg, BLOCK_SIZE); + aligned_message_block = ctx->message; + } + + sha3_process_block(ctx->hash, aligned_message_block); + msg += BLOCK_SIZE; + size -= BLOCK_SIZE; + } + + if (size) { + memcpy(ctx->message, msg, size); /* save leftovers */ + } +} + +/** +* Store calculated hash into the given array. +* +* @param ctx the algorithm context containing current hashing state +* @param result calculated hash in binary form +*/ +void keccak_final(SHA3_CTX *ctx, unsigned char* result) +{ + uint16_t digest_length = 100 - BLOCK_SIZE / 2; + +// if (!(ctx->rest & SHA3_FINALIZED)) { + /* clear the rest of the data queue */ + memset((char*)ctx->message + ctx->rest, 0, BLOCK_SIZE - ctx->rest); + ((char*)ctx->message)[ctx->rest] |= 0x01; + ((char*)ctx->message)[BLOCK_SIZE - 1] |= 0x80; + + /* process final block */ + sha3_process_block(ctx->hash, ctx->message); +// ctx->rest = SHA3_FINALIZED; /* mark context as finalized */ +// } + + if (result) { + me64_to_le_str(result, ctx->hash, digest_length); + } +} + From d2e36d77d814436228e6018bcc3a24ca792a0f1c Mon Sep 17 00:00:00 2001 From: Roger Jungemann Date: Wed, 25 Aug 2021 13:07:09 -0700 Subject: [PATCH 24/96] Working hashing --- libraries/plugins/apis/contract_api/contract_api.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/libraries/plugins/apis/contract_api/contract_api.cpp b/libraries/plugins/apis/contract_api/contract_api.cpp index dc327208..91a59443 100644 --- a/libraries/plugins/apis/contract_api/contract_api.cpp +++ b/libraries/plugins/apis/contract_api/contract_api.cpp @@ -71,7 +71,14 @@ machine::chain_adapter make_chain_adapter(chain::database& _db) { std::function< std::string(std::vector) > sha3 = [](std::vector memory) -> std::string { - return 0; + std::string message(memory.begin(), memory.end()); + unsigned char output[32]; + SHA3_CTX ctx; + keccak_init(&ctx); + keccak_update(&ctx, (unsigned char*)message.c_str(), message.size()); + keccak_final(&ctx, output); + std::string fin((char*)output, 32); + return fin; }; std::function< uint64_t(std::string) > get_balance = [](std::string address) -> uint64_t From 9bd932fa33d958ebd5720ddea179ea528fe53509 Mon Sep 17 00:00:00 2001 From: Roger Jungemann Date: Thu, 26 Aug 2021 10:31:57 -0700 Subject: [PATCH 25/96] Add keccak to chain --- libraries/chain/CMakeLists.txt | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/libraries/chain/CMakeLists.txt b/libraries/chain/CMakeLists.txt index e4be93db..4f746329 100644 --- a/libraries/chain/CMakeLists.txt +++ b/libraries/chain/CMakeLists.txt @@ -1,4 +1,8 @@ -file(GLOB HEADERS "include/xgt/chain/*.hpp" "include/xgt/chain/util/*.hpp" "include/xgt/chain/xtt_objects/*.hpp") +file(GLOB HEADERS "include/xgt/chain/*.hpp" + "include/xgt/chain/util/*.hpp" + "include/xgt/chain/xtt_objects/*.hpp" + "include/keccak256.h" + ) ## SORT .cpp by most likely to change / break compile add_library( xgt_chain @@ -7,7 +11,7 @@ add_library( xgt_chain database.cpp index.cpp - machine.cpp + keccak256.c xtt_evaluator.cpp @@ -32,11 +36,14 @@ add_library( xgt_chain ${HEADERS} ) -target_link_libraries( xgt_chain xgt_protocol fc chainbase xgt_schema appbase mira +target_link_libraries( xgt_chain xgt_protocol fc chainbase xgt_schema appbase mira xgtvm ${PATCH_MERGE_LIB} ) target_include_directories( xgt_chain PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}" - PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" "${CMAKE_CURRENT_BINARY_DIR}/include" ) + PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" + "${CMAKE_CURRENT_BINARY_DIR}/include" + "${CMAKE_CURRENT_SOURCE_DIR}/../../../vendor/xgtvm/libraries" + ) if( CLANG_TIDY_EXE ) set_target_properties( From 4d8f9736ecb0c1fed8432ccdfaba97ac2bfcba6f Mon Sep 17 00:00:00 2001 From: Roger Jungemann Date: Thu, 26 Aug 2021 10:31:57 -0700 Subject: [PATCH 26/96] Add keccak to chain --- libraries/chain/CMakeLists.txt | 15 +- libraries/chain/include/keccak256.h | 54 ++++++ libraries/chain/keccak256.c | 245 ++++++++++++++++++++++++++++ 3 files changed, 310 insertions(+), 4 deletions(-) create mode 100644 libraries/chain/include/keccak256.h create mode 100644 libraries/chain/keccak256.c diff --git a/libraries/chain/CMakeLists.txt b/libraries/chain/CMakeLists.txt index e4be93db..4f746329 100644 --- a/libraries/chain/CMakeLists.txt +++ b/libraries/chain/CMakeLists.txt @@ -1,4 +1,8 @@ -file(GLOB HEADERS "include/xgt/chain/*.hpp" "include/xgt/chain/util/*.hpp" "include/xgt/chain/xtt_objects/*.hpp") +file(GLOB HEADERS "include/xgt/chain/*.hpp" + "include/xgt/chain/util/*.hpp" + "include/xgt/chain/xtt_objects/*.hpp" + "include/keccak256.h" + ) ## SORT .cpp by most likely to change / break compile add_library( xgt_chain @@ -7,7 +11,7 @@ add_library( xgt_chain database.cpp index.cpp - machine.cpp + keccak256.c xtt_evaluator.cpp @@ -32,11 +36,14 @@ add_library( xgt_chain ${HEADERS} ) -target_link_libraries( xgt_chain xgt_protocol fc chainbase xgt_schema appbase mira +target_link_libraries( xgt_chain xgt_protocol fc chainbase xgt_schema appbase mira xgtvm ${PATCH_MERGE_LIB} ) target_include_directories( xgt_chain PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}" - PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" "${CMAKE_CURRENT_BINARY_DIR}/include" ) + PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" + "${CMAKE_CURRENT_BINARY_DIR}/include" + "${CMAKE_CURRENT_SOURCE_DIR}/../../../vendor/xgtvm/libraries" + ) if( CLANG_TIDY_EXE ) set_target_properties( diff --git a/libraries/chain/include/keccak256.h b/libraries/chain/include/keccak256.h new file mode 100644 index 00000000..c09b5e02 --- /dev/null +++ b/libraries/chain/include/keccak256.h @@ -0,0 +1,54 @@ +/* sha3 - an implementation of Secure Hash Algorithm 3 (Keccak). + * based on the + * The Keccak SHA-3 submission. Submission to NIST (Round 3), 2011 + * by Guido Bertoni, Joan Daemen, Michaël Peeters and Gilles Van Assche + * + * Copyright: 2013 Aleksey Kravchenko + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so. + * + * 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. Use this program at your own risk! + */ + +#ifndef __KECCAK256_H_ +#define __KECCAK256_H_ + +#include + +#define sha3_max_permutation_size 25 +#define sha3_max_rate_in_qwords 24 + +typedef struct SHA3_CTX { + /* 1600 bits algorithm hashing state */ + uint64_t hash[sha3_max_permutation_size]; + /* 1536-bit buffer for leftovers */ + uint64_t message[sha3_max_rate_in_qwords]; + /* count of bytes in the message[] buffer */ + uint16_t rest; + /* size of a message block processed at once */ + //unsigned block_size; +} SHA3_CTX; + + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +void keccak_init(SHA3_CTX *ctx); +void keccak_update(SHA3_CTX *ctx, const unsigned char *msg, uint16_t size); +void keccak_final(SHA3_CTX *ctx, unsigned char* result); + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __KECCAK256_H_ */ diff --git a/libraries/chain/keccak256.c b/libraries/chain/keccak256.c new file mode 100644 index 00000000..f4e1f1de --- /dev/null +++ b/libraries/chain/keccak256.c @@ -0,0 +1,245 @@ +/* sha3 - an implementation of Secure Hash Algorithm 3 (Keccak). + * based on the + * The Keccak SHA-3 submission. Submission to NIST (Round 3), 2011 + * by Guido Bertoni, Joan Daemen, Michaël Peeters and Gilles Van Assche + * + * Copyright: 2013 Aleksey Kravchenko + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so. + * + * 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. Use this program at your own risk! + */ + +#include "keccak256.h" + +//#include + +#include +#include + +#define BLOCK_SIZE ((1600 - 256 * 2) / 8) + +#define I64(x) x##LL +#define ROTL64(qword, n) ((qword) << (n) ^ ((qword) >> (64 - (n)))) +#define le2me_64(x) (x) +#define IS_ALIGNED_64(p) (0 == (7 & ((const char*)(p) - (const char*)0))) +#define me64_to_le_str(to, from, length) memcpy((to), (from), (length)) + +/* constants */ + +//const uint8_t round_constant_info[] PROGMEM = { +//const uint8_t constants[] PROGMEM = { +const uint8_t constants[] = { + + 1, 26, 94, 112, 31, 33, 121, 85, 14, 12, 53, 38, 63, 79, 93, 83, 82, 72, 22, 102, 121, 88, 33, 116, +//}; + +//const uint8_t pi_transform[] PROGMEM = { + 1, 6, 9, 22, 14, 20, 2, 12, 13, 19, 23, 15, 4, 24, 21, 8, 16, 5, 3, 18, 17, 11, 7, 10, +//}; + +//const uint8_t rhoTransforms[] PROGMEM = { + 1, 62, 28, 27, 36, 44, 6, 55, 20, 3, 10, 43, 25, 39, 41, 45, 15, 21, 8, 18, 2, 61, 56, 14, +}; + +#define TYPE_ROUND_INFO 0 +#define TYPE_PI_TRANSFORM 24 +#define TYPE_RHO_TRANSFORM 48 + +uint8_t getConstant(uint8_t type, uint8_t index) { + return constants[type + index]; + //return pgm_read_byte(&constants[type + index]); +} + +static uint64_t get_round_constant(uint8_t round) { + uint64_t result = 0; + + //uint8_t roundInfo = pgm_read_byte(&round_constant_info[round]); + uint8_t roundInfo = getConstant(TYPE_ROUND_INFO, round); + if (roundInfo & (1 << 6)) { result |= ((uint64_t)1 << 63); } + if (roundInfo & (1 << 5)) { result |= ((uint64_t)1 << 31); } + if (roundInfo & (1 << 4)) { result |= ((uint64_t)1 << 15); } + if (roundInfo & (1 << 3)) { result |= ((uint64_t)1 << 7); } + if (roundInfo & (1 << 2)) { result |= ((uint64_t)1 << 3); } + if (roundInfo & (1 << 1)) { result |= ((uint64_t)1 << 1); } + if (roundInfo & (1 << 0)) { result |= ((uint64_t)1 << 0); } + + return result; +} + + +/* Initializing a sha3 context for given number of output bits */ +void keccak_init(SHA3_CTX *ctx) { + /* NB: The Keccak capacity parameter = bits * 2 */ + + memset(ctx, 0, sizeof(SHA3_CTX)); +} + +/* Keccak theta() transformation */ +static void keccak_theta(uint64_t *A) { + uint64_t C[5], D[5]; + + for (uint8_t i = 0; i < 5; i++) { + C[i] = A[i]; + for (uint8_t j = 5; j < 25; j += 5) { C[i] ^= A[i + j]; } + } + + for (uint8_t i = 0; i < 5; i++) { + D[i] = ROTL64(C[(i + 1) % 5], 1) ^ C[(i + 4) % 5]; + } + + for (uint8_t i = 0; i < 5; i++) { + //for (uint8_t j = 0; j < 25; j += 5) { + for (uint8_t j = 0; j < 25; j += 5) { A[i + j] ^= D[i]; } + } +} + + +/* Keccak pi() transformation */ +static void keccak_pi(uint64_t *A) { + uint64_t A1 = A[1]; + //for (uint8_t i = 1; i < sizeof(pi_transform); i++) { + for (uint8_t i = 1; i < 24; i++) { + //A[pgm_read_byte(&pi_transform[i - 1])] = A[pgm_read_byte(&pi_transform[i])]; + A[getConstant(TYPE_PI_TRANSFORM, i - 1)] = A[getConstant(TYPE_PI_TRANSFORM, i)]; + } + A[10] = A1; + /* note: A[ 0] is left as is */ +} + +/* +ketch uses 30084 bytes (93%) of program storage space. Maximum is 32256 bytes. +Global variables use 743 bytes (36%) of dynamic memory, leaving 1305 bytes for local variables. Maximum is 2048 bytes. + +*/ +/* Keccak chi() transformation */ +static void keccak_chi(uint64_t *A) { + for (uint8_t i = 0; i < 25; i += 5) { + uint64_t A0 = A[0 + i], A1 = A[1 + i]; + A[0 + i] ^= ~A1 & A[2 + i]; + A[1 + i] ^= ~A[2 + i] & A[3 + i]; + A[2 + i] ^= ~A[3 + i] & A[4 + i]; + A[3 + i] ^= ~A[4 + i] & A0; + A[4 + i] ^= ~A0 & A1; + } +} + + +static void sha3_permutation(uint64_t *state) { + //for (uint8_t round = 0; round < sizeof(round_constant_info); round++) { + for (uint8_t round = 0; round < 24; round++) { + keccak_theta(state); + + /* apply Keccak rho() transformation */ + for (uint8_t i = 1; i < 25; i++) { + //state[i] = ROTL64(state[i], pgm_read_byte(&rhoTransforms[i - 1])); + state[i] = ROTL64(state[i], getConstant(TYPE_RHO_TRANSFORM, i - 1)); + } + + keccak_pi(state); + keccak_chi(state); + + /* apply iota(state, round) */ + *state ^= get_round_constant(round); + } +} + +/** + * The core transformation. Process the specified block of data. + * + * @param hash the algorithm state + * @param block the message block to process + * @param block_size the size of the processed block in bytes + */ +static void sha3_process_block(uint64_t hash[25], const uint64_t *block) { + for (uint8_t i = 0; i < 17; i++) { + hash[i] ^= le2me_64(block[i]); + } + + /* make a permutation of the hash */ + sha3_permutation(hash); +} + +//#define SHA3_FINALIZED 0x80000000 +//#define SHA3_FINALIZED 0x8000 + +/** + * Calculate message hash. + * Can be called repeatedly with chunks of the message to be hashed. + * + * @param ctx the algorithm context containing current hashing state + * @param msg message chunk + * @param size length of the message chunk + */ +void keccak_update(SHA3_CTX *ctx, const unsigned char *msg, uint16_t size) +{ + uint16_t idx = (uint16_t)ctx->rest; + + //if (ctx->rest & SHA3_FINALIZED) return; /* too late for additional input */ + ctx->rest = (unsigned)((ctx->rest + size) % BLOCK_SIZE); + + /* fill partial block */ + if (idx) { + uint16_t left = BLOCK_SIZE - idx; + memcpy((char*)ctx->message + idx, msg, (size < left ? size : left)); + if (size < left) return; + + /* process partial block */ + sha3_process_block(ctx->hash, ctx->message); + msg += left; + size -= left; + } + + while (size >= BLOCK_SIZE) { + uint64_t* aligned_message_block; + if (IS_ALIGNED_64(msg)) { + // the most common case is processing of an already aligned message without copying it + aligned_message_block = (uint64_t*)(void*)msg; + } else { + memcpy(ctx->message, msg, BLOCK_SIZE); + aligned_message_block = ctx->message; + } + + sha3_process_block(ctx->hash, aligned_message_block); + msg += BLOCK_SIZE; + size -= BLOCK_SIZE; + } + + if (size) { + memcpy(ctx->message, msg, size); /* save leftovers */ + } +} + +/** +* Store calculated hash into the given array. +* +* @param ctx the algorithm context containing current hashing state +* @param result calculated hash in binary form +*/ +void keccak_final(SHA3_CTX *ctx, unsigned char* result) +{ + uint16_t digest_length = 100 - BLOCK_SIZE / 2; + +// if (!(ctx->rest & SHA3_FINALIZED)) { + /* clear the rest of the data queue */ + memset((char*)ctx->message + ctx->rest, 0, BLOCK_SIZE - ctx->rest); + ((char*)ctx->message)[ctx->rest] |= 0x01; + ((char*)ctx->message)[BLOCK_SIZE - 1] |= 0x80; + + /* process final block */ + sha3_process_block(ctx->hash, ctx->message); +// ctx->rest = SHA3_FINALIZED; /* mark context as finalized */ +// } + + if (result) { + me64_to_le_str(result, ctx->hash, digest_length); + } +} + From e430fae1c3655b32540047c1423e9c79e9cc37ce Mon Sep 17 00:00:00 2001 From: Roger Jungemann Date: Fri, 27 Aug 2021 13:46:31 -0700 Subject: [PATCH 27/96] Continue to integrate xgtvm with chain --- libraries/chain/CMakeLists.txt | 2 +- .../chain/include/xgt/chain/database.hpp | 1 - libraries/chain/include/xgt/chain/machine.hpp | 84 ------------ libraries/chain/machine.cpp | 40 ------ libraries/chain/xgt_evaluator.cpp | 121 +++++++++++++++++- 5 files changed, 121 insertions(+), 127 deletions(-) delete mode 100644 libraries/chain/include/xgt/chain/machine.hpp delete mode 100644 libraries/chain/machine.cpp diff --git a/libraries/chain/CMakeLists.txt b/libraries/chain/CMakeLists.txt index 4f746329..bcfabf20 100644 --- a/libraries/chain/CMakeLists.txt +++ b/libraries/chain/CMakeLists.txt @@ -42,7 +42,7 @@ target_include_directories( xgt_chain PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}" PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" "${CMAKE_CURRENT_BINARY_DIR}/include" - "${CMAKE_CURRENT_SOURCE_DIR}/../../../vendor/xgtvm/libraries" + "${CMAKE_CURRENT_SOURCE_DIR}/../vendor/xgtvm/libraries" ) if( CLANG_TIDY_EXE ) diff --git a/libraries/chain/include/xgt/chain/database.hpp b/libraries/chain/include/xgt/chain/database.hpp index 145b410b..e6a6bb09 100644 --- a/libraries/chain/include/xgt/chain/database.hpp +++ b/libraries/chain/include/xgt/chain/database.hpp @@ -10,7 +10,6 @@ #include #include #include -#include #include #include diff --git a/libraries/chain/include/xgt/chain/machine.hpp b/libraries/chain/include/xgt/chain/machine.hpp deleted file mode 100644 index e5e160e8..00000000 --- a/libraries/chain/include/xgt/chain/machine.hpp +++ /dev/null @@ -1,84 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -namespace xgt { namespace chain { - - namespace detail { class machine_impl; } - - typedef uint8_t machine_word; - typedef uint64_t machine_big_word; - typedef uint64_t machine_address; - - enum class machine_opcode { - stop_opcode = 0x00, - add_opcode = 0x01, - mul_opcode = 0x02, - sub_opcode = 0x03, - div_opcode = 0x04, - sdiv_opcode = 0x05, - mod_opcode = 0x06, - smod_opcode = 0x07, - // TODO: addmod 0x08 - // TODO: mulmod 0x09 - // TODO: exp 0x0a - // TODO: signextend 0x0b - lt_opcode = 0x10, - gt_opcode = 0x11, - // TODO: slt 0x12 - // TODO: sgt 0x13 - // TODO: eq 0x14 - // TODO: iszero 0x15 - // TODO: Gap... - timestamp_opcode = 0x42, - // TODO: Gap... - jumpi_opcode = 0x57, - // TODO: Gap... - mload_opcode = 0x51, - mstore_opcode = 0x52, - // TODO: Gap... - jumpdest_opcode = 0x5b, - // TODO: Gap... - push1_opcode = 0x60, - push2_opcode = 0x61, - push3_opcode = 0x62, - push4_opcode = 0x63, - // TODO: Gap... - dup1_opcode = 0x80, - // TODO: Gap... - swap1_opcode = 0x90, - swap2_opcode = 0x91, - swap3_opcode = 0x92, - swap4_opcode = 0x93, - // TODO: Gap... - return_opcode = 0xf3, - // TODO: Gap... - }; - - enum class machine_state { - stopped, - running, - error - }; - - struct machine_context - { - bool is_debug; - uint64_t block_timestamp; - }; - - struct machine { - - machine(machine_context ctx, std::vector code); - ~machine(); - - std::unique_ptr my; - - void step(); - - }; - -} } diff --git a/libraries/chain/machine.cpp b/libraries/chain/machine.cpp deleted file mode 100644 index 0f474e11..00000000 --- a/libraries/chain/machine.cpp +++ /dev/null @@ -1,40 +0,0 @@ -#include "xgt/chain/machine.hpp" - -namespace xgt { namespace chain { - namespace detail { - class machine_impl { - public: - machine_impl( machine& self, machine_context ctx, std::vector code ) - : _self(self), ctx(ctx), code(code), pc(0), state(machine_state::running) - { - - } - - void step() - { - } - - machine& _self; - machine_context ctx; - std::vector code; - machine_address pc; - std::deque stack; - machine_state state; - }; - } - - machine::machine( machine_context ctx, std::vector code ) - : my ( new detail::machine_impl(*this, ctx, code) ) - { - - } - - machine::~machine() - { - } - - void machine::step() - { - my->step(); - } -} } // xgt::chain diff --git a/libraries/chain/xgt_evaluator.cpp b/libraries/chain/xgt_evaluator.cpp index 03dae1ce..afd259bd 100644 --- a/libraries/chain/xgt_evaluator.cpp +++ b/libraries/chain/xgt_evaluator.cpp @@ -9,7 +9,9 @@ #include #include #include -#include + +#include "keccak256.h" +#include #include @@ -1027,6 +1029,123 @@ void contract_create_evaluator::do_apply( const contract_create_operation& op ) }); } +machine::chain_adapter make_chain_adapter(chain::database& _db) +{ + std::function< std::string(std::vector) > sha3 = [](std::vector memory) -> std::string + { + std::string message(memory.begin(), memory.end()); + unsigned char output[32]; + SHA3_CTX ctx; + keccak_init(&ctx); + keccak_update(&ctx, (unsigned char*)message.c_str(), message.size()); + keccak_final(&ctx, output); + std::string fin((char*)output, 32); + return fin; + }; + + std::function< uint64_t(std::string) > get_balance = [](std::string address) -> uint64_t + { + return 0; + }; + + std::function< std::string(std::string) > get_code_hash = [](std::string address) -> std::string + { + return ""; + }; + + std::function< std::string(uint64_t) > get_block_hash = [](uint64_t block_num) -> std::string + { + return ""; + }; + + std::function< std::vector(std::string) > get_code_at_addr = [](std::string address) -> std::vector + { + return {}; + }; + + std::function< std::string(std::vector, machine::big_word) > contract_create = [](std::vector memory, machine::big_word value) -> std::string + { + return {}; + }; + + std::function< std::vector(std::string, uint64_t, machine::big_word, std::vector) > contract_call = [](std::string address, uint64_t energy, machine::big_word value, std::vector args) -> std::vector + { + return {}; + }; + + std::function< std::vector(std::string, uint64_t, machine::big_word, std::vector) > contract_callcode = [](std::string address, uint64_t energy, machine::big_word value, std::vector args) -> std::vector + { + return {}; + }; + + std::function< std::vector(std::string, uint64_t, std::vector) > contract_delegatecall = [](std::string address, uint64_t energy, std::vector args) -> std::vector + { + return {}; + }; + + std::function< std::vector(std::string, uint64_t, std::vector) > contract_staticcall = [](std::string address, uint64_t energy, std::vector args) -> std::vector + { + return {}; + }; + + std::function< std::string(std::vector, machine::big_word, std::string) > contract_create2 = [](std::vector memory, machine::big_word value, std::string salt) -> std::string + { + return {}; + }; + + std::function< bool(std::vector) > revert = [](std::vector memory) -> bool + { + return {}; + }; + + std::function< machine::big_word(std::string) > access_storage = [](std::string key) -> machine::big_word + { + return {}; + }; + + std::function< bool(std::string, std::string, machine::big_word) > set_storage = [](std::string destination, std::string key, machine::big_word value) -> bool + { + return {}; + }; + + std::function< bool(std::vector) > contract_return = [](std::vector memory) -> bool + { + return {}; + }; + + std::function< bool(std::string) > self_destruct = [](std::string address) -> bool + { + return {}; + }; + + std::function< std::vector(std::string) > get_input_data = [](std::string address) -> std::vector + { + return {}; + }; + + machine::chain_adapter adapter = { + sha3, + get_balance, + get_code_hash, + get_block_hash, + get_code_at_addr, + contract_create, + contract_call, + contract_callcode, + contract_delegatecall, + contract_staticcall, + contract_create2, + revert, + access_storage, + set_storage, + contract_return, + self_destruct, + get_input_data + }; + + return adapter; +} + void contract_invoke_evaluator::do_apply( const contract_invoke_operation& op ) { wlog("contract_invoke ${w}", ("w",op.contract_hash)); From 8974e83c0931f6d7a3e284834b162225621a6d3c Mon Sep 17 00:00:00 2001 From: Liam Noroian Date: Mon, 30 Aug 2021 11:06:45 -0700 Subject: [PATCH 28/96] WIP --- Rakefile | 6 +++++- .../apis/contract_api/contract_api.cpp | 21 +++++++++++++++++++ .../xgt/plugins/p2p/p2p_default_seeds.hpp | 8 ------- libraries/plugins/p2p/p2p_plugin.cpp | 5 +++++ 4 files changed, 31 insertions(+), 9 deletions(-) diff --git a/Rakefile b/Rakefile index 38825581..e7896fea 100644 --- a/Rakefile +++ b/Rakefile @@ -67,7 +67,7 @@ def witness_private_key end def host - ENV['XGT_HOST'] || 'http://localhost:8751' + ENV['XGT_HOST'] || 'http://localhost:8799' end def seed_hosts @@ -295,11 +295,15 @@ task :run do enable-stale-production = #{mining_disabled? ? 'false' : 'true'} ))) +<<<<<<< Updated upstream if from_genesis? f.puts "p2p-seed-node = " elsif seed_hosts && seed_hosts.any? f.puts "p2p-seed-node = #{seed_hosts.join(" ")}" end +======= + f.puts "p2p-seed-node = " +>>>>>>> Stashed changes end $stderr.puts(File.read("#{data_dir}/config.ini")) diff --git a/libraries/plugins/apis/contract_api/contract_api.cpp b/libraries/plugins/apis/contract_api/contract_api.cpp index 91a59443..682640d1 100644 --- a/libraries/plugins/apis/contract_api/contract_api.cpp +++ b/libraries/plugins/apis/contract_api/contract_api.cpp @@ -107,6 +107,7 @@ machine::chain_adapter make_chain_adapter(chain::database& _db) }; std::function< std::vector(std::string, uint64_t, machine::big_word, std::vector) > contract_call = [](std::string address, uint64_t energy, machine::big_word value, std::vector args) -> std::vector +<<<<<<< Updated upstream { return {}; }; @@ -122,10 +123,30 @@ machine::chain_adapter make_chain_adapter(chain::database& _db) }; std::function< std::vector(std::string, uint64_t, std::vector) > contract_staticcall = [](std::string address, uint64_t energy, std::vector args) -> std::vector +======= +>>>>>>> Stashed changes { return {}; }; +<<<<<<< Updated upstream +======= + std::function< std::vector(std::string, uint64_t, machine::big_word, std::vector) > contract_callcode = [](std::string address, uint64_t energy, machine::big_word value, std::vector args) -> std::vector + { + return {}; + }; + + std::function< std::vector(std::string, uint64_t, std::vector) > contract_delegatecall = [](std::string address, uint64_t energy, std::vector args) -> std::vector + { + return {}; + }; + + std::function< std::vector(std::string, uint64_t, std::vector) > contract_staticcall = [](std::string address, uint64_t energy, std::vector args) -> std::vector + { + return {}; + }; + +>>>>>>> Stashed changes std::function< std::string(std::vector, machine::big_word, std::string) > contract_create2 = [](std::vector memory, machine::big_word value, std::string salt) -> std::string { return {}; diff --git a/libraries/plugins/p2p/include/xgt/plugins/p2p/p2p_default_seeds.hpp b/libraries/plugins/p2p/include/xgt/plugins/p2p/p2p_default_seeds.hpp index d36c5131..9d55ddd9 100644 --- a/libraries/plugins/p2p/include/xgt/plugins/p2p/p2p_default_seeds.hpp +++ b/libraries/plugins/p2p/include/xgt/plugins/p2p/p2p_default_seeds.hpp @@ -9,14 +9,6 @@ namespace xgt{ namespace plugins { namespace p2p { const std::vector< std::string > default_seeds; #else const std::vector< std::string > default_seeds = { - "xgt.rag.pub:2001", - "xgt2.rag.pub:2001", - "68.129.31.2:2001", - "95.216.69.92:2001", - "95.216.71.199:2001", - "98.33.76.100:2001", - "116.202.114.157:2001", - "195.201.167.19:2001" }; #endif diff --git a/libraries/plugins/p2p/p2p_plugin.cpp b/libraries/plugins/p2p/p2p_plugin.cpp index 21af6f18..4e61e263 100644 --- a/libraries/plugins/p2p/p2p_plugin.cpp +++ b/libraries/plugins/p2p/p2p_plugin.cpp @@ -578,6 +578,11 @@ void p2p_plugin::plugin_initialize(const boost::program_options::variables_map& { my = std::make_unique< detail::p2p_plugin_impl >( appbase::app().get_plugin< plugins::chain::chain_plugin >() ); +<<<<<<< Updated upstream +======= + my->ready_to_mine = true; + +>>>>>>> Stashed changes if( options.count( "p2p-endpoint" ) ) my->endpoint = fc::ip::endpoint::from_string( options.at( "p2p-endpoint" ).as< string >() ); From 011cf262239113330b151865738b764e7650f1cf Mon Sep 17 00:00:00 2001 From: Liam Noroian Date: Mon, 30 Aug 2021 11:07:20 -0700 Subject: [PATCH 29/96] WIP --- Rakefile | 4 ++++ .../apis/contract_api/contract_api.cpp | 21 +++++++++++++++++++ libraries/plugins/p2p/p2p_plugin.cpp | 3 +++ 3 files changed, 28 insertions(+) diff --git a/Rakefile b/Rakefile index e7896fea..de3da7a0 100644 --- a/Rakefile +++ b/Rakefile @@ -295,12 +295,16 @@ task :run do enable-stale-production = #{mining_disabled? ? 'false' : 'true'} ))) +<<<<<<< Updated upstream <<<<<<< Updated upstream if from_genesis? f.puts "p2p-seed-node = " elsif seed_hosts && seed_hosts.any? f.puts "p2p-seed-node = #{seed_hosts.join(" ")}" end +======= + f.puts "p2p-seed-node = " +>>>>>>> Stashed changes ======= f.puts "p2p-seed-node = " >>>>>>> Stashed changes diff --git a/libraries/plugins/apis/contract_api/contract_api.cpp b/libraries/plugins/apis/contract_api/contract_api.cpp index 682640d1..6687256d 100644 --- a/libraries/plugins/apis/contract_api/contract_api.cpp +++ b/libraries/plugins/apis/contract_api/contract_api.cpp @@ -107,6 +107,7 @@ machine::chain_adapter make_chain_adapter(chain::database& _db) }; std::function< std::vector(std::string, uint64_t, machine::big_word, std::vector) > contract_call = [](std::string address, uint64_t energy, machine::big_word value, std::vector args) -> std::vector +<<<<<<< Updated upstream <<<<<<< Updated upstream { return {}; @@ -141,6 +142,26 @@ machine::chain_adapter make_chain_adapter(chain::database& _db) return {}; }; + std::function< std::vector(std::string, uint64_t, std::vector) > contract_staticcall = [](std::string address, uint64_t energy, std::vector args) -> std::vector +======= +>>>>>>> Stashed changes + { + return {}; + }; + +<<<<<<< Updated upstream +>>>>>>> Stashed changes +======= + std::function< std::vector(std::string, uint64_t, machine::big_word, std::vector) > contract_callcode = [](std::string address, uint64_t energy, machine::big_word value, std::vector args) -> std::vector + { + return {}; + }; + + std::function< std::vector(std::string, uint64_t, std::vector) > contract_delegatecall = [](std::string address, uint64_t energy, std::vector args) -> std::vector + { + return {}; + }; + std::function< std::vector(std::string, uint64_t, std::vector) > contract_staticcall = [](std::string address, uint64_t energy, std::vector args) -> std::vector { return {}; diff --git a/libraries/plugins/p2p/p2p_plugin.cpp b/libraries/plugins/p2p/p2p_plugin.cpp index 4e61e263..b9ccb6e1 100644 --- a/libraries/plugins/p2p/p2p_plugin.cpp +++ b/libraries/plugins/p2p/p2p_plugin.cpp @@ -579,7 +579,10 @@ void p2p_plugin::plugin_initialize(const boost::program_options::variables_map& my = std::make_unique< detail::p2p_plugin_impl >( appbase::app().get_plugin< plugins::chain::chain_plugin >() ); <<<<<<< Updated upstream +<<<<<<< Updated upstream +======= ======= +>>>>>>> Stashed changes my->ready_to_mine = true; >>>>>>> Stashed changes From eaf2773668185d88fa689071d7f074c600790af4 Mon Sep 17 00:00:00 2001 From: Liam Noroian Date: Mon, 30 Aug 2021 11:10:04 -0700 Subject: [PATCH 30/96] WIP --- Rakefile | 7 ------- 1 file changed, 7 deletions(-) diff --git a/Rakefile b/Rakefile index de3da7a0..c9964ea0 100644 --- a/Rakefile +++ b/Rakefile @@ -295,19 +295,12 @@ task :run do enable-stale-production = #{mining_disabled? ? 'false' : 'true'} ))) -<<<<<<< Updated upstream -<<<<<<< Updated upstream if from_genesis? f.puts "p2p-seed-node = " elsif seed_hosts && seed_hosts.any? f.puts "p2p-seed-node = #{seed_hosts.join(" ")}" end -======= f.puts "p2p-seed-node = " ->>>>>>> Stashed changes -======= - f.puts "p2p-seed-node = " ->>>>>>> Stashed changes end $stderr.puts(File.read("#{data_dir}/config.ini")) From f490df3ddef4410ce4cfd6a6046a4e1c49e38eda Mon Sep 17 00:00:00 2001 From: Liam Noroian Date: Mon, 30 Aug 2021 11:13:19 -0700 Subject: [PATCH 31/96] WIP --- .../apis/contract_api/contract_api.cpp | 42 ------------------- libraries/plugins/p2p/p2p_plugin.cpp | 6 --- 2 files changed, 48 deletions(-) diff --git a/libraries/plugins/apis/contract_api/contract_api.cpp b/libraries/plugins/apis/contract_api/contract_api.cpp index 6687256d..91a59443 100644 --- a/libraries/plugins/apis/contract_api/contract_api.cpp +++ b/libraries/plugins/apis/contract_api/contract_api.cpp @@ -107,8 +107,6 @@ machine::chain_adapter make_chain_adapter(chain::database& _db) }; std::function< std::vector(std::string, uint64_t, machine::big_word, std::vector) > contract_call = [](std::string address, uint64_t energy, machine::big_word value, std::vector args) -> std::vector -<<<<<<< Updated upstream -<<<<<<< Updated upstream { return {}; }; @@ -124,50 +122,10 @@ machine::chain_adapter make_chain_adapter(chain::database& _db) }; std::function< std::vector(std::string, uint64_t, std::vector) > contract_staticcall = [](std::string address, uint64_t energy, std::vector args) -> std::vector -======= ->>>>>>> Stashed changes { return {}; }; -<<<<<<< Updated upstream -======= - std::function< std::vector(std::string, uint64_t, machine::big_word, std::vector) > contract_callcode = [](std::string address, uint64_t energy, machine::big_word value, std::vector args) -> std::vector - { - return {}; - }; - - std::function< std::vector(std::string, uint64_t, std::vector) > contract_delegatecall = [](std::string address, uint64_t energy, std::vector args) -> std::vector - { - return {}; - }; - - std::function< std::vector(std::string, uint64_t, std::vector) > contract_staticcall = [](std::string address, uint64_t energy, std::vector args) -> std::vector -======= ->>>>>>> Stashed changes - { - return {}; - }; - -<<<<<<< Updated upstream ->>>>>>> Stashed changes -======= - std::function< std::vector(std::string, uint64_t, machine::big_word, std::vector) > contract_callcode = [](std::string address, uint64_t energy, machine::big_word value, std::vector args) -> std::vector - { - return {}; - }; - - std::function< std::vector(std::string, uint64_t, std::vector) > contract_delegatecall = [](std::string address, uint64_t energy, std::vector args) -> std::vector - { - return {}; - }; - - std::function< std::vector(std::string, uint64_t, std::vector) > contract_staticcall = [](std::string address, uint64_t energy, std::vector args) -> std::vector - { - return {}; - }; - ->>>>>>> Stashed changes std::function< std::string(std::vector, machine::big_word, std::string) > contract_create2 = [](std::vector memory, machine::big_word value, std::string salt) -> std::string { return {}; diff --git a/libraries/plugins/p2p/p2p_plugin.cpp b/libraries/plugins/p2p/p2p_plugin.cpp index b9ccb6e1..3022e54a 100644 --- a/libraries/plugins/p2p/p2p_plugin.cpp +++ b/libraries/plugins/p2p/p2p_plugin.cpp @@ -578,14 +578,8 @@ void p2p_plugin::plugin_initialize(const boost::program_options::variables_map& { my = std::make_unique< detail::p2p_plugin_impl >( appbase::app().get_plugin< plugins::chain::chain_plugin >() ); -<<<<<<< Updated upstream -<<<<<<< Updated upstream -======= -======= ->>>>>>> Stashed changes my->ready_to_mine = true; ->>>>>>> Stashed changes if( options.count( "p2p-endpoint" ) ) my->endpoint = fc::ip::endpoint::from_string( options.at( "p2p-endpoint" ).as< string >() ); From 1993fd7d6bfabc9dfdfcea3682400509badca597 Mon Sep 17 00:00:00 2001 From: Liam Noroian Date: Mon, 30 Aug 2021 11:20:51 -0700 Subject: [PATCH 32/96] adding back get_balance --- libraries/plugins/apis/contract_api/contract_api.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/plugins/apis/contract_api/contract_api.cpp b/libraries/plugins/apis/contract_api/contract_api.cpp index 91a59443..2d8e50b7 100644 --- a/libraries/plugins/apis/contract_api/contract_api.cpp +++ b/libraries/plugins/apis/contract_api/contract_api.cpp @@ -83,7 +83,8 @@ machine::chain_adapter make_chain_adapter(chain::database& _db) std::function< uint64_t(std::string) > get_balance = [](std::string address) -> uint64_t { - return 0; + auto& wallet = _db.get_account(address); + return static_cast(wallet.balance.amount.value); }; std::function< std::string(std::string) > get_code_hash = [](std::string address) -> std::string From 065b0774931fd1e5c881f204ad74e0a1c5e53b7c Mon Sep 17 00:00:00 2001 From: Liam Noroian Date: Mon, 30 Aug 2021 11:24:30 -0700 Subject: [PATCH 33/96] Adding get_balance to xgt_evaluator --- libraries/chain/xgt_evaluator.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/chain/xgt_evaluator.cpp b/libraries/chain/xgt_evaluator.cpp index afd259bd..e2b66869 100644 --- a/libraries/chain/xgt_evaluator.cpp +++ b/libraries/chain/xgt_evaluator.cpp @@ -1045,7 +1045,8 @@ machine::chain_adapter make_chain_adapter(chain::database& _db) std::function< uint64_t(std::string) > get_balance = [](std::string address) -> uint64_t { - return 0; + auto& wallet = _db.get_account(address); + return static_cast(wallet.balance.amount.value); }; std::function< std::string(std::string) > get_code_hash = [](std::string address) -> std::string From c46df769be6bf87c42eb50d70a3b789097f9c066 Mon Sep 17 00:00:00 2001 From: Liam Noroian Date: Mon, 30 Aug 2021 12:05:57 -0700 Subject: [PATCH 34/96] WIP outlining adapter methods --- libraries/chain/xgt_evaluator.cpp | 37 ++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/libraries/chain/xgt_evaluator.cpp b/libraries/chain/xgt_evaluator.cpp index e2b66869..19b00b1c 100644 --- a/libraries/chain/xgt_evaluator.cpp +++ b/libraries/chain/xgt_evaluator.cpp @@ -1029,7 +1029,7 @@ void contract_create_evaluator::do_apply( const contract_create_operation& op ) }); } -machine::chain_adapter make_chain_adapter(chain::database& _db) +machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type owner) { std::function< std::string(std::vector) > sha3 = [](std::vector memory) -> std::string { @@ -1051,37 +1051,61 @@ machine::chain_adapter make_chain_adapter(chain::database& _db) std::function< std::string(std::string) > get_code_hash = [](std::string address) -> std::string { + // TODO Get sha3 hash of contract code at addr return ""; }; + // ripemd160 -- store as uint256 std::function< std::string(uint64_t) > get_block_hash = [](uint64_t block_num) -> std::string { + // TODO Get a hash of a complete block with block num block_num -- returns 0 if block_num is greater than head return ""; }; std::function< std::vector(std::string) > get_code_at_addr = [](std::string address) -> std::vector { - return {}; + chain::contract_object contract = _db.get_contract_at_addr(address); + return contract.code; }; + addr = new memory[offset:offset+length].value(value) + std::function< std::string(std::vector, machine::big_word) > contract_create = [](std::vector memory, machine::big_word value) -> std::string { - return {}; + // TODO create wallet, associate contract object with that wallet, return contract address + wallet_object wallet = _db.create< wallet_object >; + + // TODO contracts need a wallet field; owner is the person calling the + // contract, wallet is a new wallet created for the contract; + // copy owner's public keys to new wallet, allowing owner to update contract wallet + // using their private keys + chain::contract_object contract = _db.create< contract_object >( [&](contract_object& c) + { + //c.contract_hash = generate_random_ripmd160(); + c.owner = owner; + c.code = memory; + }); + return contract.address; }; std::function< std::vector(std::string, uint64_t, machine::big_word, std::vector) > contract_call = [](std::string address, uint64_t energy, machine::big_word value, std::vector args) -> std::vector { - return {}; + // TODO contract_invoke should return std::vector return data? + return contract_invoke(address, energy, args); }; std::function< std::vector(std::string, uint64_t, machine::big_word, std::vector) > contract_callcode = [](std::string address, uint64_t energy, machine::big_word value, std::vector args) -> std::vector { - return {}; + // TODO Uses alternative account's code (args?) + return contract_invoke(address, energy, args); }; std::function< std::vector(std::string, uint64_t, std::vector) > contract_delegatecall = [](std::string address, uint64_t energy, std::vector args) -> std::vector { - return {}; + // TODO from eth yellowpaper: Message-call into this account with an + // alternative account’s code, but persisting the current values for sender + // and value + return contract_invoke(address, energy, args); }; std::function< std::vector(std::string, uint64_t, std::vector) > contract_staticcall = [](std::string address, uint64_t energy, std::vector args) -> std::vector @@ -1091,6 +1115,7 @@ machine::chain_adapter make_chain_adapter(chain::database& _db) std::function< std::string(std::vector, machine::big_word, std::string) > contract_create2 = [](std::vector memory, machine::big_word value, std::string salt) -> std::string { + // TODO similar to contract_create return {}; }; From 40a384d75e940c070a9e6741aef7c4310d388ed4 Mon Sep 17 00:00:00 2001 From: Liam Noroian Date: Mon, 30 Aug 2021 23:17:19 -0700 Subject: [PATCH 35/96] Adding descriptions of remaining adapter methods --- libraries/chain/xgt_evaluator.cpp | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/libraries/chain/xgt_evaluator.cpp b/libraries/chain/xgt_evaluator.cpp index 19b00b1c..1f1236bb 100644 --- a/libraries/chain/xgt_evaluator.cpp +++ b/libraries/chain/xgt_evaluator.cpp @@ -1091,6 +1091,7 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type std::function< std::vector(std::string, uint64_t, machine::big_word, std::vector) > contract_call = [](std::string address, uint64_t energy, machine::big_word value, std::vector args) -> std::vector { // TODO contract_invoke should return std::vector return data? + // calls a method from another contract -- is value method name? return contract_invoke(address, energy, args); }; @@ -1105,47 +1106,68 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type // TODO from eth yellowpaper: Message-call into this account with an // alternative account’s code, but persisting the current values for sender // and value + // + // from ethervm.io: using storage of the current contract return contract_invoke(address, energy, args); }; std::function< std::vector(std::string, uint64_t, std::vector) > contract_staticcall = [](std::string address, uint64_t energy, std::vector args) -> std::vector { + // TODO from ethervm.io: calls a method in another contract with state + // changes such as contract creation, event emission, storage modification + // and contract destruction disallowed return {}; + return contract_invoke(address, energy, args); }; std::function< std::string(std::vector, machine::big_word, std::string) > contract_create2 = [](std::vector memory, machine::big_word value, std::string salt) -> std::string { - // TODO similar to contract_create - return {}; + // TODO similar to contract_create -- includes a salt for deterministic contract address + wallet_object wallet = _db.create< wallet_object >; + + chain::contract_object contract = _db.create< contract_object >( [&](contract_object& c) + { + //c.contract_hash = generate_random_ripmd160(); + c.owner = owner; + c.code = memory; + }); + return contract.address; }; std::function< bool(std::vector) > revert = [](std::vector memory) -> bool { + // TODO from eth yellowpaper: Halt execution reverting state changes but returning data and remaining gas. return {}; }; std::function< machine::big_word(std::string) > access_storage = [](std::string key) -> machine::big_word { - return {}; + // TODO + return _db.get_storage(owner, key) }; std::function< bool(std::string, std::string, machine::big_word) > set_storage = [](std::string destination, std::string key, machine::big_word value) -> bool { - return {}; + // TODO owner and destination may be the same? -- destination is message destination from contract + return _db.set_storage(owner, destination, key, value); }; std::function< bool(std::vector) > contract_return = [](std::vector memory) -> bool { + // TODO halts execution returning contract data -- does this need to be an adapter method? return {}; }; std::function< bool(std::string) > self_destruct = [](std::string address) -> bool { + // TODO halt execution and register contract address for deletion; + // should delete wallet containing contract (?) return {}; }; std::function< std::vector(std::string) > get_input_data = [](std::string address) -> std::vector { + // TODO may not be necessary return {}; }; From b91fdd4ecd0008ce29a5d0a1ef52174ec0ca696f Mon Sep 17 00:00:00 2001 From: Roger Jungemann Date: Tue, 31 Aug 2021 10:07:34 -0700 Subject: [PATCH 36/96] Fix build --- .../include/xgt/chain/contract_objects.hpp | 1 + libraries/chain/xgt_evaluator.cpp | 32 +++++++++++-------- .../apis/contract_api/contract_api.cpp | 2 +- 3 files changed, 21 insertions(+), 14 deletions(-) diff --git a/libraries/chain/include/xgt/chain/contract_objects.hpp b/libraries/chain/include/xgt/chain/contract_objects.hpp index d75da723..350cd516 100644 --- a/libraries/chain/include/xgt/chain/contract_objects.hpp +++ b/libraries/chain/include/xgt/chain/contract_objects.hpp @@ -25,6 +25,7 @@ namespace xgt { namespace chain { contract_id_type id; wallet_name_type owner; + wallet_name_type wallet; contract_hash_type contract_hash; vector code; }; diff --git a/libraries/chain/xgt_evaluator.cpp b/libraries/chain/xgt_evaluator.cpp index 19b00b1c..227c98c2 100644 --- a/libraries/chain/xgt_evaluator.cpp +++ b/libraries/chain/xgt_evaluator.cpp @@ -1029,6 +1029,11 @@ void contract_create_evaluator::do_apply( const contract_create_operation& op ) }); } +std::vector contract_invoke(std::string address, uint64_t energy,std::vector args) +{ + return std::vector(); +} + machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type owner) { std::function< std::string(std::vector) > sha3 = [](std::vector memory) -> std::string @@ -1043,7 +1048,7 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type return fin; }; - std::function< uint64_t(std::string) > get_balance = [](std::string address) -> uint64_t + std::function< uint64_t(std::string) > get_balance = [&_db](std::string address) -> uint64_t { auto& wallet = _db.get_account(address); return static_cast(wallet.balance.amount.value); @@ -1064,28 +1069,29 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type std::function< std::vector(std::string) > get_code_at_addr = [](std::string address) -> std::vector { - chain::contract_object contract = _db.get_contract_at_addr(address); - return contract.code; + //chain::contract_object contract = _db.get_contract_at_addr(address); + //return std::vector(contract.code.begin(), contract.code.end()); + return std::vector(); }; - addr = new memory[offset:offset+length].value(value) - std::function< std::string(std::vector, machine::big_word) > contract_create = [](std::vector memory, machine::big_word value) -> std::string { // TODO create wallet, associate contract object with that wallet, return contract address - wallet_object wallet = _db.create< wallet_object >; + //wallet_object wallet = _db.create< wallet_object >; // TODO contracts need a wallet field; owner is the person calling the // contract, wallet is a new wallet created for the contract; // copy owner's public keys to new wallet, allowing owner to update contract wallet // using their private keys - chain::contract_object contract = _db.create< contract_object >( [&](contract_object& c) - { - //c.contract_hash = generate_random_ripmd160(); - c.owner = owner; - c.code = memory; - }); - return contract.address; + //chain::contract_object contract = _db.create< contract_object >( [&](contract_object& c) + // { + // //c.contract_hash = generate_random_ripmd160(); + // c.wallet = wallet.name; + // c.owner = owner; + // c.code = memory; + //}); + //return contract.wallet; + return ""; }; std::function< std::vector(std::string, uint64_t, machine::big_word, std::vector) > contract_call = [](std::string address, uint64_t energy, machine::big_word value, std::vector args) -> std::vector diff --git a/libraries/plugins/apis/contract_api/contract_api.cpp b/libraries/plugins/apis/contract_api/contract_api.cpp index 2d8e50b7..7e16513b 100644 --- a/libraries/plugins/apis/contract_api/contract_api.cpp +++ b/libraries/plugins/apis/contract_api/contract_api.cpp @@ -81,7 +81,7 @@ machine::chain_adapter make_chain_adapter(chain::database& _db) return fin; }; - std::function< uint64_t(std::string) > get_balance = [](std::string address) -> uint64_t + std::function< uint64_t(std::string) > get_balance = [&_db](std::string address) -> uint64_t { auto& wallet = _db.get_account(address); return static_cast(wallet.balance.amount.value); From 67023faf62473cb8fe6c384f6c8216523bca36b6 Mon Sep 17 00:00:00 2001 From: Liam Noroian Date: Tue, 31 Aug 2021 10:52:51 -0700 Subject: [PATCH 37/96] Expanding adapter methods --- libraries/chain/xgt_evaluator.cpp | 35 +++++++++++++++++-------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/libraries/chain/xgt_evaluator.cpp b/libraries/chain/xgt_evaluator.cpp index 7e1d490f..341c07a8 100644 --- a/libraries/chain/xgt_evaluator.cpp +++ b/libraries/chain/xgt_evaluator.cpp @@ -1034,6 +1034,7 @@ std::vector contract_invoke(std::string address, uint64_t energy, return std::vector(); } +// TODO make_chain_adapter will be called in contract_invoke machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type owner) { std::function< std::string(std::vector) > sha3 = [](std::vector memory) -> std::string @@ -1056,25 +1057,34 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type std::function< std::string(std::string) > get_code_hash = [](std::string address) -> std::string { - // TODO Get sha3 hash of contract code at addr - return ""; + // TODO Get sha3 hash of contract code at addr -- TODO verify + // get_contract or get_account? + auto& contract = _db.get_contract(address); + std::string message(contract.code.begin(), contract.code.end()); + unsigned char output[32]; + SHA3_CTX ctx; + keccak_init(&ctx); + keccak_update(&ctx, (unsigned char*)message.c_str(), message.size()); + keccak_final(&ctx, output); + std::string fin((char*)output, 32); + return fin; }; // ripemd160 -- store as uint256 - std::function< std::string(uint64_t) > get_block_hash = [](uint64_t block_num) -> std::string + std::function< std::string(uint64_t) > get_block_hash = [&_db](uint64_t block_num) -> std::string { // TODO Get a hash of a complete block with block num block_num -- returns 0 if block_num is greater than head return ""; }; - std::function< std::vector(std::string) > get_code_at_addr = [](std::string address) -> std::vector + std::function< std::vector(std::string) > get_code_at_addr = [&_db](std::string address) -> std::vector { //chain::contract_object contract = _db.get_contract_at_addr(address); //return std::vector(contract.code.begin(), contract.code.end()); return std::vector(); }; - std::function< std::string(std::vector, machine::big_word) > contract_create = [](std::vector memory, machine::big_word value) -> std::string + std::function< std::string(std::vector, machine::big_word) > contract_create = [&_db](std::vector memory, machine::big_word value) -> std::string { // TODO create wallet, associate contract object with that wallet, return contract address //wallet_object wallet = _db.create< wallet_object >; @@ -1126,7 +1136,7 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type return contract_invoke(address, energy, args); }; - std::function< std::string(std::vector, machine::big_word, std::string) > contract_create2 = [](std::vector memory, machine::big_word value, std::string salt) -> std::string + std::function< std::string(std::vector, machine::big_word, std::string) > contract_create2 = [&_db](std::vector memory, machine::big_word value, std::string salt) -> std::string { // TODO similar to contract_create -- includes a salt for deterministic contract address wallet_object wallet = _db.create< wallet_object >; @@ -1146,13 +1156,13 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type return {}; }; - std::function< machine::big_word(std::string) > access_storage = [](std::string key) -> machine::big_word + std::function< machine::big_word(std::string) > access_storage = [&_db](std::string key) -> machine::big_word { // TODO return _db.get_storage(owner, key) }; - std::function< bool(std::string, std::string, machine::big_word) > set_storage = [](std::string destination, std::string key, machine::big_word value) -> bool + std::function< bool(std::string, std::string, machine::big_word) > set_storage = [&_db](std::string destination, std::string key, machine::big_word value) -> bool { // TODO owner and destination may be the same? -- destination is message destination from contract return _db.set_storage(owner, destination, key, value); @@ -1171,12 +1181,6 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type return {}; }; - std::function< std::vector(std::string) > get_input_data = [](std::string address) -> std::vector - { - // TODO may not be necessary - return {}; - }; - machine::chain_adapter adapter = { sha3, get_balance, @@ -1193,8 +1197,7 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type access_storage, set_storage, contract_return, - self_destruct, - get_input_data + self_destruct }; return adapter; From a51133120ad0535b5542d0a60208812b13772f75 Mon Sep 17 00:00:00 2001 From: Liam Noroian Date: Tue, 31 Aug 2021 11:36:32 -0700 Subject: [PATCH 38/96] Adding utility function for block hashing, updating adapter methods --- libraries/chain/include/xgt/chain/database.hpp | 18 ++++++++++++++++++ libraries/chain/xgt_evaluator.cpp | 14 +++++++------- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/libraries/chain/include/xgt/chain/database.hpp b/libraries/chain/include/xgt/chain/database.hpp index e6a6bb09..60283294 100644 --- a/libraries/chain/include/xgt/chain/database.hpp +++ b/libraries/chain/include/xgt/chain/database.hpp @@ -441,6 +441,24 @@ namespace xgt { namespace chain { balance_operator_type balance_operator ); void modify_balance( const wallet_object& a, const asset& delta, bool check_balance ); + fc::optional get_block_hash_from_block_num(uint32_t block_num) const + { + auto block = _block_log.read_block_by_num(block_num); + if (block) { + for( const auto& trx : block.transactions ) + { + + const auto& operations = trx.operations; + for (auto& op : operations) + { + if ( is_pow_operation(op) ) + return fc::optional(op.work.proof); + } + } + } + return fc::optional(); + } + operation_notification create_operation_notification( const operation& op )const { operation_notification note(op); diff --git a/libraries/chain/xgt_evaluator.cpp b/libraries/chain/xgt_evaluator.cpp index 341c07a8..d6f20a3c 100644 --- a/libraries/chain/xgt_evaluator.cpp +++ b/libraries/chain/xgt_evaluator.cpp @@ -1035,7 +1035,7 @@ std::vector contract_invoke(std::string address, uint64_t energy, } // TODO make_chain_adapter will be called in contract_invoke -machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type owner) +machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type owner, wallet_name_type caller) { std::function< std::string(std::vector) > sha3 = [](std::vector memory) -> std::string { @@ -1055,10 +1055,8 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type return static_cast(wallet.balance.amount.value); }; - std::function< std::string(std::string) > get_code_hash = [](std::string address) -> std::string + std::function< std::string(std::string) > get_code_hash = [&_db](std::string address) -> std::string { - // TODO Get sha3 hash of contract code at addr -- TODO verify - // get_contract or get_account? auto& contract = _db.get_contract(address); std::string message(contract.code.begin(), contract.code.end()); unsigned char output[32]; @@ -1073,6 +1071,8 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type // ripemd160 -- store as uint256 std::function< std::string(uint64_t) > get_block_hash = [&_db](uint64_t block_num) -> std::string { + auto& block = _db.get_block_hash_from_block_num(block_num); + return ripemd160(block); // TODO Get a hash of a complete block with block num block_num -- returns 0 if block_num is greater than head return ""; }; @@ -1159,13 +1159,13 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type std::function< machine::big_word(std::string) > access_storage = [&_db](std::string key) -> machine::big_word { // TODO - return _db.get_storage(owner, key) + return _db.get_storage(owner, caller, key) }; - std::function< bool(std::string, std::string, machine::big_word) > set_storage = [&_db](std::string destination, std::string key, machine::big_word value) -> bool + std::function< bool(std::string, machine::big_word) > set_storage = [&_db](std::string key, machine::big_word value) -> bool { // TODO owner and destination may be the same? -- destination is message destination from contract - return _db.set_storage(owner, destination, key, value); + return _db.set_storage(owner, caller, key, value); }; std::function< bool(std::vector) > contract_return = [](std::vector memory) -> bool From 61a72e94f499f4bf992ebc0d8cf1e973d728e085 Mon Sep 17 00:00:00 2001 From: Roger Jungemann Date: Wed, 1 Sep 2021 18:06:54 -0700 Subject: [PATCH 39/96] Clean up some errors --- libraries/chain/include/xgt/chain/database.hpp | 9 +++++++-- libraries/chain/xgt_evaluator.cpp | 1 + 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/libraries/chain/include/xgt/chain/database.hpp b/libraries/chain/include/xgt/chain/database.hpp index 60283294..8845f6b2 100644 --- a/libraries/chain/include/xgt/chain/database.hpp +++ b/libraries/chain/include/xgt/chain/database.hpp @@ -445,14 +445,19 @@ namespace xgt { namespace chain { { auto block = _block_log.read_block_by_num(block_num); if (block) { - for( const auto& trx : block.transactions ) + for( const auto& trx : block->transactions ) { const auto& operations = trx.operations; for (auto& op : operations) { if ( is_pow_operation(op) ) - return fc::optional(op.work.proof); + { + const protocol::pow_operation& o = op.template get< protocol::pow_operation >(); + // TODO: May need a check to verify it is sha2_pow before continuing + const auto& work = o.work.get< sha2_pow >(); + return fc::optional(work.proof); + } } } } diff --git a/libraries/chain/xgt_evaluator.cpp b/libraries/chain/xgt_evaluator.cpp index d6f20a3c..55514b82 100644 --- a/libraries/chain/xgt_evaluator.cpp +++ b/libraries/chain/xgt_evaluator.cpp @@ -927,6 +927,7 @@ void pow_evaluator::do_apply( const pow_operation& o ) const auto& dgp = db.get_dynamic_global_properties(); uint32_t target_pow = db.get_pow_summary_target(); + // TODO: May need a check to verify it is sha2_pow before continuing const auto& work = o.work.get< sha2_pow >(); fc::optional previous_block_id = db.previous_block_id(); if (previous_block_id.valid()) From be82f83508e21338fd430f4befe90d87c73f8de4 Mon Sep 17 00:00:00 2001 From: Roger Jungemann Date: Wed, 1 Sep 2021 19:07:48 -0700 Subject: [PATCH 40/96] Fix errors --- libraries/chain/database.cpp | 5 ++ .../chain/include/xgt/chain/database.hpp | 50 +++++++++---------- libraries/chain/xgt_evaluator.cpp | 38 ++++++++------ .../apis/contract_api/contract_api.cpp | 2 +- libraries/vendor/xgtvm/libraries/machine.cpp | 11 +--- libraries/vendor/xgtvm/libraries/machine.hpp | 2 +- libraries/vendor/xgtvm/programs/xgtvm.cpp | 2 +- .../vendor/xgtvm/programs/xgtvm_tests.cpp | 2 +- 8 files changed, 60 insertions(+), 52 deletions(-) diff --git a/libraries/chain/database.cpp b/libraries/chain/database.cpp index eb1feb44..8d167720 100644 --- a/libraries/chain/database.cpp +++ b/libraries/chain/database.cpp @@ -610,6 +610,11 @@ const witness_object* database::find_witness( const wallet_name_type& name ) con return find< witness_object, by_name >( name ); } +const contract_object& database::get_contract( const contract_hash_type& hash )const +{ try { + return get< contract_object, by_contract_hash >( hash ); +} FC_CAPTURE_AND_RETHROW( (hash) ) } + const wallet_object& database::get_account( const wallet_name_type& name )const { try { return get< wallet_object, by_name >( name ); diff --git a/libraries/chain/include/xgt/chain/database.hpp b/libraries/chain/include/xgt/chain/database.hpp index 8845f6b2..8f4365a3 100644 --- a/libraries/chain/include/xgt/chain/database.hpp +++ b/libraries/chain/include/xgt/chain/database.hpp @@ -203,6 +203,8 @@ namespace xgt { namespace chain { const witness_object& get_witness( const wallet_name_type& name )const; const witness_object* find_witness( const wallet_name_type& name )const; + const contract_object& get_contract( const contract_hash_type& hash )const; + const wallet_object& get_account( const wallet_name_type& name )const; const wallet_object* find_account( const wallet_name_type& name )const; @@ -217,8 +219,6 @@ namespace xgt { namespace chain { const escrow_object& get_escrow( const wallet_name_type& name, uint32_t escrow_id )const; const escrow_object* find_escrow( const wallet_name_type& name, uint32_t escrow_id )const; - //const contract_object& get_contract( const contract_hash_type& contract_hash )const; - const dynamic_global_property_object& get_dynamic_global_properties()const; const node_property_object& get_node_properties()const; const hardfork_property_object& get_hardfork_property_object()const; @@ -399,6 +399,29 @@ namespace xgt { namespace chain { void validate_xtt_invariants()const; ///@} + fc::optional get_block_hash_from_block_num(uint32_t block_num) const + { + auto block = _block_log.read_block_by_num(block_num); + if (block) { + for( const auto& trx : block->transactions ) + { + + const auto& operations = trx.operations; + for (auto& op : operations) + { + if ( is_pow_operation(op) ) + { + const protocol::pow_operation& o = op.template get< protocol::pow_operation >(); + // TODO: May need a check to verify it is sha2_pow before continuing + const auto& work = o.work.get< sha2_pow >(); + return fc::optional(work.proof); + } + } + } + } + return fc::optional(); + } + protected: //Mark pop_undo() as protected -- we do not want outside calling pop_undo(); it should call pop_block() instead //void pop_undo() { object_database::pop_undo(); } @@ -441,29 +464,6 @@ namespace xgt { namespace chain { balance_operator_type balance_operator ); void modify_balance( const wallet_object& a, const asset& delta, bool check_balance ); - fc::optional get_block_hash_from_block_num(uint32_t block_num) const - { - auto block = _block_log.read_block_by_num(block_num); - if (block) { - for( const auto& trx : block->transactions ) - { - - const auto& operations = trx.operations; - for (auto& op : operations) - { - if ( is_pow_operation(op) ) - { - const protocol::pow_operation& o = op.template get< protocol::pow_operation >(); - // TODO: May need a check to verify it is sha2_pow before continuing - const auto& work = o.work.get< sha2_pow >(); - return fc::optional(work.proof); - } - } - } - } - return fc::optional(); - } - operation_notification create_operation_notification( const operation& op )const { operation_notification note(op); diff --git a/libraries/chain/xgt_evaluator.cpp b/libraries/chain/xgt_evaluator.cpp index 55514b82..d63cb63b 100644 --- a/libraries/chain/xgt_evaluator.cpp +++ b/libraries/chain/xgt_evaluator.cpp @@ -1036,8 +1036,11 @@ std::vector contract_invoke(std::string address, uint64_t energy, } // TODO make_chain_adapter will be called in contract_invoke -machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type owner, wallet_name_type caller) +machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type o, wallet_name_type c) { + std::string owner(o); + std::string caller(c); + std::function< std::string(std::vector) > sha3 = [](std::vector memory) -> std::string { std::string message(memory.begin(), memory.end()); @@ -1058,7 +1061,8 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type std::function< std::string(std::string) > get_code_hash = [&_db](std::string address) -> std::string { - auto& contract = _db.get_contract(address); + fc::ripemd160 address_ripemd160(address); + auto& contract = _db.get_contract(address_ripemd160); std::string message(contract.code.begin(), contract.code.end()); unsigned char output[32]; SHA3_CTX ctx; @@ -1072,8 +1076,8 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type // ripemd160 -- store as uint256 std::function< std::string(uint64_t) > get_block_hash = [&_db](uint64_t block_num) -> std::string { - auto& block = _db.get_block_hash_from_block_num(block_num); - return ripemd160(block); + //const auto& block = _db.get_block_hash_from_block_num(block_num); + //return fc::ripemd160(block); // TODO Get a hash of a complete block with block num block_num -- returns 0 if block_num is greater than head return ""; }; @@ -1137,18 +1141,20 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type return contract_invoke(address, energy, args); }; - std::function< std::string(std::vector, machine::big_word, std::string) > contract_create2 = [&_db](std::vector memory, machine::big_word value, std::string salt) -> std::string + std::function< std::string(std::vector, machine::big_word, std::string) > contract_create2 = [&_db, &owner](std::vector memory, machine::big_word value, std::string salt) -> std::string { - // TODO similar to contract_create -- includes a salt for deterministic contract address - wallet_object wallet = _db.create< wallet_object >; + //// TODO similar to contract_create -- includes a salt for deterministic contract address + //wallet_object wallet = _db.create< wallet_object >( [&](wallet_object& w) + //{ + //}); chain::contract_object contract = _db.create< contract_object >( [&](contract_object& c) - { + { //c.contract_hash = generate_random_ripmd160(); c.owner = owner; - c.code = memory; + //c.code = memory; }); - return contract.address; + return contract.wallet; }; std::function< bool(std::vector) > revert = [](std::vector memory) -> bool @@ -1157,16 +1163,20 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type return {}; }; - std::function< machine::big_word(std::string) > access_storage = [&_db](std::string key) -> machine::big_word + // TODO: key needs to be a machine::big_word. The `_db` method should take and return uint256_t instead though + std::function< machine::big_word(std::string) > access_storage = [&_db, &owner, &caller](std::string key) -> machine::big_word { // TODO - return _db.get_storage(owner, caller, key) + //return _db.get_storage(owner, caller, key); + return 0; }; - std::function< bool(std::string, machine::big_word) > set_storage = [&_db](std::string key, machine::big_word value) -> bool + // TODO: key needs to be a machine::big_word. The `_db` method should take and return uint256_t instead though + std::function< bool(std::string, machine::big_word) > set_storage = [&_db, &owner, &caller](std::string key, machine::big_word value) -> bool { // TODO owner and destination may be the same? -- destination is message destination from contract - return _db.set_storage(owner, caller, key, value); + //return _db.set_storage(owner, caller, key, value); + return true; }; std::function< bool(std::vector) > contract_return = [](std::vector memory) -> bool diff --git a/libraries/plugins/apis/contract_api/contract_api.cpp b/libraries/plugins/apis/contract_api/contract_api.cpp index 7e16513b..a0489350 100644 --- a/libraries/plugins/apis/contract_api/contract_api.cpp +++ b/libraries/plugins/apis/contract_api/contract_api.cpp @@ -142,7 +142,7 @@ machine::chain_adapter make_chain_adapter(chain::database& _db) return {}; }; - std::function< bool(std::string, std::string, machine::big_word) > set_storage = [](std::string destination, std::string key, machine::big_word value) -> bool + std::function< bool(std::string, machine::big_word) > set_storage = [](std::string key, machine::big_word value) -> bool { return {}; }; diff --git a/libraries/vendor/xgtvm/libraries/machine.cpp b/libraries/vendor/xgtvm/libraries/machine.cpp index 07da075e..41df86c4 100644 --- a/libraries/vendor/xgtvm/libraries/machine.cpp +++ b/libraries/vendor/xgtvm/libraries/machine.cpp @@ -731,15 +731,8 @@ namespace machine case sstore_opcode: logger << "op sstore" << std::endl; sv = stack.front(); - if (std::string* it = boost::get(&sv)) - { - stack.pop_front(); - va = pop_word(); - adapter.set_storage(msg.destination, *it, va); - } - else { - throw; // TODO - } + va = pop_word(); + adapter.set_storage(msg.destination, va); break; case jump_opcode: logger << "op jump" << std::endl; diff --git a/libraries/vendor/xgtvm/libraries/machine.hpp b/libraries/vendor/xgtvm/libraries/machine.hpp index 244c6cf9..32b2a313 100644 --- a/libraries/vendor/xgtvm/libraries/machine.hpp +++ b/libraries/vendor/xgtvm/libraries/machine.hpp @@ -262,7 +262,7 @@ struct chain_adapter std::function< big_word(std::string) > access_storage; // TODO sstore opcode -- destination, key, value - std::function< bool(std::string, std::string, big_word) > set_storage; + std::function< bool(std::string, big_word) > set_storage; // TODO return opcode std::function< bool(std::vector) > contract_return; diff --git a/libraries/vendor/xgtvm/programs/xgtvm.cpp b/libraries/vendor/xgtvm/programs/xgtvm.cpp index 73ba64e3..5a563f51 100644 --- a/libraries/vendor/xgtvm/programs/xgtvm.cpp +++ b/libraries/vendor/xgtvm/programs/xgtvm.cpp @@ -120,7 +120,7 @@ machine::chain_adapter make_chain_adapter() return {}; }; - std::function< bool(std::string, std::string, machine::big_word) > set_storage = [](std::string destination, std::string key, machine::big_word value) -> bool + std::function< bool(std::string, machine::big_word) > set_storage = [](std::string key, machine::big_word value) -> bool { return {}; }; diff --git a/libraries/vendor/xgtvm/programs/xgtvm_tests.cpp b/libraries/vendor/xgtvm/programs/xgtvm_tests.cpp index 62b21d19..b53fb230 100644 --- a/libraries/vendor/xgtvm/programs/xgtvm_tests.cpp +++ b/libraries/vendor/xgtvm/programs/xgtvm_tests.cpp @@ -76,7 +76,7 @@ machine::chain_adapter make_chain_adapter() return {}; }; - std::function< bool(std::string, std::string, machine::big_word) > set_storage = [](std::string destination, std::string key, machine::big_word value) -> bool + std::function< bool(std::string, machine::big_word) > set_storage = [](std::string key, machine::big_word value) -> bool { return {}; }; From 427ac3636c082be3ef5666a86dd11c56a576d625 Mon Sep 17 00:00:00 2001 From: Liam Noroian Date: Thu, 2 Sep 2021 10:42:23 -0700 Subject: [PATCH 41/96] Implement get_block_hash --- libraries/chain/xgt_evaluator.cpp | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/libraries/chain/xgt_evaluator.cpp b/libraries/chain/xgt_evaluator.cpp index d63cb63b..70f9a25f 100644 --- a/libraries/chain/xgt_evaluator.cpp +++ b/libraries/chain/xgt_evaluator.cpp @@ -1019,6 +1019,19 @@ fc::ripemd160 generate_random_ripmd160() return fc::ripemd160::hash(buf, buflen); } +boost::multiprecision::uint256_t ripemd160_to_uint256_t(fc::ripemd160 h) +{ + boost::multiprecision::uint256_t n(0); + boost::multiprecision::uint256_t m; + for (int i = 0; i < 5; i++) + { + m = h._hashes[i]; + m = m << (8 * i); + n |= m; + } + return n; +} + void contract_create_evaluator::do_apply( const contract_create_operation& op ) { wlog("!!!!!! contract_create owner ${w} code size ${x}", ("w",op.owner)("x",op.code.size())); @@ -1073,13 +1086,15 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type return fin; }; - // ripemd160 -- store as uint256 - std::function< std::string(uint64_t) > get_block_hash = [&_db](uint64_t block_num) -> std::string + std::function< machine::big_word(uint64_t) > get_block_hash = [&_db](uint64_t block_num) -> machine::big_word { - //const auto& block = _db.get_block_hash_from_block_num(block_num); - //return fc::ripemd160(block); // TODO Get a hash of a complete block with block num block_num -- returns 0 if block_num is greater than head - return ""; + + auto& block = _db.get_block_hash_from_block_num(block_num); + auto data = fc::raw::pack_to_vector( block ); + auto ripemd160_hash = fc::ripemd160::hash( data.data, data.size() ); + + return ripemd160_to_uint256_t(ripemd160_hash); }; std::function< std::vector(std::string) > get_code_at_addr = [&_db](std::string address) -> std::vector From 6fb2dc6b60a86535791d522ed7e8e5503a30e61c Mon Sep 17 00:00:00 2001 From: Roger Jungemann Date: Wed, 8 Sep 2021 12:09:28 -0700 Subject: [PATCH 42/96] Build out more invocation --- .../include/xgt/chain/contract_objects.hpp | 1 + .../include/xgt/chain/xgt_object_types.hpp | 2 + libraries/chain/xgt_evaluator.cpp | 72 ++++++++++++++----- 3 files changed, 56 insertions(+), 19 deletions(-) diff --git a/libraries/chain/include/xgt/chain/contract_objects.hpp b/libraries/chain/include/xgt/chain/contract_objects.hpp index 350cd516..338b9920 100644 --- a/libraries/chain/include/xgt/chain/contract_objects.hpp +++ b/libraries/chain/include/xgt/chain/contract_objects.hpp @@ -87,6 +87,7 @@ namespace xgt { namespace chain { c( *this ); } + contract_receipt_id_type id; contract_hash_type contract_hash; wallet_name_type caller; vector< vector > args; diff --git a/libraries/chain/include/xgt/chain/xgt_object_types.hpp b/libraries/chain/include/xgt/chain/xgt_object_types.hpp index 9f9dd0e3..c1ad4491 100644 --- a/libraries/chain/include/xgt/chain/xgt_object_types.hpp +++ b/libraries/chain/include/xgt/chain/xgt_object_types.hpp @@ -104,6 +104,7 @@ class wallet_object; class account_metadata_object; class account_authority_object; class contract_object; +class contract_receipt_object; class contract_storage_object; class witness_object; class transaction_object; @@ -147,6 +148,7 @@ typedef oid< wallet_object > wallet_id_type; typedef oid< account_metadata_object > account_metadata_id_type; typedef oid< account_authority_object > account_authority_id_type; typedef oid< contract_object > contract_id_type; +typedef oid< contract_receipt_object > contract_receipt_id_type; typedef oid< contract_storage_object > contract_storage_id_type; typedef oid< witness_object > witness_id_type; typedef oid< transaction_object > transaction_object_id_type; diff --git a/libraries/chain/xgt_evaluator.cpp b/libraries/chain/xgt_evaluator.cpp index d63cb63b..436fa5eb 100644 --- a/libraries/chain/xgt_evaluator.cpp +++ b/libraries/chain/xgt_evaluator.cpp @@ -1217,28 +1217,62 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type void contract_invoke_evaluator::do_apply( const contract_invoke_operation& op ) { wlog("contract_invoke ${w}", ("w",op.contract_hash)); - /*const contract_hash_type contract_hash = op.contract_hash; - const auto& c = _db.get_contract(contract_hash); + //const contract_hash_type contract_hash = op.contract_hash; + //const auto& c = _db.get_contract(contract_hash); - const machine_context& ctx = { - true, // bool is_running - 0x5c477758 // uint64_t block_timestamp - }; - const vector& code = {0}; - machine m(ctx, code); - m.step(); */ // // const auto& args = op.args; // // const auto& caller = op.caller; - // // TODO: Invoke VM - - // // Generate receipt - // _db.create< contract_receipt_object >( [&](contract_receipt_object& cr) - // { - // // cr.id = std::static_cast(generate_random_ripmd160()); - // cr.contract_id = op.contract; - // cr.caller = op.caller; - // cr.args = op.args; - // }); + + machine::message msg = {}; + + const bool is_debug = true; + const uint64_t block_timestamp = static_cast( _db.head_block_time().sec_since_epoch() ); + const uint64_t block_number = _db.head_block_num(); + const uint64_t block_difficulty = static_cast( _db.get_pow_summary_target() ); + const uint64_t block_energylimit = 0; + const uint64_t tx_energyprice = 0; + std::string tx_origin = op.caller; + std::string block_coinbase = op.caller; // verify this + + machine::context ctx = { + is_debug, + block_timestamp, + block_number, + block_difficulty, + block_energylimit, + tx_energyprice, + tx_origin, + block_coinbase + }; + + std::vector code = {0x00}; + // TODO: Fill in owner + machine::chain_adapter adapter = make_chain_adapter(_db, "", tx_origin); + machine::machine m(ctx, code, msg, adapter); + + m.print_stack(); + + std::string line; + while (m.is_running()) + { + std::cerr << "step\n"; + m.step(); + // Print out any logging that was generated + while ( std::getline(m.get_logger(), line) ) + std::cerr << "\e[36m" << "LOG: " << line << "\e[0m" << std::endl; + } + while ( std::getline(m.get_logger(), line) ) + std::cerr << "\e[36m" << "LOG: " << line << "\e[0m" << std::endl; + std::cout << m.to_json() << std::endl; + + // Generate receipt + _db.create< contract_receipt_object >( [&](contract_receipt_object& cr) + { + //cr.id = std::static_cast(generate_random_ripmd160()); + cr.contract_hash = op.contract_hash; + cr.caller = op.caller; + cr.args = op.args; + }); } } } // xgt::chain From 5ad73ccbdccaad1d39f0e45d213aa9553dc2a210 Mon Sep 17 00:00:00 2001 From: Liam Noroian Date: Wed, 8 Sep 2021 12:58:29 -0700 Subject: [PATCH 43/96] Adding get_contract_at_addr --- libraries/chain/database.cpp | 12 +++++------- libraries/chain/include/xgt/chain/database.hpp | 1 + libraries/chain/xgt_evaluator.cpp | 9 +++++---- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/libraries/chain/database.cpp b/libraries/chain/database.cpp index 8d167720..cd480321 100644 --- a/libraries/chain/database.cpp +++ b/libraries/chain/database.cpp @@ -615,6 +615,11 @@ const contract_object& database::get_contract( const contract_hash_type& hash )c return get< contract_object, by_contract_hash >( hash ); } FC_CAPTURE_AND_RETHROW( (hash) ) } +const contract_object& database::get_contract( const wallet_name_type& wallet )const +{ try { + return get< contract_object, by_wallet >( wallet ); +} FC_CAPTURE_AND_RETHROW( (wallet) ) } + const wallet_object& database::get_account( const wallet_name_type& name )const { try { return get< wallet_object, by_name >( name ); @@ -657,13 +662,6 @@ const escrow_object* database::find_escrow( const wallet_name_type& name, uint32 return find< escrow_object, by_from_id >( boost::make_tuple( name, escrow_id ) ); } -/* -const contract_object& database::get_contract( const contract_hash_type& contract_hash )const -{ try { - return get< contract_object, by_contract_hash >( contract_hash ); -} FC_CAPTURE_AND_RETHROW( (contract_hash) ) } -*/ - const dynamic_global_property_object&database::get_dynamic_global_properties() const { try { return get< dynamic_global_property_object >(); diff --git a/libraries/chain/include/xgt/chain/database.hpp b/libraries/chain/include/xgt/chain/database.hpp index 8f4365a3..ded3ac3d 100644 --- a/libraries/chain/include/xgt/chain/database.hpp +++ b/libraries/chain/include/xgt/chain/database.hpp @@ -204,6 +204,7 @@ namespace xgt { namespace chain { const witness_object* find_witness( const wallet_name_type& name )const; const contract_object& get_contract( const contract_hash_type& hash )const; + const contract_object& get_contract( const wallet_name_type& wallet )const; const wallet_object& get_account( const wallet_name_type& name )const; const wallet_object* find_account( const wallet_name_type& name )const; diff --git a/libraries/chain/xgt_evaluator.cpp b/libraries/chain/xgt_evaluator.cpp index 70f9a25f..013e40d2 100644 --- a/libraries/chain/xgt_evaluator.cpp +++ b/libraries/chain/xgt_evaluator.cpp @@ -1099,20 +1099,21 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type std::function< std::vector(std::string) > get_code_at_addr = [&_db](std::string address) -> std::vector { - //chain::contract_object contract = _db.get_contract_at_addr(address); - //return std::vector(contract.code.begin(), contract.code.end()); - return std::vector(); + chain::contract_object& contract = _db.get_contract(address); + return std::vector(contract.code.begin(), contract.code.end()); }; std::function< std::string(std::vector, machine::big_word) > contract_create = [&_db](std::vector memory, machine::big_word value) -> std::string { // TODO create wallet, associate contract object with that wallet, return contract address - //wallet_object wallet = _db.create< wallet_object >; + wallet_object wallet = _db.create< wallet_object >( []( wallet_object& w ){ w.can_vote = true; } ); // example + _db.update< wallet_object >( wallet, []( wallet_object& w){ w.can_vote = false; } ); // example // TODO contracts need a wallet field; owner is the person calling the // contract, wallet is a new wallet created for the contract; // copy owner's public keys to new wallet, allowing owner to update contract wallet // using their private keys + // //chain::contract_object contract = _db.create< contract_object >( [&](contract_object& c) // { // //c.contract_hash = generate_random_ripmd160(); From d1a8dd26001c51b44eeef5a4a431c282f2e47535 Mon Sep 17 00:00:00 2001 From: Roger Jungemann Date: Wed, 8 Sep 2021 16:51:17 -0700 Subject: [PATCH 44/96] Integration work --- .../include/xgt/chain/contract_objects.hpp | 71 ++++++++++--------- libraries/chain/xgt_evaluator.cpp | 20 +++--- .../apis/contract_api/contract_api.cpp | 4 +- libraries/vendor/xgtvm/libraries/machine.hpp | 2 +- libraries/vendor/xgtvm/programs/xgtvm.cpp | 4 +- .../vendor/xgtvm/programs/xgtvm_tests.cpp | 4 +- 6 files changed, 54 insertions(+), 51 deletions(-) diff --git a/libraries/chain/include/xgt/chain/contract_objects.hpp b/libraries/chain/include/xgt/chain/contract_objects.hpp index 338b9920..cc0514f6 100644 --- a/libraries/chain/include/xgt/chain/contract_objects.hpp +++ b/libraries/chain/include/xgt/chain/contract_objects.hpp @@ -24,14 +24,15 @@ namespace xgt { namespace chain { } contract_id_type id; - wallet_name_type owner; - wallet_name_type wallet; + wallet_name_type owner; // Creator of wallet + wallet_name_type wallet; // New wallet associated with contract contract_hash_type contract_hash; vector code; }; struct by_id; struct by_owner; + struct by_wallet; struct by_contract_hash; typedef multi_index_container< @@ -39,6 +40,7 @@ namespace xgt { namespace chain { indexed_by< ordered_unique< tag< by_id >, member< contract_object, contract_id_type, &contract_object::id > >, ordered_unique< tag< by_owner >, member< contract_object, wallet_name_type, &contract_object::owner > >, + ordered_unique< tag< by_wallet >, member< contract_object, wallet_name_type, &contract_object::wallet > >, ordered_unique< tag< by_contract_hash >, member< contract_object, contract_hash_type, &contract_object::contract_hash > > >, allocator< contract_object > @@ -102,32 +104,33 @@ namespace xgt { namespace chain { allocator< contract_receipt_object > > contract_receipt_index; - // class contract_storage_object : public object< contract_storage_object_type, contract_storage_object > - // { - // XGT_STD_ALLOCATOR_CONSTRUCTOR( contract_storage_object ) - - // template< typename Constructor, typename Allocator > - // contract_storage_object( Constructor&& c, allocator< Allocator > a ) - // { - // c( *this ); - // } - - // contract_storage_id_type id; - // contract_id_type contract_id; - // wallet_name_type owner; // TODO: caller - // vector data; - // }; - - // struct by_contract_id; - // // TODO: By storage id and by owner id? - - // typedef multi_index_container< - // contract_storage_object, - // indexed_by< - // ordered_unique< tag< by_contract_id >, member< contract_storage_object, contract_id_type, &contract_storage_object::contract_id > > - // >, - // allocator< contract_storage_object > - // > contract_storage_index; + class contract_storage_object : public object< contract_storage_object_type, contract_storage_object > + { + XGT_STD_ALLOCATOR_CONSTRUCTOR( contract_storage_object ) + + template< typename Constructor, typename Allocator > + contract_storage_object( Constructor&& c, allocator< Allocator > a ) + { + c( *this ); + } + + contract_storage_id_type id; + contract_hash_type contract; + wallet_name_type caller; + vector data; + }; + + struct by_contract; + struct by_caller; + + typedef multi_index_container< + contract_storage_object, + indexed_by< + ordered_unique< tag< by_contract >, member< contract_storage_object, contract_hash_type, &contract_storage_object::contract > >, + ordered_unique< tag< by_caller >, member< contract_storage_object, wallet_name_type, &contract_storage_object::caller > > + >, + allocator< contract_storage_object > + > contract_storage_index; } } @@ -154,9 +157,9 @@ FC_REFLECT( xgt::chain::contract_receipt_object, ) CHAINBASE_SET_INDEX_TYPE( xgt::chain::contract_receipt_object, xgt::chain::contract_receipt_index ) -// FC_REFLECT( xgt::chain::contract_storage_object, -// (id) -// (contract_id) -// (owner) -// (data) ) -// CHAINBASE_SET_INDEX_TYPE( xgt::chain::contract_storage_object, xgt::chain::contract_storage_index ) + FC_REFLECT( xgt::chain::contract_storage_object, + (id) + (contract) + (caller) + (data) ) + CHAINBASE_SET_INDEX_TYPE( xgt::chain::contract_storage_object, xgt::chain::contract_storage_index ) diff --git a/libraries/chain/xgt_evaluator.cpp b/libraries/chain/xgt_evaluator.cpp index a5bd4ed9..91a836a1 100644 --- a/libraries/chain/xgt_evaluator.cpp +++ b/libraries/chain/xgt_evaluator.cpp @@ -1025,7 +1025,7 @@ boost::multiprecision::uint256_t ripemd160_to_uint256_t(fc::ripemd160 h) boost::multiprecision::uint256_t m; for (int i = 0; i < 5; i++) { - m = h._hashes[i]; + m = h._hash[i]; m = m << (8 * i); n |= m; } @@ -1075,7 +1075,7 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type std::function< std::string(std::string) > get_code_hash = [&_db](std::string address) -> std::string { fc::ripemd160 address_ripemd160(address); - auto& contract = _db.get_contract(address_ripemd160); + const auto& contract = _db.get_contract(address_ripemd160); std::string message(contract.code.begin(), contract.code.end()); unsigned char output[32]; SHA3_CTX ctx; @@ -1086,28 +1086,28 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type return fin; }; + // TODO: Revisit this, we may want to use the original sha256 hash std::function< machine::big_word(uint64_t) > get_block_hash = [&_db](uint64_t block_num) -> machine::big_word { // TODO Get a hash of a complete block with block num block_num -- returns 0 if block_num is greater than head - auto& block = _db.get_block_hash_from_block_num(block_num); - auto data = fc::raw::pack_to_vector( block ); - auto ripemd160_hash = fc::ripemd160::hash( data.data, data.size() ); - - return ripemd160_to_uint256_t(ripemd160_hash); + fc::optional block_hash = _db.get_block_hash_from_block_num(block_num); + auto ripemd160_hash = fc::ripemd160::hash( block_hash->data() ); + machine::big_word item = ripemd160_to_uint256_t(ripemd160_hash); + return item; }; std::function< std::vector(std::string) > get_code_at_addr = [&_db](std::string address) -> std::vector { - chain::contract_object& contract = _db.get_contract(address); + const chain::contract_object& contract = _db.get_contract(address); return std::vector(contract.code.begin(), contract.code.end()); }; std::function< std::string(std::vector, machine::big_word) > contract_create = [&_db](std::vector memory, machine::big_word value) -> std::string { // TODO create wallet, associate contract object with that wallet, return contract address - wallet_object wallet = _db.create< wallet_object >( []( wallet_object& w ){ w.can_vote = true; } ); // example - _db.update< wallet_object >( wallet, []( wallet_object& w){ w.can_vote = false; } ); // example + //wallet_object wallet = _db.create< wallet_object >( []( wallet_object& w ){ w.can_vote = true; } ); // example + //_db.update< wallet_object >( wallet, []( wallet_object& w){ w.can_vote = false; } ); // example // TODO contracts need a wallet field; owner is the person calling the // contract, wallet is a new wallet created for the contract; diff --git a/libraries/plugins/apis/contract_api/contract_api.cpp b/libraries/plugins/apis/contract_api/contract_api.cpp index a0489350..bf58622f 100644 --- a/libraries/plugins/apis/contract_api/contract_api.cpp +++ b/libraries/plugins/apis/contract_api/contract_api.cpp @@ -92,9 +92,9 @@ machine::chain_adapter make_chain_adapter(chain::database& _db) return ""; }; - std::function< std::string(uint64_t) > get_block_hash = [](uint64_t block_num) -> std::string + std::function< machine::big_word(uint64_t) > get_block_hash = [](uint64_t block_num) -> machine::big_word { - return ""; + return {}; }; std::function< std::vector(std::string) > get_code_at_addr = [](std::string address) -> std::vector diff --git a/libraries/vendor/xgtvm/libraries/machine.hpp b/libraries/vendor/xgtvm/libraries/machine.hpp index 32b2a313..f0b102eb 100644 --- a/libraries/vendor/xgtvm/libraries/machine.hpp +++ b/libraries/vendor/xgtvm/libraries/machine.hpp @@ -231,7 +231,7 @@ struct chain_adapter std::function< std::string(std::string) > get_code_hash; // TODO for hashing block number -- blockhash opcode - std::function< std::string(uint64_t) > get_block_hash; + std::function< machine::big_word(uint64_t) > get_block_hash; // TODO get contract bytecode at address std::function< std::vector(std::string) > get_code_at_addr; diff --git a/libraries/vendor/xgtvm/programs/xgtvm.cpp b/libraries/vendor/xgtvm/programs/xgtvm.cpp index 5a563f51..917b0526 100644 --- a/libraries/vendor/xgtvm/programs/xgtvm.cpp +++ b/libraries/vendor/xgtvm/programs/xgtvm.cpp @@ -70,9 +70,9 @@ machine::chain_adapter make_chain_adapter() return ""; }; - std::function< std::string(uint64_t) > get_block_hash = [](uint64_t block_num) -> std::string + std::function< machine::big_word(uint64_t) > get_block_hash = [](uint64_t block_num) -> machine::big_word { - return ""; + return {}; }; std::function< std::vector(std::string) > get_code_at_addr = [](std::string address) -> std::vector diff --git a/libraries/vendor/xgtvm/programs/xgtvm_tests.cpp b/libraries/vendor/xgtvm/programs/xgtvm_tests.cpp index b53fb230..22b938c8 100644 --- a/libraries/vendor/xgtvm/programs/xgtvm_tests.cpp +++ b/libraries/vendor/xgtvm/programs/xgtvm_tests.cpp @@ -26,9 +26,9 @@ machine::chain_adapter make_chain_adapter() return ""; }; - std::function< std::string(uint64_t) > get_block_hash = [](uint64_t block_num) -> std::string + std::function< machine::big_word(uint64_t) > get_block_hash = [](uint64_t block_num) -> machine::big_word { - return ""; + return {}; }; std::function< std::vector(std::string) > get_code_at_addr = [](std::string address) -> std::vector From bd6a29a3cce0f5f7f30250a158dd741e4d9f946f Mon Sep 17 00:00:00 2001 From: Roger Jungemann Date: Fri, 10 Sep 2021 08:32:52 -0700 Subject: [PATCH 45/96] Remove machine from contract_api for now --- .../apis/contract_api/contract_api.cpp | 178 +----------------- .../xgt/plugins/contract_api/contract_api.hpp | 17 +- 2 files changed, 2 insertions(+), 193 deletions(-) diff --git a/libraries/plugins/apis/contract_api/contract_api.cpp b/libraries/plugins/apis/contract_api/contract_api.cpp index bf58622f..bf76de24 100644 --- a/libraries/plugins/apis/contract_api/contract_api.cpp +++ b/libraries/plugins/apis/contract_api/contract_api.cpp @@ -23,8 +23,7 @@ class contract_api_impl DECLARE_API_IMPL( (get_contract) - (list_owner_contracts) - (invoke) ) + (list_owner_contracts) ) chain::database& _db; }; @@ -67,180 +66,6 @@ DEFINE_API_IMPL( contract_api_impl, list_owner_contracts ) return result; } -machine::chain_adapter make_chain_adapter(chain::database& _db) -{ - std::function< std::string(std::vector) > sha3 = [](std::vector memory) -> std::string - { - std::string message(memory.begin(), memory.end()); - unsigned char output[32]; - SHA3_CTX ctx; - keccak_init(&ctx); - keccak_update(&ctx, (unsigned char*)message.c_str(), message.size()); - keccak_final(&ctx, output); - std::string fin((char*)output, 32); - return fin; - }; - - std::function< uint64_t(std::string) > get_balance = [&_db](std::string address) -> uint64_t - { - auto& wallet = _db.get_account(address); - return static_cast(wallet.balance.amount.value); - }; - - std::function< std::string(std::string) > get_code_hash = [](std::string address) -> std::string - { - return ""; - }; - - std::function< machine::big_word(uint64_t) > get_block_hash = [](uint64_t block_num) -> machine::big_word - { - return {}; - }; - - std::function< std::vector(std::string) > get_code_at_addr = [](std::string address) -> std::vector - { - return {}; - }; - - std::function< std::string(std::vector, machine::big_word) > contract_create = [](std::vector memory, machine::big_word value) -> std::string - { - return {}; - }; - - std::function< std::vector(std::string, uint64_t, machine::big_word, std::vector) > contract_call = [](std::string address, uint64_t energy, machine::big_word value, std::vector args) -> std::vector - { - return {}; - }; - - std::function< std::vector(std::string, uint64_t, machine::big_word, std::vector) > contract_callcode = [](std::string address, uint64_t energy, machine::big_word value, std::vector args) -> std::vector - { - return {}; - }; - - std::function< std::vector(std::string, uint64_t, std::vector) > contract_delegatecall = [](std::string address, uint64_t energy, std::vector args) -> std::vector - { - return {}; - }; - - std::function< std::vector(std::string, uint64_t, std::vector) > contract_staticcall = [](std::string address, uint64_t energy, std::vector args) -> std::vector - { - return {}; - }; - - std::function< std::string(std::vector, machine::big_word, std::string) > contract_create2 = [](std::vector memory, machine::big_word value, std::string salt) -> std::string - { - return {}; - }; - - std::function< bool(std::vector) > revert = [](std::vector memory) -> bool - { - return {}; - }; - - std::function< machine::big_word(std::string) > access_storage = [](std::string key) -> machine::big_word - { - return {}; - }; - - std::function< bool(std::string, machine::big_word) > set_storage = [](std::string key, machine::big_word value) -> bool - { - return {}; - }; - - std::function< bool(std::vector) > contract_return = [](std::vector memory) -> bool - { - return {}; - }; - - std::function< bool(std::string) > self_destruct = [](std::string address) -> bool - { - return {}; - }; - - std::function< std::vector(std::string) > get_input_data = [](std::string address) -> std::vector - { - return {}; - }; - - machine::chain_adapter adapter = { - sha3, - get_balance, - get_code_hash, - get_block_hash, - get_code_at_addr, - contract_create, - contract_call, - contract_callcode, - contract_delegatecall, - contract_staticcall, - contract_create2, - revert, - access_storage, - set_storage, - contract_return, - self_destruct, - get_input_data - }; - - return adapter; -} - -DEFINE_API_IMPL( contract_api_impl, invoke ) -{ - // TODO: Temporary - machine::message msg = {}; - ilog( "machine::message msg.flags ${f}", ("f",msg.flags) ); - - const bool is_debug = true; - const uint64_t block_timestamp = static_cast( _db.head_block_time().sec_since_epoch() ); - const uint64_t block_number = _db.head_block_num(); - const uint64_t block_difficulty = static_cast( _db.get_pow_summary_target() ); - const uint64_t block_energylimit = 0; - const uint64_t tx_energyprice = 0; - std::string tx_origin = "XGT0000000000000000000000000000000000000000"; - std::string block_coinbase = "XGT0000000000000000000000000000000000000000"; - - // machine::context ctx = {true, 0x5c477758}; - machine::context ctx = { - is_debug, - block_timestamp, - block_number, - block_difficulty, - block_energylimit, - tx_energyprice, - tx_origin, - block_coinbase - }; - - std::vector code = {0x31, 0x00}; - - machine::chain_adapter adapter = make_chain_adapter(_db); - // machine::machine m(ctx, args.code, msg, adapter); - machine::machine m(ctx, code, msg, adapter); - - std::string init_miner = "XGT0000000000000000000000000000000000000000"; - m.push_string(init_miner); - - m.print_stack(); - - std::string line; - while (m.is_running()) - { - std::cerr << "step\n"; - m.step(); - // Print out any logging that was generated - while ( std::getline(m.get_logger(), line) ) - std::cerr << "\e[36m" << "LOG: " << line << "\e[0m" << std::endl; - } - while ( std::getline(m.get_logger(), line) ) - std::cerr << "\e[36m" << "LOG: " << line << "\e[0m" << std::endl; - std::cout << m.to_json() << std::endl; - - invoke_return result; - - return result; -} - } // detail contract_api::contract_api(): my( new detail::contract_api_impl() ) @@ -253,7 +78,6 @@ contract_api::~contract_api() {} DEFINE_LOCKLESS_APIS( contract_api, (get_contract) (list_owner_contracts) - (invoke) ) } } } //xgt::plugins::contract diff --git a/libraries/plugins/apis/contract_api/include/xgt/plugins/contract_api/contract_api.hpp b/libraries/plugins/apis/contract_api/include/xgt/plugins/contract_api/contract_api.hpp index 787b3f0a..f626fe21 100644 --- a/libraries/plugins/apis/contract_api/include/xgt/plugins/contract_api/contract_api.hpp +++ b/libraries/plugins/apis/contract_api/include/xgt/plugins/contract_api/contract_api.hpp @@ -36,18 +36,6 @@ struct list_owner_contracts_return }; -struct invoke_args -{ - protocol::wallet_name_type owner; - vector< uint8_t > code; -}; - - -struct invoke_return -{ - protocol::wallet_name_type owner; -}; - class contract_api { public: @@ -56,8 +44,7 @@ class contract_api DECLARE_API( (get_contract) - (list_owner_contracts) - (invoke) ) + (list_owner_contracts) ) private: std::unique_ptr< detail::contract_api_impl > my; }; @@ -68,5 +55,3 @@ FC_REFLECT( xgt::plugins::contract::get_contract_args, (example) ) FC_REFLECT( xgt::plugins::contract::get_contract_return, (example) ) FC_REFLECT( xgt::plugins::contract::list_owner_contracts_args, (owner) ) FC_REFLECT( xgt::plugins::contract::list_owner_contracts_return, (contracts) ) -FC_REFLECT( xgt::plugins::contract::invoke_args, (owner) (code) ) -FC_REFLECT( xgt::plugins::contract::invoke_return, (owner) ) From 15afd6b83bab0f092e850f30b0b2770d6673ce3c Mon Sep 17 00:00:00 2001 From: Roger Jungemann Date: Tue, 14 Sep 2021 11:11:20 -0700 Subject: [PATCH 46/96] Invoke --- Rakefile | 309 +++++++----------- libraries/chain/xgt_evaluator.cpp | 11 +- .../apis/contract_api/contract_api.cpp | 7 +- .../include/xgt/protocol/xgt_operations.hpp | 1 + programs/xgtd/main.cpp | 2 + 5 files changed, 131 insertions(+), 199 deletions(-) diff --git a/Rakefile b/Rakefile index c9964ea0..1a232838 100644 --- a/Rakefile +++ b/Rakefile @@ -316,20 +316,125 @@ task :wc do sh %(wc -l #{Dir.glob('**/*.{c,h}pp').join(' ')}) end +def generate_keys + master = Xgt::Ruby::Auth.random_wif + ks = { 'master' => master } + %w(recovery money social memo).each do |role| + private_key = Xgt::Ruby::Auth.generate_wif(wallet, master, 'recovery') + public_key = Xgt::Ruby::Auth.wif_to_public_key(private_key, address_prefix) + ks["#{role}_private"] = private_key + ks["#{role}_public"] = public_key + end + + response = rpc.call('wallet_by_key_api.generate_wallet_name', { + 'recovery_keys' => [ks['recovery_public']] + }) + wallet_name = response['wallet_name'] + ks['wallet_name'] = wallet_name + + ks +end + +def create_wallet!(keys) + name = keys['wallet_name'] + + txn = { + 'extensions' => [], + 'operations' => [ + { + 'type' => 'wallet_create_operation', + 'value' => { + 'fee' => { + 'amount' => '0', + 'precision' => 8, + 'nai' => '@@000000021' + }, + 'creator' => wallet, + 'recovery' => { + 'weight_threshold' => 1, + 'account_auths' => [], + 'key_auths' => [[keys['recovery_public'], 1]] + }, + 'money' => { + 'weight_threshold' => 1, + 'account_auths' => [], + 'key_auths' => [[keys['money_public'], 1]] + }, + 'social' => { + 'weight_threshold' => 1, + 'account_auths' => [], + 'key_auths' => [[keys['social_public'], 1]] + }, + 'memo_key' => keys['memo_public'], + 'json_metadata' => '', + 'extensions' => [] + } + } + ] + } + + $stderr.puts(%(Creator is "#{wallet}" with wif "#{wif}"...)) + $stderr.puts(%(Creating wallet with master key "#{keys['master']}"...)) + signed = Xgt::Ruby::Auth.sign_transaction(rpc, txn, [wif], chain_id) + rpc.call('transaction_api.broadcast_transaction', [signed]) +end + +def create_contract!(owner, keys, code) + txn = { + 'extensions' => [], + 'operations' => [ + { + 'type' => 'contract_create_operation', + 'value' => { + 'owner' => owner, + 'wallet' => keys['wallet_name'], + 'code' => code + #'code' => '600260030100', + #'code' => '00', + } + } + ] + } + signed = Xgt::Ruby::Auth.sign_transaction(rpc, txn, [wif], chain_id) + $stderr.puts(%(Registering contract... #{signed.to_json})) + response = rpc.call('transaction_api.broadcast_transaction', [signed]) + $stderr.puts(%(Received response contract... #{response})) +end + +def invoke_contract!() + txn = { + 'extensions' => [], + 'operations' => [ + { + 'type' => 'contract_invoke_operation', + 'value' => { + 'owner' => wallet, + 'caller' => '...', + 'code' => [0x00], + } + } + ] + } + signed = Xgt::Ruby::Auth.sign_transaction(rpc, txn, [wif], chain_id) + $stderr.puts(%(Registering contract... #{signed.to_json})) + response = rpc.call('transaction_api.broadcast_transaction', [signed]) + $stderr.puts(%(Received response contract... #{response})) +end + +namespace :contracts do + desc 'Create a sample contract' + task :create do + keys = generate_keys + create_wallet!(keys) + create_contract!(wallet, keys, '00') + + response = rpc.call('contract_api.list_owner_contracts', { 'owner' => wallet }) || {} + p response + end +end + namespace :lazy_wallets do task :name_test do - generate_keys = ->() { - master = Xgt::Ruby::Auth.random_wif - ks = { 'master' => master } - %w(recovery money social memo).each do |role| - private_key = Xgt::Ruby::Auth.generate_wif(wallet, master, 'recovery') - public_key = Xgt::Ruby::Auth.wif_to_public_key(private_key, address_prefix) - ks["#{role}_private"] = private_key - ks["#{role}_public"] = public_key - end - ks - } - master = Xgt::Ruby::Auth.random_wif private_key = Xgt::Ruby::Auth.generate_wif(wallet, master, 'recovery') public_key = Xgt::Ruby::Auth.wif_to_public_key(private_key, address_prefix) @@ -362,7 +467,7 @@ namespace :lazy_wallets do id = rpc.broadcast_transaction(txn, [wif], chain_id) (puts 'Waiting...' or sleep 1) until rpc.transaction_ready?(id) - keys = generate_keys.call + keys = generate_keys txn = { 'extensions' => [], 'operations' => [ @@ -399,184 +504,6 @@ namespace :lazy_wallets do end end -namespace :catalyst do - generate_keys = ->() { - FileUtils.mkdir_p('out') - File.open('out/keys.json', 'w') do |f| - master = Xgt::Ruby::Auth.random_wif - ks = { 'master' => master } - %w(recovery money social memo witness).each do |role| - private_key = Xgt::Ruby::Auth.generate_wif(wallet, master, role) - public_key = Xgt::Ruby::Auth.wif_to_public_key(private_key, address_prefix) - ks["#{role}_private"] = private_key - ks["#{role}_public"] = public_key - end - response = rpc.call('wallet_by_key_api.generate_wallet_name', { - 'recovery_keys' => [ks['recovery_public']] - }) - ks['wallet_name'] = response['wallet_name'] - f.puts(JSON.pretty_generate(ks)) - end - } - - keys = ->() { - JSON.load(File.open('out/keys.json')) - } - - does_witness_exist = ->() { - name = wallet_name.call - response = rpc.call('database_api.list_witnesses', { 'start' => name, 'limit' => 1, 'order' => 'by_name'}) || {} - witnesses = response['witnesses'] || [] - witness = witnesses.first || {} - (name == witness['owner']) - } - - desc 'Generate the keys for the witness' - task :generate_keys do - generate_keys.call - end - - desc 'Create a wallet for the witness' - task :create_wallet do - name = keys.call['wallet_name'] - - txn = { - 'extensions' => [], - 'operations' => [ - { - 'type' => 'wallet_create_operation', - 'value' => { - 'fee' => { - 'amount' => '0', - 'precision' => 8, - 'nai' => '@@000000021' - }, - 'creator' => wallet, - 'recovery' => { - 'weight_threshold' => 1, - 'account_auths' => [], - 'key_auths' => [[keys.call['recovery_public'], 1]] - }, - 'money' => { - 'weight_threshold' => 1, - 'account_auths' => [], - 'key_auths' => [[keys.call['money_public'], 1]] - }, - 'social' => { - 'weight_threshold' => 1, - 'account_auths' => [], - 'key_auths' => [[keys.call['social_public'], 1]] - }, - 'memo_key' => keys.call['memo_public'], - 'json_metadata' => '', - 'extensions' => [] - } - } - ] - } - - $stderr.puts(%(Creator is "#{wallet}" with wif "#{wif}"...)) - $stderr.puts(%(Creating wallet with master key "#{keys.call['master']}"...)) - signed = Xgt::Ruby::Auth.sign_transaction(rpc, txn, [wif], chain_id) - rpc.call('transaction_api.broadcast_transaction', [signed]) - end - - desc 'Register the witness' - task :register do - name = keys.call['wallet_name'] - - components = fee.split(' ') - decimal = BigDecimal(components.first) * 1 - final_fee = decimal.truncate.to_s + '.' + sprintf('%03d', (decimal.frac * 1000).truncate) + ' ' + components.last - - # raise 'Witness already registered!' if does_witness_exist.call - - txn = { - 'extensions' => [], - 'operations' => [{ - 'type' => 'witness_update_operation', - 'value' => { - 'owner' => name, - 'url' => 'http://witness-category/my-witness', - 'block_signing_key' => keys.call['witness_public'], - 'props' => { - 'account_creation_fee' => {'amount'=>'0','precision'=>8,'nai'=>'@@000000021'} - }, - 'fee' => {'amount'=>'0','precision'=>8,'nai'=>'@@000000021'} - } - }] - } - - - signing_keys = keys.call['recovery_private'] - signed = Xgt::Ruby::Auth.sign_transaction(rpc, txn, [signing_keys], chain_id) - $stderr.puts(%(Registering witness with recovery private WIF "#{keys.call['recovery_private']}"...)) - $stderr.puts(%(Signing keypair is #{keys.call['witness_private']} (private) and #{keys.call['witness_public']} (public)...)) - response = rpc.call('transaction_api.broadcast_transaction', [signed]) - $stderr.puts(%(Registered witness #{name})) - end - - desc 'Assuming keys were generated, do everything else' - task :all => [:create_wallet, :register] - - desc 'Regenerate keys and do everything else' - task :really_all => [:generate_keys, :create_wallet, :register] -end - -namespace :contracts do - desc 'Generate a sample contract' - task :generate do - txn = { - 'extensions' => [], - 'operations' => [ - { - 'type' => 'contract_create_operation', - 'value' => { - 'owner' => wallet, - 'code' => "600260030100", - } - } - ] - } - signed = Xgt::Ruby::Auth.sign_transaction(rpc, txn, [wif], chain_id) - $stderr.puts(%(Registering contract... #{signed.to_json})) - response = rpc.call('transaction_api.broadcast_transaction', [signed]) - $stderr.puts(%(Received response contract... #{response})) - end - - desc 'Invoke a sample contract' - task :invoke do - txn = { - 'extensions' => [], - 'operations' => [ - { - 'type' => 'contract_invoke_operation', - 'value' => { - 'owner' => wallet, - 'code' => [0x00], - } - } - ] - } - signed = Xgt::Ruby::Auth.sign_transaction(rpc, txn, [wif], chain_id) - $stderr.puts(%(Registering contract... #{signed.to_json})) - response = rpc.call('transaction_api.broadcast_transaction', [signed]) - $stderr.puts(%(Received response contract... #{response})) - end - - desc 'View sample contracts' - task :list do - response = rpc.call('contract_api.list_owner_contracts', { 'owner' => wallet }) || {} - p response - end - - desc 'View sample contracts' - task :debug_invoke do - response = rpc.call('contract_api.invoke', { 'owner' => wallet, 'code' => [] }) || {} - p response - end -end - namespace :machine do src_dir = File.join(File.dirname(__FILE__), %(../xgtvm)) dest_dir = File.join(File.dirname(__FILE__), %(libraries/vendor/xgtvm)) diff --git a/libraries/chain/xgt_evaluator.cpp b/libraries/chain/xgt_evaluator.cpp index 91a836a1..986dc87b 100644 --- a/libraries/chain/xgt_evaluator.cpp +++ b/libraries/chain/xgt_evaluator.cpp @@ -1011,7 +1011,7 @@ void report_over_production_evaluator::do_apply( const report_over_production_op } // TODO: Revisit this -fc::ripemd160 generate_random_ripmd160() +fc::ripemd160 generate_random_ripemd160() { const size_t buflen = 128; char buf[buflen]; @@ -1037,8 +1037,9 @@ void contract_create_evaluator::do_apply( const contract_create_operation& op ) wlog("!!!!!! contract_create owner ${w} code size ${x}", ("w",op.owner)("x",op.code.size())); _db.create< contract_object >( [&](contract_object& c) { - //c.contract_hash = generate_random_ripmd160(); + c.contract_hash = generate_random_ripemd160(); c.owner = op.owner; + c.wallet = op.wallet; c.code = op.code; }); } @@ -1116,7 +1117,7 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type // //chain::contract_object contract = _db.create< contract_object >( [&](contract_object& c) // { - // //c.contract_hash = generate_random_ripmd160(); + // //c.contract_hash = generate_random_ripemd160(); // c.wallet = wallet.name; // c.owner = owner; // c.code = memory; @@ -1166,7 +1167,7 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type chain::contract_object contract = _db.create< contract_object >( [&](contract_object& c) { - //c.contract_hash = generate_random_ripmd160(); + //c.contract_hash = generate_random_ripemd160(); c.owner = owner; //c.code = memory; }); @@ -1284,7 +1285,7 @@ void contract_invoke_evaluator::do_apply( const contract_invoke_operation& op ) // Generate receipt _db.create< contract_receipt_object >( [&](contract_receipt_object& cr) { - //cr.id = std::static_cast(generate_random_ripmd160()); + //cr.id = std::static_cast(generate_random_ripemd160()); cr.contract_hash = op.contract_hash; cr.caller = op.caller; cr.args = op.args; diff --git a/libraries/plugins/apis/contract_api/contract_api.cpp b/libraries/plugins/apis/contract_api/contract_api.cpp index bf76de24..c5dbd66a 100644 --- a/libraries/plugins/apis/contract_api/contract_api.cpp +++ b/libraries/plugins/apis/contract_api/contract_api.cpp @@ -57,9 +57,10 @@ DEFINE_API_IMPL( contract_api_impl, list_owner_contracts ) wlog("!!!!!! LIST_OWNER_CONTRACTS"); while( itr != end ) { - if (itr->owner != args.owner) break; - wlog("!!!!!! LIST_OWNER_CONTRACTS ${w}", ("w",itr->owner)); - result.contracts.push_back(*itr); + auto& c = *itr; + if (c.owner != args.owner) break; + wlog("!!!!!! LIST_OWNER_CONTRACTS ${w}", ("w",c.owner)); + result.contracts.push_back(c); ++itr; } diff --git a/libraries/protocol/include/xgt/protocol/xgt_operations.hpp b/libraries/protocol/include/xgt/protocol/xgt_operations.hpp index dd8ddf90..c00198e3 100644 --- a/libraries/protocol/include/xgt/protocol/xgt_operations.hpp +++ b/libraries/protocol/include/xgt/protocol/xgt_operations.hpp @@ -591,6 +591,7 @@ namespace xgt { namespace protocol { struct contract_create_operation : public base_operation { wallet_name_type owner; + wallet_name_type wallet; vector code; void validate()const; diff --git a/programs/xgtd/main.cpp b/programs/xgtd/main.cpp index f629d0ff..1d8d2bbd 100644 --- a/programs/xgtd/main.cpp +++ b/programs/xgtd/main.cpp @@ -10,6 +10,7 @@ // API plugins #include +#include #include #include #include @@ -95,6 +96,7 @@ int main( int argc, char** argv ) // APIs: xgt::plugins::block_api::block_api_plugin, + xgt::plugins::contract::contract_api_plugin, xgt::plugins::chain::chain_api_plugin, xgt::plugins::database_api::database_api_plugin, xgt::plugins::transaction_api::transaction_api_plugin, From 944eeb01dc51154d65380be3822ec5ba10ecd6aa Mon Sep 17 00:00:00 2001 From: Roger Jungemann Date: Tue, 14 Sep 2021 11:34:37 -0700 Subject: [PATCH 47/96] Fix error --- libraries/chain/include/xgt/chain/contract_objects.hpp | 10 +++++++++- libraries/chain/xgt_evaluator.cpp | 1 + 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/libraries/chain/include/xgt/chain/contract_objects.hpp b/libraries/chain/include/xgt/chain/contract_objects.hpp index cc0514f6..fbe666f4 100644 --- a/libraries/chain/include/xgt/chain/contract_objects.hpp +++ b/libraries/chain/include/xgt/chain/contract_objects.hpp @@ -122,12 +122,20 @@ namespace xgt { namespace chain { struct by_contract; struct by_caller; + struct by_contract_and_caller; typedef multi_index_container< contract_storage_object, indexed_by< ordered_unique< tag< by_contract >, member< contract_storage_object, contract_hash_type, &contract_storage_object::contract > >, - ordered_unique< tag< by_caller >, member< contract_storage_object, wallet_name_type, &contract_storage_object::caller > > + ordered_unique< tag< by_caller >, member< contract_storage_object, wallet_name_type, &contract_storage_object::caller > >, + ordered_unique< tag< by_contract_and_caller >, + composite_key< contract_storage_object, + member< contract_storage_object, contract_hash_type, &contract_storage_object::contract >, + member< contract_storage_object, wallet_name_type, &contract_storage_object::caller > + >, + composite_key_compare< std::less< contract_hash_type >, std::less< wallet_name_type > > + > >, allocator< contract_storage_object > > contract_storage_index; diff --git a/libraries/chain/xgt_evaluator.cpp b/libraries/chain/xgt_evaluator.cpp index 986dc87b..09845649 100644 --- a/libraries/chain/xgt_evaluator.cpp +++ b/libraries/chain/xgt_evaluator.cpp @@ -1037,6 +1037,7 @@ void contract_create_evaluator::do_apply( const contract_create_operation& op ) wlog("!!!!!! contract_create owner ${w} code size ${x}", ("w",op.owner)("x",op.code.size())); _db.create< contract_object >( [&](contract_object& c) { + //c.contract_hash = fc::ripemd160::hash(op.code.begin(), op.code.end()); c.contract_hash = generate_random_ripemd160(); c.owner = op.owner; c.wallet = op.wallet; From cd10bb06feda2737807b5c670ece913c4c0f111d Mon Sep 17 00:00:00 2001 From: Roger Jungemann Date: Wed, 15 Sep 2021 10:01:58 -0700 Subject: [PATCH 48/96] Fix contract_api --- libraries/chain/xgt_evaluator.cpp | 4 ++-- .../apis/contract_api/contract_api.cpp | 9 ++++++++- .../xgt/plugins/contract_api/contract_api.hpp | 20 ++++++++++++++++++- 3 files changed, 29 insertions(+), 4 deletions(-) diff --git a/libraries/chain/xgt_evaluator.cpp b/libraries/chain/xgt_evaluator.cpp index 09845649..b05b96b6 100644 --- a/libraries/chain/xgt_evaluator.cpp +++ b/libraries/chain/xgt_evaluator.cpp @@ -1037,8 +1037,8 @@ void contract_create_evaluator::do_apply( const contract_create_operation& op ) wlog("!!!!!! contract_create owner ${w} code size ${x}", ("w",op.owner)("x",op.code.size())); _db.create< contract_object >( [&](contract_object& c) { - //c.contract_hash = fc::ripemd160::hash(op.code.begin(), op.code.end()); - c.contract_hash = generate_random_ripemd160(); + string s(op.code.begin(), op.code.end()); + c.contract_hash = fc::ripemd160::hash(s); c.owner = op.owner; c.wallet = op.wallet; c.code = op.code; diff --git a/libraries/plugins/apis/contract_api/contract_api.cpp b/libraries/plugins/apis/contract_api/contract_api.cpp index c5dbd66a..9ed8fb9a 100644 --- a/libraries/plugins/apis/contract_api/contract_api.cpp +++ b/libraries/plugins/apis/contract_api/contract_api.cpp @@ -60,7 +60,14 @@ DEFINE_API_IMPL( contract_api_impl, list_owner_contracts ) auto& c = *itr; if (c.owner != args.owner) break; wlog("!!!!!! LIST_OWNER_CONTRACTS ${w}", ("w",c.owner)); - result.contracts.push_back(c); + + api_contract_object ac; + ac.id = c.id; + ac.owner = c.owner; + ac.wallet = c.wallet; + ac.contract_hash = c.contract_hash; + ac.code = c.code; + result.contracts.push_back(ac); ++itr; } diff --git a/libraries/plugins/apis/contract_api/include/xgt/plugins/contract_api/contract_api.hpp b/libraries/plugins/apis/contract_api/include/xgt/plugins/contract_api/contract_api.hpp index f626fe21..006e3381 100644 --- a/libraries/plugins/apis/contract_api/include/xgt/plugins/contract_api/contract_api.hpp +++ b/libraries/plugins/apis/contract_api/include/xgt/plugins/contract_api/contract_api.hpp @@ -4,6 +4,7 @@ #include +#include #include #include @@ -12,6 +13,16 @@ namespace xgt { namespace plugins { namespace contract { namespace detail { class contract_api_impl; } +struct api_contract_object +{ + chain::contract_id_type id; + chain::wallet_name_type owner; + chain::wallet_name_type wallet; + chain::contract_hash_type contract_hash; + vector code; +}; + + struct get_contract_args { bool example = true; @@ -32,7 +43,7 @@ struct list_owner_contracts_args struct list_owner_contracts_return { - std::vector< chain::contract_object > contracts; + std::vector< api_contract_object > contracts; }; @@ -51,6 +62,13 @@ class contract_api } } } // xgt::plugins::contract +FC_REFLECT( xgt::plugins::contract::api_contract_object, + (id) + (owner) + (wallet) + (contract_hash) + (code) ) + FC_REFLECT( xgt::plugins::contract::get_contract_args, (example) ) FC_REFLECT( xgt::plugins::contract::get_contract_return, (example) ) FC_REFLECT( xgt::plugins::contract::list_owner_contracts_args, (owner) ) From fe39ab99a25f82f3768dc86b5f75bd6ab6c58a43 Mon Sep 17 00:00:00 2001 From: Roger Jungemann Date: Thu, 16 Sep 2021 09:00:25 -0700 Subject: [PATCH 49/96] Create, list, and query contracts --- Rakefile | 3 ++ .../apis/contract_api/contract_api.cpp | 34 ++++++++++++------- .../xgt/plugins/contract_api/contract_api.hpp | 8 ++--- 3 files changed, 28 insertions(+), 17 deletions(-) diff --git a/Rakefile b/Rakefile index 1a232838..434d2bc5 100644 --- a/Rakefile +++ b/Rakefile @@ -430,6 +430,9 @@ namespace :contracts do response = rpc.call('contract_api.list_owner_contracts', { 'owner' => wallet }) || {} p response + contract_hash = response['contracts'].first['contract_hash'] + response = rpc.call('contract_api.get_contract', { 'contract_hash' => contract_hash }) || {} + p response end end diff --git a/libraries/plugins/apis/contract_api/contract_api.cpp b/libraries/plugins/apis/contract_api/contract_api.cpp index 9ed8fb9a..3f1e4e13 100644 --- a/libraries/plugins/apis/contract_api/contract_api.cpp +++ b/libraries/plugins/apis/contract_api/contract_api.cpp @@ -30,20 +30,28 @@ class contract_api_impl DEFINE_API_IMPL( contract_api_impl, get_contract ) { - // TODO: Temporary - machine::message msg = {}; - ilog( "machine::message msg.flags ${f}", ("f",msg.flags) ); - - // TODO: Temporary - std::string message = "testing"; - unsigned char output[32]; - SHA3_CTX ctx; - keccak_init(&ctx); - keccak_update(&ctx, (unsigned char*)message.c_str(), message.size()); - keccak_final(&ctx, output); - + ilog( "contract_api_impl::get_contract ${c}", ("c",args.contract_hash) ); + + //// TODO: Temporary + //machine::message msg = {}; + //ilog( "machine::message msg.flags ${f}", ("f",msg.flags) ); + + //// TODO: Temporary + //std::string message = "testing"; + //unsigned char output[32]; + //SHA3_CTX ctx; + //keccak_init(&ctx); + //keccak_update(&ctx, (unsigned char*)message.c_str(), message.size()); + //keccak_final(&ctx, output); + + fc::ripemd160 contract_hash(args.contract_hash); + auto& contract = _db.get_contract(contract_hash); get_contract_return result; - result.example = true; + result.contract.id = contract.id; + result.contract.owner = contract.owner; + result.contract.wallet = contract.wallet; + result.contract.contract_hash = contract.contract_hash; + result.contract.code = contract.code; return result; } diff --git a/libraries/plugins/apis/contract_api/include/xgt/plugins/contract_api/contract_api.hpp b/libraries/plugins/apis/contract_api/include/xgt/plugins/contract_api/contract_api.hpp index 006e3381..2277c6e9 100644 --- a/libraries/plugins/apis/contract_api/include/xgt/plugins/contract_api/contract_api.hpp +++ b/libraries/plugins/apis/contract_api/include/xgt/plugins/contract_api/contract_api.hpp @@ -25,13 +25,13 @@ struct api_contract_object struct get_contract_args { - bool example = true; + chain::contract_hash_type contract_hash; }; struct get_contract_return { - bool example = true; + api_contract_object contract; }; @@ -69,7 +69,7 @@ FC_REFLECT( xgt::plugins::contract::api_contract_object, (contract_hash) (code) ) -FC_REFLECT( xgt::plugins::contract::get_contract_args, (example) ) -FC_REFLECT( xgt::plugins::contract::get_contract_return, (example) ) +FC_REFLECT( xgt::plugins::contract::get_contract_args, (contract_hash) ) +FC_REFLECT( xgt::plugins::contract::get_contract_return, (contract) ) FC_REFLECT( xgt::plugins::contract::list_owner_contracts_args, (owner) ) FC_REFLECT( xgt::plugins::contract::list_owner_contracts_return, (contracts) ) From c67c01dfb5f6c2b609d6bcc770ae0ce17ce33ce6 Mon Sep 17 00:00:00 2001 From: Roger Jungemann Date: Thu, 16 Sep 2021 09:12:27 -0700 Subject: [PATCH 50/96] rake contracts:create end-to-end --- Rakefile | 12 ++++++++---- libraries/chain/xgt_evaluator.cpp | 16 ++++++++-------- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/Rakefile b/Rakefile index 434d2bc5..e58df385 100644 --- a/Rakefile +++ b/Rakefile @@ -401,24 +401,26 @@ def create_contract!(owner, keys, code) $stderr.puts(%(Received response contract... #{response})) end -def invoke_contract!() +def invoke_contract!(contract_hash, invoker, args) txn = { 'extensions' => [], 'operations' => [ { 'type' => 'contract_invoke_operation', 'value' => { - 'owner' => wallet, - 'caller' => '...', - 'code' => [0x00], + 'contract_hash' => contract_hash, + 'caller' => invoker, + 'args' => args } } ] } + $stderr.puts(%(Signing contract contract... #{txn.to_json})) signed = Xgt::Ruby::Auth.sign_transaction(rpc, txn, [wif], chain_id) $stderr.puts(%(Registering contract... #{signed.to_json})) response = rpc.call('transaction_api.broadcast_transaction', [signed]) $stderr.puts(%(Received response contract... #{response})) + response end namespace :contracts do @@ -433,6 +435,8 @@ namespace :contracts do contract_hash = response['contracts'].first['contract_hash'] response = rpc.call('contract_api.get_contract', { 'contract_hash' => contract_hash }) || {} p response + + invoke_contract!(contract_hash, keys['wallet_name'], []) end end diff --git a/libraries/chain/xgt_evaluator.cpp b/libraries/chain/xgt_evaluator.cpp index b05b96b6..d1f2e4a2 100644 --- a/libraries/chain/xgt_evaluator.cpp +++ b/libraries/chain/xgt_evaluator.cpp @@ -1283,14 +1283,14 @@ void contract_invoke_evaluator::do_apply( const contract_invoke_operation& op ) std::cerr << "\e[36m" << "LOG: " << line << "\e[0m" << std::endl; std::cout << m.to_json() << std::endl; - // Generate receipt - _db.create< contract_receipt_object >( [&](contract_receipt_object& cr) - { - //cr.id = std::static_cast(generate_random_ripemd160()); - cr.contract_hash = op.contract_hash; - cr.caller = op.caller; - cr.args = op.args; - }); + //// Generate receipt + //_db.create< contract_receipt_object >( [&](contract_receipt_object& cr) + //{ + // //cr.id = std::static_cast(generate_random_ripemd160()); + // cr.contract_hash = op.contract_hash; + // cr.caller = op.caller; + // cr.args = op.args; + //}); } } } // xgt::chain From a97e9fa76d9da290e834b3bee1cb95aff146ec99 Mon Sep 17 00:00:00 2001 From: Roger Jungemann Date: Thu, 16 Sep 2021 17:36:14 -0700 Subject: [PATCH 51/96] Last minute tweaks --- Rakefile | 2 +- libraries/chain/xgt_evaluator.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Rakefile b/Rakefile index e58df385..7425853d 100644 --- a/Rakefile +++ b/Rakefile @@ -428,7 +428,7 @@ namespace :contracts do task :create do keys = generate_keys create_wallet!(keys) - create_contract!(wallet, keys, '00') + create_contract!(wallet, keys, '600360040100') response = rpc.call('contract_api.list_owner_contracts', { 'owner' => wallet }) || {} p response diff --git a/libraries/chain/xgt_evaluator.cpp b/libraries/chain/xgt_evaluator.cpp index d1f2e4a2..67fe827a 100644 --- a/libraries/chain/xgt_evaluator.cpp +++ b/libraries/chain/xgt_evaluator.cpp @@ -1235,8 +1235,8 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type void contract_invoke_evaluator::do_apply( const contract_invoke_operation& op ) { wlog("contract_invoke ${w}", ("w",op.contract_hash)); - //const contract_hash_type contract_hash = op.contract_hash; - //const auto& c = _db.get_contract(contract_hash); + const contract_hash_type contract_hash = op.contract_hash; + const auto& c = _db.get_contract(contract_hash); // // const auto& args = op.args; // // const auto& caller = op.caller; @@ -1263,7 +1263,7 @@ void contract_invoke_evaluator::do_apply( const contract_invoke_operation& op ) block_coinbase }; - std::vector code = {0x00}; + std::vector code(c.code.begin(), c.code.end()); // TODO: Fill in owner machine::chain_adapter adapter = make_chain_adapter(_db, "", tx_origin); machine::machine m(ctx, code, msg, adapter); From 515695a4544a84b264ede536f3dfae74c0d3e443 Mon Sep 17 00:00:00 2001 From: Liam Noroian Date: Fri, 17 Sep 2021 12:23:50 -0700 Subject: [PATCH 52/96] vendor in xgtvm changes --- libraries/vendor/xgtvm/libraries/machine.cpp | 202 +++++-- libraries/vendor/xgtvm/libraries/machine.hpp | 552 +++++++++--------- .../vendor/xgtvm/programs/xgtvm_tests.cpp | 22 +- 3 files changed, 436 insertions(+), 340 deletions(-) diff --git a/libraries/vendor/xgtvm/libraries/machine.cpp b/libraries/vendor/xgtvm/libraries/machine.cpp index 41df86c4..f31fb207 100644 --- a/libraries/vendor/xgtvm/libraries/machine.cpp +++ b/libraries/vendor/xgtvm/libraries/machine.cpp @@ -162,6 +162,30 @@ namespace machine return ss.str(); } + std::string inspect(std::map words) + { + std::stringstream ss; + ss << "["; + std::map::iterator it; + size_t i = 0; + while(true) + { + it = words.find(i); + if (it != words.end()) { + // TODO: Print hex + ss << std::to_string(it->second); + ss << ", "; + } + else { + ss << std::to_string(it->second); + break; + } + i++; + } + ss << "]"; + return ss.str(); + } + void machine::push_word(stack_variant v) { stack.push_front(v); @@ -238,6 +262,7 @@ namespace machine signed_big_word sa, sb, sc; size_t offset, dest_offset, length, code_size = 0; std::vector contract_args; + std::vector retval; std::vector ext_contract_code; std::vector::const_iterator first, last; std::string* ss; @@ -454,10 +479,18 @@ namespace machine va = pop_word(); // offset vb = pop_word(); // length - first = memory.begin() + static_cast(va); - last = memory.begin() + static_cast(va) + static_cast(vb); + for (size_t i = static_cast(va); i < static_cast(vb); i++) { + std::map::iterator it; + it = memory.find(i); + if (it != memory.end()) { + retval.push_back(it->second); + } + else { + retval.push_back(word(0)); + } + } - push_word( adapter.sha3( std::vector(first, last) ) ); // hash + push_word( adapter.sha3( retval ) ); // hash break; case address_opcode: @@ -503,15 +536,15 @@ namespace machine } va = to_big_word( - msg.input_data[offset + 7], - msg.input_data[offset + 6], - msg.input_data[offset + 5], - msg.input_data[offset + 4], - msg.input_data[offset + 3], - msg.input_data[offset + 2], - msg.input_data[offset + 1], - msg.input_data[offset + 0] - ); + msg.input_data[offset + 7], + msg.input_data[offset + 6], + msg.input_data[offset + 5], + msg.input_data[offset + 4], + msg.input_data[offset + 3], + msg.input_data[offset + 2], + msg.input_data[offset + 1], + msg.input_data[offset + 0] + ); push_word(va); break; case calldatasize_opcode: @@ -668,22 +701,17 @@ namespace machine case mload_opcode: logger << "op mload" << std::endl; va = pop_word(); // offset - if (va + 8 >= memory.size()) - { - state = machine_state::error; - error_message.emplace("Memory overflow"); - } // TODO: Verify order vb = to_big_word( - memory[static_cast(va) + 7], - memory[static_cast(va) + 6], - memory[static_cast(va) + 5], - memory[static_cast(va) + 4], - memory[static_cast(va) + 3], - memory[static_cast(va) + 2], - memory[static_cast(va) + 1], - memory[static_cast(va) + 0] - ); + memory[static_cast(va) + 7], + memory[static_cast(va) + 6], + memory[static_cast(va) + 5], + memory[static_cast(va) + 4], + memory[static_cast(va) + 3], + memory[static_cast(va) + 2], + memory[static_cast(va) + 1], + memory[static_cast(va) + 0] + ); push_word(vb); break; case mstore_opcode: @@ -691,8 +719,7 @@ namespace machine va = pop_word(); // offset vb = pop_word(); // value logger << "memory before: " << inspect(memory) << std::endl; - if (va + 8 >= memory.size()) - memory.resize(static_cast(va) + 8); + // TODO: Verify order memory[static_cast(va) + 0] = get_byte(vb, 7); memory[static_cast(va) + 1] = get_byte(vb, 6); @@ -709,8 +736,6 @@ namespace machine va = pop_word(); // offset vb = pop_word(); // value logger << "memory before: " << inspect(memory) << std::endl; - if (va + 1 >= memory.size()) - memory.resize(static_cast(va) + 1); // TODO: Verify order memory[static_cast(va)] = get_byte(vb, 0); // TODO verify byte of big_word vb logger << "memory after: " << inspect(memory) << std::endl; @@ -733,7 +758,7 @@ namespace machine sv = stack.front(); va = pop_word(); adapter.set_storage(msg.destination, va); - break; + break; case jump_opcode: logger << "op jump" << std::endl; va = pop_word(); // destination @@ -2600,10 +2625,18 @@ namespace machine vb = pop_word(); // offset vc = pop_word(); // length - first = memory.begin() + static_cast(vb); - last = memory.begin() + static_cast(vb) + static_cast(vc); + for (size_t i = static_cast(vb); i < static_cast(vc); i++) { + std::map::iterator it; + it = memory.find(i); + if (it != memory.end()) { + retval.push_back(it->second); + } + else { + retval.push_back(word(0)); + } + } - push_word( adapter.contract_create( std::vector(first, last), va ) ); // addr + push_word( adapter.contract_create( retval, va ) ); // addr break; case call_opcode: logger << "op call" << std::endl; @@ -2620,10 +2653,16 @@ namespace machine ve = pop_word(); // retOffset vf = pop_word(); // retLength - first = memory.begin() + static_cast(vc); - last = memory.begin() + static_cast(vc) + static_cast(vd); - - contract_args = std::vector(first, last); + for (size_t i = static_cast(vc); i < static_cast(vd); i++) { + std::map::iterator it; + it = memory.find(i); + if (it != memory.end()) { + contract_args.push_back(it->second); + } + else { + contract_args.push_back(word(0)); + } + } std::vector contract_call_return = adapter.contract_call(*ss, static_cast(va), vb, contract_args); @@ -2654,10 +2693,16 @@ namespace machine ve = pop_word(); // retOffset vf = pop_word(); // retLength - first = memory.begin() + static_cast(vc); - last = memory.begin() + static_cast(vc) + static_cast(vd); - - contract_args = std::vector(first, last); + for (size_t i = static_cast(vc); i < static_cast(vd); i++) { + std::map::iterator it; + it = memory.find(i); + if (it != memory.end()) { + contract_args.push_back(it->second); + } + else { + contract_args.push_back(word(0)); + } + } std::vector contract_callcode_return = adapter.contract_callcode(*ss, static_cast(va), vb, contract_args); @@ -2690,10 +2735,18 @@ namespace machine va = pop_word(); // offset vb = pop_word(); // length - first = memory.begin() + static_cast(va); - last = memory.begin() + static_cast(va) + static_cast(vb); + for (size_t i = static_cast(va); i < static_cast(vb); i++) { + std::map::iterator it; + it = memory.find(i); + if (it != memory.end()) { + retval.push_back(it->second); + } + else { + retval.push_back(word(0)); + } + } - adapter.contract_return( std::vector(first, last) ); + adapter.contract_return( retval ); break; case delegatecall_opcode: logger << "op delegatecall" << std::endl; @@ -2709,10 +2762,16 @@ namespace machine vd = pop_word(); // retOffset ve = pop_word(); // retLength - first = memory.begin() + static_cast(vb); - last = memory.begin() + static_cast(vb) + static_cast(vc); - - contract_args = std::vector(first, last); + for (size_t i = static_cast(va); i < static_cast(vb); i++) { + std::map::iterator it; + it = memory.find(i); + if (it != memory.end()) { + contract_args.push_back(it->second); + } + else { + contract_args.push_back(word(0)); + } + } std::vector contract_delegatecall_return = adapter.contract_delegatecall(*ss, static_cast(va), contract_args); @@ -2738,10 +2797,20 @@ namespace machine ss = boost::get(&sv); if (ss) { - first = memory.begin() + static_cast(vb); - last = memory.begin() + static_cast(vb) + static_cast(vc); + std::vector args; + + for (size_t i = static_cast(vb); i < static_cast(vc); i++) { + std::map::iterator it; + it = memory.find(i); + if (it != memory.end()) { + args.push_back(it->second); + } + else { + args.push_back(word(0)); + } + } - push_word( adapter.contract_create2( std::vector(first, last), va, *ss ) ); + push_word( adapter.contract_create2( args, va, *ss ) ); } else { state = machine_state::error; @@ -2762,10 +2831,16 @@ namespace machine vd = pop_word(); // retOffset ve = pop_word(); // retLength - first = memory.begin() + static_cast(vb); - last = memory.begin() + static_cast(vb) + static_cast(vc); - - contract_args = std::vector(first, last); + for (size_t i = static_cast(vb); i < static_cast(vc); i++) { + std::map::iterator it; + it = memory.find(i); + if (it != memory.end()) { + contract_args.push_back(it->second); + } + else { + contract_args.push_back(word(0)); + } + } std::vector contract_staticcall_return = adapter.contract_staticcall(*ss, static_cast(va), contract_args); @@ -2786,10 +2861,17 @@ namespace machine va = pop_word(); // offset vb = pop_word(); // length - first = memory.begin() + static_cast(va); - last = memory.begin() + static_cast(va) + static_cast(vb); - - adapter.revert( std::vector(first, last) ); + for (size_t i = static_cast(va); i < static_cast(vb); i++) { + std::map::iterator it; + it = memory.find(i); + if (it != memory.end()) { + retval.push_back(it->second); + } + else { + retval.push_back(word(0)); + } + } + adapter.revert( retval ); break; case selfdestruct_opcode: logger << "op selfdestruct" << std::endl; diff --git a/libraries/vendor/xgtvm/libraries/machine.hpp b/libraries/vendor/xgtvm/libraries/machine.hpp index f0b102eb..2ed9b5ec 100644 --- a/libraries/vendor/xgtvm/libraries/machine.hpp +++ b/libraries/vendor/xgtvm/libraries/machine.hpp @@ -13,307 +13,307 @@ namespace machine { -typedef uint8_t word; -typedef boost::multiprecision::uint256_t big_word; -typedef boost::multiprecision::int256_t signed_big_word; -typedef boost::variant stack_variant; + typedef uint8_t word; + typedef boost::multiprecision::uint256_t big_word; + typedef boost::multiprecision::int256_t signed_big_word; + typedef boost::variant stack_variant; -enum opcode -{ - // ARITHMETIC - stop_opcode = 0x00, - add_opcode = 0x01, - mul_opcode = 0x02, - sub_opcode = 0x03, - div_opcode = 0x04, - sdiv_opcode = 0x05, - mod_opcode = 0x06, - smod_opcode = 0x07, - addmod_opcode = 0x08, - mulmod_opcode = 0x09, - exp_opcode = 0x0a, - - signextend_opcode = 0x0b, - - // COMPARISON - lt_opcode = 0x10, - gt_opcode = 0x11, - slt_opcode = 0x12, - sgt_opcode = 0x13, - eq_opcode = 0x14, - iszero_opcode = 0x15, - - // BITWISE - and_opcode = 0x16, - or_opcode = 0x17, - xor_opcode = 0x18, - not_opcode = 0x19, - byte_opcode = 0x1A, - shl_opcode = 0x1B, - shr_opcode = 0x1C, - sar_opcode = 0x1D, - - sha3_opcode = 0x20, - address_opcode = 0x30, - balance_opcode = 0x31, - origin_opcode = 0x32, - caller_opcode = 0x33, - callvalue_opcode = 0x34, - calldataload_opcode = 0x35, - calldatasize_opcode = 0x36, - calldatacopy_opcode = 0x37, - codesize_opcode = 0x38, - codecopy_opcode = 0x39, - energyprice_opcode = 0x3A, - extcodesize_opcode = 0x3B, - extcodecopy_opcode = 0x3C, - returndatasize_opcode = 0x3D, - returndatacopy_opcode = 0x3E, - extcodehash_opcode = 0x3F, - blockhash_opcode = 0x40, - coinbase_opcode = 0x41, - timestamp_opcode = 0x42, - number_opcode = 0x43, - difficulty_opcode = 0x44, - energylimit_opcode = 0x45, - pop_opcode = 0x50, - mload_opcode = 0x51, - mstore_opcode = 0x52, - mstore8_opcode = 0x53, - sload_opcode = 0x54, - sstore_opcode = 0x55, - jump_opcode = 0x56, - jumpi_opcode = 0x57, - pc_opcode = 0x58, - msize_opcode = 0x59, - energy_opcode = 0x5A, - jumpdest_opcode = 0x5B, - - // PUSH - push1_opcode = 0x60, - push2_opcode = 0x61, - push3_opcode = 0x62, - push4_opcode = 0x63, - push5_opcode = 0x64, - push6_opcode = 0x65, - push7_opcode = 0x66, - push8_opcode = 0x67, - push9_opcode = 0x68, - push10_opcode = 0x69, - push11_opcode = 0x6A, - push12_opcode = 0x6B, - push13_opcode = 0x6C, - push14_opcode = 0x6D, - push15_opcode = 0x6E, - push16_opcode = 0x6F, - push17_opcode = 0x70, - push18_opcode = 0x71, - push19_opcode = 0x72, - push20_opcode = 0x73, - push21_opcode = 0x74, - push22_opcode = 0x75, - push23_opcode = 0x76, - push24_opcode = 0x77, - push25_opcode = 0x78, - push26_opcode = 0x79, - push27_opcode = 0x7A, - push28_opcode = 0x7B, - push29_opcode = 0x7C, - push30_opcode = 0x7D, - push31_opcode = 0x7E, - push32_opcode = 0x7F, - - // DUP - dup1_opcode = 0x80, - dup2_opcode = 0x81, - dup3_opcode = 0x82, - dup4_opcode = 0x83, - dup5_opcode = 0x84, - dup6_opcode = 0x85, - dup7_opcode = 0x86, - dup8_opcode = 0x87, - dup9_opcode = 0x88, - dup10_opcode = 0x89, - dup11_opcode = 0x8A, - dup12_opcode = 0x8B, - dup13_opcode = 0x8C, - dup14_opcode = 0x8D, - dup15_opcode = 0x8E, - dup16_opcode = 0x8F, - - // SWAP - swap1_opcode = 0x90, - swap2_opcode = 0x91, - swap3_opcode = 0x92, - swap4_opcode = 0x93, - swap5_opcode = 0x94, - swap6_opcode = 0x95, - swap7_opcode = 0x96, - swap8_opcode = 0x97, - swap9_opcode = 0x98, - swap10_opcode = 0x99, - swap11_opcode = 0x9A, - swap12_opcode = 0x9B, - swap13_opcode = 0x9C, - swap14_opcode = 0x9D, - swap15_opcode = 0x9E, - swap16_opcode = 0x9F, - - // LOG - log0_opcode = 0xA0, - log1_opcode = 0xA1, - log2_opcode = 0xA2, - log3_opcode = 0xA3, - log4_opcode = 0xA4, - - create_opcode = 0xF0, - call_opcode = 0xF1, - callcode_opcode = 0xF2, - return_opcode = 0xF3, - delegatecall_opcode = 0xF4, - create2_opcode = 0xF5, - staticcall_opcode = 0xFA, - revert_opcode = 0xFD, - selfdestruct_opcode = 0xFF, -}; - -enum class machine_state -{ - stopped, - running, - error -}; + enum opcode + { + // ARITHMETIC + stop_opcode = 0x00, + add_opcode = 0x01, + mul_opcode = 0x02, + sub_opcode = 0x03, + div_opcode = 0x04, + sdiv_opcode = 0x05, + mod_opcode = 0x06, + smod_opcode = 0x07, + addmod_opcode = 0x08, + mulmod_opcode = 0x09, + exp_opcode = 0x0a, + + signextend_opcode = 0x0b, + + // COMPARISON + lt_opcode = 0x10, + gt_opcode = 0x11, + slt_opcode = 0x12, + sgt_opcode = 0x13, + eq_opcode = 0x14, + iszero_opcode = 0x15, + + // BITWISE + and_opcode = 0x16, + or_opcode = 0x17, + xor_opcode = 0x18, + not_opcode = 0x19, + byte_opcode = 0x1A, + shl_opcode = 0x1B, + shr_opcode = 0x1C, + sar_opcode = 0x1D, + + sha3_opcode = 0x20, + address_opcode = 0x30, + balance_opcode = 0x31, + origin_opcode = 0x32, + caller_opcode = 0x33, + callvalue_opcode = 0x34, + calldataload_opcode = 0x35, + calldatasize_opcode = 0x36, + calldatacopy_opcode = 0x37, + codesize_opcode = 0x38, + codecopy_opcode = 0x39, + energyprice_opcode = 0x3A, + extcodesize_opcode = 0x3B, + extcodecopy_opcode = 0x3C, + returndatasize_opcode = 0x3D, + returndatacopy_opcode = 0x3E, + extcodehash_opcode = 0x3F, + blockhash_opcode = 0x40, + coinbase_opcode = 0x41, + timestamp_opcode = 0x42, + number_opcode = 0x43, + difficulty_opcode = 0x44, + energylimit_opcode = 0x45, + pop_opcode = 0x50, + mload_opcode = 0x51, + mstore_opcode = 0x52, + mstore8_opcode = 0x53, + sload_opcode = 0x54, + sstore_opcode = 0x55, + jump_opcode = 0x56, + jumpi_opcode = 0x57, + pc_opcode = 0x58, + msize_opcode = 0x59, + energy_opcode = 0x5A, + jumpdest_opcode = 0x5B, + + // PUSH + push1_opcode = 0x60, + push2_opcode = 0x61, + push3_opcode = 0x62, + push4_opcode = 0x63, + push5_opcode = 0x64, + push6_opcode = 0x65, + push7_opcode = 0x66, + push8_opcode = 0x67, + push9_opcode = 0x68, + push10_opcode = 0x69, + push11_opcode = 0x6A, + push12_opcode = 0x6B, + push13_opcode = 0x6C, + push14_opcode = 0x6D, + push15_opcode = 0x6E, + push16_opcode = 0x6F, + push17_opcode = 0x70, + push18_opcode = 0x71, + push19_opcode = 0x72, + push20_opcode = 0x73, + push21_opcode = 0x74, + push22_opcode = 0x75, + push23_opcode = 0x76, + push24_opcode = 0x77, + push25_opcode = 0x78, + push26_opcode = 0x79, + push27_opcode = 0x7A, + push28_opcode = 0x7B, + push29_opcode = 0x7C, + push30_opcode = 0x7D, + push31_opcode = 0x7E, + push32_opcode = 0x7F, + + // DUP + dup1_opcode = 0x80, + dup2_opcode = 0x81, + dup3_opcode = 0x82, + dup4_opcode = 0x83, + dup5_opcode = 0x84, + dup6_opcode = 0x85, + dup7_opcode = 0x86, + dup8_opcode = 0x87, + dup9_opcode = 0x88, + dup10_opcode = 0x89, + dup11_opcode = 0x8A, + dup12_opcode = 0x8B, + dup13_opcode = 0x8C, + dup14_opcode = 0x8D, + dup15_opcode = 0x8E, + dup16_opcode = 0x8F, + + // SWAP + swap1_opcode = 0x90, + swap2_opcode = 0x91, + swap3_opcode = 0x92, + swap4_opcode = 0x93, + swap5_opcode = 0x94, + swap6_opcode = 0x95, + swap7_opcode = 0x96, + swap8_opcode = 0x97, + swap9_opcode = 0x98, + swap10_opcode = 0x99, + swap11_opcode = 0x9A, + swap12_opcode = 0x9B, + swap13_opcode = 0x9C, + swap14_opcode = 0x9D, + swap15_opcode = 0x9E, + swap16_opcode = 0x9F, + + // LOG + log0_opcode = 0xA0, + log1_opcode = 0xA1, + log2_opcode = 0xA2, + log3_opcode = 0xA3, + log4_opcode = 0xA4, + + create_opcode = 0xF0, + call_opcode = 0xF1, + callcode_opcode = 0xF2, + return_opcode = 0xF3, + delegatecall_opcode = 0xF4, + create2_opcode = 0xF5, + staticcall_opcode = 0xFA, + revert_opcode = 0xFD, + selfdestruct_opcode = 0xFF, + }; + + enum class machine_state + { + stopped, + running, + error + }; -struct log_object -{ - uint8_t data; - uint8_t data_size; - std::vector topics; -}; + struct log_object + { + uint8_t data; + uint8_t data_size; + std::vector topics; + }; -struct message -{ - uint32_t flags; - int32_t depth; - int64_t energy; + struct message + { + uint32_t flags; + int32_t depth; + int64_t energy; - std::string sender; - std::string destination; + std::string sender; + std::string destination; - big_word value; - size_t input_size; - std::vector input_data = {}; - size_t code_size; -}; + big_word value; + size_t input_size; + std::vector input_data = {}; + size_t code_size; + }; -// TODO replace with correct data types -struct context -{ - bool is_debug; - uint64_t block_timestamp; - uint64_t block_number; - uint64_t block_difficulty; - uint64_t block_energylimit; - int64_t tx_energyprice; - std::string tx_origin; - std::string block_coinbase; -}; - -struct chain_adapter -{ - // TODO sha3 opcode - std::function< std::string(std::vector) > sha3; + // TODO replace with correct data types + struct context + { + bool is_debug; + uint64_t block_timestamp; + uint64_t block_number; + uint64_t block_difficulty; + uint64_t block_energylimit; + int64_t tx_energyprice; + std::string tx_origin; + std::string block_coinbase; + }; + + struct chain_adapter + { + // TODO sha3 opcode + std::function< std::string(std::vector) > sha3; - std::function< uint64_t(std::string) > get_balance; + std::function< uint64_t(std::string) > get_balance; - // TODO for hashing address -- extcodehash opcode - std::function< std::string(std::string) > get_code_hash; + // TODO for hashing address -- extcodehash opcode + std::function< std::string(std::string) > get_code_hash; - // TODO for hashing block number -- blockhash opcode - std::function< machine::big_word(uint64_t) > get_block_hash; + // TODO for hashing block number -- blockhash opcode + std::function< machine::big_word(uint64_t) > get_block_hash; - // TODO get contract bytecode at address - std::function< std::vector(std::string) > get_code_at_addr; + // TODO get contract bytecode at address + std::function< std::vector(std::string) > get_code_at_addr; - // TODO creates a child contract -- create opcode - std::function< std::string(std::vector, big_word) > contract_create; + // TODO creates a child contract -- create opcode + std::function< std::string(std::vector, big_word) > contract_create; - // TODO call a method from another contract -- call opcode -- address, energy, value, args - std::function< std::vector(std::string, uint64_t, big_word, std::vector) > contract_call; + // TODO call a method from another contract -- call opcode -- address, energy, value, args + std::function< std::vector(std::string, uint64_t, big_word, std::vector) > contract_call; - // TODO call a method from another contract(?) -- callcode opcode -- address, energy, value, args - std::function< std::vector(std::string, uint64_t, big_word, std::vector) > contract_callcode; + // TODO call a method from another contract(?) -- callcode opcode -- address, energy, value, args + std::function< std::vector(std::string, uint64_t, big_word, std::vector) > contract_callcode; - // TODO call a method from another contract using the storage of the current - // opcode -- delegatecall opcode -- address, energy, args - std::function< std::vector(std::string, uint64_t, std::vector) > contract_delegatecall; + // TODO call a method from another contract using the storage of the current + // opcode -- delegatecall opcode -- address, energy, args + std::function< std::vector(std::string, uint64_t, std::vector) > contract_delegatecall; - // TODO call a method from another contract with state changes disallowed -- staticcall opcode -- address, energy, args - std::function< std::vector(std::string, uint64_t, std::vector) > contract_staticcall; + // TODO call a method from another contract with state changes disallowed -- staticcall opcode -- address, energy, args + std::function< std::vector(std::string, uint64_t, std::vector) > contract_staticcall; - // TODO creates a child contract -- create2 opcode - std::function< std::string(std::vector, big_word, std::string) > contract_create2; + // TODO creates a child contract -- create2 opcode + std::function< std::string(std::vector, big_word, std::string) > contract_create2; - // TODO revert opcode - std::function< bool(std::vector) > revert; + // TODO revert opcode + std::function< bool(std::vector) > revert; - // TODO load opcode -- takes key as a parameter and returns value - std::function< big_word(std::string) > access_storage; + // TODO load opcode -- takes key as a parameter and returns value + std::function< big_word(std::string) > access_storage; - // TODO sstore opcode -- destination, key, value - std::function< bool(std::string, big_word) > set_storage; + // TODO sstore opcode -- destination, key, value + std::function< bool(std::string, big_word) > set_storage; - // TODO return opcode - std::function< bool(std::vector) > contract_return; + // TODO return opcode + std::function< bool(std::vector) > contract_return; - // TODO selfdestruct opcode - std::function< bool(std::string) > self_destruct; + // TODO selfdestruct opcode + std::function< bool(std::string) > self_destruct; - // TODO used to initialize message data - std::function< std::vector(std::string) > get_input_data; + // TODO used to initialize message data + std::function< std::vector(std::string) > get_input_data; -}; + }; -class machine -{ - size_t pc = 0; - std::deque stack; - machine_state state = machine_state::running; - context ctx; - std::vector code; - message msg; - std::vector memory; - std::vector< std::map > storage; - std::vector return_value; - std::vector ext_return_data; - boost::optional error_message; - std::stringstream logger; - chain_adapter adapter; - big_word energy_left; - - void push_word(stack_variant v); - big_word pop_word(); - void log(std::string output); - - public: - machine(context ctx, std::vector code, message msg, chain_adapter adapter) - : ctx(ctx), code(code), msg(msg), adapter(adapter) + class machine { - } - - big_word peek_word(); - void push_string(std::string s); - void print_stack(); - size_t stack_length(); - void step(); - bool is_running(); - machine_state get_state(); - boost::optional get_error_message(); - std::stringstream& get_logger(); - std::string to_json(); - - void emit_log(const log_object& o); -}; + size_t pc = 0; + std::deque stack; + machine_state state = machine_state::running; + context ctx; + std::vector code; + message msg; + std::map memory; + std::map storage; + std::vector return_value; + std::vector ext_return_data; + boost::optional error_message; + std::stringstream logger; + chain_adapter adapter; + big_word energy_left; + + void push_word(stack_variant v); + big_word pop_word(); + void log(std::string output); + + public: + machine(context ctx, std::vector code, message msg, chain_adapter adapter) + : ctx(ctx), code(code), msg(msg), adapter(adapter) + { + } + + big_word peek_word(); + void push_string(std::string s); + void print_stack(); + size_t stack_length(); + void step(); + bool is_running(); + machine_state get_state(); + boost::optional get_error_message(); + std::stringstream& get_logger(); + std::string to_json(); + + void emit_log(const log_object& o); + }; } diff --git a/libraries/vendor/xgtvm/programs/xgtvm_tests.cpp b/libraries/vendor/xgtvm/programs/xgtvm_tests.cpp index 22b938c8..15e9f752 100644 --- a/libraries/vendor/xgtvm/programs/xgtvm_tests.cpp +++ b/libraries/vendor/xgtvm/programs/xgtvm_tests.cpp @@ -4,10 +4,10 @@ #define test_that(message) \ std::cerr << "\e[34m" << ( message ) << "\e[0m" << std::endl; #define assert_message(message, assertion) \ - { \ - bool result = ( assertion ); \ - std::cerr << " " << ( result ? "\e[32m" : "\e[31m" ) << ( message ) << "\e[0m" << std::endl; \ - } +{ \ + bool result = ( assertion ); \ + std::cerr << " " << ( result ? "\e[32m" : "\e[31m" ) << ( message ) << "\e[0m" << std::endl; \ +} machine::chain_adapter make_chain_adapter() { @@ -176,6 +176,20 @@ int main(int argc, char** argv) assert_message( "top of stack has correct value", m.peek_word() == 5 ); } + test_that("machine can store and load a value to/from memory") + { + std::vector input = {0x60, 0x01, 0x60, 0x08, 0x52, 0x60, 0x08, 0x51, 0x00}; + machine::context ctx = {true, 0x00}; + machine::message msg = {}; + machine::chain_adapter adapter = make_chain_adapter(); + machine::machine m(ctx, input, msg, adapter); + while (m.is_running()) + m.step(); + assert_message( "machine should stop when done executing", m.get_state() == machine::machine_state::stopped ); + assert_message( "stack has correct length", m.stack_length() == 1 ); + assert_message( "top of stack has correct value", m.peek_word() == 1 ); + } + test_that("machine can get a wallet's balance via the chain adapter") { std::vector input = {0x31, 0x00}; From 228cedfeea046ce83619e04ba85e3d389820aea4 Mon Sep 17 00:00:00 2001 From: Roger Jungemann Date: Wed, 22 Sep 2021 15:53:54 -0700 Subject: [PATCH 53/96] Fix uniqueness issue --- libraries/chain/database.cpp | 5 ----- .../chain/include/xgt/chain/contract_objects.hpp | 15 +++++++++++---- libraries/chain/include/xgt/chain/database.hpp | 1 - libraries/chain/xgt_evaluator.cpp | 12 +++++++++--- .../plugins/apis/contract_api/contract_api.cpp | 2 +- .../include/xgt/protocol/xgt_operations.hpp | 2 +- 6 files changed, 22 insertions(+), 15 deletions(-) diff --git a/libraries/chain/database.cpp b/libraries/chain/database.cpp index cd480321..2befc7c2 100644 --- a/libraries/chain/database.cpp +++ b/libraries/chain/database.cpp @@ -615,11 +615,6 @@ const contract_object& database::get_contract( const contract_hash_type& hash )c return get< contract_object, by_contract_hash >( hash ); } FC_CAPTURE_AND_RETHROW( (hash) ) } -const contract_object& database::get_contract( const wallet_name_type& wallet )const -{ try { - return get< contract_object, by_wallet >( wallet ); -} FC_CAPTURE_AND_RETHROW( (wallet) ) } - const wallet_object& database::get_account( const wallet_name_type& name )const { try { return get< wallet_object, by_name >( name ); diff --git a/libraries/chain/include/xgt/chain/contract_objects.hpp b/libraries/chain/include/xgt/chain/contract_objects.hpp index fbe666f4..53a2f1ca 100644 --- a/libraries/chain/include/xgt/chain/contract_objects.hpp +++ b/libraries/chain/include/xgt/chain/contract_objects.hpp @@ -31,17 +31,21 @@ namespace xgt { namespace chain { }; struct by_id; - struct by_owner; struct by_wallet; struct by_contract_hash; + struct by_owner_and_contract_hash; typedef multi_index_container< contract_object, indexed_by< ordered_unique< tag< by_id >, member< contract_object, contract_id_type, &contract_object::id > >, - ordered_unique< tag< by_owner >, member< contract_object, wallet_name_type, &contract_object::owner > >, - ordered_unique< tag< by_wallet >, member< contract_object, wallet_name_type, &contract_object::wallet > >, - ordered_unique< tag< by_contract_hash >, member< contract_object, contract_hash_type, &contract_object::contract_hash > > + ordered_unique< tag< by_contract_hash >, member< contract_object, contract_hash_type, &contract_object::contract_hash > >, + ordered_unique< tag< by_owner_and_contract_hash >, + composite_key< contract_object, + member< contract_object, wallet_name_type, &contract_object::owner >, + member< contract_object, contract_hash_type, &contract_object::contract_hash > + > + > >, allocator< contract_object > > contract_index; @@ -143,7 +147,10 @@ namespace xgt { namespace chain { } } FC_REFLECT( xgt::chain::contract_object, + (id) (owner) + (wallet) + (contract_hash) (code) ) CHAINBASE_SET_INDEX_TYPE( xgt::chain::contract_object, xgt::chain::contract_index ) diff --git a/libraries/chain/include/xgt/chain/database.hpp b/libraries/chain/include/xgt/chain/database.hpp index ded3ac3d..8f4365a3 100644 --- a/libraries/chain/include/xgt/chain/database.hpp +++ b/libraries/chain/include/xgt/chain/database.hpp @@ -204,7 +204,6 @@ namespace xgt { namespace chain { const witness_object* find_witness( const wallet_name_type& name )const; const contract_object& get_contract( const contract_hash_type& hash )const; - const contract_object& get_contract( const wallet_name_type& wallet )const; const wallet_object& get_account( const wallet_name_type& name )const; const wallet_object* find_account( const wallet_name_type& name )const; diff --git a/libraries/chain/xgt_evaluator.cpp b/libraries/chain/xgt_evaluator.cpp index 67fe827a..212bad6c 100644 --- a/libraries/chain/xgt_evaluator.cpp +++ b/libraries/chain/xgt_evaluator.cpp @@ -1034,11 +1034,15 @@ boost::multiprecision::uint256_t ripemd160_to_uint256_t(fc::ripemd160 h) void contract_create_evaluator::do_apply( const contract_create_operation& op ) { - wlog("!!!!!! contract_create owner ${w} code size ${x}", ("w",op.owner)("x",op.code.size())); + wlog("!!!!!! contract_create owner ${w} wallet ${x} code size ${y}", ("w",op.owner)("x",op.wallet)("y",op.code.size())); _db.create< contract_object >( [&](contract_object& c) { + // TODO: Temporary, find better way to make contract_hash unique string s(op.code.begin(), op.code.end()); - c.contract_hash = fc::ripemd160::hash(s); + string s2 = op.wallet; + string s3(s2 + s); + c.contract_hash = fc::ripemd160::hash(s3); + wlog("!!!!!! contract_create contract_hash ${c}", ("c",c.contract_hash)); c.owner = op.owner; c.wallet = op.wallet; c.code = op.code; @@ -1099,9 +1103,11 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type return item; }; + // TODO: Uses contract_hash, should it use wallet instead? std::function< std::vector(std::string) > get_code_at_addr = [&_db](std::string address) -> std::vector { - const chain::contract_object& contract = _db.get_contract(address); + const fc::ripemd160 contract_hash(address); + const chain::contract_object& contract = _db.get_contract(contract_hash); return std::vector(contract.code.begin(), contract.code.end()); }; diff --git a/libraries/plugins/apis/contract_api/contract_api.cpp b/libraries/plugins/apis/contract_api/contract_api.cpp index 3f1e4e13..049f26d6 100644 --- a/libraries/plugins/apis/contract_api/contract_api.cpp +++ b/libraries/plugins/apis/contract_api/contract_api.cpp @@ -59,7 +59,7 @@ DEFINE_API_IMPL( contract_api_impl, list_owner_contracts ) { list_owner_contracts_return result; - const auto& idx = _db.get_index< chain::contract_index, chain::by_owner >(); + const auto& idx = _db.get_index< chain::contract_index, chain::by_owner_and_contract_hash >(); auto itr = idx.lower_bound( args.owner ); auto end = idx.end(); wlog("!!!!!! LIST_OWNER_CONTRACTS"); diff --git a/libraries/protocol/include/xgt/protocol/xgt_operations.hpp b/libraries/protocol/include/xgt/protocol/xgt_operations.hpp index c00198e3..1fc5c1a0 100644 --- a/libraries/protocol/include/xgt/protocol/xgt_operations.hpp +++ b/libraries/protocol/include/xgt/protocol/xgt_operations.hpp @@ -663,5 +663,5 @@ FC_REFLECT( xgt::protocol::request_wallet_recovery_operation, (recovery_account) FC_REFLECT( xgt::protocol::recover_wallet_operation, (account_to_recover)(new_recovery_authority)(recent_recovery_authority)(extensions) ); FC_REFLECT( xgt::protocol::change_recovery_wallet_operation, (account_to_recover)(new_recovery_account)(extensions) ); -FC_REFLECT( xgt::protocol::contract_create_operation, (owner)(code) ); +FC_REFLECT( xgt::protocol::contract_create_operation, (owner)(wallet)(code) ); FC_REFLECT( xgt::protocol::contract_invoke_operation, (caller)(contract_hash)(args) ); From 830cffac65710281f0c79141958fdd1e4fa2c573 Mon Sep 17 00:00:00 2001 From: Roger Jungemann Date: Wed, 22 Sep 2021 16:03:51 -0700 Subject: [PATCH 54/96] Bring back contract log objects --- .../include/xgt/chain/contract_objects.hpp | 64 +++++++++---------- .../include/xgt/chain/xgt_object_types.hpp | 2 + 2 files changed, 34 insertions(+), 32 deletions(-) diff --git a/libraries/chain/include/xgt/chain/contract_objects.hpp b/libraries/chain/include/xgt/chain/contract_objects.hpp index 53a2f1ca..bf91bc56 100644 --- a/libraries/chain/include/xgt/chain/contract_objects.hpp +++ b/libraries/chain/include/xgt/chain/contract_objects.hpp @@ -50,23 +50,23 @@ namespace xgt { namespace chain { allocator< contract_object > > contract_index; - // class contract_log_object : public object< contract_log_object_type, contract_log_object > - // { - // XGT_STD_ALLOCATOR_CONSTRUCTOR( contract_log_object ) - - // template< typename Constructor, typename Allocator > - // contract_log_object( Constructor&& c, allocator< Allocator > a ) - // { - // c( *this ); - // } - - // contract_log_id_type id; - // contract_id_type contract_id; - // wallet_name_type owner; - // uint8_t level; - // std::tuple< uint256_t, uint256_t, uint256_t, uint256_t > topics; - // vector data; - // }; + class contract_log_object : public object< contract_log_object_type, contract_log_object > + { + XGT_STD_ALLOCATOR_CONSTRUCTOR( contract_log_object ) + + template< typename Constructor, typename Allocator > + contract_log_object( Constructor&& c, allocator< Allocator > a ) + { + c( *this ); + } + + contract_log_id_type id; + contract_id_type contract_id; + wallet_name_type owner; + uint8_t level; + std::tuple< uint256_t, uint256_t, uint256_t, uint256_t > topics; + vector data; + }; // struct by_contract_id; // // TODO: by_topic, by_level @@ -75,13 +75,13 @@ namespace xgt { namespace chain { // // TODO: Receipt object // // https://github.com/ethereum/go-ethereum/tree/master/core/types - // typedef multi_index_container< - // contract_log_object, - // indexed_by< - // ordered_unique< tag< by_contract_id >, member< contract_log_object, contract_id_type, &contract_log_object::contract_id > > - // >, - // allocator< contract_log_object > - // > contract_log_index; + typedef multi_index_container< + contract_log_object, + indexed_by< + ordered_unique< tag< by_id >, member< contract_log_object, contract_log_id_type, &contract_log_object::id > > + >, + allocator< contract_log_object > + > contract_log_index; class contract_receipt_object : public object< contract_receipt_object_type, contract_receipt_object > { @@ -155,14 +155,14 @@ FC_REFLECT( xgt::chain::contract_object, ) CHAINBASE_SET_INDEX_TYPE( xgt::chain::contract_object, xgt::chain::contract_index ) -// FC_REFLECT( xgt::chain::contract_log_object, -// (id) -// (contract_id) -// (owner) -// (level) -// (topics) -// (data) ) -// CHAINBASE_SET_INDEX_TYPE( xgt::chain::contract_log_object, xgt::chain::contract_log_index ) +FC_REFLECT( xgt::chain::contract_log_object, + (id) + (contract_id) + (owner) + (level) + (topics) + (data) ) +CHAINBASE_SET_INDEX_TYPE( xgt::chain::contract_log_object, xgt::chain::contract_log_index ) FC_REFLECT( xgt::chain::contract_receipt_object, (contract_hash) diff --git a/libraries/chain/include/xgt/chain/xgt_object_types.hpp b/libraries/chain/include/xgt/chain/xgt_object_types.hpp index c1ad4491..eea1ea95 100644 --- a/libraries/chain/include/xgt/chain/xgt_object_types.hpp +++ b/libraries/chain/include/xgt/chain/xgt_object_types.hpp @@ -104,6 +104,7 @@ class wallet_object; class account_metadata_object; class account_authority_object; class contract_object; +class contract_log_object; class contract_receipt_object; class contract_storage_object; class witness_object; @@ -148,6 +149,7 @@ typedef oid< wallet_object > wallet_id_type; typedef oid< account_metadata_object > account_metadata_id_type; typedef oid< account_authority_object > account_authority_id_type; typedef oid< contract_object > contract_id_type; +typedef oid< contract_log_object > contract_log_id_type; typedef oid< contract_receipt_object > contract_receipt_id_type; typedef oid< contract_storage_object > contract_storage_id_type; typedef oid< witness_object > witness_id_type; From 1c97214cadf12b414ad34352243d4fe5d89fec81 Mon Sep 17 00:00:00 2001 From: Liam Noroian Date: Thu, 23 Sep 2021 09:43:54 -0700 Subject: [PATCH 55/96] Add emit_log, use address for get_code_at_addr --- libraries/chain/xgt_evaluator.cpp | 48 +++++++++++++++++-------------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/libraries/chain/xgt_evaluator.cpp b/libraries/chain/xgt_evaluator.cpp index 212bad6c..5f6542a3 100644 --- a/libraries/chain/xgt_evaluator.cpp +++ b/libraries/chain/xgt_evaluator.cpp @@ -1095,42 +1095,40 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type // TODO: Revisit this, we may want to use the original sha256 hash std::function< machine::big_word(uint64_t) > get_block_hash = [&_db](uint64_t block_num) -> machine::big_word { - // TODO Get a hash of a complete block with block num block_num -- returns 0 if block_num is greater than head - + if ( block_num > _db.head_block_num() ) { + return 0; + } fc::optional block_hash = _db.get_block_hash_from_block_num(block_num); auto ripemd160_hash = fc::ripemd160::hash( block_hash->data() ); machine::big_word item = ripemd160_to_uint256_t(ripemd160_hash); return item; }; - // TODO: Uses contract_hash, should it use wallet instead? std::function< std::vector(std::string) > get_code_at_addr = [&_db](std::string address) -> std::vector { - const fc::ripemd160 contract_hash(address); - const chain::contract_object& contract = _db.get_contract(contract_hash); + const chain::contract_object& contract = _db.get_contract(address); return std::vector(contract.code.begin(), contract.code.end()); }; std::function< std::string(std::vector, machine::big_word) > contract_create = [&_db](std::vector memory, machine::big_word value) -> std::string { // TODO create wallet, associate contract object with that wallet, return contract address - //wallet_object wallet = _db.create< wallet_object >( []( wallet_object& w ){ w.can_vote = true; } ); // example - //_db.update< wallet_object >( wallet, []( wallet_object& w){ w.can_vote = false; } ); // example + wallet_object wallet = _db.create< wallet_object >( [&]( wallet_object& acc ); + // TODO initialize wallet? // TODO contracts need a wallet field; owner is the person calling the // contract, wallet is a new wallet created for the contract; // copy owner's public keys to new wallet, allowing owner to update contract wallet // using their private keys // - //chain::contract_object contract = _db.create< contract_object >( [&](contract_object& c) - // { - // //c.contract_hash = generate_random_ripemd160(); - // c.wallet = wallet.name; - // c.owner = owner; - // c.code = memory; - //}); - //return contract.wallet; - return ""; + // TODO value argument is amount of energy to load contract with + chain::contract_object contract = _db.create< contract_object >( [&](contract_object& c) { + c.contract_hash = generate_random_ripemd160(); + c.wallet = wallet.name; + c.owner = owner; + c.code = memory; + }); + return contract.wallet; }; std::function< std::vector(std::string, uint64_t, machine::big_word, std::vector) > contract_call = [](std::string address, uint64_t energy, machine::big_word value, std::vector args) -> std::vector @@ -1184,10 +1182,10 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type std::function< bool(std::vector) > revert = [](std::vector memory) -> bool { // TODO from eth yellowpaper: Halt execution reverting state changes but returning data and remaining gas. - return {}; + return false; }; - // TODO: key needs to be a machine::big_word. The `_db` method should take and return uint256_t instead though + // TODO: key needs to be a machine::big_word. The `_db` method should take and return uint256_t instead std::function< machine::big_word(std::string) > access_storage = [&_db, &owner, &caller](std::string key) -> machine::big_word { // TODO @@ -1200,20 +1198,25 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type { // TODO owner and destination may be the same? -- destination is message destination from contract //return _db.set_storage(owner, caller, key, value); - return true; + return false; }; std::function< bool(std::vector) > contract_return = [](std::vector memory) -> bool { // TODO halts execution returning contract data -- does this need to be an adapter method? - return {}; + return false; }; std::function< bool(std::string) > self_destruct = [](std::string address) -> bool { // TODO halt execution and register contract address for deletion; // should delete wallet containing contract (?) - return {}; + return false; + }; + + std::function< std::string(const machine::log_object&) > emit_log = [](const machine::log_object& o) -> std::string + { + return ""; }; machine::chain_adapter adapter = { @@ -1232,7 +1235,8 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type access_storage, set_storage, contract_return, - self_destruct + self_destruct, + emit_log }; return adapter; From 0a22f2447e5ba5987f181d57938251de3f5433c0 Mon Sep 17 00:00:00 2001 From: Liam Noroian Date: Fri, 24 Sep 2021 12:07:32 -0700 Subject: [PATCH 56/96] Adding emit_log, revising log_object --- .../include/xgt/chain/contract_objects.hpp | 8 ++-- libraries/chain/xgt_evaluator.cpp | 38 +++++++++++-------- 2 files changed, 25 insertions(+), 21 deletions(-) diff --git a/libraries/chain/include/xgt/chain/contract_objects.hpp b/libraries/chain/include/xgt/chain/contract_objects.hpp index bf91bc56..e4f915b6 100644 --- a/libraries/chain/include/xgt/chain/contract_objects.hpp +++ b/libraries/chain/include/xgt/chain/contract_objects.hpp @@ -61,10 +61,9 @@ namespace xgt { namespace chain { } contract_log_id_type id; - contract_id_type contract_id; + contract_hash_type contract_hash; wallet_name_type owner; - uint8_t level; - std::tuple< uint256_t, uint256_t, uint256_t, uint256_t > topics; + std::vector topics; vector data; }; @@ -157,9 +156,8 @@ CHAINBASE_SET_INDEX_TYPE( xgt::chain::contract_object, xgt::chain::contract_inde FC_REFLECT( xgt::chain::contract_log_object, (id) - (contract_id) + (contract_hash) (owner) - (level) (topics) (data) ) CHAINBASE_SET_INDEX_TYPE( xgt::chain::contract_log_object, xgt::chain::contract_log_index ) diff --git a/libraries/chain/xgt_evaluator.cpp b/libraries/chain/xgt_evaluator.cpp index 5f6542a3..66b39d55 100644 --- a/libraries/chain/xgt_evaluator.cpp +++ b/libraries/chain/xgt_evaluator.cpp @@ -1055,7 +1055,7 @@ std::vector contract_invoke(std::string address, uint64_t energy, } // TODO make_chain_adapter will be called in contract_invoke -machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type o, wallet_name_type c) +machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type o, wallet_name_type c, contract_hash_type contract_hash) { std::string owner(o); std::string caller(c); @@ -1112,10 +1112,6 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type std::function< std::string(std::vector, machine::big_word) > contract_create = [&_db](std::vector memory, machine::big_word value) -> std::string { - // TODO create wallet, associate contract object with that wallet, return contract address - wallet_object wallet = _db.create< wallet_object >( [&]( wallet_object& acc ); - // TODO initialize wallet? - // TODO contracts need a wallet field; owner is the person calling the // contract, wallet is a new wallet created for the contract; // copy owner's public keys to new wallet, allowing owner to update contract wallet @@ -1135,6 +1131,7 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type { // TODO contract_invoke should return std::vector return data? // calls a method from another contract -- is value method name? + return contract_invoke(address, energy, args); }; @@ -1182,7 +1179,7 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type std::function< bool(std::vector) > revert = [](std::vector memory) -> bool { // TODO from eth yellowpaper: Halt execution reverting state changes but returning data and remaining gas. - return false; + return true; }; // TODO: key needs to be a machine::big_word. The `_db` method should take and return uint256_t instead @@ -1196,27 +1193,36 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type // TODO: key needs to be a machine::big_word. The `_db` method should take and return uint256_t instead though std::function< bool(std::string, machine::big_word) > set_storage = [&_db, &owner, &caller](std::string key, machine::big_word value) -> bool { - // TODO owner and destination may be the same? -- destination is message destination from contract + // TODO //return _db.set_storage(owner, caller, key, value); return false; }; std::function< bool(std::vector) > contract_return = [](std::vector memory) -> bool { - // TODO halts execution returning contract data -- does this need to be an adapter method? - return false; + // TODO + return true; }; - std::function< bool(std::string) > self_destruct = [](std::string address) -> bool + std::function< bool(std::string) > self_destruct = [&_db](std::string address) -> bool { - // TODO halt execution and register contract address for deletion; - // should delete wallet containing contract (?) - return false; + contract_object& contract = _db.get_contract(address); + _db.remove(contract); + + return true; }; - std::function< std::string(const machine::log_object&) > emit_log = [](const machine::log_object& o) -> std::string + std::function< std::string(const machine::log_object&) > emit_log = [&](const machine::log_object& log) -> std::string { - return ""; + _db.create< contract_log_object >( [&](contract_log_object& cl) + { + cl.contract_hash = contract_hash; + cl.owner = o; + cl.topics = log.topics; + cl.data = log.data; + }); + + return contract_hash.str(); }; machine::chain_adapter adapter = { @@ -1275,7 +1281,7 @@ void contract_invoke_evaluator::do_apply( const contract_invoke_operation& op ) std::vector code(c.code.begin(), c.code.end()); // TODO: Fill in owner - machine::chain_adapter adapter = make_chain_adapter(_db, "", tx_origin); + machine::chain_adapter adapter = make_chain_adapter(_db, "", tx_origin, op.contract_hash); machine::machine m(ctx, code, msg, adapter); m.print_stack(); From 55e9fefb87b6d256386635690d59dcbbf35fec0a Mon Sep 17 00:00:00 2001 From: Roger Jungemann Date: Mon, 27 Sep 2021 20:22:58 -0700 Subject: [PATCH 57/96] Fix build error --- libraries/chain/xgt_evaluator.cpp | 21 +- libraries/vendor/xgtvm/libraries/machine.cpp | 276 ++++++++++--------- libraries/vendor/xgtvm/libraries/machine.hpp | 4 +- 3 files changed, 157 insertions(+), 144 deletions(-) diff --git a/libraries/chain/xgt_evaluator.cpp b/libraries/chain/xgt_evaluator.cpp index 66b39d55..8578b0c3 100644 --- a/libraries/chain/xgt_evaluator.cpp +++ b/libraries/chain/xgt_evaluator.cpp @@ -1106,13 +1106,13 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type std::function< std::vector(std::string) > get_code_at_addr = [&_db](std::string address) -> std::vector { - const chain::contract_object& contract = _db.get_contract(address); + const chain::contract_object& contract = _db.get_contract(fc::ripemd160(address)); return std::vector(contract.code.begin(), contract.code.end()); }; - std::function< std::string(std::vector, machine::big_word) > contract_create = [&_db](std::vector memory, machine::big_word value) -> std::string + std::function< std::string(std::vector, machine::big_word) > contract_create = [&](std::vector memory, machine::big_word value) -> std::string { - // TODO contracts need a wallet field; owner is the person calling the + // TODO contracts need a wallet field; owner is the person creating the // contract, wallet is a new wallet created for the contract; // copy owner's public keys to new wallet, allowing owner to update contract wallet // using their private keys @@ -1120,9 +1120,9 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type // TODO value argument is amount of energy to load contract with chain::contract_object contract = _db.create< contract_object >( [&](contract_object& c) { c.contract_hash = generate_random_ripemd160(); - c.wallet = wallet.name; + // c.wallet = wallet.name; // TODO c.owner = owner; - c.code = memory; + c.code = reinterpret_cast< std::vector& >(memory); }); return contract.wallet; }; @@ -1206,13 +1206,19 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type std::function< bool(std::string) > self_destruct = [&_db](std::string address) -> bool { - contract_object& contract = _db.get_contract(address); + contract_object contract = _db.get_contract(fc::ripemd160(address)); _db.remove(contract); return true; }; - std::function< std::string(const machine::log_object&) > emit_log = [&](const machine::log_object& log) -> std::string + std::function< std::vector(std::string) > get_input_data = [&](std::string input) -> std::vector + { + // TODO + return std::vector(); + }; + + std::function< void(const machine::log_object&) > emit_log = [&](const machine::log_object& log) { _db.create< contract_log_object >( [&](contract_log_object& cl) { @@ -1242,6 +1248,7 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type set_storage, contract_return, self_destruct, + get_input_data, emit_log }; diff --git a/libraries/vendor/xgtvm/libraries/machine.cpp b/libraries/vendor/xgtvm/libraries/machine.cpp index f31fb207..a946aedb 100644 --- a/libraries/vendor/xgtvm/libraries/machine.cpp +++ b/libraries/vendor/xgtvm/libraries/machine.cpp @@ -2458,8 +2458,14 @@ namespace machine logger << "op log0" << std::endl; va = pop_word(); // offset vb = pop_word(); // length - word data = memory[size_t(va)]; - const log_object o = { data, uint8_t(vb), {} }; + offset = size_t(va); + length = size_t(vb); + std::vector slice; + slice.resize(length); + for (size_t i = 0; i < length; i++) { + slice[i] = memory[offset + i]; + } + const log_object o = { slice, {} }; this->emit_log(o); // Ex: @@ -2469,153 +2475,153 @@ namespace machine case log1_opcode: { logger << "op log1" << std::endl; - va = pop_word(); // offset - vb = pop_word(); // length - - std::vector topics; - - stack_variant& stack_object = stack.front(); - if (big_word* it = boost::get(&stack_object)) - { - stack.pop_front(); - topics.push_back(*it); - } - else { - throw; - } - - word data = memory[size_t(va)]; - const log_object o = { data, uint8_t(vb), topics }; - this->emit_log(o); + // va = pop_word(); // offset + // vb = pop_word(); // length + + // std::vector topics; + + // stack_variant& stack_object = stack.front(); + // if (big_word* it = boost::get(&stack_object)) + // { + // stack.pop_front(); + // topics.push_back(*it); + // } + // else { + // throw; + // } + + // word data = memory[size_t(va)]; + // const log_object o = { data, uint8_t(vb), topics }; + // this->emit_log(o); break; } case log2_opcode: { logger << "op log2" << std::endl; - va = pop_word(); // offset - vb = pop_word(); // length - - std::vector topics; - - stack_variant& stack_object = stack.front(); - if (big_word* it = boost::get(&stack_object)) - { - stack.pop_front(); - topics.push_back(*it); - } - else { - throw; - } - - stack_object = stack.front(); - if (big_word* it = boost::get(&stack_object)) - { - stack.pop_front(); - topics.push_back(*it); - } - else { - throw; - } - - word data = memory[size_t(va)]; - const log_object o = { data, uint8_t(vb), topics }; - this->emit_log(o); + // va = pop_word(); // offset + // vb = pop_word(); // length + + // std::vector topics; + + // stack_variant& stack_object = stack.front(); + // if (big_word* it = boost::get(&stack_object)) + // { + // stack.pop_front(); + // topics.push_back(*it); + // } + // else { + // throw; + // } + + // stack_object = stack.front(); + // if (big_word* it = boost::get(&stack_object)) + // { + // stack.pop_front(); + // topics.push_back(*it); + // } + // else { + // throw; + // } + + // word data = memory[size_t(va)]; + // const log_object o = { data, uint8_t(vb), topics }; + // this->emit_log(o); break; } case log3_opcode: { logger << "op log3" << std::endl; - va = pop_word(); // offset - vb = pop_word(); // length - - std::vector topics; - - stack_variant& stack_object = stack.front(); - if (big_word* it = boost::get(&stack_object)) - { - stack.pop_front(); - topics.push_back(*it); - } - else { - throw; - } - - stack_object = stack.front(); - if (big_word* it = boost::get(&stack_object)) - { - stack.pop_front(); - topics.push_back(*it); - } - else { - throw; - } - - stack_object = stack.front(); - if (big_word* it = boost::get(&stack_object)) - { - stack.pop_front(); - topics.push_back(*it); - } - else { - throw; - } - - word data = memory[size_t(va)]; - const log_object o = { data, uint8_t(vb), topics }; - this->emit_log(o); + // va = pop_word(); // offset + // vb = pop_word(); // length + + // std::vector topics; + + // stack_variant& stack_object = stack.front(); + // if (big_word* it = boost::get(&stack_object)) + // { + // stack.pop_front(); + // topics.push_back(*it); + // } + // else { + // throw; + // } + + // stack_object = stack.front(); + // if (big_word* it = boost::get(&stack_object)) + // { + // stack.pop_front(); + // topics.push_back(*it); + // } + // else { + // throw; + // } + + // stack_object = stack.front(); + // if (big_word* it = boost::get(&stack_object)) + // { + // stack.pop_front(); + // topics.push_back(*it); + // } + // else { + // throw; + // } + + // word data = memory[size_t(va)]; + // const log_object o = { data, uint8_t(vb), topics }; + // this->emit_log(o); break; } case log4_opcode: { - logger << "op log4" << std::endl; - va = pop_word(); // offset - vb = pop_word(); // length - - std::vector topics; - - stack_variant& stack_object = stack.front(); - if (big_word* it = boost::get(&stack_object)) - { - stack.pop_front(); - topics.push_back(*it); - } - else { - throw; - } - - stack_object = stack.front(); - if (big_word* it = boost::get(&stack_object)) - { - stack.pop_front(); - topics.push_back(*it); - } - else { - throw; - } - - stack_object = stack.front(); - if (big_word* it = boost::get(&stack_object)) - { - stack.pop_front(); - topics.push_back(*it); - } - else { - throw; - } - - stack_object = stack.front(); - if (big_word* it = boost::get(&stack_object)) - { - stack.pop_front(); - topics.push_back(*it); - } - else { - throw; - } - - word data = memory[size_t(va)]; - const log_object o = { data, uint8_t(vb), topics }; - this->emit_log(o); + // logger << "op log4" << std::endl; + // va = pop_word(); // offset + // vb = pop_word(); // length + + // std::vector topics; + + // stack_variant& stack_object = stack.front(); + // if (big_word* it = boost::get(&stack_object)) + // { + // stack.pop_front(); + // topics.push_back(*it); + // } + // else { + // throw; + // } + + // stack_object = stack.front(); + // if (big_word* it = boost::get(&stack_object)) + // { + // stack.pop_front(); + // topics.push_back(*it); + // } + // else { + // throw; + // } + + // stack_object = stack.front(); + // if (big_word* it = boost::get(&stack_object)) + // { + // stack.pop_front(); + // topics.push_back(*it); + // } + // else { + // throw; + // } + + // stack_object = stack.front(); + // if (big_word* it = boost::get(&stack_object)) + // { + // stack.pop_front(); + // topics.push_back(*it); + // } + // else { + // throw; + // } + + // word data = memory[size_t(va)]; + // const log_object o = { data, uint8_t(vb), topics }; + // this->emit_log(o); break; } case create_opcode: diff --git a/libraries/vendor/xgtvm/libraries/machine.hpp b/libraries/vendor/xgtvm/libraries/machine.hpp index 2ed9b5ec..49c52bbc 100644 --- a/libraries/vendor/xgtvm/libraries/machine.hpp +++ b/libraries/vendor/xgtvm/libraries/machine.hpp @@ -186,8 +186,7 @@ namespace machine struct log_object { - uint8_t data; - uint8_t data_size; + std::vector data; std::vector topics; }; @@ -273,6 +272,7 @@ namespace machine // TODO used to initialize message data std::function< std::vector(std::string) > get_input_data; + std::function< void(const log_object&) > emit_log; }; class machine From 6696754fb6845fdae6a81d0bbc2ac9702c1c7006 Mon Sep 17 00:00:00 2001 From: Roger Jungemann Date: Wed, 29 Sep 2021 21:44:37 -0700 Subject: [PATCH 58/96] Remove wallet field from contract (use owner instead) --- .vimrc | 6 ++++ .../include/xgt/chain/contract_objects.hpp | 3 -- libraries/chain/xgt_evaluator.cpp | 36 ++++++++----------- .../apis/contract_api/contract_api.cpp | 2 -- .../include/xgt/protocol/xgt_operations.hpp | 3 +- 5 files changed, 22 insertions(+), 28 deletions(-) create mode 100644 .vimrc diff --git a/.vimrc b/.vimrc new file mode 100644 index 00000000..deeafae2 --- /dev/null +++ b/.vimrc @@ -0,0 +1,6 @@ +set tabstop=3 +set expandtab +set shiftwidth=3 +"set autoindent +"set smartindent +"set cindent diff --git a/libraries/chain/include/xgt/chain/contract_objects.hpp b/libraries/chain/include/xgt/chain/contract_objects.hpp index e4f915b6..a50496fe 100644 --- a/libraries/chain/include/xgt/chain/contract_objects.hpp +++ b/libraries/chain/include/xgt/chain/contract_objects.hpp @@ -25,13 +25,11 @@ namespace xgt { namespace chain { contract_id_type id; wallet_name_type owner; // Creator of wallet - wallet_name_type wallet; // New wallet associated with contract contract_hash_type contract_hash; vector code; }; struct by_id; - struct by_wallet; struct by_contract_hash; struct by_owner_and_contract_hash; @@ -148,7 +146,6 @@ namespace xgt { namespace chain { FC_REFLECT( xgt::chain::contract_object, (id) (owner) - (wallet) (contract_hash) (code) ) diff --git a/libraries/chain/xgt_evaluator.cpp b/libraries/chain/xgt_evaluator.cpp index 8578b0c3..1ad611fb 100644 --- a/libraries/chain/xgt_evaluator.cpp +++ b/libraries/chain/xgt_evaluator.cpp @@ -1032,19 +1032,22 @@ boost::multiprecision::uint256_t ripemd160_to_uint256_t(fc::ripemd160 h) return n; } +fc::ripemd160 make_contract_hash(const wallet_name_type& owner, const vector code) +{ + string s(code.begin(), code.end()); + string s2 = owner; + string s3(s2 + s); + return fc::ripemd160::hash(s3); +} + void contract_create_evaluator::do_apply( const contract_create_operation& op ) { - wlog("!!!!!! contract_create owner ${w} wallet ${x} code size ${y}", ("w",op.owner)("x",op.wallet)("y",op.code.size())); + wlog("!!!!!! contract_create owner ${w} code size ${y}", ("w",op.owner)("y",op.code.size())); _db.create< contract_object >( [&](contract_object& c) { - // TODO: Temporary, find better way to make contract_hash unique - string s(op.code.begin(), op.code.end()); - string s2 = op.wallet; - string s3(s2 + s); - c.contract_hash = fc::ripemd160::hash(s3); + c.contract_hash = make_contract_hash(op.owner, op.code); wlog("!!!!!! contract_create contract_hash ${c}", ("c",c.contract_hash)); c.owner = op.owner; - c.wallet = op.wallet; c.code = op.code; }); } @@ -1112,19 +1115,14 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type std::function< std::string(std::vector, machine::big_word) > contract_create = [&](std::vector memory, machine::big_word value) -> std::string { - // TODO contracts need a wallet field; owner is the person creating the - // contract, wallet is a new wallet created for the contract; - // copy owner's public keys to new wallet, allowing owner to update contract wallet - // using their private keys - // // TODO value argument is amount of energy to load contract with + fc::ripemd160 contract_hash = generate_random_ripemd160(); chain::contract_object contract = _db.create< contract_object >( [&](contract_object& c) { - c.contract_hash = generate_random_ripemd160(); - // c.wallet = wallet.name; // TODO + c.contract_hash = contract_hash; c.owner = owner; c.code = reinterpret_cast< std::vector& >(memory); }); - return contract.wallet; + return contract_hash.str(); }; std::function< std::vector(std::string, uint64_t, machine::big_word, std::vector) > contract_call = [](std::string address, uint64_t energy, machine::big_word value, std::vector args) -> std::vector @@ -1162,18 +1160,14 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type std::function< std::string(std::vector, machine::big_word, std::string) > contract_create2 = [&_db, &owner](std::vector memory, machine::big_word value, std::string salt) -> std::string { - //// TODO similar to contract_create -- includes a salt for deterministic contract address - //wallet_object wallet = _db.create< wallet_object >( [&](wallet_object& w) - //{ - //}); - + // TODO: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1014.md chain::contract_object contract = _db.create< contract_object >( [&](contract_object& c) { //c.contract_hash = generate_random_ripemd160(); c.owner = owner; //c.code = memory; }); - return contract.wallet; + return ""; }; std::function< bool(std::vector) > revert = [](std::vector memory) -> bool diff --git a/libraries/plugins/apis/contract_api/contract_api.cpp b/libraries/plugins/apis/contract_api/contract_api.cpp index 049f26d6..7c9553aa 100644 --- a/libraries/plugins/apis/contract_api/contract_api.cpp +++ b/libraries/plugins/apis/contract_api/contract_api.cpp @@ -49,7 +49,6 @@ DEFINE_API_IMPL( contract_api_impl, get_contract ) get_contract_return result; result.contract.id = contract.id; result.contract.owner = contract.owner; - result.contract.wallet = contract.wallet; result.contract.contract_hash = contract.contract_hash; result.contract.code = contract.code; return result; @@ -72,7 +71,6 @@ DEFINE_API_IMPL( contract_api_impl, list_owner_contracts ) api_contract_object ac; ac.id = c.id; ac.owner = c.owner; - ac.wallet = c.wallet; ac.contract_hash = c.contract_hash; ac.code = c.code; result.contracts.push_back(ac); diff --git a/libraries/protocol/include/xgt/protocol/xgt_operations.hpp b/libraries/protocol/include/xgt/protocol/xgt_operations.hpp index 1fc5c1a0..dd8ddf90 100644 --- a/libraries/protocol/include/xgt/protocol/xgt_operations.hpp +++ b/libraries/protocol/include/xgt/protocol/xgt_operations.hpp @@ -591,7 +591,6 @@ namespace xgt { namespace protocol { struct contract_create_operation : public base_operation { wallet_name_type owner; - wallet_name_type wallet; vector code; void validate()const; @@ -663,5 +662,5 @@ FC_REFLECT( xgt::protocol::request_wallet_recovery_operation, (recovery_account) FC_REFLECT( xgt::protocol::recover_wallet_operation, (account_to_recover)(new_recovery_authority)(recent_recovery_authority)(extensions) ); FC_REFLECT( xgt::protocol::change_recovery_wallet_operation, (account_to_recover)(new_recovery_account)(extensions) ); -FC_REFLECT( xgt::protocol::contract_create_operation, (owner)(wallet)(code) ); +FC_REFLECT( xgt::protocol::contract_create_operation, (owner)(code) ); FC_REFLECT( xgt::protocol::contract_invoke_operation, (caller)(contract_hash)(args) ); From 2b7060d66a60847bd3947730899de4818b83c189 Mon Sep 17 00:00:00 2001 From: Roger Jungemann Date: Fri, 1 Oct 2021 10:17:05 -0700 Subject: [PATCH 59/96] Finish log operations --- .../include/xgt/chain/contract_objects.hpp | 40 --- .../include/xgt/chain/xgt_object_types.hpp | 4 - libraries/chain/xgt_evaluator.cpp | 13 +- libraries/vendor/xgtvm/libraries/machine.cpp | 292 ++++++++++-------- 4 files changed, 157 insertions(+), 192 deletions(-) diff --git a/libraries/chain/include/xgt/chain/contract_objects.hpp b/libraries/chain/include/xgt/chain/contract_objects.hpp index a50496fe..13384967 100644 --- a/libraries/chain/include/xgt/chain/contract_objects.hpp +++ b/libraries/chain/include/xgt/chain/contract_objects.hpp @@ -65,13 +65,6 @@ namespace xgt { namespace chain { vector data; }; - // struct by_contract_id; - // // TODO: by_topic, by_level - - // // TODO: block id, transaction id, transaction op index? - // // TODO: Receipt object - // // https://github.com/ethereum/go-ethereum/tree/master/core/types - typedef multi_index_container< contract_log_object, indexed_by< @@ -80,31 +73,6 @@ namespace xgt { namespace chain { allocator< contract_log_object > > contract_log_index; - class contract_receipt_object : public object< contract_receipt_object_type, contract_receipt_object > - { - XGT_STD_ALLOCATOR_CONSTRUCTOR( contract_receipt_object ) - - template< typename Constructor, typename Allocator > - contract_receipt_object( Constructor&& c, allocator< Allocator > a ) - { - c( *this ); - } - - contract_receipt_id_type id; - contract_hash_type contract_hash; - wallet_name_type caller; - vector< vector > args; - // uint64_t energy_used; // TODO: Verify this - }; - - typedef multi_index_container< - contract_receipt_object, - indexed_by< - ordered_unique< tag< by_contract_hash >, member< contract_receipt_object, contract_hash_type, &contract_receipt_object::contract_hash > > - >, - allocator< contract_receipt_object > - > contract_receipt_index; - class contract_storage_object : public object< contract_storage_object_type, contract_storage_object > { XGT_STD_ALLOCATOR_CONSTRUCTOR( contract_storage_object ) @@ -159,14 +127,6 @@ FC_REFLECT( xgt::chain::contract_log_object, (data) ) CHAINBASE_SET_INDEX_TYPE( xgt::chain::contract_log_object, xgt::chain::contract_log_index ) -FC_REFLECT( xgt::chain::contract_receipt_object, - (contract_hash) - (caller) - (args) - // (energy_used) - ) -CHAINBASE_SET_INDEX_TYPE( xgt::chain::contract_receipt_object, xgt::chain::contract_receipt_index ) - FC_REFLECT( xgt::chain::contract_storage_object, (id) (contract) diff --git a/libraries/chain/include/xgt/chain/xgt_object_types.hpp b/libraries/chain/include/xgt/chain/xgt_object_types.hpp index eea1ea95..87ce96e2 100644 --- a/libraries/chain/include/xgt/chain/xgt_object_types.hpp +++ b/libraries/chain/include/xgt/chain/xgt_object_types.hpp @@ -60,7 +60,6 @@ enum object_type account_authority_object_type, contract_object_type, contract_log_object_type, - contract_receipt_object_type, contract_storage_object_type, witness_object_type, transaction_object_type, @@ -105,7 +104,6 @@ class account_metadata_object; class account_authority_object; class contract_object; class contract_log_object; -class contract_receipt_object; class contract_storage_object; class witness_object; class transaction_object; @@ -150,7 +148,6 @@ typedef oid< account_metadata_object > account_metadata_id_type; typedef oid< account_authority_object > account_authority_id_type; typedef oid< contract_object > contract_id_type; typedef oid< contract_log_object > contract_log_id_type; -typedef oid< contract_receipt_object > contract_receipt_id_type; typedef oid< contract_storage_object > contract_storage_id_type; typedef oid< witness_object > witness_id_type; typedef oid< transaction_object > transaction_object_id_type; @@ -365,7 +362,6 @@ FC_REFLECT_ENUM( xgt::chain::object_type, (account_authority_object_type) (contract_object_type) (contract_log_object_type) - (contract_receipt_object_type) (contract_storage_object_type) (witness_object_type) (transaction_object_type) diff --git a/libraries/chain/xgt_evaluator.cpp b/libraries/chain/xgt_evaluator.cpp index 1ad611fb..f660c921 100644 --- a/libraries/chain/xgt_evaluator.cpp +++ b/libraries/chain/xgt_evaluator.cpp @@ -1057,7 +1057,6 @@ std::vector contract_invoke(std::string address, uint64_t energy, return std::vector(); } -// TODO make_chain_adapter will be called in contract_invoke machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type o, wallet_name_type c, contract_hash_type contract_hash) { std::string owner(o); @@ -1281,8 +1280,7 @@ void contract_invoke_evaluator::do_apply( const contract_invoke_operation& op ) }; std::vector code(c.code.begin(), c.code.end()); - // TODO: Fill in owner - machine::chain_adapter adapter = make_chain_adapter(_db, "", tx_origin, op.contract_hash); + machine::chain_adapter adapter = make_chain_adapter(_db, c.owner, tx_origin, op.contract_hash); machine::machine m(ctx, code, msg, adapter); m.print_stack(); @@ -1299,15 +1297,6 @@ void contract_invoke_evaluator::do_apply( const contract_invoke_operation& op ) while ( std::getline(m.get_logger(), line) ) std::cerr << "\e[36m" << "LOG: " << line << "\e[0m" << std::endl; std::cout << m.to_json() << std::endl; - - //// Generate receipt - //_db.create< contract_receipt_object >( [&](contract_receipt_object& cr) - //{ - // //cr.id = std::static_cast(generate_random_ripemd160()); - // cr.contract_hash = op.contract_hash; - // cr.caller = op.caller; - // cr.args = op.args; - //}); } } } // xgt::chain diff --git a/libraries/vendor/xgtvm/libraries/machine.cpp b/libraries/vendor/xgtvm/libraries/machine.cpp index a946aedb..22f318cc 100644 --- a/libraries/vendor/xgtvm/libraries/machine.cpp +++ b/libraries/vendor/xgtvm/libraries/machine.cpp @@ -2467,161 +2467,181 @@ namespace machine } const log_object o = { slice, {} }; this->emit_log(o); - - // Ex: - // log_object& o = { 0 /* data */, { 1, 2 } /* topics, 2 of them */ }; break; } case log1_opcode: { logger << "op log1" << std::endl; - // va = pop_word(); // offset - // vb = pop_word(); // length - - // std::vector topics; - - // stack_variant& stack_object = stack.front(); - // if (big_word* it = boost::get(&stack_object)) - // { - // stack.pop_front(); - // topics.push_back(*it); - // } - // else { - // throw; - // } - - // word data = memory[size_t(va)]; - // const log_object o = { data, uint8_t(vb), topics }; - // this->emit_log(o); + va = pop_word(); // offset + vb = pop_word(); // length + offset = size_t(va); + length = size_t(vb); + std::vector slice; + slice.resize(length); + for (size_t i = 0; i < length; i++) { + slice[i] = memory[offset + i]; + } + + std::vector topics; + stack_variant& stack_object = stack.front(); + if (big_word* it = boost::get(&stack_object)) + { + stack.pop_front(); + topics.push_back(*it); + } + else { + throw; + } + + const log_object o = { slice, topics }; + this->emit_log(o); break; } case log2_opcode: { logger << "op log2" << std::endl; - // va = pop_word(); // offset - // vb = pop_word(); // length - - // std::vector topics; - - // stack_variant& stack_object = stack.front(); - // if (big_word* it = boost::get(&stack_object)) - // { - // stack.pop_front(); - // topics.push_back(*it); - // } - // else { - // throw; - // } - - // stack_object = stack.front(); - // if (big_word* it = boost::get(&stack_object)) - // { - // stack.pop_front(); - // topics.push_back(*it); - // } - // else { - // throw; - // } - - // word data = memory[size_t(va)]; - // const log_object o = { data, uint8_t(vb), topics }; - // this->emit_log(o); + va = pop_word(); // offset + vb = pop_word(); // length + offset = size_t(va); + length = size_t(vb); + std::vector slice; + slice.resize(length); + for (size_t i = 0; i < length; i++) { + slice[i] = memory[offset + i]; + } + + std::vector topics; + + stack_variant& stack_object = stack.front(); + if (big_word* it = boost::get(&stack_object)) + { + stack.pop_front(); + topics.push_back(*it); + } + else { + throw; + } + + stack_object = stack.front(); + if (big_word* it = boost::get(&stack_object)) + { + stack.pop_front(); + topics.push_back(*it); + } + else { + throw; + } + + const log_object o = { slice, topics }; + this->emit_log(o); break; } case log3_opcode: { logger << "op log3" << std::endl; - // va = pop_word(); // offset - // vb = pop_word(); // length - - // std::vector topics; - - // stack_variant& stack_object = stack.front(); - // if (big_word* it = boost::get(&stack_object)) - // { - // stack.pop_front(); - // topics.push_back(*it); - // } - // else { - // throw; - // } - - // stack_object = stack.front(); - // if (big_word* it = boost::get(&stack_object)) - // { - // stack.pop_front(); - // topics.push_back(*it); - // } - // else { - // throw; - // } - - // stack_object = stack.front(); - // if (big_word* it = boost::get(&stack_object)) - // { - // stack.pop_front(); - // topics.push_back(*it); - // } - // else { - // throw; - // } - - // word data = memory[size_t(va)]; - // const log_object o = { data, uint8_t(vb), topics }; - // this->emit_log(o); + va = pop_word(); // offset + vb = pop_word(); // length + offset = size_t(va); + length = size_t(vb); + std::vector slice; + slice.resize(length); + for (size_t i = 0; i < length; i++) { + slice[i] = memory[offset + i]; + } + + std::vector topics; + + stack_variant& stack_object = stack.front(); + if (big_word* it = boost::get(&stack_object)) + { + stack.pop_front(); + topics.push_back(*it); + } + else { + throw; + } + + stack_object = stack.front(); + if (big_word* it = boost::get(&stack_object)) + { + stack.pop_front(); + topics.push_back(*it); + } + else { + throw; + } + + stack_object = stack.front(); + if (big_word* it = boost::get(&stack_object)) + { + stack.pop_front(); + topics.push_back(*it); + } + else { + throw; + } + + const log_object o = { slice, topics }; + this->emit_log(o); break; } case log4_opcode: { - // logger << "op log4" << std::endl; - // va = pop_word(); // offset - // vb = pop_word(); // length - - // std::vector topics; - - // stack_variant& stack_object = stack.front(); - // if (big_word* it = boost::get(&stack_object)) - // { - // stack.pop_front(); - // topics.push_back(*it); - // } - // else { - // throw; - // } - - // stack_object = stack.front(); - // if (big_word* it = boost::get(&stack_object)) - // { - // stack.pop_front(); - // topics.push_back(*it); - // } - // else { - // throw; - // } - - // stack_object = stack.front(); - // if (big_word* it = boost::get(&stack_object)) - // { - // stack.pop_front(); - // topics.push_back(*it); - // } - // else { - // throw; - // } - - // stack_object = stack.front(); - // if (big_word* it = boost::get(&stack_object)) - // { - // stack.pop_front(); - // topics.push_back(*it); - // } - // else { - // throw; - // } - - // word data = memory[size_t(va)]; - // const log_object o = { data, uint8_t(vb), topics }; - // this->emit_log(o); + logger << "op log4" << std::endl; + va = pop_word(); // offset + vb = pop_word(); // length + offset = size_t(va); + length = size_t(vb); + std::vector slice; + slice.resize(length); + for (size_t i = 0; i < length; i++) { + slice[i] = memory[offset + i]; + } + + std::vector topics; + + stack_variant& stack_object = stack.front(); + if (big_word* it = boost::get(&stack_object)) + { + stack.pop_front(); + topics.push_back(*it); + } + else { + throw; + } + + stack_object = stack.front(); + if (big_word* it = boost::get(&stack_object)) + { + stack.pop_front(); + topics.push_back(*it); + } + else { + throw; + } + + stack_object = stack.front(); + if (big_word* it = boost::get(&stack_object)) + { + stack.pop_front(); + topics.push_back(*it); + } + else { + throw; + } + + stack_object = stack.front(); + if (big_word* it = boost::get(&stack_object)) + { + stack.pop_front(); + topics.push_back(*it); + } + else { + throw; + } + + const log_object o = { slice, topics }; + this->emit_log(o); break; } case create_opcode: From 855bde401dede17503baf1d1b32ec5e827deea42 Mon Sep 17 00:00:00 2001 From: Roger Jungemann Date: Fri, 1 Oct 2021 16:55:23 -0700 Subject: [PATCH 60/96] LOAD and SSTORE --- libraries/chain/database.cpp | 10 ++++ .../include/xgt/chain/contract_objects.hpp | 6 +-- .../chain/include/xgt/chain/database.hpp | 3 ++ libraries/chain/xgt_evaluator.cpp | 49 +++++++++---------- libraries/vendor/xgtvm/libraries/machine.cpp | 29 ++++++++--- libraries/vendor/xgtvm/libraries/machine.hpp | 4 +- libraries/vendor/xgtvm/programs/xgtvm.cpp | 9 ++-- .../vendor/xgtvm/programs/xgtvm_tests.cpp | 9 ++-- 8 files changed, 70 insertions(+), 49 deletions(-) diff --git a/libraries/chain/database.cpp b/libraries/chain/database.cpp index 2befc7c2..2da3377d 100644 --- a/libraries/chain/database.cpp +++ b/libraries/chain/database.cpp @@ -600,6 +600,16 @@ void database::foreach_operation(std::function( boost::make_tuple( contract_hash, caller ) ); +} FC_CAPTURE_AND_RETHROW( (contract_hash)(caller) ) } + +const contract_storage_object* database::find_contract_storage( const contract_hash_type& contract_hash, const wallet_name_type& caller ) const +{ + return find< contract_storage_object, by_contract_and_caller >( boost::make_tuple( contract_hash, caller ) ); +} + const witness_object& database::get_witness( const wallet_name_type& name ) const { try { return get< witness_object, by_name >( name ); diff --git a/libraries/chain/include/xgt/chain/contract_objects.hpp b/libraries/chain/include/xgt/chain/contract_objects.hpp index 13384967..f8cde966 100644 --- a/libraries/chain/include/xgt/chain/contract_objects.hpp +++ b/libraries/chain/include/xgt/chain/contract_objects.hpp @@ -86,18 +86,14 @@ namespace xgt { namespace chain { contract_storage_id_type id; contract_hash_type contract; wallet_name_type caller; - vector data; + map data; }; - struct by_contract; - struct by_caller; struct by_contract_and_caller; typedef multi_index_container< contract_storage_object, indexed_by< - ordered_unique< tag< by_contract >, member< contract_storage_object, contract_hash_type, &contract_storage_object::contract > >, - ordered_unique< tag< by_caller >, member< contract_storage_object, wallet_name_type, &contract_storage_object::caller > >, ordered_unique< tag< by_contract_and_caller >, composite_key< contract_storage_object, member< contract_storage_object, contract_hash_type, &contract_storage_object::contract >, diff --git a/libraries/chain/include/xgt/chain/database.hpp b/libraries/chain/include/xgt/chain/database.hpp index 8f4365a3..a68c0d08 100644 --- a/libraries/chain/include/xgt/chain/database.hpp +++ b/libraries/chain/include/xgt/chain/database.hpp @@ -200,6 +200,9 @@ namespace xgt { namespace chain { void foreach_operation(std::function processor) const; + const contract_storage_object& get_contract_storage( const contract_hash_type& owner, const wallet_name_type& caller )const; + const contract_storage_object* find_contract_storage( const contract_hash_type& owner, const wallet_name_type& caller )const; + const witness_object& get_witness( const wallet_name_type& name )const; const witness_object* find_witness( const wallet_name_type& name )const; diff --git a/libraries/chain/xgt_evaluator.cpp b/libraries/chain/xgt_evaluator.cpp index f660c921..3f8833ec 100644 --- a/libraries/chain/xgt_evaluator.cpp +++ b/libraries/chain/xgt_evaluator.cpp @@ -1057,12 +1057,12 @@ std::vector contract_invoke(std::string address, uint64_t energy, return std::vector(); } -machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type o, wallet_name_type c, contract_hash_type contract_hash) +machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type o, wallet_name_type c, contract_hash_type contract_hash, map& storage) { std::string owner(o); std::string caller(c); - std::function< std::string(std::vector) > sha3 = [](std::vector memory) -> std::string + std::function< std::string(std::vector) > sha3 = [&](std::vector memory) -> std::string { std::string message(memory.begin(), memory.end()); unsigned char output[32]; @@ -1074,13 +1074,13 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type return fin; }; - std::function< uint64_t(std::string) > get_balance = [&_db](std::string address) -> uint64_t + std::function< uint64_t(std::string) > get_balance = [&](std::string address) -> uint64_t { auto& wallet = _db.get_account(address); return static_cast(wallet.balance.amount.value); }; - std::function< std::string(std::string) > get_code_hash = [&_db](std::string address) -> std::string + std::function< std::string(std::string) > get_code_hash = [&](std::string address) -> std::string { fc::ripemd160 address_ripemd160(address); const auto& contract = _db.get_contract(address_ripemd160); @@ -1095,7 +1095,7 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type }; // TODO: Revisit this, we may want to use the original sha256 hash - std::function< machine::big_word(uint64_t) > get_block_hash = [&_db](uint64_t block_num) -> machine::big_word + std::function< machine::big_word(uint64_t) > get_block_hash = [&](uint64_t block_num) -> machine::big_word { if ( block_num > _db.head_block_num() ) { return 0; @@ -1106,7 +1106,7 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type return item; }; - std::function< std::vector(std::string) > get_code_at_addr = [&_db](std::string address) -> std::vector + std::function< std::vector(std::string) > get_code_at_addr = [&](std::string address) -> std::vector { const chain::contract_object& contract = _db.get_contract(fc::ripemd160(address)); return std::vector(contract.code.begin(), contract.code.end()); @@ -1124,7 +1124,7 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type return contract_hash.str(); }; - std::function< std::vector(std::string, uint64_t, machine::big_word, std::vector) > contract_call = [](std::string address, uint64_t energy, machine::big_word value, std::vector args) -> std::vector + std::function< std::vector(std::string, uint64_t, machine::big_word, std::vector) > contract_call = [&](std::string address, uint64_t energy, machine::big_word value, std::vector args) -> std::vector { // TODO contract_invoke should return std::vector return data? // calls a method from another contract -- is value method name? @@ -1132,13 +1132,13 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type return contract_invoke(address, energy, args); }; - std::function< std::vector(std::string, uint64_t, machine::big_word, std::vector) > contract_callcode = [](std::string address, uint64_t energy, machine::big_word value, std::vector args) -> std::vector + std::function< std::vector(std::string, uint64_t, machine::big_word, std::vector) > contract_callcode = [&](std::string address, uint64_t energy, machine::big_word value, std::vector args) -> std::vector { // TODO Uses alternative account's code (args?) return contract_invoke(address, energy, args); }; - std::function< std::vector(std::string, uint64_t, std::vector) > contract_delegatecall = [](std::string address, uint64_t energy, std::vector args) -> std::vector + std::function< std::vector(std::string, uint64_t, std::vector) > contract_delegatecall = [&](std::string address, uint64_t energy, std::vector args) -> std::vector { // TODO from eth yellowpaper: Message-call into this account with an // alternative account’s code, but persisting the current values for sender @@ -1148,7 +1148,7 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type return contract_invoke(address, energy, args); }; - std::function< std::vector(std::string, uint64_t, std::vector) > contract_staticcall = [](std::string address, uint64_t energy, std::vector args) -> std::vector + std::function< std::vector(std::string, uint64_t, std::vector) > contract_staticcall = [&](std::string address, uint64_t energy, std::vector args) -> std::vector { // TODO from ethervm.io: calls a method in another contract with state // changes such as contract creation, event emission, storage modification @@ -1169,35 +1169,30 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type return ""; }; - std::function< bool(std::vector) > revert = [](std::vector memory) -> bool + std::function< bool(std::vector) > revert = [&](std::vector memory) -> bool { // TODO from eth yellowpaper: Halt execution reverting state changes but returning data and remaining gas. return true; }; - // TODO: key needs to be a machine::big_word. The `_db` method should take and return uint256_t instead - std::function< machine::big_word(std::string) > access_storage = [&_db, &owner, &caller](std::string key) -> machine::big_word + std::function< machine::big_word(machine::big_word) > get_storage = [&](uint256_t key) -> machine::big_word { - // TODO - //return _db.get_storage(owner, caller, key); - return 0; + return storage[key]; }; - // TODO: key needs to be a machine::big_word. The `_db` method should take and return uint256_t instead though - std::function< bool(std::string, machine::big_word) > set_storage = [&_db, &owner, &caller](std::string key, machine::big_word value) -> bool + std::function< bool(machine::big_word, machine::big_word) > set_storage = [&](machine::big_word key, machine::big_word value) -> bool { - // TODO - //return _db.set_storage(owner, caller, key, value); + storage[key] = value; return false; }; - std::function< bool(std::vector) > contract_return = [](std::vector memory) -> bool + std::function< bool(std::vector) > contract_return = [&](std::vector memory) -> bool { // TODO return true; }; - std::function< bool(std::string) > self_destruct = [&_db](std::string address) -> bool + std::function< bool(std::string) > self_destruct = [&](std::string address) -> bool { contract_object contract = _db.get_contract(fc::ripemd160(address)); _db.remove(contract); @@ -1237,7 +1232,7 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type contract_staticcall, contract_create2, revert, - access_storage, + get_storage, set_storage, contract_return, self_destruct, @@ -1254,8 +1249,10 @@ void contract_invoke_evaluator::do_apply( const contract_invoke_operation& op ) const contract_hash_type contract_hash = op.contract_hash; const auto& c = _db.get_contract(contract_hash); - // // const auto& args = op.args; - // // const auto& caller = op.caller; + const contract_storage_object* cs = _db.find_contract_storage(contract_hash, op.caller); + map< uint256_t, uint256_t > storage; + if (cs) + storage = cs->data; machine::message msg = {}; @@ -1280,7 +1277,7 @@ void contract_invoke_evaluator::do_apply( const contract_invoke_operation& op ) }; std::vector code(c.code.begin(), c.code.end()); - machine::chain_adapter adapter = make_chain_adapter(_db, c.owner, tx_origin, op.contract_hash); + machine::chain_adapter adapter = make_chain_adapter(_db, c.owner, tx_origin, op.contract_hash, storage); machine::machine m(ctx, code, msg, adapter); m.print_stack(); diff --git a/libraries/vendor/xgtvm/libraries/machine.cpp b/libraries/vendor/xgtvm/libraries/machine.cpp index 22f318cc..ba17797e 100644 --- a/libraries/vendor/xgtvm/libraries/machine.cpp +++ b/libraries/vendor/xgtvm/libraries/machine.cpp @@ -743,21 +743,38 @@ namespace machine case sload_opcode: logger << "op sload" << std::endl; sv = stack.front(); - if (std::string* it = boost::get(&sv)) + stack.pop_front(); + if (big_word* it = boost::get(&sv)) { - stack.pop_front(); - va = adapter.access_storage(*it); - push_word(va); + va = adapter.get_storage(*it); } else { throw; // TODO } + push_word(va); break; case sstore_opcode: logger << "op sstore" << std::endl; sv = stack.front(); - va = pop_word(); - adapter.set_storage(msg.destination, va); + stack.pop_front(); + if (big_word* it = boost::get(&sv)) + { + va = *it; + } + else { + throw; // TODO + } + + sv = stack.front(); + stack.pop_front(); + if (big_word* it = boost::get(&sv)) + { + vb = *it; + } + else { + throw; // TODO + } + adapter.set_storage(va, vb); break; case jump_opcode: logger << "op jump" << std::endl; diff --git a/libraries/vendor/xgtvm/libraries/machine.hpp b/libraries/vendor/xgtvm/libraries/machine.hpp index 49c52bbc..dd1a5462 100644 --- a/libraries/vendor/xgtvm/libraries/machine.hpp +++ b/libraries/vendor/xgtvm/libraries/machine.hpp @@ -258,10 +258,10 @@ namespace machine std::function< bool(std::vector) > revert; // TODO load opcode -- takes key as a parameter and returns value - std::function< big_word(std::string) > access_storage; + std::function< big_word(big_word) > get_storage; // TODO sstore opcode -- destination, key, value - std::function< bool(std::string, big_word) > set_storage; + std::function< void(big_word, big_word) > set_storage; // TODO return opcode std::function< bool(std::vector) > contract_return; diff --git a/libraries/vendor/xgtvm/programs/xgtvm.cpp b/libraries/vendor/xgtvm/programs/xgtvm.cpp index 917b0526..3196b183 100644 --- a/libraries/vendor/xgtvm/programs/xgtvm.cpp +++ b/libraries/vendor/xgtvm/programs/xgtvm.cpp @@ -115,14 +115,13 @@ machine::chain_adapter make_chain_adapter() return {}; }; - std::function< machine::big_word(std::string) > access_storage = [](std::string key) -> machine::big_word + std::function< machine::big_word(machine::big_word) > get_storage = [](machine::big_word) -> machine::big_word { - return {}; + return 0; }; - std::function< bool(std::string, machine::big_word) > set_storage = [](std::string key, machine::big_word value) -> bool + std::function< void(machine::big_word, machine::big_word) > set_storage = [](machine::big_word, machine::big_word value) -> void { - return {}; }; std::function< bool(std::vector) > contract_return = [](std::vector memory) -> bool @@ -153,7 +152,7 @@ machine::chain_adapter make_chain_adapter() contract_staticcall, contract_create2, revert, - access_storage, + get_storage, set_storage, contract_return, self_destruct, diff --git a/libraries/vendor/xgtvm/programs/xgtvm_tests.cpp b/libraries/vendor/xgtvm/programs/xgtvm_tests.cpp index 15e9f752..4b23c5aa 100644 --- a/libraries/vendor/xgtvm/programs/xgtvm_tests.cpp +++ b/libraries/vendor/xgtvm/programs/xgtvm_tests.cpp @@ -71,14 +71,13 @@ machine::chain_adapter make_chain_adapter() return {}; }; - std::function< machine::big_word(std::string) > access_storage = [](std::string key) -> machine::big_word + std::function< machine::big_word(machine::big_word) > get_storage = [](machine::big_word) -> machine::big_word { - return {}; + return 0; }; - std::function< bool(std::string, machine::big_word) > set_storage = [](std::string key, machine::big_word value) -> bool + std::function< void(machine::big_word, machine::big_word) > set_storage = [](machine::big_word, machine::big_word value) -> bool { - return {}; }; std::function< bool(std::vector) > contract_return = [](std::vector memory) -> bool @@ -109,7 +108,7 @@ machine::chain_adapter make_chain_adapter() contract_staticcall, contract_create2, revert, - access_storage, + get_storage, set_storage, contract_return, self_destruct, From 9be6ec9ff41603ba2c4a87efc96cd4c24c34ae80 Mon Sep 17 00:00:00 2001 From: Liam Noroian Date: Thu, 14 Oct 2021 13:09:03 -0700 Subject: [PATCH 61/96] Adding energy_interval and energy_multiplier --- libraries/chain/database.cpp | 1 + .../chain/include/xgt/chain/global_property_object.hpp | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/libraries/chain/database.cpp b/libraries/chain/database.cpp index 2da3377d..3b399ec3 100644 --- a/libraries/chain/database.cpp +++ b/libraries/chain/database.cpp @@ -1428,6 +1428,7 @@ void database::init_genesis( uint64_t init_supply ) p.reverse_auction_seconds = XGT_REVERSE_AUCTION_WINDOW_SECONDS; p.next_maintenance_time = XGT_GENESIS_TIME; p.last_budget_time = XGT_GENESIS_TIME; + p.energy_multiplier = 1; } ); for( int i = 0; i < 0x10000; i++ ) diff --git a/libraries/chain/include/xgt/chain/global_property_object.hpp b/libraries/chain/include/xgt/chain/global_property_object.hpp index 3a44e3dc..1d360d12 100644 --- a/libraries/chain/include/xgt/chain/global_property_object.hpp +++ b/libraries/chain/include/xgt/chain/global_property_object.hpp @@ -110,6 +110,12 @@ namespace xgt { namespace chain { uint16_t downvote_pool_percent = 0; asset xtt_creation_fee = asset( 1000, XGT_SYMBOL ); + + // Virtual machine energy implementation + + int64_t energy_multiplier; + + int64_t energy_interval; }; typedef multi_index_container< From d59af36cc4258998b771d07ac625a4e4691ad702 Mon Sep 17 00:00:00 2001 From: Roger Jungemann Date: Thu, 21 Oct 2021 11:23:05 -0700 Subject: [PATCH 62/96] Contract invoke stuff --- libraries/chain/xgt_evaluator.cpp | 70 +++++++++++++++++++++++++++---- 1 file changed, 61 insertions(+), 9 deletions(-) diff --git a/libraries/chain/xgt_evaluator.cpp b/libraries/chain/xgt_evaluator.cpp index 3f8833ec..6a4192a0 100644 --- a/libraries/chain/xgt_evaluator.cpp +++ b/libraries/chain/xgt_evaluator.cpp @@ -1052,9 +1052,57 @@ void contract_create_evaluator::do_apply( const contract_create_operation& op ) }); } -std::vector contract_invoke(std::string address, uint64_t energy,std::vector args) +// Forward declaration +machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type o, wallet_name_type c, contract_hash_type contract_hash, map& storage); + +std::vector contract_invoke(chain::database& _db, wallet_name_type o, wallet_name_type caller, contract_hash_type contract_hash, uint64_t energy,std::vector args, map< uint256_t, uint256_t >& storage) { - return std::vector(); + wlog("contract_invoke another contract ${w}", ("w",contract_hash)); + const auto& c = _db.get_contract(contract_hash); + + machine::message msg = {}; + + const bool is_debug = true; + const uint64_t block_timestamp = static_cast( _db.head_block_time().sec_since_epoch() ); + const uint64_t block_number = _db.head_block_num(); + const uint64_t block_difficulty = static_cast( _db.get_pow_summary_target() ); + const uint64_t block_energylimit = 0; + const uint64_t tx_energyprice = 0; + std::string tx_origin = caller; + std::string block_coinbase = caller; // verify this + + machine::context ctx = { + is_debug, + block_timestamp, + block_number, + block_difficulty, + block_energylimit, + tx_energyprice, + tx_origin, + block_coinbase + }; + + std::vector code(c.code.begin(), c.code.end()); + machine::chain_adapter adapter = make_chain_adapter(_db, c.owner, tx_origin, contract_hash, storage); + machine::machine m(ctx, code, msg, adapter); + + m.print_stack(); + + std::string line; + while (m.is_running()) + { + std::cerr << "step\n"; + m.step(); + // Print out any logging that was generated + while ( std::getline(m.get_logger(), line) ) + std::cerr << "\e[36m" << "LOG: " << line << "\e[0m" << std::endl; + } + while ( std::getline(m.get_logger(), line) ) + std::cerr << "\e[36m" << "LOG: " << line << "\e[0m" << std::endl; + std::cout << m.to_json() << std::endl; + + // TODO: return values + return std::vector(); } machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type o, wallet_name_type c, contract_hash_type contract_hash, map& storage) @@ -1126,16 +1174,18 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type std::function< std::vector(std::string, uint64_t, machine::big_word, std::vector) > contract_call = [&](std::string address, uint64_t energy, machine::big_word value, std::vector args) -> std::vector { - // TODO contract_invoke should return std::vector return data? - // calls a method from another contract -- is value method name? - - return contract_invoke(address, energy, args); + const contract_storage_object& cs = _db.get_contract_storage(contract_hash, caller); + map< uint256_t, uint256_t > storage = cs.data; + auto result = contract_invoke(_db, o, c, contract_hash, energy, args, storage); + // TODO: Update storage + return result; }; std::function< std::vector(std::string, uint64_t, machine::big_word, std::vector) > contract_callcode = [&](std::string address, uint64_t energy, machine::big_word value, std::vector args) -> std::vector { // TODO Uses alternative account's code (args?) - return contract_invoke(address, energy, args); + //return contract_invoke(address, energy, args); + return {}; }; std::function< std::vector(std::string, uint64_t, std::vector) > contract_delegatecall = [&](std::string address, uint64_t energy, std::vector args) -> std::vector @@ -1145,7 +1195,9 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type // and value // // from ethervm.io: using storage of the current contract - return contract_invoke(address, energy, args); + auto result = contract_invoke(_db, o, c, contract_hash, energy, args, storage); + // TODO: Update storage + return result; }; std::function< std::vector(std::string, uint64_t, std::vector) > contract_staticcall = [&](std::string address, uint64_t energy, std::vector args) -> std::vector @@ -1154,7 +1206,7 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type // changes such as contract creation, event emission, storage modification // and contract destruction disallowed return {}; - return contract_invoke(address, energy, args); + //return contract_invoke(address, energy, args); }; std::function< std::string(std::vector, machine::big_word, std::string) > contract_create2 = [&_db, &owner](std::vector memory, machine::big_word value, std::string salt) -> std::string From 2e46d9aadb6204ed5cd35aaf344bfeb496bef6c0 Mon Sep 17 00:00:00 2001 From: Liam Noroian Date: Thu, 21 Oct 2021 12:14:25 -0700 Subject: [PATCH 63/96] Adding energy map --- libraries/chain/xgt_evaluator.cpp | 151 ++++++++++++++++++++++++++++++ 1 file changed, 151 insertions(+) diff --git a/libraries/chain/xgt_evaluator.cpp b/libraries/chain/xgt_evaluator.cpp index 3f8833ec..f49d481c 100644 --- a/libraries/chain/xgt_evaluator.cpp +++ b/libraries/chain/xgt_evaluator.cpp @@ -18,6 +18,8 @@ #include #include +#include + #ifndef IS_LOW_MEM #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wsign-compare" @@ -1243,6 +1245,149 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type return adapter; } +std::map< uint64_t, std::function > energy_cost { + // [] == scoped variables, () == params, -> optional return type, {} == function body + {stop_opcode, [](machine::machine m){ return 0; }}, + {add_opcode, [](machine::machine m){ return 3; }}, + {mul_opcode, [](machine::machine m){ return 5; }}, + {sub_opcode, [](machine::machine m){ return 3; }}, + {div_opcode, [](machine::machine m){ return 5; }}, + {sdiv_opcode, [](machine::machine m){ return 5; }}, + {mod_opcode, [](machine::machine m){ return 5; }}, + {smod_opcode, [](machine::machine m){ return 5; }}, + {addmod_opcode, [](machine::machine m){ return 8; }}, + {mulmod_opcode, [](machine::machine m){ return 8; }}, + {exp_opcode, [](machine::machine m){ return 0}}, // TODO -- Exp -- variab; le + {signextend_opcode, [](machine::machine m){ return 5; }}, + {lt_opcode, [](machine::machine m){ return 3; }}, + {gt_opcode, [](machine::machine m){ return 3; }}, + {slt_opcode, [](machine::machine m){ return 3; }}, + {sgt_opcode, [](machine::machine m){ return 3; }}, + {eq_opcode, [](machine::machine m){ return 3; }}, + {iszero_opcode, [](machine::machine m){ return 3; }}, + {and_opcode, [](machine::machine m){ return 3; }}, + {or_opcode, [](machine::machine m){ return 3; }}, + {xor_opcode, [](machine::machine m){ return 3; }}, + {not_opcode, [](machine::machine m){ return 3; }}, + {byte_opcode, [](machine::machine m){ return 3; }}, + {shl_opcode, [](machine::machine m){ return 3; }}, + {shr_opcode, [](machine::machine m){ return 3; }}, + {sar_opcode, [](machine::machine m){ return 3; }}, + {sha3_opcode, [](machine::machine m){ return 0}}, // TODO -- SHA3 -- variab; le + {address_opcode, [](machine::machine m){ return 2; }}, + {balance_opcode, [](machine::machine m){ return 700; }}, + {origin_opcode, [](machine::machine m){ return 2; }}, + {caller_opcode, [](machine::machine m){ return 2; }}, + {callvalue_opcode, [](machine::machine m){ return 2; }}, + {calldataload_opcode, [](machine::machine m){ return 3; }}, + {calldatasize_opcode, [](machine::machine m){ return 2; }}, + {calldatacopy_opcode, [](machine::machine m){ return 0}}, // TODO -- calldatacoy -- variab; le + {codesize_opcode, [](machine::machine m){ return 2; }}, + {codecopy_opcode, [](machine::machine m){ return 0}}, // TODO -- codecopy -- variab; le + {energyprice_opcode, [](machine::machine m){ return 2; }}, + {extcodesize_opcode, [](machine::machine m){ return 700; }}, + {extcodecopy_opcode, [](machine::machine m){ return 0}}, // TODO -- extcodecopy -- variab; le + {returndatasize_opcode, [](machine::machine m){ return 2; }}, + {returndatacopy_opcode, [](machine::machine m){ return 0}}, // TODO -- returndatacopy -- variab; le + {extcodehash_opcode, [](machine::machine m){ return 700; }}, + {blockhash_opcode, [](machine::machine m){ return 20; }}, + {coinbase_opcode, [](machine::machine m){ return 2; }}, + {timestamp_opcode, [](machine::machine m){ return 2; }}, + {number_opcode, [](machine::machine m){ return 2; }}, + {difficulty_opcode, [](machine::machine m){ return 2; }}, + {energylimit_opcode, [](machine::machine m){ return 2; }}, + {pop_opcode, [](machine::machine m){ return 3; }}, + {mload_opcode, [](machine::machine m){ return 3; }}, + {mstore_opcode, [](machine::machine m){ return 3; }}, + {mstore8_opcode, [](machine::machine m){ return 3; }}, + {sload_opcode, [](machine::machine m){ return 800; }}, + {sstore_opcode, [](machine::machine m){ return 0; }}, // TODO -- sstore -- variab; le + {jump_opcode, [](machine::machine m){ return 8; }}, + {jumpi_opcode, [](machine::machine m){ return 10; }}, + {pc_opcode, [](machine::machine m){ return 2; }}, + {msize_opcode, [](machine::machine m){ return 2; }}, + {energy_opcode, [](machine::machine m){ return 2; }}, + {jumpdest_opcode, [](machine::machine m){ return 1; }}, + {push1_opcode, [](machine::machine m){ return 3; }}, + {push2_opcode, [](machine::machine m){ return 3; }}, + {push3_opcode, [](machine::machine m){ return 3; }}, + {push4_opcode, [](machine::machine m){ return 3; }}, + {push5_opcode, [](machine::machine m){ return 3; }}, + {push6_opcode, [](machine::machine m){ return 3; }}, + {push7_opcode, [](machine::machine m){ return 3; }}, + {push8_opcode, [](machine::machine m){ return 3; }}, + {push9_opcode, [](machine::machine m){ return 3; }}, + {push10_opcode, [](machine::machine m){ return 3; }}, + {push11_opcode, [](machine::machine m){ return 3; }}, + {push12_opcode, [](machine::machine m){ return 3; }}, + {push13_opcode, [](machine::machine m){ return 3; }}, + {push14_opcode, [](machine::machine m){ return 3; }}, + {push15_opcode, [](machine::machine m){ return 3; }}, + {push16_opcode, [](machine::machine m){ return 3; }}, + {push17_opcode, [](machine::machine m){ return 3; }}, + {push18_opcode, [](machine::machine m){ return 3; }}, + {push19_opcode, [](machine::machine m){ return 3; }}, + {push20_opcode, [](machine::machine m){ return 3; }}, + {push21_opcode, [](machine::machine m){ return 3; }}, + {push22_opcode, [](machine::machine m){ return 3; }}, + {push23_opcode, [](machine::machine m){ return 3; }}, + {push24_opcode, [](machine::machine m){ return 3; }}, + {push25_opcode, [](machine::machine m){ return 3; }}, + {push26_opcode, [](machine::machine m){ return 3; }}, + {push27_opcode, [](machine::machine m){ return 3; }}, + {push28_opcode, [](machine::machine m){ return 3; }}, + {push29_opcode, [](machine::machine m){ return 3; }}, + {push30_opcode, [](machine::machine m){ return 3; }}, + {push31_opcode, [](machine::machine m){ return 3; }}, + {push32_opcode, [](machine::machine m){ return 3; }}, + {dup1_opcode, [](machine::machine m){ return 3; }}, + {dup2_opcode, [](machine::machine m){ return 3; }}, + {dup3_opcode, [](machine::machine m){ return 3; }}, + {dup4_opcode, [](machine::machine m){ return 3; }}, + {dup5_opcode, [](machine::machine m){ return 3; }}, + {dup6_opcode, [](machine::machine m){ return 3; }}, + {dup7_opcode, [](machine::machine m){ return 3; }}, + {dup8_opcode, [](machine::machine m){ return 3; }}, + {dup9_opcode, [](machine::machine m){ return 3; }}, + {dup10_opcode, [](machine::machine m){ return 3; }}, + {dup11_opcode, [](machine::machine m){ return 3; }}, + {dup12_opcode, [](machine::machine m){ return 3; }}, + {dup13_opcode, [](machine::machine m){ return 3; }}, + {dup14_opcode, [](machine::machine m){ return 3; }}, + {dup15_opcode, [](machine::machine m){ return 3; }}, + {dup16_opcode, [](machine::machine m){ return 3; }}, + {swap1_opcode, [](machine::machine m){ return 3; }}, + {swap2_opcode, [](machine::machine m){ return 3; }}, + {swap3_opcode, [](machine::machine m){ return 3; }}, + {swap4_opcode, [](machine::machine m){ return 3; }}, + {swap5_opcode, [](machine::machine m){ return 3; }}, + {swap6_opcode, [](machine::machine m){ return 3; }}, + {swap7_opcode, [](machine::machine m){ return 3; }}, + {swap8_opcode, [](machine::machine m){ return 3; }}, + {swap9_opcode, [](machine::machine m){ return 3; }}, + {swap10_opcode, [](machine::machine m){ return 3; }}, + {swap11_opcode, [](machine::machine m){ return 3; }}, + {swap12_opcode, [](machine::machine m){ return 3; }}, + {swap13_opcode, [](machine::machine m){ return 3; }}, + {swap14_opcode, [](machine::machine m){ return 3; }}, + {swap15_opcode, [](machine::machine m){ return 3; }}, + {swap16_opcode, [](machine::machine m){ return 3; }}, + {log0_opcode, [](machine::machine m){ return 0; }}, // TODO -- log0 -- variable + {log1_opcode, [](machine::machine m){ return 0; }}, // TODO -- log1 -- variable + {log2_opcode, [](machine::machine m){ return 0; }}, // TODO -- log2 -- variable + {log3_opcode, [](machine::machine m){ return 0; }}, // TODO -- log3 -- variable + {log4_opcode, [](machine::machine m){ return 0; }}, // TODO -- log4 -- variable + {create_opcode, [](machine::machine m){ return 0; }}, // TODO -- create -- variable + {call_opcode, [](machine::machine m){ return 0; }}, // TODO -- call -- variable + {callcode_opcode, [](machine::machine m){ return 0; }}, // TODO -- callcode -- variable + {return_opcode, [](machine::machine m){ return 0; }}, + {delegatecall_opcode, [](machine::machine m){ return 0; }}, // TODO -- delegatecall -- variable + {create2_opcode, [](machine::machine m){ return 0; }}, // TODO -- create2 -- variable + {staticcall_opcode, [](machine::machine m){ return 0; }}, // TODO -- staticcall -- variable + {revert_opcode, [](machine::machine m){ return 0; }}, + {selfdestruct_opcode, [](machine::machine m){ return 0; }} // TODO -- selfdestruct -- variable +}; + void contract_invoke_evaluator::do_apply( const contract_invoke_operation& op ) { wlog("contract_invoke ${w}", ("w",op.contract_hash)); @@ -1276,6 +1421,8 @@ void contract_invoke_evaluator::do_apply( const contract_invoke_operation& op ) block_coinbase }; + int64_t energy_cost_incurred = 0; + std::vector code(c.code.begin(), c.code.end()); machine::chain_adapter adapter = make_chain_adapter(_db, c.owner, tx_origin, op.contract_hash, storage); machine::machine m(ctx, code, msg, adapter); @@ -1283,10 +1430,14 @@ void contract_invoke_evaluator::do_apply( const contract_invoke_operation& op ) m.print_stack(); std::string line; + // Get current opcode in machine at each step while (m.is_running()) { std::cerr << "step\n"; m.step(); + auto energy_callback = energy_cost[m.current_opcode]; + // Calculate energy cost and add to total + energy_cost_incurred += energy_callback(m); // Print out any logging that was generated while ( std::getline(m.get_logger(), line) ) std::cerr << "\e[36m" << "LOG: " << line << "\e[0m" << std::endl; From c8a9663f2bfdd2262403be41d5a1ee57a07122ab Mon Sep 17 00:00:00 2001 From: Liam Noroian Date: Mon, 25 Oct 2021 06:14:42 -0700 Subject: [PATCH 64/96] Vendor updated xgtvm --- libraries/chain/xgt_evaluator.cpp | 280 +++++++++--------- libraries/vendor/xgtvm/libraries/machine.cpp | 1 + libraries/vendor/xgtvm/libraries/machine.hpp | 6 +- .../vendor/xgtvm/programs/xgtvm_tests.cpp | 3 +- 4 files changed, 146 insertions(+), 144 deletions(-) diff --git a/libraries/chain/xgt_evaluator.cpp b/libraries/chain/xgt_evaluator.cpp index f49d481c..9f530a19 100644 --- a/libraries/chain/xgt_evaluator.cpp +++ b/libraries/chain/xgt_evaluator.cpp @@ -1247,145 +1247,145 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type std::map< uint64_t, std::function > energy_cost { // [] == scoped variables, () == params, -> optional return type, {} == function body - {stop_opcode, [](machine::machine m){ return 0; }}, - {add_opcode, [](machine::machine m){ return 3; }}, - {mul_opcode, [](machine::machine m){ return 5; }}, - {sub_opcode, [](machine::machine m){ return 3; }}, - {div_opcode, [](machine::machine m){ return 5; }}, - {sdiv_opcode, [](machine::machine m){ return 5; }}, - {mod_opcode, [](machine::machine m){ return 5; }}, - {smod_opcode, [](machine::machine m){ return 5; }}, - {addmod_opcode, [](machine::machine m){ return 8; }}, - {mulmod_opcode, [](machine::machine m){ return 8; }}, - {exp_opcode, [](machine::machine m){ return 0}}, // TODO -- Exp -- variab; le - {signextend_opcode, [](machine::machine m){ return 5; }}, - {lt_opcode, [](machine::machine m){ return 3; }}, - {gt_opcode, [](machine::machine m){ return 3; }}, - {slt_opcode, [](machine::machine m){ return 3; }}, - {sgt_opcode, [](machine::machine m){ return 3; }}, - {eq_opcode, [](machine::machine m){ return 3; }}, - {iszero_opcode, [](machine::machine m){ return 3; }}, - {and_opcode, [](machine::machine m){ return 3; }}, - {or_opcode, [](machine::machine m){ return 3; }}, - {xor_opcode, [](machine::machine m){ return 3; }}, - {not_opcode, [](machine::machine m){ return 3; }}, - {byte_opcode, [](machine::machine m){ return 3; }}, - {shl_opcode, [](machine::machine m){ return 3; }}, - {shr_opcode, [](machine::machine m){ return 3; }}, - {sar_opcode, [](machine::machine m){ return 3; }}, - {sha3_opcode, [](machine::machine m){ return 0}}, // TODO -- SHA3 -- variab; le - {address_opcode, [](machine::machine m){ return 2; }}, - {balance_opcode, [](machine::machine m){ return 700; }}, - {origin_opcode, [](machine::machine m){ return 2; }}, - {caller_opcode, [](machine::machine m){ return 2; }}, - {callvalue_opcode, [](machine::machine m){ return 2; }}, - {calldataload_opcode, [](machine::machine m){ return 3; }}, - {calldatasize_opcode, [](machine::machine m){ return 2; }}, - {calldatacopy_opcode, [](machine::machine m){ return 0}}, // TODO -- calldatacoy -- variab; le - {codesize_opcode, [](machine::machine m){ return 2; }}, - {codecopy_opcode, [](machine::machine m){ return 0}}, // TODO -- codecopy -- variab; le - {energyprice_opcode, [](machine::machine m){ return 2; }}, - {extcodesize_opcode, [](machine::machine m){ return 700; }}, - {extcodecopy_opcode, [](machine::machine m){ return 0}}, // TODO -- extcodecopy -- variab; le - {returndatasize_opcode, [](machine::machine m){ return 2; }}, - {returndatacopy_opcode, [](machine::machine m){ return 0}}, // TODO -- returndatacopy -- variab; le - {extcodehash_opcode, [](machine::machine m){ return 700; }}, - {blockhash_opcode, [](machine::machine m){ return 20; }}, - {coinbase_opcode, [](machine::machine m){ return 2; }}, - {timestamp_opcode, [](machine::machine m){ return 2; }}, - {number_opcode, [](machine::machine m){ return 2; }}, - {difficulty_opcode, [](machine::machine m){ return 2; }}, - {energylimit_opcode, [](machine::machine m){ return 2; }}, - {pop_opcode, [](machine::machine m){ return 3; }}, - {mload_opcode, [](machine::machine m){ return 3; }}, - {mstore_opcode, [](machine::machine m){ return 3; }}, - {mstore8_opcode, [](machine::machine m){ return 3; }}, - {sload_opcode, [](machine::machine m){ return 800; }}, - {sstore_opcode, [](machine::machine m){ return 0; }}, // TODO -- sstore -- variab; le - {jump_opcode, [](machine::machine m){ return 8; }}, - {jumpi_opcode, [](machine::machine m){ return 10; }}, - {pc_opcode, [](machine::machine m){ return 2; }}, - {msize_opcode, [](machine::machine m){ return 2; }}, - {energy_opcode, [](machine::machine m){ return 2; }}, - {jumpdest_opcode, [](machine::machine m){ return 1; }}, - {push1_opcode, [](machine::machine m){ return 3; }}, - {push2_opcode, [](machine::machine m){ return 3; }}, - {push3_opcode, [](machine::machine m){ return 3; }}, - {push4_opcode, [](machine::machine m){ return 3; }}, - {push5_opcode, [](machine::machine m){ return 3; }}, - {push6_opcode, [](machine::machine m){ return 3; }}, - {push7_opcode, [](machine::machine m){ return 3; }}, - {push8_opcode, [](machine::machine m){ return 3; }}, - {push9_opcode, [](machine::machine m){ return 3; }}, - {push10_opcode, [](machine::machine m){ return 3; }}, - {push11_opcode, [](machine::machine m){ return 3; }}, - {push12_opcode, [](machine::machine m){ return 3; }}, - {push13_opcode, [](machine::machine m){ return 3; }}, - {push14_opcode, [](machine::machine m){ return 3; }}, - {push15_opcode, [](machine::machine m){ return 3; }}, - {push16_opcode, [](machine::machine m){ return 3; }}, - {push17_opcode, [](machine::machine m){ return 3; }}, - {push18_opcode, [](machine::machine m){ return 3; }}, - {push19_opcode, [](machine::machine m){ return 3; }}, - {push20_opcode, [](machine::machine m){ return 3; }}, - {push21_opcode, [](machine::machine m){ return 3; }}, - {push22_opcode, [](machine::machine m){ return 3; }}, - {push23_opcode, [](machine::machine m){ return 3; }}, - {push24_opcode, [](machine::machine m){ return 3; }}, - {push25_opcode, [](machine::machine m){ return 3; }}, - {push26_opcode, [](machine::machine m){ return 3; }}, - {push27_opcode, [](machine::machine m){ return 3; }}, - {push28_opcode, [](machine::machine m){ return 3; }}, - {push29_opcode, [](machine::machine m){ return 3; }}, - {push30_opcode, [](machine::machine m){ return 3; }}, - {push31_opcode, [](machine::machine m){ return 3; }}, - {push32_opcode, [](machine::machine m){ return 3; }}, - {dup1_opcode, [](machine::machine m){ return 3; }}, - {dup2_opcode, [](machine::machine m){ return 3; }}, - {dup3_opcode, [](machine::machine m){ return 3; }}, - {dup4_opcode, [](machine::machine m){ return 3; }}, - {dup5_opcode, [](machine::machine m){ return 3; }}, - {dup6_opcode, [](machine::machine m){ return 3; }}, - {dup7_opcode, [](machine::machine m){ return 3; }}, - {dup8_opcode, [](machine::machine m){ return 3; }}, - {dup9_opcode, [](machine::machine m){ return 3; }}, - {dup10_opcode, [](machine::machine m){ return 3; }}, - {dup11_opcode, [](machine::machine m){ return 3; }}, - {dup12_opcode, [](machine::machine m){ return 3; }}, - {dup13_opcode, [](machine::machine m){ return 3; }}, - {dup14_opcode, [](machine::machine m){ return 3; }}, - {dup15_opcode, [](machine::machine m){ return 3; }}, - {dup16_opcode, [](machine::machine m){ return 3; }}, - {swap1_opcode, [](machine::machine m){ return 3; }}, - {swap2_opcode, [](machine::machine m){ return 3; }}, - {swap3_opcode, [](machine::machine m){ return 3; }}, - {swap4_opcode, [](machine::machine m){ return 3; }}, - {swap5_opcode, [](machine::machine m){ return 3; }}, - {swap6_opcode, [](machine::machine m){ return 3; }}, - {swap7_opcode, [](machine::machine m){ return 3; }}, - {swap8_opcode, [](machine::machine m){ return 3; }}, - {swap9_opcode, [](machine::machine m){ return 3; }}, - {swap10_opcode, [](machine::machine m){ return 3; }}, - {swap11_opcode, [](machine::machine m){ return 3; }}, - {swap12_opcode, [](machine::machine m){ return 3; }}, - {swap13_opcode, [](machine::machine m){ return 3; }}, - {swap14_opcode, [](machine::machine m){ return 3; }}, - {swap15_opcode, [](machine::machine m){ return 3; }}, - {swap16_opcode, [](machine::machine m){ return 3; }}, - {log0_opcode, [](machine::machine m){ return 0; }}, // TODO -- log0 -- variable - {log1_opcode, [](machine::machine m){ return 0; }}, // TODO -- log1 -- variable - {log2_opcode, [](machine::machine m){ return 0; }}, // TODO -- log2 -- variable - {log3_opcode, [](machine::machine m){ return 0; }}, // TODO -- log3 -- variable - {log4_opcode, [](machine::machine m){ return 0; }}, // TODO -- log4 -- variable - {create_opcode, [](machine::machine m){ return 0; }}, // TODO -- create -- variable - {call_opcode, [](machine::machine m){ return 0; }}, // TODO -- call -- variable - {callcode_opcode, [](machine::machine m){ return 0; }}, // TODO -- callcode -- variable - {return_opcode, [](machine::machine m){ return 0; }}, - {delegatecall_opcode, [](machine::machine m){ return 0; }}, // TODO -- delegatecall -- variable - {create2_opcode, [](machine::machine m){ return 0; }}, // TODO -- create2 -- variable - {staticcall_opcode, [](machine::machine m){ return 0; }}, // TODO -- staticcall -- variable - {revert_opcode, [](machine::machine m){ return 0; }}, - {selfdestruct_opcode, [](machine::machine m){ return 0; }} // TODO -- selfdestruct -- variable + {machine::stop_opcode, [](machine::machine m){ return 0; }}, + {machine::add_opcode, [](machine::machine m){ return 3; }}, + {machine::mul_opcode, [](machine::machine m){ return 5; }}, + {machine::sub_opcode, [](machine::machine m){ return 3; }}, + {machine::div_opcode, [](machine::machine m){ return 5; }}, + {machine::sdiv_opcode, [](machine::machine m){ return 5; }}, + {machine::mod_opcode, [](machine::machine m){ return 5; }}, + {machine::smod_opcode, [](machine::machine m){ return 5; }}, + {machine::addmod_opcode, [](machine::machine m){ return 8; }}, + {machine::mulmod_opcode, [](machine::machine m){ return 8; }}, + {machine::exp_opcode, [](machine::machine m){ return 0; }}, // TODO -- Exp -- variab; le + {machine::signextend_opcode, [](machine::machine m){ return 5; }}, + {machine::lt_opcode, [](machine::machine m){ return 3; }}, + {machine::gt_opcode, [](machine::machine m){ return 3; }}, + {machine::slt_opcode, [](machine::machine m){ return 3; }}, + {machine::sgt_opcode, [](machine::machine m){ return 3; }}, + {machine::eq_opcode, [](machine::machine m){ return 3; }}, + {machine::iszero_opcode, [](machine::machine m){ return 3; }}, + {machine::and_opcode, [](machine::machine m){ return 3; }}, + {machine::or_opcode, [](machine::machine m){ return 3; }}, + {machine::xor_opcode, [](machine::machine m){ return 3; }}, + {machine::not_opcode, [](machine::machine m){ return 3; }}, + {machine::byte_opcode, [](machine::machine m){ return 3; }}, + {machine::shl_opcode, [](machine::machine m){ return 3; }}, + {machine::shr_opcode, [](machine::machine m){ return 3; }}, + {machine::sar_opcode, [](machine::machine m){ return 3; }}, + {machine::sha3_opcode, [](machine::machine m){ return 0; }}, // TODO -- SHA3 -- variab; le + {machine::address_opcode, [](machine::machine m){ return 2; }}, + {machine::balance_opcode, [](machine::machine m){ return 700; }}, + {machine::origin_opcode, [](machine::machine m){ return 2; }}, + {machine::caller_opcode, [](machine::machine m){ return 2; }}, + {machine::callvalue_opcode, [](machine::machine m){ return 2; }}, + {machine::calldataload_opcode, [](machine::machine m){ return 3; }}, + {machine::calldatasize_opcode, [](machine::machine m){ return 2; }}, + {machine::calldatacopy_opcode, [](machine::machine m){ return 0; }}, // TODO -- calldatacoy -- variab; le + {machine::codesize_opcode, [](machine::machine m){ return 2; }}, + {machine::codecopy_opcode, [](machine::machine m){ return 0; }}, // TODO -- codecopy -- variab; le + {machine::energyprice_opcode, [](machine::machine m){ return 2; }}, + {machine::extcodesize_opcode, [](machine::machine m){ return 700; }}, + {machine::extcodecopy_opcode, [](machine::machine m){ return 0; }}, // TODO -- extcodecopy -- variab; le + {machine::returndatasize_opcode, [](machine::machine m){ return 2; }}, + {machine::returndatacopy_opcode, [](machine::machine m){ return 0; }}, // TODO -- returndatacopy -- variab; le + {machine::extcodehash_opcode, [](machine::machine m){ return 700; }}, + {machine::blockhash_opcode, [](machine::machine m){ return 20; }}, + {machine::coinbase_opcode, [](machine::machine m){ return 2; }}, + {machine::timestamp_opcode, [](machine::machine m){ return 2; }}, + {machine::number_opcode, [](machine::machine m){ return 2; }}, + {machine::difficulty_opcode, [](machine::machine m){ return 2; }}, + {machine::energylimit_opcode, [](machine::machine m){ return 2; }}, + {machine::pop_opcode, [](machine::machine m){ return 3; }}, + {machine::mload_opcode, [](machine::machine m){ return 3; }}, + {machine::mstore_opcode, [](machine::machine m){ return 3; }}, + {machine::mstore8_opcode, [](machine::machine m){ return 3; }}, + {machine::sload_opcode, [](machine::machine m){ return 800; }}, + {machine::sstore_opcode, [](machine::machine m){ return 0; }}, // TODO -- sstore -- variab; le + {machine::jump_opcode, [](machine::machine m){ return 8; }}, + {machine::jumpi_opcode, [](machine::machine m){ return 10; }}, + {machine::pc_opcode, [](machine::machine m){ return 2; }}, + {machine::msize_opcode, [](machine::machine m){ return 2; }}, + {machine::energy_opcode, [](machine::machine m){ return 2; }}, + {machine::jumpdest_opcode, [](machine::machine m){ return 1; }}, + {machine::push1_opcode, [](machine::machine m){ return 3; }}, + {machine::push2_opcode, [](machine::machine m){ return 3; }}, + {machine::push3_opcode, [](machine::machine m){ return 3; }}, + {machine::push4_opcode, [](machine::machine m){ return 3; }}, + {machine::push5_opcode, [](machine::machine m){ return 3; }}, + {machine::push6_opcode, [](machine::machine m){ return 3; }}, + {machine::push7_opcode, [](machine::machine m){ return 3; }}, + {machine::push8_opcode, [](machine::machine m){ return 3; }}, + {machine::push9_opcode, [](machine::machine m){ return 3; }}, + {machine::push10_opcode, [](machine::machine m){ return 3; }}, + {machine::push11_opcode, [](machine::machine m){ return 3; }}, + {machine::push12_opcode, [](machine::machine m){ return 3; }}, + {machine::push13_opcode, [](machine::machine m){ return 3; }}, + {machine::push14_opcode, [](machine::machine m){ return 3; }}, + {machine::push15_opcode, [](machine::machine m){ return 3; }}, + {machine::push16_opcode, [](machine::machine m){ return 3; }}, + {machine::push17_opcode, [](machine::machine m){ return 3; }}, + {machine::push18_opcode, [](machine::machine m){ return 3; }}, + {machine::push19_opcode, [](machine::machine m){ return 3; }}, + {machine::push20_opcode, [](machine::machine m){ return 3; }}, + {machine::push21_opcode, [](machine::machine m){ return 3; }}, + {machine::push22_opcode, [](machine::machine m){ return 3; }}, + {machine::push23_opcode, [](machine::machine m){ return 3; }}, + {machine::push24_opcode, [](machine::machine m){ return 3; }}, + {machine::push25_opcode, [](machine::machine m){ return 3; }}, + {machine::push26_opcode, [](machine::machine m){ return 3; }}, + {machine::push27_opcode, [](machine::machine m){ return 3; }}, + {machine::push28_opcode, [](machine::machine m){ return 3; }}, + {machine::push29_opcode, [](machine::machine m){ return 3; }}, + {machine::push30_opcode, [](machine::machine m){ return 3; }}, + {machine::push31_opcode, [](machine::machine m){ return 3; }}, + {machine::push32_opcode, [](machine::machine m){ return 3; }}, + {machine::dup1_opcode, [](machine::machine m){ return 3; }}, + {machine::dup2_opcode, [](machine::machine m){ return 3; }}, + {machine::dup3_opcode, [](machine::machine m){ return 3; }}, + {machine::dup4_opcode, [](machine::machine m){ return 3; }}, + {machine::dup5_opcode, [](machine::machine m){ return 3; }}, + {machine::dup6_opcode, [](machine::machine m){ return 3; }}, + {machine::dup7_opcode, [](machine::machine m){ return 3; }}, + {machine::dup8_opcode, [](machine::machine m){ return 3; }}, + {machine::dup9_opcode, [](machine::machine m){ return 3; }}, + {machine::dup10_opcode, [](machine::machine m){ return 3; }}, + {machine::dup11_opcode, [](machine::machine m){ return 3; }}, + {machine::dup12_opcode, [](machine::machine m){ return 3; }}, + {machine::dup13_opcode, [](machine::machine m){ return 3; }}, + {machine::dup14_opcode, [](machine::machine m){ return 3; }}, + {machine::dup15_opcode, [](machine::machine m){ return 3; }}, + {machine::dup16_opcode, [](machine::machine m){ return 3; }}, + {machine::swap1_opcode, [](machine::machine m){ return 3; }}, + {machine::swap2_opcode, [](machine::machine m){ return 3; }}, + {machine::swap3_opcode, [](machine::machine m){ return 3; }}, + {machine::swap4_opcode, [](machine::machine m){ return 3; }}, + {machine::swap5_opcode, [](machine::machine m){ return 3; }}, + {machine::swap6_opcode, [](machine::machine m){ return 3; }}, + {machine::swap7_opcode, [](machine::machine m){ return 3; }}, + {machine::swap8_opcode, [](machine::machine m){ return 3; }}, + {machine::swap9_opcode, [](machine::machine m){ return 3; }}, + {machine::swap10_opcode, [](machine::machine m){ return 3; }}, + {machine::swap11_opcode, [](machine::machine m){ return 3; }}, + {machine::swap12_opcode, [](machine::machine m){ return 3; }}, + {machine::swap13_opcode, [](machine::machine m){ return 3; }}, + {machine::swap14_opcode, [](machine::machine m){ return 3; }}, + {machine::swap15_opcode, [](machine::machine m){ return 3; }}, + {machine::swap16_opcode, [](machine::machine m){ return 3; }}, + {machine::log0_opcode, [](machine::machine m){ return 0; }}, // TODO -- log0 -- variable + {machine::log1_opcode, [](machine::machine m){ return 0; }}, // TODO -- log1 -- variable + {machine::log2_opcode, [](machine::machine m){ return 0; }}, // TODO -- log2 -- variable + {machine::log3_opcode, [](machine::machine m){ return 0; }}, // TODO -- log3 -- variable + {machine::log4_opcode, [](machine::machine m){ return 0; }}, // TODO -- log4 -- variable + {machine::create_opcode, [](machine::machine m){ return 0; }}, // TODO -- create -- variable + {machine::call_opcode, [](machine::machine m){ return 0; }}, // TODO -- call -- variable + {machine::callcode_opcode, [](machine::machine m){ return 0; }}, // TODO -- callcode -- variable + {machine::return_opcode, [](machine::machine m){ return 0; }}, + {machine::delegatecall_opcode, [](machine::machine m){ return 0; }}, // TODO -- delegatecall -- variable + {machine::create2_opcode, [](machine::machine m){ return 0; }}, // TODO -- create2 -- variable + {machine::staticcall_opcode, [](machine::machine m){ return 0; }}, // TODO -- staticcall -- variable + {machine::revert_opcode, [](machine::machine m){ return 0; }}, + {machine::selfdestruct_opcode, [](machine::machine m){ return 0; }} // TODO -- selfdestruct -- variable }; void contract_invoke_evaluator::do_apply( const contract_invoke_operation& op ) @@ -1435,7 +1435,7 @@ void contract_invoke_evaluator::do_apply( const contract_invoke_operation& op ) { std::cerr << "step\n"; m.step(); - auto energy_callback = energy_cost[m.current_opcode]; + auto energy_callback = energy_cost[m.get_current_opcode()]; // Calculate energy cost and add to total energy_cost_incurred += energy_callback(m); // Print out any logging that was generated diff --git a/libraries/vendor/xgtvm/libraries/machine.cpp b/libraries/vendor/xgtvm/libraries/machine.cpp index ba17797e..db15ab71 100644 --- a/libraries/vendor/xgtvm/libraries/machine.cpp +++ b/libraries/vendor/xgtvm/libraries/machine.cpp @@ -249,6 +249,7 @@ namespace machine } word current_instruction = code[pc]; opcode op = (opcode)current_instruction; + current_opcode = op; pc++; logger << "step pc " << std::to_string(pc) << " opcode " << std::hex << op << std::dec << std::endl; diff --git a/libraries/vendor/xgtvm/libraries/machine.hpp b/libraries/vendor/xgtvm/libraries/machine.hpp index dd1a5462..e09ebd7f 100644 --- a/libraries/vendor/xgtvm/libraries/machine.hpp +++ b/libraries/vendor/xgtvm/libraries/machine.hpp @@ -12,7 +12,6 @@ namespace machine { - typedef uint8_t word; typedef boost::multiprecision::uint256_t big_word; typedef boost::multiprecision::int256_t signed_big_word; @@ -190,7 +189,6 @@ namespace machine std::vector topics; }; - struct message { uint32_t flags; @@ -206,7 +204,7 @@ namespace machine size_t code_size; }; - // TODO replace with correct data types + // TODO ensure correct data types struct context { bool is_debug; @@ -291,6 +289,7 @@ namespace machine std::stringstream logger; chain_adapter adapter; big_word energy_left; + opcode current_opcode = stop_opcode; void push_word(stack_variant v); big_word pop_word(); @@ -311,6 +310,7 @@ namespace machine machine_state get_state(); boost::optional get_error_message(); std::stringstream& get_logger(); + opcode get_current_opcode() { return current_opcode; }; std::string to_json(); void emit_log(const log_object& o); diff --git a/libraries/vendor/xgtvm/programs/xgtvm_tests.cpp b/libraries/vendor/xgtvm/programs/xgtvm_tests.cpp index 4b23c5aa..83f37fbb 100644 --- a/libraries/vendor/xgtvm/programs/xgtvm_tests.cpp +++ b/libraries/vendor/xgtvm/programs/xgtvm_tests.cpp @@ -76,8 +76,9 @@ machine::chain_adapter make_chain_adapter() return 0; }; - std::function< void(machine::big_word, machine::big_word) > set_storage = [](machine::big_word, machine::big_word value) -> bool + std::function< bool(machine::big_word, machine::big_word) > set_storage = [](machine::big_word, machine::big_word value) -> bool { + return 0; }; std::function< bool(std::vector) > contract_return = [](std::vector memory) -> bool From 9759f5792984af61a9f999d62f84ede51123199a Mon Sep 17 00:00:00 2001 From: Roger Jungemann Date: Thu, 28 Oct 2021 20:14:53 -0700 Subject: [PATCH 65/96] WIP: pack and unpack uiint256_t --- Rakefile | 42 +++++++++++++++++++ .../include/xgt/chain/contract_objects.hpp | 9 ++-- libraries/chain/index.cpp | 3 ++ libraries/chain/xgt_evaluator.cpp | 2 +- libraries/fc/include/fc/io/raw.hpp | 37 ++++++++++++++++ 5 files changed, 89 insertions(+), 4 deletions(-) diff --git a/Rakefile b/Rakefile index 7425853d..0ba15bd8 100644 --- a/Rakefile +++ b/Rakefile @@ -428,6 +428,11 @@ namespace :contracts do task :create do keys = generate_keys create_wallet!(keys) + # Bytecode explanation: + # + # 60 03 60 04 01 00 + # PUSH 3 PUSH 4 ADD HALT + # create_contract!(wallet, keys, '600360040100') response = rpc.call('contract_api.list_owner_contracts', { 'owner' => wallet }) || {} @@ -438,6 +443,43 @@ namespace :contracts do invoke_contract!(contract_hash, keys['wallet_name'], []) end + + desc 'Create a sample contract which calls another' + task :create_and_call do + create_contract = lambda { |code| + keys = generate_keys + create_wallet!(keys) + create_contract!(wallet, keys, code) + + response = rpc.call('contract_api.list_owner_contracts', { 'owner' => wallet }) || {} + p response + contract_hash = response['contracts'].first['contract_hash'] + response = rpc.call('contract_api.get_contract', { 'contract_hash' => contract_hash }) || {} + p response + + [contract_hash, keys] + } + + # Arguments to `call` opcode are: + # + # energy contract_hash value argsOffset argsLength retOffset retLength + # + # Bytecode explanation: + # + # PUSH 0 PUSH 0 RETURN HALT + # 60 00 60 00 F3 00 + # + contract_hash1, keys1 = create_contract.(%(60006000F300)) + # + # Bytecode explanation: + # + # PUSH 0 PUSH #{contract_hash1} 0 0 0 0 0 CALL HALT + # 60 00 60 #{contract_hash1} 60 00 60 00 60 00 60 00 60 00 F1 00 + # + contract_hash2, keys2 = create_contract.(%(600060#{contract_hash1}60006000600060006000F100)) + + invoke_contract!(contract_hash2, keys2['wallet_name'], []) + end end namespace :lazy_wallets do diff --git a/libraries/chain/include/xgt/chain/contract_objects.hpp b/libraries/chain/include/xgt/chain/contract_objects.hpp index f8cde966..f146b41e 100644 --- a/libraries/chain/include/xgt/chain/contract_objects.hpp +++ b/libraries/chain/include/xgt/chain/contract_objects.hpp @@ -61,7 +61,8 @@ namespace xgt { namespace chain { contract_log_id_type id; contract_hash_type contract_hash; wallet_name_type owner; - std::vector topics; + //uint256_t example; + //std::vector topics; vector data; }; @@ -119,8 +120,10 @@ FC_REFLECT( xgt::chain::contract_log_object, (id) (contract_hash) (owner) - (topics) - (data) ) + //(example) + //(topics) + (data) + ) CHAINBASE_SET_INDEX_TYPE( xgt::chain::contract_log_object, xgt::chain::contract_log_index ) FC_REFLECT( xgt::chain::contract_storage_object, diff --git a/libraries/chain/index.cpp b/libraries/chain/index.cpp index c34259fa..30eac473 100644 --- a/libraries/chain/index.cpp +++ b/libraries/chain/index.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include namespace xgt { namespace chain { @@ -41,6 +42,8 @@ void initialize_core_indexes( database& db ) XGT_ADD_CORE_INDEX(db, xtt_ico_index); XGT_ADD_CORE_INDEX(db, xtt_ico_tier_index); XGT_ADD_CORE_INDEX(db, contract_index); + XGT_ADD_CORE_INDEX(db, contract_log_index); + //XGT_ADD_CORE_INDEX(db, contract_storage_index); } index_info::index_info() {} diff --git a/libraries/chain/xgt_evaluator.cpp b/libraries/chain/xgt_evaluator.cpp index 6a4192a0..e09765df 100644 --- a/libraries/chain/xgt_evaluator.cpp +++ b/libraries/chain/xgt_evaluator.cpp @@ -1264,7 +1264,7 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type { cl.contract_hash = contract_hash; cl.owner = o; - cl.topics = log.topics; + //cl.topics = log.topics; cl.data = log.data; }); diff --git a/libraries/fc/include/fc/io/raw.hpp b/libraries/fc/include/fc/io/raw.hpp index 13574eb7..0c53239f 100644 --- a/libraries/fc/include/fc/io/raw.hpp +++ b/libraries/fc/include/fc/io/raw.hpp @@ -1,4 +1,6 @@ #pragma once +#include +#include #include #include #include @@ -13,6 +15,7 @@ #include #include #include +#include #include #include @@ -95,6 +98,40 @@ namespace fc { tp = fc::time_point() + fc::seconds(sec); } FC_RETHROW_EXCEPTIONS( warn, "" ) } + template + inline void pack( Stream& s, const boost::multiprecision::uint256_t& v ) + { + std::ostringstream os; + os << std::hex << std::setw(64) << std::setfill('0') << v; + std::string string_hash = os.str(); + fc::raw::pack(s, string_hash); + } + + template + inline void unpack( Stream& s, boost::multiprecision::uint256_t& v, uint32_t depth ) + { + string string_hash; + fc::raw::unpack(s, string_hash, depth); + std::string prefix = "0x"; + std::string prepended_string_hash = prefix.append(string_hash); + v = boost::multiprecision::uint256_t(prepended_string_hash); + } + + template + inline void pack( Stream& s, const fc::ripemd160& v ) + { + string str = v.str(); + fc::raw::pack(s, str); + } + + template + inline void unpack( Stream& s, fc::ripemd160& v, uint32_t depth ) + { + string tmp; + fc::raw::unpack(s,tmp,depth); + v = fc::ripemd160(tmp); + } + template inline void pack( Stream& s, const fc::time_point& tp ) { From a438b543fb84ed796e8aaca139783121542c96b2 Mon Sep 17 00:00:00 2001 From: Roger Jungemann Date: Mon, 1 Nov 2021 10:09:50 -0700 Subject: [PATCH 66/96] Storage adapter methods --- libraries/chain/database.cpp | 16 -------------- .../include/xgt/chain/contract_objects.hpp | 12 +++------- .../chain/include/xgt/chain/database.hpp | 16 ++++++++++++++ libraries/chain/xgt_evaluator.cpp | 22 +++++++++++-------- libraries/fc/include/fc/io/raw.hpp | 19 ---------------- 5 files changed, 32 insertions(+), 53 deletions(-) diff --git a/libraries/chain/database.cpp b/libraries/chain/database.cpp index 2da3377d..8755263d 100644 --- a/libraries/chain/database.cpp +++ b/libraries/chain/database.cpp @@ -95,22 +95,6 @@ database::~database() clear_pending(); } -fc::sha256 bigint_to_hash(boost::multiprecision::uint256_t b) -{ - std::ostringstream os; - os << std::hex << std::setw(64) << std::setfill('0') << b; - std::string string_hash = os.str(); - return fc::sha256(string_hash); -} - -boost::multiprecision::uint256_t hash_to_bigint(fc::sha256 h) -{ - std::string prefix = "0x"; - std::string string_hash = h.str(); - std::string prepended_string_hash = prefix.append(string_hash); - return boost::multiprecision::uint256_t(prepended_string_hash); -} - #ifdef ENABLE_MIRA void set_index_helper( database& db, mira::index_type type, const boost::filesystem::path& p, const boost::any& cfg, std::vector< std::string > indices ) { diff --git a/libraries/chain/include/xgt/chain/contract_objects.hpp b/libraries/chain/include/xgt/chain/contract_objects.hpp index f146b41e..42a17f10 100644 --- a/libraries/chain/include/xgt/chain/contract_objects.hpp +++ b/libraries/chain/include/xgt/chain/contract_objects.hpp @@ -1,7 +1,5 @@ #pragma once -#include - #include #include @@ -11,8 +9,6 @@ namespace xgt { namespace chain { - using uint256_t = boost::multiprecision::uint256_t; - class contract_object : public object< contract_object_type, contract_object > { XGT_STD_ALLOCATOR_CONSTRUCTOR( contract_object ) @@ -61,8 +57,7 @@ namespace xgt { namespace chain { contract_log_id_type id; contract_hash_type contract_hash; wallet_name_type owner; - //uint256_t example; - //std::vector topics; + std::vector topics; vector data; }; @@ -87,7 +82,7 @@ namespace xgt { namespace chain { contract_storage_id_type id; contract_hash_type contract; wallet_name_type caller; - map data; + map data; }; struct by_contract_and_caller; @@ -120,8 +115,7 @@ FC_REFLECT( xgt::chain::contract_log_object, (id) (contract_hash) (owner) - //(example) - //(topics) + (topics) (data) ) CHAINBASE_SET_INDEX_TYPE( xgt::chain::contract_log_object, xgt::chain::contract_log_index ) diff --git a/libraries/chain/include/xgt/chain/database.hpp b/libraries/chain/include/xgt/chain/database.hpp index a68c0d08..ef9258e7 100644 --- a/libraries/chain/include/xgt/chain/database.hpp +++ b/libraries/chain/include/xgt/chain/database.hpp @@ -498,6 +498,22 @@ namespace xgt { namespace chain { return _hardfork_versions; } + fc::sha256 bigint_to_hash(boost::multiprecision::uint256_t b) + { + std::ostringstream os; + os << std::hex << std::setw(64) << std::setfill('0') << b; + std::string string_hash = os.str(); + return fc::sha256(string_hash); + } + + boost::multiprecision::uint256_t hash_to_bigint(fc::sha256 h) + { + std::string prefix = "0x"; + std::string string_hash = h.str(); + std::string prepended_string_hash = prefix.append(string_hash); + return boost::multiprecision::uint256_t(prepended_string_hash); + } + private: std::unique_ptr< database_impl > _my; diff --git a/libraries/chain/xgt_evaluator.cpp b/libraries/chain/xgt_evaluator.cpp index e09765df..0396c2b8 100644 --- a/libraries/chain/xgt_evaluator.cpp +++ b/libraries/chain/xgt_evaluator.cpp @@ -1,5 +1,6 @@ #include +#include #include #include #include @@ -31,6 +32,7 @@ #include using boost::locale::conv::utf_to_utf; +using uint256_t = boost::multiprecision::uint256_t; std::wstring utf8_to_wstring(const std::string& str) { @@ -1053,9 +1055,9 @@ void contract_create_evaluator::do_apply( const contract_create_operation& op ) } // Forward declaration -machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type o, wallet_name_type c, contract_hash_type contract_hash, map& storage); +machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type o, wallet_name_type c, contract_hash_type contract_hash, map& storage); -std::vector contract_invoke(chain::database& _db, wallet_name_type o, wallet_name_type caller, contract_hash_type contract_hash, uint64_t energy,std::vector args, map< uint256_t, uint256_t >& storage) +std::vector contract_invoke(chain::database& _db, wallet_name_type o, wallet_name_type caller, contract_hash_type contract_hash, uint64_t energy,std::vector args, map< fc::sha256, fc::sha256 >& storage) { wlog("contract_invoke another contract ${w}", ("w",contract_hash)); const auto& c = _db.get_contract(contract_hash); @@ -1105,7 +1107,7 @@ std::vector contract_invoke(chain::database& _db, wallet_name_typ return std::vector(); } -machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type o, wallet_name_type c, contract_hash_type contract_hash, map& storage) +machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type o, wallet_name_type c, contract_hash_type contract_hash, map& storage) { std::string owner(o); std::string caller(c); @@ -1175,7 +1177,7 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type std::function< std::vector(std::string, uint64_t, machine::big_word, std::vector) > contract_call = [&](std::string address, uint64_t energy, machine::big_word value, std::vector args) -> std::vector { const contract_storage_object& cs = _db.get_contract_storage(contract_hash, caller); - map< uint256_t, uint256_t > storage = cs.data; + map< fc::sha256, fc::sha256 > storage = cs.data; auto result = contract_invoke(_db, o, c, contract_hash, energy, args, storage); // TODO: Update storage return result; @@ -1229,13 +1231,13 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type std::function< machine::big_word(machine::big_word) > get_storage = [&](uint256_t key) -> machine::big_word { - return storage[key]; + return _db.hash_to_bigint( storage[ _db.bigint_to_hash(key) ] ); }; std::function< bool(machine::big_word, machine::big_word) > set_storage = [&](machine::big_word key, machine::big_word value) -> bool { - storage[key] = value; - return false; + storage[ _db.bigint_to_hash(key) ] = _db.bigint_to_hash(value); + return true; }; std::function< bool(std::vector) > contract_return = [&](std::vector memory) -> bool @@ -1264,7 +1266,9 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type { cl.contract_hash = contract_hash; cl.owner = o; - //cl.topics = log.topics; + cl.topics.reserve(log.topics.size()); + for (auto topic : log.topics) + cl.topics.push_back(_db.bigint_to_hash(topic)); cl.data = log.data; }); @@ -1302,7 +1306,7 @@ void contract_invoke_evaluator::do_apply( const contract_invoke_operation& op ) const auto& c = _db.get_contract(contract_hash); const contract_storage_object* cs = _db.find_contract_storage(contract_hash, op.caller); - map< uint256_t, uint256_t > storage; + map< fc::sha256, fc::sha256 > storage; if (cs) storage = cs->data; diff --git a/libraries/fc/include/fc/io/raw.hpp b/libraries/fc/include/fc/io/raw.hpp index 0c53239f..33dbb198 100644 --- a/libraries/fc/include/fc/io/raw.hpp +++ b/libraries/fc/include/fc/io/raw.hpp @@ -98,25 +98,6 @@ namespace fc { tp = fc::time_point() + fc::seconds(sec); } FC_RETHROW_EXCEPTIONS( warn, "" ) } - template - inline void pack( Stream& s, const boost::multiprecision::uint256_t& v ) - { - std::ostringstream os; - os << std::hex << std::setw(64) << std::setfill('0') << v; - std::string string_hash = os.str(); - fc::raw::pack(s, string_hash); - } - - template - inline void unpack( Stream& s, boost::multiprecision::uint256_t& v, uint32_t depth ) - { - string string_hash; - fc::raw::unpack(s, string_hash, depth); - std::string prefix = "0x"; - std::string prepended_string_hash = prefix.append(string_hash); - v = boost::multiprecision::uint256_t(prepended_string_hash); - } - template inline void pack( Stream& s, const fc::ripemd160& v ) { From e4d48fd2fdde99cc1555e60f811f92a408ff86dc Mon Sep 17 00:00:00 2001 From: Roger Jungemann Date: Mon, 1 Nov 2021 21:16:42 -0700 Subject: [PATCH 67/96] Invocation, storage, and return --- libraries/chain/xgt_evaluator.cpp | 67 ++++++++++++++------ libraries/vendor/xgtvm/libraries/machine.cpp | 6 ++ libraries/vendor/xgtvm/libraries/machine.hpp | 1 + 3 files changed, 53 insertions(+), 21 deletions(-) diff --git a/libraries/chain/xgt_evaluator.cpp b/libraries/chain/xgt_evaluator.cpp index 0396c2b8..558102ad 100644 --- a/libraries/chain/xgt_evaluator.cpp +++ b/libraries/chain/xgt_evaluator.cpp @@ -1103,8 +1103,7 @@ std::vector contract_invoke(chain::database& _db, wallet_name_typ std::cerr << "\e[36m" << "LOG: " << line << "\e[0m" << std::endl; std::cout << m.to_json() << std::endl; - // TODO: return values - return std::vector(); + return m.get_return_value(); } machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type o, wallet_name_type c, contract_hash_type contract_hash, map& storage) @@ -1176,39 +1175,65 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type std::function< std::vector(std::string, uint64_t, machine::big_word, std::vector) > contract_call = [&](std::string address, uint64_t energy, machine::big_word value, std::vector args) -> std::vector { - const contract_storage_object& cs = _db.get_contract_storage(contract_hash, caller); - map< fc::sha256, fc::sha256 > storage = cs.data; + const contract_storage_object* cs = _db.find_contract_storage(contract_hash, caller); + map< fc::sha256, fc::sha256 > storage; + if (cs) + storage = cs->data; + else + storage = map< fc::sha256, fc::sha256 >(); + auto result = contract_invoke(_db, o, c, contract_hash, energy, args, storage); - // TODO: Update storage + + if (cs) + _db.modify< contract_storage_object >(*cs, [&](contract_storage_object& cs) { + cs.contract = contract_hash; + cs.caller = caller; + cs.data = storage; + }); + else + _db.create< contract_storage_object >([&](contract_storage_object& cs) { + cs.data = storage; + }); + return result; }; std::function< std::vector(std::string, uint64_t, machine::big_word, std::vector) > contract_callcode = [&](std::string address, uint64_t energy, machine::big_word value, std::vector args) -> std::vector { - // TODO Uses alternative account's code (args?) - //return contract_invoke(address, energy, args); - return {}; + // TODO + return std::vector(); }; std::function< std::vector(std::string, uint64_t, std::vector) > contract_delegatecall = [&](std::string address, uint64_t energy, std::vector args) -> std::vector { - // TODO from eth yellowpaper: Message-call into this account with an - // alternative account’s code, but persisting the current values for sender - // and value - // - // from ethervm.io: using storage of the current contract - auto result = contract_invoke(_db, o, c, contract_hash, energy, args, storage); - // TODO: Update storage - return result; + const contract_storage_object* cs = _db.find_contract_storage(contract_hash, c); // TODO: Verify `c` is correct + map< fc::sha256, fc::sha256 > storage; + if (cs) + storage = cs->data; + else + storage = map< fc::sha256, fc::sha256 >(); + + auto result = contract_invoke(_db, o, c, contract_hash, energy, args, storage); + + if (cs) + _db.modify< contract_storage_object >(*cs, [&](contract_storage_object& cs) { + cs.contract = contract_hash; + cs.caller = c; + cs.data = storage; + }); + else + _db.create< contract_storage_object >([&](contract_storage_object& cs) { + cs.data = storage; + }); + + return result; }; std::function< std::vector(std::string, uint64_t, std::vector) > contract_staticcall = [&](std::string address, uint64_t energy, std::vector args) -> std::vector { - // TODO from ethervm.io: calls a method in another contract with state - // changes such as contract creation, event emission, storage modification - // and contract destruction disallowed - return {}; - //return contract_invoke(address, energy, args); + map< fc::sha256, fc::sha256 > storage; // Should this be empty, or just immutable for `staticcall`? + auto result = contract_invoke(_db, o, c, contract_hash, energy, args, storage); + return result; }; std::function< std::string(std::vector, machine::big_word, std::string) > contract_create2 = [&_db, &owner](std::vector memory, machine::big_word value, std::string salt) -> std::string diff --git a/libraries/vendor/xgtvm/libraries/machine.cpp b/libraries/vendor/xgtvm/libraries/machine.cpp index ba17797e..7687f435 100644 --- a/libraries/vendor/xgtvm/libraries/machine.cpp +++ b/libraries/vendor/xgtvm/libraries/machine.cpp @@ -2790,6 +2790,7 @@ namespace machine } adapter.contract_return( retval ); + state = machine_state::stopped; // TODO: Add elsewhere break; case delegatecall_opcode: logger << "op delegatecall" << std::endl; @@ -2943,6 +2944,11 @@ namespace machine return logger; } + std::vector& machine::get_return_value() + { + return return_value; + } + bool machine::is_running() { return state == machine_state::running; diff --git a/libraries/vendor/xgtvm/libraries/machine.hpp b/libraries/vendor/xgtvm/libraries/machine.hpp index dd1a5462..5de8a970 100644 --- a/libraries/vendor/xgtvm/libraries/machine.hpp +++ b/libraries/vendor/xgtvm/libraries/machine.hpp @@ -308,6 +308,7 @@ namespace machine size_t stack_length(); void step(); bool is_running(); + std::vector& get_return_value(); machine_state get_state(); boost::optional get_error_message(); std::stringstream& get_logger(); From 281d04b9a8f4cfedcb81f41d8868a11caf9cf410 Mon Sep 17 00:00:00 2001 From: Roger Jungemann Date: Wed, 3 Nov 2021 15:30:17 -0700 Subject: [PATCH 68/96] Fix blocks not pushing issue --- .../chain/include/xgt/chain/contract_objects.hpp | 1 + libraries/chain/index.cpp | 2 +- libraries/fc/include/fc/io/raw.hpp | 15 --------------- 3 files changed, 2 insertions(+), 16 deletions(-) diff --git a/libraries/chain/include/xgt/chain/contract_objects.hpp b/libraries/chain/include/xgt/chain/contract_objects.hpp index 42a17f10..e77c7aa3 100644 --- a/libraries/chain/include/xgt/chain/contract_objects.hpp +++ b/libraries/chain/include/xgt/chain/contract_objects.hpp @@ -90,6 +90,7 @@ namespace xgt { namespace chain { typedef multi_index_container< contract_storage_object, indexed_by< + ordered_unique< tag< by_id >, member< contract_storage_object, contract_storage_id_type, &contract_storage_object::id > >, ordered_unique< tag< by_contract_and_caller >, composite_key< contract_storage_object, member< contract_storage_object, contract_hash_type, &contract_storage_object::contract >, diff --git a/libraries/chain/index.cpp b/libraries/chain/index.cpp index 30eac473..a05a77bc 100644 --- a/libraries/chain/index.cpp +++ b/libraries/chain/index.cpp @@ -43,7 +43,7 @@ void initialize_core_indexes( database& db ) XGT_ADD_CORE_INDEX(db, xtt_ico_tier_index); XGT_ADD_CORE_INDEX(db, contract_index); XGT_ADD_CORE_INDEX(db, contract_log_index); - //XGT_ADD_CORE_INDEX(db, contract_storage_index); + XGT_ADD_CORE_INDEX(db, contract_storage_index); } index_info::index_info() {} diff --git a/libraries/fc/include/fc/io/raw.hpp b/libraries/fc/include/fc/io/raw.hpp index 33dbb198..f43e5192 100644 --- a/libraries/fc/include/fc/io/raw.hpp +++ b/libraries/fc/include/fc/io/raw.hpp @@ -98,21 +98,6 @@ namespace fc { tp = fc::time_point() + fc::seconds(sec); } FC_RETHROW_EXCEPTIONS( warn, "" ) } - template - inline void pack( Stream& s, const fc::ripemd160& v ) - { - string str = v.str(); - fc::raw::pack(s, str); - } - - template - inline void unpack( Stream& s, fc::ripemd160& v, uint32_t depth ) - { - string tmp; - fc::raw::unpack(s,tmp,depth); - v = fc::ripemd160(tmp); - } - template inline void pack( Stream& s, const fc::time_point& tp ) { From 25f6b0d302c1b70615184bb0a55cff7f06967a28 Mon Sep 17 00:00:00 2001 From: Roger Jungemann Date: Thu, 4 Nov 2021 11:58:35 -0700 Subject: [PATCH 69/96] Add "Do Nothing" test contract --- Rakefile | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/Rakefile b/Rakefile index 0ba15bd8..cf306ef2 100644 --- a/Rakefile +++ b/Rakefile @@ -480,6 +480,27 @@ namespace :contracts do invoke_contract!(contract_hash2, keys2['wallet_name'], []) end + + desc 'The "Do Nothing" contract' + task :do_nothing do + create_contract = lambda { |code| + keys = generate_keys + create_wallet!(keys) + create_contract!(wallet, keys, code) + + response = rpc.call('contract_api.list_owner_contracts', { 'owner' => wallet }) || {} + p response + contract_hash = response['contracts'].first['contract_hash'] + response = rpc.call('contract_api.get_contract', { 'contract_hash' => contract_hash }) || {} + p response + + [contract_hash, keys] + } + + contract_hash, keys = create_contract.(%(6080604052348015600f57600080fd5b50606d80601d6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c80632f576f2014602d575b600080fd5b60336035565b005b56fea2646970667358221220975bdb6949442538b90c14c420b0a2f547f0437e85a73da12faf4e6834f0817264736f6c63430008070033)) + + invoke_contract!(contract_hash, keys['wallet_name'], []) + end end namespace :lazy_wallets do From 933ae006f7748b53a351b80e43224e319a6a7cd3 Mon Sep 17 00:00:00 2001 From: Liam Noroian Date: Sun, 7 Nov 2021 19:08:23 -0800 Subject: [PATCH 70/96] updating energy regeneration --- .../include/xgt/chain/util/energybar.hpp | 12 +- libraries/chain/xgt_evaluator.cpp | 310 ++++++++++-------- libraries/protocol/get_config.cpp | 1 + .../protocol/include/xgt/protocol/config.hpp | 1 + 4 files changed, 176 insertions(+), 148 deletions(-) diff --git a/libraries/chain/include/xgt/chain/util/energybar.hpp b/libraries/chain/include/xgt/chain/util/energybar.hpp index 6c0462d0..4b2f303b 100644 --- a/libraries/chain/include/xgt/chain/util/energybar.hpp +++ b/libraries/chain/include/xgt/chain/util/energybar.hpp @@ -100,11 +100,17 @@ struct energybar template< typename PropType, typename AccountType > void update_energybar( const PropType& gpo, AccountType& account, int32_t energy_regen_seconds, bool downvote_energy = false, int64_t new_energy = 0 ) { + try + { + energybar_params params( static_cast(account.balance.amount.value), energy_regen_seconds ); + account.energybar.regenerate_energy( params, gpo.time ); + account.energybar.use_energy( -new_energy ); + } FC_CAPTURE_LOG_AND_RETHROW( (account)(account.balance.amount) ) } } } } // xgt::chain::util FC_REFLECT( xgt::chain::util::energybar, - (current_energy) - (last_update_time) - ) + (current_energy) + (last_update_time) + ) diff --git a/libraries/chain/xgt_evaluator.cpp b/libraries/chain/xgt_evaluator.cpp index 83644dfe..f946ab98 100644 --- a/libraries/chain/xgt_evaluator.cpp +++ b/libraries/chain/xgt_evaluator.cpp @@ -1231,12 +1231,13 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type std::function< machine::big_word(machine::big_word) > get_storage = [&](uint256_t key) -> machine::big_word { - return storage[key]; + // return storage[key]; + return 0; }; std::function< bool(machine::big_word, machine::big_word) > set_storage = [&](machine::big_word key, machine::big_word value) -> bool { - storage[key] = value; + // storage[key] = value; return false; }; @@ -1297,147 +1298,147 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type return adapter; } -std::map< uint64_t, std::function > energy_cost { +std::map< uint64_t, std::function > energy_cost { // [] == scoped variables, () == params, -> optional return type, {} == function body - {machine::stop_opcode, [](machine::machine m){ return 0; }}, - {machine::add_opcode, [](machine::machine m){ return 3; }}, - {machine::mul_opcode, [](machine::machine m){ return 5; }}, - {machine::sub_opcode, [](machine::machine m){ return 3; }}, - {machine::div_opcode, [](machine::machine m){ return 5; }}, - {machine::sdiv_opcode, [](machine::machine m){ return 5; }}, - {machine::mod_opcode, [](machine::machine m){ return 5; }}, - {machine::smod_opcode, [](machine::machine m){ return 5; }}, - {machine::addmod_opcode, [](machine::machine m){ return 8; }}, - {machine::mulmod_opcode, [](machine::machine m){ return 8; }}, - {machine::exp_opcode, [](machine::machine m){ return 0; }}, // TODO -- Exp -- variab; le - {machine::signextend_opcode, [](machine::machine m){ return 5; }}, - {machine::lt_opcode, [](machine::machine m){ return 3; }}, - {machine::gt_opcode, [](machine::machine m){ return 3; }}, - {machine::slt_opcode, [](machine::machine m){ return 3; }}, - {machine::sgt_opcode, [](machine::machine m){ return 3; }}, - {machine::eq_opcode, [](machine::machine m){ return 3; }}, - {machine::iszero_opcode, [](machine::machine m){ return 3; }}, - {machine::and_opcode, [](machine::machine m){ return 3; }}, - {machine::or_opcode, [](machine::machine m){ return 3; }}, - {machine::xor_opcode, [](machine::machine m){ return 3; }}, - {machine::not_opcode, [](machine::machine m){ return 3; }}, - {machine::byte_opcode, [](machine::machine m){ return 3; }}, - {machine::shl_opcode, [](machine::machine m){ return 3; }}, - {machine::shr_opcode, [](machine::machine m){ return 3; }}, - {machine::sar_opcode, [](machine::machine m){ return 3; }}, - {machine::sha3_opcode, [](machine::machine m){ return 0; }}, // TODO -- SHA3 -- variab; le - {machine::address_opcode, [](machine::machine m){ return 2; }}, - {machine::balance_opcode, [](machine::machine m){ return 700; }}, - {machine::origin_opcode, [](machine::machine m){ return 2; }}, - {machine::caller_opcode, [](machine::machine m){ return 2; }}, - {machine::callvalue_opcode, [](machine::machine m){ return 2; }}, - {machine::calldataload_opcode, [](machine::machine m){ return 3; }}, - {machine::calldatasize_opcode, [](machine::machine m){ return 2; }}, - {machine::calldatacopy_opcode, [](machine::machine m){ return 0; }}, // TODO -- calldatacoy -- variab; le - {machine::codesize_opcode, [](machine::machine m){ return 2; }}, - {machine::codecopy_opcode, [](machine::machine m){ return 0; }}, // TODO -- codecopy -- variab; le - {machine::energyprice_opcode, [](machine::machine m){ return 2; }}, - {machine::extcodesize_opcode, [](machine::machine m){ return 700; }}, - {machine::extcodecopy_opcode, [](machine::machine m){ return 0; }}, // TODO -- extcodecopy -- variab; le - {machine::returndatasize_opcode, [](machine::machine m){ return 2; }}, - {machine::returndatacopy_opcode, [](machine::machine m){ return 0; }}, // TODO -- returndatacopy -- variab; le - {machine::extcodehash_opcode, [](machine::machine m){ return 700; }}, - {machine::blockhash_opcode, [](machine::machine m){ return 20; }}, - {machine::coinbase_opcode, [](machine::machine m){ return 2; }}, - {machine::timestamp_opcode, [](machine::machine m){ return 2; }}, - {machine::number_opcode, [](machine::machine m){ return 2; }}, - {machine::difficulty_opcode, [](machine::machine m){ return 2; }}, - {machine::energylimit_opcode, [](machine::machine m){ return 2; }}, - {machine::pop_opcode, [](machine::machine m){ return 3; }}, - {machine::mload_opcode, [](machine::machine m){ return 3; }}, - {machine::mstore_opcode, [](machine::machine m){ return 3; }}, - {machine::mstore8_opcode, [](machine::machine m){ return 3; }}, - {machine::sload_opcode, [](machine::machine m){ return 800; }}, - {machine::sstore_opcode, [](machine::machine m){ return 0; }}, // TODO -- sstore -- variab; le - {machine::jump_opcode, [](machine::machine m){ return 8; }}, - {machine::jumpi_opcode, [](machine::machine m){ return 10; }}, - {machine::pc_opcode, [](machine::machine m){ return 2; }}, - {machine::msize_opcode, [](machine::machine m){ return 2; }}, - {machine::energy_opcode, [](machine::machine m){ return 2; }}, - {machine::jumpdest_opcode, [](machine::machine m){ return 1; }}, - {machine::push1_opcode, [](machine::machine m){ return 3; }}, - {machine::push2_opcode, [](machine::machine m){ return 3; }}, - {machine::push3_opcode, [](machine::machine m){ return 3; }}, - {machine::push4_opcode, [](machine::machine m){ return 3; }}, - {machine::push5_opcode, [](machine::machine m){ return 3; }}, - {machine::push6_opcode, [](machine::machine m){ return 3; }}, - {machine::push7_opcode, [](machine::machine m){ return 3; }}, - {machine::push8_opcode, [](machine::machine m){ return 3; }}, - {machine::push9_opcode, [](machine::machine m){ return 3; }}, - {machine::push10_opcode, [](machine::machine m){ return 3; }}, - {machine::push11_opcode, [](machine::machine m){ return 3; }}, - {machine::push12_opcode, [](machine::machine m){ return 3; }}, - {machine::push13_opcode, [](machine::machine m){ return 3; }}, - {machine::push14_opcode, [](machine::machine m){ return 3; }}, - {machine::push15_opcode, [](machine::machine m){ return 3; }}, - {machine::push16_opcode, [](machine::machine m){ return 3; }}, - {machine::push17_opcode, [](machine::machine m){ return 3; }}, - {machine::push18_opcode, [](machine::machine m){ return 3; }}, - {machine::push19_opcode, [](machine::machine m){ return 3; }}, - {machine::push20_opcode, [](machine::machine m){ return 3; }}, - {machine::push21_opcode, [](machine::machine m){ return 3; }}, - {machine::push22_opcode, [](machine::machine m){ return 3; }}, - {machine::push23_opcode, [](machine::machine m){ return 3; }}, - {machine::push24_opcode, [](machine::machine m){ return 3; }}, - {machine::push25_opcode, [](machine::machine m){ return 3; }}, - {machine::push26_opcode, [](machine::machine m){ return 3; }}, - {machine::push27_opcode, [](machine::machine m){ return 3; }}, - {machine::push28_opcode, [](machine::machine m){ return 3; }}, - {machine::push29_opcode, [](machine::machine m){ return 3; }}, - {machine::push30_opcode, [](machine::machine m){ return 3; }}, - {machine::push31_opcode, [](machine::machine m){ return 3; }}, - {machine::push32_opcode, [](machine::machine m){ return 3; }}, - {machine::dup1_opcode, [](machine::machine m){ return 3; }}, - {machine::dup2_opcode, [](machine::machine m){ return 3; }}, - {machine::dup3_opcode, [](machine::machine m){ return 3; }}, - {machine::dup4_opcode, [](machine::machine m){ return 3; }}, - {machine::dup5_opcode, [](machine::machine m){ return 3; }}, - {machine::dup6_opcode, [](machine::machine m){ return 3; }}, - {machine::dup7_opcode, [](machine::machine m){ return 3; }}, - {machine::dup8_opcode, [](machine::machine m){ return 3; }}, - {machine::dup9_opcode, [](machine::machine m){ return 3; }}, - {machine::dup10_opcode, [](machine::machine m){ return 3; }}, - {machine::dup11_opcode, [](machine::machine m){ return 3; }}, - {machine::dup12_opcode, [](machine::machine m){ return 3; }}, - {machine::dup13_opcode, [](machine::machine m){ return 3; }}, - {machine::dup14_opcode, [](machine::machine m){ return 3; }}, - {machine::dup15_opcode, [](machine::machine m){ return 3; }}, - {machine::dup16_opcode, [](machine::machine m){ return 3; }}, - {machine::swap1_opcode, [](machine::machine m){ return 3; }}, - {machine::swap2_opcode, [](machine::machine m){ return 3; }}, - {machine::swap3_opcode, [](machine::machine m){ return 3; }}, - {machine::swap4_opcode, [](machine::machine m){ return 3; }}, - {machine::swap5_opcode, [](machine::machine m){ return 3; }}, - {machine::swap6_opcode, [](machine::machine m){ return 3; }}, - {machine::swap7_opcode, [](machine::machine m){ return 3; }}, - {machine::swap8_opcode, [](machine::machine m){ return 3; }}, - {machine::swap9_opcode, [](machine::machine m){ return 3; }}, - {machine::swap10_opcode, [](machine::machine m){ return 3; }}, - {machine::swap11_opcode, [](machine::machine m){ return 3; }}, - {machine::swap12_opcode, [](machine::machine m){ return 3; }}, - {machine::swap13_opcode, [](machine::machine m){ return 3; }}, - {machine::swap14_opcode, [](machine::machine m){ return 3; }}, - {machine::swap15_opcode, [](machine::machine m){ return 3; }}, - {machine::swap16_opcode, [](machine::machine m){ return 3; }}, - {machine::log0_opcode, [](machine::machine m){ return 0; }}, // TODO -- log0 -- variable - {machine::log1_opcode, [](machine::machine m){ return 0; }}, // TODO -- log1 -- variable - {machine::log2_opcode, [](machine::machine m){ return 0; }}, // TODO -- log2 -- variable - {machine::log3_opcode, [](machine::machine m){ return 0; }}, // TODO -- log3 -- variable - {machine::log4_opcode, [](machine::machine m){ return 0; }}, // TODO -- log4 -- variable - {machine::create_opcode, [](machine::machine m){ return 0; }}, // TODO -- create -- variable - {machine::call_opcode, [](machine::machine m){ return 0; }}, // TODO -- call -- variable - {machine::callcode_opcode, [](machine::machine m){ return 0; }}, // TODO -- callcode -- variable - {machine::return_opcode, [](machine::machine m){ return 0; }}, - {machine::delegatecall_opcode, [](machine::machine m){ return 0; }}, // TODO -- delegatecall -- variable - {machine::create2_opcode, [](machine::machine m){ return 0; }}, // TODO -- create2 -- variable - {machine::staticcall_opcode, [](machine::machine m){ return 0; }}, // TODO -- staticcall -- variable - {machine::revert_opcode, [](machine::machine m){ return 0; }}, - {machine::selfdestruct_opcode, [](machine::machine m){ return 0; }} // TODO -- selfdestruct -- variable + {machine::stop_opcode, [](machine::machine& m){ return 0; }}, + {machine::add_opcode, [](machine::machine& m){ return 3; }}, + {machine::mul_opcode, [](machine::machine& m){ return 5; }}, + {machine::sub_opcode, [](machine::machine& m){ return 3; }}, + {machine::div_opcode, [](machine::machine& m){ return 5; }}, + {machine::sdiv_opcode, [](machine::machine& m){ return 5; }}, + {machine::mod_opcode, [](machine::machine& m){ return 5; }}, + {machine::smod_opcode, [](machine::machine& m){ return 5; }}, + {machine::addmod_opcode, [](machine::machine& m){ return 8; }}, + {machine::mulmod_opcode, [](machine::machine& m){ return 8; }}, + {machine::exp_opcode, [](machine::machine& m){ return 0; }}, // TODO -- Exp -- variab; le + {machine::signextend_opcode, [](machine::machine& m){ return 5; }}, + {machine::lt_opcode, [](machine::machine& m){ return 3; }}, + {machine::gt_opcode, [](machine::machine& m){ return 3; }}, + {machine::slt_opcode, [](machine::machine& m){ return 3; }}, + {machine::sgt_opcode, [](machine::machine& m){ return 3; }}, + {machine::eq_opcode, [](machine::machine& m){ return 3; }}, + {machine::iszero_opcode, [](machine::machine& m){ return 3; }}, + {machine::and_opcode, [](machine::machine& m){ return 3; }}, + {machine::or_opcode, [](machine::machine& m){ return 3; }}, + {machine::xor_opcode, [](machine::machine& m){ return 3; }}, + {machine::not_opcode, [](machine::machine& m){ return 3; }}, + {machine::byte_opcode, [](machine::machine& m){ return 3; }}, + {machine::shl_opcode, [](machine::machine& m){ return 3; }}, + {machine::shr_opcode, [](machine::machine& m){ return 3; }}, + {machine::sar_opcode, [](machine::machine& m){ return 3; }}, + {machine::sha3_opcode, [](machine::machine& m){ return 0; }}, // TODO -- SHA3 -- variab; le + {machine::address_opcode, [](machine::machine& m){ return 2; }}, + {machine::balance_opcode, [](machine::machine& m){ return 700; }}, + {machine::origin_opcode, [](machine::machine& m){ return 2; }}, + {machine::caller_opcode, [](machine::machine& m){ return 2; }}, + {machine::callvalue_opcode, [](machine::machine& m){ return 2; }}, + {machine::calldataload_opcode, [](machine::machine& m){ return 3; }}, + {machine::calldatasize_opcode, [](machine::machine& m){ return 2; }}, + {machine::calldatacopy_opcode, [](machine::machine& m){ return 0; }}, // TODO -- calldatacoy -- variab; le + {machine::codesize_opcode, [](machine::machine& m){ return 2; }}, + {machine::codecopy_opcode, [](machine::machine& m){ return 0; }}, // TODO -- codecopy -- variab; le + {machine::energyprice_opcode, [](machine::machine& m){ return 2; }}, + {machine::extcodesize_opcode, [](machine::machine& m){ return 700; }}, + {machine::extcodecopy_opcode, [](machine::machine& m){ return 0; }}, // TODO -- extcodecopy -- variab; le + {machine::returndatasize_opcode, [](machine::machine& m){ return 2; }}, + {machine::returndatacopy_opcode, [](machine::machine& m){ return 0; }}, // TODO -- returndatacopy -- variab; le + {machine::extcodehash_opcode, [](machine::machine& m){ return 700; }}, + {machine::blockhash_opcode, [](machine::machine& m){ return 20; }}, + {machine::coinbase_opcode, [](machine::machine& m){ return 2; }}, + {machine::timestamp_opcode, [](machine::machine& m){ return 2; }}, + {machine::number_opcode, [](machine::machine& m){ return 2; }}, + {machine::difficulty_opcode, [](machine::machine& m){ return 2; }}, + {machine::energylimit_opcode, [](machine::machine& m){ return 2; }}, + {machine::pop_opcode, [](machine::machine& m){ return 3; }}, + {machine::mload_opcode, [](machine::machine& m){ return 3; }}, + {machine::mstore_opcode, [](machine::machine& m){ return 3; }}, + {machine::mstore8_opcode, [](machine::machine& m){ return 3; }}, + {machine::sload_opcode, [](machine::machine& m){ return 800; }}, + {machine::sstore_opcode, [](machine::machine& m){ return 0; }}, // TODO -- sstore -- variab; le + {machine::jump_opcode, [](machine::machine& m){ return 8; }}, + {machine::jumpi_opcode, [](machine::machine& m){ return 10; }}, + {machine::pc_opcode, [](machine::machine& m){ return 2; }}, + {machine::msize_opcode, [](machine::machine& m){ return 2; }}, + {machine::energy_opcode, [](machine::machine& m){ return 2; }}, + {machine::jumpdest_opcode, [](machine::machine& m){ return 1; }}, + {machine::push1_opcode, [](machine::machine& m){ return 3; }}, + {machine::push2_opcode, [](machine::machine& m){ return 3; }}, + {machine::push3_opcode, [](machine::machine& m){ return 3; }}, + {machine::push4_opcode, [](machine::machine& m){ return 3; }}, + {machine::push5_opcode, [](machine::machine& m){ return 3; }}, + {machine::push6_opcode, [](machine::machine& m){ return 3; }}, + {machine::push7_opcode, [](machine::machine& m){ return 3; }}, + {machine::push8_opcode, [](machine::machine& m){ return 3; }}, + {machine::push9_opcode, [](machine::machine& m){ return 3; }}, + {machine::push10_opcode, [](machine::machine& m){ return 3; }}, + {machine::push11_opcode, [](machine::machine& m){ return 3; }}, + {machine::push12_opcode, [](machine::machine& m){ return 3; }}, + {machine::push13_opcode, [](machine::machine& m){ return 3; }}, + {machine::push14_opcode, [](machine::machine& m){ return 3; }}, + {machine::push15_opcode, [](machine::machine& m){ return 3; }}, + {machine::push16_opcode, [](machine::machine& m){ return 3; }}, + {machine::push17_opcode, [](machine::machine& m){ return 3; }}, + {machine::push18_opcode, [](machine::machine& m){ return 3; }}, + {machine::push19_opcode, [](machine::machine& m){ return 3; }}, + {machine::push20_opcode, [](machine::machine& m){ return 3; }}, + {machine::push21_opcode, [](machine::machine& m){ return 3; }}, + {machine::push22_opcode, [](machine::machine& m){ return 3; }}, + {machine::push23_opcode, [](machine::machine& m){ return 3; }}, + {machine::push24_opcode, [](machine::machine& m){ return 3; }}, + {machine::push25_opcode, [](machine::machine& m){ return 3; }}, + {machine::push26_opcode, [](machine::machine& m){ return 3; }}, + {machine::push27_opcode, [](machine::machine& m){ return 3; }}, + {machine::push28_opcode, [](machine::machine& m){ return 3; }}, + {machine::push29_opcode, [](machine::machine& m){ return 3; }}, + {machine::push30_opcode, [](machine::machine& m){ return 3; }}, + {machine::push31_opcode, [](machine::machine& m){ return 3; }}, + {machine::push32_opcode, [](machine::machine& m){ return 3; }}, + {machine::dup1_opcode, [](machine::machine& m){ return 3; }}, + {machine::dup2_opcode, [](machine::machine& m){ return 3; }}, + {machine::dup3_opcode, [](machine::machine& m){ return 3; }}, + {machine::dup4_opcode, [](machine::machine& m){ return 3; }}, + {machine::dup5_opcode, [](machine::machine& m){ return 3; }}, + {machine::dup6_opcode, [](machine::machine& m){ return 3; }}, + {machine::dup7_opcode, [](machine::machine& m){ return 3; }}, + {machine::dup8_opcode, [](machine::machine& m){ return 3; }}, + {machine::dup9_opcode, [](machine::machine& m){ return 3; }}, + {machine::dup10_opcode, [](machine::machine& m){ return 3; }}, + {machine::dup11_opcode, [](machine::machine& m){ return 3; }}, + {machine::dup12_opcode, [](machine::machine& m){ return 3; }}, + {machine::dup13_opcode, [](machine::machine& m){ return 3; }}, + {machine::dup14_opcode, [](machine::machine& m){ return 3; }}, + {machine::dup15_opcode, [](machine::machine& m){ return 3; }}, + {machine::dup16_opcode, [](machine::machine& m){ return 3; }}, + {machine::swap1_opcode, [](machine::machine& m){ return 3; }}, + {machine::swap2_opcode, [](machine::machine& m){ return 3; }}, + {machine::swap3_opcode, [](machine::machine& m){ return 3; }}, + {machine::swap4_opcode, [](machine::machine& m){ return 3; }}, + {machine::swap5_opcode, [](machine::machine& m){ return 3; }}, + {machine::swap6_opcode, [](machine::machine& m){ return 3; }}, + {machine::swap7_opcode, [](machine::machine& m){ return 3; }}, + {machine::swap8_opcode, [](machine::machine& m){ return 3; }}, + {machine::swap9_opcode, [](machine::machine& m){ return 3; }}, + {machine::swap10_opcode, [](machine::machine& m){ return 3; }}, + {machine::swap11_opcode, [](machine::machine& m){ return 3; }}, + {machine::swap12_opcode, [](machine::machine& m){ return 3; }}, + {machine::swap13_opcode, [](machine::machine& m){ return 3; }}, + {machine::swap14_opcode, [](machine::machine& m){ return 3; }}, + {machine::swap15_opcode, [](machine::machine& m){ return 3; }}, + {machine::swap16_opcode, [](machine::machine& m){ return 3; }}, + {machine::log0_opcode, [](machine::machine& m){ return 0; }}, // TODO -- log0 -- variable + {machine::log1_opcode, [](machine::machine& m){ return 0; }}, // TODO -- log1 -- variable + {machine::log2_opcode, [](machine::machine& m){ return 0; }}, // TODO -- log2 -- variable + {machine::log3_opcode, [](machine::machine& m){ return 0; }}, // TODO -- log3 -- variable + {machine::log4_opcode, [](machine::machine& m){ return 0; }}, // TODO -- log4 -- variable + {machine::create_opcode, [](machine::machine& m){ return 0; }}, // TODO -- create -- variable + {machine::call_opcode, [](machine::machine& m){ return 0; }}, // TODO -- call -- variable + {machine::callcode_opcode, [](machine::machine& m){ return 0; }}, // TODO -- callcode -- variable + {machine::return_opcode, [](machine::machine& m){ return 0; }}, + {machine::delegatecall_opcode, [](machine::machine& m){ return 0; }}, // TODO -- delegatecall -- variable + {machine::create2_opcode, [](machine::machine& m){ return 0; }}, // TODO -- create2 -- variable + {machine::staticcall_opcode, [](machine::machine& m){ return 0; }}, // TODO -- staticcall -- variable + {machine::revert_opcode, [](machine::machine& m){ return 0; }}, + {machine::selfdestruct_opcode, [](machine::machine& m){ return 0; }} // TODO -- selfdestruct -- variable }; void contract_invoke_evaluator::do_apply( const contract_invoke_operation& op ) @@ -1446,10 +1447,10 @@ void contract_invoke_evaluator::do_apply( const contract_invoke_operation& op ) const contract_hash_type contract_hash = op.contract_hash; const auto& c = _db.get_contract(contract_hash); - const contract_storage_object* cs = _db.find_contract_storage(contract_hash, op.caller); + // const contract_storage_object* cs = _db.find_contract_storage(contract_hash, op.caller); map< uint256_t, uint256_t > storage; - if (cs) - storage = cs->data; + // if (cs) + // storage = cs->data; machine::message msg = {}; @@ -1497,6 +1498,25 @@ void contract_invoke_evaluator::do_apply( const contract_invoke_operation& op ) while ( std::getline(m.get_logger(), line) ) std::cerr << "\e[36m" << "LOG: " << line << "\e[0m" << std::endl; std::cout << m.to_json() << std::endl; + std::cout << "Energy cost incurred" << energy_cost_incurred << std::endl; + + + const wallet_object wallet = _db.get_account(op.caller); + std::cout << wallet.energybar.current_energy << std::endl; + std::cout << wallet.energybar.last_update_time << std::endl; + + uint32_t energy_regen_period = XGT_ENERGY_REGENERATION_SECONDS; // TODO: Hardcode this for now (should be a constant I think) + _db.modify(wallet, [&](wallet_object& w) + { + util::update_energybar( _db.get_dynamic_global_properties(), w, energy_regen_period, true ); + w.energybar.use_energy( energy_cost_incurred ); + }); + + const wallet_object wallet_after = _db.get_account(op.caller); + + std::cout << "*******************" << std::endl; + std::cout << wallet_after.energybar.current_energy << std::endl; + std::cout << wallet_after.energybar.last_update_time << std::endl; } } } // xgt::chain diff --git a/libraries/protocol/get_config.cpp b/libraries/protocol/get_config.cpp index b5b2db9f..35d2ca38 100644 --- a/libraries/protocol/get_config.cpp +++ b/libraries/protocol/get_config.cpp @@ -153,6 +153,7 @@ fc::variant_object get_config() result["XGT_UPVOTE_LOCKOUT_SECONDS"] = XGT_UPVOTE_LOCKOUT_SECONDS; result["XGT_VOTE_DUST_THRESHOLD"] = XGT_VOTE_DUST_THRESHOLD; result["XGT_VOTING_ENERGY_REGENERATION_SECONDS"] = XGT_VOTING_ENERGY_REGENERATION_SECONDS; + result["XGT_ENERGY_REGENERATION_SECONDS"] = XGT_ENERGY_REGENERATION_SECONDS; result["XGT_VIRTUAL_SCHEDULE_LAP_LENGTH"] = XGT_VIRTUAL_SCHEDULE_LAP_LENGTH; result["XGT_VIRTUAL_SCHEDULE_LAP_LENGTH2"] = XGT_VIRTUAL_SCHEDULE_LAP_LENGTH2; result["XGT_VOTES_PER_PERIOD_XTT_HF"] = XGT_VOTES_PER_PERIOD_XTT_HF; diff --git a/libraries/protocol/include/xgt/protocol/config.hpp b/libraries/protocol/include/xgt/protocol/config.hpp index acf72a00..19634af0 100644 --- a/libraries/protocol/include/xgt/protocol/config.hpp +++ b/libraries/protocol/include/xgt/protocol/config.hpp @@ -99,6 +99,7 @@ #define XGT_MAX_TIME_UNTIL_EXPIRATION (60*60) // seconds, aka: 1 hour #define XGT_MAX_MEMO_SIZE 2048 #define XGT_VOTING_ENERGY_REGENERATION_SECONDS (1*60*60*24) // 1 day +#define XGT_ENERGY_REGENERATION_SECONDS (1*60*60*24) // 1 day #define XGT_MAX_VOTE_CHANGES 5 #define XGT_REVERSE_AUCTION_WINDOW_SECONDS (60*5) /// 5 minutes #define XGT_MIN_VOTE_INTERVAL_SEC 3 From 71fc084f1fbb2335814ef4db7a48973d5f047742 Mon Sep 17 00:00:00 2001 From: Liam Noroian Date: Thu, 11 Nov 2021 09:29:19 -0800 Subject: [PATCH 71/96] removing unnecessary logging --- libraries/chain/xgt_evaluator.cpp | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/libraries/chain/xgt_evaluator.cpp b/libraries/chain/xgt_evaluator.cpp index f946ab98..155868dd 100644 --- a/libraries/chain/xgt_evaluator.cpp +++ b/libraries/chain/xgt_evaluator.cpp @@ -1498,12 +1498,8 @@ void contract_invoke_evaluator::do_apply( const contract_invoke_operation& op ) while ( std::getline(m.get_logger(), line) ) std::cerr << "\e[36m" << "LOG: " << line << "\e[0m" << std::endl; std::cout << m.to_json() << std::endl; - std::cout << "Energy cost incurred" << energy_cost_incurred << std::endl; - - const wallet_object wallet = _db.get_account(op.caller); - std::cout << wallet.energybar.current_energy << std::endl; - std::cout << wallet.energybar.last_update_time << std::endl; + const wallet_object& wallet = _db.get_account(op.caller); uint32_t energy_regen_period = XGT_ENERGY_REGENERATION_SECONDS; // TODO: Hardcode this for now (should be a constant I think) _db.modify(wallet, [&](wallet_object& w) @@ -1511,12 +1507,6 @@ void contract_invoke_evaluator::do_apply( const contract_invoke_operation& op ) util::update_energybar( _db.get_dynamic_global_properties(), w, energy_regen_period, true ); w.energybar.use_energy( energy_cost_incurred ); }); - - const wallet_object wallet_after = _db.get_account(op.caller); - - std::cout << "*******************" << std::endl; - std::cout << wallet_after.energybar.current_energy << std::endl; - std::cout << wallet_after.energybar.last_update_time << std::endl; } } } // xgt::chain From fc5a1b6b459b7ee45fdf600c2e09b60a6a91a765 Mon Sep 17 00:00:00 2001 From: Liam Noroian Date: Sun, 14 Nov 2021 16:19:16 -0800 Subject: [PATCH 72/96] Updating formatting --- libraries/chain/xgt_evaluator.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/chain/xgt_evaluator.cpp b/libraries/chain/xgt_evaluator.cpp index 155868dd..2bbecb72 100644 --- a/libraries/chain/xgt_evaluator.cpp +++ b/libraries/chain/xgt_evaluator.cpp @@ -1310,7 +1310,7 @@ std::map< uint64_t, std::function > energy_cost { {machine::smod_opcode, [](machine::machine& m){ return 5; }}, {machine::addmod_opcode, [](machine::machine& m){ return 8; }}, {machine::mulmod_opcode, [](machine::machine& m){ return 8; }}, - {machine::exp_opcode, [](machine::machine& m){ return 0; }}, // TODO -- Exp -- variab; le + {machine::exp_opcode, [](machine::machine& m){ return 0; }}, // TODO -- Exp -- variable {machine::signextend_opcode, [](machine::machine& m){ return 5; }}, {machine::lt_opcode, [](machine::machine& m){ return 3; }}, {machine::gt_opcode, [](machine::machine& m){ return 3; }}, @@ -1447,7 +1447,7 @@ void contract_invoke_evaluator::do_apply( const contract_invoke_operation& op ) const contract_hash_type contract_hash = op.contract_hash; const auto& c = _db.get_contract(contract_hash); - // const contract_storage_object* cs = _db.find_contract_storage(contract_hash, op.caller); + // const contract_storage_object* cs = _db.find_contract_storage(contract_hash, op.caller) map< uint256_t, uint256_t > storage; // if (cs) // storage = cs->data; From b1d6fcac3b95d2132b6a4b8c4c8bdc47803f08ac Mon Sep 17 00:00:00 2001 From: Roger Jungemann Date: Mon, 15 Nov 2021 09:30:39 -0800 Subject: [PATCH 73/96] Consolidate contract invoke calls --- libraries/chain/xgt_evaluator.cpp | 56 ++-- .../include/xgt/protocol/xgt_operations.hpp | 2 +- libraries/vendor/xgtvm/libraries/machine.cpp | 47 +++- libraries/vendor/xgtvm/programs/xgtvm.cpp | 10 +- .../vendor/xgtvm/programs/xgtvm_tests.cpp | 248 +++++++++++++----- 5 files changed, 249 insertions(+), 114 deletions(-) diff --git a/libraries/chain/xgt_evaluator.cpp b/libraries/chain/xgt_evaluator.cpp index 558102ad..0f7775f9 100644 --- a/libraries/chain/xgt_evaluator.cpp +++ b/libraries/chain/xgt_evaluator.cpp @@ -1327,54 +1327,32 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type void contract_invoke_evaluator::do_apply( const contract_invoke_operation& op ) { wlog("contract_invoke ${w}", ("w",op.contract_hash)); + const contract_hash_type contract_hash = op.contract_hash; const auto& c = _db.get_contract(contract_hash); + uint64_t energy = 0; // TODO const contract_storage_object* cs = _db.find_contract_storage(contract_hash, op.caller); map< fc::sha256, fc::sha256 > storage; if (cs) storage = cs->data; + else + storage = map< fc::sha256, fc::sha256 >(); - machine::message msg = {}; - - const bool is_debug = true; - const uint64_t block_timestamp = static_cast( _db.head_block_time().sec_since_epoch() ); - const uint64_t block_number = _db.head_block_num(); - const uint64_t block_difficulty = static_cast( _db.get_pow_summary_target() ); - const uint64_t block_energylimit = 0; - const uint64_t tx_energyprice = 0; - std::string tx_origin = op.caller; - std::string block_coinbase = op.caller; // verify this - - machine::context ctx = { - is_debug, - block_timestamp, - block_number, - block_difficulty, - block_energylimit, - tx_energyprice, - tx_origin, - block_coinbase - }; - - std::vector code(c.code.begin(), c.code.end()); - machine::chain_adapter adapter = make_chain_adapter(_db, c.owner, tx_origin, op.contract_hash, storage); - machine::machine m(ctx, code, msg, adapter); - - m.print_stack(); + std::vector unsigned_args; + std::copy(op.args.begin(), op.args.end(), std::back_inserter(unsigned_args)); + auto result = contract_invoke(_db, c.owner, op.caller, contract_hash, energy, unsigned_args, storage); - std::string line; - while (m.is_running()) - { - std::cerr << "step\n"; - m.step(); - // Print out any logging that was generated - while ( std::getline(m.get_logger(), line) ) - std::cerr << "\e[36m" << "LOG: " << line << "\e[0m" << std::endl; - } - while ( std::getline(m.get_logger(), line) ) - std::cerr << "\e[36m" << "LOG: " << line << "\e[0m" << std::endl; - std::cout << m.to_json() << std::endl; + if (cs) + _db.modify< contract_storage_object >(*cs, [&](contract_storage_object& cs) { + cs.contract = contract_hash; + cs.caller = op.caller; + cs.data = storage; + }); + else + _db.create< contract_storage_object >([&](contract_storage_object& cs) { + cs.data = storage; + }); } } } // xgt::chain diff --git a/libraries/protocol/include/xgt/protocol/xgt_operations.hpp b/libraries/protocol/include/xgt/protocol/xgt_operations.hpp index dd8ddf90..6ecbaa17 100644 --- a/libraries/protocol/include/xgt/protocol/xgt_operations.hpp +++ b/libraries/protocol/include/xgt/protocol/xgt_operations.hpp @@ -605,7 +605,7 @@ namespace xgt { namespace protocol { { wallet_name_type caller; contract_hash_type contract_hash; - vector< vector > args; + vector args; void validate()const; uint64_t energy_cost()const { return 0; } diff --git a/libraries/vendor/xgtvm/libraries/machine.cpp b/libraries/vendor/xgtvm/libraries/machine.cpp index 7687f435..901e1f6a 100644 --- a/libraries/vendor/xgtvm/libraries/machine.cpp +++ b/libraries/vendor/xgtvm/libraries/machine.cpp @@ -531,7 +531,7 @@ namespace machine offset = static_cast( pop_word() ); if (offset > msg.input_size) { - logger << "calldataload start index is larger than message input_size"; + logger << "calldataload start index is larger than message input_size" << std::endl; break; } @@ -559,7 +559,7 @@ namespace machine length = static_cast( pop_word() ); if ((offset + length) > msg.input_size) { - logger << "calldatacopy end index is larger than message input_size"; + logger << "calldatacopy end index is larger than message input_size" << std::endl; break; } @@ -579,7 +579,7 @@ namespace machine length = static_cast( pop_word() ); if ((offset + length) > msg.input_size) { - logger << "Codecopy end index is larger than message input_size"; + logger << "Codecopy end index is larger than message input_size" << std::endl; break; } @@ -621,7 +621,7 @@ namespace machine length = static_cast( pop_word() ); if ((offset + length) > code_size) { - logger << "codecopy end index exceeds external contract code length"; + logger << "codecopy end index exceeds external contract code length" << std::endl; break; } @@ -646,7 +646,7 @@ namespace machine length = static_cast( pop_word() ); if ( (offset + length) > ext_return_data.size() ) { - logger << "returndatacopy end index exceeds return data size"; + logger << "returndatacopy end index exceeds return data size" << std::endl; break; } @@ -2967,7 +2967,7 @@ namespace machine { stack_variant sv = *it; s << sv; - if (it + 1 != stack.cend()) + if (stack.size() > 1 && std::next(it, 1) != stack.cend()) s << ","; } s << "],"; @@ -2976,14 +2976,47 @@ namespace machine { word w = *it; s << std::to_string(w); - if (it + 1 != return_value.cend()) + if (return_value.size() > 1 && std::next(it, 1) != return_value.cend()) s << ","; } s << "],"; + + s << "\"machineState\":\""; + switch (state) { + case machine_state::stopped: + s << "stopped"; + break; + case machine_state::running: + s << "running"; + break; + case machine_state::error: + s << "error"; + break; + default: + s << "unknown"; + } + s << "\","; + + word current_instruction = code[pc]; + opcode op = (opcode)current_instruction; + s << "\"opcode\":" << std::dec << op << ","; + if (error_message == boost::none) s << "\"exceptionError\":" << "null"; else s << "\"exceptionError\":" << "\"" << error_message.value() << "\""; + s << ","; + + s << "\"memory\":" << "{"; + for (auto it = memory.cbegin(); it != memory.cend(); ++it) + { + s << "\"" << it->first << "\""; + s << ":"; + s << unsigned(it->second); + if (memory.size() > 1 && std::next(it, 1) != memory.cend()) + s << ","; + } + s << "}"; } s << "}"; } diff --git a/libraries/vendor/xgtvm/programs/xgtvm.cpp b/libraries/vendor/xgtvm/programs/xgtvm.cpp index 3196b183..82818ed6 100644 --- a/libraries/vendor/xgtvm/programs/xgtvm.cpp +++ b/libraries/vendor/xgtvm/programs/xgtvm.cpp @@ -203,17 +203,17 @@ int main(int argc, char** argv) std::string line; while (m.is_running()) { - std::cerr << "step\n"; + if (debug_flag) + std::cerr << "step\n"; m.step(); // Print out any logging that was generated if (debug_flag) - { while ( std::getline(m.get_logger(), line) ) std::cerr << "\e[36m" << "LOG: " << line << "\e[0m" << std::endl; - } } - while ( std::getline(m.get_logger(), line) ) - std::cerr << "\e[36m" << "LOG: " << line << "\e[0m" << std::endl; + if (debug_flag) + while ( std::getline(m.get_logger(), line) ) + std::cerr << "\e[36m" << "LOG: " << line << "\e[0m" << std::endl; std::cout << m.to_json() << std::endl; } diff --git a/libraries/vendor/xgtvm/programs/xgtvm_tests.cpp b/libraries/vendor/xgtvm/programs/xgtvm_tests.cpp index 4b23c5aa..d75ed781 100644 --- a/libraries/vendor/xgtvm/programs/xgtvm_tests.cpp +++ b/libraries/vendor/xgtvm/programs/xgtvm_tests.cpp @@ -13,85 +13,103 @@ machine::chain_adapter make_chain_adapter() { std::function< std::string(std::vector) > sha3 = [](std::vector memory) -> std::string { + std::cout << "chain_adapter::sha3" << std::endl; return 0; }; std::function< uint64_t(std::string) > get_balance = [](std::string address) -> uint64_t { + std::cout << "chain_adapter::get_balance" << std::endl; return 0; }; std::function< std::string(std::string) > get_code_hash = [](std::string address) -> std::string { + std::cout << "chain_adapter::get_code_hash" << std::endl; return ""; }; std::function< machine::big_word(uint64_t) > get_block_hash = [](uint64_t block_num) -> machine::big_word { + std::cout << "chain_adapter::get_block_hash" << std::endl; return {}; }; std::function< std::vector(std::string) > get_code_at_addr = [](std::string address) -> std::vector { + std::cout << "chain_adapter::get_code_at_addr" << std::endl; return {}; }; std::function< std::string(std::vector, machine::big_word) > contract_create = [](std::vector memory, machine::big_word value) -> std::string { + std::cout << "chain_adapter::contract_create" << std::endl; return {}; }; std::function< std::vector(std::string, uint64_t, machine::big_word, std::vector) > contract_call = [](std::string address, uint64_t energy, machine::big_word value, std::vector args) -> std::vector { + std::cout << "chain_adapter::contract_call" << std::endl; return {}; }; std::function< std::vector(std::string, uint64_t, machine::big_word, std::vector) > contract_callcode = [](std::string address, uint64_t energy, machine::big_word value, std::vector args) -> std::vector { + std::cout << "chain_adapter::contract_callcode" << std::endl; return {}; }; std::function< std::vector(std::string, uint64_t, std::vector) > contract_delegatecall = [](std::string address, uint64_t energy, std::vector args) -> std::vector { + std::cout << "chain_adapter::contract_delegatecall" << std::endl; return {}; }; std::function< std::vector(std::string, uint64_t, std::vector) > contract_staticcall = [](std::string address, uint64_t energy, std::vector args) -> std::vector { + std::cout << "chain_adapter::contract_staticcall" << std::endl; return {}; }; std::function< std::string(std::vector, machine::big_word, std::string) > contract_create2 = [](std::vector memory, machine::big_word value, std::string salt) -> std::string { + std::cout << "chain_adapter::contract_create2" << std::endl; return {}; }; std::function< bool(std::vector) > revert = [](std::vector memory) -> bool { + std::cout << "chain_adapter::revert" << std::endl; return {}; }; std::function< machine::big_word(machine::big_word) > get_storage = [](machine::big_word) -> machine::big_word { + std::cout << "chain_adapter::get_storage" << std::endl; return 0; }; - std::function< void(machine::big_word, machine::big_word) > set_storage = [](machine::big_word, machine::big_word value) -> bool + std::function< bool(machine::big_word, machine::big_word) > set_storage = [](machine::big_word, machine::big_word value) -> bool { + std::cout << "chain_adapter::set_storage" << std::endl; + return false; }; std::function< bool(std::vector) > contract_return = [](std::vector memory) -> bool { + std::cout << "chain_adapter::contract_return" << std::endl; return {}; }; std::function< bool(std::string) > self_destruct = [](std::string address) -> bool { + std::cout << "chain_adapter::self_destruct" << std::endl; return {}; }; std::function< std::vector(std::string) > get_input_data = [](std::string address) -> std::vector { + std::cout << "chain_adapter::get_input_data" << std::endl; return {}; }; @@ -120,93 +138,199 @@ machine::chain_adapter make_chain_adapter() int main(int argc, char** argv) { - test_that("machine runs and halts") + //test_that("machine runs and halts") + //{ + // std::vector input = {0x00}; + // machine::context ctx = {true, 0x00}; + // machine::message msg = {}; + // machine::chain_adapter adapter = make_chain_adapter(); + // machine::machine m(ctx, input, msg, adapter); + // assert_message( "machine should start running", m.get_state() == machine::machine_state::running ); + // while (m.is_running()) + // m.step(); + // assert_message( "machine should stop when done executing", m.get_state() == machine::machine_state::stopped ); + // assert_message( "stack has correct length", m.stack_length() == 0 ); + //} + + //test_that("machine halts when nothing else to do") + //{ + // std::vector input = {}; + // machine::context ctx = {true, 0x00}; + // machine::message msg = {}; + // machine::chain_adapter adapter = make_chain_adapter(); + // machine::machine m(ctx, input, msg, adapter); + // while (m.is_running()) + // m.step(); + // assert_message( "machine should stop when done executing", m.get_state() == machine::machine_state::stopped ); + // assert_message( "stack has correct length", m.stack_length() == 0 ); + //} + + //test_that("machine returns a timestamp") + //{ + // std::vector input = {0x42, 0x00}; + // machine::context ctx = {true, 0x5c477758}; + // machine::message msg = {}; + // machine::chain_adapter adapter = make_chain_adapter(); + // machine::machine m(ctx, input, msg, adapter); + // while (m.is_running()) + // m.step(); + // assert_message( "machine should stop when done executing", m.get_state() == machine::machine_state::stopped ); + // assert_message( "stack has correct length", m.stack_length() == 1 ); + // assert_message( "top of stack has correct value", m.peek_word() == 0x5c477758 ); + //} + + //test_that("machine adds unsigned 8-bit values") + //{ + // std::vector input = {0x60, 0x02, 0x60, 0x03, 0x01, 0x00}; + // machine::context ctx = {true, 0x00}; + // machine::message msg = {}; + // machine::chain_adapter adapter = make_chain_adapter(); + // machine::machine m(ctx, input, msg, adapter); + // while (m.is_running()) + // m.step(); + // assert_message( "machine should stop when done executing", m.get_state() == machine::machine_state::stopped ); + // assert_message( "stack has correct length", m.stack_length() == 1 ); + // assert_message( "top of stack has correct value", m.peek_word() == 5 ); + //} + + //test_that("machine can store and load a value to/from memory") + //{ + // std::vector input = {0x60, 0x01, 0x60, 0x08, 0x52, 0x60, 0x08, 0x51, 0x00}; + // machine::context ctx = {true, 0x00}; + // machine::message msg = {}; + // machine::chain_adapter adapter = make_chain_adapter(); + // machine::machine m(ctx, input, msg, adapter); + // while (m.is_running()) + // m.step(); + // assert_message( "machine should stop when done executing", m.get_state() == machine::machine_state::stopped ); + // assert_message( "stack has correct length", m.stack_length() == 1 ); + // assert_message( "top of stack has correct value", m.peek_word() == 1 ); + //} + + //test_that("machine can get a wallet's balance via the chain adapter") + //{ + // std::vector input = {0x31, 0x00}; + // machine::context ctx = {true, 0x00}; + // machine::message msg = {}; + // machine::chain_adapter adapter = make_chain_adapter(); + // adapter.get_balance = [](std::string wallet_name) -> uint64_t + // { + // return 2; + // }; + // machine::machine m(ctx, input, msg, adapter); + // m.push_string("alice"); + // while (m.is_running()) + // m.step(); + // assert_message( "machine should stop when done executing", m.get_state() == machine::machine_state::stopped ); + // assert_message( "stack has correct length", m.stack_length() == 1 ); + // assert_message( "top of stack has correct value", m.peek_word() == 2 ); + //} + + test_that("do nothing contract evaluates") { - std::vector input = {0x00}; + std::vector input = {0x60, 0x80, 0x60, 0x40, 0x52, 0x34, 0x80, 0x15, 0x60, 0x0f, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x60, 0x6d, 0x80, 0x60, 0x1d, 0x60, 0x00, 0x39, 0x60, 0x00, 0xf3, 0xfe, 0x60, 0x80, 0x60, 0x40, 0x52, 0x34, 0x80, 0x15, 0x60, 0x0f, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x60, 0x04, 0x36, 0x10, 0x60, 0x28, 0x57, 0x60, 0x00, 0x35, 0x60, 0xe0, 0x1c, 0x80, 0x63, 0x2f, 0x57, 0x6f, 0x20, 0x14, 0x60, 0x2d, 0x57, 0x5b, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x60, 0x33, 0x60, 0x35, 0x56, 0x5b, 0x00, 0x5b, 0x56, 0xfe, 0xa2, 0x64, 0x69, 0x70, 0x66, 0x73, 0x58, 0x22, 0x12, 0x20, 0x97, 0x5b, 0xdb, 0x69, 0x49, 0x44, 0x25, 0x38, 0xb9, 0x0c, 0x14, 0xc4, 0x20, 0xb0, 0xa2, 0xf5, 0x47, 0xf0, 0x43, 0x7e, 0x85, 0xa7, 0x3d, 0xa1, 0x2f, 0xaf, 0x4e, 0x68, 0x34, 0xf0, 0x81, 0x72, 0x64, 0x73, 0x6f, 0x6c, 0x63, 0x43, 0x00, 0x08, 0x07, 0x00, 0x33}; machine::context ctx = {true, 0x00}; machine::message msg = {}; machine::chain_adapter adapter = make_chain_adapter(); machine::machine m(ctx, input, msg, adapter); assert_message( "machine should start running", m.get_state() == machine::machine_state::running ); + + auto& logger = m.get_logger(); + std::string line; + std::cerr << "\e[36m" << "LOG: " << m.to_json() << "\e[0m" << std::endl; while (m.is_running()) + { m.step(); + //// TODO: Figure out why logs not emitting + //while ( std::getline(logger, line) ) + // std::cerr << "\e[36m" << "LOG: " << line << "\e[0m" << std::endl; + std::cerr << "\e[36m" << "LOG: " << m.to_json() << "\e[0m" << std::endl; + } + //while ( std::getline(logger, line) ) + // std::cerr << "\e[36m" << "LOG: " << line << "\e[0m" << std::endl; + std::cerr << "\e[36m" << "LOG: " << m.to_json() << "\e[0m" << std::endl; + assert_message( "machine should stop when done executing", m.get_state() == machine::machine_state::stopped ); assert_message( "stack has correct length", m.stack_length() == 0 ); } - test_that("machine halts when nothing else to do") + test_that("storage contract evaluates") { - std::vector input = {}; + std::vector input = {0x60, 0x80, 0x60, 0x40, 0x52, 0x34, 0x80, 0x15, 0x61, 0x00, 0x10, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x61, 0x01, 0x50, 0x80, 0x61, 0x00, 0x20, 0x60, 0x00, 0x39, 0x60, 0x00, 0xf3, 0xfe, 0x60, 0x80, 0x60, 0x40, 0x52, 0x34, 0x80, 0x15, 0x61, 0x00, 0x10, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x60, 0x04, 0x36, 0x10, 0x61, 0x00, 0x36, 0x57, 0x60, 0x00, 0x35, 0x60, 0xe0, 0x1c, 0x80, 0x63, 0x2e, 0x64, 0xce, 0xc1, 0x14, 0x61, 0x00, 0x3b, 0x57, 0x80, 0x63, 0x60, 0x57, 0x36, 0x1d, 0x14, 0x61, 0x00, 0x59, 0x57, 0x5b, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x61, 0x00, 0x43, 0x61, 0x00, 0x75, 0x56, 0x5b, 0x60, 0x40, 0x51, 0x61, 0x00, 0x50, 0x91, 0x90, 0x61, 0x00, 0xd9, 0x56, 0x5b, 0x60, 0x40, 0x51, 0x80, 0x91, 0x03, 0x90, 0xf3, 0x5b, 0x61, 0x00, 0x73, 0x60, 0x04, 0x80, 0x36, 0x03, 0x81, 0x01, 0x90, 0x61, 0x00, 0x6e, 0x91, 0x90, 0x61, 0x00, 0x9d, 0x56, 0x5b, 0x61, 0x00, 0x7e, 0x56, 0x5b, 0x00, 0x5b, 0x60, 0x00, 0x80, 0x54, 0x90, 0x50, 0x90, 0x56, 0x5b, 0x80, 0x60, 0x00, 0x81, 0x90, 0x55, 0x50, 0x50, 0x56, 0x5b, 0x60, 0x00, 0x81, 0x35, 0x90, 0x50, 0x61, 0x00, 0x97, 0x81, 0x61, 0x01, 0x03, 0x56, 0x5b, 0x92, 0x91, 0x50, 0x50, 0x56, 0x5b, 0x60, 0x00, 0x60, 0x20, 0x82, 0x84, 0x03, 0x12, 0x15, 0x61, 0x00, 0xb3, 0x57, 0x61, 0x00, 0xb2, 0x61, 0x00, 0xfe, 0x56, 0x5b, 0x5b, 0x60, 0x00, 0x61, 0x00, 0xc1, 0x84, 0x82, 0x85, 0x01, 0x61, 0x00, 0x88, 0x56, 0x5b, 0x91, 0x50, 0x50, 0x92, 0x91, 0x50, 0x50, 0x56, 0x5b, 0x61, 0x00, 0xd3, 0x81, 0x61, 0x00, 0xf4, 0x56, 0x5b, 0x82, 0x52, 0x50, 0x50, 0x56, 0x5b, 0x60, 0x00, 0x60, 0x20, 0x82, 0x01, 0x90, 0x50, 0x61, 0x00, 0xee, 0x60, 0x00, 0x83, 0x01, 0x84, 0x61, 0x00, 0xca, 0x56, 0x5b, 0x92, 0x91, 0x50, 0x50, 0x56, 0x5b, 0x60, 0x00, 0x81, 0x90, 0x50, 0x91, 0x90, 0x50, 0x56, 0x5b, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x61, 0x01, 0x0c, 0x81, 0x61, 0x00, 0xf4, 0x56, 0x5b, 0x81, 0x14, 0x61, 0x01, 0x17, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x56, 0xfe, 0xa2, 0x64, 0x69, 0x70, 0x66, 0x73, 0x58, 0x22, 0x12, 0x20, 0x40, 0x4e, 0x37, 0xf4, 0x87, 0xa8, 0x9a, 0x93, 0x2d, 0xca, 0x5e, 0x77, 0xfa, 0xaf, 0x6c, 0xa2, 0xde, 0x3b, 0x99, 0x1f, 0x93, 0xd2, 0x30, 0x60, 0x4b, 0x1b, 0x8d, 0xaa, 0xef, 0x64, 0x76, 0x62, 0x64, 0x73, 0x6f, 0x6c, 0x63, 0x43, 0x00, 0x08, 0x07, 0x00, 0x33}; machine::context ctx = {true, 0x00}; machine::message msg = {}; machine::chain_adapter adapter = make_chain_adapter(); machine::machine m(ctx, input, msg, adapter); + assert_message( "machine should start running", m.get_state() == machine::machine_state::running ); + + auto& logger = m.get_logger(); + std::string line; + std::cerr << "\e[36m" << "LOG: " << m.to_json() << "\e[0m" << std::endl; while (m.is_running()) + { m.step(); + //// TODO: Figure out why logs not emitting + //while ( std::getline(logger, line) ) + // std::cerr << "\e[36m" << "LOG: " << line << "\e[0m" << std::endl; + std::cerr << "\e[36m" << "LOG: " << m.to_json() << "\e[0m" << std::endl; + } + //while ( std::getline(logger, line) ) + // std::cerr << "\e[36m" << "LOG: " << line << "\e[0m" << std::endl; + std::cerr << "\e[36m" << "LOG: " << m.to_json() << "\e[0m" << std::endl; + assert_message( "machine should stop when done executing", m.get_state() == machine::machine_state::stopped ); assert_message( "stack has correct length", m.stack_length() == 0 ); } - test_that("machine returns a timestamp") - { - std::vector input = {0x42, 0x00}; - machine::context ctx = {true, 0x5c477758}; - machine::message msg = {}; - machine::chain_adapter adapter = make_chain_adapter(); - machine::machine m(ctx, input, msg, adapter); - while (m.is_running()) - m.step(); - assert_message( "machine should stop when done executing", m.get_state() == machine::machine_state::stopped ); - assert_message( "stack has correct length", m.stack_length() == 1 ); - assert_message( "top of stack has correct value", m.peek_word() == 0x5c477758 ); - } + //test_that("first lottery contract evaluates") + //{ + // std::vector input = {0x60, 0x80, 0x60, 0x40, 0x52, 0x34, 0x80, 0x15, 0x61, 0x00, 0x10, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x33, 0x60, 0x00, 0x80, 0x61, 0x01, 0x00, 0x0a, 0x81, 0x54, 0x81, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0x19, 0x16, 0x90, 0x83, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x02, 0x17, 0x90, 0x55, 0x50, 0x61, 0x06, 0x80, 0x80, 0x61, 0x00, 0x60, 0x60, 0x00, 0x39, 0x60, 0x00, 0xf3, 0x00, 0x60, 0x80, 0x60, 0x40, 0x52, 0x60, 0x04, 0x36, 0x10, 0x61, 0x00, 0x6d, 0x57, 0x60, 0x00, 0x35, 0x7c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x04, 0x63, 0xff, 0xff, 0xff, 0xff, 0x16, 0x80, 0x63, 0x48, 0x1c, 0x6a, 0x75, 0x14, 0x61, 0x00, 0x72, 0x57, 0x80, 0x63, 0x5d, 0x49, 0x5a, 0xea, 0x14, 0x61, 0x00, 0xc9, 0x57, 0x80, 0x63, 0x8b, 0x5b, 0x9c, 0xcc, 0x14, 0x61, 0x00, 0xe0, 0x57, 0x80, 0x63, 0xe9, 0x7d, 0xcb, 0x62, 0x14, 0x61, 0x01, 0x4c, 0x57, 0x80, 0x63, 0xf7, 0x1d, 0x96, 0xcb, 0x14, 0x61, 0x01, 0x56, 0x57, 0x5b, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x34, 0x80, 0x15, 0x61, 0x00, 0x7e, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x61, 0x00, 0x87, 0x61, 0x01, 0xc3, 0x56, 0x5b, 0x60, 0x40, 0x51, 0x80, 0x82, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x91, 0x50, 0x50, 0x60, 0x40, 0x51, 0x80, 0x91, 0x03, 0x90, 0xf3, 0x5b, 0x34, 0x80, 0x15, 0x61, 0x00, 0xd5, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x61, 0x00, 0xde, 0x61, 0x01, 0xe8, 0x56, 0x5b, 0x00, 0x5b, 0x34, 0x80, 0x15, 0x61, 0x00, 0xec, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x61, 0x00, 0xf5, 0x61, 0x03, 0x40, 0x56, 0x5b, 0x60, 0x40, 0x51, 0x80, 0x80, 0x60, 0x20, 0x01, 0x82, 0x81, 0x03, 0x82, 0x52, 0x83, 0x81, 0x81, 0x51, 0x81, 0x52, 0x60, 0x20, 0x01, 0x91, 0x50, 0x80, 0x51, 0x90, 0x60, 0x20, 0x01, 0x90, 0x60, 0x20, 0x02, 0x80, 0x83, 0x83, 0x60, 0x00, 0x5b, 0x83, 0x81, 0x10, 0x15, 0x61, 0x01, 0x38, 0x57, 0x80, 0x82, 0x01, 0x51, 0x81, 0x84, 0x01, 0x52, 0x60, 0x20, 0x81, 0x01, 0x90, 0x50, 0x61, 0x01, 0x1d, 0x56, 0x5b, 0x50, 0x50, 0x50, 0x50, 0x90, 0x50, 0x01, 0x92, 0x50, 0x50, 0x50, 0x60, 0x40, 0x51, 0x80, 0x91, 0x03, 0x90, 0xf3, 0x5b, 0x61, 0x01, 0x54, 0x61, 0x03, 0xce, 0x56, 0x5b, 0x00, 0x5b, 0x34, 0x80, 0x15, 0x61, 0x01, 0x62, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x61, 0x01, 0x81, 0x60, 0x04, 0x80, 0x36, 0x03, 0x81, 0x01, 0x90, 0x80, 0x80, 0x35, 0x90, 0x60, 0x20, 0x01, 0x90, 0x92, 0x91, 0x90, 0x50, 0x50, 0x50, 0x61, 0x04, 0x4b, 0x56, 0x5b, 0x60, 0x40, 0x51, 0x80, 0x82, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x91, 0x50, 0x50, 0x60, 0x40, 0x51, 0x80, 0x91, 0x03, 0x90, 0xf3, 0x5b, 0x60, 0x00, 0x80, 0x90, 0x54, 0x90, 0x61, 0x01, 0x00, 0x0a, 0x90, 0x04, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x56, 0x5b, 0x60, 0x00, 0x80, 0x60, 0x00, 0x90, 0x54, 0x90, 0x61, 0x01, 0x00, 0x0a, 0x90, 0x04, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x33, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x14, 0x15, 0x15, 0x61, 0x02, 0x45, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x60, 0x01, 0x80, 0x54, 0x90, 0x50, 0x61, 0x02, 0x53, 0x61, 0x04, 0x89, 0x56, 0x5b, 0x81, 0x15, 0x15, 0x61, 0x02, 0x5c, 0x57, 0xfe, 0x5b, 0x06, 0x90, 0x50, 0x60, 0x01, 0x81, 0x81, 0x54, 0x81, 0x10, 0x15, 0x15, 0x61, 0x02, 0x6e, 0x57, 0xfe, 0x5b, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x01, 0x60, 0x00, 0x90, 0x54, 0x90, 0x61, 0x01, 0x00, 0x0a, 0x90, 0x04, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x61, 0x08, 0xfc, 0x30, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x31, 0x90, 0x81, 0x15, 0x02, 0x90, 0x60, 0x40, 0x51, 0x60, 0x00, 0x60, 0x40, 0x51, 0x80, 0x83, 0x03, 0x81, 0x85, 0x88, 0x88, 0xf1, 0x93, 0x50, 0x50, 0x50, 0x50, 0x15, 0x80, 0x15, 0x61, 0x02, 0xf5, 0x57, 0x3d, 0x60, 0x00, 0x80, 0x3e, 0x3d, 0x60, 0x00, 0xfd, 0x5b, 0x50, 0x60, 0x00, 0x60, 0x40, 0x51, 0x90, 0x80, 0x82, 0x52, 0x80, 0x60, 0x20, 0x02, 0x60, 0x20, 0x01, 0x82, 0x01, 0x60, 0x40, 0x52, 0x80, 0x15, 0x61, 0x03, 0x26, 0x57, 0x81, 0x60, 0x20, 0x01, 0x60, 0x20, 0x82, 0x02, 0x80, 0x38, 0x83, 0x39, 0x80, 0x82, 0x01, 0x91, 0x50, 0x50, 0x90, 0x50, 0x5b, 0x50, 0x60, 0x01, 0x90, 0x80, 0x51, 0x90, 0x60, 0x20, 0x01, 0x90, 0x61, 0x03, 0x3c, 0x92, 0x91, 0x90, 0x61, 0x05, 0x87, 0x56, 0x5b, 0x50, 0x50, 0x56, 0x5b, 0x60, 0x60, 0x60, 0x01, 0x80, 0x54, 0x80, 0x60, 0x20, 0x02, 0x60, 0x20, 0x01, 0x60, 0x40, 0x51, 0x90, 0x81, 0x01, 0x60, 0x40, 0x52, 0x80, 0x92, 0x91, 0x90, 0x81, 0x81, 0x52, 0x60, 0x20, 0x01, 0x82, 0x80, 0x54, 0x80, 0x15, 0x61, 0x03, 0xc4, 0x57, 0x60, 0x20, 0x02, 0x82, 0x01, 0x91, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x90, 0x5b, 0x81, 0x60, 0x00, 0x90, 0x54, 0x90, 0x61, 0x01, 0x00, 0x0a, 0x90, 0x04, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x90, 0x60, 0x01, 0x01, 0x90, 0x80, 0x83, 0x11, 0x61, 0x03, 0x7a, 0x57, 0x5b, 0x50, 0x50, 0x50, 0x50, 0x50, 0x90, 0x50, 0x90, 0x56, 0x5b, 0x66, 0x23, 0x86, 0xf2, 0x6f, 0xc1, 0x00, 0x00, 0x34, 0x11, 0x15, 0x15, 0x61, 0x03, 0xe3, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x60, 0x01, 0x33, 0x90, 0x80, 0x60, 0x01, 0x81, 0x54, 0x01, 0x80, 0x82, 0x55, 0x80, 0x91, 0x50, 0x50, 0x90, 0x60, 0x01, 0x82, 0x03, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x01, 0x60, 0x00, 0x90, 0x91, 0x92, 0x90, 0x91, 0x90, 0x91, 0x61, 0x01, 0x00, 0x0a, 0x81, 0x54, 0x81, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0x19, 0x16, 0x90, 0x83, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x02, 0x17, 0x90, 0x55, 0x50, 0x50, 0x56, 0x5b, 0x60, 0x01, 0x81, 0x81, 0x54, 0x81, 0x10, 0x15, 0x15, 0x61, 0x04, 0x5a, 0x57, 0xfe, 0x5b, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x01, 0x60, 0x00, 0x91, 0x50, 0x54, 0x90, 0x61, 0x01, 0x00, 0x0a, 0x90, 0x04, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x56, 0x5b, 0x60, 0x00, 0x44, 0x42, 0x60, 0x01, 0x60, 0x40, 0x51, 0x60, 0x20, 0x01, 0x80, 0x84, 0x81, 0x52, 0x60, 0x20, 0x01, 0x83, 0x81, 0x52, 0x60, 0x20, 0x01, 0x82, 0x80, 0x54, 0x80, 0x15, 0x61, 0x05, 0x06, 0x57, 0x60, 0x20, 0x02, 0x82, 0x01, 0x91, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x90, 0x5b, 0x81, 0x60, 0x00, 0x90, 0x54, 0x90, 0x61, 0x01, 0x00, 0x0a, 0x90, 0x04, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x90, 0x60, 0x01, 0x01, 0x90, 0x80, 0x83, 0x11, 0x61, 0x04, 0xbc, 0x57, 0x5b, 0x50, 0x50, 0x93, 0x50, 0x50, 0x50, 0x50, 0x60, 0x40, 0x51, 0x60, 0x20, 0x81, 0x83, 0x03, 0x03, 0x81, 0x52, 0x90, 0x60, 0x40, 0x52, 0x60, 0x40, 0x51, 0x80, 0x82, 0x80, 0x51, 0x90, 0x60, 0x20, 0x01, 0x90, 0x80, 0x83, 0x83, 0x5b, 0x60, 0x20, 0x83, 0x10, 0x15, 0x15, 0x61, 0x05, 0x51, 0x57, 0x80, 0x51, 0x82, 0x52, 0x60, 0x20, 0x82, 0x01, 0x91, 0x50, 0x60, 0x20, 0x81, 0x01, 0x90, 0x50, 0x60, 0x20, 0x83, 0x03, 0x92, 0x50, 0x61, 0x05, 0x2c, 0x56, 0x5b, 0x60, 0x01, 0x83, 0x60, 0x20, 0x03, 0x61, 0x01, 0x00, 0x0a, 0x03, 0x80, 0x19, 0x82, 0x51, 0x16, 0x81, 0x84, 0x51, 0x16, 0x80, 0x82, 0x17, 0x85, 0x52, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x90, 0x50, 0x01, 0x91, 0x50, 0x50, 0x60, 0x40, 0x51, 0x80, 0x91, 0x03, 0x90, 0x20, 0x60, 0x01, 0x90, 0x04, 0x90, 0x50, 0x90, 0x56, 0x5b, 0x82, 0x80, 0x54, 0x82, 0x82, 0x55, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x90, 0x81, 0x01, 0x92, 0x82, 0x15, 0x61, 0x06, 0x00, 0x57, 0x91, 0x60, 0x20, 0x02, 0x82, 0x01, 0x5b, 0x82, 0x81, 0x11, 0x15, 0x61, 0x05, 0xff, 0x57, 0x82, 0x51, 0x82, 0x60, 0x00, 0x61, 0x01, 0x00, 0x0a, 0x81, 0x54, 0x81, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0x19, 0x16, 0x90, 0x83, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x02, 0x17, 0x90, 0x55, 0x50, 0x91, 0x60, 0x20, 0x01, 0x91, 0x90, 0x60, 0x01, 0x01, 0x90, 0x61, 0x05, 0xa7, 0x56, 0x5b, 0x5b, 0x50, 0x90, 0x50, 0x61, 0x06, 0x0d, 0x91, 0x90, 0x61, 0x06, 0x11, 0x56, 0x5b, 0x50, 0x90, 0x56, 0x5b, 0x61, 0x06, 0x51, 0x91, 0x90, 0x5b, 0x80, 0x82, 0x11, 0x15, 0x61, 0x06, 0x4d, 0x57, 0x60, 0x00, 0x81, 0x81, 0x61, 0x01, 0x00, 0x0a, 0x81, 0x54, 0x90, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0x19, 0x16, 0x90, 0x55, 0x50, 0x60, 0x01, 0x01, 0x61, 0x06, 0x17, 0x56, 0x5b, 0x50, 0x90, 0x56, 0x5b, 0x90, 0x56, 0x00, 0xa1, 0x65, 0x62, 0x7a, 0x7a, 0x72, 0x30, 0x58, 0x20, 0x91, 0x9b, 0x1f, 0x32, 0x9a, 0xfa, 0x64, 0x06, 0xac, 0x32, 0xcc, 0xc8, 0x12, 0xf6, 0x5d, 0x08, 0xdc, 0xb2, 0x9f, 0x0c, 0x1b, 0x9f, 0xb6, 0x3c, 0xf3, 0x4e, 0x5a, 0xbf, 0xde, 0xf8, 0xda, 0x07, 0x00, 0x29}; + // machine::context ctx = {true, 0x00}; + // machine::message msg = {}; + // machine::chain_adapter adapter = make_chain_adapter(); + // machine::machine m(ctx, input, msg, adapter); + // assert_message( "machine should start running", m.get_state() == machine::machine_state::running ); - test_that("machine adds unsigned 8-bit values") - { - std::vector input = {0x60, 0x02, 0x60, 0x03, 0x01, 0x00}; - machine::context ctx = {true, 0x00}; - machine::message msg = {}; - machine::chain_adapter adapter = make_chain_adapter(); - machine::machine m(ctx, input, msg, adapter); - while (m.is_running()) - m.step(); - assert_message( "machine should stop when done executing", m.get_state() == machine::machine_state::stopped ); - assert_message( "stack has correct length", m.stack_length() == 1 ); - assert_message( "top of stack has correct value", m.peek_word() == 5 ); - } + // std::string line; + // while (m.is_running()) + // { + // m.step(); + // while ( std::getline(m.get_logger(), line) ) + // std::cerr << "\e[36m" << "LOG: " << line << "\e[0m" << std::endl; + // std::cout << m.to_json() << std::endl; + // } + // while ( std::getline(m.get_logger(), line) ) + // std::cerr << "\e[36m" << "LOG: " << line << "\e[0m" << std::endl; + // std::cout << m.to_json() << std::endl; - test_that("machine can store and load a value to/from memory") - { - std::vector input = {0x60, 0x01, 0x60, 0x08, 0x52, 0x60, 0x08, 0x51, 0x00}; - machine::context ctx = {true, 0x00}; - machine::message msg = {}; - machine::chain_adapter adapter = make_chain_adapter(); - machine::machine m(ctx, input, msg, adapter); - while (m.is_running()) - m.step(); - assert_message( "machine should stop when done executing", m.get_state() == machine::machine_state::stopped ); - assert_message( "stack has correct length", m.stack_length() == 1 ); - assert_message( "top of stack has correct value", m.peek_word() == 1 ); - } + // assert_message( "machine should stop when done executing", m.get_state() == machine::machine_state::stopped ); + // assert_message( "stack has correct length", m.stack_length() == 0 ); + //} - test_that("machine can get a wallet's balance via the chain adapter") - { - std::vector input = {0x31, 0x00}; - machine::context ctx = {true, 0x00}; - machine::message msg = {}; - machine::chain_adapter adapter = make_chain_adapter(); - adapter.get_balance = [](std::string wallet_name) -> uint64_t - { - return 2; - }; - machine::machine m(ctx, input, msg, adapter); - m.push_string("alice"); - while (m.is_running()) - m.step(); - assert_message( "machine should stop when done executing", m.get_state() == machine::machine_state::stopped ); - assert_message( "stack has correct length", m.stack_length() == 1 ); - assert_message( "top of stack has correct value", m.peek_word() == 2 ); - } + //test_that("second lottery contract evaluates") + //{ + // std::vector input = {0x60, 0x80, 0x60, 0x40, 0x52, 0x34, 0x80, 0x15, 0x62, 0x00, 0x00, 0x11, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x60, 0x40, 0x51, 0x62, 0x00, 0x17, 0x54, 0x38, 0x03, 0x80, 0x62, 0x00, 0x17, 0x54, 0x83, 0x39, 0x81, 0x01, 0x80, 0x60, 0x40, 0x52, 0x81, 0x01, 0x90, 0x80, 0x80, 0x51, 0x82, 0x01, 0x92, 0x91, 0x90, 0x60, 0x20, 0x01, 0x80, 0x51, 0x90, 0x60, 0x20, 0x01, 0x90, 0x92, 0x91, 0x90, 0x50, 0x50, 0x50, 0x80, 0x60, 0x01, 0x60, 0x00, 0x61, 0x01, 0x00, 0x0a, 0x81, 0x54, 0x81, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0x19, 0x16, 0x90, 0x83, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x02, 0x17, 0x90, 0x55, 0x50, 0x81, 0x60, 0x00, 0x90, 0x80, 0x51, 0x90, 0x60, 0x20, 0x01, 0x90, 0x62, 0x00, 0x00, 0x9c, 0x92, 0x91, 0x90, 0x62, 0x00, 0x00, 0xa5, 0x56, 0x5b, 0x50, 0x50, 0x50, 0x62, 0x00, 0x01, 0x54, 0x56, 0x5b, 0x82, 0x80, 0x54, 0x60, 0x01, 0x81, 0x60, 0x01, 0x16, 0x15, 0x61, 0x01, 0x00, 0x02, 0x03, 0x16, 0x60, 0x02, 0x90, 0x04, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x90, 0x60, 0x1f, 0x01, 0x60, 0x20, 0x90, 0x04, 0x81, 0x01, 0x92, 0x82, 0x60, 0x1f, 0x10, 0x62, 0x00, 0x00, 0xe8, 0x57, 0x80, 0x51, 0x60, 0xff, 0x19, 0x16, 0x83, 0x80, 0x01, 0x17, 0x85, 0x55, 0x62, 0x00, 0x01, 0x19, 0x56, 0x5b, 0x82, 0x80, 0x01, 0x60, 0x01, 0x01, 0x85, 0x55, 0x82, 0x15, 0x62, 0x00, 0x01, 0x19, 0x57, 0x91, 0x82, 0x01, 0x5b, 0x82, 0x81, 0x11, 0x15, 0x62, 0x00, 0x01, 0x18, 0x57, 0x82, 0x51, 0x82, 0x55, 0x91, 0x60, 0x20, 0x01, 0x91, 0x90, 0x60, 0x01, 0x01, 0x90, 0x62, 0x00, 0x00, 0xfb, 0x56, 0x5b, 0x5b, 0x50, 0x90, 0x50, 0x62, 0x00, 0x01, 0x28, 0x91, 0x90, 0x62, 0x00, 0x01, 0x2c, 0x56, 0x5b, 0x50, 0x90, 0x56, 0x5b, 0x62, 0x00, 0x01, 0x51, 0x91, 0x90, 0x5b, 0x80, 0x82, 0x11, 0x15, 0x62, 0x00, 0x01, 0x4d, 0x57, 0x60, 0x00, 0x81, 0x60, 0x00, 0x90, 0x55, 0x50, 0x60, 0x01, 0x01, 0x62, 0x00, 0x01, 0x33, 0x56, 0x5b, 0x50, 0x90, 0x56, 0x5b, 0x90, 0x56, 0x5b, 0x61, 0x15, 0xf0, 0x80, 0x62, 0x00, 0x01, 0x64, 0x60, 0x00, 0x39, 0x60, 0x00, 0xf3, 0x00, 0x60, 0x80, 0x60, 0x40, 0x52, 0x60, 0x04, 0x36, 0x10, 0x61, 0x00, 0xd0, 0x57, 0x60, 0x00, 0x35, 0x7c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x04, 0x63, 0xff, 0xff, 0xff, 0xff, 0x16, 0x80, 0x63, 0x10, 0xc8, 0x5f, 0xe5, 0x14, 0x61, 0x01, 0x10, 0x57, 0x80, 0x63, 0x14, 0x03, 0x4b, 0xd2, 0x14, 0x61, 0x01, 0x3f, 0x57, 0x80, 0x63, 0x1d, 0x27, 0x76, 0x9f, 0x14, 0x61, 0x01, 0x56, 0x57, 0x80, 0x63, 0x23, 0xd1, 0x41, 0x49, 0x14, 0x61, 0x01, 0xb2, 0x57, 0x80, 0x63, 0x48, 0x1c, 0x6a, 0x75, 0x14, 0x61, 0x02, 0x42, 0x57, 0x80, 0x63, 0x58, 0x32, 0xd5, 0x71, 0x14, 0x61, 0x02, 0x99, 0x57, 0x80, 0x63, 0x5c, 0x12, 0xcd, 0x4b, 0x14, 0x61, 0x03, 0x06, 0x57, 0x80, 0x63, 0x5d, 0x58, 0xa7, 0x4a, 0x14, 0x61, 0x03, 0xc9, 0x57, 0x80, 0x63, 0x77, 0x52, 0x04, 0x5b, 0x14, 0x61, 0x03, 0xf4, 0x57, 0x80, 0x63, 0x8b, 0x5b, 0x9c, 0xcc, 0x14, 0x61, 0x04, 0x1f, 0x57, 0x80, 0x63, 0xbd, 0xae, 0xa3, 0x26, 0x14, 0x61, 0x04, 0x8b, 0x57, 0x80, 0x63, 0xd6, 0x88, 0x95, 0xd8, 0x14, 0x61, 0x04, 0xc2, 0x57, 0x80, 0x63, 0xdf, 0xbf, 0x53, 0xae, 0x14, 0x61, 0x04, 0xed, 0x57, 0x80, 0x63, 0xf2, 0x52, 0x66, 0xdd, 0x14, 0x61, 0x05, 0x8b, 0x57, 0x5b, 0x61, 0x01, 0x0e, 0x60, 0x40, 0x80, 0x51, 0x90, 0x81, 0x01, 0x60, 0x40, 0x52, 0x80, 0x60, 0x07, 0x81, 0x52, 0x60, 0x20, 0x01, 0x7f, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x52, 0x50, 0x61, 0x05, 0xf8, 0x56, 0x5b, 0x00, 0x5b, 0x34, 0x80, 0x15, 0x61, 0x01, 0x1c, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x61, 0x01, 0x25, 0x61, 0x09, 0xee, 0x56, 0x5b, 0x60, 0x40, 0x51, 0x80, 0x82, 0x15, 0x15, 0x15, 0x15, 0x81, 0x52, 0x60, 0x20, 0x01, 0x91, 0x50, 0x50, 0x60, 0x40, 0x51, 0x80, 0x91, 0x03, 0x90, 0xf3, 0x5b, 0x34, 0x80, 0x15, 0x61, 0x01, 0x4b, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x61, 0x01, 0x54, 0x61, 0x0a, 0x01, 0x56, 0x5b, 0x00, 0x5b, 0x61, 0x01, 0xb0, 0x60, 0x04, 0x80, 0x36, 0x03, 0x81, 0x01, 0x90, 0x80, 0x80, 0x35, 0x90, 0x60, 0x20, 0x01, 0x90, 0x82, 0x01, 0x80, 0x35, 0x90, 0x60, 0x20, 0x01, 0x90, 0x80, 0x80, 0x60, 0x1f, 0x01, 0x60, 0x20, 0x80, 0x91, 0x04, 0x02, 0x60, 0x20, 0x01, 0x60, 0x40, 0x51, 0x90, 0x81, 0x01, 0x60, 0x40, 0x52, 0x80, 0x93, 0x92, 0x91, 0x90, 0x81, 0x81, 0x52, 0x60, 0x20, 0x01, 0x83, 0x83, 0x80, 0x82, 0x84, 0x37, 0x82, 0x01, 0x91, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x91, 0x92, 0x91, 0x92, 0x90, 0x50, 0x50, 0x50, 0x61, 0x05, 0xf8, 0x56, 0x5b, 0x00, 0x5b, 0x34, 0x80, 0x15, 0x61, 0x01, 0xbe, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x61, 0x01, 0xc7, 0x61, 0x0d, 0xbf, 0x56, 0x5b, 0x60, 0x40, 0x51, 0x80, 0x80, 0x60, 0x20, 0x01, 0x82, 0x81, 0x03, 0x82, 0x52, 0x83, 0x81, 0x81, 0x51, 0x81, 0x52, 0x60, 0x20, 0x01, 0x91, 0x50, 0x80, 0x51, 0x90, 0x60, 0x20, 0x01, 0x90, 0x80, 0x83, 0x83, 0x60, 0x00, 0x5b, 0x83, 0x81, 0x10, 0x15, 0x61, 0x02, 0x07, 0x57, 0x80, 0x82, 0x01, 0x51, 0x81, 0x84, 0x01, 0x52, 0x60, 0x20, 0x81, 0x01, 0x90, 0x50, 0x61, 0x01, 0xec, 0x56, 0x5b, 0x50, 0x50, 0x50, 0x50, 0x90, 0x50, 0x90, 0x81, 0x01, 0x90, 0x60, 0x1f, 0x16, 0x80, 0x15, 0x61, 0x02, 0x34, 0x57, 0x80, 0x82, 0x03, 0x80, 0x51, 0x60, 0x01, 0x83, 0x60, 0x20, 0x03, 0x61, 0x01, 0x00, 0x0a, 0x03, 0x19, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x91, 0x50, 0x5b, 0x50, 0x92, 0x50, 0x50, 0x50, 0x60, 0x40, 0x51, 0x80, 0x91, 0x03, 0x90, 0xf3, 0x5b, 0x34, 0x80, 0x15, 0x61, 0x02, 0x4e, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x61, 0x02, 0x57, 0x61, 0x0e, 0x5d, 0x56, 0x5b, 0x60, 0x40, 0x51, 0x80, 0x82, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x91, 0x50, 0x50, 0x60, 0x40, 0x51, 0x80, 0x91, 0x03, 0x90, 0xf3, 0x5b, 0x34, 0x80, 0x15, 0x61, 0x02, 0xa5, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x61, 0x02, 0xc4, 0x60, 0x04, 0x80, 0x36, 0x03, 0x81, 0x01, 0x90, 0x80, 0x80, 0x35, 0x90, 0x60, 0x20, 0x01, 0x90, 0x92, 0x91, 0x90, 0x50, 0x50, 0x50, 0x61, 0x0e, 0x83, 0x56, 0x5b, 0x60, 0x40, 0x51, 0x80, 0x82, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x91, 0x50, 0x50, 0x60, 0x40, 0x51, 0x80, 0x91, 0x03, 0x90, 0xf3, 0x5b, 0x34, 0x80, 0x15, 0x61, 0x03, 0x12, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x61, 0x03, 0x47, 0x60, 0x04, 0x80, 0x36, 0x03, 0x81, 0x01, 0x90, 0x80, 0x80, 0x35, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x90, 0x60, 0x20, 0x01, 0x90, 0x92, 0x91, 0x90, 0x50, 0x50, 0x50, 0x61, 0x0e, 0xc1, 0x56, 0x5b, 0x60, 0x40, 0x51, 0x80, 0x80, 0x60, 0x20, 0x01, 0x83, 0x81, 0x52, 0x60, 0x20, 0x01, 0x82, 0x81, 0x03, 0x82, 0x52, 0x84, 0x81, 0x81, 0x51, 0x81, 0x52, 0x60, 0x20, 0x01, 0x91, 0x50, 0x80, 0x51, 0x90, 0x60, 0x20, 0x01, 0x90, 0x80, 0x83, 0x83, 0x60, 0x00, 0x5b, 0x83, 0x81, 0x10, 0x15, 0x61, 0x03, 0x8d, 0x57, 0x80, 0x82, 0x01, 0x51, 0x81, 0x84, 0x01, 0x52, 0x60, 0x20, 0x81, 0x01, 0x90, 0x50, 0x61, 0x03, 0x72, 0x56, 0x5b, 0x50, 0x50, 0x50, 0x50, 0x90, 0x50, 0x90, 0x81, 0x01, 0x90, 0x60, 0x1f, 0x16, 0x80, 0x15, 0x61, 0x03, 0xba, 0x57, 0x80, 0x82, 0x03, 0x80, 0x51, 0x60, 0x01, 0x83, 0x60, 0x20, 0x03, 0x61, 0x01, 0x00, 0x0a, 0x03, 0x19, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x91, 0x50, 0x5b, 0x50, 0x93, 0x50, 0x50, 0x50, 0x50, 0x60, 0x40, 0x51, 0x80, 0x91, 0x03, 0x90, 0xf3, 0x5b, 0x34, 0x80, 0x15, 0x61, 0x03, 0xd5, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x61, 0x03, 0xde, 0x61, 0x10, 0x1e, 0x56, 0x5b, 0x60, 0x40, 0x51, 0x80, 0x82, 0x81, 0x52, 0x60, 0x20, 0x01, 0x91, 0x50, 0x50, 0x60, 0x40, 0x51, 0x80, 0x91, 0x03, 0x90, 0xf3, 0x5b, 0x34, 0x80, 0x15, 0x61, 0x04, 0x00, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x61, 0x04, 0x09, 0x61, 0x10, 0x24, 0x56, 0x5b, 0x60, 0x40, 0x51, 0x80, 0x82, 0x81, 0x52, 0x60, 0x20, 0x01, 0x91, 0x50, 0x50, 0x60, 0x40, 0x51, 0x80, 0x91, 0x03, 0x90, 0xf3, 0x5b, 0x34, 0x80, 0x15, 0x61, 0x04, 0x2b, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x61, 0x04, 0x34, 0x61, 0x10, 0x2a, 0x56, 0x5b, 0x60, 0x40, 0x51, 0x80, 0x80, 0x60, 0x20, 0x01, 0x82, 0x81, 0x03, 0x82, 0x52, 0x83, 0x81, 0x81, 0x51, 0x81, 0x52, 0x60, 0x20, 0x01, 0x91, 0x50, 0x80, 0x51, 0x90, 0x60, 0x20, 0x01, 0x90, 0x60, 0x20, 0x02, 0x80, 0x83, 0x83, 0x60, 0x00, 0x5b, 0x83, 0x81, 0x10, 0x15, 0x61, 0x04, 0x77, 0x57, 0x80, 0x82, 0x01, 0x51, 0x81, 0x84, 0x01, 0x52, 0x60, 0x20, 0x81, 0x01, 0x90, 0x50, 0x61, 0x04, 0x5c, 0x56, 0x5b, 0x50, 0x50, 0x50, 0x50, 0x90, 0x50, 0x01, 0x92, 0x50, 0x50, 0x50, 0x60, 0x40, 0x51, 0x80, 0x91, 0x03, 0x90, 0xf3, 0x5b, 0x34, 0x80, 0x15, 0x61, 0x04, 0x97, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x61, 0x04, 0xc0, 0x60, 0x04, 0x80, 0x36, 0x03, 0x81, 0x01, 0x90, 0x80, 0x80, 0x35, 0x90, 0x60, 0x20, 0x01, 0x90, 0x92, 0x91, 0x90, 0x80, 0x35, 0x90, 0x60, 0x20, 0x01, 0x90, 0x92, 0x91, 0x90, 0x50, 0x50, 0x50, 0x61, 0x10, 0xb8, 0x56, 0x5b, 0x00, 0x5b, 0x34, 0x80, 0x15, 0x61, 0x04, 0xce, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x61, 0x04, 0xd7, 0x61, 0x11, 0x61, 0x56, 0x5b, 0x60, 0x40, 0x51, 0x80, 0x82, 0x81, 0x52, 0x60, 0x20, 0x01, 0x91, 0x50, 0x50, 0x60, 0x40, 0x51, 0x80, 0x91, 0x03, 0x90, 0xf3, 0x5b, 0x34, 0x80, 0x15, 0x61, 0x04, 0xf9, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x61, 0x05, 0x02, 0x61, 0x11, 0x80, 0x56, 0x5b, 0x60, 0x40, 0x51, 0x80, 0x80, 0x60, 0x20, 0x01, 0x84, 0x81, 0x52, 0x60, 0x20, 0x01, 0x83, 0x81, 0x52, 0x60, 0x20, 0x01, 0x82, 0x81, 0x03, 0x82, 0x52, 0x85, 0x81, 0x81, 0x51, 0x81, 0x52, 0x60, 0x20, 0x01, 0x91, 0x50, 0x80, 0x51, 0x90, 0x60, 0x20, 0x01, 0x90, 0x80, 0x83, 0x83, 0x60, 0x00, 0x5b, 0x83, 0x81, 0x10, 0x15, 0x61, 0x05, 0x4e, 0x57, 0x80, 0x82, 0x01, 0x51, 0x81, 0x84, 0x01, 0x52, 0x60, 0x20, 0x81, 0x01, 0x90, 0x50, 0x61, 0x05, 0x33, 0x56, 0x5b, 0x50, 0x50, 0x50, 0x50, 0x90, 0x50, 0x90, 0x81, 0x01, 0x90, 0x60, 0x1f, 0x16, 0x80, 0x15, 0x61, 0x05, 0x7b, 0x57, 0x80, 0x82, 0x03, 0x80, 0x51, 0x60, 0x01, 0x83, 0x60, 0x20, 0x03, 0x61, 0x01, 0x00, 0x0a, 0x03, 0x19, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x91, 0x50, 0x5b, 0x50, 0x94, 0x50, 0x50, 0x50, 0x50, 0x50, 0x60, 0x40, 0x51, 0x80, 0x91, 0x03, 0x90, 0xf3, 0x5b, 0x34, 0x80, 0x15, 0x61, 0x05, 0x97, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x61, 0x05, 0xb6, 0x60, 0x04, 0x80, 0x36, 0x03, 0x81, 0x01, 0x90, 0x80, 0x80, 0x35, 0x90, 0x60, 0x20, 0x01, 0x90, 0x92, 0x91, 0x90, 0x50, 0x50, 0x50, 0x61, 0x12, 0x30, 0x56, 0x5b, 0x60, 0x40, 0x51, 0x80, 0x82, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x91, 0x50, 0x50, 0x60, 0x40, 0x51, 0x80, 0x91, 0x03, 0x90, 0xf3, 0x5b, 0x60, 0x00, 0x81, 0x51, 0x11, 0x15, 0x15, 0x61, 0x06, 0x08, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x60, 0x08, 0x60, 0x00, 0x90, 0x54, 0x90, 0x61, 0x01, 0x00, 0x0a, 0x90, 0x04, 0x60, 0xff, 0x16, 0x15, 0x15, 0x61, 0x06, 0x23, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x67, 0x0d, 0xe0, 0xb6, 0xb3, 0xa7, 0x64, 0x00, 0x00, 0x60, 0x0a, 0x54, 0x02, 0x34, 0x14, 0x15, 0x15, 0x61, 0x06, 0x3d, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x60, 0x09, 0x54, 0x60, 0x03, 0x60, 0x00, 0x33, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x90, 0x81, 0x52, 0x60, 0x20, 0x01, 0x60, 0x00, 0x20, 0x60, 0x01, 0x01, 0x54, 0x10, 0x15, 0x15, 0x61, 0x06, 0x8f, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x61, 0x06, 0x98, 0x33, 0x61, 0x12, 0x6e, 0x56, 0x5b, 0x15, 0x61, 0x07, 0xef, 0x57, 0x60, 0x01, 0x60, 0x03, 0x60, 0x00, 0x33, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x90, 0x81, 0x52, 0x60, 0x20, 0x01, 0x60, 0x00, 0x20, 0x60, 0x01, 0x01, 0x81, 0x90, 0x55, 0x50, 0x80, 0x60, 0x03, 0x60, 0x00, 0x33, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x90, 0x81, 0x52, 0x60, 0x20, 0x01, 0x60, 0x00, 0x20, 0x60, 0x00, 0x01, 0x90, 0x80, 0x51, 0x90, 0x60, 0x20, 0x01, 0x90, 0x61, 0x07, 0x3b, 0x92, 0x91, 0x90, 0x61, 0x13, 0xcb, 0x56, 0x5b, 0x50, 0x60, 0x01, 0x60, 0x02, 0x33, 0x90, 0x80, 0x60, 0x01, 0x81, 0x54, 0x01, 0x80, 0x82, 0x55, 0x80, 0x91, 0x50, 0x50, 0x90, 0x60, 0x01, 0x82, 0x03, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x01, 0x60, 0x00, 0x90, 0x91, 0x92, 0x90, 0x91, 0x90, 0x91, 0x61, 0x01, 0x00, 0x0a, 0x81, 0x54, 0x81, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0x19, 0x16, 0x90, 0x83, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x02, 0x17, 0x90, 0x55, 0x50, 0x03, 0x60, 0x03, 0x60, 0x00, 0x33, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x90, 0x81, 0x52, 0x60, 0x20, 0x01, 0x60, 0x00, 0x20, 0x60, 0x02, 0x01, 0x81, 0x90, 0x55, 0x50, 0x61, 0x08, 0x41, 0x56, 0x5b, 0x60, 0x01, 0x60, 0x03, 0x60, 0x00, 0x33, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x90, 0x81, 0x52, 0x60, 0x20, 0x01, 0x60, 0x00, 0x20, 0x60, 0x01, 0x01, 0x60, 0x00, 0x82, 0x82, 0x54, 0x01, 0x92, 0x50, 0x50, 0x81, 0x90, 0x55, 0x50, 0x5b, 0x60, 0x04, 0x33, 0x90, 0x80, 0x60, 0x01, 0x81, 0x54, 0x01, 0x80, 0x82, 0x55, 0x80, 0x91, 0x50, 0x50, 0x90, 0x60, 0x01, 0x82, 0x03, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x01, 0x60, 0x00, 0x90, 0x91, 0x92, 0x90, 0x91, 0x90, 0x91, 0x61, 0x01, 0x00, 0x0a, 0x81, 0x54, 0x81, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0x19, 0x16, 0x90, 0x83, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x02, 0x17, 0x90, 0x55, 0x50, 0x50, 0x7f, 0x76, 0x04, 0x1b, 0x6e, 0x81, 0x30, 0x99, 0x58, 0x74, 0xe7, 0x9e, 0x75, 0x1d, 0x28, 0x45, 0x36, 0xc3, 0x72, 0x42, 0xcb, 0x01, 0x4f, 0xb0, 0x58, 0x4e, 0xde, 0x1d, 0x1e, 0x64, 0xce, 0x03, 0xc9, 0x60, 0x03, 0x60, 0x00, 0x33, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x90, 0x81, 0x52, 0x60, 0x20, 0x01, 0x60, 0x00, 0x20, 0x60, 0x00, 0x01, 0x60, 0x03, 0x60, 0x00, 0x33, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x90, 0x81, 0x52, 0x60, 0x20, 0x01, 0x60, 0x00, 0x20, 0x60, 0x01, 0x01, 0x54, 0x60, 0x40, 0x51, 0x80, 0x80, 0x60, 0x20, 0x01, 0x83, 0x81, 0x52, 0x60, 0x20, 0x01, 0x82, 0x81, 0x03, 0x82, 0x52, 0x84, 0x81, 0x81, 0x54, 0x60, 0x01, 0x81, 0x60, 0x01, 0x16, 0x15, 0x61, 0x01, 0x00, 0x02, 0x03, 0x16, 0x60, 0x02, 0x90, 0x04, 0x81, 0x52, 0x60, 0x20, 0x01, 0x91, 0x50, 0x80, 0x54, 0x60, 0x01, 0x81, 0x60, 0x01, 0x16, 0x15, 0x61, 0x01, 0x00, 0x02, 0x03, 0x16, 0x60, 0x02, 0x90, 0x04, 0x80, 0x15, 0x61, 0x09, 0xdc, 0x57, 0x80, 0x60, 0x1f, 0x10, 0x61, 0x09, 0xb1, 0x57, 0x61, 0x01, 0x00, 0x80, 0x83, 0x54, 0x04, 0x02, 0x83, 0x52, 0x91, 0x60, 0x20, 0x01, 0x91, 0x61, 0x09, 0xdc, 0x56, 0x5b, 0x82, 0x01, 0x91, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x90, 0x5b, 0x81, 0x54, 0x81, 0x52, 0x90, 0x60, 0x01, 0x01, 0x90, 0x60, 0x20, 0x01, 0x80, 0x83, 0x11, 0x61, 0x09, 0xbf, 0x57, 0x82, 0x90, 0x03, 0x60, 0x1f, 0x16, 0x82, 0x01, 0x91, 0x5b, 0x50, 0x50, 0x93, 0x50, 0x50, 0x50, 0x50, 0x60, 0x40, 0x51, 0x80, 0x91, 0x03, 0x90, 0xa1, 0x50, 0x56, 0x5b, 0x60, 0x08, 0x60, 0x00, 0x90, 0x54, 0x90, 0x61, 0x01, 0x00, 0x0a, 0x90, 0x04, 0x60, 0xff, 0x16, 0x81, 0x56, 0x5b, 0x60, 0x00, 0x60, 0x01, 0x60, 0x00, 0x90, 0x54, 0x90, 0x61, 0x01, 0x00, 0x0a, 0x90, 0x04, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x33, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x14, 0x15, 0x15, 0x61, 0x0a, 0x5f, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x60, 0x00, 0x60, 0x04, 0x80, 0x54, 0x90, 0x50, 0x11, 0x15, 0x15, 0x61, 0x0a, 0x73, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x60, 0x04, 0x80, 0x54, 0x90, 0x50, 0x61, 0x0a, 0x81, 0x61, 0x13, 0x39, 0x56, 0x5b, 0x81, 0x15, 0x15, 0x61, 0x0a, 0x8a, 0x57, 0xfe, 0x5b, 0x06, 0x90, 0x50, 0x60, 0x04, 0x81, 0x81, 0x54, 0x81, 0x10, 0x15, 0x15, 0x61, 0x0a, 0x9c, 0x57, 0xfe, 0x5b, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x01, 0x60, 0x00, 0x90, 0x54, 0x90, 0x61, 0x01, 0x00, 0x0a, 0x90, 0x04, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x61, 0x08, 0xfc, 0x30, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x31, 0x90, 0x81, 0x15, 0x02, 0x90, 0x60, 0x40, 0x51, 0x60, 0x00, 0x60, 0x40, 0x51, 0x80, 0x83, 0x03, 0x81, 0x85, 0x88, 0x88, 0xf1, 0x93, 0x50, 0x50, 0x50, 0x50, 0x15, 0x80, 0x15, 0x61, 0x0b, 0x23, 0x57, 0x3d, 0x60, 0x00, 0x80, 0x3e, 0x3d, 0x60, 0x00, 0xfd, 0x5b, 0x50, 0x60, 0x03, 0x60, 0x00, 0x60, 0x04, 0x83, 0x81, 0x54, 0x81, 0x10, 0x15, 0x15, 0x61, 0x0b, 0x37, 0x57, 0xfe, 0x5b, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x01, 0x60, 0x00, 0x90, 0x54, 0x90, 0x61, 0x01, 0x00, 0x0a, 0x90, 0x04, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x90, 0x81, 0x52, 0x60, 0x20, 0x01, 0x60, 0x00, 0x20, 0x60, 0x00, 0x01, 0x60, 0x05, 0x60, 0x00, 0x01, 0x90, 0x80, 0x54, 0x60, 0x01, 0x81, 0x60, 0x01, 0x16, 0x15, 0x61, 0x01, 0x00, 0x02, 0x03, 0x16, 0x60, 0x02, 0x90, 0x04, 0x61, 0x0b, 0xc3, 0x92, 0x91, 0x90, 0x61, 0x14, 0x4b, 0x56, 0x5b, 0x50, 0x60, 0x03, 0x60, 0x00, 0x60, 0x04, 0x83, 0x81, 0x54, 0x81, 0x10, 0x15, 0x15, 0x61, 0x0b, 0xd7, 0x57, 0xfe, 0x5b, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x01, 0x60, 0x00, 0x90, 0x54, 0x90, 0x61, 0x01, 0x00, 0x0a, 0x90, 0x04, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x90, 0x81, 0x52, 0x60, 0x20, 0x01, 0x60, 0x00, 0x20, 0x60, 0x01, 0x01, 0x54, 0x60, 0x05, 0x60, 0x01, 0x01, 0x81, 0x90, 0x55, 0x50, 0x60, 0x00, 0x60, 0x40, 0x51, 0x90, 0x80, 0x82, 0x52, 0x80, 0x60, 0x20, 0x02, 0x60, 0x20, 0x01, 0x82, 0x01, 0x60, 0x40, 0x52, 0x80, 0x15, 0x61, 0x0c, 0x79, 0x57, 0x81, 0x60, 0x20, 0x01, 0x60, 0x20, 0x82, 0x02, 0x80, 0x38, 0x83, 0x39, 0x80, 0x82, 0x01, 0x91, 0x50, 0x50, 0x90, 0x50, 0x5b, 0x50, 0x60, 0x04, 0x90, 0x80, 0x51, 0x90, 0x60, 0x20, 0x01, 0x90, 0x61, 0x0c, 0x8f, 0x92, 0x91, 0x90, 0x61, 0x14, 0xd2, 0x56, 0x5b, 0x50, 0x60, 0x00, 0x60, 0x40, 0x51, 0x90, 0x80, 0x82, 0x52, 0x80, 0x60, 0x20, 0x02, 0x60, 0x20, 0x01, 0x82, 0x01, 0x60, 0x40, 0x52, 0x80, 0x15, 0x61, 0x0c, 0xc0, 0x57, 0x81, 0x60, 0x20, 0x01, 0x60, 0x20, 0x82, 0x02, 0x80, 0x38, 0x83, 0x39, 0x80, 0x82, 0x01, 0x91, 0x50, 0x50, 0x90, 0x50, 0x5b, 0x50, 0x60, 0x02, 0x90, 0x80, 0x51, 0x90, 0x60, 0x20, 0x01, 0x90, 0x61, 0x0c, 0xd6, 0x92, 0x91, 0x90, 0x61, 0x14, 0xd2, 0x56, 0x5b, 0x50, 0x60, 0x00, 0x60, 0x08, 0x60, 0x00, 0x61, 0x01, 0x00, 0x0a, 0x81, 0x54, 0x81, 0x60, 0xff, 0x02, 0x19, 0x16, 0x90, 0x83, 0x15, 0x15, 0x02, 0x17, 0x90, 0x55, 0x50, 0x7f, 0xd6, 0xd1, 0xee, 0xba, 0x63, 0x92, 0x54, 0xbd, 0x05, 0xe3, 0x62, 0x61, 0xae, 0x29, 0x9a, 0xf2, 0x45, 0x32, 0x8a, 0xb9, 0x97, 0xfd, 0x9b, 0x78, 0x23, 0xd5, 0xff, 0xf1, 0x7f, 0x1b, 0x74, 0xa4, 0x60, 0x05, 0x60, 0x00, 0x01, 0x60, 0x05, 0x60, 0x01, 0x01, 0x54, 0x60, 0x40, 0x51, 0x80, 0x80, 0x60, 0x20, 0x01, 0x83, 0x81, 0x52, 0x60, 0x20, 0x01, 0x82, 0x81, 0x03, 0x82, 0x52, 0x84, 0x81, 0x81, 0x54, 0x60, 0x01, 0x81, 0x60, 0x01, 0x16, 0x15, 0x61, 0x01, 0x00, 0x02, 0x03, 0x16, 0x60, 0x02, 0x90, 0x04, 0x81, 0x52, 0x60, 0x20, 0x01, 0x91, 0x50, 0x80, 0x54, 0x60, 0x01, 0x81, 0x60, 0x01, 0x16, 0x15, 0x61, 0x01, 0x00, 0x02, 0x03, 0x16, 0x60, 0x02, 0x90, 0x04, 0x80, 0x15, 0x61, 0x0d, 0xad, 0x57, 0x80, 0x60, 0x1f, 0x10, 0x61, 0x0d, 0x82, 0x57, 0x61, 0x01, 0x00, 0x80, 0x83, 0x54, 0x04, 0x02, 0x83, 0x52, 0x91, 0x60, 0x20, 0x01, 0x91, 0x61, 0x0d, 0xad, 0x56, 0x5b, 0x82, 0x01, 0x91, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x90, 0x5b, 0x81, 0x54, 0x81, 0x52, 0x90, 0x60, 0x01, 0x01, 0x90, 0x60, 0x20, 0x01, 0x80, 0x83, 0x11, 0x61, 0x0d, 0x90, 0x57, 0x82, 0x90, 0x03, 0x60, 0x1f, 0x16, 0x82, 0x01, 0x91, 0x5b, 0x50, 0x50, 0x93, 0x50, 0x50, 0x50, 0x50, 0x60, 0x40, 0x51, 0x80, 0x91, 0x03, 0x90, 0xa1, 0x50, 0x56, 0x5b, 0x60, 0x00, 0x80, 0x54, 0x60, 0x01, 0x81, 0x60, 0x01, 0x16, 0x15, 0x61, 0x01, 0x00, 0x02, 0x03, 0x16, 0x60, 0x02, 0x90, 0x04, 0x80, 0x60, 0x1f, 0x01, 0x60, 0x20, 0x80, 0x91, 0x04, 0x02, 0x60, 0x20, 0x01, 0x60, 0x40, 0x51, 0x90, 0x81, 0x01, 0x60, 0x40, 0x52, 0x80, 0x92, 0x91, 0x90, 0x81, 0x81, 0x52, 0x60, 0x20, 0x01, 0x82, 0x80, 0x54, 0x60, 0x01, 0x81, 0x60, 0x01, 0x16, 0x15, 0x61, 0x01, 0x00, 0x02, 0x03, 0x16, 0x60, 0x02, 0x90, 0x04, 0x80, 0x15, 0x61, 0x0e, 0x55, 0x57, 0x80, 0x60, 0x1f, 0x10, 0x61, 0x0e, 0x2a, 0x57, 0x61, 0x01, 0x00, 0x80, 0x83, 0x54, 0x04, 0x02, 0x83, 0x52, 0x91, 0x60, 0x20, 0x01, 0x91, 0x61, 0x0e, 0x55, 0x56, 0x5b, 0x82, 0x01, 0x91, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x90, 0x5b, 0x81, 0x54, 0x81, 0x52, 0x90, 0x60, 0x01, 0x01, 0x90, 0x60, 0x20, 0x01, 0x80, 0x83, 0x11, 0x61, 0x0e, 0x38, 0x57, 0x82, 0x90, 0x03, 0x60, 0x1f, 0x16, 0x82, 0x01, 0x91, 0x5b, 0x50, 0x50, 0x50, 0x50, 0x50, 0x81, 0x56, 0x5b, 0x60, 0x01, 0x60, 0x00, 0x90, 0x54, 0x90, 0x61, 0x01, 0x00, 0x0a, 0x90, 0x04, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x56, 0x5b, 0x60, 0x02, 0x81, 0x81, 0x54, 0x81, 0x10, 0x15, 0x15, 0x61, 0x0e, 0x92, 0x57, 0xfe, 0x5b, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x01, 0x60, 0x00, 0x91, 0x50, 0x54, 0x90, 0x61, 0x01, 0x00, 0x0a, 0x90, 0x04, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x56, 0x5b, 0x60, 0x60, 0x60, 0x00, 0x61, 0x0e, 0xce, 0x83, 0x61, 0x12, 0x6e, 0x56, 0x5b, 0x15, 0x61, 0x0e, 0xf3, 0x57, 0x60, 0x00, 0x60, 0x20, 0x60, 0x40, 0x51, 0x90, 0x81, 0x01, 0x60, 0x40, 0x52, 0x80, 0x60, 0x00, 0x81, 0x52, 0x50, 0x90, 0x80, 0x90, 0x50, 0x91, 0x50, 0x91, 0x50, 0x61, 0x10, 0x19, 0x56, 0x5b, 0x60, 0x03, 0x60, 0x00, 0x84, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x90, 0x81, 0x52, 0x60, 0x20, 0x01, 0x60, 0x00, 0x20, 0x60, 0x00, 0x01, 0x60, 0x03, 0x60, 0x00, 0x85, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x90, 0x81, 0x52, 0x60, 0x20, 0x01, 0x60, 0x00, 0x20, 0x60, 0x01, 0x01, 0x54, 0x81, 0x80, 0x54, 0x60, 0x01, 0x81, 0x60, 0x01, 0x16, 0x15, 0x61, 0x01, 0x00, 0x02, 0x03, 0x16, 0x60, 0x02, 0x90, 0x04, 0x80, 0x60, 0x1f, 0x01, 0x60, 0x20, 0x80, 0x91, 0x04, 0x02, 0x60, 0x20, 0x01, 0x60, 0x40, 0x51, 0x90, 0x81, 0x01, 0x60, 0x40, 0x52, 0x80, 0x92, 0x91, 0x90, 0x81, 0x81, 0x52, 0x60, 0x20, 0x01, 0x82, 0x80, 0x54, 0x60, 0x01, 0x81, 0x60, 0x01, 0x16, 0x15, 0x61, 0x01, 0x00, 0x02, 0x03, 0x16, 0x60, 0x02, 0x90, 0x04, 0x80, 0x15, 0x61, 0x10, 0x0d, 0x57, 0x80, 0x60, 0x1f, 0x10, 0x61, 0x0f, 0xe2, 0x57, 0x61, 0x01, 0x00, 0x80, 0x83, 0x54, 0x04, 0x02, 0x83, 0x52, 0x91, 0x60, 0x20, 0x01, 0x91, 0x61, 0x10, 0x0d, 0x56, 0x5b, 0x82, 0x01, 0x91, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x90, 0x5b, 0x81, 0x54, 0x81, 0x52, 0x90, 0x60, 0x01, 0x01, 0x90, 0x60, 0x20, 0x01, 0x80, 0x83, 0x11, 0x61, 0x0f, 0xf0, 0x57, 0x82, 0x90, 0x03, 0x60, 0x1f, 0x16, 0x82, 0x01, 0x91, 0x5b, 0x50, 0x50, 0x50, 0x50, 0x50, 0x91, 0x50, 0x91, 0x50, 0x91, 0x50, 0x5b, 0x91, 0x50, 0x91, 0x56, 0x5b, 0x60, 0x0a, 0x54, 0x81, 0x56, 0x5b, 0x60, 0x09, 0x54, 0x81, 0x56, 0x5b, 0x60, 0x60, 0x60, 0x02, 0x80, 0x54, 0x80, 0x60, 0x20, 0x02, 0x60, 0x20, 0x01, 0x60, 0x40, 0x51, 0x90, 0x81, 0x01, 0x60, 0x40, 0x52, 0x80, 0x92, 0x91, 0x90, 0x81, 0x81, 0x52, 0x60, 0x20, 0x01, 0x82, 0x80, 0x54, 0x80, 0x15, 0x61, 0x10, 0xae, 0x57, 0x60, 0x20, 0x02, 0x82, 0x01, 0x91, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x90, 0x5b, 0x81, 0x60, 0x00, 0x90, 0x54, 0x90, 0x61, 0x01, 0x00, 0x0a, 0x90, 0x04, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x90, 0x60, 0x01, 0x01, 0x90, 0x80, 0x83, 0x11, 0x61, 0x10, 0x64, 0x57, 0x5b, 0x50, 0x50, 0x50, 0x50, 0x50, 0x90, 0x50, 0x90, 0x56, 0x5b, 0x60, 0x01, 0x60, 0x00, 0x90, 0x54, 0x90, 0x61, 0x01, 0x00, 0x0a, 0x90, 0x04, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x33, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x14, 0x15, 0x15, 0x61, 0x11, 0x14, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x60, 0x01, 0x60, 0x08, 0x60, 0x00, 0x61, 0x01, 0x00, 0x0a, 0x81, 0x54, 0x81, 0x60, 0xff, 0x02, 0x19, 0x16, 0x90, 0x83, 0x15, 0x15, 0x02, 0x17, 0x90, 0x55, 0x50, 0x60, 0x00, 0x82, 0x14, 0x61, 0x11, 0x3d, 0x57, 0x81, 0x61, 0x11, 0x40, 0x56, 0x5b, 0x60, 0x01, 0x5b, 0x60, 0x09, 0x81, 0x90, 0x55, 0x50, 0x60, 0x00, 0x81, 0x14, 0x61, 0x11, 0x54, 0x57, 0x80, 0x61, 0x11, 0x57, 0x56, 0x5b, 0x60, 0x01, 0x5b, 0x60, 0x0a, 0x81, 0x90, 0x55, 0x50, 0x50, 0x50, 0x56, 0x5b, 0x60, 0x00, 0x30, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x31, 0x90, 0x50, 0x90, 0x56, 0x5b, 0x60, 0x05, 0x80, 0x60, 0x00, 0x01, 0x80, 0x54, 0x60, 0x01, 0x81, 0x60, 0x01, 0x16, 0x15, 0x61, 0x01, 0x00, 0x02, 0x03, 0x16, 0x60, 0x02, 0x90, 0x04, 0x80, 0x60, 0x1f, 0x01, 0x60, 0x20, 0x80, 0x91, 0x04, 0x02, 0x60, 0x20, 0x01, 0x60, 0x40, 0x51, 0x90, 0x81, 0x01, 0x60, 0x40, 0x52, 0x80, 0x92, 0x91, 0x90, 0x81, 0x81, 0x52, 0x60, 0x20, 0x01, 0x82, 0x80, 0x54, 0x60, 0x01, 0x81, 0x60, 0x01, 0x16, 0x15, 0x61, 0x01, 0x00, 0x02, 0x03, 0x16, 0x60, 0x02, 0x90, 0x04, 0x80, 0x15, 0x61, 0x12, 0x1a, 0x57, 0x80, 0x60, 0x1f, 0x10, 0x61, 0x11, 0xef, 0x57, 0x61, 0x01, 0x00, 0x80, 0x83, 0x54, 0x04, 0x02, 0x83, 0x52, 0x91, 0x60, 0x20, 0x01, 0x91, 0x61, 0x12, 0x1a, 0x56, 0x5b, 0x82, 0x01, 0x91, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x90, 0x5b, 0x81, 0x54, 0x81, 0x52, 0x90, 0x60, 0x01, 0x01, 0x90, 0x60, 0x20, 0x01, 0x80, 0x83, 0x11, 0x61, 0x11, 0xfd, 0x57, 0x82, 0x90, 0x03, 0x60, 0x1f, 0x16, 0x82, 0x01, 0x91, 0x5b, 0x50, 0x50, 0x50, 0x50, 0x50, 0x90, 0x80, 0x60, 0x01, 0x01, 0x54, 0x90, 0x80, 0x60, 0x02, 0x01, 0x54, 0x90, 0x50, 0x83, 0x56, 0x5b, 0x60, 0x04, 0x81, 0x81, 0x54, 0x81, 0x10, 0x15, 0x15, 0x61, 0x12, 0x3f, 0x57, 0xfe, 0x5b, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x01, 0x60, 0x00, 0x91, 0x50, 0x54, 0x90, 0x61, 0x01, 0x00, 0x0a, 0x90, 0x04, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x56, 0x5b, 0x60, 0x00, 0x80, 0x60, 0x02, 0x80, 0x54, 0x90, 0x50, 0x14, 0x15, 0x61, 0x12, 0x86, 0x57, 0x60, 0x01, 0x90, 0x50, 0x61, 0x13, 0x34, 0x56, 0x5b, 0x81, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x60, 0x02, 0x60, 0x03, 0x60, 0x00, 0x85, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x90, 0x81, 0x52, 0x60, 0x20, 0x01, 0x60, 0x00, 0x20, 0x60, 0x02, 0x01, 0x54, 0x81, 0x54, 0x81, 0x10, 0x15, 0x15, 0x61, 0x12, 0xee, 0x57, 0xfe, 0x5b, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x01, 0x60, 0x00, 0x90, 0x54, 0x90, 0x61, 0x01, 0x00, 0x0a, 0x90, 0x04, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x14, 0x15, 0x90, 0x50, 0x5b, 0x91, 0x90, 0x50, 0x56, 0x5b, 0x60, 0x00, 0x44, 0x42, 0x60, 0x04, 0x60, 0x40, 0x51, 0x80, 0x84, 0x81, 0x52, 0x60, 0x20, 0x01, 0x83, 0x81, 0x52, 0x60, 0x20, 0x01, 0x82, 0x80, 0x54, 0x80, 0x15, 0x61, 0x13, 0xb3, 0x57, 0x60, 0x20, 0x02, 0x82, 0x01, 0x91, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x90, 0x5b, 0x81, 0x60, 0x00, 0x90, 0x54, 0x90, 0x61, 0x01, 0x00, 0x0a, 0x90, 0x04, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x90, 0x60, 0x01, 0x01, 0x90, 0x80, 0x83, 0x11, 0x61, 0x13, 0x69, 0x57, 0x5b, 0x50, 0x50, 0x93, 0x50, 0x50, 0x50, 0x50, 0x60, 0x40, 0x51, 0x80, 0x91, 0x03, 0x90, 0x20, 0x60, 0x01, 0x90, 0x04, 0x90, 0x50, 0x90, 0x56, 0x5b, 0x82, 0x80, 0x54, 0x60, 0x01, 0x81, 0x60, 0x01, 0x16, 0x15, 0x61, 0x01, 0x00, 0x02, 0x03, 0x16, 0x60, 0x02, 0x90, 0x04, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x90, 0x60, 0x1f, 0x01, 0x60, 0x20, 0x90, 0x04, 0x81, 0x01, 0x92, 0x82, 0x60, 0x1f, 0x10, 0x61, 0x14, 0x0c, 0x57, 0x80, 0x51, 0x60, 0xff, 0x19, 0x16, 0x83, 0x80, 0x01, 0x17, 0x85, 0x55, 0x61, 0x14, 0x3a, 0x56, 0x5b, 0x82, 0x80, 0x01, 0x60, 0x01, 0x01, 0x85, 0x55, 0x82, 0x15, 0x61, 0x14, 0x3a, 0x57, 0x91, 0x82, 0x01, 0x5b, 0x82, 0x81, 0x11, 0x15, 0x61, 0x14, 0x39, 0x57, 0x82, 0x51, 0x82, 0x55, 0x91, 0x60, 0x20, 0x01, 0x91, 0x90, 0x60, 0x01, 0x01, 0x90, 0x61, 0x14, 0x1e, 0x56, 0x5b, 0x5b, 0x50, 0x90, 0x50, 0x61, 0x14, 0x47, 0x91, 0x90, 0x61, 0x15, 0x5c, 0x56, 0x5b, 0x50, 0x90, 0x56, 0x5b, 0x82, 0x80, 0x54, 0x60, 0x01, 0x81, 0x60, 0x01, 0x16, 0x15, 0x61, 0x01, 0x00, 0x02, 0x03, 0x16, 0x60, 0x02, 0x90, 0x04, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x90, 0x60, 0x1f, 0x01, 0x60, 0x20, 0x90, 0x04, 0x81, 0x01, 0x92, 0x82, 0x60, 0x1f, 0x10, 0x61, 0x14, 0x84, 0x57, 0x80, 0x54, 0x85, 0x55, 0x61, 0x14, 0xc1, 0x56, 0x5b, 0x82, 0x80, 0x01, 0x60, 0x01, 0x01, 0x85, 0x55, 0x82, 0x15, 0x61, 0x14, 0xc1, 0x57, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x91, 0x60, 0x1f, 0x01, 0x60, 0x20, 0x90, 0x04, 0x82, 0x01, 0x5b, 0x82, 0x81, 0x11, 0x15, 0x61, 0x14, 0xc0, 0x57, 0x82, 0x54, 0x82, 0x55, 0x91, 0x60, 0x01, 0x01, 0x91, 0x90, 0x60, 0x01, 0x01, 0x90, 0x61, 0x14, 0xa5, 0x56, 0x5b, 0x5b, 0x50, 0x90, 0x50, 0x61, 0x14, 0xce, 0x91, 0x90, 0x61, 0x15, 0x5c, 0x56, 0x5b, 0x50, 0x90, 0x56, 0x5b, 0x82, 0x80, 0x54, 0x82, 0x82, 0x55, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x90, 0x81, 0x01, 0x92, 0x82, 0x15, 0x61, 0x15, 0x4b, 0x57, 0x91, 0x60, 0x20, 0x02, 0x82, 0x01, 0x5b, 0x82, 0x81, 0x11, 0x15, 0x61, 0x15, 0x4a, 0x57, 0x82, 0x51, 0x82, 0x60, 0x00, 0x61, 0x01, 0x00, 0x0a, 0x81, 0x54, 0x81, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0x19, 0x16, 0x90, 0x83, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x02, 0x17, 0x90, 0x55, 0x50, 0x91, 0x60, 0x20, 0x01, 0x91, 0x90, 0x60, 0x01, 0x01, 0x90, 0x61, 0x14, 0xf2, 0x56, 0x5b, 0x5b, 0x50, 0x90, 0x50, 0x61, 0x15, 0x58, 0x91, 0x90, 0x61, 0x15, 0x81, 0x56, 0x5b, 0x50, 0x90, 0x56, 0x5b, 0x61, 0x15, 0x7e, 0x91, 0x90, 0x5b, 0x80, 0x82, 0x11, 0x15, 0x61, 0x15, 0x7a, 0x57, 0x60, 0x00, 0x81, 0x60, 0x00, 0x90, 0x55, 0x50, 0x60, 0x01, 0x01, 0x61, 0x15, 0x62, 0x56, 0x5b, 0x50, 0x90, 0x56, 0x5b, 0x90, 0x56, 0x5b, 0x61, 0x15, 0xc1, 0x91, 0x90, 0x5b, 0x80, 0x82, 0x11, 0x15, 0x61, 0x15, 0xbd, 0x57, 0x60, 0x00, 0x81, 0x81, 0x61, 0x01, 0x00, 0x0a, 0x81, 0x54, 0x90, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0x19, 0x16, 0x90, 0x55, 0x50, 0x60, 0x01, 0x01, 0x61, 0x15, 0x87, 0x56, 0x5b, 0x50, 0x90, 0x56, 0x5b, 0x90, 0x56, 0x00, 0xa1, 0x65, 0x62, 0x7a, 0x7a, 0x72, 0x30, 0x58, 0x20, 0xa8, 0xfb, 0x9f, 0x06, 0x53, 0x3d, 0xb9, 0x44, 0x22, 0x03, 0x33, 0x2b, 0xcb, 0x5c, 0x2e, 0xdf, 0x68, 0xb6, 0x99, 0xd5, 0x4b, 0x7d, 0xb0, 0xbe, 0x9b, 0x1c, 0xa7, 0x85, 0x28, 0x47, 0x5c, 0x18, 0x00, 0x29}; + // machine::context ctx = {true, 0x00}; + // machine::message msg = {}; + // machine::chain_adapter adapter = make_chain_adapter(); + // machine::machine m(ctx, input, msg, adapter); + // assert_message( "machine should start running", m.get_state() == machine::machine_state::running ); + + // std::string line; + // while (m.is_running()) + // { + // m.step(); + // while ( std::getline(m.get_logger(), line) ) + // std::cerr << "\e[36m" << "LOG: " << line << "\e[0m" << std::endl; + // std::cout << m.to_json() << std::endl; + // } + // while ( std::getline(m.get_logger(), line) ) + // std::cerr << "\e[36m" << "LOG: " << line << "\e[0m" << std::endl; + // std::cout << m.to_json() << std::endl; + + // assert_message( "machine should stop when done executing", m.get_state() == machine::machine_state::stopped ); + // assert_message( "stack has correct length", m.stack_length() == 0 ); + //} return 0; } From 5d32c2b1cbb0324c87b29ac8af14e08939d22d91 Mon Sep 17 00:00:00 2001 From: Roger Jungemann Date: Mon, 15 Nov 2021 12:44:20 -0800 Subject: [PATCH 74/96] Add bytecode examples --- libraries/vendor/xgtvm/lottery.bytecode | 1 + libraries/vendor/xgtvm/lottery.json | 1 + libraries/vendor/xgtvm/lottery2.bytecode | 1 + libraries/vendor/xgtvm/lottery2.json | 1 + 4 files changed, 4 insertions(+) create mode 100644 libraries/vendor/xgtvm/lottery.bytecode create mode 100644 libraries/vendor/xgtvm/lottery.json create mode 100644 libraries/vendor/xgtvm/lottery2.bytecode create mode 100644 libraries/vendor/xgtvm/lottery2.json diff --git a/libraries/vendor/xgtvm/lottery.bytecode b/libraries/vendor/xgtvm/lottery.bytecode new file mode 100644 index 00000000..991ce37f --- /dev/null +++ b/libraries/vendor/xgtvm/lottery.bytecode @@ -0,0 +1 @@ +608060405234801561001057600080fd5b50336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550610680806100606000396000f30060806040526004361061006d576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063481c6a75146100725780635d495aea146100c95780638b5b9ccc146100e0578063e97dcb621461014c578063f71d96cb14610156575b600080fd5b34801561007e57600080fd5b506100876101c3565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156100d557600080fd5b506100de6101e8565b005b3480156100ec57600080fd5b506100f5610340565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561013857808201518184015260208101905061011d565b505050509050019250505060405180910390f35b6101546103ce565b005b34801561016257600080fd5b506101816004803603810190808035906020019092919050505061044b565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561024557600080fd5b600180549050610253610489565b81151561025c57fe5b06905060018181548110151561026e57fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc3073ffffffffffffffffffffffffffffffffffffffff16319081150290604051600060405180830381858888f193505050501580156102f5573d6000803e3d6000fd5b5060006040519080825280602002602001820160405280156103265781602001602082028038833980820191505090505b506001908051906020019061033c929190610587565b5050565b606060018054806020026020016040519081016040528092919081815260200182805480156103c457602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001906001019080831161037a575b5050505050905090565b662386f26fc10000341115156103e357600080fd5b60013390806001815401808255809150509060018203906000526020600020016000909192909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60018181548110151561045a57fe5b906000526020600020016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60004442600160405160200180848152602001838152602001828054801561050657602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190600101908083116104bc575b505093505050506040516020818303038152906040526040518082805190602001908083835b602083101515610551578051825260208201915060208101905060208303925061052c565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902060019004905090565b828054828255906000526020600020908101928215610600579160200282015b828111156105ff5782518260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550916020019190600101906105a7565b5b50905061060d9190610611565b5090565b61065191905b8082111561064d57600081816101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905550600101610617565b5090565b905600a165627a7a72305820919b1f329afa6406ac32ccc812f65d08dcb29f0c1b9fb63cf34e5abfdef8da070029 diff --git a/libraries/vendor/xgtvm/lottery.json b/libraries/vendor/xgtvm/lottery.json new file mode 100644 index 00000000..d2d88c9c --- /dev/null +++ b/libraries/vendor/xgtvm/lottery.json @@ -0,0 +1 @@ +[0x60, 0x80, 0x60, 0x40, 0x52, 0x34, 0x80, 0x15, 0x61, 0x00, 0x10, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x33, 0x60, 0x00, 0x80, 0x61, 0x01, 0x00, 0x0a, 0x81, 0x54, 0x81, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0x19, 0x16, 0x90, 0x83, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x02, 0x17, 0x90, 0x55, 0x50, 0x61, 0x06, 0x80, 0x80, 0x61, 0x00, 0x60, 0x60, 0x00, 0x39, 0x60, 0x00, 0xf3, 0x00, 0x60, 0x80, 0x60, 0x40, 0x52, 0x60, 0x04, 0x36, 0x10, 0x61, 0x00, 0x6d, 0x57, 0x60, 0x00, 0x35, 0x7c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x04, 0x63, 0xff, 0xff, 0xff, 0xff, 0x16, 0x80, 0x63, 0x48, 0x1c, 0x6a, 0x75, 0x14, 0x61, 0x00, 0x72, 0x57, 0x80, 0x63, 0x5d, 0x49, 0x5a, 0xea, 0x14, 0x61, 0x00, 0xc9, 0x57, 0x80, 0x63, 0x8b, 0x5b, 0x9c, 0xcc, 0x14, 0x61, 0x00, 0xe0, 0x57, 0x80, 0x63, 0xe9, 0x7d, 0xcb, 0x62, 0x14, 0x61, 0x01, 0x4c, 0x57, 0x80, 0x63, 0xf7, 0x1d, 0x96, 0xcb, 0x14, 0x61, 0x01, 0x56, 0x57, 0x5b, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x34, 0x80, 0x15, 0x61, 0x00, 0x7e, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x61, 0x00, 0x87, 0x61, 0x01, 0xc3, 0x56, 0x5b, 0x60, 0x40, 0x51, 0x80, 0x82, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x91, 0x50, 0x50, 0x60, 0x40, 0x51, 0x80, 0x91, 0x03, 0x90, 0xf3, 0x5b, 0x34, 0x80, 0x15, 0x61, 0x00, 0xd5, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x61, 0x00, 0xde, 0x61, 0x01, 0xe8, 0x56, 0x5b, 0x00, 0x5b, 0x34, 0x80, 0x15, 0x61, 0x00, 0xec, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x61, 0x00, 0xf5, 0x61, 0x03, 0x40, 0x56, 0x5b, 0x60, 0x40, 0x51, 0x80, 0x80, 0x60, 0x20, 0x01, 0x82, 0x81, 0x03, 0x82, 0x52, 0x83, 0x81, 0x81, 0x51, 0x81, 0x52, 0x60, 0x20, 0x01, 0x91, 0x50, 0x80, 0x51, 0x90, 0x60, 0x20, 0x01, 0x90, 0x60, 0x20, 0x02, 0x80, 0x83, 0x83, 0x60, 0x00, 0x5b, 0x83, 0x81, 0x10, 0x15, 0x61, 0x01, 0x38, 0x57, 0x80, 0x82, 0x01, 0x51, 0x81, 0x84, 0x01, 0x52, 0x60, 0x20, 0x81, 0x01, 0x90, 0x50, 0x61, 0x01, 0x1d, 0x56, 0x5b, 0x50, 0x50, 0x50, 0x50, 0x90, 0x50, 0x01, 0x92, 0x50, 0x50, 0x50, 0x60, 0x40, 0x51, 0x80, 0x91, 0x03, 0x90, 0xf3, 0x5b, 0x61, 0x01, 0x54, 0x61, 0x03, 0xce, 0x56, 0x5b, 0x00, 0x5b, 0x34, 0x80, 0x15, 0x61, 0x01, 0x62, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x61, 0x01, 0x81, 0x60, 0x04, 0x80, 0x36, 0x03, 0x81, 0x01, 0x90, 0x80, 0x80, 0x35, 0x90, 0x60, 0x20, 0x01, 0x90, 0x92, 0x91, 0x90, 0x50, 0x50, 0x50, 0x61, 0x04, 0x4b, 0x56, 0x5b, 0x60, 0x40, 0x51, 0x80, 0x82, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x91, 0x50, 0x50, 0x60, 0x40, 0x51, 0x80, 0x91, 0x03, 0x90, 0xf3, 0x5b, 0x60, 0x00, 0x80, 0x90, 0x54, 0x90, 0x61, 0x01, 0x00, 0x0a, 0x90, 0x04, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x56, 0x5b, 0x60, 0x00, 0x80, 0x60, 0x00, 0x90, 0x54, 0x90, 0x61, 0x01, 0x00, 0x0a, 0x90, 0x04, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x33, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x14, 0x15, 0x15, 0x61, 0x02, 0x45, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x60, 0x01, 0x80, 0x54, 0x90, 0x50, 0x61, 0x02, 0x53, 0x61, 0x04, 0x89, 0x56, 0x5b, 0x81, 0x15, 0x15, 0x61, 0x02, 0x5c, 0x57, 0xfe, 0x5b, 0x06, 0x90, 0x50, 0x60, 0x01, 0x81, 0x81, 0x54, 0x81, 0x10, 0x15, 0x15, 0x61, 0x02, 0x6e, 0x57, 0xfe, 0x5b, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x01, 0x60, 0x00, 0x90, 0x54, 0x90, 0x61, 0x01, 0x00, 0x0a, 0x90, 0x04, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x61, 0x08, 0xfc, 0x30, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x31, 0x90, 0x81, 0x15, 0x02, 0x90, 0x60, 0x40, 0x51, 0x60, 0x00, 0x60, 0x40, 0x51, 0x80, 0x83, 0x03, 0x81, 0x85, 0x88, 0x88, 0xf1, 0x93, 0x50, 0x50, 0x50, 0x50, 0x15, 0x80, 0x15, 0x61, 0x02, 0xf5, 0x57, 0x3d, 0x60, 0x00, 0x80, 0x3e, 0x3d, 0x60, 0x00, 0xfd, 0x5b, 0x50, 0x60, 0x00, 0x60, 0x40, 0x51, 0x90, 0x80, 0x82, 0x52, 0x80, 0x60, 0x20, 0x02, 0x60, 0x20, 0x01, 0x82, 0x01, 0x60, 0x40, 0x52, 0x80, 0x15, 0x61, 0x03, 0x26, 0x57, 0x81, 0x60, 0x20, 0x01, 0x60, 0x20, 0x82, 0x02, 0x80, 0x38, 0x83, 0x39, 0x80, 0x82, 0x01, 0x91, 0x50, 0x50, 0x90, 0x50, 0x5b, 0x50, 0x60, 0x01, 0x90, 0x80, 0x51, 0x90, 0x60, 0x20, 0x01, 0x90, 0x61, 0x03, 0x3c, 0x92, 0x91, 0x90, 0x61, 0x05, 0x87, 0x56, 0x5b, 0x50, 0x50, 0x56, 0x5b, 0x60, 0x60, 0x60, 0x01, 0x80, 0x54, 0x80, 0x60, 0x20, 0x02, 0x60, 0x20, 0x01, 0x60, 0x40, 0x51, 0x90, 0x81, 0x01, 0x60, 0x40, 0x52, 0x80, 0x92, 0x91, 0x90, 0x81, 0x81, 0x52, 0x60, 0x20, 0x01, 0x82, 0x80, 0x54, 0x80, 0x15, 0x61, 0x03, 0xc4, 0x57, 0x60, 0x20, 0x02, 0x82, 0x01, 0x91, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x90, 0x5b, 0x81, 0x60, 0x00, 0x90, 0x54, 0x90, 0x61, 0x01, 0x00, 0x0a, 0x90, 0x04, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x90, 0x60, 0x01, 0x01, 0x90, 0x80, 0x83, 0x11, 0x61, 0x03, 0x7a, 0x57, 0x5b, 0x50, 0x50, 0x50, 0x50, 0x50, 0x90, 0x50, 0x90, 0x56, 0x5b, 0x66, 0x23, 0x86, 0xf2, 0x6f, 0xc1, 0x00, 0x00, 0x34, 0x11, 0x15, 0x15, 0x61, 0x03, 0xe3, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x60, 0x01, 0x33, 0x90, 0x80, 0x60, 0x01, 0x81, 0x54, 0x01, 0x80, 0x82, 0x55, 0x80, 0x91, 0x50, 0x50, 0x90, 0x60, 0x01, 0x82, 0x03, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x01, 0x60, 0x00, 0x90, 0x91, 0x92, 0x90, 0x91, 0x90, 0x91, 0x61, 0x01, 0x00, 0x0a, 0x81, 0x54, 0x81, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0x19, 0x16, 0x90, 0x83, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x02, 0x17, 0x90, 0x55, 0x50, 0x50, 0x56, 0x5b, 0x60, 0x01, 0x81, 0x81, 0x54, 0x81, 0x10, 0x15, 0x15, 0x61, 0x04, 0x5a, 0x57, 0xfe, 0x5b, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x01, 0x60, 0x00, 0x91, 0x50, 0x54, 0x90, 0x61, 0x01, 0x00, 0x0a, 0x90, 0x04, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x56, 0x5b, 0x60, 0x00, 0x44, 0x42, 0x60, 0x01, 0x60, 0x40, 0x51, 0x60, 0x20, 0x01, 0x80, 0x84, 0x81, 0x52, 0x60, 0x20, 0x01, 0x83, 0x81, 0x52, 0x60, 0x20, 0x01, 0x82, 0x80, 0x54, 0x80, 0x15, 0x61, 0x05, 0x06, 0x57, 0x60, 0x20, 0x02, 0x82, 0x01, 0x91, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x90, 0x5b, 0x81, 0x60, 0x00, 0x90, 0x54, 0x90, 0x61, 0x01, 0x00, 0x0a, 0x90, 0x04, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x90, 0x60, 0x01, 0x01, 0x90, 0x80, 0x83, 0x11, 0x61, 0x04, 0xbc, 0x57, 0x5b, 0x50, 0x50, 0x93, 0x50, 0x50, 0x50, 0x50, 0x60, 0x40, 0x51, 0x60, 0x20, 0x81, 0x83, 0x03, 0x03, 0x81, 0x52, 0x90, 0x60, 0x40, 0x52, 0x60, 0x40, 0x51, 0x80, 0x82, 0x80, 0x51, 0x90, 0x60, 0x20, 0x01, 0x90, 0x80, 0x83, 0x83, 0x5b, 0x60, 0x20, 0x83, 0x10, 0x15, 0x15, 0x61, 0x05, 0x51, 0x57, 0x80, 0x51, 0x82, 0x52, 0x60, 0x20, 0x82, 0x01, 0x91, 0x50, 0x60, 0x20, 0x81, 0x01, 0x90, 0x50, 0x60, 0x20, 0x83, 0x03, 0x92, 0x50, 0x61, 0x05, 0x2c, 0x56, 0x5b, 0x60, 0x01, 0x83, 0x60, 0x20, 0x03, 0x61, 0x01, 0x00, 0x0a, 0x03, 0x80, 0x19, 0x82, 0x51, 0x16, 0x81, 0x84, 0x51, 0x16, 0x80, 0x82, 0x17, 0x85, 0x52, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x90, 0x50, 0x01, 0x91, 0x50, 0x50, 0x60, 0x40, 0x51, 0x80, 0x91, 0x03, 0x90, 0x20, 0x60, 0x01, 0x90, 0x04, 0x90, 0x50, 0x90, 0x56, 0x5b, 0x82, 0x80, 0x54, 0x82, 0x82, 0x55, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x90, 0x81, 0x01, 0x92, 0x82, 0x15, 0x61, 0x06, 0x00, 0x57, 0x91, 0x60, 0x20, 0x02, 0x82, 0x01, 0x5b, 0x82, 0x81, 0x11, 0x15, 0x61, 0x05, 0xff, 0x57, 0x82, 0x51, 0x82, 0x60, 0x00, 0x61, 0x01, 0x00, 0x0a, 0x81, 0x54, 0x81, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0x19, 0x16, 0x90, 0x83, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x02, 0x17, 0x90, 0x55, 0x50, 0x91, 0x60, 0x20, 0x01, 0x91, 0x90, 0x60, 0x01, 0x01, 0x90, 0x61, 0x05, 0xa7, 0x56, 0x5b, 0x5b, 0x50, 0x90, 0x50, 0x61, 0x06, 0x0d, 0x91, 0x90, 0x61, 0x06, 0x11, 0x56, 0x5b, 0x50, 0x90, 0x56, 0x5b, 0x61, 0x06, 0x51, 0x91, 0x90, 0x5b, 0x80, 0x82, 0x11, 0x15, 0x61, 0x06, 0x4d, 0x57, 0x60, 0x00, 0x81, 0x81, 0x61, 0x01, 0x00, 0x0a, 0x81, 0x54, 0x90, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0x19, 0x16, 0x90, 0x55, 0x50, 0x60, 0x01, 0x01, 0x61, 0x06, 0x17, 0x56, 0x5b, 0x50, 0x90, 0x56, 0x5b, 0x90, 0x56, 0x00, 0xa1, 0x65, 0x62, 0x7a, 0x7a, 0x72, 0x30, 0x58, 0x20, 0x91, 0x9b, 0x1f, 0x32, 0x9a, 0xfa, 0x64, 0x06, 0xac, 0x32, 0xcc, 0xc8, 0x12, 0xf6, 0x5d, 0x08, 0xdc, 0xb2, 0x9f, 0x0c, 0x1b, 0x9f, 0xb6, 0x3c, 0xf3, 0x4e, 0x5a, 0xbf, 0xde, 0xf8, 0xda, 0x07, 0x00, 0x29] diff --git a/libraries/vendor/xgtvm/lottery2.bytecode b/libraries/vendor/xgtvm/lottery2.bytecode new file mode 100644 index 00000000..3b0030f8 --- /dev/null +++ b/libraries/vendor/xgtvm/lottery2.bytecode @@ -0,0 +1 @@ +60806040523480156200001157600080fd5b506040516200175438038062001754833981018060405281019080805182019291906020018051906020019092919050505080600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555081600090805190602001906200009c929190620000a5565b50505062000154565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620000e857805160ff191683800117855562000119565b8280016001018555821562000119579182015b8281111562000118578251825591602001919060010190620000fb565b5b5090506200012891906200012c565b5090565b6200015191905b808211156200014d57600081600090555060010162000133565b5090565b90565b6115f080620001646000396000f3006080604052600436106100d0576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806310c85fe51461011057806314034bd21461013f5780631d27769f1461015657806323d14149146101b2578063481c6a75146102425780635832d571146102995780635c12cd4b146103065780635d58a74a146103c95780637752045b146103f45780638b5b9ccc1461041f578063bdaea3261461048b578063d68895d8146104c2578063dfbf53ae146104ed578063f25266dd1461058b575b61010e6040805190810160405280600781526020017f556e6b6e6f776e000000000000000000000000000000000000000000000000008152506105f8565b005b34801561011c57600080fd5b506101256109ee565b604051808215151515815260200191505060405180910390f35b34801561014b57600080fd5b50610154610a01565b005b6101b0600480360381019080803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091929192905050506105f8565b005b3480156101be57600080fd5b506101c7610dbf565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156102075780820151818401526020810190506101ec565b50505050905090810190601f1680156102345780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561024e57600080fd5b50610257610e5d565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156102a557600080fd5b506102c460048036038101908080359060200190929190505050610e83565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561031257600080fd5b50610347600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610ec1565b6040518080602001838152602001828103825284818151815260200191508051906020019080838360005b8381101561038d578082015181840152602081019050610372565b50505050905090810190601f1680156103ba5780820380516001836020036101000a031916815260200191505b50935050505060405180910390f35b3480156103d557600080fd5b506103de61101e565b6040518082815260200191505060405180910390f35b34801561040057600080fd5b50610409611024565b6040518082815260200191505060405180910390f35b34801561042b57600080fd5b5061043461102a565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561047757808201518184015260208101905061045c565b505050509050019250505060405180910390f35b34801561049757600080fd5b506104c060048036038101908080359060200190929190803590602001909291905050506110b8565b005b3480156104ce57600080fd5b506104d7611161565b6040518082815260200191505060405180910390f35b3480156104f957600080fd5b50610502611180565b6040518080602001848152602001838152602001828103825285818151815260200191508051906020019080838360005b8381101561054e578082015181840152602081019050610533565b50505050905090810190601f16801561057b5780820380516001836020036101000a031916815260200191505b5094505050505060405180910390f35b34801561059757600080fd5b506105b660048036038101908080359060200190929190505050611230565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6000815111151561060857600080fd5b600860009054906101000a900460ff16151561062357600080fd5b670de0b6b3a7640000600a54023414151561063d57600080fd5b600954600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001015410151561068f57600080fd5b6106983361126e565b156107ef576001600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001018190555080600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001908051906020019061073b9291906113cb565b50600160023390806001815401808255809150509060018203906000526020600020016000909192909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555003600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020181905550610841565b6001600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101600082825401925050819055505b60043390806001815401808255809150509060018203906000526020600020016000909192909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550507f76041b6e8130995874e79e751d284536c37242cb014fb0584ede1d1e64ce03c9600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001015460405180806020018381526020018281038252848181546001816001161561010002031660029004815260200191508054600181600116156101000203166002900480156109dc5780601f106109b1576101008083540402835291602001916109dc565b820191906000526020600020905b8154815290600101906020018083116109bf57829003601f168201915b5050935050505060405180910390a150565b600860009054906101000a900460ff1681565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610a5f57600080fd5b6000600480549050111515610a7357600080fd5b600480549050610a81611339565b811515610a8a57fe5b069050600481815481101515610a9c57fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc3073ffffffffffffffffffffffffffffffffffffffff16319081150290604051600060405180830381858888f19350505050158015610b23573d6000803e3d6000fd5b5060036000600483815481101515610b3757fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160056000019080546001816001161561010002031660029004610bc392919061144b565b5060036000600483815481101515610bd757fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101546005600101819055506000604051908082528060200260200182016040528015610c795781602001602082028038833980820191505090505b5060049080519060200190610c8f9291906114d2565b506000604051908082528060200260200182016040528015610cc05781602001602082028038833980820191505090505b5060029080519060200190610cd69291906114d2565b506000600860006101000a81548160ff0219169083151502179055507fd6d1eeba639254bd05e36261ae299af245328ab997fd9b7823d5fff17f1b74a460056000016005600101546040518080602001838152602001828103825284818154600181600116156101000203166002900481526020019150805460018160011615610100020316600290048015610dad5780601f10610d8257610100808354040283529160200191610dad565b820191906000526020600020905b815481529060010190602001808311610d9057829003601f168201915b5050935050505060405180910390a150565b60008054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610e555780601f10610e2a57610100808354040283529160200191610e55565b820191906000526020600020905b815481529060010190602001808311610e3857829003601f168201915b505050505081565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600281815481101515610e9257fe5b906000526020600020016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60606000610ece8361126e565b15610ef357600060206040519081016040528060008152509080905091509150611019565b600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010154818054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561100d5780601f10610fe25761010080835404028352916020019161100d565b820191906000526020600020905b815481529060010190602001808311610ff057829003601f168201915b50505050509150915091505b915091565b600a5481565b60095481565b606060028054806020026020016040519081016040528092919081815260200182805480156110ae57602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311611064575b5050505050905090565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561111457600080fd5b6001600860006101000a81548160ff0219169083151502179055506000821461113d5781611140565b60015b600981905550600081146111545780611157565b60015b600a819055505050565b60003073ffffffffffffffffffffffffffffffffffffffff1631905090565b6005806000018054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561121a5780601f106111ef5761010080835404028352916020019161121a565b820191906000526020600020905b8154815290600101906020018083116111fd57829003601f168201915b5050505050908060010154908060020154905083565b60048181548110151561123f57fe5b906000526020600020016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008060028054905014156112865760019050611334565b8173ffffffffffffffffffffffffffffffffffffffff166002600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600201548154811015156112ee57fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141590505b919050565b6000444260046040518084815260200183815260200182805480156113b357602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311611369575b50509350505050604051809103902060019004905090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061140c57805160ff191683800117855561143a565b8280016001018555821561143a579182015b8281111561143957825182559160200191906001019061141e565b5b509050611447919061155c565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061148457805485556114c1565b828001600101855582156114c157600052602060002091601f016020900482015b828111156114c05782548255916001019190600101906114a5565b5b5090506114ce919061155c565b5090565b82805482825590600052602060002090810192821561154b579160200282015b8281111561154a5782518260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550916020019190600101906114f2565b5b5090506115589190611581565b5090565b61157e91905b8082111561157a576000816000905550600101611562565b5090565b90565b6115c191905b808211156115bd57600081816101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905550600101611587565b5090565b905600a165627a7a72305820a8fb9f06533db9442203332bcb5c2edf68b699d54b7db0be9b1ca78528475c180029 diff --git a/libraries/vendor/xgtvm/lottery2.json b/libraries/vendor/xgtvm/lottery2.json new file mode 100644 index 00000000..8c65486a --- /dev/null +++ b/libraries/vendor/xgtvm/lottery2.json @@ -0,0 +1 @@ +[0x60, 0x80, 0x60, 0x40, 0x52, 0x34, 0x80, 0x15, 0x62, 0x00, 0x00, 0x11, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x60, 0x40, 0x51, 0x62, 0x00, 0x17, 0x54, 0x38, 0x03, 0x80, 0x62, 0x00, 0x17, 0x54, 0x83, 0x39, 0x81, 0x01, 0x80, 0x60, 0x40, 0x52, 0x81, 0x01, 0x90, 0x80, 0x80, 0x51, 0x82, 0x01, 0x92, 0x91, 0x90, 0x60, 0x20, 0x01, 0x80, 0x51, 0x90, 0x60, 0x20, 0x01, 0x90, 0x92, 0x91, 0x90, 0x50, 0x50, 0x50, 0x80, 0x60, 0x01, 0x60, 0x00, 0x61, 0x01, 0x00, 0x0a, 0x81, 0x54, 0x81, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0x19, 0x16, 0x90, 0x83, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x02, 0x17, 0x90, 0x55, 0x50, 0x81, 0x60, 0x00, 0x90, 0x80, 0x51, 0x90, 0x60, 0x20, 0x01, 0x90, 0x62, 0x00, 0x00, 0x9c, 0x92, 0x91, 0x90, 0x62, 0x00, 0x00, 0xa5, 0x56, 0x5b, 0x50, 0x50, 0x50, 0x62, 0x00, 0x01, 0x54, 0x56, 0x5b, 0x82, 0x80, 0x54, 0x60, 0x01, 0x81, 0x60, 0x01, 0x16, 0x15, 0x61, 0x01, 0x00, 0x02, 0x03, 0x16, 0x60, 0x02, 0x90, 0x04, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x90, 0x60, 0x1f, 0x01, 0x60, 0x20, 0x90, 0x04, 0x81, 0x01, 0x92, 0x82, 0x60, 0x1f, 0x10, 0x62, 0x00, 0x00, 0xe8, 0x57, 0x80, 0x51, 0x60, 0xff, 0x19, 0x16, 0x83, 0x80, 0x01, 0x17, 0x85, 0x55, 0x62, 0x00, 0x01, 0x19, 0x56, 0x5b, 0x82, 0x80, 0x01, 0x60, 0x01, 0x01, 0x85, 0x55, 0x82, 0x15, 0x62, 0x00, 0x01, 0x19, 0x57, 0x91, 0x82, 0x01, 0x5b, 0x82, 0x81, 0x11, 0x15, 0x62, 0x00, 0x01, 0x18, 0x57, 0x82, 0x51, 0x82, 0x55, 0x91, 0x60, 0x20, 0x01, 0x91, 0x90, 0x60, 0x01, 0x01, 0x90, 0x62, 0x00, 0x00, 0xfb, 0x56, 0x5b, 0x5b, 0x50, 0x90, 0x50, 0x62, 0x00, 0x01, 0x28, 0x91, 0x90, 0x62, 0x00, 0x01, 0x2c, 0x56, 0x5b, 0x50, 0x90, 0x56, 0x5b, 0x62, 0x00, 0x01, 0x51, 0x91, 0x90, 0x5b, 0x80, 0x82, 0x11, 0x15, 0x62, 0x00, 0x01, 0x4d, 0x57, 0x60, 0x00, 0x81, 0x60, 0x00, 0x90, 0x55, 0x50, 0x60, 0x01, 0x01, 0x62, 0x00, 0x01, 0x33, 0x56, 0x5b, 0x50, 0x90, 0x56, 0x5b, 0x90, 0x56, 0x5b, 0x61, 0x15, 0xf0, 0x80, 0x62, 0x00, 0x01, 0x64, 0x60, 0x00, 0x39, 0x60, 0x00, 0xf3, 0x00, 0x60, 0x80, 0x60, 0x40, 0x52, 0x60, 0x04, 0x36, 0x10, 0x61, 0x00, 0xd0, 0x57, 0x60, 0x00, 0x35, 0x7c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x04, 0x63, 0xff, 0xff, 0xff, 0xff, 0x16, 0x80, 0x63, 0x10, 0xc8, 0x5f, 0xe5, 0x14, 0x61, 0x01, 0x10, 0x57, 0x80, 0x63, 0x14, 0x03, 0x4b, 0xd2, 0x14, 0x61, 0x01, 0x3f, 0x57, 0x80, 0x63, 0x1d, 0x27, 0x76, 0x9f, 0x14, 0x61, 0x01, 0x56, 0x57, 0x80, 0x63, 0x23, 0xd1, 0x41, 0x49, 0x14, 0x61, 0x01, 0xb2, 0x57, 0x80, 0x63, 0x48, 0x1c, 0x6a, 0x75, 0x14, 0x61, 0x02, 0x42, 0x57, 0x80, 0x63, 0x58, 0x32, 0xd5, 0x71, 0x14, 0x61, 0x02, 0x99, 0x57, 0x80, 0x63, 0x5c, 0x12, 0xcd, 0x4b, 0x14, 0x61, 0x03, 0x06, 0x57, 0x80, 0x63, 0x5d, 0x58, 0xa7, 0x4a, 0x14, 0x61, 0x03, 0xc9, 0x57, 0x80, 0x63, 0x77, 0x52, 0x04, 0x5b, 0x14, 0x61, 0x03, 0xf4, 0x57, 0x80, 0x63, 0x8b, 0x5b, 0x9c, 0xcc, 0x14, 0x61, 0x04, 0x1f, 0x57, 0x80, 0x63, 0xbd, 0xae, 0xa3, 0x26, 0x14, 0x61, 0x04, 0x8b, 0x57, 0x80, 0x63, 0xd6, 0x88, 0x95, 0xd8, 0x14, 0x61, 0x04, 0xc2, 0x57, 0x80, 0x63, 0xdf, 0xbf, 0x53, 0xae, 0x14, 0x61, 0x04, 0xed, 0x57, 0x80, 0x63, 0xf2, 0x52, 0x66, 0xdd, 0x14, 0x61, 0x05, 0x8b, 0x57, 0x5b, 0x61, 0x01, 0x0e, 0x60, 0x40, 0x80, 0x51, 0x90, 0x81, 0x01, 0x60, 0x40, 0x52, 0x80, 0x60, 0x07, 0x81, 0x52, 0x60, 0x20, 0x01, 0x7f, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x52, 0x50, 0x61, 0x05, 0xf8, 0x56, 0x5b, 0x00, 0x5b, 0x34, 0x80, 0x15, 0x61, 0x01, 0x1c, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x61, 0x01, 0x25, 0x61, 0x09, 0xee, 0x56, 0x5b, 0x60, 0x40, 0x51, 0x80, 0x82, 0x15, 0x15, 0x15, 0x15, 0x81, 0x52, 0x60, 0x20, 0x01, 0x91, 0x50, 0x50, 0x60, 0x40, 0x51, 0x80, 0x91, 0x03, 0x90, 0xf3, 0x5b, 0x34, 0x80, 0x15, 0x61, 0x01, 0x4b, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x61, 0x01, 0x54, 0x61, 0x0a, 0x01, 0x56, 0x5b, 0x00, 0x5b, 0x61, 0x01, 0xb0, 0x60, 0x04, 0x80, 0x36, 0x03, 0x81, 0x01, 0x90, 0x80, 0x80, 0x35, 0x90, 0x60, 0x20, 0x01, 0x90, 0x82, 0x01, 0x80, 0x35, 0x90, 0x60, 0x20, 0x01, 0x90, 0x80, 0x80, 0x60, 0x1f, 0x01, 0x60, 0x20, 0x80, 0x91, 0x04, 0x02, 0x60, 0x20, 0x01, 0x60, 0x40, 0x51, 0x90, 0x81, 0x01, 0x60, 0x40, 0x52, 0x80, 0x93, 0x92, 0x91, 0x90, 0x81, 0x81, 0x52, 0x60, 0x20, 0x01, 0x83, 0x83, 0x80, 0x82, 0x84, 0x37, 0x82, 0x01, 0x91, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x91, 0x92, 0x91, 0x92, 0x90, 0x50, 0x50, 0x50, 0x61, 0x05, 0xf8, 0x56, 0x5b, 0x00, 0x5b, 0x34, 0x80, 0x15, 0x61, 0x01, 0xbe, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x61, 0x01, 0xc7, 0x61, 0x0d, 0xbf, 0x56, 0x5b, 0x60, 0x40, 0x51, 0x80, 0x80, 0x60, 0x20, 0x01, 0x82, 0x81, 0x03, 0x82, 0x52, 0x83, 0x81, 0x81, 0x51, 0x81, 0x52, 0x60, 0x20, 0x01, 0x91, 0x50, 0x80, 0x51, 0x90, 0x60, 0x20, 0x01, 0x90, 0x80, 0x83, 0x83, 0x60, 0x00, 0x5b, 0x83, 0x81, 0x10, 0x15, 0x61, 0x02, 0x07, 0x57, 0x80, 0x82, 0x01, 0x51, 0x81, 0x84, 0x01, 0x52, 0x60, 0x20, 0x81, 0x01, 0x90, 0x50, 0x61, 0x01, 0xec, 0x56, 0x5b, 0x50, 0x50, 0x50, 0x50, 0x90, 0x50, 0x90, 0x81, 0x01, 0x90, 0x60, 0x1f, 0x16, 0x80, 0x15, 0x61, 0x02, 0x34, 0x57, 0x80, 0x82, 0x03, 0x80, 0x51, 0x60, 0x01, 0x83, 0x60, 0x20, 0x03, 0x61, 0x01, 0x00, 0x0a, 0x03, 0x19, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x91, 0x50, 0x5b, 0x50, 0x92, 0x50, 0x50, 0x50, 0x60, 0x40, 0x51, 0x80, 0x91, 0x03, 0x90, 0xf3, 0x5b, 0x34, 0x80, 0x15, 0x61, 0x02, 0x4e, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x61, 0x02, 0x57, 0x61, 0x0e, 0x5d, 0x56, 0x5b, 0x60, 0x40, 0x51, 0x80, 0x82, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x91, 0x50, 0x50, 0x60, 0x40, 0x51, 0x80, 0x91, 0x03, 0x90, 0xf3, 0x5b, 0x34, 0x80, 0x15, 0x61, 0x02, 0xa5, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x61, 0x02, 0xc4, 0x60, 0x04, 0x80, 0x36, 0x03, 0x81, 0x01, 0x90, 0x80, 0x80, 0x35, 0x90, 0x60, 0x20, 0x01, 0x90, 0x92, 0x91, 0x90, 0x50, 0x50, 0x50, 0x61, 0x0e, 0x83, 0x56, 0x5b, 0x60, 0x40, 0x51, 0x80, 0x82, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x91, 0x50, 0x50, 0x60, 0x40, 0x51, 0x80, 0x91, 0x03, 0x90, 0xf3, 0x5b, 0x34, 0x80, 0x15, 0x61, 0x03, 0x12, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x61, 0x03, 0x47, 0x60, 0x04, 0x80, 0x36, 0x03, 0x81, 0x01, 0x90, 0x80, 0x80, 0x35, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x90, 0x60, 0x20, 0x01, 0x90, 0x92, 0x91, 0x90, 0x50, 0x50, 0x50, 0x61, 0x0e, 0xc1, 0x56, 0x5b, 0x60, 0x40, 0x51, 0x80, 0x80, 0x60, 0x20, 0x01, 0x83, 0x81, 0x52, 0x60, 0x20, 0x01, 0x82, 0x81, 0x03, 0x82, 0x52, 0x84, 0x81, 0x81, 0x51, 0x81, 0x52, 0x60, 0x20, 0x01, 0x91, 0x50, 0x80, 0x51, 0x90, 0x60, 0x20, 0x01, 0x90, 0x80, 0x83, 0x83, 0x60, 0x00, 0x5b, 0x83, 0x81, 0x10, 0x15, 0x61, 0x03, 0x8d, 0x57, 0x80, 0x82, 0x01, 0x51, 0x81, 0x84, 0x01, 0x52, 0x60, 0x20, 0x81, 0x01, 0x90, 0x50, 0x61, 0x03, 0x72, 0x56, 0x5b, 0x50, 0x50, 0x50, 0x50, 0x90, 0x50, 0x90, 0x81, 0x01, 0x90, 0x60, 0x1f, 0x16, 0x80, 0x15, 0x61, 0x03, 0xba, 0x57, 0x80, 0x82, 0x03, 0x80, 0x51, 0x60, 0x01, 0x83, 0x60, 0x20, 0x03, 0x61, 0x01, 0x00, 0x0a, 0x03, 0x19, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x91, 0x50, 0x5b, 0x50, 0x93, 0x50, 0x50, 0x50, 0x50, 0x60, 0x40, 0x51, 0x80, 0x91, 0x03, 0x90, 0xf3, 0x5b, 0x34, 0x80, 0x15, 0x61, 0x03, 0xd5, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x61, 0x03, 0xde, 0x61, 0x10, 0x1e, 0x56, 0x5b, 0x60, 0x40, 0x51, 0x80, 0x82, 0x81, 0x52, 0x60, 0x20, 0x01, 0x91, 0x50, 0x50, 0x60, 0x40, 0x51, 0x80, 0x91, 0x03, 0x90, 0xf3, 0x5b, 0x34, 0x80, 0x15, 0x61, 0x04, 0x00, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x61, 0x04, 0x09, 0x61, 0x10, 0x24, 0x56, 0x5b, 0x60, 0x40, 0x51, 0x80, 0x82, 0x81, 0x52, 0x60, 0x20, 0x01, 0x91, 0x50, 0x50, 0x60, 0x40, 0x51, 0x80, 0x91, 0x03, 0x90, 0xf3, 0x5b, 0x34, 0x80, 0x15, 0x61, 0x04, 0x2b, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x61, 0x04, 0x34, 0x61, 0x10, 0x2a, 0x56, 0x5b, 0x60, 0x40, 0x51, 0x80, 0x80, 0x60, 0x20, 0x01, 0x82, 0x81, 0x03, 0x82, 0x52, 0x83, 0x81, 0x81, 0x51, 0x81, 0x52, 0x60, 0x20, 0x01, 0x91, 0x50, 0x80, 0x51, 0x90, 0x60, 0x20, 0x01, 0x90, 0x60, 0x20, 0x02, 0x80, 0x83, 0x83, 0x60, 0x00, 0x5b, 0x83, 0x81, 0x10, 0x15, 0x61, 0x04, 0x77, 0x57, 0x80, 0x82, 0x01, 0x51, 0x81, 0x84, 0x01, 0x52, 0x60, 0x20, 0x81, 0x01, 0x90, 0x50, 0x61, 0x04, 0x5c, 0x56, 0x5b, 0x50, 0x50, 0x50, 0x50, 0x90, 0x50, 0x01, 0x92, 0x50, 0x50, 0x50, 0x60, 0x40, 0x51, 0x80, 0x91, 0x03, 0x90, 0xf3, 0x5b, 0x34, 0x80, 0x15, 0x61, 0x04, 0x97, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x61, 0x04, 0xc0, 0x60, 0x04, 0x80, 0x36, 0x03, 0x81, 0x01, 0x90, 0x80, 0x80, 0x35, 0x90, 0x60, 0x20, 0x01, 0x90, 0x92, 0x91, 0x90, 0x80, 0x35, 0x90, 0x60, 0x20, 0x01, 0x90, 0x92, 0x91, 0x90, 0x50, 0x50, 0x50, 0x61, 0x10, 0xb8, 0x56, 0x5b, 0x00, 0x5b, 0x34, 0x80, 0x15, 0x61, 0x04, 0xce, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x61, 0x04, 0xd7, 0x61, 0x11, 0x61, 0x56, 0x5b, 0x60, 0x40, 0x51, 0x80, 0x82, 0x81, 0x52, 0x60, 0x20, 0x01, 0x91, 0x50, 0x50, 0x60, 0x40, 0x51, 0x80, 0x91, 0x03, 0x90, 0xf3, 0x5b, 0x34, 0x80, 0x15, 0x61, 0x04, 0xf9, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x61, 0x05, 0x02, 0x61, 0x11, 0x80, 0x56, 0x5b, 0x60, 0x40, 0x51, 0x80, 0x80, 0x60, 0x20, 0x01, 0x84, 0x81, 0x52, 0x60, 0x20, 0x01, 0x83, 0x81, 0x52, 0x60, 0x20, 0x01, 0x82, 0x81, 0x03, 0x82, 0x52, 0x85, 0x81, 0x81, 0x51, 0x81, 0x52, 0x60, 0x20, 0x01, 0x91, 0x50, 0x80, 0x51, 0x90, 0x60, 0x20, 0x01, 0x90, 0x80, 0x83, 0x83, 0x60, 0x00, 0x5b, 0x83, 0x81, 0x10, 0x15, 0x61, 0x05, 0x4e, 0x57, 0x80, 0x82, 0x01, 0x51, 0x81, 0x84, 0x01, 0x52, 0x60, 0x20, 0x81, 0x01, 0x90, 0x50, 0x61, 0x05, 0x33, 0x56, 0x5b, 0x50, 0x50, 0x50, 0x50, 0x90, 0x50, 0x90, 0x81, 0x01, 0x90, 0x60, 0x1f, 0x16, 0x80, 0x15, 0x61, 0x05, 0x7b, 0x57, 0x80, 0x82, 0x03, 0x80, 0x51, 0x60, 0x01, 0x83, 0x60, 0x20, 0x03, 0x61, 0x01, 0x00, 0x0a, 0x03, 0x19, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x91, 0x50, 0x5b, 0x50, 0x94, 0x50, 0x50, 0x50, 0x50, 0x50, 0x60, 0x40, 0x51, 0x80, 0x91, 0x03, 0x90, 0xf3, 0x5b, 0x34, 0x80, 0x15, 0x61, 0x05, 0x97, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x61, 0x05, 0xb6, 0x60, 0x04, 0x80, 0x36, 0x03, 0x81, 0x01, 0x90, 0x80, 0x80, 0x35, 0x90, 0x60, 0x20, 0x01, 0x90, 0x92, 0x91, 0x90, 0x50, 0x50, 0x50, 0x61, 0x12, 0x30, 0x56, 0x5b, 0x60, 0x40, 0x51, 0x80, 0x82, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x91, 0x50, 0x50, 0x60, 0x40, 0x51, 0x80, 0x91, 0x03, 0x90, 0xf3, 0x5b, 0x60, 0x00, 0x81, 0x51, 0x11, 0x15, 0x15, 0x61, 0x06, 0x08, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x60, 0x08, 0x60, 0x00, 0x90, 0x54, 0x90, 0x61, 0x01, 0x00, 0x0a, 0x90, 0x04, 0x60, 0xff, 0x16, 0x15, 0x15, 0x61, 0x06, 0x23, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x67, 0x0d, 0xe0, 0xb6, 0xb3, 0xa7, 0x64, 0x00, 0x00, 0x60, 0x0a, 0x54, 0x02, 0x34, 0x14, 0x15, 0x15, 0x61, 0x06, 0x3d, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x60, 0x09, 0x54, 0x60, 0x03, 0x60, 0x00, 0x33, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x90, 0x81, 0x52, 0x60, 0x20, 0x01, 0x60, 0x00, 0x20, 0x60, 0x01, 0x01, 0x54, 0x10, 0x15, 0x15, 0x61, 0x06, 0x8f, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x61, 0x06, 0x98, 0x33, 0x61, 0x12, 0x6e, 0x56, 0x5b, 0x15, 0x61, 0x07, 0xef, 0x57, 0x60, 0x01, 0x60, 0x03, 0x60, 0x00, 0x33, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x90, 0x81, 0x52, 0x60, 0x20, 0x01, 0x60, 0x00, 0x20, 0x60, 0x01, 0x01, 0x81, 0x90, 0x55, 0x50, 0x80, 0x60, 0x03, 0x60, 0x00, 0x33, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x90, 0x81, 0x52, 0x60, 0x20, 0x01, 0x60, 0x00, 0x20, 0x60, 0x00, 0x01, 0x90, 0x80, 0x51, 0x90, 0x60, 0x20, 0x01, 0x90, 0x61, 0x07, 0x3b, 0x92, 0x91, 0x90, 0x61, 0x13, 0xcb, 0x56, 0x5b, 0x50, 0x60, 0x01, 0x60, 0x02, 0x33, 0x90, 0x80, 0x60, 0x01, 0x81, 0x54, 0x01, 0x80, 0x82, 0x55, 0x80, 0x91, 0x50, 0x50, 0x90, 0x60, 0x01, 0x82, 0x03, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x01, 0x60, 0x00, 0x90, 0x91, 0x92, 0x90, 0x91, 0x90, 0x91, 0x61, 0x01, 0x00, 0x0a, 0x81, 0x54, 0x81, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0x19, 0x16, 0x90, 0x83, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x02, 0x17, 0x90, 0x55, 0x50, 0x03, 0x60, 0x03, 0x60, 0x00, 0x33, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x90, 0x81, 0x52, 0x60, 0x20, 0x01, 0x60, 0x00, 0x20, 0x60, 0x02, 0x01, 0x81, 0x90, 0x55, 0x50, 0x61, 0x08, 0x41, 0x56, 0x5b, 0x60, 0x01, 0x60, 0x03, 0x60, 0x00, 0x33, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x90, 0x81, 0x52, 0x60, 0x20, 0x01, 0x60, 0x00, 0x20, 0x60, 0x01, 0x01, 0x60, 0x00, 0x82, 0x82, 0x54, 0x01, 0x92, 0x50, 0x50, 0x81, 0x90, 0x55, 0x50, 0x5b, 0x60, 0x04, 0x33, 0x90, 0x80, 0x60, 0x01, 0x81, 0x54, 0x01, 0x80, 0x82, 0x55, 0x80, 0x91, 0x50, 0x50, 0x90, 0x60, 0x01, 0x82, 0x03, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x01, 0x60, 0x00, 0x90, 0x91, 0x92, 0x90, 0x91, 0x90, 0x91, 0x61, 0x01, 0x00, 0x0a, 0x81, 0x54, 0x81, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0x19, 0x16, 0x90, 0x83, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x02, 0x17, 0x90, 0x55, 0x50, 0x50, 0x7f, 0x76, 0x04, 0x1b, 0x6e, 0x81, 0x30, 0x99, 0x58, 0x74, 0xe7, 0x9e, 0x75, 0x1d, 0x28, 0x45, 0x36, 0xc3, 0x72, 0x42, 0xcb, 0x01, 0x4f, 0xb0, 0x58, 0x4e, 0xde, 0x1d, 0x1e, 0x64, 0xce, 0x03, 0xc9, 0x60, 0x03, 0x60, 0x00, 0x33, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x90, 0x81, 0x52, 0x60, 0x20, 0x01, 0x60, 0x00, 0x20, 0x60, 0x00, 0x01, 0x60, 0x03, 0x60, 0x00, 0x33, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x90, 0x81, 0x52, 0x60, 0x20, 0x01, 0x60, 0x00, 0x20, 0x60, 0x01, 0x01, 0x54, 0x60, 0x40, 0x51, 0x80, 0x80, 0x60, 0x20, 0x01, 0x83, 0x81, 0x52, 0x60, 0x20, 0x01, 0x82, 0x81, 0x03, 0x82, 0x52, 0x84, 0x81, 0x81, 0x54, 0x60, 0x01, 0x81, 0x60, 0x01, 0x16, 0x15, 0x61, 0x01, 0x00, 0x02, 0x03, 0x16, 0x60, 0x02, 0x90, 0x04, 0x81, 0x52, 0x60, 0x20, 0x01, 0x91, 0x50, 0x80, 0x54, 0x60, 0x01, 0x81, 0x60, 0x01, 0x16, 0x15, 0x61, 0x01, 0x00, 0x02, 0x03, 0x16, 0x60, 0x02, 0x90, 0x04, 0x80, 0x15, 0x61, 0x09, 0xdc, 0x57, 0x80, 0x60, 0x1f, 0x10, 0x61, 0x09, 0xb1, 0x57, 0x61, 0x01, 0x00, 0x80, 0x83, 0x54, 0x04, 0x02, 0x83, 0x52, 0x91, 0x60, 0x20, 0x01, 0x91, 0x61, 0x09, 0xdc, 0x56, 0x5b, 0x82, 0x01, 0x91, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x90, 0x5b, 0x81, 0x54, 0x81, 0x52, 0x90, 0x60, 0x01, 0x01, 0x90, 0x60, 0x20, 0x01, 0x80, 0x83, 0x11, 0x61, 0x09, 0xbf, 0x57, 0x82, 0x90, 0x03, 0x60, 0x1f, 0x16, 0x82, 0x01, 0x91, 0x5b, 0x50, 0x50, 0x93, 0x50, 0x50, 0x50, 0x50, 0x60, 0x40, 0x51, 0x80, 0x91, 0x03, 0x90, 0xa1, 0x50, 0x56, 0x5b, 0x60, 0x08, 0x60, 0x00, 0x90, 0x54, 0x90, 0x61, 0x01, 0x00, 0x0a, 0x90, 0x04, 0x60, 0xff, 0x16, 0x81, 0x56, 0x5b, 0x60, 0x00, 0x60, 0x01, 0x60, 0x00, 0x90, 0x54, 0x90, 0x61, 0x01, 0x00, 0x0a, 0x90, 0x04, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x33, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x14, 0x15, 0x15, 0x61, 0x0a, 0x5f, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x60, 0x00, 0x60, 0x04, 0x80, 0x54, 0x90, 0x50, 0x11, 0x15, 0x15, 0x61, 0x0a, 0x73, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x60, 0x04, 0x80, 0x54, 0x90, 0x50, 0x61, 0x0a, 0x81, 0x61, 0x13, 0x39, 0x56, 0x5b, 0x81, 0x15, 0x15, 0x61, 0x0a, 0x8a, 0x57, 0xfe, 0x5b, 0x06, 0x90, 0x50, 0x60, 0x04, 0x81, 0x81, 0x54, 0x81, 0x10, 0x15, 0x15, 0x61, 0x0a, 0x9c, 0x57, 0xfe, 0x5b, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x01, 0x60, 0x00, 0x90, 0x54, 0x90, 0x61, 0x01, 0x00, 0x0a, 0x90, 0x04, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x61, 0x08, 0xfc, 0x30, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x31, 0x90, 0x81, 0x15, 0x02, 0x90, 0x60, 0x40, 0x51, 0x60, 0x00, 0x60, 0x40, 0x51, 0x80, 0x83, 0x03, 0x81, 0x85, 0x88, 0x88, 0xf1, 0x93, 0x50, 0x50, 0x50, 0x50, 0x15, 0x80, 0x15, 0x61, 0x0b, 0x23, 0x57, 0x3d, 0x60, 0x00, 0x80, 0x3e, 0x3d, 0x60, 0x00, 0xfd, 0x5b, 0x50, 0x60, 0x03, 0x60, 0x00, 0x60, 0x04, 0x83, 0x81, 0x54, 0x81, 0x10, 0x15, 0x15, 0x61, 0x0b, 0x37, 0x57, 0xfe, 0x5b, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x01, 0x60, 0x00, 0x90, 0x54, 0x90, 0x61, 0x01, 0x00, 0x0a, 0x90, 0x04, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x90, 0x81, 0x52, 0x60, 0x20, 0x01, 0x60, 0x00, 0x20, 0x60, 0x00, 0x01, 0x60, 0x05, 0x60, 0x00, 0x01, 0x90, 0x80, 0x54, 0x60, 0x01, 0x81, 0x60, 0x01, 0x16, 0x15, 0x61, 0x01, 0x00, 0x02, 0x03, 0x16, 0x60, 0x02, 0x90, 0x04, 0x61, 0x0b, 0xc3, 0x92, 0x91, 0x90, 0x61, 0x14, 0x4b, 0x56, 0x5b, 0x50, 0x60, 0x03, 0x60, 0x00, 0x60, 0x04, 0x83, 0x81, 0x54, 0x81, 0x10, 0x15, 0x15, 0x61, 0x0b, 0xd7, 0x57, 0xfe, 0x5b, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x01, 0x60, 0x00, 0x90, 0x54, 0x90, 0x61, 0x01, 0x00, 0x0a, 0x90, 0x04, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x90, 0x81, 0x52, 0x60, 0x20, 0x01, 0x60, 0x00, 0x20, 0x60, 0x01, 0x01, 0x54, 0x60, 0x05, 0x60, 0x01, 0x01, 0x81, 0x90, 0x55, 0x50, 0x60, 0x00, 0x60, 0x40, 0x51, 0x90, 0x80, 0x82, 0x52, 0x80, 0x60, 0x20, 0x02, 0x60, 0x20, 0x01, 0x82, 0x01, 0x60, 0x40, 0x52, 0x80, 0x15, 0x61, 0x0c, 0x79, 0x57, 0x81, 0x60, 0x20, 0x01, 0x60, 0x20, 0x82, 0x02, 0x80, 0x38, 0x83, 0x39, 0x80, 0x82, 0x01, 0x91, 0x50, 0x50, 0x90, 0x50, 0x5b, 0x50, 0x60, 0x04, 0x90, 0x80, 0x51, 0x90, 0x60, 0x20, 0x01, 0x90, 0x61, 0x0c, 0x8f, 0x92, 0x91, 0x90, 0x61, 0x14, 0xd2, 0x56, 0x5b, 0x50, 0x60, 0x00, 0x60, 0x40, 0x51, 0x90, 0x80, 0x82, 0x52, 0x80, 0x60, 0x20, 0x02, 0x60, 0x20, 0x01, 0x82, 0x01, 0x60, 0x40, 0x52, 0x80, 0x15, 0x61, 0x0c, 0xc0, 0x57, 0x81, 0x60, 0x20, 0x01, 0x60, 0x20, 0x82, 0x02, 0x80, 0x38, 0x83, 0x39, 0x80, 0x82, 0x01, 0x91, 0x50, 0x50, 0x90, 0x50, 0x5b, 0x50, 0x60, 0x02, 0x90, 0x80, 0x51, 0x90, 0x60, 0x20, 0x01, 0x90, 0x61, 0x0c, 0xd6, 0x92, 0x91, 0x90, 0x61, 0x14, 0xd2, 0x56, 0x5b, 0x50, 0x60, 0x00, 0x60, 0x08, 0x60, 0x00, 0x61, 0x01, 0x00, 0x0a, 0x81, 0x54, 0x81, 0x60, 0xff, 0x02, 0x19, 0x16, 0x90, 0x83, 0x15, 0x15, 0x02, 0x17, 0x90, 0x55, 0x50, 0x7f, 0xd6, 0xd1, 0xee, 0xba, 0x63, 0x92, 0x54, 0xbd, 0x05, 0xe3, 0x62, 0x61, 0xae, 0x29, 0x9a, 0xf2, 0x45, 0x32, 0x8a, 0xb9, 0x97, 0xfd, 0x9b, 0x78, 0x23, 0xd5, 0xff, 0xf1, 0x7f, 0x1b, 0x74, 0xa4, 0x60, 0x05, 0x60, 0x00, 0x01, 0x60, 0x05, 0x60, 0x01, 0x01, 0x54, 0x60, 0x40, 0x51, 0x80, 0x80, 0x60, 0x20, 0x01, 0x83, 0x81, 0x52, 0x60, 0x20, 0x01, 0x82, 0x81, 0x03, 0x82, 0x52, 0x84, 0x81, 0x81, 0x54, 0x60, 0x01, 0x81, 0x60, 0x01, 0x16, 0x15, 0x61, 0x01, 0x00, 0x02, 0x03, 0x16, 0x60, 0x02, 0x90, 0x04, 0x81, 0x52, 0x60, 0x20, 0x01, 0x91, 0x50, 0x80, 0x54, 0x60, 0x01, 0x81, 0x60, 0x01, 0x16, 0x15, 0x61, 0x01, 0x00, 0x02, 0x03, 0x16, 0x60, 0x02, 0x90, 0x04, 0x80, 0x15, 0x61, 0x0d, 0xad, 0x57, 0x80, 0x60, 0x1f, 0x10, 0x61, 0x0d, 0x82, 0x57, 0x61, 0x01, 0x00, 0x80, 0x83, 0x54, 0x04, 0x02, 0x83, 0x52, 0x91, 0x60, 0x20, 0x01, 0x91, 0x61, 0x0d, 0xad, 0x56, 0x5b, 0x82, 0x01, 0x91, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x90, 0x5b, 0x81, 0x54, 0x81, 0x52, 0x90, 0x60, 0x01, 0x01, 0x90, 0x60, 0x20, 0x01, 0x80, 0x83, 0x11, 0x61, 0x0d, 0x90, 0x57, 0x82, 0x90, 0x03, 0x60, 0x1f, 0x16, 0x82, 0x01, 0x91, 0x5b, 0x50, 0x50, 0x93, 0x50, 0x50, 0x50, 0x50, 0x60, 0x40, 0x51, 0x80, 0x91, 0x03, 0x90, 0xa1, 0x50, 0x56, 0x5b, 0x60, 0x00, 0x80, 0x54, 0x60, 0x01, 0x81, 0x60, 0x01, 0x16, 0x15, 0x61, 0x01, 0x00, 0x02, 0x03, 0x16, 0x60, 0x02, 0x90, 0x04, 0x80, 0x60, 0x1f, 0x01, 0x60, 0x20, 0x80, 0x91, 0x04, 0x02, 0x60, 0x20, 0x01, 0x60, 0x40, 0x51, 0x90, 0x81, 0x01, 0x60, 0x40, 0x52, 0x80, 0x92, 0x91, 0x90, 0x81, 0x81, 0x52, 0x60, 0x20, 0x01, 0x82, 0x80, 0x54, 0x60, 0x01, 0x81, 0x60, 0x01, 0x16, 0x15, 0x61, 0x01, 0x00, 0x02, 0x03, 0x16, 0x60, 0x02, 0x90, 0x04, 0x80, 0x15, 0x61, 0x0e, 0x55, 0x57, 0x80, 0x60, 0x1f, 0x10, 0x61, 0x0e, 0x2a, 0x57, 0x61, 0x01, 0x00, 0x80, 0x83, 0x54, 0x04, 0x02, 0x83, 0x52, 0x91, 0x60, 0x20, 0x01, 0x91, 0x61, 0x0e, 0x55, 0x56, 0x5b, 0x82, 0x01, 0x91, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x90, 0x5b, 0x81, 0x54, 0x81, 0x52, 0x90, 0x60, 0x01, 0x01, 0x90, 0x60, 0x20, 0x01, 0x80, 0x83, 0x11, 0x61, 0x0e, 0x38, 0x57, 0x82, 0x90, 0x03, 0x60, 0x1f, 0x16, 0x82, 0x01, 0x91, 0x5b, 0x50, 0x50, 0x50, 0x50, 0x50, 0x81, 0x56, 0x5b, 0x60, 0x01, 0x60, 0x00, 0x90, 0x54, 0x90, 0x61, 0x01, 0x00, 0x0a, 0x90, 0x04, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x56, 0x5b, 0x60, 0x02, 0x81, 0x81, 0x54, 0x81, 0x10, 0x15, 0x15, 0x61, 0x0e, 0x92, 0x57, 0xfe, 0x5b, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x01, 0x60, 0x00, 0x91, 0x50, 0x54, 0x90, 0x61, 0x01, 0x00, 0x0a, 0x90, 0x04, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x56, 0x5b, 0x60, 0x60, 0x60, 0x00, 0x61, 0x0e, 0xce, 0x83, 0x61, 0x12, 0x6e, 0x56, 0x5b, 0x15, 0x61, 0x0e, 0xf3, 0x57, 0x60, 0x00, 0x60, 0x20, 0x60, 0x40, 0x51, 0x90, 0x81, 0x01, 0x60, 0x40, 0x52, 0x80, 0x60, 0x00, 0x81, 0x52, 0x50, 0x90, 0x80, 0x90, 0x50, 0x91, 0x50, 0x91, 0x50, 0x61, 0x10, 0x19, 0x56, 0x5b, 0x60, 0x03, 0x60, 0x00, 0x84, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x90, 0x81, 0x52, 0x60, 0x20, 0x01, 0x60, 0x00, 0x20, 0x60, 0x00, 0x01, 0x60, 0x03, 0x60, 0x00, 0x85, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x90, 0x81, 0x52, 0x60, 0x20, 0x01, 0x60, 0x00, 0x20, 0x60, 0x01, 0x01, 0x54, 0x81, 0x80, 0x54, 0x60, 0x01, 0x81, 0x60, 0x01, 0x16, 0x15, 0x61, 0x01, 0x00, 0x02, 0x03, 0x16, 0x60, 0x02, 0x90, 0x04, 0x80, 0x60, 0x1f, 0x01, 0x60, 0x20, 0x80, 0x91, 0x04, 0x02, 0x60, 0x20, 0x01, 0x60, 0x40, 0x51, 0x90, 0x81, 0x01, 0x60, 0x40, 0x52, 0x80, 0x92, 0x91, 0x90, 0x81, 0x81, 0x52, 0x60, 0x20, 0x01, 0x82, 0x80, 0x54, 0x60, 0x01, 0x81, 0x60, 0x01, 0x16, 0x15, 0x61, 0x01, 0x00, 0x02, 0x03, 0x16, 0x60, 0x02, 0x90, 0x04, 0x80, 0x15, 0x61, 0x10, 0x0d, 0x57, 0x80, 0x60, 0x1f, 0x10, 0x61, 0x0f, 0xe2, 0x57, 0x61, 0x01, 0x00, 0x80, 0x83, 0x54, 0x04, 0x02, 0x83, 0x52, 0x91, 0x60, 0x20, 0x01, 0x91, 0x61, 0x10, 0x0d, 0x56, 0x5b, 0x82, 0x01, 0x91, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x90, 0x5b, 0x81, 0x54, 0x81, 0x52, 0x90, 0x60, 0x01, 0x01, 0x90, 0x60, 0x20, 0x01, 0x80, 0x83, 0x11, 0x61, 0x0f, 0xf0, 0x57, 0x82, 0x90, 0x03, 0x60, 0x1f, 0x16, 0x82, 0x01, 0x91, 0x5b, 0x50, 0x50, 0x50, 0x50, 0x50, 0x91, 0x50, 0x91, 0x50, 0x91, 0x50, 0x5b, 0x91, 0x50, 0x91, 0x56, 0x5b, 0x60, 0x0a, 0x54, 0x81, 0x56, 0x5b, 0x60, 0x09, 0x54, 0x81, 0x56, 0x5b, 0x60, 0x60, 0x60, 0x02, 0x80, 0x54, 0x80, 0x60, 0x20, 0x02, 0x60, 0x20, 0x01, 0x60, 0x40, 0x51, 0x90, 0x81, 0x01, 0x60, 0x40, 0x52, 0x80, 0x92, 0x91, 0x90, 0x81, 0x81, 0x52, 0x60, 0x20, 0x01, 0x82, 0x80, 0x54, 0x80, 0x15, 0x61, 0x10, 0xae, 0x57, 0x60, 0x20, 0x02, 0x82, 0x01, 0x91, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x90, 0x5b, 0x81, 0x60, 0x00, 0x90, 0x54, 0x90, 0x61, 0x01, 0x00, 0x0a, 0x90, 0x04, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x90, 0x60, 0x01, 0x01, 0x90, 0x80, 0x83, 0x11, 0x61, 0x10, 0x64, 0x57, 0x5b, 0x50, 0x50, 0x50, 0x50, 0x50, 0x90, 0x50, 0x90, 0x56, 0x5b, 0x60, 0x01, 0x60, 0x00, 0x90, 0x54, 0x90, 0x61, 0x01, 0x00, 0x0a, 0x90, 0x04, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x33, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x14, 0x15, 0x15, 0x61, 0x11, 0x14, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x60, 0x01, 0x60, 0x08, 0x60, 0x00, 0x61, 0x01, 0x00, 0x0a, 0x81, 0x54, 0x81, 0x60, 0xff, 0x02, 0x19, 0x16, 0x90, 0x83, 0x15, 0x15, 0x02, 0x17, 0x90, 0x55, 0x50, 0x60, 0x00, 0x82, 0x14, 0x61, 0x11, 0x3d, 0x57, 0x81, 0x61, 0x11, 0x40, 0x56, 0x5b, 0x60, 0x01, 0x5b, 0x60, 0x09, 0x81, 0x90, 0x55, 0x50, 0x60, 0x00, 0x81, 0x14, 0x61, 0x11, 0x54, 0x57, 0x80, 0x61, 0x11, 0x57, 0x56, 0x5b, 0x60, 0x01, 0x5b, 0x60, 0x0a, 0x81, 0x90, 0x55, 0x50, 0x50, 0x50, 0x56, 0x5b, 0x60, 0x00, 0x30, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x31, 0x90, 0x50, 0x90, 0x56, 0x5b, 0x60, 0x05, 0x80, 0x60, 0x00, 0x01, 0x80, 0x54, 0x60, 0x01, 0x81, 0x60, 0x01, 0x16, 0x15, 0x61, 0x01, 0x00, 0x02, 0x03, 0x16, 0x60, 0x02, 0x90, 0x04, 0x80, 0x60, 0x1f, 0x01, 0x60, 0x20, 0x80, 0x91, 0x04, 0x02, 0x60, 0x20, 0x01, 0x60, 0x40, 0x51, 0x90, 0x81, 0x01, 0x60, 0x40, 0x52, 0x80, 0x92, 0x91, 0x90, 0x81, 0x81, 0x52, 0x60, 0x20, 0x01, 0x82, 0x80, 0x54, 0x60, 0x01, 0x81, 0x60, 0x01, 0x16, 0x15, 0x61, 0x01, 0x00, 0x02, 0x03, 0x16, 0x60, 0x02, 0x90, 0x04, 0x80, 0x15, 0x61, 0x12, 0x1a, 0x57, 0x80, 0x60, 0x1f, 0x10, 0x61, 0x11, 0xef, 0x57, 0x61, 0x01, 0x00, 0x80, 0x83, 0x54, 0x04, 0x02, 0x83, 0x52, 0x91, 0x60, 0x20, 0x01, 0x91, 0x61, 0x12, 0x1a, 0x56, 0x5b, 0x82, 0x01, 0x91, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x90, 0x5b, 0x81, 0x54, 0x81, 0x52, 0x90, 0x60, 0x01, 0x01, 0x90, 0x60, 0x20, 0x01, 0x80, 0x83, 0x11, 0x61, 0x11, 0xfd, 0x57, 0x82, 0x90, 0x03, 0x60, 0x1f, 0x16, 0x82, 0x01, 0x91, 0x5b, 0x50, 0x50, 0x50, 0x50, 0x50, 0x90, 0x80, 0x60, 0x01, 0x01, 0x54, 0x90, 0x80, 0x60, 0x02, 0x01, 0x54, 0x90, 0x50, 0x83, 0x56, 0x5b, 0x60, 0x04, 0x81, 0x81, 0x54, 0x81, 0x10, 0x15, 0x15, 0x61, 0x12, 0x3f, 0x57, 0xfe, 0x5b, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x01, 0x60, 0x00, 0x91, 0x50, 0x54, 0x90, 0x61, 0x01, 0x00, 0x0a, 0x90, 0x04, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x56, 0x5b, 0x60, 0x00, 0x80, 0x60, 0x02, 0x80, 0x54, 0x90, 0x50, 0x14, 0x15, 0x61, 0x12, 0x86, 0x57, 0x60, 0x01, 0x90, 0x50, 0x61, 0x13, 0x34, 0x56, 0x5b, 0x81, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x60, 0x02, 0x60, 0x03, 0x60, 0x00, 0x85, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x90, 0x81, 0x52, 0x60, 0x20, 0x01, 0x60, 0x00, 0x20, 0x60, 0x02, 0x01, 0x54, 0x81, 0x54, 0x81, 0x10, 0x15, 0x15, 0x61, 0x12, 0xee, 0x57, 0xfe, 0x5b, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x01, 0x60, 0x00, 0x90, 0x54, 0x90, 0x61, 0x01, 0x00, 0x0a, 0x90, 0x04, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x14, 0x15, 0x90, 0x50, 0x5b, 0x91, 0x90, 0x50, 0x56, 0x5b, 0x60, 0x00, 0x44, 0x42, 0x60, 0x04, 0x60, 0x40, 0x51, 0x80, 0x84, 0x81, 0x52, 0x60, 0x20, 0x01, 0x83, 0x81, 0x52, 0x60, 0x20, 0x01, 0x82, 0x80, 0x54, 0x80, 0x15, 0x61, 0x13, 0xb3, 0x57, 0x60, 0x20, 0x02, 0x82, 0x01, 0x91, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x90, 0x5b, 0x81, 0x60, 0x00, 0x90, 0x54, 0x90, 0x61, 0x01, 0x00, 0x0a, 0x90, 0x04, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x90, 0x60, 0x01, 0x01, 0x90, 0x80, 0x83, 0x11, 0x61, 0x13, 0x69, 0x57, 0x5b, 0x50, 0x50, 0x93, 0x50, 0x50, 0x50, 0x50, 0x60, 0x40, 0x51, 0x80, 0x91, 0x03, 0x90, 0x20, 0x60, 0x01, 0x90, 0x04, 0x90, 0x50, 0x90, 0x56, 0x5b, 0x82, 0x80, 0x54, 0x60, 0x01, 0x81, 0x60, 0x01, 0x16, 0x15, 0x61, 0x01, 0x00, 0x02, 0x03, 0x16, 0x60, 0x02, 0x90, 0x04, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x90, 0x60, 0x1f, 0x01, 0x60, 0x20, 0x90, 0x04, 0x81, 0x01, 0x92, 0x82, 0x60, 0x1f, 0x10, 0x61, 0x14, 0x0c, 0x57, 0x80, 0x51, 0x60, 0xff, 0x19, 0x16, 0x83, 0x80, 0x01, 0x17, 0x85, 0x55, 0x61, 0x14, 0x3a, 0x56, 0x5b, 0x82, 0x80, 0x01, 0x60, 0x01, 0x01, 0x85, 0x55, 0x82, 0x15, 0x61, 0x14, 0x3a, 0x57, 0x91, 0x82, 0x01, 0x5b, 0x82, 0x81, 0x11, 0x15, 0x61, 0x14, 0x39, 0x57, 0x82, 0x51, 0x82, 0x55, 0x91, 0x60, 0x20, 0x01, 0x91, 0x90, 0x60, 0x01, 0x01, 0x90, 0x61, 0x14, 0x1e, 0x56, 0x5b, 0x5b, 0x50, 0x90, 0x50, 0x61, 0x14, 0x47, 0x91, 0x90, 0x61, 0x15, 0x5c, 0x56, 0x5b, 0x50, 0x90, 0x56, 0x5b, 0x82, 0x80, 0x54, 0x60, 0x01, 0x81, 0x60, 0x01, 0x16, 0x15, 0x61, 0x01, 0x00, 0x02, 0x03, 0x16, 0x60, 0x02, 0x90, 0x04, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x90, 0x60, 0x1f, 0x01, 0x60, 0x20, 0x90, 0x04, 0x81, 0x01, 0x92, 0x82, 0x60, 0x1f, 0x10, 0x61, 0x14, 0x84, 0x57, 0x80, 0x54, 0x85, 0x55, 0x61, 0x14, 0xc1, 0x56, 0x5b, 0x82, 0x80, 0x01, 0x60, 0x01, 0x01, 0x85, 0x55, 0x82, 0x15, 0x61, 0x14, 0xc1, 0x57, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x91, 0x60, 0x1f, 0x01, 0x60, 0x20, 0x90, 0x04, 0x82, 0x01, 0x5b, 0x82, 0x81, 0x11, 0x15, 0x61, 0x14, 0xc0, 0x57, 0x82, 0x54, 0x82, 0x55, 0x91, 0x60, 0x01, 0x01, 0x91, 0x90, 0x60, 0x01, 0x01, 0x90, 0x61, 0x14, 0xa5, 0x56, 0x5b, 0x5b, 0x50, 0x90, 0x50, 0x61, 0x14, 0xce, 0x91, 0x90, 0x61, 0x15, 0x5c, 0x56, 0x5b, 0x50, 0x90, 0x56, 0x5b, 0x82, 0x80, 0x54, 0x82, 0x82, 0x55, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x90, 0x81, 0x01, 0x92, 0x82, 0x15, 0x61, 0x15, 0x4b, 0x57, 0x91, 0x60, 0x20, 0x02, 0x82, 0x01, 0x5b, 0x82, 0x81, 0x11, 0x15, 0x61, 0x15, 0x4a, 0x57, 0x82, 0x51, 0x82, 0x60, 0x00, 0x61, 0x01, 0x00, 0x0a, 0x81, 0x54, 0x81, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0x19, 0x16, 0x90, 0x83, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x02, 0x17, 0x90, 0x55, 0x50, 0x91, 0x60, 0x20, 0x01, 0x91, 0x90, 0x60, 0x01, 0x01, 0x90, 0x61, 0x14, 0xf2, 0x56, 0x5b, 0x5b, 0x50, 0x90, 0x50, 0x61, 0x15, 0x58, 0x91, 0x90, 0x61, 0x15, 0x81, 0x56, 0x5b, 0x50, 0x90, 0x56, 0x5b, 0x61, 0x15, 0x7e, 0x91, 0x90, 0x5b, 0x80, 0x82, 0x11, 0x15, 0x61, 0x15, 0x7a, 0x57, 0x60, 0x00, 0x81, 0x60, 0x00, 0x90, 0x55, 0x50, 0x60, 0x01, 0x01, 0x61, 0x15, 0x62, 0x56, 0x5b, 0x50, 0x90, 0x56, 0x5b, 0x90, 0x56, 0x5b, 0x61, 0x15, 0xc1, 0x91, 0x90, 0x5b, 0x80, 0x82, 0x11, 0x15, 0x61, 0x15, 0xbd, 0x57, 0x60, 0x00, 0x81, 0x81, 0x61, 0x01, 0x00, 0x0a, 0x81, 0x54, 0x90, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0x19, 0x16, 0x90, 0x55, 0x50, 0x60, 0x01, 0x01, 0x61, 0x15, 0x87, 0x56, 0x5b, 0x50, 0x90, 0x56, 0x5b, 0x90, 0x56, 0x00, 0xa1, 0x65, 0x62, 0x7a, 0x7a, 0x72, 0x30, 0x58, 0x20, 0xa8, 0xfb, 0x9f, 0x06, 0x53, 0x3d, 0xb9, 0x44, 0x22, 0x03, 0x33, 0x2b, 0xcb, 0x5c, 0x2e, 0xdf, 0x68, 0xb6, 0x99, 0xd5, 0x4b, 0x7d, 0xb0, 0xbe, 0x9b, 0x1c, 0xa7, 0x85, 0x28, 0x47, 0x5c, 0x18, 0x00, 0x29] From 1fb531a111eda26e63669bee9a1d53ad9a1d350d Mon Sep 17 00:00:00 2001 From: Liam Noroian Date: Mon, 15 Nov 2021 15:22:48 -0800 Subject: [PATCH 75/96] updating xgt evaluator --- libraries/chain/xgt_evaluator.cpp | 288 +++++++++++++++--------------- 1 file changed, 144 insertions(+), 144 deletions(-) diff --git a/libraries/chain/xgt_evaluator.cpp b/libraries/chain/xgt_evaluator.cpp index dd77e9f4..b9a17b83 100644 --- a/libraries/chain/xgt_evaluator.cpp +++ b/libraries/chain/xgt_evaluator.cpp @@ -1059,6 +1059,149 @@ void contract_create_evaluator::do_apply( const contract_create_operation& op ) // Forward declaration machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type o, wallet_name_type c, contract_hash_type contract_hash, map& storage); +std::map< uint64_t, std::function > energy_cost { + // [] == scoped variables, () == params, -> optional return type, {} == function body + {machine::stop_opcode, [](machine::machine& m){ return 0; }}, + {machine::add_opcode, [](machine::machine& m){ return 3; }}, + {machine::mul_opcode, [](machine::machine& m){ return 5; }}, + {machine::sub_opcode, [](machine::machine& m){ return 3; }}, + {machine::div_opcode, [](machine::machine& m){ return 5; }}, + {machine::sdiv_opcode, [](machine::machine& m){ return 5; }}, + {machine::mod_opcode, [](machine::machine& m){ return 5; }}, + {machine::smod_opcode, [](machine::machine& m){ return 5; }}, + {machine::addmod_opcode, [](machine::machine& m){ return 8; }}, + {machine::mulmod_opcode, [](machine::machine& m){ return 8; }}, + {machine::exp_opcode, [](machine::machine& m){ return 0; }}, // TODO -- Exp -- variable + {machine::signextend_opcode, [](machine::machine& m){ return 5; }}, + {machine::lt_opcode, [](machine::machine& m){ return 3; }}, + {machine::gt_opcode, [](machine::machine& m){ return 3; }}, + {machine::slt_opcode, [](machine::machine& m){ return 3; }}, + {machine::sgt_opcode, [](machine::machine& m){ return 3; }}, + {machine::eq_opcode, [](machine::machine& m){ return 3; }}, + {machine::iszero_opcode, [](machine::machine& m){ return 3; }}, + {machine::and_opcode, [](machine::machine& m){ return 3; }}, + {machine::or_opcode, [](machine::machine& m){ return 3; }}, + {machine::xor_opcode, [](machine::machine& m){ return 3; }}, + {machine::not_opcode, [](machine::machine& m){ return 3; }}, + {machine::byte_opcode, [](machine::machine& m){ return 3; }}, + {machine::shl_opcode, [](machine::machine& m){ return 3; }}, + {machine::shr_opcode, [](machine::machine& m){ return 3; }}, + {machine::sar_opcode, [](machine::machine& m){ return 3; }}, + {machine::sha3_opcode, [](machine::machine& m){ return 0; }}, // TODO -- SHA3 -- variab; le + {machine::address_opcode, [](machine::machine& m){ return 2; }}, + {machine::balance_opcode, [](machine::machine& m){ return 700; }}, + {machine::origin_opcode, [](machine::machine& m){ return 2; }}, + {machine::caller_opcode, [](machine::machine& m){ return 2; }}, + {machine::callvalue_opcode, [](machine::machine& m){ return 2; }}, + {machine::calldataload_opcode, [](machine::machine& m){ return 3; }}, + {machine::calldatasize_opcode, [](machine::machine& m){ return 2; }}, + {machine::calldatacopy_opcode, [](machine::machine& m){ return 0; }}, // TODO -- calldatacoy -- variab; le + {machine::codesize_opcode, [](machine::machine& m){ return 2; }}, + {machine::codecopy_opcode, [](machine::machine& m){ return 0; }}, // TODO -- codecopy -- variab; le + {machine::energyprice_opcode, [](machine::machine& m){ return 2; }}, + {machine::extcodesize_opcode, [](machine::machine& m){ return 700; }}, + {machine::extcodecopy_opcode, [](machine::machine& m){ return 0; }}, // TODO -- extcodecopy -- variab; le + {machine::returndatasize_opcode, [](machine::machine& m){ return 2; }}, + {machine::returndatacopy_opcode, [](machine::machine& m){ return 0; }}, // TODO -- returndatacopy -- variab; le + {machine::extcodehash_opcode, [](machine::machine& m){ return 700; }}, + {machine::blockhash_opcode, [](machine::machine& m){ return 20; }}, + {machine::coinbase_opcode, [](machine::machine& m){ return 2; }}, + {machine::timestamp_opcode, [](machine::machine& m){ return 2; }}, + {machine::number_opcode, [](machine::machine& m){ return 2; }}, + {machine::difficulty_opcode, [](machine::machine& m){ return 2; }}, + {machine::energylimit_opcode, [](machine::machine& m){ return 2; }}, + {machine::pop_opcode, [](machine::machine& m){ return 3; }}, + {machine::mload_opcode, [](machine::machine& m){ return 3; }}, + {machine::mstore_opcode, [](machine::machine& m){ return 3; }}, + {machine::mstore8_opcode, [](machine::machine& m){ return 3; }}, + {machine::sload_opcode, [](machine::machine& m){ return 800; }}, + {machine::sstore_opcode, [](machine::machine& m){ return 0; }}, // TODO -- sstore -- variab; le + {machine::jump_opcode, [](machine::machine& m){ return 8; }}, + {machine::jumpi_opcode, [](machine::machine& m){ return 10; }}, + {machine::pc_opcode, [](machine::machine& m){ return 2; }}, + {machine::msize_opcode, [](machine::machine& m){ return 2; }}, + {machine::energy_opcode, [](machine::machine& m){ return 2; }}, + {machine::jumpdest_opcode, [](machine::machine& m){ return 1; }}, + {machine::push1_opcode, [](machine::machine& m){ return 3; }}, + {machine::push2_opcode, [](machine::machine& m){ return 3; }}, + {machine::push3_opcode, [](machine::machine& m){ return 3; }}, + {machine::push4_opcode, [](machine::machine& m){ return 3; }}, + {machine::push5_opcode, [](machine::machine& m){ return 3; }}, + {machine::push6_opcode, [](machine::machine& m){ return 3; }}, + {machine::push7_opcode, [](machine::machine& m){ return 3; }}, + {machine::push8_opcode, [](machine::machine& m){ return 3; }}, + {machine::push9_opcode, [](machine::machine& m){ return 3; }}, + {machine::push10_opcode, [](machine::machine& m){ return 3; }}, + {machine::push11_opcode, [](machine::machine& m){ return 3; }}, + {machine::push12_opcode, [](machine::machine& m){ return 3; }}, + {machine::push13_opcode, [](machine::machine& m){ return 3; }}, + {machine::push14_opcode, [](machine::machine& m){ return 3; }}, + {machine::push15_opcode, [](machine::machine& m){ return 3; }}, + {machine::push16_opcode, [](machine::machine& m){ return 3; }}, + {machine::push17_opcode, [](machine::machine& m){ return 3; }}, + {machine::push18_opcode, [](machine::machine& m){ return 3; }}, + {machine::push19_opcode, [](machine::machine& m){ return 3; }}, + {machine::push20_opcode, [](machine::machine& m){ return 3; }}, + {machine::push21_opcode, [](machine::machine& m){ return 3; }}, + {machine::push22_opcode, [](machine::machine& m){ return 3; }}, + {machine::push23_opcode, [](machine::machine& m){ return 3; }}, + {machine::push24_opcode, [](machine::machine& m){ return 3; }}, + {machine::push25_opcode, [](machine::machine& m){ return 3; }}, + {machine::push26_opcode, [](machine::machine& m){ return 3; }}, + {machine::push27_opcode, [](machine::machine& m){ return 3; }}, + {machine::push28_opcode, [](machine::machine& m){ return 3; }}, + {machine::push29_opcode, [](machine::machine& m){ return 3; }}, + {machine::push30_opcode, [](machine::machine& m){ return 3; }}, + {machine::push31_opcode, [](machine::machine& m){ return 3; }}, + {machine::push32_opcode, [](machine::machine& m){ return 3; }}, + {machine::dup1_opcode, [](machine::machine& m){ return 3; }}, + {machine::dup2_opcode, [](machine::machine& m){ return 3; }}, + {machine::dup3_opcode, [](machine::machine& m){ return 3; }}, + {machine::dup4_opcode, [](machine::machine& m){ return 3; }}, + {machine::dup5_opcode, [](machine::machine& m){ return 3; }}, + {machine::dup6_opcode, [](machine::machine& m){ return 3; }}, + {machine::dup7_opcode, [](machine::machine& m){ return 3; }}, + {machine::dup8_opcode, [](machine::machine& m){ return 3; }}, + {machine::dup9_opcode, [](machine::machine& m){ return 3; }}, + {machine::dup10_opcode, [](machine::machine& m){ return 3; }}, + {machine::dup11_opcode, [](machine::machine& m){ return 3; }}, + {machine::dup12_opcode, [](machine::machine& m){ return 3; }}, + {machine::dup13_opcode, [](machine::machine& m){ return 3; }}, + {machine::dup14_opcode, [](machine::machine& m){ return 3; }}, + {machine::dup15_opcode, [](machine::machine& m){ return 3; }}, + {machine::dup16_opcode, [](machine::machine& m){ return 3; }}, + {machine::swap1_opcode, [](machine::machine& m){ return 3; }}, + {machine::swap2_opcode, [](machine::machine& m){ return 3; }}, + {machine::swap3_opcode, [](machine::machine& m){ return 3; }}, + {machine::swap4_opcode, [](machine::machine& m){ return 3; }}, + {machine::swap5_opcode, [](machine::machine& m){ return 3; }}, + {machine::swap6_opcode, [](machine::machine& m){ return 3; }}, + {machine::swap7_opcode, [](machine::machine& m){ return 3; }}, + {machine::swap8_opcode, [](machine::machine& m){ return 3; }}, + {machine::swap9_opcode, [](machine::machine& m){ return 3; }}, + {machine::swap10_opcode, [](machine::machine& m){ return 3; }}, + {machine::swap11_opcode, [](machine::machine& m){ return 3; }}, + {machine::swap12_opcode, [](machine::machine& m){ return 3; }}, + {machine::swap13_opcode, [](machine::machine& m){ return 3; }}, + {machine::swap14_opcode, [](machine::machine& m){ return 3; }}, + {machine::swap15_opcode, [](machine::machine& m){ return 3; }}, + {machine::swap16_opcode, [](machine::machine& m){ return 3; }}, + {machine::log0_opcode, [](machine::machine& m){ return 0; }}, // TODO -- log0 -- variable + {machine::log1_opcode, [](machine::machine& m){ return 0; }}, // TODO -- log1 -- variable + {machine::log2_opcode, [](machine::machine& m){ return 0; }}, // TODO -- log2 -- variable + {machine::log3_opcode, [](machine::machine& m){ return 0; }}, // TODO -- log3 -- variable + {machine::log4_opcode, [](machine::machine& m){ return 0; }}, // TODO -- log4 -- variable + {machine::create_opcode, [](machine::machine& m){ return 0; }}, // TODO -- create -- variable + {machine::call_opcode, [](machine::machine& m){ return 0; }}, // TODO -- call -- variable + {machine::callcode_opcode, [](machine::machine& m){ return 0; }}, // TODO -- callcode -- variable + {machine::return_opcode, [](machine::machine& m){ return 0; }}, + {machine::delegatecall_opcode, [](machine::machine& m){ return 0; }}, // TODO -- delegatecall -- variable + {machine::create2_opcode, [](machine::machine& m){ return 0; }}, // TODO -- create2 -- variable + {machine::staticcall_opcode, [](machine::machine& m){ return 0; }}, // TODO -- staticcall -- variable + {machine::revert_opcode, [](machine::machine& m){ return 0; }}, + {machine::selfdestruct_opcode, [](machine::machine& m){ return 0; }} // TODO -- selfdestruct -- variable +}; + std::vector contract_invoke(chain::database& _db, wallet_name_type o, wallet_name_type caller, contract_hash_type contract_hash, uint64_t energy,std::vector args, map< fc::sha256, fc::sha256 >& storage) { wlog("contract_invoke another contract ${w}", ("w",contract_hash)); @@ -1110,7 +1253,7 @@ std::vector contract_invoke(chain::database& _db, wallet_name_typ std::cerr << "\e[36m" << "LOG: " << line << "\e[0m" << std::endl; std::cout << m.to_json() << std::endl; - const wallet_object& wallet = _db.get_account(op.caller); + const wallet_object& wallet = _db.get_account(caller); uint32_t energy_regen_period = XGT_ENERGY_REGENERATION_SECONDS; // TODO: Hardcode this for now (should be a constant I think) _db.modify(wallet, [&](wallet_object& w) @@ -1340,149 +1483,6 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type return adapter; } -std::map< uint64_t, std::function > energy_cost { - // [] == scoped variables, () == params, -> optional return type, {} == function body - {machine::stop_opcode, [](machine::machine& m){ return 0; }}, - {machine::add_opcode, [](machine::machine& m){ return 3; }}, - {machine::mul_opcode, [](machine::machine& m){ return 5; }}, - {machine::sub_opcode, [](machine::machine& m){ return 3; }}, - {machine::div_opcode, [](machine::machine& m){ return 5; }}, - {machine::sdiv_opcode, [](machine::machine& m){ return 5; }}, - {machine::mod_opcode, [](machine::machine& m){ return 5; }}, - {machine::smod_opcode, [](machine::machine& m){ return 5; }}, - {machine::addmod_opcode, [](machine::machine& m){ return 8; }}, - {machine::mulmod_opcode, [](machine::machine& m){ return 8; }}, - {machine::exp_opcode, [](machine::machine& m){ return 0; }}, // TODO -- Exp -- variable - {machine::signextend_opcode, [](machine::machine& m){ return 5; }}, - {machine::lt_opcode, [](machine::machine& m){ return 3; }}, - {machine::gt_opcode, [](machine::machine& m){ return 3; }}, - {machine::slt_opcode, [](machine::machine& m){ return 3; }}, - {machine::sgt_opcode, [](machine::machine& m){ return 3; }}, - {machine::eq_opcode, [](machine::machine& m){ return 3; }}, - {machine::iszero_opcode, [](machine::machine& m){ return 3; }}, - {machine::and_opcode, [](machine::machine& m){ return 3; }}, - {machine::or_opcode, [](machine::machine& m){ return 3; }}, - {machine::xor_opcode, [](machine::machine& m){ return 3; }}, - {machine::not_opcode, [](machine::machine& m){ return 3; }}, - {machine::byte_opcode, [](machine::machine& m){ return 3; }}, - {machine::shl_opcode, [](machine::machine& m){ return 3; }}, - {machine::shr_opcode, [](machine::machine& m){ return 3; }}, - {machine::sar_opcode, [](machine::machine& m){ return 3; }}, - {machine::sha3_opcode, [](machine::machine& m){ return 0; }}, // TODO -- SHA3 -- variab; le - {machine::address_opcode, [](machine::machine& m){ return 2; }}, - {machine::balance_opcode, [](machine::machine& m){ return 700; }}, - {machine::origin_opcode, [](machine::machine& m){ return 2; }}, - {machine::caller_opcode, [](machine::machine& m){ return 2; }}, - {machine::callvalue_opcode, [](machine::machine& m){ return 2; }}, - {machine::calldataload_opcode, [](machine::machine& m){ return 3; }}, - {machine::calldatasize_opcode, [](machine::machine& m){ return 2; }}, - {machine::calldatacopy_opcode, [](machine::machine& m){ return 0; }}, // TODO -- calldatacoy -- variab; le - {machine::codesize_opcode, [](machine::machine& m){ return 2; }}, - {machine::codecopy_opcode, [](machine::machine& m){ return 0; }}, // TODO -- codecopy -- variab; le - {machine::energyprice_opcode, [](machine::machine& m){ return 2; }}, - {machine::extcodesize_opcode, [](machine::machine& m){ return 700; }}, - {machine::extcodecopy_opcode, [](machine::machine& m){ return 0; }}, // TODO -- extcodecopy -- variab; le - {machine::returndatasize_opcode, [](machine::machine& m){ return 2; }}, - {machine::returndatacopy_opcode, [](machine::machine& m){ return 0; }}, // TODO -- returndatacopy -- variab; le - {machine::extcodehash_opcode, [](machine::machine& m){ return 700; }}, - {machine::blockhash_opcode, [](machine::machine& m){ return 20; }}, - {machine::coinbase_opcode, [](machine::machine& m){ return 2; }}, - {machine::timestamp_opcode, [](machine::machine& m){ return 2; }}, - {machine::number_opcode, [](machine::machine& m){ return 2; }}, - {machine::difficulty_opcode, [](machine::machine& m){ return 2; }}, - {machine::energylimit_opcode, [](machine::machine& m){ return 2; }}, - {machine::pop_opcode, [](machine::machine& m){ return 3; }}, - {machine::mload_opcode, [](machine::machine& m){ return 3; }}, - {machine::mstore_opcode, [](machine::machine& m){ return 3; }}, - {machine::mstore8_opcode, [](machine::machine& m){ return 3; }}, - {machine::sload_opcode, [](machine::machine& m){ return 800; }}, - {machine::sstore_opcode, [](machine::machine& m){ return 0; }}, // TODO -- sstore -- variab; le - {machine::jump_opcode, [](machine::machine& m){ return 8; }}, - {machine::jumpi_opcode, [](machine::machine& m){ return 10; }}, - {machine::pc_opcode, [](machine::machine& m){ return 2; }}, - {machine::msize_opcode, [](machine::machine& m){ return 2; }}, - {machine::energy_opcode, [](machine::machine& m){ return 2; }}, - {machine::jumpdest_opcode, [](machine::machine& m){ return 1; }}, - {machine::push1_opcode, [](machine::machine& m){ return 3; }}, - {machine::push2_opcode, [](machine::machine& m){ return 3; }}, - {machine::push3_opcode, [](machine::machine& m){ return 3; }}, - {machine::push4_opcode, [](machine::machine& m){ return 3; }}, - {machine::push5_opcode, [](machine::machine& m){ return 3; }}, - {machine::push6_opcode, [](machine::machine& m){ return 3; }}, - {machine::push7_opcode, [](machine::machine& m){ return 3; }}, - {machine::push8_opcode, [](machine::machine& m){ return 3; }}, - {machine::push9_opcode, [](machine::machine& m){ return 3; }}, - {machine::push10_opcode, [](machine::machine& m){ return 3; }}, - {machine::push11_opcode, [](machine::machine& m){ return 3; }}, - {machine::push12_opcode, [](machine::machine& m){ return 3; }}, - {machine::push13_opcode, [](machine::machine& m){ return 3; }}, - {machine::push14_opcode, [](machine::machine& m){ return 3; }}, - {machine::push15_opcode, [](machine::machine& m){ return 3; }}, - {machine::push16_opcode, [](machine::machine& m){ return 3; }}, - {machine::push17_opcode, [](machine::machine& m){ return 3; }}, - {machine::push18_opcode, [](machine::machine& m){ return 3; }}, - {machine::push19_opcode, [](machine::machine& m){ return 3; }}, - {machine::push20_opcode, [](machine::machine& m){ return 3; }}, - {machine::push21_opcode, [](machine::machine& m){ return 3; }}, - {machine::push22_opcode, [](machine::machine& m){ return 3; }}, - {machine::push23_opcode, [](machine::machine& m){ return 3; }}, - {machine::push24_opcode, [](machine::machine& m){ return 3; }}, - {machine::push25_opcode, [](machine::machine& m){ return 3; }}, - {machine::push26_opcode, [](machine::machine& m){ return 3; }}, - {machine::push27_opcode, [](machine::machine& m){ return 3; }}, - {machine::push28_opcode, [](machine::machine& m){ return 3; }}, - {machine::push29_opcode, [](machine::machine& m){ return 3; }}, - {machine::push30_opcode, [](machine::machine& m){ return 3; }}, - {machine::push31_opcode, [](machine::machine& m){ return 3; }}, - {machine::push32_opcode, [](machine::machine& m){ return 3; }}, - {machine::dup1_opcode, [](machine::machine& m){ return 3; }}, - {machine::dup2_opcode, [](machine::machine& m){ return 3; }}, - {machine::dup3_opcode, [](machine::machine& m){ return 3; }}, - {machine::dup4_opcode, [](machine::machine& m){ return 3; }}, - {machine::dup5_opcode, [](machine::machine& m){ return 3; }}, - {machine::dup6_opcode, [](machine::machine& m){ return 3; }}, - {machine::dup7_opcode, [](machine::machine& m){ return 3; }}, - {machine::dup8_opcode, [](machine::machine& m){ return 3; }}, - {machine::dup9_opcode, [](machine::machine& m){ return 3; }}, - {machine::dup10_opcode, [](machine::machine& m){ return 3; }}, - {machine::dup11_opcode, [](machine::machine& m){ return 3; }}, - {machine::dup12_opcode, [](machine::machine& m){ return 3; }}, - {machine::dup13_opcode, [](machine::machine& m){ return 3; }}, - {machine::dup14_opcode, [](machine::machine& m){ return 3; }}, - {machine::dup15_opcode, [](machine::machine& m){ return 3; }}, - {machine::dup16_opcode, [](machine::machine& m){ return 3; }}, - {machine::swap1_opcode, [](machine::machine& m){ return 3; }}, - {machine::swap2_opcode, [](machine::machine& m){ return 3; }}, - {machine::swap3_opcode, [](machine::machine& m){ return 3; }}, - {machine::swap4_opcode, [](machine::machine& m){ return 3; }}, - {machine::swap5_opcode, [](machine::machine& m){ return 3; }}, - {machine::swap6_opcode, [](machine::machine& m){ return 3; }}, - {machine::swap7_opcode, [](machine::machine& m){ return 3; }}, - {machine::swap8_opcode, [](machine::machine& m){ return 3; }}, - {machine::swap9_opcode, [](machine::machine& m){ return 3; }}, - {machine::swap10_opcode, [](machine::machine& m){ return 3; }}, - {machine::swap11_opcode, [](machine::machine& m){ return 3; }}, - {machine::swap12_opcode, [](machine::machine& m){ return 3; }}, - {machine::swap13_opcode, [](machine::machine& m){ return 3; }}, - {machine::swap14_opcode, [](machine::machine& m){ return 3; }}, - {machine::swap15_opcode, [](machine::machine& m){ return 3; }}, - {machine::swap16_opcode, [](machine::machine& m){ return 3; }}, - {machine::log0_opcode, [](machine::machine& m){ return 0; }}, // TODO -- log0 -- variable - {machine::log1_opcode, [](machine::machine& m){ return 0; }}, // TODO -- log1 -- variable - {machine::log2_opcode, [](machine::machine& m){ return 0; }}, // TODO -- log2 -- variable - {machine::log3_opcode, [](machine::machine& m){ return 0; }}, // TODO -- log3 -- variable - {machine::log4_opcode, [](machine::machine& m){ return 0; }}, // TODO -- log4 -- variable - {machine::create_opcode, [](machine::machine& m){ return 0; }}, // TODO -- create -- variable - {machine::call_opcode, [](machine::machine& m){ return 0; }}, // TODO -- call -- variable - {machine::callcode_opcode, [](machine::machine& m){ return 0; }}, // TODO -- callcode -- variable - {machine::return_opcode, [](machine::machine& m){ return 0; }}, - {machine::delegatecall_opcode, [](machine::machine& m){ return 0; }}, // TODO -- delegatecall -- variable - {machine::create2_opcode, [](machine::machine& m){ return 0; }}, // TODO -- create2 -- variable - {machine::staticcall_opcode, [](machine::machine& m){ return 0; }}, // TODO -- staticcall -- variable - {machine::revert_opcode, [](machine::machine& m){ return 0; }}, - {machine::selfdestruct_opcode, [](machine::machine& m){ return 0; }} // TODO -- selfdestruct -- variable -}; - void contract_invoke_evaluator::do_apply( const contract_invoke_operation& op ) { wlog("contract_invoke ${w}", ("w",op.contract_hash)); From 010469da3353eaa54a49ac7e168c3c175b19ca31 Mon Sep 17 00:00:00 2001 From: Liam Noroian Date: Tue, 16 Nov 2021 10:12:57 -0800 Subject: [PATCH 76/96] Fixing contract storage db creation --- libraries/chain/xgt_evaluator.cpp | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/libraries/chain/xgt_evaluator.cpp b/libraries/chain/xgt_evaluator.cpp index b9a17b83..969257f7 100644 --- a/libraries/chain/xgt_evaluator.cpp +++ b/libraries/chain/xgt_evaluator.cpp @@ -1351,6 +1351,8 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type }); else _db.create< contract_storage_object >([&](contract_storage_object& cs) { + cs.contract = contract_hash; + cs.caller = caller; cs.data = storage; }); @@ -1382,6 +1384,8 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type }); else _db.create< contract_storage_object >([&](contract_storage_object& cs) { + cs.contract = contract_hash; + cs.caller = c; cs.data = storage; }); @@ -1485,33 +1489,37 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type void contract_invoke_evaluator::do_apply( const contract_invoke_operation& op ) { - wlog("contract_invoke ${w}", ("w",op.contract_hash)); - const contract_hash_type contract_hash = op.contract_hash; const auto& c = _db.get_contract(contract_hash); uint64_t energy = 0; // TODO const contract_storage_object* cs = _db.find_contract_storage(contract_hash, op.caller); map< fc::sha256, fc::sha256 > storage; - if (cs) + if (cs != nullptr) { storage = cs->data; - else + } + else { storage = map< fc::sha256, fc::sha256 >(); + } std::vector unsigned_args; std::copy(op.args.begin(), op.args.end(), std::back_inserter(unsigned_args)); auto result = contract_invoke(_db, c.owner, op.caller, contract_hash, energy, unsigned_args, storage); - if (cs) + if (cs != nullptr) { _db.modify< contract_storage_object >(*cs, [&](contract_storage_object& cs) { cs.contract = contract_hash; cs.caller = op.caller; cs.data = storage; }); - else + } + else { _db.create< contract_storage_object >([&](contract_storage_object& cs) { + cs.contract = contract_hash; + cs.caller = op.caller; cs.data = storage; }); + } } } } // xgt::chain From c4fca641e19eca7ab3096ebade6b7a39f18473e1 Mon Sep 17 00:00:00 2001 From: Liam Noroian Date: Sun, 5 Dec 2021 00:01:54 -0800 Subject: [PATCH 77/96] Smart contract invokation --- .../chain/include/xgt/chain/wallet_object.hpp | 1 + libraries/chain/xgt_evaluator.cpp | 87 +++- .../include/xgt/protocol/xgt_operations.hpp | 4 +- libraries/vendor/xgtvm/libraries/machine.cpp | 401 +++++++++++------- libraries/vendor/xgtvm/libraries/machine.hpp | 7 +- libraries/vendor/xgtvm/programs/xgtvm.cpp | 2 +- .../vendor/xgtvm/programs/xgtvm_tests.cpp | 159 +++---- 7 files changed, 408 insertions(+), 253 deletions(-) diff --git a/libraries/chain/include/xgt/chain/wallet_object.hpp b/libraries/chain/include/xgt/chain/wallet_object.hpp index 51b81373..d8806883 100644 --- a/libraries/chain/include/xgt/chain/wallet_object.hpp +++ b/libraries/chain/include/xgt/chain/wallet_object.hpp @@ -90,6 +90,7 @@ namespace xgt { namespace chain { id_type id; wallet_name_type account; + fc::ripemd160 address_ripemd160; shared_authority recovery; ///< used for backup control, can set recovery or money shared_authority money; ///< used for all monetary operations, can set money or social diff --git a/libraries/chain/xgt_evaluator.cpp b/libraries/chain/xgt_evaluator.cpp index 969257f7..1a1301ee 100644 --- a/libraries/chain/xgt_evaluator.cpp +++ b/libraries/chain/xgt_evaluator.cpp @@ -18,6 +18,9 @@ #include #include +#include +#include +#include #include @@ -206,6 +209,7 @@ void wallet_create_evaluator::do_apply( const wallet_create_operation& o ) auth.recovery = o.recovery; auth.money = o.money; auth.social = o.social; + auth.address_ripemd160 = o.address_ripemd160; auth.last_recovery_update = fc::time_point_sec::min(); }); } @@ -1023,6 +1027,7 @@ fc::ripemd160 generate_random_ripemd160() return fc::ripemd160::hash(buf, buflen); } +// XXX Needs work -- does not consistently convert values boost::multiprecision::uint256_t ripemd160_to_uint256_t(fc::ripemd160 h) { boost::multiprecision::uint256_t n(0); @@ -1199,15 +1204,43 @@ std::map< uint64_t, std::function > energy_cost { {machine::create2_opcode, [](machine::machine& m){ return 0; }}, // TODO -- create2 -- variable {machine::staticcall_opcode, [](machine::machine& m){ return 0; }}, // TODO -- staticcall -- variable {machine::revert_opcode, [](machine::machine& m){ return 0; }}, + {machine::invalid_opcode, [](machine::machine& m){ return 0; }}, {machine::selfdestruct_opcode, [](machine::machine& m){ return 0; }} // TODO -- selfdestruct -- variable }; -std::vector contract_invoke(chain::database& _db, wallet_name_type o, wallet_name_type caller, contract_hash_type contract_hash, uint64_t energy,std::vector args, map< fc::sha256, fc::sha256 >& storage) +boost::multiprecision::uint256_t address_to_uint256_t(const std::string& base58str) { + std::string prefix( XGT_ADDRESS_PREFIX ); + + const size_t prefix_len = prefix.size(); + auto b58 = base58str.substr( prefix_len ); + auto r160 = fc::ripemd160::hash(b58); + + std::stringstream ss; + ss << std::hex << r160.str(); + boost::multiprecision::uint256_t x; + ss >> x; + return x; +}; + +std::vector contract_invoke(chain::database& _db, wallet_name_type o, wallet_name_type caller, contract_hash_type contract_hash, uint64_t value, uint64_t energy, std::vector args, map< fc::sha256, fc::sha256 >& storage) { wlog("contract_invoke another contract ${w}", ("w",contract_hash)); const auto& c = _db.get_contract(contract_hash); - - machine::message msg = {}; + const std::string& address_ref = std::string(caller); + + boost::multiprecision::uint256_t converted_address = address_to_uint256_t(address_ref); + + machine::message msg = { + 0, + 0, + 0, + converted_address, + converted_address, + value, + args.size(), + args, + 0 + }; const bool is_debug = true; const uint64_t block_timestamp = static_cast( _db.head_block_time().sec_since_epoch() ); @@ -1235,12 +1268,11 @@ std::vector contract_invoke(chain::database& _db, wallet_name_typ machine::chain_adapter adapter = make_chain_adapter(_db, c.owner, tx_origin, contract_hash, storage); machine::machine m(ctx, code, msg, adapter); - m.print_stack(); - std::string line; while (m.is_running()) { - std::cerr << "step\n"; + std::cerr << "step\n" << std::endl; + std::cerr << m.to_json() << std::endl; m.step(); auto energy_callback = energy_cost[m.get_current_opcode()]; // Calculate energy cost and add to total @@ -1262,9 +1294,25 @@ std::vector contract_invoke(chain::database& _db, wallet_name_typ w.energybar.use_energy( energy_cost_incurred ); }); + // TODO make return value public in machine + wlog("contract_invoke return value ${w}", ("w",m.get_return_value())); return m.get_return_value(); } +std::string inspect(std::vector words) +{ + std::stringstream ss; + ss << "["; + for (size_t i = 0; i < words.size(); i++) + { + ss << std::to_string(words.at(i)); + if (i != words.size() -1) + ss << ", "; + } + ss << "]"; + return ss.str(); +} + machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type o, wallet_name_type c, contract_hash_type contract_hash, map& storage) { std::string owner(o); @@ -1272,14 +1320,21 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type std::function< std::string(std::vector) > sha3 = [&](std::vector memory) -> std::string { - std::string message(memory.begin(), memory.end()); + std::stringstream ss; + std::string message; + for (int i = 0; i < 32; i++) { + message += std::to_string(memory[i]); + } unsigned char output[32]; SHA3_CTX ctx; keccak_init(&ctx); keccak_update(&ctx, (unsigned char*)message.c_str(), message.size()); keccak_final(&ctx, output); - std::string fin((char*)output, 32); - return fin; + for (size_t i = 0; i < 32; i++) { + ss << std::hex << (machine::opcode)output[i]; + } + // std::string fin((char*)output, 32); + return ss.str(); }; std::function< uint64_t(std::string) > get_balance = [&](std::string address) -> uint64_t @@ -1341,7 +1396,7 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type else storage = map< fc::sha256, fc::sha256 >(); - auto result = contract_invoke(_db, o, c, contract_hash, energy, args, storage); + auto result = contract_invoke(_db, o, c, contract_hash, energy, static_cast(value), args, storage); if (cs) _db.modify< contract_storage_object >(*cs, [&](contract_storage_object& cs) { @@ -1374,7 +1429,7 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type else storage = map< fc::sha256, fc::sha256 >(); - auto result = contract_invoke(_db, o, c, contract_hash, energy, args, storage); + auto result = contract_invoke(_db, o, c, contract_hash, energy, 0, args, storage); if (cs) _db.modify< contract_storage_object >(*cs, [&](contract_storage_object& cs) { @@ -1395,7 +1450,7 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type std::function< std::vector(std::string, uint64_t, std::vector) > contract_staticcall = [&](std::string address, uint64_t energy, std::vector args) -> std::vector { map< fc::sha256, fc::sha256 > storage; // Should this be empty, or just immutable for `staticcall`? - auto result = contract_invoke(_db, o, c, contract_hash, energy, args, storage); + auto result = contract_invoke(_db, o, c, contract_hash, energy, 0, args, storage); return result; }; @@ -1428,10 +1483,9 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type return true; }; - std::function< bool(std::vector) > contract_return = [&](std::vector memory) -> bool + std::function< std::vector(std::vector) > contract_return = [&](std::vector memory) -> std::vector { - // TODO - return true; + return memory; }; std::function< bool(std::string) > self_destruct = [&](std::string address) -> bool @@ -1494,6 +1548,7 @@ void contract_invoke_evaluator::do_apply( const contract_invoke_operation& op ) uint64_t energy = 0; // TODO const contract_storage_object* cs = _db.find_contract_storage(contract_hash, op.caller); + map< fc::sha256, fc::sha256 > storage; if (cs != nullptr) { storage = cs->data; @@ -1504,7 +1559,7 @@ void contract_invoke_evaluator::do_apply( const contract_invoke_operation& op ) std::vector unsigned_args; std::copy(op.args.begin(), op.args.end(), std::back_inserter(unsigned_args)); - auto result = contract_invoke(_db, c.owner, op.caller, contract_hash, energy, unsigned_args, storage); + auto result = contract_invoke(_db, c.owner, op.caller, contract_hash, energy, op.value, unsigned_args, storage); if (cs != nullptr) { _db.modify< contract_storage_object >(*cs, [&](contract_storage_object& cs) { diff --git a/libraries/protocol/include/xgt/protocol/xgt_operations.hpp b/libraries/protocol/include/xgt/protocol/xgt_operations.hpp index 6ecbaa17..9d344a9f 100644 --- a/libraries/protocol/include/xgt/protocol/xgt_operations.hpp +++ b/libraries/protocol/include/xgt/protocol/xgt_operations.hpp @@ -16,6 +16,7 @@ namespace xgt { namespace protocol { asset fee; wallet_name_type creator; wallet_name_type new_wallet_name; + fc::ripemd160 address_ripemd160; authority recovery; authority money; authority social; @@ -605,6 +606,7 @@ namespace xgt { namespace protocol { { wallet_name_type caller; contract_hash_type contract_hash; + uint64_t value; vector args; void validate()const; @@ -663,4 +665,4 @@ FC_REFLECT( xgt::protocol::recover_wallet_operation, (account_to_recover)(new_re FC_REFLECT( xgt::protocol::change_recovery_wallet_operation, (account_to_recover)(new_recovery_account)(extensions) ); FC_REFLECT( xgt::protocol::contract_create_operation, (owner)(code) ); -FC_REFLECT( xgt::protocol::contract_invoke_operation, (caller)(contract_hash)(args) ); +FC_REFLECT( xgt::protocol::contract_invoke_operation, (caller)(contract_hash)(value)(args) ); diff --git a/libraries/vendor/xgtvm/libraries/machine.cpp b/libraries/vendor/xgtvm/libraries/machine.cpp index 3cd904c2..ac2e75cd 100644 --- a/libraries/vendor/xgtvm/libraries/machine.cpp +++ b/libraries/vendor/xgtvm/libraries/machine.cpp @@ -23,12 +23,14 @@ namespace machine return bytes[n]; } - void set_byte(boost::multiprecision::uint256_t& x, int n, int v) + uint16_t get_bytes(boost::multiprecision::uint256_t x, int n) { std::vector bytes; boost::multiprecision::export_bits(x, std::back_inserter(bytes), 8); - bytes[n] = v; - boost::multiprecision::import_bits(x, bytes.begin(), bytes.end()); + if (x > 255) { + return ((uint16_t)bytes[n] << 8) | bytes[n + 1]; + } + return bytes[n]; } size_t uint256_t_to_size_t(boost::multiprecision::uint256_t& x) @@ -53,57 +55,49 @@ namespace machine big_word to_big_word(word a, word b) { - big_word va = 0; - set_byte(va, 0, a); - set_byte(va, 1, b); + big_word va = ((big_word)a << 8) | b; return va; } big_word to_big_word(word a, word b, word c, word d) { - big_word va = 0; - set_byte(va, 0, a); - set_byte(va, 1, b); - set_byte(va, 2, c); - set_byte(va, 3, d); - return va; + big_word va = ((big_word)a << 8) | b; + big_word vb = (va << 8) | c; + big_word vc = (vb << 8) | d; + return vc; } big_word to_big_word(word a, word b, word c, word d, word e, word f, word g, word h) { - big_word va = 0; - set_byte(va, 0, a); - set_byte(va, 1, b); - set_byte(va, 2, c); - set_byte(va, 3, d); - set_byte(va, 4, e); - set_byte(va, 5, f); - set_byte(va, 6, g); - set_byte(va, 7, h); - return va; + big_word va = ((big_word)a << 8) | b; + big_word vb = (va << 8) | c; + big_word vc = (vb << 8) | d; + big_word vd = (vc << 8) | e; + big_word ve = (vd << 8) | f; + big_word vf = (ve << 8) | g; + big_word vg = (vf << 8) | h; + return vg; } big_word to_big_word(word a, word b, word c, word d, word e, word f, word g, word h, word i, word j, word k, word l, word m, word n, word o, word p) { - big_word va = 0; - set_byte(va, 0, a); - set_byte(va, 1, b); - set_byte(va, 2, c); - set_byte(va, 3, d); - set_byte(va, 4, e); - set_byte(va, 5, f); - set_byte(va, 6, g); - set_byte(va, 7, h); - set_byte(va, 8, i); - set_byte(va, 9, j); - set_byte(va, 10, k); - set_byte(va, 11, l); - set_byte(va, 12, m); - set_byte(va, 13, n); - set_byte(va, 14, o); - set_byte(va, 15, p); - return va; + big_word va = ((big_word)a << 8) | b; + big_word vb = (va << 8) | c; + big_word vc = (vb << 8) | d; + big_word vd = (vc << 8) | e; + big_word ve = (vd << 8) | f; + big_word vf = (ve << 8) | g; + big_word vg = (vf << 8) | h; + big_word vh = (vg << 8) | i; + big_word vi = (vh << 8) | j; + big_word vj = (vi << 8) | k; + big_word vk = (vj << 8) | l; + big_word vl = (vk << 8) | m; + big_word vm = (vl << 8) | n; + big_word vn = (vm << 8) | o; + big_word vo = (vn << 8) | p; + return vo; } big_word to_big_word(word a, word b, word c, word d, word e, word f, word g, @@ -111,40 +105,48 @@ namespace machine word q, word r, word s, word t, word u, word v, word w, word x, word y, word z, word aa, word ab, word ac, word ad, word ae, word af) { - big_word va = 0; - set_byte(va, 0, a); - set_byte(va, 1, b); - set_byte(va, 2, c); - set_byte(va, 3, d); - set_byte(va, 4, e); - set_byte(va, 5, f); - set_byte(va, 6, g); - set_byte(va, 7, h); - set_byte(va, 8, i); - set_byte(va, 9, j); - set_byte(va, 10, k); - set_byte(va, 11, l); - set_byte(va, 12, m); - set_byte(va, 13, n); - set_byte(va, 14, o); - set_byte(va, 15, p); - set_byte(va, 16, q); - set_byte(va, 17, r); - set_byte(va, 18, s); - set_byte(va, 19, t); - set_byte(va, 20, u); - set_byte(va, 21, v); - set_byte(va, 22, w); - set_byte(va, 23, x); - set_byte(va, 24, y); - set_byte(va, 25, z); - set_byte(va, 26, aa); - set_byte(va, 27, ab); - set_byte(va, 28, ac); - set_byte(va, 29, ad); - set_byte(va, 30, ae); - set_byte(va, 31, af); - return va; + big_word va = ((big_word)a << 8) | b; + big_word vb = (va << 8) | c; + big_word vc = (vb << 8) | d; + big_word vd = (vc << 8) | e; + big_word ve = (vd << 8) | f; + big_word vf = (ve << 8) | g; + big_word vg = (vf << 8) | h; + big_word vh = (vg << 8) | i; + big_word vi = (vh << 8) | j; + big_word vj = (vi << 8) | k; + big_word vk = (vj << 8) | l; + big_word vl = (vk << 8) | m; + big_word vm = (vl << 8) | n; + big_word vn = (vm << 8) | o; + big_word vo = (vn << 8) | p; + big_word vp = (vo << 8) | q; + big_word vq = (vp << 8) | r; + big_word vr = (vq << 8) | s; + big_word vs = (vr << 8) | t; + big_word vt = (vs << 8) | u; + big_word vu = (vt << 8) | v; + big_word vv = (vu << 8) | w; + big_word vw = (vv << 8) | x; + big_word vx = (vw << 8) | y; + big_word vy = (vx << 8) | z; + big_word vz = (vy << 8) | aa; + big_word vaa = (vz << 8) | ab; + big_word vab = (vaa << 8) | ac; + big_word vac = (vab << 8) | ad; + big_word vad = (vac << 8) | ae; + big_word vae = (vad << 8) | af; + return vae; + } + + std::vector from_big_word(big_word a) + { + std::vector vec; + for (size_t i = 0; i < 31; i++) { + vec.push_back(static_cast(((a >>= (8 * i)) & 0xFF))); + } + + return vec; } std::string inspect(std::vector words) @@ -153,7 +155,6 @@ namespace machine ss << "["; for (size_t i = 0; i < words.size(); i++) { - // TODO: Print hex ss << std::to_string(words.at(i)); if (i != words.size() - 1) ss << ", "; @@ -172,7 +173,6 @@ namespace machine { it = words.find(i); if (it != words.end()) { - // TODO: Print hex ss << std::to_string(it->second); ss << ", "; } @@ -220,8 +220,6 @@ namespace machine stack.push_front(s); } - // TODO: Make better - // TODO: Return string instead? void machine::print_stack() { for (auto it = stack.cbegin(); it != stack.cend(); ++it) @@ -259,14 +257,19 @@ namespace machine word a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, aa, ab, ac, ad, ae, af; big_word va, vb, vc, vd, ve, vf, vg, vh, vi, vj, vk, vl, vm, vn, vo, vp, vq; + + word jumpdest_instruction; + opcode jumpdest_op; stack_variant sv; signed_big_word sa, sb, sc; size_t offset, dest_offset, length, code_size = 0; + std::vector vec1; std::vector contract_args; std::vector retval; std::vector ext_contract_code; std::vector::const_iterator first, last; std::string* ss; + std::stringstream sstream; switch (op) { case stop_opcode: @@ -278,6 +281,7 @@ namespace machine va = pop_word(); vb = pop_word(); vc = va + vb; + push_word(vc); break; case mul_opcode: @@ -298,7 +302,10 @@ namespace machine logger << "op div" << std::endl; va = pop_word(); vb = pop_word(); - vc = va / vb; + if (vb == 0) + push_word(word(0)); + else + vc = va / vb; push_word(vc); break; case sdiv_opcode: @@ -491,7 +498,9 @@ namespace machine } } - push_word( adapter.sha3( retval ) ); // hash + sstream << std::hex << adapter.sha3( retval ); + sstream >> vc; + push_word( vc ); // hash break; case address_opcode: @@ -537,15 +546,39 @@ namespace machine } va = to_big_word( - msg.input_data[offset + 7], - msg.input_data[offset + 6], - msg.input_data[offset + 5], - msg.input_data[offset + 4], - msg.input_data[offset + 3], - msg.input_data[offset + 2], + msg.input_data[offset + 0], msg.input_data[offset + 1], - msg.input_data[offset + 0] - ); + msg.input_data[offset + 2], + msg.input_data[offset + 3], + msg.input_data[offset + 4], + msg.input_data[offset + 5], + msg.input_data[offset + 6], + msg.input_data[offset + 7], + msg.input_data[offset + 8], + msg.input_data[offset + 9], + msg.input_data[offset + 10], + msg.input_data[offset + 11], + msg.input_data[offset + 12], + msg.input_data[offset + 13], + msg.input_data[offset + 14], + msg.input_data[offset + 15], + msg.input_data[offset + 16], + msg.input_data[offset + 17], + msg.input_data[offset + 18], + msg.input_data[offset + 19], + msg.input_data[offset + 20], + msg.input_data[offset + 21], + msg.input_data[offset + 22], + msg.input_data[offset + 23], + msg.input_data[offset + 24], + msg.input_data[offset + 25], + msg.input_data[offset + 26], + msg.input_data[offset + 27], + msg.input_data[offset + 28], + msg.input_data[offset + 29], + msg.input_data[offset + 30], + msg.input_data[offset + 31] + ); push_word(va); break; case calldatasize_opcode: @@ -702,17 +735,40 @@ namespace machine case mload_opcode: logger << "op mload" << std::endl; va = pop_word(); // offset - // TODO: Verify order vb = to_big_word( - memory[static_cast(va) + 7], - memory[static_cast(va) + 6], - memory[static_cast(va) + 5], - memory[static_cast(va) + 4], - memory[static_cast(va) + 3], - memory[static_cast(va) + 2], + memory[static_cast(va) + 0], memory[static_cast(va) + 1], - memory[static_cast(va) + 0] - ); + memory[static_cast(va) + 2], + memory[static_cast(va) + 3], + memory[static_cast(va) + 4], + memory[static_cast(va) + 5], + memory[static_cast(va) + 6], + memory[static_cast(va) + 7], + memory[static_cast(va) + 8], + memory[static_cast(va) + 9], + memory[static_cast(va) + 10], + memory[static_cast(va) + 11], + memory[static_cast(va) + 12], + memory[static_cast(va) + 13], + memory[static_cast(va) + 14], + memory[static_cast(va) + 15], + memory[static_cast(va) + 16], + memory[static_cast(va) + 17], + memory[static_cast(va) + 18], + memory[static_cast(va) + 19], + memory[static_cast(va) + 20], + memory[static_cast(va) + 21], + memory[static_cast(va) + 22], + memory[static_cast(va) + 23], + memory[static_cast(va) + 24], + memory[static_cast(va) + 25], + memory[static_cast(va) + 26], + memory[static_cast(va) + 27], + memory[static_cast(va) + 28], + memory[static_cast(va) + 29], + memory[static_cast(va) + 30], + memory[static_cast(va) + 31] + ); push_word(vb); break; case mstore_opcode: @@ -721,15 +777,40 @@ namespace machine vb = pop_word(); // value logger << "memory before: " << inspect(memory) << std::endl; - // TODO: Verify order - memory[static_cast(va) + 0] = get_byte(vb, 7); - memory[static_cast(va) + 1] = get_byte(vb, 6); - memory[static_cast(va) + 2] = get_byte(vb, 5); - memory[static_cast(va) + 3] = get_byte(vb, 4); - memory[static_cast(va) + 4] = get_byte(vb, 3); - memory[static_cast(va) + 5] = get_byte(vb, 2); - memory[static_cast(va) + 6] = get_byte(vb, 1); - memory[static_cast(va) + 7] = get_byte(vb, 0); + vec1 = from_big_word(vb); + + memory[static_cast(va) + 0] = vec1[31]; + memory[static_cast(va) + 1] = vec1[30]; + memory[static_cast(va) + 2] = vec1[29]; + memory[static_cast(va) + 3] = vec1[28]; + memory[static_cast(va) + 4] = vec1[27]; + memory[static_cast(va) + 5] = vec1[26]; + memory[static_cast(va) + 6] = vec1[25]; + memory[static_cast(va) + 7] = vec1[24]; + memory[static_cast(va) + 8] = vec1[23]; + memory[static_cast(va) + 9] = vec1[22]; + memory[static_cast(va) + 10] = vec1[21]; + memory[static_cast(va) + 11] = vec1[20]; + memory[static_cast(va) + 12] = vec1[19]; + memory[static_cast(va) + 13] = vec1[18]; + memory[static_cast(va) + 14] = vec1[17]; + memory[static_cast(va) + 15] = vec1[16]; + memory[static_cast(va) + 16] = vec1[15]; + memory[static_cast(va) + 17] = vec1[14]; + memory[static_cast(va) + 18] = vec1[13]; + memory[static_cast(va) + 19] = vec1[12]; + memory[static_cast(va) + 20] = vec1[11]; + memory[static_cast(va) + 21] = vec1[10]; + memory[static_cast(va) + 22] = vec1[9]; + memory[static_cast(va) + 23] = vec1[8]; + memory[static_cast(va) + 24] = vec1[7]; + memory[static_cast(va) + 25] = vec1[6]; + memory[static_cast(va) + 26] = vec1[5]; + memory[static_cast(va) + 27] = vec1[4]; + memory[static_cast(va) + 28] = vec1[3]; + memory[static_cast(va) + 29] = vec1[2]; + memory[static_cast(va) + 30] = vec1[1]; + memory[static_cast(va) + 31] = vec1[0]; logger << "memory after: " << inspect(memory) << std::endl; break; case mstore8_opcode: @@ -780,17 +861,24 @@ namespace machine case jump_opcode: logger << "op jump" << std::endl; va = pop_word(); // destination - if (code[get_byte(va, 0)] == jumpdest_opcode) - pc = get_byte(va, 0); + + jumpdest_instruction = code[get_bytes(va, 0)]; + jumpdest_op = (opcode)jumpdest_instruction; + if (jumpdest_op == jumpdest_opcode) + pc = get_bytes(va, 0); break; case jumpi_opcode: logger << "op jumpi" << std::endl; print_stack(); - va = pop_word(); - vb = pop_word(); - if (vb != 0) - if (code[get_byte(va, 0)] == jumpdest_opcode) - pc = get_byte(va, 0); + va = pop_word(); // destination + vb = pop_word(); // condition + + if (vb != 0) { + jumpdest_instruction = code[get_bytes(va, 0)]; + jumpdest_op = (opcode)jumpdest_instruction; + if (jumpdest_op == jumpdest_opcode) + pc = get_bytes(va, 0); + } break; case pc_opcode: logger << "op pc" << std::endl; @@ -820,7 +908,7 @@ namespace machine pc++; b = code[pc]; pc++; - va = to_big_word(0, 0, a, b); // TODO: Verify + va = to_big_word(a, b); push_word(va); break; case push3_opcode: @@ -831,7 +919,7 @@ namespace machine pc++; c = code[pc]; pc++; - va = to_big_word(0, a, b, c); // TODO: Verify + va = to_big_word(0, a, b, c); push_word(va); break; case push4_opcode: @@ -844,7 +932,7 @@ namespace machine pc++; d = code[pc]; pc++; - va = to_big_word(a, b, c, d); // TODO: Verify + va = to_big_word(a, b, c, d); push_word(va); break; case push5_opcode: @@ -859,7 +947,7 @@ namespace machine pc++; e = code[pc]; pc++; - va = to_big_word(0, 0, 0, a, b, c, d, e); // TODO: Verify + va = to_big_word(0, 0, 0, a, b, c, d, e); push_word(va); break; case push6_opcode: @@ -876,7 +964,7 @@ namespace machine pc++; f = code[pc]; pc++; - va = to_big_word(0, 0, a, b, c, d, e, f); // TODO: Verify + va = to_big_word(0, 0, a, b, c, d, e, f); push_word(va); break; case push7_opcode: @@ -895,7 +983,7 @@ namespace machine pc++; g = code[pc]; pc++; - va = to_big_word(0, a, b, c, d, e, f, g); // TODO: Verify + va = to_big_word(0, a, b, c, d, e, f, g); push_word(va); break; case push8_opcode: @@ -916,7 +1004,7 @@ namespace machine pc++; h = code[pc]; pc++; - va = to_big_word(a, b, c, d, e, f, g, h); // TODO: Verify + va = to_big_word(a, b, c, d, e, f, g, h); push_word(va); break; case push9_opcode: @@ -939,7 +1027,7 @@ namespace machine pc++; i = code[pc]; pc++; - va = to_big_word(0, 0, 0, 0, 0, 0, 0, a, b, c, d, e, f, g, h, i); // TODO: Verify + va = to_big_word(0, 0, 0, 0, 0, 0, 0, a, b, c, d, e, f, g, h, i); push_word(va); break; case push10_opcode: @@ -964,7 +1052,7 @@ namespace machine pc++; j = code[pc]; pc++; - va = to_big_word(0, 0, 0, 0, 0, 0, a, b, c, d, e, f, g, h, i, j); // TODO: Verify + va = to_big_word(0, 0, 0, 0, 0, 0, a, b, c, d, e, f, g, h, i, j); push_word(va); break; case push11_opcode: @@ -991,7 +1079,7 @@ namespace machine pc++; k = code[pc]; pc++; - va = to_big_word(0, 0, 0, 0, 0, a, b, c, d, e, f, g, h, i, j, k); // TODO: Verify + va = to_big_word(0, 0, 0, 0, 0, a, b, c, d, e, f, g, h, i, j, k); push_word(va); break; case push12_opcode: @@ -1020,7 +1108,7 @@ namespace machine pc++; l = code[pc]; pc++; - va = to_big_word(0, 0, 0, 0, a, b, c, d, e, f, g, h, i, j, k, l); // TODO: Verify + va = to_big_word(0, 0, 0, 0, a, b, c, d, e, f, g, h, i, j, k, l); push_word(va); break; case push13_opcode: @@ -1051,7 +1139,7 @@ namespace machine pc++; m = code[pc]; pc++; - va = to_big_word(0, 0, 0, a, b, c, d, e, f, g, h, i, j, k, l, m); // TODO: Verify + va = to_big_word(0, 0, 0, a, b, c, d, e, f, g, h, i, j, k, l, m); push_word(va); break; case push14_opcode: @@ -1084,7 +1172,7 @@ namespace machine pc++; n = code[pc]; pc++; - va = to_big_word(0, 0, a, b, c, d, e, f, g, h, i, j, k, l, m, n); // TODO: Verify + va = to_big_word(0, 0, a, b, c, d, e, f, g, h, i, j, k, l, m, n); push_word(va); break; case push15_opcode: @@ -1119,7 +1207,7 @@ namespace machine pc++; o = code[pc]; pc++; - va = to_big_word(0, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o); // TODO: Verify + va = to_big_word(0, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o); push_word(va); break; case push16_opcode: @@ -1156,7 +1244,7 @@ namespace machine pc++; p = code[pc]; pc++; - va = to_big_word(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p); // TODO: Verify + va = to_big_word(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p); push_word(va); break; case push17_opcode: @@ -1196,7 +1284,7 @@ namespace machine q = code[pc]; pc++; va = to_big_word(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d, - e, f, g, h, i, j, k, l, m, n, o, p, q); // TODO: Verify + e, f, g, h, i, j, k, l, m, n, o, p, q); push_word(va); break; case push18_opcode: @@ -1238,7 +1326,7 @@ namespace machine r = code[pc]; pc++; va = to_big_word(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d, e, - f, g, h, i, j, k, l, m, n, o, p, q, r); // TODO: Verify + f, g, h, i, j, k, l, m, n, o, p, q, r); push_word(va); break; case push19_opcode: @@ -1282,7 +1370,7 @@ namespace machine s = code[pc]; pc++; va = to_big_word(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d, e, f, - g, h, i, j, k, l, m, n, o, p, q, r, s); // TODO: Verify + g, h, i, j, k, l, m, n, o, p, q, r, s); push_word(va); break; case push20_opcode: @@ -1328,7 +1416,7 @@ namespace machine t = code[pc]; pc++; va = to_big_word(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d, e, f, g, - h, i, j, k, l, m, n, o, p, q, r, s, t); // TODO: Verify + h, i, j, k, l, m, n, o, p, q, r, s, t); push_word(va); break; case push21_opcode: @@ -1376,7 +1464,7 @@ namespace machine u = code[pc]; pc++; va = to_big_word(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d, e, f, g, h, - i, j, k, l, m, n, o, p, q, r, s, t, u); // TODO: Verify + i, j, k, l, m, n, o, p, q, r, s, t, u); push_word(va); break; case push22_opcode: @@ -1426,7 +1514,7 @@ namespace machine v = code[pc]; pc++; va = to_big_word(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d, e, f, g, h, i, - j, k, l, m, n, o, p, q, r, s, t, u, v); // TODO: Verify + j, k, l, m, n, o, p, q, r, s, t, u, v); push_word(va); break; case push23_opcode: @@ -1478,7 +1566,7 @@ namespace machine w = code[pc]; pc++; va = to_big_word(0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d, e, f, g, h, i, j, - k, l, m, n, o, p, q, r, s, t, u, v, w); // TODO: Verify + k, l, m, n, o, p, q, r, s, t, u, v, w); push_word(va); break; case push24_opcode: @@ -1532,7 +1620,7 @@ namespace machine x = code[pc]; pc++; va = to_big_word(0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d, e, f, g, h, i, j, k, - l, m, n, o, p, q, r, s, t, u, v, w, x); // TODO: Verify + l, m, n, o, p, q, r, s, t, u, v, w, x); push_word(va); break; case push25_opcode: @@ -1588,7 +1676,7 @@ namespace machine y = code[pc]; pc++; va = to_big_word(0, 0, 0, 0, 0, 0, 0, a, b, c, d, e, f, g, h, i, j, k, l, - m, n, o, p, q, r, s, t, u, v, w, x, y); // TODO: Verify + m, n, o, p, q, r, s, t, u, v, w, x, y); push_word(va); break; case push26_opcode: @@ -1646,7 +1734,7 @@ namespace machine z = code[pc]; pc++; va = to_big_word(0, 0, 0, 0, 0, 0, a, b, c, d, e, f, g, h, i, j, k, l, m, - n, o, p, q, r, s, t, u, v, w, x, y, z); // TODO: Verify + n, o, p, q, r, s, t, u, v, w, x, y, z); push_word(va); break; case push27_opcode: @@ -1706,7 +1794,7 @@ namespace machine aa = code[pc]; pc++; va = to_big_word(0, 0, 0, 0, 0, a, b, c, d, e, f, g, h, i, j, k, l, m, n, - o, p, q, r, s, t, u, v, w, x, y, z, aa); // TODO: Verify + o, p, q, r, s, t, u, v, w, x, y, z, aa); push_word(va); break; case push28_opcode: @@ -1768,7 +1856,7 @@ namespace machine ab = code[pc]; pc++; va = to_big_word(0, 0, 0, 0, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, - p, q, r, s, t, u, v, w, x, y, z, aa, ab); // TODO: Verify + p, q, r, s, t, u, v, w, x, y, z, aa, ab); push_word(va); break; case push29_opcode: @@ -1832,7 +1920,7 @@ namespace machine ac = code[pc]; pc++; va = to_big_word(0, 0, 0, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, - q, r, s, t, u, v, w, x, y, z, aa, ab, ac); // TODO: Verify + q, r, s, t, u, v, w, x, y, z, aa, ab, ac); push_word(va); break; case push30_opcode: @@ -1898,7 +1986,7 @@ namespace machine ad = code[pc]; pc++; va = to_big_word(0, 0, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, - q, r, s, t, u, v, w, x, y, z, aa, ab, ac, ad); // TODO: Verify + q, r, s, t, u, v, w, x, y, z, aa, ab, ac, ad); push_word(va); break; case push31_opcode: @@ -1966,7 +2054,7 @@ namespace machine ae = code[pc]; pc++; va = to_big_word(0, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, - q, r, s, t, u, v, w, x, y, z, aa, ab, ac, ad, ae); // TODO: Verify + q, r, s, t, u, v, w, x, y, z, aa, ab, ac, ad, ae); push_word(va); break; case push32_opcode: @@ -2036,18 +2124,18 @@ namespace machine af = code[pc]; pc++; va = to_big_word(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, - q, r, s, t, u, v, w, x, y, z, aa, ab, ac, ad, ae, af); // TODO: Verify + q, r, s, t, u, v, w, x, y, z, aa, ab, ac, ad, ae, af); push_word(va); break; case dup1_opcode: logger << "op dup1" << std::endl; - sv = stack.front(); + sv = stack.at(0); push_word(sv); break; case dup2_opcode: logger << "op dup2" << std::endl; - sv = stack.at(1); - push_word(va); + sv = stack.at(1); + push_word(sv); break; case dup3_opcode: logger << "op dup3" << std::endl; @@ -2123,8 +2211,8 @@ namespace machine logger << "op swap1" << std::endl; va = pop_word(); vb = pop_word(); - push_word(a); - push_word(b); + push_word(va); + push_word(vb); break; case swap2_opcode: logger << "op swap2" << std::endl; @@ -2764,6 +2852,7 @@ namespace machine break; case return_opcode: logger << "op return" << std::endl; + // XXX // TODO REVIEW // a = pop_word(); // offset // b = pop_word(); // length @@ -2779,7 +2868,7 @@ namespace machine va = pop_word(); // offset vb = pop_word(); // length - for (size_t i = static_cast(va); i < static_cast(vb); i++) { + for (size_t i = static_cast(va); i < static_cast(va + vb); i++) { std::map::iterator it; it = memory.find(i); if (it != memory.end()) { @@ -2790,8 +2879,9 @@ namespace machine } } + return_value = retval; adapter.contract_return( retval ); - state = machine_state::stopped; // TODO: Add elsewhere + state = machine_state::stopped; break; case delegatecall_opcode: logger << "op delegatecall" << std::endl; @@ -2915,9 +3005,13 @@ namespace machine else { retval.push_back(word(0)); } + memory[i] = 0; } adapter.revert( retval ); break; + case invalid_opcode: + logger << "op invalid" << std::endl; + break; case selfdestruct_opcode: logger << "op selfdestruct" << std::endl; sv = stack.front(); // addr @@ -2962,7 +3056,7 @@ namespace machine { s << "\"finalState\":" << "{"; { - s << "\"pc\":" << pc << ","; + s << "\"pc\":" << std::hex << pc << ","; s << "\"stack\":" << "["; for (auto it = stack.cbegin(); it != stack.cend(); ++it) { @@ -3000,7 +3094,7 @@ namespace machine word current_instruction = code[pc]; opcode op = (opcode)current_instruction; - s << "\"opcode\":" << std::dec << op << ","; + s << "\"opcode\":" << std::hex << op << ","; if (error_message == boost::none) s << "\"exceptionError\":" << "null"; @@ -3017,7 +3111,6 @@ namespace machine if (memory.size() > 1 && std::next(it, 1) != memory.cend()) s << ","; } - s << "}"; } s << "}"; } diff --git a/libraries/vendor/xgtvm/libraries/machine.hpp b/libraries/vendor/xgtvm/libraries/machine.hpp index dcb5bc24..c32e3a14 100644 --- a/libraries/vendor/xgtvm/libraries/machine.hpp +++ b/libraries/vendor/xgtvm/libraries/machine.hpp @@ -173,6 +173,7 @@ namespace machine create2_opcode = 0xF5, staticcall_opcode = 0xFA, revert_opcode = 0xFD, + invalid_opcode = 0xFE, selfdestruct_opcode = 0xFF, }; @@ -195,8 +196,8 @@ namespace machine int32_t depth; int64_t energy; - std::string sender; - std::string destination; + big_word sender; + big_word destination; big_word value; size_t input_size; @@ -262,7 +263,7 @@ namespace machine std::function< void(big_word, big_word) > set_storage; // TODO return opcode - std::function< bool(std::vector) > contract_return; + std::function< std::vector(std::vector) > contract_return; // TODO selfdestruct opcode std::function< bool(std::string) > self_destruct; diff --git a/libraries/vendor/xgtvm/programs/xgtvm.cpp b/libraries/vendor/xgtvm/programs/xgtvm.cpp index 82818ed6..593ac8b6 100644 --- a/libraries/vendor/xgtvm/programs/xgtvm.cpp +++ b/libraries/vendor/xgtvm/programs/xgtvm.cpp @@ -124,7 +124,7 @@ machine::chain_adapter make_chain_adapter() { }; - std::function< bool(std::vector) > contract_return = [](std::vector memory) -> bool + std::function< std::vector(std::vector) > contract_return = [](std::vector memory) -> std::vector { return {}; }; diff --git a/libraries/vendor/xgtvm/programs/xgtvm_tests.cpp b/libraries/vendor/xgtvm/programs/xgtvm_tests.cpp index d75ed781..6968fb5c 100644 --- a/libraries/vendor/xgtvm/programs/xgtvm_tests.cpp +++ b/libraries/vendor/xgtvm/programs/xgtvm_tests.cpp @@ -95,7 +95,7 @@ machine::chain_adapter make_chain_adapter() return false; }; - std::function< bool(std::vector) > contract_return = [](std::vector memory) -> bool + std::function< std::vector(std::vector) > contract_return = [](std::vector memory) -> std::vector { std::cout << "chain_adapter::contract_return" << std::endl; return {}; @@ -226,61 +226,61 @@ int main(int argc, char** argv) // assert_message( "top of stack has correct value", m.peek_word() == 2 ); //} - test_that("do nothing contract evaluates") - { - std::vector input = {0x60, 0x80, 0x60, 0x40, 0x52, 0x34, 0x80, 0x15, 0x60, 0x0f, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x60, 0x6d, 0x80, 0x60, 0x1d, 0x60, 0x00, 0x39, 0x60, 0x00, 0xf3, 0xfe, 0x60, 0x80, 0x60, 0x40, 0x52, 0x34, 0x80, 0x15, 0x60, 0x0f, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x60, 0x04, 0x36, 0x10, 0x60, 0x28, 0x57, 0x60, 0x00, 0x35, 0x60, 0xe0, 0x1c, 0x80, 0x63, 0x2f, 0x57, 0x6f, 0x20, 0x14, 0x60, 0x2d, 0x57, 0x5b, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x60, 0x33, 0x60, 0x35, 0x56, 0x5b, 0x00, 0x5b, 0x56, 0xfe, 0xa2, 0x64, 0x69, 0x70, 0x66, 0x73, 0x58, 0x22, 0x12, 0x20, 0x97, 0x5b, 0xdb, 0x69, 0x49, 0x44, 0x25, 0x38, 0xb9, 0x0c, 0x14, 0xc4, 0x20, 0xb0, 0xa2, 0xf5, 0x47, 0xf0, 0x43, 0x7e, 0x85, 0xa7, 0x3d, 0xa1, 0x2f, 0xaf, 0x4e, 0x68, 0x34, 0xf0, 0x81, 0x72, 0x64, 0x73, 0x6f, 0x6c, 0x63, 0x43, 0x00, 0x08, 0x07, 0x00, 0x33}; - machine::context ctx = {true, 0x00}; - machine::message msg = {}; - machine::chain_adapter adapter = make_chain_adapter(); - machine::machine m(ctx, input, msg, adapter); - assert_message( "machine should start running", m.get_state() == machine::machine_state::running ); - - auto& logger = m.get_logger(); - std::string line; - std::cerr << "\e[36m" << "LOG: " << m.to_json() << "\e[0m" << std::endl; - while (m.is_running()) - { - m.step(); - //// TODO: Figure out why logs not emitting - //while ( std::getline(logger, line) ) - // std::cerr << "\e[36m" << "LOG: " << line << "\e[0m" << std::endl; - std::cerr << "\e[36m" << "LOG: " << m.to_json() << "\e[0m" << std::endl; - } - //while ( std::getline(logger, line) ) - // std::cerr << "\e[36m" << "LOG: " << line << "\e[0m" << std::endl; - std::cerr << "\e[36m" << "LOG: " << m.to_json() << "\e[0m" << std::endl; - - assert_message( "machine should stop when done executing", m.get_state() == machine::machine_state::stopped ); - assert_message( "stack has correct length", m.stack_length() == 0 ); - } - - test_that("storage contract evaluates") - { - std::vector input = {0x60, 0x80, 0x60, 0x40, 0x52, 0x34, 0x80, 0x15, 0x61, 0x00, 0x10, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x61, 0x01, 0x50, 0x80, 0x61, 0x00, 0x20, 0x60, 0x00, 0x39, 0x60, 0x00, 0xf3, 0xfe, 0x60, 0x80, 0x60, 0x40, 0x52, 0x34, 0x80, 0x15, 0x61, 0x00, 0x10, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x60, 0x04, 0x36, 0x10, 0x61, 0x00, 0x36, 0x57, 0x60, 0x00, 0x35, 0x60, 0xe0, 0x1c, 0x80, 0x63, 0x2e, 0x64, 0xce, 0xc1, 0x14, 0x61, 0x00, 0x3b, 0x57, 0x80, 0x63, 0x60, 0x57, 0x36, 0x1d, 0x14, 0x61, 0x00, 0x59, 0x57, 0x5b, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x61, 0x00, 0x43, 0x61, 0x00, 0x75, 0x56, 0x5b, 0x60, 0x40, 0x51, 0x61, 0x00, 0x50, 0x91, 0x90, 0x61, 0x00, 0xd9, 0x56, 0x5b, 0x60, 0x40, 0x51, 0x80, 0x91, 0x03, 0x90, 0xf3, 0x5b, 0x61, 0x00, 0x73, 0x60, 0x04, 0x80, 0x36, 0x03, 0x81, 0x01, 0x90, 0x61, 0x00, 0x6e, 0x91, 0x90, 0x61, 0x00, 0x9d, 0x56, 0x5b, 0x61, 0x00, 0x7e, 0x56, 0x5b, 0x00, 0x5b, 0x60, 0x00, 0x80, 0x54, 0x90, 0x50, 0x90, 0x56, 0x5b, 0x80, 0x60, 0x00, 0x81, 0x90, 0x55, 0x50, 0x50, 0x56, 0x5b, 0x60, 0x00, 0x81, 0x35, 0x90, 0x50, 0x61, 0x00, 0x97, 0x81, 0x61, 0x01, 0x03, 0x56, 0x5b, 0x92, 0x91, 0x50, 0x50, 0x56, 0x5b, 0x60, 0x00, 0x60, 0x20, 0x82, 0x84, 0x03, 0x12, 0x15, 0x61, 0x00, 0xb3, 0x57, 0x61, 0x00, 0xb2, 0x61, 0x00, 0xfe, 0x56, 0x5b, 0x5b, 0x60, 0x00, 0x61, 0x00, 0xc1, 0x84, 0x82, 0x85, 0x01, 0x61, 0x00, 0x88, 0x56, 0x5b, 0x91, 0x50, 0x50, 0x92, 0x91, 0x50, 0x50, 0x56, 0x5b, 0x61, 0x00, 0xd3, 0x81, 0x61, 0x00, 0xf4, 0x56, 0x5b, 0x82, 0x52, 0x50, 0x50, 0x56, 0x5b, 0x60, 0x00, 0x60, 0x20, 0x82, 0x01, 0x90, 0x50, 0x61, 0x00, 0xee, 0x60, 0x00, 0x83, 0x01, 0x84, 0x61, 0x00, 0xca, 0x56, 0x5b, 0x92, 0x91, 0x50, 0x50, 0x56, 0x5b, 0x60, 0x00, 0x81, 0x90, 0x50, 0x91, 0x90, 0x50, 0x56, 0x5b, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x61, 0x01, 0x0c, 0x81, 0x61, 0x00, 0xf4, 0x56, 0x5b, 0x81, 0x14, 0x61, 0x01, 0x17, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x56, 0xfe, 0xa2, 0x64, 0x69, 0x70, 0x66, 0x73, 0x58, 0x22, 0x12, 0x20, 0x40, 0x4e, 0x37, 0xf4, 0x87, 0xa8, 0x9a, 0x93, 0x2d, 0xca, 0x5e, 0x77, 0xfa, 0xaf, 0x6c, 0xa2, 0xde, 0x3b, 0x99, 0x1f, 0x93, 0xd2, 0x30, 0x60, 0x4b, 0x1b, 0x8d, 0xaa, 0xef, 0x64, 0x76, 0x62, 0x64, 0x73, 0x6f, 0x6c, 0x63, 0x43, 0x00, 0x08, 0x07, 0x00, 0x33}; - machine::context ctx = {true, 0x00}; - machine::message msg = {}; - machine::chain_adapter adapter = make_chain_adapter(); - machine::machine m(ctx, input, msg, adapter); - assert_message( "machine should start running", m.get_state() == machine::machine_state::running ); - - auto& logger = m.get_logger(); - std::string line; - std::cerr << "\e[36m" << "LOG: " << m.to_json() << "\e[0m" << std::endl; - while (m.is_running()) - { - m.step(); - //// TODO: Figure out why logs not emitting - //while ( std::getline(logger, line) ) - // std::cerr << "\e[36m" << "LOG: " << line << "\e[0m" << std::endl; - std::cerr << "\e[36m" << "LOG: " << m.to_json() << "\e[0m" << std::endl; - } - //while ( std::getline(logger, line) ) - // std::cerr << "\e[36m" << "LOG: " << line << "\e[0m" << std::endl; - std::cerr << "\e[36m" << "LOG: " << m.to_json() << "\e[0m" << std::endl; - - assert_message( "machine should stop when done executing", m.get_state() == machine::machine_state::stopped ); - assert_message( "stack has correct length", m.stack_length() == 0 ); - } + // test_that("do nothing contract evaluates") + // { + // std::vector input = {0x60, 0x80, 0x60, 0x40, 0x52, 0x34, 0x80, 0x15, 0x60, 0x0f, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x60, 0x6d, 0x80, 0x60, 0x1d, 0x60, 0x00, 0x39, 0x60, 0x00, 0xf3, 0xfe, 0x60, 0x80, 0x60, 0x40, 0x52, 0x34, 0x80, 0x15, 0x60, 0x0f, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x60, 0x04, 0x36, 0x10, 0x60, 0x28, 0x57, 0x60, 0x00, 0x35, 0x60, 0xe0, 0x1c, 0x80, 0x63, 0x2f, 0x57, 0x6f, 0x20, 0x14, 0x60, 0x2d, 0x57, 0x5b, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x60, 0x33, 0x60, 0x35, 0x56, 0x5b, 0x00, 0x5b, 0x56, 0xfe, 0xa2, 0x64, 0x69, 0x70, 0x66, 0x73, 0x58, 0x22, 0x12, 0x20, 0x97, 0x5b, 0xdb, 0x69, 0x49, 0x44, 0x25, 0x38, 0xb9, 0x0c, 0x14, 0xc4, 0x20, 0xb0, 0xa2, 0xf5, 0x47, 0xf0, 0x43, 0x7e, 0x85, 0xa7, 0x3d, 0xa1, 0x2f, 0xaf, 0x4e, 0x68, 0x34, 0xf0, 0x81, 0x72, 0x64, 0x73, 0x6f, 0x6c, 0x63, 0x43, 0x00, 0x08, 0x07, 0x00, 0x33}; + // machine::context ctx = {true, 0x00}; + // machine::message msg = {}; + // machine::chain_adapter adapter = make_chain_adapter(); + // machine::machine m(ctx, input, msg, adapter); + // assert_message( "machine should start running", m.get_state() == machine::machine_state::running ); + + // auto& logger = m.get_logger(); + // std::string line; + // std::cerr << "\e[36m" << "LOG: " << m.to_json() << "\e[0m" << std::endl; + // while (m.is_running()) + // { + // m.step(); + // //// TODO: Figure out why logs not emitting + // //while ( std::getline(logger, line) ) + // // std::cerr << "\e[36m" << "LOG: " << line << "\e[0m" << std::endl; + // std::cerr << "\e[36m" << "LOG: " << m.to_json() << "\e[0m" << std::endl; + // } + // //while ( std::getline(logger, line) ) + // // std::cerr << "\e[36m" << "LOG: " << line << "\e[0m" << std::endl; + // std::cerr << "\e[36m" << "LOG: " << m.to_json() << "\e[0m" << std::endl; + + // assert_message( "machine should stop when done executing", m.get_state() == machine::machine_state::stopped ); + // assert_message( "stack has correct length", m.stack_length() == 0 ); + // } + + // test_that("storage contract evaluates") + // { + // std::vector input = {0x60, 0x80, 0x60, 0x40, 0x52, 0x34, 0x80, 0x15, 0x61, 0x00, 0x10, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x61, 0x01, 0x50, 0x80, 0x61, 0x00, 0x20, 0x60, 0x00, 0x39, 0x60, 0x00, 0xf3, 0xfe, 0x60, 0x80, 0x60, 0x40, 0x52, 0x34, 0x80, 0x15, 0x61, 0x00, 0x10, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x60, 0x04, 0x36, 0x10, 0x61, 0x00, 0x36, 0x57, 0x60, 0x00, 0x35, 0x60, 0xe0, 0x1c, 0x80, 0x63, 0x2e, 0x64, 0xce, 0xc1, 0x14, 0x61, 0x00, 0x3b, 0x57, 0x80, 0x63, 0x60, 0x57, 0x36, 0x1d, 0x14, 0x61, 0x00, 0x59, 0x57, 0x5b, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x61, 0x00, 0x43, 0x61, 0x00, 0x75, 0x56, 0x5b, 0x60, 0x40, 0x51, 0x61, 0x00, 0x50, 0x91, 0x90, 0x61, 0x00, 0xd9, 0x56, 0x5b, 0x60, 0x40, 0x51, 0x80, 0x91, 0x03, 0x90, 0xf3, 0x5b, 0x61, 0x00, 0x73, 0x60, 0x04, 0x80, 0x36, 0x03, 0x81, 0x01, 0x90, 0x61, 0x00, 0x6e, 0x91, 0x90, 0x61, 0x00, 0x9d, 0x56, 0x5b, 0x61, 0x00, 0x7e, 0x56, 0x5b, 0x00, 0x5b, 0x60, 0x00, 0x80, 0x54, 0x90, 0x50, 0x90, 0x56, 0x5b, 0x80, 0x60, 0x00, 0x81, 0x90, 0x55, 0x50, 0x50, 0x56, 0x5b, 0x60, 0x00, 0x81, 0x35, 0x90, 0x50, 0x61, 0x00, 0x97, 0x81, 0x61, 0x01, 0x03, 0x56, 0x5b, 0x92, 0x91, 0x50, 0x50, 0x56, 0x5b, 0x60, 0x00, 0x60, 0x20, 0x82, 0x84, 0x03, 0x12, 0x15, 0x61, 0x00, 0xb3, 0x57, 0x61, 0x00, 0xb2, 0x61, 0x00, 0xfe, 0x56, 0x5b, 0x5b, 0x60, 0x00, 0x61, 0x00, 0xc1, 0x84, 0x82, 0x85, 0x01, 0x61, 0x00, 0x88, 0x56, 0x5b, 0x91, 0x50, 0x50, 0x92, 0x91, 0x50, 0x50, 0x56, 0x5b, 0x61, 0x00, 0xd3, 0x81, 0x61, 0x00, 0xf4, 0x56, 0x5b, 0x82, 0x52, 0x50, 0x50, 0x56, 0x5b, 0x60, 0x00, 0x60, 0x20, 0x82, 0x01, 0x90, 0x50, 0x61, 0x00, 0xee, 0x60, 0x00, 0x83, 0x01, 0x84, 0x61, 0x00, 0xca, 0x56, 0x5b, 0x92, 0x91, 0x50, 0x50, 0x56, 0x5b, 0x60, 0x00, 0x81, 0x90, 0x50, 0x91, 0x90, 0x50, 0x56, 0x5b, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x61, 0x01, 0x0c, 0x81, 0x61, 0x00, 0xf4, 0x56, 0x5b, 0x81, 0x14, 0x61, 0x01, 0x17, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x56, 0xfe, 0xa2, 0x64, 0x69, 0x70, 0x66, 0x73, 0x58, 0x22, 0x12, 0x20, 0x40, 0x4e, 0x37, 0xf4, 0x87, 0xa8, 0x9a, 0x93, 0x2d, 0xca, 0x5e, 0x77, 0xfa, 0xaf, 0x6c, 0xa2, 0xde, 0x3b, 0x99, 0x1f, 0x93, 0xd2, 0x30, 0x60, 0x4b, 0x1b, 0x8d, 0xaa, 0xef, 0x64, 0x76, 0x62, 0x64, 0x73, 0x6f, 0x6c, 0x63, 0x43, 0x00, 0x08, 0x07, 0x00, 0x33}; + // machine::context ctx = {true, 0x00}; + // machine::message msg = {}; + // machine::chain_adapter adapter = make_chain_adapter(); + // machine::machine m(ctx, input, msg, adapter); + // assert_message( "machine should start running", m.get_state() == machine::machine_state::running ); + + // auto& logger = m.get_logger(); + // std::string line; + // std::cerr << "\e[36m" << "LOG: " << m.to_json() << "\e[0m" << std::endl; + // while (m.is_running()) + // { + // m.step(); + // //// TODO: Figure out why logs not emitting + // //while ( std::getline(logger, line) ) + // // std::cerr << "\e[36m" << "LOG: " << line << "\e[0m" << std::endl; + // std::cerr << "\e[36m" << "LOG: " << m.to_json() << "\e[0m" << std::endl; + // } + // //while ( std::getline(logger, line) ) + // // std::cerr << "\e[36m" << "LOG: " << line << "\e[0m" << std::endl; + // std::cerr << "\e[36m" << "LOG: " << m.to_json() << "\e[0m" << std::endl; + + // assert_message( "machine should stop when done executing", m.get_state() == machine::machine_state::stopped ); + // assert_message( "stack has correct length", m.stack_length() == 0 ); + // } //test_that("first lottery contract evaluates") //{ @@ -307,30 +307,33 @@ int main(int argc, char** argv) // assert_message( "stack has correct length", m.stack_length() == 0 ); //} - //test_that("second lottery contract evaluates") - //{ - // std::vector input = {0x60, 0x80, 0x60, 0x40, 0x52, 0x34, 0x80, 0x15, 0x62, 0x00, 0x00, 0x11, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x60, 0x40, 0x51, 0x62, 0x00, 0x17, 0x54, 0x38, 0x03, 0x80, 0x62, 0x00, 0x17, 0x54, 0x83, 0x39, 0x81, 0x01, 0x80, 0x60, 0x40, 0x52, 0x81, 0x01, 0x90, 0x80, 0x80, 0x51, 0x82, 0x01, 0x92, 0x91, 0x90, 0x60, 0x20, 0x01, 0x80, 0x51, 0x90, 0x60, 0x20, 0x01, 0x90, 0x92, 0x91, 0x90, 0x50, 0x50, 0x50, 0x80, 0x60, 0x01, 0x60, 0x00, 0x61, 0x01, 0x00, 0x0a, 0x81, 0x54, 0x81, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0x19, 0x16, 0x90, 0x83, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x02, 0x17, 0x90, 0x55, 0x50, 0x81, 0x60, 0x00, 0x90, 0x80, 0x51, 0x90, 0x60, 0x20, 0x01, 0x90, 0x62, 0x00, 0x00, 0x9c, 0x92, 0x91, 0x90, 0x62, 0x00, 0x00, 0xa5, 0x56, 0x5b, 0x50, 0x50, 0x50, 0x62, 0x00, 0x01, 0x54, 0x56, 0x5b, 0x82, 0x80, 0x54, 0x60, 0x01, 0x81, 0x60, 0x01, 0x16, 0x15, 0x61, 0x01, 0x00, 0x02, 0x03, 0x16, 0x60, 0x02, 0x90, 0x04, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x90, 0x60, 0x1f, 0x01, 0x60, 0x20, 0x90, 0x04, 0x81, 0x01, 0x92, 0x82, 0x60, 0x1f, 0x10, 0x62, 0x00, 0x00, 0xe8, 0x57, 0x80, 0x51, 0x60, 0xff, 0x19, 0x16, 0x83, 0x80, 0x01, 0x17, 0x85, 0x55, 0x62, 0x00, 0x01, 0x19, 0x56, 0x5b, 0x82, 0x80, 0x01, 0x60, 0x01, 0x01, 0x85, 0x55, 0x82, 0x15, 0x62, 0x00, 0x01, 0x19, 0x57, 0x91, 0x82, 0x01, 0x5b, 0x82, 0x81, 0x11, 0x15, 0x62, 0x00, 0x01, 0x18, 0x57, 0x82, 0x51, 0x82, 0x55, 0x91, 0x60, 0x20, 0x01, 0x91, 0x90, 0x60, 0x01, 0x01, 0x90, 0x62, 0x00, 0x00, 0xfb, 0x56, 0x5b, 0x5b, 0x50, 0x90, 0x50, 0x62, 0x00, 0x01, 0x28, 0x91, 0x90, 0x62, 0x00, 0x01, 0x2c, 0x56, 0x5b, 0x50, 0x90, 0x56, 0x5b, 0x62, 0x00, 0x01, 0x51, 0x91, 0x90, 0x5b, 0x80, 0x82, 0x11, 0x15, 0x62, 0x00, 0x01, 0x4d, 0x57, 0x60, 0x00, 0x81, 0x60, 0x00, 0x90, 0x55, 0x50, 0x60, 0x01, 0x01, 0x62, 0x00, 0x01, 0x33, 0x56, 0x5b, 0x50, 0x90, 0x56, 0x5b, 0x90, 0x56, 0x5b, 0x61, 0x15, 0xf0, 0x80, 0x62, 0x00, 0x01, 0x64, 0x60, 0x00, 0x39, 0x60, 0x00, 0xf3, 0x00, 0x60, 0x80, 0x60, 0x40, 0x52, 0x60, 0x04, 0x36, 0x10, 0x61, 0x00, 0xd0, 0x57, 0x60, 0x00, 0x35, 0x7c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x04, 0x63, 0xff, 0xff, 0xff, 0xff, 0x16, 0x80, 0x63, 0x10, 0xc8, 0x5f, 0xe5, 0x14, 0x61, 0x01, 0x10, 0x57, 0x80, 0x63, 0x14, 0x03, 0x4b, 0xd2, 0x14, 0x61, 0x01, 0x3f, 0x57, 0x80, 0x63, 0x1d, 0x27, 0x76, 0x9f, 0x14, 0x61, 0x01, 0x56, 0x57, 0x80, 0x63, 0x23, 0xd1, 0x41, 0x49, 0x14, 0x61, 0x01, 0xb2, 0x57, 0x80, 0x63, 0x48, 0x1c, 0x6a, 0x75, 0x14, 0x61, 0x02, 0x42, 0x57, 0x80, 0x63, 0x58, 0x32, 0xd5, 0x71, 0x14, 0x61, 0x02, 0x99, 0x57, 0x80, 0x63, 0x5c, 0x12, 0xcd, 0x4b, 0x14, 0x61, 0x03, 0x06, 0x57, 0x80, 0x63, 0x5d, 0x58, 0xa7, 0x4a, 0x14, 0x61, 0x03, 0xc9, 0x57, 0x80, 0x63, 0x77, 0x52, 0x04, 0x5b, 0x14, 0x61, 0x03, 0xf4, 0x57, 0x80, 0x63, 0x8b, 0x5b, 0x9c, 0xcc, 0x14, 0x61, 0x04, 0x1f, 0x57, 0x80, 0x63, 0xbd, 0xae, 0xa3, 0x26, 0x14, 0x61, 0x04, 0x8b, 0x57, 0x80, 0x63, 0xd6, 0x88, 0x95, 0xd8, 0x14, 0x61, 0x04, 0xc2, 0x57, 0x80, 0x63, 0xdf, 0xbf, 0x53, 0xae, 0x14, 0x61, 0x04, 0xed, 0x57, 0x80, 0x63, 0xf2, 0x52, 0x66, 0xdd, 0x14, 0x61, 0x05, 0x8b, 0x57, 0x5b, 0x61, 0x01, 0x0e, 0x60, 0x40, 0x80, 0x51, 0x90, 0x81, 0x01, 0x60, 0x40, 0x52, 0x80, 0x60, 0x07, 0x81, 0x52, 0x60, 0x20, 0x01, 0x7f, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x52, 0x50, 0x61, 0x05, 0xf8, 0x56, 0x5b, 0x00, 0x5b, 0x34, 0x80, 0x15, 0x61, 0x01, 0x1c, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x61, 0x01, 0x25, 0x61, 0x09, 0xee, 0x56, 0x5b, 0x60, 0x40, 0x51, 0x80, 0x82, 0x15, 0x15, 0x15, 0x15, 0x81, 0x52, 0x60, 0x20, 0x01, 0x91, 0x50, 0x50, 0x60, 0x40, 0x51, 0x80, 0x91, 0x03, 0x90, 0xf3, 0x5b, 0x34, 0x80, 0x15, 0x61, 0x01, 0x4b, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x61, 0x01, 0x54, 0x61, 0x0a, 0x01, 0x56, 0x5b, 0x00, 0x5b, 0x61, 0x01, 0xb0, 0x60, 0x04, 0x80, 0x36, 0x03, 0x81, 0x01, 0x90, 0x80, 0x80, 0x35, 0x90, 0x60, 0x20, 0x01, 0x90, 0x82, 0x01, 0x80, 0x35, 0x90, 0x60, 0x20, 0x01, 0x90, 0x80, 0x80, 0x60, 0x1f, 0x01, 0x60, 0x20, 0x80, 0x91, 0x04, 0x02, 0x60, 0x20, 0x01, 0x60, 0x40, 0x51, 0x90, 0x81, 0x01, 0x60, 0x40, 0x52, 0x80, 0x93, 0x92, 0x91, 0x90, 0x81, 0x81, 0x52, 0x60, 0x20, 0x01, 0x83, 0x83, 0x80, 0x82, 0x84, 0x37, 0x82, 0x01, 0x91, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x91, 0x92, 0x91, 0x92, 0x90, 0x50, 0x50, 0x50, 0x61, 0x05, 0xf8, 0x56, 0x5b, 0x00, 0x5b, 0x34, 0x80, 0x15, 0x61, 0x01, 0xbe, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x61, 0x01, 0xc7, 0x61, 0x0d, 0xbf, 0x56, 0x5b, 0x60, 0x40, 0x51, 0x80, 0x80, 0x60, 0x20, 0x01, 0x82, 0x81, 0x03, 0x82, 0x52, 0x83, 0x81, 0x81, 0x51, 0x81, 0x52, 0x60, 0x20, 0x01, 0x91, 0x50, 0x80, 0x51, 0x90, 0x60, 0x20, 0x01, 0x90, 0x80, 0x83, 0x83, 0x60, 0x00, 0x5b, 0x83, 0x81, 0x10, 0x15, 0x61, 0x02, 0x07, 0x57, 0x80, 0x82, 0x01, 0x51, 0x81, 0x84, 0x01, 0x52, 0x60, 0x20, 0x81, 0x01, 0x90, 0x50, 0x61, 0x01, 0xec, 0x56, 0x5b, 0x50, 0x50, 0x50, 0x50, 0x90, 0x50, 0x90, 0x81, 0x01, 0x90, 0x60, 0x1f, 0x16, 0x80, 0x15, 0x61, 0x02, 0x34, 0x57, 0x80, 0x82, 0x03, 0x80, 0x51, 0x60, 0x01, 0x83, 0x60, 0x20, 0x03, 0x61, 0x01, 0x00, 0x0a, 0x03, 0x19, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x91, 0x50, 0x5b, 0x50, 0x92, 0x50, 0x50, 0x50, 0x60, 0x40, 0x51, 0x80, 0x91, 0x03, 0x90, 0xf3, 0x5b, 0x34, 0x80, 0x15, 0x61, 0x02, 0x4e, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x61, 0x02, 0x57, 0x61, 0x0e, 0x5d, 0x56, 0x5b, 0x60, 0x40, 0x51, 0x80, 0x82, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x91, 0x50, 0x50, 0x60, 0x40, 0x51, 0x80, 0x91, 0x03, 0x90, 0xf3, 0x5b, 0x34, 0x80, 0x15, 0x61, 0x02, 0xa5, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x61, 0x02, 0xc4, 0x60, 0x04, 0x80, 0x36, 0x03, 0x81, 0x01, 0x90, 0x80, 0x80, 0x35, 0x90, 0x60, 0x20, 0x01, 0x90, 0x92, 0x91, 0x90, 0x50, 0x50, 0x50, 0x61, 0x0e, 0x83, 0x56, 0x5b, 0x60, 0x40, 0x51, 0x80, 0x82, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x91, 0x50, 0x50, 0x60, 0x40, 0x51, 0x80, 0x91, 0x03, 0x90, 0xf3, 0x5b, 0x34, 0x80, 0x15, 0x61, 0x03, 0x12, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x61, 0x03, 0x47, 0x60, 0x04, 0x80, 0x36, 0x03, 0x81, 0x01, 0x90, 0x80, 0x80, 0x35, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x90, 0x60, 0x20, 0x01, 0x90, 0x92, 0x91, 0x90, 0x50, 0x50, 0x50, 0x61, 0x0e, 0xc1, 0x56, 0x5b, 0x60, 0x40, 0x51, 0x80, 0x80, 0x60, 0x20, 0x01, 0x83, 0x81, 0x52, 0x60, 0x20, 0x01, 0x82, 0x81, 0x03, 0x82, 0x52, 0x84, 0x81, 0x81, 0x51, 0x81, 0x52, 0x60, 0x20, 0x01, 0x91, 0x50, 0x80, 0x51, 0x90, 0x60, 0x20, 0x01, 0x90, 0x80, 0x83, 0x83, 0x60, 0x00, 0x5b, 0x83, 0x81, 0x10, 0x15, 0x61, 0x03, 0x8d, 0x57, 0x80, 0x82, 0x01, 0x51, 0x81, 0x84, 0x01, 0x52, 0x60, 0x20, 0x81, 0x01, 0x90, 0x50, 0x61, 0x03, 0x72, 0x56, 0x5b, 0x50, 0x50, 0x50, 0x50, 0x90, 0x50, 0x90, 0x81, 0x01, 0x90, 0x60, 0x1f, 0x16, 0x80, 0x15, 0x61, 0x03, 0xba, 0x57, 0x80, 0x82, 0x03, 0x80, 0x51, 0x60, 0x01, 0x83, 0x60, 0x20, 0x03, 0x61, 0x01, 0x00, 0x0a, 0x03, 0x19, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x91, 0x50, 0x5b, 0x50, 0x93, 0x50, 0x50, 0x50, 0x50, 0x60, 0x40, 0x51, 0x80, 0x91, 0x03, 0x90, 0xf3, 0x5b, 0x34, 0x80, 0x15, 0x61, 0x03, 0xd5, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x61, 0x03, 0xde, 0x61, 0x10, 0x1e, 0x56, 0x5b, 0x60, 0x40, 0x51, 0x80, 0x82, 0x81, 0x52, 0x60, 0x20, 0x01, 0x91, 0x50, 0x50, 0x60, 0x40, 0x51, 0x80, 0x91, 0x03, 0x90, 0xf3, 0x5b, 0x34, 0x80, 0x15, 0x61, 0x04, 0x00, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x61, 0x04, 0x09, 0x61, 0x10, 0x24, 0x56, 0x5b, 0x60, 0x40, 0x51, 0x80, 0x82, 0x81, 0x52, 0x60, 0x20, 0x01, 0x91, 0x50, 0x50, 0x60, 0x40, 0x51, 0x80, 0x91, 0x03, 0x90, 0xf3, 0x5b, 0x34, 0x80, 0x15, 0x61, 0x04, 0x2b, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x61, 0x04, 0x34, 0x61, 0x10, 0x2a, 0x56, 0x5b, 0x60, 0x40, 0x51, 0x80, 0x80, 0x60, 0x20, 0x01, 0x82, 0x81, 0x03, 0x82, 0x52, 0x83, 0x81, 0x81, 0x51, 0x81, 0x52, 0x60, 0x20, 0x01, 0x91, 0x50, 0x80, 0x51, 0x90, 0x60, 0x20, 0x01, 0x90, 0x60, 0x20, 0x02, 0x80, 0x83, 0x83, 0x60, 0x00, 0x5b, 0x83, 0x81, 0x10, 0x15, 0x61, 0x04, 0x77, 0x57, 0x80, 0x82, 0x01, 0x51, 0x81, 0x84, 0x01, 0x52, 0x60, 0x20, 0x81, 0x01, 0x90, 0x50, 0x61, 0x04, 0x5c, 0x56, 0x5b, 0x50, 0x50, 0x50, 0x50, 0x90, 0x50, 0x01, 0x92, 0x50, 0x50, 0x50, 0x60, 0x40, 0x51, 0x80, 0x91, 0x03, 0x90, 0xf3, 0x5b, 0x34, 0x80, 0x15, 0x61, 0x04, 0x97, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x61, 0x04, 0xc0, 0x60, 0x04, 0x80, 0x36, 0x03, 0x81, 0x01, 0x90, 0x80, 0x80, 0x35, 0x90, 0x60, 0x20, 0x01, 0x90, 0x92, 0x91, 0x90, 0x80, 0x35, 0x90, 0x60, 0x20, 0x01, 0x90, 0x92, 0x91, 0x90, 0x50, 0x50, 0x50, 0x61, 0x10, 0xb8, 0x56, 0x5b, 0x00, 0x5b, 0x34, 0x80, 0x15, 0x61, 0x04, 0xce, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x61, 0x04, 0xd7, 0x61, 0x11, 0x61, 0x56, 0x5b, 0x60, 0x40, 0x51, 0x80, 0x82, 0x81, 0x52, 0x60, 0x20, 0x01, 0x91, 0x50, 0x50, 0x60, 0x40, 0x51, 0x80, 0x91, 0x03, 0x90, 0xf3, 0x5b, 0x34, 0x80, 0x15, 0x61, 0x04, 0xf9, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x61, 0x05, 0x02, 0x61, 0x11, 0x80, 0x56, 0x5b, 0x60, 0x40, 0x51, 0x80, 0x80, 0x60, 0x20, 0x01, 0x84, 0x81, 0x52, 0x60, 0x20, 0x01, 0x83, 0x81, 0x52, 0x60, 0x20, 0x01, 0x82, 0x81, 0x03, 0x82, 0x52, 0x85, 0x81, 0x81, 0x51, 0x81, 0x52, 0x60, 0x20, 0x01, 0x91, 0x50, 0x80, 0x51, 0x90, 0x60, 0x20, 0x01, 0x90, 0x80, 0x83, 0x83, 0x60, 0x00, 0x5b, 0x83, 0x81, 0x10, 0x15, 0x61, 0x05, 0x4e, 0x57, 0x80, 0x82, 0x01, 0x51, 0x81, 0x84, 0x01, 0x52, 0x60, 0x20, 0x81, 0x01, 0x90, 0x50, 0x61, 0x05, 0x33, 0x56, 0x5b, 0x50, 0x50, 0x50, 0x50, 0x90, 0x50, 0x90, 0x81, 0x01, 0x90, 0x60, 0x1f, 0x16, 0x80, 0x15, 0x61, 0x05, 0x7b, 0x57, 0x80, 0x82, 0x03, 0x80, 0x51, 0x60, 0x01, 0x83, 0x60, 0x20, 0x03, 0x61, 0x01, 0x00, 0x0a, 0x03, 0x19, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x91, 0x50, 0x5b, 0x50, 0x94, 0x50, 0x50, 0x50, 0x50, 0x50, 0x60, 0x40, 0x51, 0x80, 0x91, 0x03, 0x90, 0xf3, 0x5b, 0x34, 0x80, 0x15, 0x61, 0x05, 0x97, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x61, 0x05, 0xb6, 0x60, 0x04, 0x80, 0x36, 0x03, 0x81, 0x01, 0x90, 0x80, 0x80, 0x35, 0x90, 0x60, 0x20, 0x01, 0x90, 0x92, 0x91, 0x90, 0x50, 0x50, 0x50, 0x61, 0x12, 0x30, 0x56, 0x5b, 0x60, 0x40, 0x51, 0x80, 0x82, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x91, 0x50, 0x50, 0x60, 0x40, 0x51, 0x80, 0x91, 0x03, 0x90, 0xf3, 0x5b, 0x60, 0x00, 0x81, 0x51, 0x11, 0x15, 0x15, 0x61, 0x06, 0x08, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x60, 0x08, 0x60, 0x00, 0x90, 0x54, 0x90, 0x61, 0x01, 0x00, 0x0a, 0x90, 0x04, 0x60, 0xff, 0x16, 0x15, 0x15, 0x61, 0x06, 0x23, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x67, 0x0d, 0xe0, 0xb6, 0xb3, 0xa7, 0x64, 0x00, 0x00, 0x60, 0x0a, 0x54, 0x02, 0x34, 0x14, 0x15, 0x15, 0x61, 0x06, 0x3d, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x60, 0x09, 0x54, 0x60, 0x03, 0x60, 0x00, 0x33, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x90, 0x81, 0x52, 0x60, 0x20, 0x01, 0x60, 0x00, 0x20, 0x60, 0x01, 0x01, 0x54, 0x10, 0x15, 0x15, 0x61, 0x06, 0x8f, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x61, 0x06, 0x98, 0x33, 0x61, 0x12, 0x6e, 0x56, 0x5b, 0x15, 0x61, 0x07, 0xef, 0x57, 0x60, 0x01, 0x60, 0x03, 0x60, 0x00, 0x33, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x90, 0x81, 0x52, 0x60, 0x20, 0x01, 0x60, 0x00, 0x20, 0x60, 0x01, 0x01, 0x81, 0x90, 0x55, 0x50, 0x80, 0x60, 0x03, 0x60, 0x00, 0x33, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x90, 0x81, 0x52, 0x60, 0x20, 0x01, 0x60, 0x00, 0x20, 0x60, 0x00, 0x01, 0x90, 0x80, 0x51, 0x90, 0x60, 0x20, 0x01, 0x90, 0x61, 0x07, 0x3b, 0x92, 0x91, 0x90, 0x61, 0x13, 0xcb, 0x56, 0x5b, 0x50, 0x60, 0x01, 0x60, 0x02, 0x33, 0x90, 0x80, 0x60, 0x01, 0x81, 0x54, 0x01, 0x80, 0x82, 0x55, 0x80, 0x91, 0x50, 0x50, 0x90, 0x60, 0x01, 0x82, 0x03, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x01, 0x60, 0x00, 0x90, 0x91, 0x92, 0x90, 0x91, 0x90, 0x91, 0x61, 0x01, 0x00, 0x0a, 0x81, 0x54, 0x81, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0x19, 0x16, 0x90, 0x83, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x02, 0x17, 0x90, 0x55, 0x50, 0x03, 0x60, 0x03, 0x60, 0x00, 0x33, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x90, 0x81, 0x52, 0x60, 0x20, 0x01, 0x60, 0x00, 0x20, 0x60, 0x02, 0x01, 0x81, 0x90, 0x55, 0x50, 0x61, 0x08, 0x41, 0x56, 0x5b, 0x60, 0x01, 0x60, 0x03, 0x60, 0x00, 0x33, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x90, 0x81, 0x52, 0x60, 0x20, 0x01, 0x60, 0x00, 0x20, 0x60, 0x01, 0x01, 0x60, 0x00, 0x82, 0x82, 0x54, 0x01, 0x92, 0x50, 0x50, 0x81, 0x90, 0x55, 0x50, 0x5b, 0x60, 0x04, 0x33, 0x90, 0x80, 0x60, 0x01, 0x81, 0x54, 0x01, 0x80, 0x82, 0x55, 0x80, 0x91, 0x50, 0x50, 0x90, 0x60, 0x01, 0x82, 0x03, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x01, 0x60, 0x00, 0x90, 0x91, 0x92, 0x90, 0x91, 0x90, 0x91, 0x61, 0x01, 0x00, 0x0a, 0x81, 0x54, 0x81, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0x19, 0x16, 0x90, 0x83, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x02, 0x17, 0x90, 0x55, 0x50, 0x50, 0x7f, 0x76, 0x04, 0x1b, 0x6e, 0x81, 0x30, 0x99, 0x58, 0x74, 0xe7, 0x9e, 0x75, 0x1d, 0x28, 0x45, 0x36, 0xc3, 0x72, 0x42, 0xcb, 0x01, 0x4f, 0xb0, 0x58, 0x4e, 0xde, 0x1d, 0x1e, 0x64, 0xce, 0x03, 0xc9, 0x60, 0x03, 0x60, 0x00, 0x33, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x90, 0x81, 0x52, 0x60, 0x20, 0x01, 0x60, 0x00, 0x20, 0x60, 0x00, 0x01, 0x60, 0x03, 0x60, 0x00, 0x33, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x90, 0x81, 0x52, 0x60, 0x20, 0x01, 0x60, 0x00, 0x20, 0x60, 0x01, 0x01, 0x54, 0x60, 0x40, 0x51, 0x80, 0x80, 0x60, 0x20, 0x01, 0x83, 0x81, 0x52, 0x60, 0x20, 0x01, 0x82, 0x81, 0x03, 0x82, 0x52, 0x84, 0x81, 0x81, 0x54, 0x60, 0x01, 0x81, 0x60, 0x01, 0x16, 0x15, 0x61, 0x01, 0x00, 0x02, 0x03, 0x16, 0x60, 0x02, 0x90, 0x04, 0x81, 0x52, 0x60, 0x20, 0x01, 0x91, 0x50, 0x80, 0x54, 0x60, 0x01, 0x81, 0x60, 0x01, 0x16, 0x15, 0x61, 0x01, 0x00, 0x02, 0x03, 0x16, 0x60, 0x02, 0x90, 0x04, 0x80, 0x15, 0x61, 0x09, 0xdc, 0x57, 0x80, 0x60, 0x1f, 0x10, 0x61, 0x09, 0xb1, 0x57, 0x61, 0x01, 0x00, 0x80, 0x83, 0x54, 0x04, 0x02, 0x83, 0x52, 0x91, 0x60, 0x20, 0x01, 0x91, 0x61, 0x09, 0xdc, 0x56, 0x5b, 0x82, 0x01, 0x91, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x90, 0x5b, 0x81, 0x54, 0x81, 0x52, 0x90, 0x60, 0x01, 0x01, 0x90, 0x60, 0x20, 0x01, 0x80, 0x83, 0x11, 0x61, 0x09, 0xbf, 0x57, 0x82, 0x90, 0x03, 0x60, 0x1f, 0x16, 0x82, 0x01, 0x91, 0x5b, 0x50, 0x50, 0x93, 0x50, 0x50, 0x50, 0x50, 0x60, 0x40, 0x51, 0x80, 0x91, 0x03, 0x90, 0xa1, 0x50, 0x56, 0x5b, 0x60, 0x08, 0x60, 0x00, 0x90, 0x54, 0x90, 0x61, 0x01, 0x00, 0x0a, 0x90, 0x04, 0x60, 0xff, 0x16, 0x81, 0x56, 0x5b, 0x60, 0x00, 0x60, 0x01, 0x60, 0x00, 0x90, 0x54, 0x90, 0x61, 0x01, 0x00, 0x0a, 0x90, 0x04, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x33, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x14, 0x15, 0x15, 0x61, 0x0a, 0x5f, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x60, 0x00, 0x60, 0x04, 0x80, 0x54, 0x90, 0x50, 0x11, 0x15, 0x15, 0x61, 0x0a, 0x73, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x60, 0x04, 0x80, 0x54, 0x90, 0x50, 0x61, 0x0a, 0x81, 0x61, 0x13, 0x39, 0x56, 0x5b, 0x81, 0x15, 0x15, 0x61, 0x0a, 0x8a, 0x57, 0xfe, 0x5b, 0x06, 0x90, 0x50, 0x60, 0x04, 0x81, 0x81, 0x54, 0x81, 0x10, 0x15, 0x15, 0x61, 0x0a, 0x9c, 0x57, 0xfe, 0x5b, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x01, 0x60, 0x00, 0x90, 0x54, 0x90, 0x61, 0x01, 0x00, 0x0a, 0x90, 0x04, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x61, 0x08, 0xfc, 0x30, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x31, 0x90, 0x81, 0x15, 0x02, 0x90, 0x60, 0x40, 0x51, 0x60, 0x00, 0x60, 0x40, 0x51, 0x80, 0x83, 0x03, 0x81, 0x85, 0x88, 0x88, 0xf1, 0x93, 0x50, 0x50, 0x50, 0x50, 0x15, 0x80, 0x15, 0x61, 0x0b, 0x23, 0x57, 0x3d, 0x60, 0x00, 0x80, 0x3e, 0x3d, 0x60, 0x00, 0xfd, 0x5b, 0x50, 0x60, 0x03, 0x60, 0x00, 0x60, 0x04, 0x83, 0x81, 0x54, 0x81, 0x10, 0x15, 0x15, 0x61, 0x0b, 0x37, 0x57, 0xfe, 0x5b, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x01, 0x60, 0x00, 0x90, 0x54, 0x90, 0x61, 0x01, 0x00, 0x0a, 0x90, 0x04, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x90, 0x81, 0x52, 0x60, 0x20, 0x01, 0x60, 0x00, 0x20, 0x60, 0x00, 0x01, 0x60, 0x05, 0x60, 0x00, 0x01, 0x90, 0x80, 0x54, 0x60, 0x01, 0x81, 0x60, 0x01, 0x16, 0x15, 0x61, 0x01, 0x00, 0x02, 0x03, 0x16, 0x60, 0x02, 0x90, 0x04, 0x61, 0x0b, 0xc3, 0x92, 0x91, 0x90, 0x61, 0x14, 0x4b, 0x56, 0x5b, 0x50, 0x60, 0x03, 0x60, 0x00, 0x60, 0x04, 0x83, 0x81, 0x54, 0x81, 0x10, 0x15, 0x15, 0x61, 0x0b, 0xd7, 0x57, 0xfe, 0x5b, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x01, 0x60, 0x00, 0x90, 0x54, 0x90, 0x61, 0x01, 0x00, 0x0a, 0x90, 0x04, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x90, 0x81, 0x52, 0x60, 0x20, 0x01, 0x60, 0x00, 0x20, 0x60, 0x01, 0x01, 0x54, 0x60, 0x05, 0x60, 0x01, 0x01, 0x81, 0x90, 0x55, 0x50, 0x60, 0x00, 0x60, 0x40, 0x51, 0x90, 0x80, 0x82, 0x52, 0x80, 0x60, 0x20, 0x02, 0x60, 0x20, 0x01, 0x82, 0x01, 0x60, 0x40, 0x52, 0x80, 0x15, 0x61, 0x0c, 0x79, 0x57, 0x81, 0x60, 0x20, 0x01, 0x60, 0x20, 0x82, 0x02, 0x80, 0x38, 0x83, 0x39, 0x80, 0x82, 0x01, 0x91, 0x50, 0x50, 0x90, 0x50, 0x5b, 0x50, 0x60, 0x04, 0x90, 0x80, 0x51, 0x90, 0x60, 0x20, 0x01, 0x90, 0x61, 0x0c, 0x8f, 0x92, 0x91, 0x90, 0x61, 0x14, 0xd2, 0x56, 0x5b, 0x50, 0x60, 0x00, 0x60, 0x40, 0x51, 0x90, 0x80, 0x82, 0x52, 0x80, 0x60, 0x20, 0x02, 0x60, 0x20, 0x01, 0x82, 0x01, 0x60, 0x40, 0x52, 0x80, 0x15, 0x61, 0x0c, 0xc0, 0x57, 0x81, 0x60, 0x20, 0x01, 0x60, 0x20, 0x82, 0x02, 0x80, 0x38, 0x83, 0x39, 0x80, 0x82, 0x01, 0x91, 0x50, 0x50, 0x90, 0x50, 0x5b, 0x50, 0x60, 0x02, 0x90, 0x80, 0x51, 0x90, 0x60, 0x20, 0x01, 0x90, 0x61, 0x0c, 0xd6, 0x92, 0x91, 0x90, 0x61, 0x14, 0xd2, 0x56, 0x5b, 0x50, 0x60, 0x00, 0x60, 0x08, 0x60, 0x00, 0x61, 0x01, 0x00, 0x0a, 0x81, 0x54, 0x81, 0x60, 0xff, 0x02, 0x19, 0x16, 0x90, 0x83, 0x15, 0x15, 0x02, 0x17, 0x90, 0x55, 0x50, 0x7f, 0xd6, 0xd1, 0xee, 0xba, 0x63, 0x92, 0x54, 0xbd, 0x05, 0xe3, 0x62, 0x61, 0xae, 0x29, 0x9a, 0xf2, 0x45, 0x32, 0x8a, 0xb9, 0x97, 0xfd, 0x9b, 0x78, 0x23, 0xd5, 0xff, 0xf1, 0x7f, 0x1b, 0x74, 0xa4, 0x60, 0x05, 0x60, 0x00, 0x01, 0x60, 0x05, 0x60, 0x01, 0x01, 0x54, 0x60, 0x40, 0x51, 0x80, 0x80, 0x60, 0x20, 0x01, 0x83, 0x81, 0x52, 0x60, 0x20, 0x01, 0x82, 0x81, 0x03, 0x82, 0x52, 0x84, 0x81, 0x81, 0x54, 0x60, 0x01, 0x81, 0x60, 0x01, 0x16, 0x15, 0x61, 0x01, 0x00, 0x02, 0x03, 0x16, 0x60, 0x02, 0x90, 0x04, 0x81, 0x52, 0x60, 0x20, 0x01, 0x91, 0x50, 0x80, 0x54, 0x60, 0x01, 0x81, 0x60, 0x01, 0x16, 0x15, 0x61, 0x01, 0x00, 0x02, 0x03, 0x16, 0x60, 0x02, 0x90, 0x04, 0x80, 0x15, 0x61, 0x0d, 0xad, 0x57, 0x80, 0x60, 0x1f, 0x10, 0x61, 0x0d, 0x82, 0x57, 0x61, 0x01, 0x00, 0x80, 0x83, 0x54, 0x04, 0x02, 0x83, 0x52, 0x91, 0x60, 0x20, 0x01, 0x91, 0x61, 0x0d, 0xad, 0x56, 0x5b, 0x82, 0x01, 0x91, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x90, 0x5b, 0x81, 0x54, 0x81, 0x52, 0x90, 0x60, 0x01, 0x01, 0x90, 0x60, 0x20, 0x01, 0x80, 0x83, 0x11, 0x61, 0x0d, 0x90, 0x57, 0x82, 0x90, 0x03, 0x60, 0x1f, 0x16, 0x82, 0x01, 0x91, 0x5b, 0x50, 0x50, 0x93, 0x50, 0x50, 0x50, 0x50, 0x60, 0x40, 0x51, 0x80, 0x91, 0x03, 0x90, 0xa1, 0x50, 0x56, 0x5b, 0x60, 0x00, 0x80, 0x54, 0x60, 0x01, 0x81, 0x60, 0x01, 0x16, 0x15, 0x61, 0x01, 0x00, 0x02, 0x03, 0x16, 0x60, 0x02, 0x90, 0x04, 0x80, 0x60, 0x1f, 0x01, 0x60, 0x20, 0x80, 0x91, 0x04, 0x02, 0x60, 0x20, 0x01, 0x60, 0x40, 0x51, 0x90, 0x81, 0x01, 0x60, 0x40, 0x52, 0x80, 0x92, 0x91, 0x90, 0x81, 0x81, 0x52, 0x60, 0x20, 0x01, 0x82, 0x80, 0x54, 0x60, 0x01, 0x81, 0x60, 0x01, 0x16, 0x15, 0x61, 0x01, 0x00, 0x02, 0x03, 0x16, 0x60, 0x02, 0x90, 0x04, 0x80, 0x15, 0x61, 0x0e, 0x55, 0x57, 0x80, 0x60, 0x1f, 0x10, 0x61, 0x0e, 0x2a, 0x57, 0x61, 0x01, 0x00, 0x80, 0x83, 0x54, 0x04, 0x02, 0x83, 0x52, 0x91, 0x60, 0x20, 0x01, 0x91, 0x61, 0x0e, 0x55, 0x56, 0x5b, 0x82, 0x01, 0x91, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x90, 0x5b, 0x81, 0x54, 0x81, 0x52, 0x90, 0x60, 0x01, 0x01, 0x90, 0x60, 0x20, 0x01, 0x80, 0x83, 0x11, 0x61, 0x0e, 0x38, 0x57, 0x82, 0x90, 0x03, 0x60, 0x1f, 0x16, 0x82, 0x01, 0x91, 0x5b, 0x50, 0x50, 0x50, 0x50, 0x50, 0x81, 0x56, 0x5b, 0x60, 0x01, 0x60, 0x00, 0x90, 0x54, 0x90, 0x61, 0x01, 0x00, 0x0a, 0x90, 0x04, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x56, 0x5b, 0x60, 0x02, 0x81, 0x81, 0x54, 0x81, 0x10, 0x15, 0x15, 0x61, 0x0e, 0x92, 0x57, 0xfe, 0x5b, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x01, 0x60, 0x00, 0x91, 0x50, 0x54, 0x90, 0x61, 0x01, 0x00, 0x0a, 0x90, 0x04, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x56, 0x5b, 0x60, 0x60, 0x60, 0x00, 0x61, 0x0e, 0xce, 0x83, 0x61, 0x12, 0x6e, 0x56, 0x5b, 0x15, 0x61, 0x0e, 0xf3, 0x57, 0x60, 0x00, 0x60, 0x20, 0x60, 0x40, 0x51, 0x90, 0x81, 0x01, 0x60, 0x40, 0x52, 0x80, 0x60, 0x00, 0x81, 0x52, 0x50, 0x90, 0x80, 0x90, 0x50, 0x91, 0x50, 0x91, 0x50, 0x61, 0x10, 0x19, 0x56, 0x5b, 0x60, 0x03, 0x60, 0x00, 0x84, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x90, 0x81, 0x52, 0x60, 0x20, 0x01, 0x60, 0x00, 0x20, 0x60, 0x00, 0x01, 0x60, 0x03, 0x60, 0x00, 0x85, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x90, 0x81, 0x52, 0x60, 0x20, 0x01, 0x60, 0x00, 0x20, 0x60, 0x01, 0x01, 0x54, 0x81, 0x80, 0x54, 0x60, 0x01, 0x81, 0x60, 0x01, 0x16, 0x15, 0x61, 0x01, 0x00, 0x02, 0x03, 0x16, 0x60, 0x02, 0x90, 0x04, 0x80, 0x60, 0x1f, 0x01, 0x60, 0x20, 0x80, 0x91, 0x04, 0x02, 0x60, 0x20, 0x01, 0x60, 0x40, 0x51, 0x90, 0x81, 0x01, 0x60, 0x40, 0x52, 0x80, 0x92, 0x91, 0x90, 0x81, 0x81, 0x52, 0x60, 0x20, 0x01, 0x82, 0x80, 0x54, 0x60, 0x01, 0x81, 0x60, 0x01, 0x16, 0x15, 0x61, 0x01, 0x00, 0x02, 0x03, 0x16, 0x60, 0x02, 0x90, 0x04, 0x80, 0x15, 0x61, 0x10, 0x0d, 0x57, 0x80, 0x60, 0x1f, 0x10, 0x61, 0x0f, 0xe2, 0x57, 0x61, 0x01, 0x00, 0x80, 0x83, 0x54, 0x04, 0x02, 0x83, 0x52, 0x91, 0x60, 0x20, 0x01, 0x91, 0x61, 0x10, 0x0d, 0x56, 0x5b, 0x82, 0x01, 0x91, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x90, 0x5b, 0x81, 0x54, 0x81, 0x52, 0x90, 0x60, 0x01, 0x01, 0x90, 0x60, 0x20, 0x01, 0x80, 0x83, 0x11, 0x61, 0x0f, 0xf0, 0x57, 0x82, 0x90, 0x03, 0x60, 0x1f, 0x16, 0x82, 0x01, 0x91, 0x5b, 0x50, 0x50, 0x50, 0x50, 0x50, 0x91, 0x50, 0x91, 0x50, 0x91, 0x50, 0x5b, 0x91, 0x50, 0x91, 0x56, 0x5b, 0x60, 0x0a, 0x54, 0x81, 0x56, 0x5b, 0x60, 0x09, 0x54, 0x81, 0x56, 0x5b, 0x60, 0x60, 0x60, 0x02, 0x80, 0x54, 0x80, 0x60, 0x20, 0x02, 0x60, 0x20, 0x01, 0x60, 0x40, 0x51, 0x90, 0x81, 0x01, 0x60, 0x40, 0x52, 0x80, 0x92, 0x91, 0x90, 0x81, 0x81, 0x52, 0x60, 0x20, 0x01, 0x82, 0x80, 0x54, 0x80, 0x15, 0x61, 0x10, 0xae, 0x57, 0x60, 0x20, 0x02, 0x82, 0x01, 0x91, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x90, 0x5b, 0x81, 0x60, 0x00, 0x90, 0x54, 0x90, 0x61, 0x01, 0x00, 0x0a, 0x90, 0x04, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x90, 0x60, 0x01, 0x01, 0x90, 0x80, 0x83, 0x11, 0x61, 0x10, 0x64, 0x57, 0x5b, 0x50, 0x50, 0x50, 0x50, 0x50, 0x90, 0x50, 0x90, 0x56, 0x5b, 0x60, 0x01, 0x60, 0x00, 0x90, 0x54, 0x90, 0x61, 0x01, 0x00, 0x0a, 0x90, 0x04, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x33, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x14, 0x15, 0x15, 0x61, 0x11, 0x14, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x60, 0x01, 0x60, 0x08, 0x60, 0x00, 0x61, 0x01, 0x00, 0x0a, 0x81, 0x54, 0x81, 0x60, 0xff, 0x02, 0x19, 0x16, 0x90, 0x83, 0x15, 0x15, 0x02, 0x17, 0x90, 0x55, 0x50, 0x60, 0x00, 0x82, 0x14, 0x61, 0x11, 0x3d, 0x57, 0x81, 0x61, 0x11, 0x40, 0x56, 0x5b, 0x60, 0x01, 0x5b, 0x60, 0x09, 0x81, 0x90, 0x55, 0x50, 0x60, 0x00, 0x81, 0x14, 0x61, 0x11, 0x54, 0x57, 0x80, 0x61, 0x11, 0x57, 0x56, 0x5b, 0x60, 0x01, 0x5b, 0x60, 0x0a, 0x81, 0x90, 0x55, 0x50, 0x50, 0x50, 0x56, 0x5b, 0x60, 0x00, 0x30, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x31, 0x90, 0x50, 0x90, 0x56, 0x5b, 0x60, 0x05, 0x80, 0x60, 0x00, 0x01, 0x80, 0x54, 0x60, 0x01, 0x81, 0x60, 0x01, 0x16, 0x15, 0x61, 0x01, 0x00, 0x02, 0x03, 0x16, 0x60, 0x02, 0x90, 0x04, 0x80, 0x60, 0x1f, 0x01, 0x60, 0x20, 0x80, 0x91, 0x04, 0x02, 0x60, 0x20, 0x01, 0x60, 0x40, 0x51, 0x90, 0x81, 0x01, 0x60, 0x40, 0x52, 0x80, 0x92, 0x91, 0x90, 0x81, 0x81, 0x52, 0x60, 0x20, 0x01, 0x82, 0x80, 0x54, 0x60, 0x01, 0x81, 0x60, 0x01, 0x16, 0x15, 0x61, 0x01, 0x00, 0x02, 0x03, 0x16, 0x60, 0x02, 0x90, 0x04, 0x80, 0x15, 0x61, 0x12, 0x1a, 0x57, 0x80, 0x60, 0x1f, 0x10, 0x61, 0x11, 0xef, 0x57, 0x61, 0x01, 0x00, 0x80, 0x83, 0x54, 0x04, 0x02, 0x83, 0x52, 0x91, 0x60, 0x20, 0x01, 0x91, 0x61, 0x12, 0x1a, 0x56, 0x5b, 0x82, 0x01, 0x91, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x90, 0x5b, 0x81, 0x54, 0x81, 0x52, 0x90, 0x60, 0x01, 0x01, 0x90, 0x60, 0x20, 0x01, 0x80, 0x83, 0x11, 0x61, 0x11, 0xfd, 0x57, 0x82, 0x90, 0x03, 0x60, 0x1f, 0x16, 0x82, 0x01, 0x91, 0x5b, 0x50, 0x50, 0x50, 0x50, 0x50, 0x90, 0x80, 0x60, 0x01, 0x01, 0x54, 0x90, 0x80, 0x60, 0x02, 0x01, 0x54, 0x90, 0x50, 0x83, 0x56, 0x5b, 0x60, 0x04, 0x81, 0x81, 0x54, 0x81, 0x10, 0x15, 0x15, 0x61, 0x12, 0x3f, 0x57, 0xfe, 0x5b, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x01, 0x60, 0x00, 0x91, 0x50, 0x54, 0x90, 0x61, 0x01, 0x00, 0x0a, 0x90, 0x04, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x56, 0x5b, 0x60, 0x00, 0x80, 0x60, 0x02, 0x80, 0x54, 0x90, 0x50, 0x14, 0x15, 0x61, 0x12, 0x86, 0x57, 0x60, 0x01, 0x90, 0x50, 0x61, 0x13, 0x34, 0x56, 0x5b, 0x81, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x60, 0x02, 0x60, 0x03, 0x60, 0x00, 0x85, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x90, 0x81, 0x52, 0x60, 0x20, 0x01, 0x60, 0x00, 0x20, 0x60, 0x02, 0x01, 0x54, 0x81, 0x54, 0x81, 0x10, 0x15, 0x15, 0x61, 0x12, 0xee, 0x57, 0xfe, 0x5b, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x01, 0x60, 0x00, 0x90, 0x54, 0x90, 0x61, 0x01, 0x00, 0x0a, 0x90, 0x04, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x14, 0x15, 0x90, 0x50, 0x5b, 0x91, 0x90, 0x50, 0x56, 0x5b, 0x60, 0x00, 0x44, 0x42, 0x60, 0x04, 0x60, 0x40, 0x51, 0x80, 0x84, 0x81, 0x52, 0x60, 0x20, 0x01, 0x83, 0x81, 0x52, 0x60, 0x20, 0x01, 0x82, 0x80, 0x54, 0x80, 0x15, 0x61, 0x13, 0xb3, 0x57, 0x60, 0x20, 0x02, 0x82, 0x01, 0x91, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x90, 0x5b, 0x81, 0x60, 0x00, 0x90, 0x54, 0x90, 0x61, 0x01, 0x00, 0x0a, 0x90, 0x04, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x90, 0x60, 0x01, 0x01, 0x90, 0x80, 0x83, 0x11, 0x61, 0x13, 0x69, 0x57, 0x5b, 0x50, 0x50, 0x93, 0x50, 0x50, 0x50, 0x50, 0x60, 0x40, 0x51, 0x80, 0x91, 0x03, 0x90, 0x20, 0x60, 0x01, 0x90, 0x04, 0x90, 0x50, 0x90, 0x56, 0x5b, 0x82, 0x80, 0x54, 0x60, 0x01, 0x81, 0x60, 0x01, 0x16, 0x15, 0x61, 0x01, 0x00, 0x02, 0x03, 0x16, 0x60, 0x02, 0x90, 0x04, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x90, 0x60, 0x1f, 0x01, 0x60, 0x20, 0x90, 0x04, 0x81, 0x01, 0x92, 0x82, 0x60, 0x1f, 0x10, 0x61, 0x14, 0x0c, 0x57, 0x80, 0x51, 0x60, 0xff, 0x19, 0x16, 0x83, 0x80, 0x01, 0x17, 0x85, 0x55, 0x61, 0x14, 0x3a, 0x56, 0x5b, 0x82, 0x80, 0x01, 0x60, 0x01, 0x01, 0x85, 0x55, 0x82, 0x15, 0x61, 0x14, 0x3a, 0x57, 0x91, 0x82, 0x01, 0x5b, 0x82, 0x81, 0x11, 0x15, 0x61, 0x14, 0x39, 0x57, 0x82, 0x51, 0x82, 0x55, 0x91, 0x60, 0x20, 0x01, 0x91, 0x90, 0x60, 0x01, 0x01, 0x90, 0x61, 0x14, 0x1e, 0x56, 0x5b, 0x5b, 0x50, 0x90, 0x50, 0x61, 0x14, 0x47, 0x91, 0x90, 0x61, 0x15, 0x5c, 0x56, 0x5b, 0x50, 0x90, 0x56, 0x5b, 0x82, 0x80, 0x54, 0x60, 0x01, 0x81, 0x60, 0x01, 0x16, 0x15, 0x61, 0x01, 0x00, 0x02, 0x03, 0x16, 0x60, 0x02, 0x90, 0x04, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x90, 0x60, 0x1f, 0x01, 0x60, 0x20, 0x90, 0x04, 0x81, 0x01, 0x92, 0x82, 0x60, 0x1f, 0x10, 0x61, 0x14, 0x84, 0x57, 0x80, 0x54, 0x85, 0x55, 0x61, 0x14, 0xc1, 0x56, 0x5b, 0x82, 0x80, 0x01, 0x60, 0x01, 0x01, 0x85, 0x55, 0x82, 0x15, 0x61, 0x14, 0xc1, 0x57, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x91, 0x60, 0x1f, 0x01, 0x60, 0x20, 0x90, 0x04, 0x82, 0x01, 0x5b, 0x82, 0x81, 0x11, 0x15, 0x61, 0x14, 0xc0, 0x57, 0x82, 0x54, 0x82, 0x55, 0x91, 0x60, 0x01, 0x01, 0x91, 0x90, 0x60, 0x01, 0x01, 0x90, 0x61, 0x14, 0xa5, 0x56, 0x5b, 0x5b, 0x50, 0x90, 0x50, 0x61, 0x14, 0xce, 0x91, 0x90, 0x61, 0x15, 0x5c, 0x56, 0x5b, 0x50, 0x90, 0x56, 0x5b, 0x82, 0x80, 0x54, 0x82, 0x82, 0x55, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x90, 0x81, 0x01, 0x92, 0x82, 0x15, 0x61, 0x15, 0x4b, 0x57, 0x91, 0x60, 0x20, 0x02, 0x82, 0x01, 0x5b, 0x82, 0x81, 0x11, 0x15, 0x61, 0x15, 0x4a, 0x57, 0x82, 0x51, 0x82, 0x60, 0x00, 0x61, 0x01, 0x00, 0x0a, 0x81, 0x54, 0x81, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0x19, 0x16, 0x90, 0x83, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x02, 0x17, 0x90, 0x55, 0x50, 0x91, 0x60, 0x20, 0x01, 0x91, 0x90, 0x60, 0x01, 0x01, 0x90, 0x61, 0x14, 0xf2, 0x56, 0x5b, 0x5b, 0x50, 0x90, 0x50, 0x61, 0x15, 0x58, 0x91, 0x90, 0x61, 0x15, 0x81, 0x56, 0x5b, 0x50, 0x90, 0x56, 0x5b, 0x61, 0x15, 0x7e, 0x91, 0x90, 0x5b, 0x80, 0x82, 0x11, 0x15, 0x61, 0x15, 0x7a, 0x57, 0x60, 0x00, 0x81, 0x60, 0x00, 0x90, 0x55, 0x50, 0x60, 0x01, 0x01, 0x61, 0x15, 0x62, 0x56, 0x5b, 0x50, 0x90, 0x56, 0x5b, 0x90, 0x56, 0x5b, 0x61, 0x15, 0xc1, 0x91, 0x90, 0x5b, 0x80, 0x82, 0x11, 0x15, 0x61, 0x15, 0xbd, 0x57, 0x60, 0x00, 0x81, 0x81, 0x61, 0x01, 0x00, 0x0a, 0x81, 0x54, 0x90, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0x19, 0x16, 0x90, 0x55, 0x50, 0x60, 0x01, 0x01, 0x61, 0x15, 0x87, 0x56, 0x5b, 0x50, 0x90, 0x56, 0x5b, 0x90, 0x56, 0x00, 0xa1, 0x65, 0x62, 0x7a, 0x7a, 0x72, 0x30, 0x58, 0x20, 0xa8, 0xfb, 0x9f, 0x06, 0x53, 0x3d, 0xb9, 0x44, 0x22, 0x03, 0x33, 0x2b, 0xcb, 0x5c, 0x2e, 0xdf, 0x68, 0xb6, 0x99, 0xd5, 0x4b, 0x7d, 0xb0, 0xbe, 0x9b, 0x1c, 0xa7, 0x85, 0x28, 0x47, 0x5c, 0x18, 0x00, 0x29}; - // machine::context ctx = {true, 0x00}; - // machine::message msg = {}; - // machine::chain_adapter adapter = make_chain_adapter(); - // machine::machine m(ctx, input, msg, adapter); - // assert_message( "machine should start running", m.get_state() == machine::machine_state::running ); + test_that("push opcodes / to_big_word work") + { + std::vector input = {0x7f, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00}; + machine::context ctx = {true, 0x00}; + machine::message msg = {}; + machine::chain_adapter adapter = make_chain_adapter(); + machine::machine m(ctx, input, msg, adapter); + assert_message( "machine should start running", m.get_state() == machine::machine_state::running ); - // std::string line; - // while (m.is_running()) - // { - // m.step(); - // while ( std::getline(m.get_logger(), line) ) - // std::cerr << "\e[36m" << "LOG: " << line << "\e[0m" << std::endl; - // std::cout << m.to_json() << std::endl; - // } - // while ( std::getline(m.get_logger(), line) ) - // std::cerr << "\e[36m" << "LOG: " << line << "\e[0m" << std::endl; - // std::cout << m.to_json() << std::endl; + std::string line; + while (m.is_running()) + { + m.step(); + while ( std::getline(m.get_logger(), line) ) + std::cerr << "\e[36m" << "LOG: " << line << "\e[0m" << std::endl; + std::cout << m.to_json() << std::endl; + } + while ( std::getline(m.get_logger(), line) ) + std::cerr << "\e[36m" << "LOG: " << line << "\e[0m" << std::endl; + std::cout << m.to_json() << std::endl; - // assert_message( "machine should stop when done executing", m.get_state() == machine::machine_state::stopped ); - // assert_message( "stack has correct length", m.stack_length() == 0 ); - //} + assert_message( "machine should stop when done executing", m.get_state() == machine::machine_state::stopped ); + assert_message( "stack has correct length", m.stack_length() == 1 ); + } return 0; } From 3b86400453741cae7077c44aa281a9127d7c57c5 Mon Sep 17 00:00:00 2001 From: Liam Noroian Date: Sun, 5 Dec 2021 00:01:54 -0800 Subject: [PATCH 78/96] Smart contract invocation --- .../chain/include/xgt/chain/wallet_object.hpp | 1 + libraries/chain/xgt_evaluator.cpp | 87 +++- .../include/xgt/protocol/xgt_operations.hpp | 4 +- libraries/vendor/xgtvm/libraries/machine.cpp | 401 +++++++++++------- libraries/vendor/xgtvm/libraries/machine.hpp | 7 +- libraries/vendor/xgtvm/programs/xgtvm.cpp | 2 +- .../vendor/xgtvm/programs/xgtvm_tests.cpp | 159 +++---- 7 files changed, 408 insertions(+), 253 deletions(-) diff --git a/libraries/chain/include/xgt/chain/wallet_object.hpp b/libraries/chain/include/xgt/chain/wallet_object.hpp index 51b81373..d8806883 100644 --- a/libraries/chain/include/xgt/chain/wallet_object.hpp +++ b/libraries/chain/include/xgt/chain/wallet_object.hpp @@ -90,6 +90,7 @@ namespace xgt { namespace chain { id_type id; wallet_name_type account; + fc::ripemd160 address_ripemd160; shared_authority recovery; ///< used for backup control, can set recovery or money shared_authority money; ///< used for all monetary operations, can set money or social diff --git a/libraries/chain/xgt_evaluator.cpp b/libraries/chain/xgt_evaluator.cpp index 969257f7..1a1301ee 100644 --- a/libraries/chain/xgt_evaluator.cpp +++ b/libraries/chain/xgt_evaluator.cpp @@ -18,6 +18,9 @@ #include #include +#include +#include +#include #include @@ -206,6 +209,7 @@ void wallet_create_evaluator::do_apply( const wallet_create_operation& o ) auth.recovery = o.recovery; auth.money = o.money; auth.social = o.social; + auth.address_ripemd160 = o.address_ripemd160; auth.last_recovery_update = fc::time_point_sec::min(); }); } @@ -1023,6 +1027,7 @@ fc::ripemd160 generate_random_ripemd160() return fc::ripemd160::hash(buf, buflen); } +// XXX Needs work -- does not consistently convert values boost::multiprecision::uint256_t ripemd160_to_uint256_t(fc::ripemd160 h) { boost::multiprecision::uint256_t n(0); @@ -1199,15 +1204,43 @@ std::map< uint64_t, std::function > energy_cost { {machine::create2_opcode, [](machine::machine& m){ return 0; }}, // TODO -- create2 -- variable {machine::staticcall_opcode, [](machine::machine& m){ return 0; }}, // TODO -- staticcall -- variable {machine::revert_opcode, [](machine::machine& m){ return 0; }}, + {machine::invalid_opcode, [](machine::machine& m){ return 0; }}, {machine::selfdestruct_opcode, [](machine::machine& m){ return 0; }} // TODO -- selfdestruct -- variable }; -std::vector contract_invoke(chain::database& _db, wallet_name_type o, wallet_name_type caller, contract_hash_type contract_hash, uint64_t energy,std::vector args, map< fc::sha256, fc::sha256 >& storage) +boost::multiprecision::uint256_t address_to_uint256_t(const std::string& base58str) { + std::string prefix( XGT_ADDRESS_PREFIX ); + + const size_t prefix_len = prefix.size(); + auto b58 = base58str.substr( prefix_len ); + auto r160 = fc::ripemd160::hash(b58); + + std::stringstream ss; + ss << std::hex << r160.str(); + boost::multiprecision::uint256_t x; + ss >> x; + return x; +}; + +std::vector contract_invoke(chain::database& _db, wallet_name_type o, wallet_name_type caller, contract_hash_type contract_hash, uint64_t value, uint64_t energy, std::vector args, map< fc::sha256, fc::sha256 >& storage) { wlog("contract_invoke another contract ${w}", ("w",contract_hash)); const auto& c = _db.get_contract(contract_hash); - - machine::message msg = {}; + const std::string& address_ref = std::string(caller); + + boost::multiprecision::uint256_t converted_address = address_to_uint256_t(address_ref); + + machine::message msg = { + 0, + 0, + 0, + converted_address, + converted_address, + value, + args.size(), + args, + 0 + }; const bool is_debug = true; const uint64_t block_timestamp = static_cast( _db.head_block_time().sec_since_epoch() ); @@ -1235,12 +1268,11 @@ std::vector contract_invoke(chain::database& _db, wallet_name_typ machine::chain_adapter adapter = make_chain_adapter(_db, c.owner, tx_origin, contract_hash, storage); machine::machine m(ctx, code, msg, adapter); - m.print_stack(); - std::string line; while (m.is_running()) { - std::cerr << "step\n"; + std::cerr << "step\n" << std::endl; + std::cerr << m.to_json() << std::endl; m.step(); auto energy_callback = energy_cost[m.get_current_opcode()]; // Calculate energy cost and add to total @@ -1262,9 +1294,25 @@ std::vector contract_invoke(chain::database& _db, wallet_name_typ w.energybar.use_energy( energy_cost_incurred ); }); + // TODO make return value public in machine + wlog("contract_invoke return value ${w}", ("w",m.get_return_value())); return m.get_return_value(); } +std::string inspect(std::vector words) +{ + std::stringstream ss; + ss << "["; + for (size_t i = 0; i < words.size(); i++) + { + ss << std::to_string(words.at(i)); + if (i != words.size() -1) + ss << ", "; + } + ss << "]"; + return ss.str(); +} + machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type o, wallet_name_type c, contract_hash_type contract_hash, map& storage) { std::string owner(o); @@ -1272,14 +1320,21 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type std::function< std::string(std::vector) > sha3 = [&](std::vector memory) -> std::string { - std::string message(memory.begin(), memory.end()); + std::stringstream ss; + std::string message; + for (int i = 0; i < 32; i++) { + message += std::to_string(memory[i]); + } unsigned char output[32]; SHA3_CTX ctx; keccak_init(&ctx); keccak_update(&ctx, (unsigned char*)message.c_str(), message.size()); keccak_final(&ctx, output); - std::string fin((char*)output, 32); - return fin; + for (size_t i = 0; i < 32; i++) { + ss << std::hex << (machine::opcode)output[i]; + } + // std::string fin((char*)output, 32); + return ss.str(); }; std::function< uint64_t(std::string) > get_balance = [&](std::string address) -> uint64_t @@ -1341,7 +1396,7 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type else storage = map< fc::sha256, fc::sha256 >(); - auto result = contract_invoke(_db, o, c, contract_hash, energy, args, storage); + auto result = contract_invoke(_db, o, c, contract_hash, energy, static_cast(value), args, storage); if (cs) _db.modify< contract_storage_object >(*cs, [&](contract_storage_object& cs) { @@ -1374,7 +1429,7 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type else storage = map< fc::sha256, fc::sha256 >(); - auto result = contract_invoke(_db, o, c, contract_hash, energy, args, storage); + auto result = contract_invoke(_db, o, c, contract_hash, energy, 0, args, storage); if (cs) _db.modify< contract_storage_object >(*cs, [&](contract_storage_object& cs) { @@ -1395,7 +1450,7 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type std::function< std::vector(std::string, uint64_t, std::vector) > contract_staticcall = [&](std::string address, uint64_t energy, std::vector args) -> std::vector { map< fc::sha256, fc::sha256 > storage; // Should this be empty, or just immutable for `staticcall`? - auto result = contract_invoke(_db, o, c, contract_hash, energy, args, storage); + auto result = contract_invoke(_db, o, c, contract_hash, energy, 0, args, storage); return result; }; @@ -1428,10 +1483,9 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type return true; }; - std::function< bool(std::vector) > contract_return = [&](std::vector memory) -> bool + std::function< std::vector(std::vector) > contract_return = [&](std::vector memory) -> std::vector { - // TODO - return true; + return memory; }; std::function< bool(std::string) > self_destruct = [&](std::string address) -> bool @@ -1494,6 +1548,7 @@ void contract_invoke_evaluator::do_apply( const contract_invoke_operation& op ) uint64_t energy = 0; // TODO const contract_storage_object* cs = _db.find_contract_storage(contract_hash, op.caller); + map< fc::sha256, fc::sha256 > storage; if (cs != nullptr) { storage = cs->data; @@ -1504,7 +1559,7 @@ void contract_invoke_evaluator::do_apply( const contract_invoke_operation& op ) std::vector unsigned_args; std::copy(op.args.begin(), op.args.end(), std::back_inserter(unsigned_args)); - auto result = contract_invoke(_db, c.owner, op.caller, contract_hash, energy, unsigned_args, storage); + auto result = contract_invoke(_db, c.owner, op.caller, contract_hash, energy, op.value, unsigned_args, storage); if (cs != nullptr) { _db.modify< contract_storage_object >(*cs, [&](contract_storage_object& cs) { diff --git a/libraries/protocol/include/xgt/protocol/xgt_operations.hpp b/libraries/protocol/include/xgt/protocol/xgt_operations.hpp index 6ecbaa17..9d344a9f 100644 --- a/libraries/protocol/include/xgt/protocol/xgt_operations.hpp +++ b/libraries/protocol/include/xgt/protocol/xgt_operations.hpp @@ -16,6 +16,7 @@ namespace xgt { namespace protocol { asset fee; wallet_name_type creator; wallet_name_type new_wallet_name; + fc::ripemd160 address_ripemd160; authority recovery; authority money; authority social; @@ -605,6 +606,7 @@ namespace xgt { namespace protocol { { wallet_name_type caller; contract_hash_type contract_hash; + uint64_t value; vector args; void validate()const; @@ -663,4 +665,4 @@ FC_REFLECT( xgt::protocol::recover_wallet_operation, (account_to_recover)(new_re FC_REFLECT( xgt::protocol::change_recovery_wallet_operation, (account_to_recover)(new_recovery_account)(extensions) ); FC_REFLECT( xgt::protocol::contract_create_operation, (owner)(code) ); -FC_REFLECT( xgt::protocol::contract_invoke_operation, (caller)(contract_hash)(args) ); +FC_REFLECT( xgt::protocol::contract_invoke_operation, (caller)(contract_hash)(value)(args) ); diff --git a/libraries/vendor/xgtvm/libraries/machine.cpp b/libraries/vendor/xgtvm/libraries/machine.cpp index 3cd904c2..ac2e75cd 100644 --- a/libraries/vendor/xgtvm/libraries/machine.cpp +++ b/libraries/vendor/xgtvm/libraries/machine.cpp @@ -23,12 +23,14 @@ namespace machine return bytes[n]; } - void set_byte(boost::multiprecision::uint256_t& x, int n, int v) + uint16_t get_bytes(boost::multiprecision::uint256_t x, int n) { std::vector bytes; boost::multiprecision::export_bits(x, std::back_inserter(bytes), 8); - bytes[n] = v; - boost::multiprecision::import_bits(x, bytes.begin(), bytes.end()); + if (x > 255) { + return ((uint16_t)bytes[n] << 8) | bytes[n + 1]; + } + return bytes[n]; } size_t uint256_t_to_size_t(boost::multiprecision::uint256_t& x) @@ -53,57 +55,49 @@ namespace machine big_word to_big_word(word a, word b) { - big_word va = 0; - set_byte(va, 0, a); - set_byte(va, 1, b); + big_word va = ((big_word)a << 8) | b; return va; } big_word to_big_word(word a, word b, word c, word d) { - big_word va = 0; - set_byte(va, 0, a); - set_byte(va, 1, b); - set_byte(va, 2, c); - set_byte(va, 3, d); - return va; + big_word va = ((big_word)a << 8) | b; + big_word vb = (va << 8) | c; + big_word vc = (vb << 8) | d; + return vc; } big_word to_big_word(word a, word b, word c, word d, word e, word f, word g, word h) { - big_word va = 0; - set_byte(va, 0, a); - set_byte(va, 1, b); - set_byte(va, 2, c); - set_byte(va, 3, d); - set_byte(va, 4, e); - set_byte(va, 5, f); - set_byte(va, 6, g); - set_byte(va, 7, h); - return va; + big_word va = ((big_word)a << 8) | b; + big_word vb = (va << 8) | c; + big_word vc = (vb << 8) | d; + big_word vd = (vc << 8) | e; + big_word ve = (vd << 8) | f; + big_word vf = (ve << 8) | g; + big_word vg = (vf << 8) | h; + return vg; } big_word to_big_word(word a, word b, word c, word d, word e, word f, word g, word h, word i, word j, word k, word l, word m, word n, word o, word p) { - big_word va = 0; - set_byte(va, 0, a); - set_byte(va, 1, b); - set_byte(va, 2, c); - set_byte(va, 3, d); - set_byte(va, 4, e); - set_byte(va, 5, f); - set_byte(va, 6, g); - set_byte(va, 7, h); - set_byte(va, 8, i); - set_byte(va, 9, j); - set_byte(va, 10, k); - set_byte(va, 11, l); - set_byte(va, 12, m); - set_byte(va, 13, n); - set_byte(va, 14, o); - set_byte(va, 15, p); - return va; + big_word va = ((big_word)a << 8) | b; + big_word vb = (va << 8) | c; + big_word vc = (vb << 8) | d; + big_word vd = (vc << 8) | e; + big_word ve = (vd << 8) | f; + big_word vf = (ve << 8) | g; + big_word vg = (vf << 8) | h; + big_word vh = (vg << 8) | i; + big_word vi = (vh << 8) | j; + big_word vj = (vi << 8) | k; + big_word vk = (vj << 8) | l; + big_word vl = (vk << 8) | m; + big_word vm = (vl << 8) | n; + big_word vn = (vm << 8) | o; + big_word vo = (vn << 8) | p; + return vo; } big_word to_big_word(word a, word b, word c, word d, word e, word f, word g, @@ -111,40 +105,48 @@ namespace machine word q, word r, word s, word t, word u, word v, word w, word x, word y, word z, word aa, word ab, word ac, word ad, word ae, word af) { - big_word va = 0; - set_byte(va, 0, a); - set_byte(va, 1, b); - set_byte(va, 2, c); - set_byte(va, 3, d); - set_byte(va, 4, e); - set_byte(va, 5, f); - set_byte(va, 6, g); - set_byte(va, 7, h); - set_byte(va, 8, i); - set_byte(va, 9, j); - set_byte(va, 10, k); - set_byte(va, 11, l); - set_byte(va, 12, m); - set_byte(va, 13, n); - set_byte(va, 14, o); - set_byte(va, 15, p); - set_byte(va, 16, q); - set_byte(va, 17, r); - set_byte(va, 18, s); - set_byte(va, 19, t); - set_byte(va, 20, u); - set_byte(va, 21, v); - set_byte(va, 22, w); - set_byte(va, 23, x); - set_byte(va, 24, y); - set_byte(va, 25, z); - set_byte(va, 26, aa); - set_byte(va, 27, ab); - set_byte(va, 28, ac); - set_byte(va, 29, ad); - set_byte(va, 30, ae); - set_byte(va, 31, af); - return va; + big_word va = ((big_word)a << 8) | b; + big_word vb = (va << 8) | c; + big_word vc = (vb << 8) | d; + big_word vd = (vc << 8) | e; + big_word ve = (vd << 8) | f; + big_word vf = (ve << 8) | g; + big_word vg = (vf << 8) | h; + big_word vh = (vg << 8) | i; + big_word vi = (vh << 8) | j; + big_word vj = (vi << 8) | k; + big_word vk = (vj << 8) | l; + big_word vl = (vk << 8) | m; + big_word vm = (vl << 8) | n; + big_word vn = (vm << 8) | o; + big_word vo = (vn << 8) | p; + big_word vp = (vo << 8) | q; + big_word vq = (vp << 8) | r; + big_word vr = (vq << 8) | s; + big_word vs = (vr << 8) | t; + big_word vt = (vs << 8) | u; + big_word vu = (vt << 8) | v; + big_word vv = (vu << 8) | w; + big_word vw = (vv << 8) | x; + big_word vx = (vw << 8) | y; + big_word vy = (vx << 8) | z; + big_word vz = (vy << 8) | aa; + big_word vaa = (vz << 8) | ab; + big_word vab = (vaa << 8) | ac; + big_word vac = (vab << 8) | ad; + big_word vad = (vac << 8) | ae; + big_word vae = (vad << 8) | af; + return vae; + } + + std::vector from_big_word(big_word a) + { + std::vector vec; + for (size_t i = 0; i < 31; i++) { + vec.push_back(static_cast(((a >>= (8 * i)) & 0xFF))); + } + + return vec; } std::string inspect(std::vector words) @@ -153,7 +155,6 @@ namespace machine ss << "["; for (size_t i = 0; i < words.size(); i++) { - // TODO: Print hex ss << std::to_string(words.at(i)); if (i != words.size() - 1) ss << ", "; @@ -172,7 +173,6 @@ namespace machine { it = words.find(i); if (it != words.end()) { - // TODO: Print hex ss << std::to_string(it->second); ss << ", "; } @@ -220,8 +220,6 @@ namespace machine stack.push_front(s); } - // TODO: Make better - // TODO: Return string instead? void machine::print_stack() { for (auto it = stack.cbegin(); it != stack.cend(); ++it) @@ -259,14 +257,19 @@ namespace machine word a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, aa, ab, ac, ad, ae, af; big_word va, vb, vc, vd, ve, vf, vg, vh, vi, vj, vk, vl, vm, vn, vo, vp, vq; + + word jumpdest_instruction; + opcode jumpdest_op; stack_variant sv; signed_big_word sa, sb, sc; size_t offset, dest_offset, length, code_size = 0; + std::vector vec1; std::vector contract_args; std::vector retval; std::vector ext_contract_code; std::vector::const_iterator first, last; std::string* ss; + std::stringstream sstream; switch (op) { case stop_opcode: @@ -278,6 +281,7 @@ namespace machine va = pop_word(); vb = pop_word(); vc = va + vb; + push_word(vc); break; case mul_opcode: @@ -298,7 +302,10 @@ namespace machine logger << "op div" << std::endl; va = pop_word(); vb = pop_word(); - vc = va / vb; + if (vb == 0) + push_word(word(0)); + else + vc = va / vb; push_word(vc); break; case sdiv_opcode: @@ -491,7 +498,9 @@ namespace machine } } - push_word( adapter.sha3( retval ) ); // hash + sstream << std::hex << adapter.sha3( retval ); + sstream >> vc; + push_word( vc ); // hash break; case address_opcode: @@ -537,15 +546,39 @@ namespace machine } va = to_big_word( - msg.input_data[offset + 7], - msg.input_data[offset + 6], - msg.input_data[offset + 5], - msg.input_data[offset + 4], - msg.input_data[offset + 3], - msg.input_data[offset + 2], + msg.input_data[offset + 0], msg.input_data[offset + 1], - msg.input_data[offset + 0] - ); + msg.input_data[offset + 2], + msg.input_data[offset + 3], + msg.input_data[offset + 4], + msg.input_data[offset + 5], + msg.input_data[offset + 6], + msg.input_data[offset + 7], + msg.input_data[offset + 8], + msg.input_data[offset + 9], + msg.input_data[offset + 10], + msg.input_data[offset + 11], + msg.input_data[offset + 12], + msg.input_data[offset + 13], + msg.input_data[offset + 14], + msg.input_data[offset + 15], + msg.input_data[offset + 16], + msg.input_data[offset + 17], + msg.input_data[offset + 18], + msg.input_data[offset + 19], + msg.input_data[offset + 20], + msg.input_data[offset + 21], + msg.input_data[offset + 22], + msg.input_data[offset + 23], + msg.input_data[offset + 24], + msg.input_data[offset + 25], + msg.input_data[offset + 26], + msg.input_data[offset + 27], + msg.input_data[offset + 28], + msg.input_data[offset + 29], + msg.input_data[offset + 30], + msg.input_data[offset + 31] + ); push_word(va); break; case calldatasize_opcode: @@ -702,17 +735,40 @@ namespace machine case mload_opcode: logger << "op mload" << std::endl; va = pop_word(); // offset - // TODO: Verify order vb = to_big_word( - memory[static_cast(va) + 7], - memory[static_cast(va) + 6], - memory[static_cast(va) + 5], - memory[static_cast(va) + 4], - memory[static_cast(va) + 3], - memory[static_cast(va) + 2], + memory[static_cast(va) + 0], memory[static_cast(va) + 1], - memory[static_cast(va) + 0] - ); + memory[static_cast(va) + 2], + memory[static_cast(va) + 3], + memory[static_cast(va) + 4], + memory[static_cast(va) + 5], + memory[static_cast(va) + 6], + memory[static_cast(va) + 7], + memory[static_cast(va) + 8], + memory[static_cast(va) + 9], + memory[static_cast(va) + 10], + memory[static_cast(va) + 11], + memory[static_cast(va) + 12], + memory[static_cast(va) + 13], + memory[static_cast(va) + 14], + memory[static_cast(va) + 15], + memory[static_cast(va) + 16], + memory[static_cast(va) + 17], + memory[static_cast(va) + 18], + memory[static_cast(va) + 19], + memory[static_cast(va) + 20], + memory[static_cast(va) + 21], + memory[static_cast(va) + 22], + memory[static_cast(va) + 23], + memory[static_cast(va) + 24], + memory[static_cast(va) + 25], + memory[static_cast(va) + 26], + memory[static_cast(va) + 27], + memory[static_cast(va) + 28], + memory[static_cast(va) + 29], + memory[static_cast(va) + 30], + memory[static_cast(va) + 31] + ); push_word(vb); break; case mstore_opcode: @@ -721,15 +777,40 @@ namespace machine vb = pop_word(); // value logger << "memory before: " << inspect(memory) << std::endl; - // TODO: Verify order - memory[static_cast(va) + 0] = get_byte(vb, 7); - memory[static_cast(va) + 1] = get_byte(vb, 6); - memory[static_cast(va) + 2] = get_byte(vb, 5); - memory[static_cast(va) + 3] = get_byte(vb, 4); - memory[static_cast(va) + 4] = get_byte(vb, 3); - memory[static_cast(va) + 5] = get_byte(vb, 2); - memory[static_cast(va) + 6] = get_byte(vb, 1); - memory[static_cast(va) + 7] = get_byte(vb, 0); + vec1 = from_big_word(vb); + + memory[static_cast(va) + 0] = vec1[31]; + memory[static_cast(va) + 1] = vec1[30]; + memory[static_cast(va) + 2] = vec1[29]; + memory[static_cast(va) + 3] = vec1[28]; + memory[static_cast(va) + 4] = vec1[27]; + memory[static_cast(va) + 5] = vec1[26]; + memory[static_cast(va) + 6] = vec1[25]; + memory[static_cast(va) + 7] = vec1[24]; + memory[static_cast(va) + 8] = vec1[23]; + memory[static_cast(va) + 9] = vec1[22]; + memory[static_cast(va) + 10] = vec1[21]; + memory[static_cast(va) + 11] = vec1[20]; + memory[static_cast(va) + 12] = vec1[19]; + memory[static_cast(va) + 13] = vec1[18]; + memory[static_cast(va) + 14] = vec1[17]; + memory[static_cast(va) + 15] = vec1[16]; + memory[static_cast(va) + 16] = vec1[15]; + memory[static_cast(va) + 17] = vec1[14]; + memory[static_cast(va) + 18] = vec1[13]; + memory[static_cast(va) + 19] = vec1[12]; + memory[static_cast(va) + 20] = vec1[11]; + memory[static_cast(va) + 21] = vec1[10]; + memory[static_cast(va) + 22] = vec1[9]; + memory[static_cast(va) + 23] = vec1[8]; + memory[static_cast(va) + 24] = vec1[7]; + memory[static_cast(va) + 25] = vec1[6]; + memory[static_cast(va) + 26] = vec1[5]; + memory[static_cast(va) + 27] = vec1[4]; + memory[static_cast(va) + 28] = vec1[3]; + memory[static_cast(va) + 29] = vec1[2]; + memory[static_cast(va) + 30] = vec1[1]; + memory[static_cast(va) + 31] = vec1[0]; logger << "memory after: " << inspect(memory) << std::endl; break; case mstore8_opcode: @@ -780,17 +861,24 @@ namespace machine case jump_opcode: logger << "op jump" << std::endl; va = pop_word(); // destination - if (code[get_byte(va, 0)] == jumpdest_opcode) - pc = get_byte(va, 0); + + jumpdest_instruction = code[get_bytes(va, 0)]; + jumpdest_op = (opcode)jumpdest_instruction; + if (jumpdest_op == jumpdest_opcode) + pc = get_bytes(va, 0); break; case jumpi_opcode: logger << "op jumpi" << std::endl; print_stack(); - va = pop_word(); - vb = pop_word(); - if (vb != 0) - if (code[get_byte(va, 0)] == jumpdest_opcode) - pc = get_byte(va, 0); + va = pop_word(); // destination + vb = pop_word(); // condition + + if (vb != 0) { + jumpdest_instruction = code[get_bytes(va, 0)]; + jumpdest_op = (opcode)jumpdest_instruction; + if (jumpdest_op == jumpdest_opcode) + pc = get_bytes(va, 0); + } break; case pc_opcode: logger << "op pc" << std::endl; @@ -820,7 +908,7 @@ namespace machine pc++; b = code[pc]; pc++; - va = to_big_word(0, 0, a, b); // TODO: Verify + va = to_big_word(a, b); push_word(va); break; case push3_opcode: @@ -831,7 +919,7 @@ namespace machine pc++; c = code[pc]; pc++; - va = to_big_word(0, a, b, c); // TODO: Verify + va = to_big_word(0, a, b, c); push_word(va); break; case push4_opcode: @@ -844,7 +932,7 @@ namespace machine pc++; d = code[pc]; pc++; - va = to_big_word(a, b, c, d); // TODO: Verify + va = to_big_word(a, b, c, d); push_word(va); break; case push5_opcode: @@ -859,7 +947,7 @@ namespace machine pc++; e = code[pc]; pc++; - va = to_big_word(0, 0, 0, a, b, c, d, e); // TODO: Verify + va = to_big_word(0, 0, 0, a, b, c, d, e); push_word(va); break; case push6_opcode: @@ -876,7 +964,7 @@ namespace machine pc++; f = code[pc]; pc++; - va = to_big_word(0, 0, a, b, c, d, e, f); // TODO: Verify + va = to_big_word(0, 0, a, b, c, d, e, f); push_word(va); break; case push7_opcode: @@ -895,7 +983,7 @@ namespace machine pc++; g = code[pc]; pc++; - va = to_big_word(0, a, b, c, d, e, f, g); // TODO: Verify + va = to_big_word(0, a, b, c, d, e, f, g); push_word(va); break; case push8_opcode: @@ -916,7 +1004,7 @@ namespace machine pc++; h = code[pc]; pc++; - va = to_big_word(a, b, c, d, e, f, g, h); // TODO: Verify + va = to_big_word(a, b, c, d, e, f, g, h); push_word(va); break; case push9_opcode: @@ -939,7 +1027,7 @@ namespace machine pc++; i = code[pc]; pc++; - va = to_big_word(0, 0, 0, 0, 0, 0, 0, a, b, c, d, e, f, g, h, i); // TODO: Verify + va = to_big_word(0, 0, 0, 0, 0, 0, 0, a, b, c, d, e, f, g, h, i); push_word(va); break; case push10_opcode: @@ -964,7 +1052,7 @@ namespace machine pc++; j = code[pc]; pc++; - va = to_big_word(0, 0, 0, 0, 0, 0, a, b, c, d, e, f, g, h, i, j); // TODO: Verify + va = to_big_word(0, 0, 0, 0, 0, 0, a, b, c, d, e, f, g, h, i, j); push_word(va); break; case push11_opcode: @@ -991,7 +1079,7 @@ namespace machine pc++; k = code[pc]; pc++; - va = to_big_word(0, 0, 0, 0, 0, a, b, c, d, e, f, g, h, i, j, k); // TODO: Verify + va = to_big_word(0, 0, 0, 0, 0, a, b, c, d, e, f, g, h, i, j, k); push_word(va); break; case push12_opcode: @@ -1020,7 +1108,7 @@ namespace machine pc++; l = code[pc]; pc++; - va = to_big_word(0, 0, 0, 0, a, b, c, d, e, f, g, h, i, j, k, l); // TODO: Verify + va = to_big_word(0, 0, 0, 0, a, b, c, d, e, f, g, h, i, j, k, l); push_word(va); break; case push13_opcode: @@ -1051,7 +1139,7 @@ namespace machine pc++; m = code[pc]; pc++; - va = to_big_word(0, 0, 0, a, b, c, d, e, f, g, h, i, j, k, l, m); // TODO: Verify + va = to_big_word(0, 0, 0, a, b, c, d, e, f, g, h, i, j, k, l, m); push_word(va); break; case push14_opcode: @@ -1084,7 +1172,7 @@ namespace machine pc++; n = code[pc]; pc++; - va = to_big_word(0, 0, a, b, c, d, e, f, g, h, i, j, k, l, m, n); // TODO: Verify + va = to_big_word(0, 0, a, b, c, d, e, f, g, h, i, j, k, l, m, n); push_word(va); break; case push15_opcode: @@ -1119,7 +1207,7 @@ namespace machine pc++; o = code[pc]; pc++; - va = to_big_word(0, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o); // TODO: Verify + va = to_big_word(0, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o); push_word(va); break; case push16_opcode: @@ -1156,7 +1244,7 @@ namespace machine pc++; p = code[pc]; pc++; - va = to_big_word(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p); // TODO: Verify + va = to_big_word(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p); push_word(va); break; case push17_opcode: @@ -1196,7 +1284,7 @@ namespace machine q = code[pc]; pc++; va = to_big_word(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d, - e, f, g, h, i, j, k, l, m, n, o, p, q); // TODO: Verify + e, f, g, h, i, j, k, l, m, n, o, p, q); push_word(va); break; case push18_opcode: @@ -1238,7 +1326,7 @@ namespace machine r = code[pc]; pc++; va = to_big_word(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d, e, - f, g, h, i, j, k, l, m, n, o, p, q, r); // TODO: Verify + f, g, h, i, j, k, l, m, n, o, p, q, r); push_word(va); break; case push19_opcode: @@ -1282,7 +1370,7 @@ namespace machine s = code[pc]; pc++; va = to_big_word(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d, e, f, - g, h, i, j, k, l, m, n, o, p, q, r, s); // TODO: Verify + g, h, i, j, k, l, m, n, o, p, q, r, s); push_word(va); break; case push20_opcode: @@ -1328,7 +1416,7 @@ namespace machine t = code[pc]; pc++; va = to_big_word(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d, e, f, g, - h, i, j, k, l, m, n, o, p, q, r, s, t); // TODO: Verify + h, i, j, k, l, m, n, o, p, q, r, s, t); push_word(va); break; case push21_opcode: @@ -1376,7 +1464,7 @@ namespace machine u = code[pc]; pc++; va = to_big_word(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d, e, f, g, h, - i, j, k, l, m, n, o, p, q, r, s, t, u); // TODO: Verify + i, j, k, l, m, n, o, p, q, r, s, t, u); push_word(va); break; case push22_opcode: @@ -1426,7 +1514,7 @@ namespace machine v = code[pc]; pc++; va = to_big_word(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d, e, f, g, h, i, - j, k, l, m, n, o, p, q, r, s, t, u, v); // TODO: Verify + j, k, l, m, n, o, p, q, r, s, t, u, v); push_word(va); break; case push23_opcode: @@ -1478,7 +1566,7 @@ namespace machine w = code[pc]; pc++; va = to_big_word(0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d, e, f, g, h, i, j, - k, l, m, n, o, p, q, r, s, t, u, v, w); // TODO: Verify + k, l, m, n, o, p, q, r, s, t, u, v, w); push_word(va); break; case push24_opcode: @@ -1532,7 +1620,7 @@ namespace machine x = code[pc]; pc++; va = to_big_word(0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d, e, f, g, h, i, j, k, - l, m, n, o, p, q, r, s, t, u, v, w, x); // TODO: Verify + l, m, n, o, p, q, r, s, t, u, v, w, x); push_word(va); break; case push25_opcode: @@ -1588,7 +1676,7 @@ namespace machine y = code[pc]; pc++; va = to_big_word(0, 0, 0, 0, 0, 0, 0, a, b, c, d, e, f, g, h, i, j, k, l, - m, n, o, p, q, r, s, t, u, v, w, x, y); // TODO: Verify + m, n, o, p, q, r, s, t, u, v, w, x, y); push_word(va); break; case push26_opcode: @@ -1646,7 +1734,7 @@ namespace machine z = code[pc]; pc++; va = to_big_word(0, 0, 0, 0, 0, 0, a, b, c, d, e, f, g, h, i, j, k, l, m, - n, o, p, q, r, s, t, u, v, w, x, y, z); // TODO: Verify + n, o, p, q, r, s, t, u, v, w, x, y, z); push_word(va); break; case push27_opcode: @@ -1706,7 +1794,7 @@ namespace machine aa = code[pc]; pc++; va = to_big_word(0, 0, 0, 0, 0, a, b, c, d, e, f, g, h, i, j, k, l, m, n, - o, p, q, r, s, t, u, v, w, x, y, z, aa); // TODO: Verify + o, p, q, r, s, t, u, v, w, x, y, z, aa); push_word(va); break; case push28_opcode: @@ -1768,7 +1856,7 @@ namespace machine ab = code[pc]; pc++; va = to_big_word(0, 0, 0, 0, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, - p, q, r, s, t, u, v, w, x, y, z, aa, ab); // TODO: Verify + p, q, r, s, t, u, v, w, x, y, z, aa, ab); push_word(va); break; case push29_opcode: @@ -1832,7 +1920,7 @@ namespace machine ac = code[pc]; pc++; va = to_big_word(0, 0, 0, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, - q, r, s, t, u, v, w, x, y, z, aa, ab, ac); // TODO: Verify + q, r, s, t, u, v, w, x, y, z, aa, ab, ac); push_word(va); break; case push30_opcode: @@ -1898,7 +1986,7 @@ namespace machine ad = code[pc]; pc++; va = to_big_word(0, 0, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, - q, r, s, t, u, v, w, x, y, z, aa, ab, ac, ad); // TODO: Verify + q, r, s, t, u, v, w, x, y, z, aa, ab, ac, ad); push_word(va); break; case push31_opcode: @@ -1966,7 +2054,7 @@ namespace machine ae = code[pc]; pc++; va = to_big_word(0, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, - q, r, s, t, u, v, w, x, y, z, aa, ab, ac, ad, ae); // TODO: Verify + q, r, s, t, u, v, w, x, y, z, aa, ab, ac, ad, ae); push_word(va); break; case push32_opcode: @@ -2036,18 +2124,18 @@ namespace machine af = code[pc]; pc++; va = to_big_word(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, - q, r, s, t, u, v, w, x, y, z, aa, ab, ac, ad, ae, af); // TODO: Verify + q, r, s, t, u, v, w, x, y, z, aa, ab, ac, ad, ae, af); push_word(va); break; case dup1_opcode: logger << "op dup1" << std::endl; - sv = stack.front(); + sv = stack.at(0); push_word(sv); break; case dup2_opcode: logger << "op dup2" << std::endl; - sv = stack.at(1); - push_word(va); + sv = stack.at(1); + push_word(sv); break; case dup3_opcode: logger << "op dup3" << std::endl; @@ -2123,8 +2211,8 @@ namespace machine logger << "op swap1" << std::endl; va = pop_word(); vb = pop_word(); - push_word(a); - push_word(b); + push_word(va); + push_word(vb); break; case swap2_opcode: logger << "op swap2" << std::endl; @@ -2764,6 +2852,7 @@ namespace machine break; case return_opcode: logger << "op return" << std::endl; + // XXX // TODO REVIEW // a = pop_word(); // offset // b = pop_word(); // length @@ -2779,7 +2868,7 @@ namespace machine va = pop_word(); // offset vb = pop_word(); // length - for (size_t i = static_cast(va); i < static_cast(vb); i++) { + for (size_t i = static_cast(va); i < static_cast(va + vb); i++) { std::map::iterator it; it = memory.find(i); if (it != memory.end()) { @@ -2790,8 +2879,9 @@ namespace machine } } + return_value = retval; adapter.contract_return( retval ); - state = machine_state::stopped; // TODO: Add elsewhere + state = machine_state::stopped; break; case delegatecall_opcode: logger << "op delegatecall" << std::endl; @@ -2915,9 +3005,13 @@ namespace machine else { retval.push_back(word(0)); } + memory[i] = 0; } adapter.revert( retval ); break; + case invalid_opcode: + logger << "op invalid" << std::endl; + break; case selfdestruct_opcode: logger << "op selfdestruct" << std::endl; sv = stack.front(); // addr @@ -2962,7 +3056,7 @@ namespace machine { s << "\"finalState\":" << "{"; { - s << "\"pc\":" << pc << ","; + s << "\"pc\":" << std::hex << pc << ","; s << "\"stack\":" << "["; for (auto it = stack.cbegin(); it != stack.cend(); ++it) { @@ -3000,7 +3094,7 @@ namespace machine word current_instruction = code[pc]; opcode op = (opcode)current_instruction; - s << "\"opcode\":" << std::dec << op << ","; + s << "\"opcode\":" << std::hex << op << ","; if (error_message == boost::none) s << "\"exceptionError\":" << "null"; @@ -3017,7 +3111,6 @@ namespace machine if (memory.size() > 1 && std::next(it, 1) != memory.cend()) s << ","; } - s << "}"; } s << "}"; } diff --git a/libraries/vendor/xgtvm/libraries/machine.hpp b/libraries/vendor/xgtvm/libraries/machine.hpp index dcb5bc24..c32e3a14 100644 --- a/libraries/vendor/xgtvm/libraries/machine.hpp +++ b/libraries/vendor/xgtvm/libraries/machine.hpp @@ -173,6 +173,7 @@ namespace machine create2_opcode = 0xF5, staticcall_opcode = 0xFA, revert_opcode = 0xFD, + invalid_opcode = 0xFE, selfdestruct_opcode = 0xFF, }; @@ -195,8 +196,8 @@ namespace machine int32_t depth; int64_t energy; - std::string sender; - std::string destination; + big_word sender; + big_word destination; big_word value; size_t input_size; @@ -262,7 +263,7 @@ namespace machine std::function< void(big_word, big_word) > set_storage; // TODO return opcode - std::function< bool(std::vector) > contract_return; + std::function< std::vector(std::vector) > contract_return; // TODO selfdestruct opcode std::function< bool(std::string) > self_destruct; diff --git a/libraries/vendor/xgtvm/programs/xgtvm.cpp b/libraries/vendor/xgtvm/programs/xgtvm.cpp index 82818ed6..593ac8b6 100644 --- a/libraries/vendor/xgtvm/programs/xgtvm.cpp +++ b/libraries/vendor/xgtvm/programs/xgtvm.cpp @@ -124,7 +124,7 @@ machine::chain_adapter make_chain_adapter() { }; - std::function< bool(std::vector) > contract_return = [](std::vector memory) -> bool + std::function< std::vector(std::vector) > contract_return = [](std::vector memory) -> std::vector { return {}; }; diff --git a/libraries/vendor/xgtvm/programs/xgtvm_tests.cpp b/libraries/vendor/xgtvm/programs/xgtvm_tests.cpp index d75ed781..6968fb5c 100644 --- a/libraries/vendor/xgtvm/programs/xgtvm_tests.cpp +++ b/libraries/vendor/xgtvm/programs/xgtvm_tests.cpp @@ -95,7 +95,7 @@ machine::chain_adapter make_chain_adapter() return false; }; - std::function< bool(std::vector) > contract_return = [](std::vector memory) -> bool + std::function< std::vector(std::vector) > contract_return = [](std::vector memory) -> std::vector { std::cout << "chain_adapter::contract_return" << std::endl; return {}; @@ -226,61 +226,61 @@ int main(int argc, char** argv) // assert_message( "top of stack has correct value", m.peek_word() == 2 ); //} - test_that("do nothing contract evaluates") - { - std::vector input = {0x60, 0x80, 0x60, 0x40, 0x52, 0x34, 0x80, 0x15, 0x60, 0x0f, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x60, 0x6d, 0x80, 0x60, 0x1d, 0x60, 0x00, 0x39, 0x60, 0x00, 0xf3, 0xfe, 0x60, 0x80, 0x60, 0x40, 0x52, 0x34, 0x80, 0x15, 0x60, 0x0f, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x60, 0x04, 0x36, 0x10, 0x60, 0x28, 0x57, 0x60, 0x00, 0x35, 0x60, 0xe0, 0x1c, 0x80, 0x63, 0x2f, 0x57, 0x6f, 0x20, 0x14, 0x60, 0x2d, 0x57, 0x5b, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x60, 0x33, 0x60, 0x35, 0x56, 0x5b, 0x00, 0x5b, 0x56, 0xfe, 0xa2, 0x64, 0x69, 0x70, 0x66, 0x73, 0x58, 0x22, 0x12, 0x20, 0x97, 0x5b, 0xdb, 0x69, 0x49, 0x44, 0x25, 0x38, 0xb9, 0x0c, 0x14, 0xc4, 0x20, 0xb0, 0xa2, 0xf5, 0x47, 0xf0, 0x43, 0x7e, 0x85, 0xa7, 0x3d, 0xa1, 0x2f, 0xaf, 0x4e, 0x68, 0x34, 0xf0, 0x81, 0x72, 0x64, 0x73, 0x6f, 0x6c, 0x63, 0x43, 0x00, 0x08, 0x07, 0x00, 0x33}; - machine::context ctx = {true, 0x00}; - machine::message msg = {}; - machine::chain_adapter adapter = make_chain_adapter(); - machine::machine m(ctx, input, msg, adapter); - assert_message( "machine should start running", m.get_state() == machine::machine_state::running ); - - auto& logger = m.get_logger(); - std::string line; - std::cerr << "\e[36m" << "LOG: " << m.to_json() << "\e[0m" << std::endl; - while (m.is_running()) - { - m.step(); - //// TODO: Figure out why logs not emitting - //while ( std::getline(logger, line) ) - // std::cerr << "\e[36m" << "LOG: " << line << "\e[0m" << std::endl; - std::cerr << "\e[36m" << "LOG: " << m.to_json() << "\e[0m" << std::endl; - } - //while ( std::getline(logger, line) ) - // std::cerr << "\e[36m" << "LOG: " << line << "\e[0m" << std::endl; - std::cerr << "\e[36m" << "LOG: " << m.to_json() << "\e[0m" << std::endl; - - assert_message( "machine should stop when done executing", m.get_state() == machine::machine_state::stopped ); - assert_message( "stack has correct length", m.stack_length() == 0 ); - } - - test_that("storage contract evaluates") - { - std::vector input = {0x60, 0x80, 0x60, 0x40, 0x52, 0x34, 0x80, 0x15, 0x61, 0x00, 0x10, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x61, 0x01, 0x50, 0x80, 0x61, 0x00, 0x20, 0x60, 0x00, 0x39, 0x60, 0x00, 0xf3, 0xfe, 0x60, 0x80, 0x60, 0x40, 0x52, 0x34, 0x80, 0x15, 0x61, 0x00, 0x10, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x60, 0x04, 0x36, 0x10, 0x61, 0x00, 0x36, 0x57, 0x60, 0x00, 0x35, 0x60, 0xe0, 0x1c, 0x80, 0x63, 0x2e, 0x64, 0xce, 0xc1, 0x14, 0x61, 0x00, 0x3b, 0x57, 0x80, 0x63, 0x60, 0x57, 0x36, 0x1d, 0x14, 0x61, 0x00, 0x59, 0x57, 0x5b, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x61, 0x00, 0x43, 0x61, 0x00, 0x75, 0x56, 0x5b, 0x60, 0x40, 0x51, 0x61, 0x00, 0x50, 0x91, 0x90, 0x61, 0x00, 0xd9, 0x56, 0x5b, 0x60, 0x40, 0x51, 0x80, 0x91, 0x03, 0x90, 0xf3, 0x5b, 0x61, 0x00, 0x73, 0x60, 0x04, 0x80, 0x36, 0x03, 0x81, 0x01, 0x90, 0x61, 0x00, 0x6e, 0x91, 0x90, 0x61, 0x00, 0x9d, 0x56, 0x5b, 0x61, 0x00, 0x7e, 0x56, 0x5b, 0x00, 0x5b, 0x60, 0x00, 0x80, 0x54, 0x90, 0x50, 0x90, 0x56, 0x5b, 0x80, 0x60, 0x00, 0x81, 0x90, 0x55, 0x50, 0x50, 0x56, 0x5b, 0x60, 0x00, 0x81, 0x35, 0x90, 0x50, 0x61, 0x00, 0x97, 0x81, 0x61, 0x01, 0x03, 0x56, 0x5b, 0x92, 0x91, 0x50, 0x50, 0x56, 0x5b, 0x60, 0x00, 0x60, 0x20, 0x82, 0x84, 0x03, 0x12, 0x15, 0x61, 0x00, 0xb3, 0x57, 0x61, 0x00, 0xb2, 0x61, 0x00, 0xfe, 0x56, 0x5b, 0x5b, 0x60, 0x00, 0x61, 0x00, 0xc1, 0x84, 0x82, 0x85, 0x01, 0x61, 0x00, 0x88, 0x56, 0x5b, 0x91, 0x50, 0x50, 0x92, 0x91, 0x50, 0x50, 0x56, 0x5b, 0x61, 0x00, 0xd3, 0x81, 0x61, 0x00, 0xf4, 0x56, 0x5b, 0x82, 0x52, 0x50, 0x50, 0x56, 0x5b, 0x60, 0x00, 0x60, 0x20, 0x82, 0x01, 0x90, 0x50, 0x61, 0x00, 0xee, 0x60, 0x00, 0x83, 0x01, 0x84, 0x61, 0x00, 0xca, 0x56, 0x5b, 0x92, 0x91, 0x50, 0x50, 0x56, 0x5b, 0x60, 0x00, 0x81, 0x90, 0x50, 0x91, 0x90, 0x50, 0x56, 0x5b, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x61, 0x01, 0x0c, 0x81, 0x61, 0x00, 0xf4, 0x56, 0x5b, 0x81, 0x14, 0x61, 0x01, 0x17, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x56, 0xfe, 0xa2, 0x64, 0x69, 0x70, 0x66, 0x73, 0x58, 0x22, 0x12, 0x20, 0x40, 0x4e, 0x37, 0xf4, 0x87, 0xa8, 0x9a, 0x93, 0x2d, 0xca, 0x5e, 0x77, 0xfa, 0xaf, 0x6c, 0xa2, 0xde, 0x3b, 0x99, 0x1f, 0x93, 0xd2, 0x30, 0x60, 0x4b, 0x1b, 0x8d, 0xaa, 0xef, 0x64, 0x76, 0x62, 0x64, 0x73, 0x6f, 0x6c, 0x63, 0x43, 0x00, 0x08, 0x07, 0x00, 0x33}; - machine::context ctx = {true, 0x00}; - machine::message msg = {}; - machine::chain_adapter adapter = make_chain_adapter(); - machine::machine m(ctx, input, msg, adapter); - assert_message( "machine should start running", m.get_state() == machine::machine_state::running ); - - auto& logger = m.get_logger(); - std::string line; - std::cerr << "\e[36m" << "LOG: " << m.to_json() << "\e[0m" << std::endl; - while (m.is_running()) - { - m.step(); - //// TODO: Figure out why logs not emitting - //while ( std::getline(logger, line) ) - // std::cerr << "\e[36m" << "LOG: " << line << "\e[0m" << std::endl; - std::cerr << "\e[36m" << "LOG: " << m.to_json() << "\e[0m" << std::endl; - } - //while ( std::getline(logger, line) ) - // std::cerr << "\e[36m" << "LOG: " << line << "\e[0m" << std::endl; - std::cerr << "\e[36m" << "LOG: " << m.to_json() << "\e[0m" << std::endl; - - assert_message( "machine should stop when done executing", m.get_state() == machine::machine_state::stopped ); - assert_message( "stack has correct length", m.stack_length() == 0 ); - } + // test_that("do nothing contract evaluates") + // { + // std::vector input = {0x60, 0x80, 0x60, 0x40, 0x52, 0x34, 0x80, 0x15, 0x60, 0x0f, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x60, 0x6d, 0x80, 0x60, 0x1d, 0x60, 0x00, 0x39, 0x60, 0x00, 0xf3, 0xfe, 0x60, 0x80, 0x60, 0x40, 0x52, 0x34, 0x80, 0x15, 0x60, 0x0f, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x60, 0x04, 0x36, 0x10, 0x60, 0x28, 0x57, 0x60, 0x00, 0x35, 0x60, 0xe0, 0x1c, 0x80, 0x63, 0x2f, 0x57, 0x6f, 0x20, 0x14, 0x60, 0x2d, 0x57, 0x5b, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x60, 0x33, 0x60, 0x35, 0x56, 0x5b, 0x00, 0x5b, 0x56, 0xfe, 0xa2, 0x64, 0x69, 0x70, 0x66, 0x73, 0x58, 0x22, 0x12, 0x20, 0x97, 0x5b, 0xdb, 0x69, 0x49, 0x44, 0x25, 0x38, 0xb9, 0x0c, 0x14, 0xc4, 0x20, 0xb0, 0xa2, 0xf5, 0x47, 0xf0, 0x43, 0x7e, 0x85, 0xa7, 0x3d, 0xa1, 0x2f, 0xaf, 0x4e, 0x68, 0x34, 0xf0, 0x81, 0x72, 0x64, 0x73, 0x6f, 0x6c, 0x63, 0x43, 0x00, 0x08, 0x07, 0x00, 0x33}; + // machine::context ctx = {true, 0x00}; + // machine::message msg = {}; + // machine::chain_adapter adapter = make_chain_adapter(); + // machine::machine m(ctx, input, msg, adapter); + // assert_message( "machine should start running", m.get_state() == machine::machine_state::running ); + + // auto& logger = m.get_logger(); + // std::string line; + // std::cerr << "\e[36m" << "LOG: " << m.to_json() << "\e[0m" << std::endl; + // while (m.is_running()) + // { + // m.step(); + // //// TODO: Figure out why logs not emitting + // //while ( std::getline(logger, line) ) + // // std::cerr << "\e[36m" << "LOG: " << line << "\e[0m" << std::endl; + // std::cerr << "\e[36m" << "LOG: " << m.to_json() << "\e[0m" << std::endl; + // } + // //while ( std::getline(logger, line) ) + // // std::cerr << "\e[36m" << "LOG: " << line << "\e[0m" << std::endl; + // std::cerr << "\e[36m" << "LOG: " << m.to_json() << "\e[0m" << std::endl; + + // assert_message( "machine should stop when done executing", m.get_state() == machine::machine_state::stopped ); + // assert_message( "stack has correct length", m.stack_length() == 0 ); + // } + + // test_that("storage contract evaluates") + // { + // std::vector input = {0x60, 0x80, 0x60, 0x40, 0x52, 0x34, 0x80, 0x15, 0x61, 0x00, 0x10, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x61, 0x01, 0x50, 0x80, 0x61, 0x00, 0x20, 0x60, 0x00, 0x39, 0x60, 0x00, 0xf3, 0xfe, 0x60, 0x80, 0x60, 0x40, 0x52, 0x34, 0x80, 0x15, 0x61, 0x00, 0x10, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x60, 0x04, 0x36, 0x10, 0x61, 0x00, 0x36, 0x57, 0x60, 0x00, 0x35, 0x60, 0xe0, 0x1c, 0x80, 0x63, 0x2e, 0x64, 0xce, 0xc1, 0x14, 0x61, 0x00, 0x3b, 0x57, 0x80, 0x63, 0x60, 0x57, 0x36, 0x1d, 0x14, 0x61, 0x00, 0x59, 0x57, 0x5b, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x61, 0x00, 0x43, 0x61, 0x00, 0x75, 0x56, 0x5b, 0x60, 0x40, 0x51, 0x61, 0x00, 0x50, 0x91, 0x90, 0x61, 0x00, 0xd9, 0x56, 0x5b, 0x60, 0x40, 0x51, 0x80, 0x91, 0x03, 0x90, 0xf3, 0x5b, 0x61, 0x00, 0x73, 0x60, 0x04, 0x80, 0x36, 0x03, 0x81, 0x01, 0x90, 0x61, 0x00, 0x6e, 0x91, 0x90, 0x61, 0x00, 0x9d, 0x56, 0x5b, 0x61, 0x00, 0x7e, 0x56, 0x5b, 0x00, 0x5b, 0x60, 0x00, 0x80, 0x54, 0x90, 0x50, 0x90, 0x56, 0x5b, 0x80, 0x60, 0x00, 0x81, 0x90, 0x55, 0x50, 0x50, 0x56, 0x5b, 0x60, 0x00, 0x81, 0x35, 0x90, 0x50, 0x61, 0x00, 0x97, 0x81, 0x61, 0x01, 0x03, 0x56, 0x5b, 0x92, 0x91, 0x50, 0x50, 0x56, 0x5b, 0x60, 0x00, 0x60, 0x20, 0x82, 0x84, 0x03, 0x12, 0x15, 0x61, 0x00, 0xb3, 0x57, 0x61, 0x00, 0xb2, 0x61, 0x00, 0xfe, 0x56, 0x5b, 0x5b, 0x60, 0x00, 0x61, 0x00, 0xc1, 0x84, 0x82, 0x85, 0x01, 0x61, 0x00, 0x88, 0x56, 0x5b, 0x91, 0x50, 0x50, 0x92, 0x91, 0x50, 0x50, 0x56, 0x5b, 0x61, 0x00, 0xd3, 0x81, 0x61, 0x00, 0xf4, 0x56, 0x5b, 0x82, 0x52, 0x50, 0x50, 0x56, 0x5b, 0x60, 0x00, 0x60, 0x20, 0x82, 0x01, 0x90, 0x50, 0x61, 0x00, 0xee, 0x60, 0x00, 0x83, 0x01, 0x84, 0x61, 0x00, 0xca, 0x56, 0x5b, 0x92, 0x91, 0x50, 0x50, 0x56, 0x5b, 0x60, 0x00, 0x81, 0x90, 0x50, 0x91, 0x90, 0x50, 0x56, 0x5b, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x61, 0x01, 0x0c, 0x81, 0x61, 0x00, 0xf4, 0x56, 0x5b, 0x81, 0x14, 0x61, 0x01, 0x17, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x56, 0xfe, 0xa2, 0x64, 0x69, 0x70, 0x66, 0x73, 0x58, 0x22, 0x12, 0x20, 0x40, 0x4e, 0x37, 0xf4, 0x87, 0xa8, 0x9a, 0x93, 0x2d, 0xca, 0x5e, 0x77, 0xfa, 0xaf, 0x6c, 0xa2, 0xde, 0x3b, 0x99, 0x1f, 0x93, 0xd2, 0x30, 0x60, 0x4b, 0x1b, 0x8d, 0xaa, 0xef, 0x64, 0x76, 0x62, 0x64, 0x73, 0x6f, 0x6c, 0x63, 0x43, 0x00, 0x08, 0x07, 0x00, 0x33}; + // machine::context ctx = {true, 0x00}; + // machine::message msg = {}; + // machine::chain_adapter adapter = make_chain_adapter(); + // machine::machine m(ctx, input, msg, adapter); + // assert_message( "machine should start running", m.get_state() == machine::machine_state::running ); + + // auto& logger = m.get_logger(); + // std::string line; + // std::cerr << "\e[36m" << "LOG: " << m.to_json() << "\e[0m" << std::endl; + // while (m.is_running()) + // { + // m.step(); + // //// TODO: Figure out why logs not emitting + // //while ( std::getline(logger, line) ) + // // std::cerr << "\e[36m" << "LOG: " << line << "\e[0m" << std::endl; + // std::cerr << "\e[36m" << "LOG: " << m.to_json() << "\e[0m" << std::endl; + // } + // //while ( std::getline(logger, line) ) + // // std::cerr << "\e[36m" << "LOG: " << line << "\e[0m" << std::endl; + // std::cerr << "\e[36m" << "LOG: " << m.to_json() << "\e[0m" << std::endl; + + // assert_message( "machine should stop when done executing", m.get_state() == machine::machine_state::stopped ); + // assert_message( "stack has correct length", m.stack_length() == 0 ); + // } //test_that("first lottery contract evaluates") //{ @@ -307,30 +307,33 @@ int main(int argc, char** argv) // assert_message( "stack has correct length", m.stack_length() == 0 ); //} - //test_that("second lottery contract evaluates") - //{ - // std::vector input = {0x60, 0x80, 0x60, 0x40, 0x52, 0x34, 0x80, 0x15, 0x62, 0x00, 0x00, 0x11, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x60, 0x40, 0x51, 0x62, 0x00, 0x17, 0x54, 0x38, 0x03, 0x80, 0x62, 0x00, 0x17, 0x54, 0x83, 0x39, 0x81, 0x01, 0x80, 0x60, 0x40, 0x52, 0x81, 0x01, 0x90, 0x80, 0x80, 0x51, 0x82, 0x01, 0x92, 0x91, 0x90, 0x60, 0x20, 0x01, 0x80, 0x51, 0x90, 0x60, 0x20, 0x01, 0x90, 0x92, 0x91, 0x90, 0x50, 0x50, 0x50, 0x80, 0x60, 0x01, 0x60, 0x00, 0x61, 0x01, 0x00, 0x0a, 0x81, 0x54, 0x81, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0x19, 0x16, 0x90, 0x83, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x02, 0x17, 0x90, 0x55, 0x50, 0x81, 0x60, 0x00, 0x90, 0x80, 0x51, 0x90, 0x60, 0x20, 0x01, 0x90, 0x62, 0x00, 0x00, 0x9c, 0x92, 0x91, 0x90, 0x62, 0x00, 0x00, 0xa5, 0x56, 0x5b, 0x50, 0x50, 0x50, 0x62, 0x00, 0x01, 0x54, 0x56, 0x5b, 0x82, 0x80, 0x54, 0x60, 0x01, 0x81, 0x60, 0x01, 0x16, 0x15, 0x61, 0x01, 0x00, 0x02, 0x03, 0x16, 0x60, 0x02, 0x90, 0x04, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x90, 0x60, 0x1f, 0x01, 0x60, 0x20, 0x90, 0x04, 0x81, 0x01, 0x92, 0x82, 0x60, 0x1f, 0x10, 0x62, 0x00, 0x00, 0xe8, 0x57, 0x80, 0x51, 0x60, 0xff, 0x19, 0x16, 0x83, 0x80, 0x01, 0x17, 0x85, 0x55, 0x62, 0x00, 0x01, 0x19, 0x56, 0x5b, 0x82, 0x80, 0x01, 0x60, 0x01, 0x01, 0x85, 0x55, 0x82, 0x15, 0x62, 0x00, 0x01, 0x19, 0x57, 0x91, 0x82, 0x01, 0x5b, 0x82, 0x81, 0x11, 0x15, 0x62, 0x00, 0x01, 0x18, 0x57, 0x82, 0x51, 0x82, 0x55, 0x91, 0x60, 0x20, 0x01, 0x91, 0x90, 0x60, 0x01, 0x01, 0x90, 0x62, 0x00, 0x00, 0xfb, 0x56, 0x5b, 0x5b, 0x50, 0x90, 0x50, 0x62, 0x00, 0x01, 0x28, 0x91, 0x90, 0x62, 0x00, 0x01, 0x2c, 0x56, 0x5b, 0x50, 0x90, 0x56, 0x5b, 0x62, 0x00, 0x01, 0x51, 0x91, 0x90, 0x5b, 0x80, 0x82, 0x11, 0x15, 0x62, 0x00, 0x01, 0x4d, 0x57, 0x60, 0x00, 0x81, 0x60, 0x00, 0x90, 0x55, 0x50, 0x60, 0x01, 0x01, 0x62, 0x00, 0x01, 0x33, 0x56, 0x5b, 0x50, 0x90, 0x56, 0x5b, 0x90, 0x56, 0x5b, 0x61, 0x15, 0xf0, 0x80, 0x62, 0x00, 0x01, 0x64, 0x60, 0x00, 0x39, 0x60, 0x00, 0xf3, 0x00, 0x60, 0x80, 0x60, 0x40, 0x52, 0x60, 0x04, 0x36, 0x10, 0x61, 0x00, 0xd0, 0x57, 0x60, 0x00, 0x35, 0x7c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x04, 0x63, 0xff, 0xff, 0xff, 0xff, 0x16, 0x80, 0x63, 0x10, 0xc8, 0x5f, 0xe5, 0x14, 0x61, 0x01, 0x10, 0x57, 0x80, 0x63, 0x14, 0x03, 0x4b, 0xd2, 0x14, 0x61, 0x01, 0x3f, 0x57, 0x80, 0x63, 0x1d, 0x27, 0x76, 0x9f, 0x14, 0x61, 0x01, 0x56, 0x57, 0x80, 0x63, 0x23, 0xd1, 0x41, 0x49, 0x14, 0x61, 0x01, 0xb2, 0x57, 0x80, 0x63, 0x48, 0x1c, 0x6a, 0x75, 0x14, 0x61, 0x02, 0x42, 0x57, 0x80, 0x63, 0x58, 0x32, 0xd5, 0x71, 0x14, 0x61, 0x02, 0x99, 0x57, 0x80, 0x63, 0x5c, 0x12, 0xcd, 0x4b, 0x14, 0x61, 0x03, 0x06, 0x57, 0x80, 0x63, 0x5d, 0x58, 0xa7, 0x4a, 0x14, 0x61, 0x03, 0xc9, 0x57, 0x80, 0x63, 0x77, 0x52, 0x04, 0x5b, 0x14, 0x61, 0x03, 0xf4, 0x57, 0x80, 0x63, 0x8b, 0x5b, 0x9c, 0xcc, 0x14, 0x61, 0x04, 0x1f, 0x57, 0x80, 0x63, 0xbd, 0xae, 0xa3, 0x26, 0x14, 0x61, 0x04, 0x8b, 0x57, 0x80, 0x63, 0xd6, 0x88, 0x95, 0xd8, 0x14, 0x61, 0x04, 0xc2, 0x57, 0x80, 0x63, 0xdf, 0xbf, 0x53, 0xae, 0x14, 0x61, 0x04, 0xed, 0x57, 0x80, 0x63, 0xf2, 0x52, 0x66, 0xdd, 0x14, 0x61, 0x05, 0x8b, 0x57, 0x5b, 0x61, 0x01, 0x0e, 0x60, 0x40, 0x80, 0x51, 0x90, 0x81, 0x01, 0x60, 0x40, 0x52, 0x80, 0x60, 0x07, 0x81, 0x52, 0x60, 0x20, 0x01, 0x7f, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x52, 0x50, 0x61, 0x05, 0xf8, 0x56, 0x5b, 0x00, 0x5b, 0x34, 0x80, 0x15, 0x61, 0x01, 0x1c, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x61, 0x01, 0x25, 0x61, 0x09, 0xee, 0x56, 0x5b, 0x60, 0x40, 0x51, 0x80, 0x82, 0x15, 0x15, 0x15, 0x15, 0x81, 0x52, 0x60, 0x20, 0x01, 0x91, 0x50, 0x50, 0x60, 0x40, 0x51, 0x80, 0x91, 0x03, 0x90, 0xf3, 0x5b, 0x34, 0x80, 0x15, 0x61, 0x01, 0x4b, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x61, 0x01, 0x54, 0x61, 0x0a, 0x01, 0x56, 0x5b, 0x00, 0x5b, 0x61, 0x01, 0xb0, 0x60, 0x04, 0x80, 0x36, 0x03, 0x81, 0x01, 0x90, 0x80, 0x80, 0x35, 0x90, 0x60, 0x20, 0x01, 0x90, 0x82, 0x01, 0x80, 0x35, 0x90, 0x60, 0x20, 0x01, 0x90, 0x80, 0x80, 0x60, 0x1f, 0x01, 0x60, 0x20, 0x80, 0x91, 0x04, 0x02, 0x60, 0x20, 0x01, 0x60, 0x40, 0x51, 0x90, 0x81, 0x01, 0x60, 0x40, 0x52, 0x80, 0x93, 0x92, 0x91, 0x90, 0x81, 0x81, 0x52, 0x60, 0x20, 0x01, 0x83, 0x83, 0x80, 0x82, 0x84, 0x37, 0x82, 0x01, 0x91, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x91, 0x92, 0x91, 0x92, 0x90, 0x50, 0x50, 0x50, 0x61, 0x05, 0xf8, 0x56, 0x5b, 0x00, 0x5b, 0x34, 0x80, 0x15, 0x61, 0x01, 0xbe, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x61, 0x01, 0xc7, 0x61, 0x0d, 0xbf, 0x56, 0x5b, 0x60, 0x40, 0x51, 0x80, 0x80, 0x60, 0x20, 0x01, 0x82, 0x81, 0x03, 0x82, 0x52, 0x83, 0x81, 0x81, 0x51, 0x81, 0x52, 0x60, 0x20, 0x01, 0x91, 0x50, 0x80, 0x51, 0x90, 0x60, 0x20, 0x01, 0x90, 0x80, 0x83, 0x83, 0x60, 0x00, 0x5b, 0x83, 0x81, 0x10, 0x15, 0x61, 0x02, 0x07, 0x57, 0x80, 0x82, 0x01, 0x51, 0x81, 0x84, 0x01, 0x52, 0x60, 0x20, 0x81, 0x01, 0x90, 0x50, 0x61, 0x01, 0xec, 0x56, 0x5b, 0x50, 0x50, 0x50, 0x50, 0x90, 0x50, 0x90, 0x81, 0x01, 0x90, 0x60, 0x1f, 0x16, 0x80, 0x15, 0x61, 0x02, 0x34, 0x57, 0x80, 0x82, 0x03, 0x80, 0x51, 0x60, 0x01, 0x83, 0x60, 0x20, 0x03, 0x61, 0x01, 0x00, 0x0a, 0x03, 0x19, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x91, 0x50, 0x5b, 0x50, 0x92, 0x50, 0x50, 0x50, 0x60, 0x40, 0x51, 0x80, 0x91, 0x03, 0x90, 0xf3, 0x5b, 0x34, 0x80, 0x15, 0x61, 0x02, 0x4e, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x61, 0x02, 0x57, 0x61, 0x0e, 0x5d, 0x56, 0x5b, 0x60, 0x40, 0x51, 0x80, 0x82, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x91, 0x50, 0x50, 0x60, 0x40, 0x51, 0x80, 0x91, 0x03, 0x90, 0xf3, 0x5b, 0x34, 0x80, 0x15, 0x61, 0x02, 0xa5, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x61, 0x02, 0xc4, 0x60, 0x04, 0x80, 0x36, 0x03, 0x81, 0x01, 0x90, 0x80, 0x80, 0x35, 0x90, 0x60, 0x20, 0x01, 0x90, 0x92, 0x91, 0x90, 0x50, 0x50, 0x50, 0x61, 0x0e, 0x83, 0x56, 0x5b, 0x60, 0x40, 0x51, 0x80, 0x82, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x91, 0x50, 0x50, 0x60, 0x40, 0x51, 0x80, 0x91, 0x03, 0x90, 0xf3, 0x5b, 0x34, 0x80, 0x15, 0x61, 0x03, 0x12, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x61, 0x03, 0x47, 0x60, 0x04, 0x80, 0x36, 0x03, 0x81, 0x01, 0x90, 0x80, 0x80, 0x35, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x90, 0x60, 0x20, 0x01, 0x90, 0x92, 0x91, 0x90, 0x50, 0x50, 0x50, 0x61, 0x0e, 0xc1, 0x56, 0x5b, 0x60, 0x40, 0x51, 0x80, 0x80, 0x60, 0x20, 0x01, 0x83, 0x81, 0x52, 0x60, 0x20, 0x01, 0x82, 0x81, 0x03, 0x82, 0x52, 0x84, 0x81, 0x81, 0x51, 0x81, 0x52, 0x60, 0x20, 0x01, 0x91, 0x50, 0x80, 0x51, 0x90, 0x60, 0x20, 0x01, 0x90, 0x80, 0x83, 0x83, 0x60, 0x00, 0x5b, 0x83, 0x81, 0x10, 0x15, 0x61, 0x03, 0x8d, 0x57, 0x80, 0x82, 0x01, 0x51, 0x81, 0x84, 0x01, 0x52, 0x60, 0x20, 0x81, 0x01, 0x90, 0x50, 0x61, 0x03, 0x72, 0x56, 0x5b, 0x50, 0x50, 0x50, 0x50, 0x90, 0x50, 0x90, 0x81, 0x01, 0x90, 0x60, 0x1f, 0x16, 0x80, 0x15, 0x61, 0x03, 0xba, 0x57, 0x80, 0x82, 0x03, 0x80, 0x51, 0x60, 0x01, 0x83, 0x60, 0x20, 0x03, 0x61, 0x01, 0x00, 0x0a, 0x03, 0x19, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x91, 0x50, 0x5b, 0x50, 0x93, 0x50, 0x50, 0x50, 0x50, 0x60, 0x40, 0x51, 0x80, 0x91, 0x03, 0x90, 0xf3, 0x5b, 0x34, 0x80, 0x15, 0x61, 0x03, 0xd5, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x61, 0x03, 0xde, 0x61, 0x10, 0x1e, 0x56, 0x5b, 0x60, 0x40, 0x51, 0x80, 0x82, 0x81, 0x52, 0x60, 0x20, 0x01, 0x91, 0x50, 0x50, 0x60, 0x40, 0x51, 0x80, 0x91, 0x03, 0x90, 0xf3, 0x5b, 0x34, 0x80, 0x15, 0x61, 0x04, 0x00, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x61, 0x04, 0x09, 0x61, 0x10, 0x24, 0x56, 0x5b, 0x60, 0x40, 0x51, 0x80, 0x82, 0x81, 0x52, 0x60, 0x20, 0x01, 0x91, 0x50, 0x50, 0x60, 0x40, 0x51, 0x80, 0x91, 0x03, 0x90, 0xf3, 0x5b, 0x34, 0x80, 0x15, 0x61, 0x04, 0x2b, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x61, 0x04, 0x34, 0x61, 0x10, 0x2a, 0x56, 0x5b, 0x60, 0x40, 0x51, 0x80, 0x80, 0x60, 0x20, 0x01, 0x82, 0x81, 0x03, 0x82, 0x52, 0x83, 0x81, 0x81, 0x51, 0x81, 0x52, 0x60, 0x20, 0x01, 0x91, 0x50, 0x80, 0x51, 0x90, 0x60, 0x20, 0x01, 0x90, 0x60, 0x20, 0x02, 0x80, 0x83, 0x83, 0x60, 0x00, 0x5b, 0x83, 0x81, 0x10, 0x15, 0x61, 0x04, 0x77, 0x57, 0x80, 0x82, 0x01, 0x51, 0x81, 0x84, 0x01, 0x52, 0x60, 0x20, 0x81, 0x01, 0x90, 0x50, 0x61, 0x04, 0x5c, 0x56, 0x5b, 0x50, 0x50, 0x50, 0x50, 0x90, 0x50, 0x01, 0x92, 0x50, 0x50, 0x50, 0x60, 0x40, 0x51, 0x80, 0x91, 0x03, 0x90, 0xf3, 0x5b, 0x34, 0x80, 0x15, 0x61, 0x04, 0x97, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x61, 0x04, 0xc0, 0x60, 0x04, 0x80, 0x36, 0x03, 0x81, 0x01, 0x90, 0x80, 0x80, 0x35, 0x90, 0x60, 0x20, 0x01, 0x90, 0x92, 0x91, 0x90, 0x80, 0x35, 0x90, 0x60, 0x20, 0x01, 0x90, 0x92, 0x91, 0x90, 0x50, 0x50, 0x50, 0x61, 0x10, 0xb8, 0x56, 0x5b, 0x00, 0x5b, 0x34, 0x80, 0x15, 0x61, 0x04, 0xce, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x61, 0x04, 0xd7, 0x61, 0x11, 0x61, 0x56, 0x5b, 0x60, 0x40, 0x51, 0x80, 0x82, 0x81, 0x52, 0x60, 0x20, 0x01, 0x91, 0x50, 0x50, 0x60, 0x40, 0x51, 0x80, 0x91, 0x03, 0x90, 0xf3, 0x5b, 0x34, 0x80, 0x15, 0x61, 0x04, 0xf9, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x61, 0x05, 0x02, 0x61, 0x11, 0x80, 0x56, 0x5b, 0x60, 0x40, 0x51, 0x80, 0x80, 0x60, 0x20, 0x01, 0x84, 0x81, 0x52, 0x60, 0x20, 0x01, 0x83, 0x81, 0x52, 0x60, 0x20, 0x01, 0x82, 0x81, 0x03, 0x82, 0x52, 0x85, 0x81, 0x81, 0x51, 0x81, 0x52, 0x60, 0x20, 0x01, 0x91, 0x50, 0x80, 0x51, 0x90, 0x60, 0x20, 0x01, 0x90, 0x80, 0x83, 0x83, 0x60, 0x00, 0x5b, 0x83, 0x81, 0x10, 0x15, 0x61, 0x05, 0x4e, 0x57, 0x80, 0x82, 0x01, 0x51, 0x81, 0x84, 0x01, 0x52, 0x60, 0x20, 0x81, 0x01, 0x90, 0x50, 0x61, 0x05, 0x33, 0x56, 0x5b, 0x50, 0x50, 0x50, 0x50, 0x90, 0x50, 0x90, 0x81, 0x01, 0x90, 0x60, 0x1f, 0x16, 0x80, 0x15, 0x61, 0x05, 0x7b, 0x57, 0x80, 0x82, 0x03, 0x80, 0x51, 0x60, 0x01, 0x83, 0x60, 0x20, 0x03, 0x61, 0x01, 0x00, 0x0a, 0x03, 0x19, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x91, 0x50, 0x5b, 0x50, 0x94, 0x50, 0x50, 0x50, 0x50, 0x50, 0x60, 0x40, 0x51, 0x80, 0x91, 0x03, 0x90, 0xf3, 0x5b, 0x34, 0x80, 0x15, 0x61, 0x05, 0x97, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x50, 0x61, 0x05, 0xb6, 0x60, 0x04, 0x80, 0x36, 0x03, 0x81, 0x01, 0x90, 0x80, 0x80, 0x35, 0x90, 0x60, 0x20, 0x01, 0x90, 0x92, 0x91, 0x90, 0x50, 0x50, 0x50, 0x61, 0x12, 0x30, 0x56, 0x5b, 0x60, 0x40, 0x51, 0x80, 0x82, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x91, 0x50, 0x50, 0x60, 0x40, 0x51, 0x80, 0x91, 0x03, 0x90, 0xf3, 0x5b, 0x60, 0x00, 0x81, 0x51, 0x11, 0x15, 0x15, 0x61, 0x06, 0x08, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x60, 0x08, 0x60, 0x00, 0x90, 0x54, 0x90, 0x61, 0x01, 0x00, 0x0a, 0x90, 0x04, 0x60, 0xff, 0x16, 0x15, 0x15, 0x61, 0x06, 0x23, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x67, 0x0d, 0xe0, 0xb6, 0xb3, 0xa7, 0x64, 0x00, 0x00, 0x60, 0x0a, 0x54, 0x02, 0x34, 0x14, 0x15, 0x15, 0x61, 0x06, 0x3d, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x60, 0x09, 0x54, 0x60, 0x03, 0x60, 0x00, 0x33, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x90, 0x81, 0x52, 0x60, 0x20, 0x01, 0x60, 0x00, 0x20, 0x60, 0x01, 0x01, 0x54, 0x10, 0x15, 0x15, 0x61, 0x06, 0x8f, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x61, 0x06, 0x98, 0x33, 0x61, 0x12, 0x6e, 0x56, 0x5b, 0x15, 0x61, 0x07, 0xef, 0x57, 0x60, 0x01, 0x60, 0x03, 0x60, 0x00, 0x33, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x90, 0x81, 0x52, 0x60, 0x20, 0x01, 0x60, 0x00, 0x20, 0x60, 0x01, 0x01, 0x81, 0x90, 0x55, 0x50, 0x80, 0x60, 0x03, 0x60, 0x00, 0x33, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x90, 0x81, 0x52, 0x60, 0x20, 0x01, 0x60, 0x00, 0x20, 0x60, 0x00, 0x01, 0x90, 0x80, 0x51, 0x90, 0x60, 0x20, 0x01, 0x90, 0x61, 0x07, 0x3b, 0x92, 0x91, 0x90, 0x61, 0x13, 0xcb, 0x56, 0x5b, 0x50, 0x60, 0x01, 0x60, 0x02, 0x33, 0x90, 0x80, 0x60, 0x01, 0x81, 0x54, 0x01, 0x80, 0x82, 0x55, 0x80, 0x91, 0x50, 0x50, 0x90, 0x60, 0x01, 0x82, 0x03, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x01, 0x60, 0x00, 0x90, 0x91, 0x92, 0x90, 0x91, 0x90, 0x91, 0x61, 0x01, 0x00, 0x0a, 0x81, 0x54, 0x81, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0x19, 0x16, 0x90, 0x83, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x02, 0x17, 0x90, 0x55, 0x50, 0x03, 0x60, 0x03, 0x60, 0x00, 0x33, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x90, 0x81, 0x52, 0x60, 0x20, 0x01, 0x60, 0x00, 0x20, 0x60, 0x02, 0x01, 0x81, 0x90, 0x55, 0x50, 0x61, 0x08, 0x41, 0x56, 0x5b, 0x60, 0x01, 0x60, 0x03, 0x60, 0x00, 0x33, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x90, 0x81, 0x52, 0x60, 0x20, 0x01, 0x60, 0x00, 0x20, 0x60, 0x01, 0x01, 0x60, 0x00, 0x82, 0x82, 0x54, 0x01, 0x92, 0x50, 0x50, 0x81, 0x90, 0x55, 0x50, 0x5b, 0x60, 0x04, 0x33, 0x90, 0x80, 0x60, 0x01, 0x81, 0x54, 0x01, 0x80, 0x82, 0x55, 0x80, 0x91, 0x50, 0x50, 0x90, 0x60, 0x01, 0x82, 0x03, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x01, 0x60, 0x00, 0x90, 0x91, 0x92, 0x90, 0x91, 0x90, 0x91, 0x61, 0x01, 0x00, 0x0a, 0x81, 0x54, 0x81, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0x19, 0x16, 0x90, 0x83, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x02, 0x17, 0x90, 0x55, 0x50, 0x50, 0x7f, 0x76, 0x04, 0x1b, 0x6e, 0x81, 0x30, 0x99, 0x58, 0x74, 0xe7, 0x9e, 0x75, 0x1d, 0x28, 0x45, 0x36, 0xc3, 0x72, 0x42, 0xcb, 0x01, 0x4f, 0xb0, 0x58, 0x4e, 0xde, 0x1d, 0x1e, 0x64, 0xce, 0x03, 0xc9, 0x60, 0x03, 0x60, 0x00, 0x33, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x90, 0x81, 0x52, 0x60, 0x20, 0x01, 0x60, 0x00, 0x20, 0x60, 0x00, 0x01, 0x60, 0x03, 0x60, 0x00, 0x33, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x90, 0x81, 0x52, 0x60, 0x20, 0x01, 0x60, 0x00, 0x20, 0x60, 0x01, 0x01, 0x54, 0x60, 0x40, 0x51, 0x80, 0x80, 0x60, 0x20, 0x01, 0x83, 0x81, 0x52, 0x60, 0x20, 0x01, 0x82, 0x81, 0x03, 0x82, 0x52, 0x84, 0x81, 0x81, 0x54, 0x60, 0x01, 0x81, 0x60, 0x01, 0x16, 0x15, 0x61, 0x01, 0x00, 0x02, 0x03, 0x16, 0x60, 0x02, 0x90, 0x04, 0x81, 0x52, 0x60, 0x20, 0x01, 0x91, 0x50, 0x80, 0x54, 0x60, 0x01, 0x81, 0x60, 0x01, 0x16, 0x15, 0x61, 0x01, 0x00, 0x02, 0x03, 0x16, 0x60, 0x02, 0x90, 0x04, 0x80, 0x15, 0x61, 0x09, 0xdc, 0x57, 0x80, 0x60, 0x1f, 0x10, 0x61, 0x09, 0xb1, 0x57, 0x61, 0x01, 0x00, 0x80, 0x83, 0x54, 0x04, 0x02, 0x83, 0x52, 0x91, 0x60, 0x20, 0x01, 0x91, 0x61, 0x09, 0xdc, 0x56, 0x5b, 0x82, 0x01, 0x91, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x90, 0x5b, 0x81, 0x54, 0x81, 0x52, 0x90, 0x60, 0x01, 0x01, 0x90, 0x60, 0x20, 0x01, 0x80, 0x83, 0x11, 0x61, 0x09, 0xbf, 0x57, 0x82, 0x90, 0x03, 0x60, 0x1f, 0x16, 0x82, 0x01, 0x91, 0x5b, 0x50, 0x50, 0x93, 0x50, 0x50, 0x50, 0x50, 0x60, 0x40, 0x51, 0x80, 0x91, 0x03, 0x90, 0xa1, 0x50, 0x56, 0x5b, 0x60, 0x08, 0x60, 0x00, 0x90, 0x54, 0x90, 0x61, 0x01, 0x00, 0x0a, 0x90, 0x04, 0x60, 0xff, 0x16, 0x81, 0x56, 0x5b, 0x60, 0x00, 0x60, 0x01, 0x60, 0x00, 0x90, 0x54, 0x90, 0x61, 0x01, 0x00, 0x0a, 0x90, 0x04, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x33, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x14, 0x15, 0x15, 0x61, 0x0a, 0x5f, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x60, 0x00, 0x60, 0x04, 0x80, 0x54, 0x90, 0x50, 0x11, 0x15, 0x15, 0x61, 0x0a, 0x73, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x60, 0x04, 0x80, 0x54, 0x90, 0x50, 0x61, 0x0a, 0x81, 0x61, 0x13, 0x39, 0x56, 0x5b, 0x81, 0x15, 0x15, 0x61, 0x0a, 0x8a, 0x57, 0xfe, 0x5b, 0x06, 0x90, 0x50, 0x60, 0x04, 0x81, 0x81, 0x54, 0x81, 0x10, 0x15, 0x15, 0x61, 0x0a, 0x9c, 0x57, 0xfe, 0x5b, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x01, 0x60, 0x00, 0x90, 0x54, 0x90, 0x61, 0x01, 0x00, 0x0a, 0x90, 0x04, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x61, 0x08, 0xfc, 0x30, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x31, 0x90, 0x81, 0x15, 0x02, 0x90, 0x60, 0x40, 0x51, 0x60, 0x00, 0x60, 0x40, 0x51, 0x80, 0x83, 0x03, 0x81, 0x85, 0x88, 0x88, 0xf1, 0x93, 0x50, 0x50, 0x50, 0x50, 0x15, 0x80, 0x15, 0x61, 0x0b, 0x23, 0x57, 0x3d, 0x60, 0x00, 0x80, 0x3e, 0x3d, 0x60, 0x00, 0xfd, 0x5b, 0x50, 0x60, 0x03, 0x60, 0x00, 0x60, 0x04, 0x83, 0x81, 0x54, 0x81, 0x10, 0x15, 0x15, 0x61, 0x0b, 0x37, 0x57, 0xfe, 0x5b, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x01, 0x60, 0x00, 0x90, 0x54, 0x90, 0x61, 0x01, 0x00, 0x0a, 0x90, 0x04, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x90, 0x81, 0x52, 0x60, 0x20, 0x01, 0x60, 0x00, 0x20, 0x60, 0x00, 0x01, 0x60, 0x05, 0x60, 0x00, 0x01, 0x90, 0x80, 0x54, 0x60, 0x01, 0x81, 0x60, 0x01, 0x16, 0x15, 0x61, 0x01, 0x00, 0x02, 0x03, 0x16, 0x60, 0x02, 0x90, 0x04, 0x61, 0x0b, 0xc3, 0x92, 0x91, 0x90, 0x61, 0x14, 0x4b, 0x56, 0x5b, 0x50, 0x60, 0x03, 0x60, 0x00, 0x60, 0x04, 0x83, 0x81, 0x54, 0x81, 0x10, 0x15, 0x15, 0x61, 0x0b, 0xd7, 0x57, 0xfe, 0x5b, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x01, 0x60, 0x00, 0x90, 0x54, 0x90, 0x61, 0x01, 0x00, 0x0a, 0x90, 0x04, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x90, 0x81, 0x52, 0x60, 0x20, 0x01, 0x60, 0x00, 0x20, 0x60, 0x01, 0x01, 0x54, 0x60, 0x05, 0x60, 0x01, 0x01, 0x81, 0x90, 0x55, 0x50, 0x60, 0x00, 0x60, 0x40, 0x51, 0x90, 0x80, 0x82, 0x52, 0x80, 0x60, 0x20, 0x02, 0x60, 0x20, 0x01, 0x82, 0x01, 0x60, 0x40, 0x52, 0x80, 0x15, 0x61, 0x0c, 0x79, 0x57, 0x81, 0x60, 0x20, 0x01, 0x60, 0x20, 0x82, 0x02, 0x80, 0x38, 0x83, 0x39, 0x80, 0x82, 0x01, 0x91, 0x50, 0x50, 0x90, 0x50, 0x5b, 0x50, 0x60, 0x04, 0x90, 0x80, 0x51, 0x90, 0x60, 0x20, 0x01, 0x90, 0x61, 0x0c, 0x8f, 0x92, 0x91, 0x90, 0x61, 0x14, 0xd2, 0x56, 0x5b, 0x50, 0x60, 0x00, 0x60, 0x40, 0x51, 0x90, 0x80, 0x82, 0x52, 0x80, 0x60, 0x20, 0x02, 0x60, 0x20, 0x01, 0x82, 0x01, 0x60, 0x40, 0x52, 0x80, 0x15, 0x61, 0x0c, 0xc0, 0x57, 0x81, 0x60, 0x20, 0x01, 0x60, 0x20, 0x82, 0x02, 0x80, 0x38, 0x83, 0x39, 0x80, 0x82, 0x01, 0x91, 0x50, 0x50, 0x90, 0x50, 0x5b, 0x50, 0x60, 0x02, 0x90, 0x80, 0x51, 0x90, 0x60, 0x20, 0x01, 0x90, 0x61, 0x0c, 0xd6, 0x92, 0x91, 0x90, 0x61, 0x14, 0xd2, 0x56, 0x5b, 0x50, 0x60, 0x00, 0x60, 0x08, 0x60, 0x00, 0x61, 0x01, 0x00, 0x0a, 0x81, 0x54, 0x81, 0x60, 0xff, 0x02, 0x19, 0x16, 0x90, 0x83, 0x15, 0x15, 0x02, 0x17, 0x90, 0x55, 0x50, 0x7f, 0xd6, 0xd1, 0xee, 0xba, 0x63, 0x92, 0x54, 0xbd, 0x05, 0xe3, 0x62, 0x61, 0xae, 0x29, 0x9a, 0xf2, 0x45, 0x32, 0x8a, 0xb9, 0x97, 0xfd, 0x9b, 0x78, 0x23, 0xd5, 0xff, 0xf1, 0x7f, 0x1b, 0x74, 0xa4, 0x60, 0x05, 0x60, 0x00, 0x01, 0x60, 0x05, 0x60, 0x01, 0x01, 0x54, 0x60, 0x40, 0x51, 0x80, 0x80, 0x60, 0x20, 0x01, 0x83, 0x81, 0x52, 0x60, 0x20, 0x01, 0x82, 0x81, 0x03, 0x82, 0x52, 0x84, 0x81, 0x81, 0x54, 0x60, 0x01, 0x81, 0x60, 0x01, 0x16, 0x15, 0x61, 0x01, 0x00, 0x02, 0x03, 0x16, 0x60, 0x02, 0x90, 0x04, 0x81, 0x52, 0x60, 0x20, 0x01, 0x91, 0x50, 0x80, 0x54, 0x60, 0x01, 0x81, 0x60, 0x01, 0x16, 0x15, 0x61, 0x01, 0x00, 0x02, 0x03, 0x16, 0x60, 0x02, 0x90, 0x04, 0x80, 0x15, 0x61, 0x0d, 0xad, 0x57, 0x80, 0x60, 0x1f, 0x10, 0x61, 0x0d, 0x82, 0x57, 0x61, 0x01, 0x00, 0x80, 0x83, 0x54, 0x04, 0x02, 0x83, 0x52, 0x91, 0x60, 0x20, 0x01, 0x91, 0x61, 0x0d, 0xad, 0x56, 0x5b, 0x82, 0x01, 0x91, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x90, 0x5b, 0x81, 0x54, 0x81, 0x52, 0x90, 0x60, 0x01, 0x01, 0x90, 0x60, 0x20, 0x01, 0x80, 0x83, 0x11, 0x61, 0x0d, 0x90, 0x57, 0x82, 0x90, 0x03, 0x60, 0x1f, 0x16, 0x82, 0x01, 0x91, 0x5b, 0x50, 0x50, 0x93, 0x50, 0x50, 0x50, 0x50, 0x60, 0x40, 0x51, 0x80, 0x91, 0x03, 0x90, 0xa1, 0x50, 0x56, 0x5b, 0x60, 0x00, 0x80, 0x54, 0x60, 0x01, 0x81, 0x60, 0x01, 0x16, 0x15, 0x61, 0x01, 0x00, 0x02, 0x03, 0x16, 0x60, 0x02, 0x90, 0x04, 0x80, 0x60, 0x1f, 0x01, 0x60, 0x20, 0x80, 0x91, 0x04, 0x02, 0x60, 0x20, 0x01, 0x60, 0x40, 0x51, 0x90, 0x81, 0x01, 0x60, 0x40, 0x52, 0x80, 0x92, 0x91, 0x90, 0x81, 0x81, 0x52, 0x60, 0x20, 0x01, 0x82, 0x80, 0x54, 0x60, 0x01, 0x81, 0x60, 0x01, 0x16, 0x15, 0x61, 0x01, 0x00, 0x02, 0x03, 0x16, 0x60, 0x02, 0x90, 0x04, 0x80, 0x15, 0x61, 0x0e, 0x55, 0x57, 0x80, 0x60, 0x1f, 0x10, 0x61, 0x0e, 0x2a, 0x57, 0x61, 0x01, 0x00, 0x80, 0x83, 0x54, 0x04, 0x02, 0x83, 0x52, 0x91, 0x60, 0x20, 0x01, 0x91, 0x61, 0x0e, 0x55, 0x56, 0x5b, 0x82, 0x01, 0x91, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x90, 0x5b, 0x81, 0x54, 0x81, 0x52, 0x90, 0x60, 0x01, 0x01, 0x90, 0x60, 0x20, 0x01, 0x80, 0x83, 0x11, 0x61, 0x0e, 0x38, 0x57, 0x82, 0x90, 0x03, 0x60, 0x1f, 0x16, 0x82, 0x01, 0x91, 0x5b, 0x50, 0x50, 0x50, 0x50, 0x50, 0x81, 0x56, 0x5b, 0x60, 0x01, 0x60, 0x00, 0x90, 0x54, 0x90, 0x61, 0x01, 0x00, 0x0a, 0x90, 0x04, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x56, 0x5b, 0x60, 0x02, 0x81, 0x81, 0x54, 0x81, 0x10, 0x15, 0x15, 0x61, 0x0e, 0x92, 0x57, 0xfe, 0x5b, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x01, 0x60, 0x00, 0x91, 0x50, 0x54, 0x90, 0x61, 0x01, 0x00, 0x0a, 0x90, 0x04, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x56, 0x5b, 0x60, 0x60, 0x60, 0x00, 0x61, 0x0e, 0xce, 0x83, 0x61, 0x12, 0x6e, 0x56, 0x5b, 0x15, 0x61, 0x0e, 0xf3, 0x57, 0x60, 0x00, 0x60, 0x20, 0x60, 0x40, 0x51, 0x90, 0x81, 0x01, 0x60, 0x40, 0x52, 0x80, 0x60, 0x00, 0x81, 0x52, 0x50, 0x90, 0x80, 0x90, 0x50, 0x91, 0x50, 0x91, 0x50, 0x61, 0x10, 0x19, 0x56, 0x5b, 0x60, 0x03, 0x60, 0x00, 0x84, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x90, 0x81, 0x52, 0x60, 0x20, 0x01, 0x60, 0x00, 0x20, 0x60, 0x00, 0x01, 0x60, 0x03, 0x60, 0x00, 0x85, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x90, 0x81, 0x52, 0x60, 0x20, 0x01, 0x60, 0x00, 0x20, 0x60, 0x01, 0x01, 0x54, 0x81, 0x80, 0x54, 0x60, 0x01, 0x81, 0x60, 0x01, 0x16, 0x15, 0x61, 0x01, 0x00, 0x02, 0x03, 0x16, 0x60, 0x02, 0x90, 0x04, 0x80, 0x60, 0x1f, 0x01, 0x60, 0x20, 0x80, 0x91, 0x04, 0x02, 0x60, 0x20, 0x01, 0x60, 0x40, 0x51, 0x90, 0x81, 0x01, 0x60, 0x40, 0x52, 0x80, 0x92, 0x91, 0x90, 0x81, 0x81, 0x52, 0x60, 0x20, 0x01, 0x82, 0x80, 0x54, 0x60, 0x01, 0x81, 0x60, 0x01, 0x16, 0x15, 0x61, 0x01, 0x00, 0x02, 0x03, 0x16, 0x60, 0x02, 0x90, 0x04, 0x80, 0x15, 0x61, 0x10, 0x0d, 0x57, 0x80, 0x60, 0x1f, 0x10, 0x61, 0x0f, 0xe2, 0x57, 0x61, 0x01, 0x00, 0x80, 0x83, 0x54, 0x04, 0x02, 0x83, 0x52, 0x91, 0x60, 0x20, 0x01, 0x91, 0x61, 0x10, 0x0d, 0x56, 0x5b, 0x82, 0x01, 0x91, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x90, 0x5b, 0x81, 0x54, 0x81, 0x52, 0x90, 0x60, 0x01, 0x01, 0x90, 0x60, 0x20, 0x01, 0x80, 0x83, 0x11, 0x61, 0x0f, 0xf0, 0x57, 0x82, 0x90, 0x03, 0x60, 0x1f, 0x16, 0x82, 0x01, 0x91, 0x5b, 0x50, 0x50, 0x50, 0x50, 0x50, 0x91, 0x50, 0x91, 0x50, 0x91, 0x50, 0x5b, 0x91, 0x50, 0x91, 0x56, 0x5b, 0x60, 0x0a, 0x54, 0x81, 0x56, 0x5b, 0x60, 0x09, 0x54, 0x81, 0x56, 0x5b, 0x60, 0x60, 0x60, 0x02, 0x80, 0x54, 0x80, 0x60, 0x20, 0x02, 0x60, 0x20, 0x01, 0x60, 0x40, 0x51, 0x90, 0x81, 0x01, 0x60, 0x40, 0x52, 0x80, 0x92, 0x91, 0x90, 0x81, 0x81, 0x52, 0x60, 0x20, 0x01, 0x82, 0x80, 0x54, 0x80, 0x15, 0x61, 0x10, 0xae, 0x57, 0x60, 0x20, 0x02, 0x82, 0x01, 0x91, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x90, 0x5b, 0x81, 0x60, 0x00, 0x90, 0x54, 0x90, 0x61, 0x01, 0x00, 0x0a, 0x90, 0x04, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x90, 0x60, 0x01, 0x01, 0x90, 0x80, 0x83, 0x11, 0x61, 0x10, 0x64, 0x57, 0x5b, 0x50, 0x50, 0x50, 0x50, 0x50, 0x90, 0x50, 0x90, 0x56, 0x5b, 0x60, 0x01, 0x60, 0x00, 0x90, 0x54, 0x90, 0x61, 0x01, 0x00, 0x0a, 0x90, 0x04, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x33, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x14, 0x15, 0x15, 0x61, 0x11, 0x14, 0x57, 0x60, 0x00, 0x80, 0xfd, 0x5b, 0x60, 0x01, 0x60, 0x08, 0x60, 0x00, 0x61, 0x01, 0x00, 0x0a, 0x81, 0x54, 0x81, 0x60, 0xff, 0x02, 0x19, 0x16, 0x90, 0x83, 0x15, 0x15, 0x02, 0x17, 0x90, 0x55, 0x50, 0x60, 0x00, 0x82, 0x14, 0x61, 0x11, 0x3d, 0x57, 0x81, 0x61, 0x11, 0x40, 0x56, 0x5b, 0x60, 0x01, 0x5b, 0x60, 0x09, 0x81, 0x90, 0x55, 0x50, 0x60, 0x00, 0x81, 0x14, 0x61, 0x11, 0x54, 0x57, 0x80, 0x61, 0x11, 0x57, 0x56, 0x5b, 0x60, 0x01, 0x5b, 0x60, 0x0a, 0x81, 0x90, 0x55, 0x50, 0x50, 0x50, 0x56, 0x5b, 0x60, 0x00, 0x30, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x31, 0x90, 0x50, 0x90, 0x56, 0x5b, 0x60, 0x05, 0x80, 0x60, 0x00, 0x01, 0x80, 0x54, 0x60, 0x01, 0x81, 0x60, 0x01, 0x16, 0x15, 0x61, 0x01, 0x00, 0x02, 0x03, 0x16, 0x60, 0x02, 0x90, 0x04, 0x80, 0x60, 0x1f, 0x01, 0x60, 0x20, 0x80, 0x91, 0x04, 0x02, 0x60, 0x20, 0x01, 0x60, 0x40, 0x51, 0x90, 0x81, 0x01, 0x60, 0x40, 0x52, 0x80, 0x92, 0x91, 0x90, 0x81, 0x81, 0x52, 0x60, 0x20, 0x01, 0x82, 0x80, 0x54, 0x60, 0x01, 0x81, 0x60, 0x01, 0x16, 0x15, 0x61, 0x01, 0x00, 0x02, 0x03, 0x16, 0x60, 0x02, 0x90, 0x04, 0x80, 0x15, 0x61, 0x12, 0x1a, 0x57, 0x80, 0x60, 0x1f, 0x10, 0x61, 0x11, 0xef, 0x57, 0x61, 0x01, 0x00, 0x80, 0x83, 0x54, 0x04, 0x02, 0x83, 0x52, 0x91, 0x60, 0x20, 0x01, 0x91, 0x61, 0x12, 0x1a, 0x56, 0x5b, 0x82, 0x01, 0x91, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x90, 0x5b, 0x81, 0x54, 0x81, 0x52, 0x90, 0x60, 0x01, 0x01, 0x90, 0x60, 0x20, 0x01, 0x80, 0x83, 0x11, 0x61, 0x11, 0xfd, 0x57, 0x82, 0x90, 0x03, 0x60, 0x1f, 0x16, 0x82, 0x01, 0x91, 0x5b, 0x50, 0x50, 0x50, 0x50, 0x50, 0x90, 0x80, 0x60, 0x01, 0x01, 0x54, 0x90, 0x80, 0x60, 0x02, 0x01, 0x54, 0x90, 0x50, 0x83, 0x56, 0x5b, 0x60, 0x04, 0x81, 0x81, 0x54, 0x81, 0x10, 0x15, 0x15, 0x61, 0x12, 0x3f, 0x57, 0xfe, 0x5b, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x01, 0x60, 0x00, 0x91, 0x50, 0x54, 0x90, 0x61, 0x01, 0x00, 0x0a, 0x90, 0x04, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x56, 0x5b, 0x60, 0x00, 0x80, 0x60, 0x02, 0x80, 0x54, 0x90, 0x50, 0x14, 0x15, 0x61, 0x12, 0x86, 0x57, 0x60, 0x01, 0x90, 0x50, 0x61, 0x13, 0x34, 0x56, 0x5b, 0x81, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x60, 0x02, 0x60, 0x03, 0x60, 0x00, 0x85, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x90, 0x81, 0x52, 0x60, 0x20, 0x01, 0x60, 0x00, 0x20, 0x60, 0x02, 0x01, 0x54, 0x81, 0x54, 0x81, 0x10, 0x15, 0x15, 0x61, 0x12, 0xee, 0x57, 0xfe, 0x5b, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x01, 0x60, 0x00, 0x90, 0x54, 0x90, 0x61, 0x01, 0x00, 0x0a, 0x90, 0x04, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x14, 0x15, 0x90, 0x50, 0x5b, 0x91, 0x90, 0x50, 0x56, 0x5b, 0x60, 0x00, 0x44, 0x42, 0x60, 0x04, 0x60, 0x40, 0x51, 0x80, 0x84, 0x81, 0x52, 0x60, 0x20, 0x01, 0x83, 0x81, 0x52, 0x60, 0x20, 0x01, 0x82, 0x80, 0x54, 0x80, 0x15, 0x61, 0x13, 0xb3, 0x57, 0x60, 0x20, 0x02, 0x82, 0x01, 0x91, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x90, 0x5b, 0x81, 0x60, 0x00, 0x90, 0x54, 0x90, 0x61, 0x01, 0x00, 0x0a, 0x90, 0x04, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x81, 0x52, 0x60, 0x20, 0x01, 0x90, 0x60, 0x01, 0x01, 0x90, 0x80, 0x83, 0x11, 0x61, 0x13, 0x69, 0x57, 0x5b, 0x50, 0x50, 0x93, 0x50, 0x50, 0x50, 0x50, 0x60, 0x40, 0x51, 0x80, 0x91, 0x03, 0x90, 0x20, 0x60, 0x01, 0x90, 0x04, 0x90, 0x50, 0x90, 0x56, 0x5b, 0x82, 0x80, 0x54, 0x60, 0x01, 0x81, 0x60, 0x01, 0x16, 0x15, 0x61, 0x01, 0x00, 0x02, 0x03, 0x16, 0x60, 0x02, 0x90, 0x04, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x90, 0x60, 0x1f, 0x01, 0x60, 0x20, 0x90, 0x04, 0x81, 0x01, 0x92, 0x82, 0x60, 0x1f, 0x10, 0x61, 0x14, 0x0c, 0x57, 0x80, 0x51, 0x60, 0xff, 0x19, 0x16, 0x83, 0x80, 0x01, 0x17, 0x85, 0x55, 0x61, 0x14, 0x3a, 0x56, 0x5b, 0x82, 0x80, 0x01, 0x60, 0x01, 0x01, 0x85, 0x55, 0x82, 0x15, 0x61, 0x14, 0x3a, 0x57, 0x91, 0x82, 0x01, 0x5b, 0x82, 0x81, 0x11, 0x15, 0x61, 0x14, 0x39, 0x57, 0x82, 0x51, 0x82, 0x55, 0x91, 0x60, 0x20, 0x01, 0x91, 0x90, 0x60, 0x01, 0x01, 0x90, 0x61, 0x14, 0x1e, 0x56, 0x5b, 0x5b, 0x50, 0x90, 0x50, 0x61, 0x14, 0x47, 0x91, 0x90, 0x61, 0x15, 0x5c, 0x56, 0x5b, 0x50, 0x90, 0x56, 0x5b, 0x82, 0x80, 0x54, 0x60, 0x01, 0x81, 0x60, 0x01, 0x16, 0x15, 0x61, 0x01, 0x00, 0x02, 0x03, 0x16, 0x60, 0x02, 0x90, 0x04, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x90, 0x60, 0x1f, 0x01, 0x60, 0x20, 0x90, 0x04, 0x81, 0x01, 0x92, 0x82, 0x60, 0x1f, 0x10, 0x61, 0x14, 0x84, 0x57, 0x80, 0x54, 0x85, 0x55, 0x61, 0x14, 0xc1, 0x56, 0x5b, 0x82, 0x80, 0x01, 0x60, 0x01, 0x01, 0x85, 0x55, 0x82, 0x15, 0x61, 0x14, 0xc1, 0x57, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x91, 0x60, 0x1f, 0x01, 0x60, 0x20, 0x90, 0x04, 0x82, 0x01, 0x5b, 0x82, 0x81, 0x11, 0x15, 0x61, 0x14, 0xc0, 0x57, 0x82, 0x54, 0x82, 0x55, 0x91, 0x60, 0x01, 0x01, 0x91, 0x90, 0x60, 0x01, 0x01, 0x90, 0x61, 0x14, 0xa5, 0x56, 0x5b, 0x5b, 0x50, 0x90, 0x50, 0x61, 0x14, 0xce, 0x91, 0x90, 0x61, 0x15, 0x5c, 0x56, 0x5b, 0x50, 0x90, 0x56, 0x5b, 0x82, 0x80, 0x54, 0x82, 0x82, 0x55, 0x90, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0x20, 0x90, 0x81, 0x01, 0x92, 0x82, 0x15, 0x61, 0x15, 0x4b, 0x57, 0x91, 0x60, 0x20, 0x02, 0x82, 0x01, 0x5b, 0x82, 0x81, 0x11, 0x15, 0x61, 0x15, 0x4a, 0x57, 0x82, 0x51, 0x82, 0x60, 0x00, 0x61, 0x01, 0x00, 0x0a, 0x81, 0x54, 0x81, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0x19, 0x16, 0x90, 0x83, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x02, 0x17, 0x90, 0x55, 0x50, 0x91, 0x60, 0x20, 0x01, 0x91, 0x90, 0x60, 0x01, 0x01, 0x90, 0x61, 0x14, 0xf2, 0x56, 0x5b, 0x5b, 0x50, 0x90, 0x50, 0x61, 0x15, 0x58, 0x91, 0x90, 0x61, 0x15, 0x81, 0x56, 0x5b, 0x50, 0x90, 0x56, 0x5b, 0x61, 0x15, 0x7e, 0x91, 0x90, 0x5b, 0x80, 0x82, 0x11, 0x15, 0x61, 0x15, 0x7a, 0x57, 0x60, 0x00, 0x81, 0x60, 0x00, 0x90, 0x55, 0x50, 0x60, 0x01, 0x01, 0x61, 0x15, 0x62, 0x56, 0x5b, 0x50, 0x90, 0x56, 0x5b, 0x90, 0x56, 0x5b, 0x61, 0x15, 0xc1, 0x91, 0x90, 0x5b, 0x80, 0x82, 0x11, 0x15, 0x61, 0x15, 0xbd, 0x57, 0x60, 0x00, 0x81, 0x81, 0x61, 0x01, 0x00, 0x0a, 0x81, 0x54, 0x90, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0x19, 0x16, 0x90, 0x55, 0x50, 0x60, 0x01, 0x01, 0x61, 0x15, 0x87, 0x56, 0x5b, 0x50, 0x90, 0x56, 0x5b, 0x90, 0x56, 0x00, 0xa1, 0x65, 0x62, 0x7a, 0x7a, 0x72, 0x30, 0x58, 0x20, 0xa8, 0xfb, 0x9f, 0x06, 0x53, 0x3d, 0xb9, 0x44, 0x22, 0x03, 0x33, 0x2b, 0xcb, 0x5c, 0x2e, 0xdf, 0x68, 0xb6, 0x99, 0xd5, 0x4b, 0x7d, 0xb0, 0xbe, 0x9b, 0x1c, 0xa7, 0x85, 0x28, 0x47, 0x5c, 0x18, 0x00, 0x29}; - // machine::context ctx = {true, 0x00}; - // machine::message msg = {}; - // machine::chain_adapter adapter = make_chain_adapter(); - // machine::machine m(ctx, input, msg, adapter); - // assert_message( "machine should start running", m.get_state() == machine::machine_state::running ); + test_that("push opcodes / to_big_word work") + { + std::vector input = {0x7f, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00}; + machine::context ctx = {true, 0x00}; + machine::message msg = {}; + machine::chain_adapter adapter = make_chain_adapter(); + machine::machine m(ctx, input, msg, adapter); + assert_message( "machine should start running", m.get_state() == machine::machine_state::running ); - // std::string line; - // while (m.is_running()) - // { - // m.step(); - // while ( std::getline(m.get_logger(), line) ) - // std::cerr << "\e[36m" << "LOG: " << line << "\e[0m" << std::endl; - // std::cout << m.to_json() << std::endl; - // } - // while ( std::getline(m.get_logger(), line) ) - // std::cerr << "\e[36m" << "LOG: " << line << "\e[0m" << std::endl; - // std::cout << m.to_json() << std::endl; + std::string line; + while (m.is_running()) + { + m.step(); + while ( std::getline(m.get_logger(), line) ) + std::cerr << "\e[36m" << "LOG: " << line << "\e[0m" << std::endl; + std::cout << m.to_json() << std::endl; + } + while ( std::getline(m.get_logger(), line) ) + std::cerr << "\e[36m" << "LOG: " << line << "\e[0m" << std::endl; + std::cout << m.to_json() << std::endl; - // assert_message( "machine should stop when done executing", m.get_state() == machine::machine_state::stopped ); - // assert_message( "stack has correct length", m.stack_length() == 0 ); - //} + assert_message( "machine should stop when done executing", m.get_state() == machine::machine_state::stopped ); + assert_message( "stack has correct length", m.stack_length() == 1 ); + } return 0; } From 3a0e52e962e51061aab39ac6382511b4113d8523 Mon Sep 17 00:00:00 2001 From: Liam Noroian Date: Mon, 6 Dec 2021 15:00:23 -0800 Subject: [PATCH 79/96] WIP handle contract preamble --- libraries/chain/xgt_evaluator.cpp | 40 +++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/libraries/chain/xgt_evaluator.cpp b/libraries/chain/xgt_evaluator.cpp index 1a1301ee..7eaafd5f 100644 --- a/libraries/chain/xgt_evaluator.cpp +++ b/libraries/chain/xgt_evaluator.cpp @@ -1049,18 +1049,6 @@ fc::ripemd160 make_contract_hash(const wallet_name_type& owner, const vector( [&](contract_object& c) - { - c.contract_hash = make_contract_hash(op.owner, op.code); - wlog("!!!!!! contract_create contract_hash ${c}", ("c",c.contract_hash)); - c.owner = op.owner; - c.code = op.code; - }); -} - // Forward declaration machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type o, wallet_name_type c, contract_hash_type contract_hash, map& storage); @@ -1233,7 +1221,7 @@ std::vector contract_invoke(chain::database& _db, wallet_name_typ machine::message msg = { 0, 0, - 0, + int64_t(energy), converted_address, converted_address, value, @@ -1299,6 +1287,32 @@ std::vector contract_invoke(chain::database& _db, wallet_name_typ return m.get_return_value(); } +void contract_create_evaluator::do_apply( const contract_create_operation& op ) +{ + wlog("!!!!!! contract_create owner ${w} code size ${y}", ("w",op.owner)("y",op.code.size())); + auto base_contract = _db.create< contract_object >( [&](contract_object& c) + { + c.contract_hash = make_contract_hash(op.owner, op.code); + wlog("!!!!!! contract_create contract_hash ${c}", ("c",c.contract_hash)); + c.owner = op.owner; + c.code = op.code; + }); + + const contract_storage_object* cs = _db.find_contract_storage(base_contract.contract_hash, op.owner); + map< fc::sha256, fc::sha256 > storage; + if (cs) + storage = cs->data; + else + storage = map< fc::sha256, fc::sha256 >(); + auto machine_return = contract_invoke(_db, op.owner, op.owner, base_contract.contract_hash, 0, 0, {}, storage); + std::vector result(machine_return.begin(), machine_return.end()); + + const auto& contract = _db.get_contract(base_contract.contract_hash); + _db.modify< contract_object >(contract, [&](contract_object& c) { + c.code = result; + }); +} + std::string inspect(std::vector words) { std::stringstream ss; From d9d17cd0f6ea15c1acdfcd4995141078d7851cde Mon Sep 17 00:00:00 2001 From: Liam Noroian Date: Tue, 7 Dec 2021 14:57:07 -0800 Subject: [PATCH 80/96] Ripemd160 address type indexing --- libraries/chain/database.cpp | 12 ++++ .../chain/include/xgt/chain/wallet_object.hpp | 7 +- .../include/xgt/chain/xgt_object_types.hpp | 2 + libraries/chain/xgt_evaluator.cpp | 3 +- libraries/fc/include/fc/crypto/ripemd160.hpp | 1 + libraries/fc/src/crypto/ripemd160.cpp | 14 ++++ .../schema_types/wallet_name_type.hpp | 64 ++++++++++++------- .../protocol/include/xgt/protocol/types.hpp | 1 + .../include/xgt/protocol/xgt_operations.hpp | 2 +- libraries/vendor/xgtvm/libraries/machine.cpp | 10 ++- 10 files changed, 83 insertions(+), 33 deletions(-) diff --git a/libraries/chain/database.cpp b/libraries/chain/database.cpp index 2a57bb4d..de8f3240 100644 --- a/libraries/chain/database.cpp +++ b/libraries/chain/database.cpp @@ -1340,10 +1340,13 @@ void database::init_genesis( uint64_t init_supply ) create< wallet_object >( [&]( wallet_object& a ) { a.name = XGT_MINER_WALLET; + a.address_ripemd160 = fc::ripemd160::hex_digest(XGT_MINER_WALLET); } ); + create< account_authority_object >( [&]( account_authority_object& auth ) { auth.account = XGT_MINER_WALLET; + auth.address_ripemd160 = fc::ripemd160::hex_digest(XGT_MINER_WALLET); auth.recovery.weight_threshold = 1; auth.money.weight_threshold = 1; }); @@ -1351,6 +1354,7 @@ void database::init_genesis( uint64_t init_supply ) create< wallet_object >( [&]( wallet_object& a ) { a.name = XGT_INIT_MINER_NAME; + a.address_ripemd160 = fc::ripemd160::hex_digest(XGT_INIT_MINER_NAME); a.memo_key = init_public_key; a.balance = asset( init_supply, XGT_SYMBOL ); } ); @@ -1358,6 +1362,7 @@ void database::init_genesis( uint64_t init_supply ) create< account_authority_object >( [&]( account_authority_object& auth ) { auth.account = XGT_INIT_MINER_NAME; + auth.address_ripemd160 = fc::ripemd160::hex_digest(XGT_INIT_MINER_NAME); auth.recovery.add_authority( init_public_key, 1 ); auth.recovery.weight_threshold = 1; auth.money = auth.recovery; @@ -1373,10 +1378,13 @@ void database::init_genesis( uint64_t init_supply ) create< wallet_object >( [&]( wallet_object& a ) { a.name = XGT_NULL_WALLET; + a.address_ripemd160 = fc::ripemd160::hex_digest(XGT_NULL_WALLET); } ); + create< account_authority_object >( [&]( account_authority_object& auth ) { auth.account = XGT_NULL_WALLET; + auth.address_ripemd160 = fc::ripemd160::hex_digest(XGT_NULL_WALLET); auth.recovery.weight_threshold = 1; auth.money.weight_threshold = 1; }); @@ -1384,15 +1392,19 @@ void database::init_genesis( uint64_t init_supply ) create< wallet_object >( [&]( wallet_object& a ) { a.name = XGT_TREASURY_WALLET; + a.address_ripemd160 = fc::ripemd160::hex_digest(XGT_TREASURY_WALLET); } ); create< wallet_object >( [&]( wallet_object& a ) { a.name = XGT_TEMP_WALLET; + a.address_ripemd160 = fc::ripemd160::hex_digest(XGT_TEMP_WALLET); } ); + create< account_authority_object >( [&]( account_authority_object& auth ) { auth.account = XGT_TEMP_WALLET; + auth.address_ripemd160 = fc::ripemd160::hex_digest(XGT_TEMP_WALLET); auth.recovery.weight_threshold = 0; auth.money.weight_threshold = 0; }); diff --git a/libraries/chain/include/xgt/chain/wallet_object.hpp b/libraries/chain/include/xgt/chain/wallet_object.hpp index d8806883..f630db2f 100644 --- a/libraries/chain/include/xgt/chain/wallet_object.hpp +++ b/libraries/chain/include/xgt/chain/wallet_object.hpp @@ -31,6 +31,7 @@ namespace xgt { namespace chain { id_type id; wallet_name_type name; + address_ripemd160_type address_ripemd160; public_key_type memo_key; time_point_sec last_account_update; @@ -90,7 +91,7 @@ namespace xgt { namespace chain { id_type id; wallet_name_type account; - fc::ripemd160 address_ripemd160; + address_ripemd160_type address_ripemd160; shared_authority recovery; ///< used for backup control, can set recovery or money shared_authority money; ///< used for all monetary operations, can set money or social @@ -164,7 +165,9 @@ namespace xgt { namespace chain { ordered_unique< tag< by_id >, member< wallet_object, wallet_id_type, &wallet_object::id > >, ordered_unique< tag< by_name >, - member< wallet_object, wallet_name_type, &wallet_object::name > > + member< wallet_object, wallet_name_type, &wallet_object::name > >, + ordered_unique< tag< by_address_ripemd160 >, + member< wallet_object, address_ripemd160_type, &wallet_object::address_ripemd160 > > >, allocator< wallet_object > > wallet_index; diff --git a/libraries/chain/include/xgt/chain/xgt_object_types.hpp b/libraries/chain/include/xgt/chain/xgt_object_types.hpp index 87ce96e2..7528a946 100644 --- a/libraries/chain/include/xgt/chain/xgt_object_types.hpp +++ b/libraries/chain/include/xgt/chain/xgt_object_types.hpp @@ -42,6 +42,7 @@ using xgt::protocol::block_id_type; using xgt::protocol::transaction_id_type; using xgt::protocol::chain_id_type; using xgt::protocol::wallet_name_type; +using xgt::protocol::address_ripemd160_type; using xgt::protocol::share_type; using chainbase::shared_string; @@ -51,6 +52,7 @@ inline void from_string( shared_string& out, const string& in ){ out.assign( in. struct by_id; struct by_name; +struct by_address_ripemd160; enum object_type { diff --git a/libraries/chain/xgt_evaluator.cpp b/libraries/chain/xgt_evaluator.cpp index 7eaafd5f..060fdf20 100644 --- a/libraries/chain/xgt_evaluator.cpp +++ b/libraries/chain/xgt_evaluator.cpp @@ -149,6 +149,7 @@ void initialize_wallet_object( wallet_object& acc, const wallet_name_type& name, wlog("?????? initialize_wallet_object key ${n}", ("n", key)); wlog("?????? initialize_wallet_object created ${n}", ("n", props.time)); acc.name = name; + acc.address_ripemd160 = fc::ripemd160::hex_digest(name); acc.memo_key = key; acc.created = props.time; //acc.energybar.last_update_time = props.time.sec_since_epoch(); @@ -209,7 +210,7 @@ void wallet_create_evaluator::do_apply( const wallet_create_operation& o ) auth.recovery = o.recovery; auth.money = o.money; auth.social = o.social; - auth.address_ripemd160 = o.address_ripemd160; + auth.address_ripemd160 = fc::ripemd160::hex_digest(wallet_name); auth.last_recovery_update = fc::time_point_sec::min(); }); } diff --git a/libraries/fc/include/fc/crypto/ripemd160.hpp b/libraries/fc/include/fc/crypto/ripemd160.hpp index 912c3929..3d8d5629 100644 --- a/libraries/fc/include/fc/crypto/ripemd160.hpp +++ b/libraries/fc/include/fc/crypto/ripemd160.hpp @@ -24,6 +24,7 @@ class ripemd160 static ripemd160 hash( const fc::sha256& h ); static ripemd160 hash( const char* d, uint32_t dlen ); static ripemd160 hash( const string& ); + static string hex_digest( const string wallet_name ); template static ripemd160 hash( const T& t ) diff --git a/libraries/fc/src/crypto/ripemd160.cpp b/libraries/fc/src/crypto/ripemd160.cpp index 1ccfa5f9..076167e2 100644 --- a/libraries/fc/src/crypto/ripemd160.cpp +++ b/libraries/fc/src/crypto/ripemd160.cpp @@ -56,6 +56,20 @@ ripemd160 ripemd160::hash( const string& s ) { return hash( s.c_str(), s.size() ); } +string ripemd160::hex_digest(const string wallet_name) +{ + std::string prefix( "XGT" ); + + const size_t prefix_len = prefix.size(); + auto b58 = wallet_name.substr( prefix_len ); + auto r160 = fc::ripemd160::hash(b58); + + std::stringstream ss; + ss << std::hex << r160.str(); + + return ss.str(); +} + void ripemd160::encoder::write( const char* d, uint32_t dlen ) { RIPEMD160_Update( &my->ctx, d, dlen); } diff --git a/libraries/protocol/include/xgt/protocol/schema_types/wallet_name_type.hpp b/libraries/protocol/include/xgt/protocol/schema_types/wallet_name_type.hpp index d0d80dce..ff86c941 100644 --- a/libraries/protocol/include/xgt/protocol/schema_types/wallet_name_type.hpp +++ b/libraries/protocol/include/xgt/protocol/schema_types/wallet_name_type.hpp @@ -6,37 +6,55 @@ #include -namespace xgt { namespace schema { namespace detail { +namespace xgt { + namespace schema { + namespace detail { -////////////////////////////////////////////// -// wallet_name_type // -////////////////////////////////////////////// + ////////////////////////////////////////////// + // wallet_name_type // + ////////////////////////////////////////////// -struct schema_wallet_name_type_impl - : public abstract_schema -{ - XGT_SCHEMA_CLASS_BODY( schema_wallet_name_type_impl ) -}; + struct schema_wallet_name_type_impl : public abstract_schema + { + XGT_SCHEMA_CLASS_BODY( schema_wallet_name_type_impl ) + }; -} + } -template<> -struct schema_reflect< xgt::protocol::wallet_name_type > -{ - typedef detail::schema_wallet_name_type_impl schema_impl_type; -}; + template<> struct schema_reflect< xgt::protocol::wallet_name_type > + { + typedef detail::schema_wallet_name_type_impl schema_impl_type; + }; -} } + } +} namespace fc { -template<> -struct get_typename< xgt::protocol::wallet_name_type > -{ - static const char* name() + template<> struct get_typename< xgt::protocol::wallet_name_type > { - return "xgt::protocol::wallet_name_type"; - } -}; + static const char* name() + { + return "xgt::protocol::wallet_name_type"; + } + }; + +} +namespace xgt { + namespace schema { + namespace detail { + + ////////////////////////////////////////////// + // address_ripemd160_type // + ////////////////////////////////////////////// + + struct schema_address_ripemd160_type_impl : public abstract_schema + { + XGT_SCHEMA_CLASS_BODY( schema_address_ripemd160_type_impl ) + }; + + } + + } } diff --git a/libraries/protocol/include/xgt/protocol/types.hpp b/libraries/protocol/include/xgt/protocol/types.hpp index c40b1b01..47f9e891 100644 --- a/libraries/protocol/include/xgt/protocol/types.hpp +++ b/libraries/protocol/include/xgt/protocol/types.hpp @@ -73,6 +73,7 @@ namespace xgt { typedef fc::sha256 chain_id_type; typedef fixed_string<8> xtt_ticker_type; typedef fixed_string<256> wallet_name_type; + typedef fixed_string<256> address_ripemd160_type; typedef fc::ripemd160 block_id_type; typedef fc::ripemd160 checksum_type; typedef fc::ripemd160 transaction_id_type; diff --git a/libraries/protocol/include/xgt/protocol/xgt_operations.hpp b/libraries/protocol/include/xgt/protocol/xgt_operations.hpp index 9d344a9f..703609c9 100644 --- a/libraries/protocol/include/xgt/protocol/xgt_operations.hpp +++ b/libraries/protocol/include/xgt/protocol/xgt_operations.hpp @@ -16,7 +16,7 @@ namespace xgt { namespace protocol { asset fee; wallet_name_type creator; wallet_name_type new_wallet_name; - fc::ripemd160 address_ripemd160; + string address_ripemd160; authority recovery; authority money; authority social; diff --git a/libraries/vendor/xgtvm/libraries/machine.cpp b/libraries/vendor/xgtvm/libraries/machine.cpp index ac2e75cd..5bc61004 100644 --- a/libraries/vendor/xgtvm/libraries/machine.cpp +++ b/libraries/vendor/xgtvm/libraries/machine.cpp @@ -469,7 +469,8 @@ namespace machine va = pop_word(); // shift vb = pop_word(); // value - vc = vb >> va.convert_to(); + // TODO Implement shift in a loop for va sizes larger than 256 + vc = vb >> static_cast(va); push_word(vc); break; @@ -612,11 +613,6 @@ namespace machine offset = static_cast( pop_word() ); length = static_cast( pop_word() ); - if ((offset + length) > msg.input_size) { - logger << "Codecopy end index is larger than message input_size" << std::endl; - break; - } - for (size_t i = 0; i < length; ++i) memory[dest_offset + i] = code[offset + i]; @@ -3007,7 +3003,9 @@ namespace machine } memory[i] = 0; } + return_value = retval; adapter.revert( retval ); + state = machine_state::stopped; break; case invalid_opcode: logger << "op invalid" << std::endl; From 5897f22c4d3962897647f7f28ef4a145c38a5578 Mon Sep 17 00:00:00 2001 From: Liam Noroian Date: Wed, 8 Dec 2021 05:07:09 -0800 Subject: [PATCH 81/96] Adding wallet lookup by ripemd160 address --- libraries/chain/database.cpp | 5 +++++ libraries/chain/include/xgt/chain/database.hpp | 1 + libraries/chain/xgt_evaluator.cpp | 4 ++-- libraries/vendor/xgtvm/programs/xgtvm.cpp | 2 +- libraries/vendor/xgtvm/programs/xgtvm_tests.cpp | 2 +- 5 files changed, 10 insertions(+), 4 deletions(-) diff --git a/libraries/chain/database.cpp b/libraries/chain/database.cpp index de8f3240..43e073eb 100644 --- a/libraries/chain/database.cpp +++ b/libraries/chain/database.cpp @@ -614,6 +614,11 @@ const wallet_object& database::get_account( const wallet_name_type& name )const return get< wallet_object, by_name >( name ); } FC_CAPTURE_AND_RETHROW( (name) ) } +const wallet_object& database::get_account_by_ripemd160( const address_ripemd160_type& address_ripemd160 )const +{ try { + return get< wallet_object, by_address_ripemd160 >( address_ripemd160 ); +} FC_CAPTURE_AND_RETHROW( (address_ripemd160) ) } + const wallet_object* database::find_account( const wallet_name_type& name )const { return find< wallet_object, by_name >( name ); diff --git a/libraries/chain/include/xgt/chain/database.hpp b/libraries/chain/include/xgt/chain/database.hpp index ef9258e7..8b612c1d 100644 --- a/libraries/chain/include/xgt/chain/database.hpp +++ b/libraries/chain/include/xgt/chain/database.hpp @@ -209,6 +209,7 @@ namespace xgt { namespace chain { const contract_object& get_contract( const contract_hash_type& hash )const; const wallet_object& get_account( const wallet_name_type& name )const; + const wallet_object& get_account_by_ripemd160( const address_ripemd160_type& address_ripemd160 )const; const wallet_object* find_account( const wallet_name_type& name )const; const comment_object& get_comment( const wallet_name_type& author, const shared_string& permlink )const; diff --git a/libraries/chain/xgt_evaluator.cpp b/libraries/chain/xgt_evaluator.cpp index 060fdf20..32cb94f9 100644 --- a/libraries/chain/xgt_evaluator.cpp +++ b/libraries/chain/xgt_evaluator.cpp @@ -1352,9 +1352,9 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type return ss.str(); }; - std::function< uint64_t(std::string) > get_balance = [&](std::string address) -> uint64_t + std::function< uint64_t(std::string) > get_balance = [&](std::string address_ripemd160) -> uint64_t { - auto& wallet = _db.get_account(address); + auto& wallet = _db.get_account_by_ripemd160(address_ripemd160); return static_cast(wallet.balance.amount.value); }; diff --git a/libraries/vendor/xgtvm/programs/xgtvm.cpp b/libraries/vendor/xgtvm/programs/xgtvm.cpp index 593ac8b6..b1129c9c 100644 --- a/libraries/vendor/xgtvm/programs/xgtvm.cpp +++ b/libraries/vendor/xgtvm/programs/xgtvm.cpp @@ -60,7 +60,7 @@ machine::chain_adapter make_chain_adapter() return 0; }; - std::function< uint64_t(std::string) > get_balance = [](std::string address) -> uint64_t + std::function< uint64_t(std::string) > get_balance = [](std::string address_ripemd160) -> uint64_t { return 0; }; diff --git a/libraries/vendor/xgtvm/programs/xgtvm_tests.cpp b/libraries/vendor/xgtvm/programs/xgtvm_tests.cpp index 6968fb5c..4bb8a191 100644 --- a/libraries/vendor/xgtvm/programs/xgtvm_tests.cpp +++ b/libraries/vendor/xgtvm/programs/xgtvm_tests.cpp @@ -17,7 +17,7 @@ machine::chain_adapter make_chain_adapter() return 0; }; - std::function< uint64_t(std::string) > get_balance = [](std::string address) -> uint64_t + std::function< uint64_t(std::string) > get_balance = [](std::string address_ripemd160) -> uint64_t { std::cout << "chain_adapter::get_balance" << std::endl; return 0; From 1133aafdf54c4d130d9e4ad398e28833debea479 Mon Sep 17 00:00:00 2001 From: Liam Noroian Date: Wed, 5 Jan 2022 21:18:44 -0800 Subject: [PATCH 82/96] Adding ripemd160 utilities --- libraries/fc/include/fc/crypto/ripemd160.hpp | 2 ++ libraries/fc/src/crypto/ripemd160.cpp | 15 +++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/libraries/fc/include/fc/crypto/ripemd160.hpp b/libraries/fc/include/fc/crypto/ripemd160.hpp index 3d8d5629..3235e4bc 100644 --- a/libraries/fc/include/fc/crypto/ripemd160.hpp +++ b/libraries/fc/include/fc/crypto/ripemd160.hpp @@ -3,6 +3,7 @@ #include #include #include +#include namespace fc{ class sha512; @@ -25,6 +26,7 @@ class ripemd160 static ripemd160 hash( const char* d, uint32_t dlen ); static ripemd160 hash( const string& ); static string hex_digest( const string wallet_name ); + static string uint256_t_digest( const string wallet_name ); template static ripemd160 hash( const T& t ) diff --git a/libraries/fc/src/crypto/ripemd160.cpp b/libraries/fc/src/crypto/ripemd160.cpp index 076167e2..2925f4d2 100644 --- a/libraries/fc/src/crypto/ripemd160.cpp +++ b/libraries/fc/src/crypto/ripemd160.cpp @@ -70,6 +70,21 @@ string ripemd160::hex_digest(const string wallet_name) return ss.str(); } +boost::multiprecision::uint256_t uint256_t_digest( const string wallet_name ) +{ + std::string prefix( "XGT" ); + + const size_t prefix_len = prefix.size(); + auto b58 = wallet_name.substr( prefix_len ); + auto r160 = fc::ripemd160::hash(b58); + + std::stringstream ss; + ss << std::hex << r160.str(); + boost::multiprecision::uint256_t x; + ss >> x; + return x; +} + void ripemd160::encoder::write( const char* d, uint32_t dlen ) { RIPEMD160_Update( &my->ctx, d, dlen); } From 0d636a62663e5fbb37c370bdc2742205c2cf53ef Mon Sep 17 00:00:00 2001 From: Liam Noroian Date: Wed, 5 Jan 2022 21:20:08 -0800 Subject: [PATCH 83/96] Adding helper methods to retrieve wallets --- libraries/chain/database.cpp | 10 ++++++++++ libraries/chain/include/xgt/chain/database.hpp | 2 ++ 2 files changed, 12 insertions(+) diff --git a/libraries/chain/database.cpp b/libraries/chain/database.cpp index 43e073eb..9e706e41 100644 --- a/libraries/chain/database.cpp +++ b/libraries/chain/database.cpp @@ -609,6 +609,11 @@ const contract_object& database::get_contract( const contract_hash_type& hash )c return get< contract_object, by_contract_hash >( hash ); } FC_CAPTURE_AND_RETHROW( (hash) ) } +const contract_object& database::get_contract_by_wallet( const wallet_name_type& wallet )const +{ try { + return get< contract_object, by_wallet >( wallet ); +} FC_CAPTURE_AND_RETHROW( (wallet) ) } + const wallet_object& database::get_account( const wallet_name_type& name )const { try { return get< wallet_object, by_name >( name ); @@ -624,6 +629,11 @@ const wallet_object* database::find_account( const wallet_name_type& name )const return find< wallet_object, by_name >( name ); } +const wallet_object* database::find_account_by_ripemd160( const address_ripemd160_type& address_ripemd160 )const +{ + return find< wallet_object, by_address_ripemd160 >( address_ripemd160 ); +} + const comment_object& database::get_comment( const wallet_name_type& author, const shared_string& permlink )const { try { return get< comment_object, by_permlink >( boost::make_tuple( author, permlink ) ); diff --git a/libraries/chain/include/xgt/chain/database.hpp b/libraries/chain/include/xgt/chain/database.hpp index 8b612c1d..3925f982 100644 --- a/libraries/chain/include/xgt/chain/database.hpp +++ b/libraries/chain/include/xgt/chain/database.hpp @@ -207,10 +207,12 @@ namespace xgt { namespace chain { const witness_object* find_witness( const wallet_name_type& name )const; const contract_object& get_contract( const contract_hash_type& hash )const; + const contract_object& get_contract_by_wallet( const wallet_name_type& wallet )const; const wallet_object& get_account( const wallet_name_type& name )const; const wallet_object& get_account_by_ripemd160( const address_ripemd160_type& address_ripemd160 )const; const wallet_object* find_account( const wallet_name_type& name )const; + const wallet_object* find_account_by_ripemd160( const address_ripemd160_type& address_ripemd160 )const; const comment_object& get_comment( const wallet_name_type& author, const shared_string& permlink )const; const comment_object* find_comment( const wallet_name_type& author, const shared_string& permlink )const; From 6a8c9b6a1fa03b0762f10e58ce87d8762d3ce0d2 Mon Sep 17 00:00:00 2001 From: Liam Noroian Date: Wed, 5 Jan 2022 21:24:37 -0800 Subject: [PATCH 84/96] Updating contract object to query for associated wallet address --- libraries/chain/include/xgt/chain/contract_objects.hpp | 3 +++ libraries/plugins/apis/contract_api/contract_api.cpp | 1 + .../include/xgt/plugins/database_api/database_api_objects.hpp | 4 +++- libraries/protocol/include/xgt/protocol/xgt_operations.hpp | 3 ++- 4 files changed, 9 insertions(+), 2 deletions(-) diff --git a/libraries/chain/include/xgt/chain/contract_objects.hpp b/libraries/chain/include/xgt/chain/contract_objects.hpp index e77c7aa3..37141926 100644 --- a/libraries/chain/include/xgt/chain/contract_objects.hpp +++ b/libraries/chain/include/xgt/chain/contract_objects.hpp @@ -22,11 +22,13 @@ namespace xgt { namespace chain { contract_id_type id; wallet_name_type owner; // Creator of wallet contract_hash_type contract_hash; + wallet_name_type wallet; vector code; }; struct by_id; struct by_contract_hash; + struct by_wallet; struct by_owner_and_contract_hash; typedef multi_index_container< @@ -34,6 +36,7 @@ namespace xgt { namespace chain { indexed_by< ordered_unique< tag< by_id >, member< contract_object, contract_id_type, &contract_object::id > >, ordered_unique< tag< by_contract_hash >, member< contract_object, contract_hash_type, &contract_object::contract_hash > >, + ordered_unique< tag< by_wallet >, member< contract_object, wallet_name_type, &contract_object::wallet > >, ordered_unique< tag< by_owner_and_contract_hash >, composite_key< contract_object, member< contract_object, wallet_name_type, &contract_object::owner >, diff --git a/libraries/plugins/apis/contract_api/contract_api.cpp b/libraries/plugins/apis/contract_api/contract_api.cpp index 7c9553aa..0662c7b7 100644 --- a/libraries/plugins/apis/contract_api/contract_api.cpp +++ b/libraries/plugins/apis/contract_api/contract_api.cpp @@ -72,6 +72,7 @@ DEFINE_API_IMPL( contract_api_impl, list_owner_contracts ) ac.id = c.id; ac.owner = c.owner; ac.contract_hash = c.contract_hash; + ac.wallet = c.wallet; ac.code = c.code; result.contracts.push_back(ac); ++itr; diff --git a/libraries/plugins/apis/database_api/include/xgt/plugins/database_api/database_api_objects.hpp b/libraries/plugins/apis/database_api/include/xgt/plugins/database_api/database_api_objects.hpp index b7e5beb8..6e6fcef4 100644 --- a/libraries/plugins/apis/database_api/include/xgt/plugins/database_api/database_api_objects.hpp +++ b/libraries/plugins/apis/database_api/include/xgt/plugins/database_api/database_api_objects.hpp @@ -106,6 +106,7 @@ struct api_wallet_object api_wallet_object( const wallet_object& a, const database& db ) : id( a.id ), name( a.name ), + address_ripemd160( a.address_ripemd160 ), memo_key( a.memo_key ), last_account_update( a.last_account_update ), created( a.created ), @@ -150,6 +151,7 @@ struct api_wallet_object wallet_id_type id; wallet_name_type name; + address_ripemd160_type address_ripemd160; authority recovery; authority money; authority social; @@ -370,7 +372,7 @@ FC_REFLECT( xgt::plugins::database_api::api_comment_vote_object, ) FC_REFLECT( xgt::plugins::database_api::api_wallet_object, - (id)(name)(recovery)(money)(social)(memo_key)(json_metadata)(social_json_metadata)(last_recovery_update)(last_account_update) + (id)(name)(address_ripemd160)(recovery)(money)(social)(memo_key)(json_metadata)(social_json_metadata)(last_recovery_update)(last_account_update) (created)(mined) (recovery_account)(last_account_recovery)(reset_account) (comment_count)(lifetime_vote_count)(post_count)(can_vote)(energybar) diff --git a/libraries/protocol/include/xgt/protocol/xgt_operations.hpp b/libraries/protocol/include/xgt/protocol/xgt_operations.hpp index 703609c9..3f6af86d 100644 --- a/libraries/protocol/include/xgt/protocol/xgt_operations.hpp +++ b/libraries/protocol/include/xgt/protocol/xgt_operations.hpp @@ -592,6 +592,7 @@ namespace xgt { namespace protocol { struct contract_create_operation : public base_operation { wallet_name_type owner; + wallet_name_type wallet; vector code; void validate()const; @@ -664,5 +665,5 @@ FC_REFLECT( xgt::protocol::request_wallet_recovery_operation, (recovery_account) FC_REFLECT( xgt::protocol::recover_wallet_operation, (account_to_recover)(new_recovery_authority)(recent_recovery_authority)(extensions) ); FC_REFLECT( xgt::protocol::change_recovery_wallet_operation, (account_to_recover)(new_recovery_account)(extensions) ); -FC_REFLECT( xgt::protocol::contract_create_operation, (owner)(code) ); +FC_REFLECT( xgt::protocol::contract_create_operation, (owner)(wallet)(code) ); FC_REFLECT( xgt::protocol::contract_invoke_operation, (caller)(contract_hash)(value)(args) ); From 367c707ae840b4e14e5d8373bf47db1fd3087811 Mon Sep 17 00:00:00 2001 From: Liam Noroian Date: Wed, 5 Jan 2022 21:25:07 -0800 Subject: [PATCH 85/96] Begin implementation of vm call methods --- libraries/chain/xgt_evaluator.cpp | 402 ++++++++++++++---- libraries/vendor/xgtvm/libraries/machine.cpp | 265 +++++------- libraries/vendor/xgtvm/libraries/machine.hpp | 13 +- libraries/vendor/xgtvm/programs/xgtvm.cpp | 12 +- .../vendor/xgtvm/programs/xgtvm_tests.cpp | 12 +- 5 files changed, 445 insertions(+), 259 deletions(-) diff --git a/libraries/chain/xgt_evaluator.cpp b/libraries/chain/xgt_evaluator.cpp index 32cb94f9..0bcc5161 100644 --- a/libraries/chain/xgt_evaluator.cpp +++ b/libraries/chain/xgt_evaluator.cpp @@ -1051,7 +1051,7 @@ fc::ripemd160 make_contract_hash(const wallet_name_type& owner, const vector& storage); +machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type owner, wallet_name_type caller, wallet_name_type contract_wallet, contract_hash_type contract_hash, map& storage); std::map< uint64_t, std::function > energy_cost { // [] == scoped variables, () == params, -> optional return type, {} == function body @@ -1104,6 +1104,7 @@ std::map< uint64_t, std::function > energy_cost { {machine::number_opcode, [](machine::machine& m){ return 2; }}, {machine::difficulty_opcode, [](machine::machine& m){ return 2; }}, {machine::energylimit_opcode, [](machine::machine& m){ return 2; }}, + {machine::selfbalance_opcode, [](machine::machine& m){ return 0; }}, // TODO not yet implemented {machine::pop_opcode, [](machine::machine& m){ return 3; }}, {machine::mload_opcode, [](machine::machine& m){ return 3; }}, {machine::mstore_opcode, [](machine::machine& m){ return 3; }}, @@ -1211,20 +1212,57 @@ boost::multiprecision::uint256_t address_to_uint256_t(const std::string& base58s return x; }; +const wallet_object& wallet_create(chain::database& _db) +{ + fc::ecc::private_key recovery_privkey = generate_random_private_key(); + fc::ecc::public_key recovery_pubkey = recovery_privkey.get_public_key(); + fc::ecc::private_key money_privkey = generate_random_private_key(); + fc::ecc::public_key money_pubkey = money_privkey.get_public_key(); + fc::ecc::private_key social_privkey = generate_random_private_key(); + fc::ecc::public_key social_pubkey = social_privkey.get_public_key(); + fc::ecc::private_key memo_privkey = generate_random_private_key(); + fc::ecc::public_key memo_pubkey = memo_privkey.get_public_key(); + std::vector recovery_pubkeys = {recovery_pubkey}; + const auto& props = _db.get_dynamic_global_properties(); + + string wallet_name = wallet_create_operation::get_wallet_name(recovery_pubkeys); + + const wallet_object& wallet = _db.create< wallet_object >( [&]( wallet_object& w ) + { + initialize_wallet_object( w, wallet_name, memo_pubkey, props, false /*mined*/, XGT_INIT_MINER_NAME, _db.get_hardfork() ); + }); + + _db.create< account_authority_object >( [&]( account_authority_object& auth ) + { + auth.account = wallet_name; + auth.recovery.weight_threshold = 1; + auth.recovery.add_authority((public_key_type)recovery_pubkey, 1); + auth.money.weight_threshold = 1; + auth.money.add_authority((public_key_type)money_pubkey, 1); + auth.social.weight_threshold = 1; + auth.social.add_authority((public_key_type)social_pubkey, 1); + auth.last_recovery_update = fc::time_point_sec::min(); + }); + + return wallet; +} + std::vector contract_invoke(chain::database& _db, wallet_name_type o, wallet_name_type caller, contract_hash_type contract_hash, uint64_t value, uint64_t energy, std::vector args, map< fc::sha256, fc::sha256 >& storage) { wlog("contract_invoke another contract ${w}", ("w",contract_hash)); const auto& c = _db.get_contract(contract_hash); - const std::string& address_ref = std::string(caller); + const std::string& caller_address_ref = std::string(caller); + const std::string& destination_address_ref = std::string(c.wallet); - boost::multiprecision::uint256_t converted_address = address_to_uint256_t(address_ref); + boost::multiprecision::uint256_t converted_caller = address_to_uint256_t(caller_address_ref); + boost::multiprecision::uint256_t converted_destination = address_to_uint256_t(destination_address_ref); machine::message msg = { 0, 0, int64_t(energy), - converted_address, - converted_address, + converted_caller, + converted_destination, value, args.size(), args, @@ -1237,8 +1275,8 @@ std::vector contract_invoke(chain::database& _db, wallet_name_typ const uint64_t block_difficulty = static_cast( _db.get_pow_summary_target() ); const uint64_t block_energylimit = 0; const uint64_t tx_energyprice = 0; - std::string tx_origin = caller; - std::string block_coinbase = caller; // verify this + std::string tx_origin = caller; // TODO update this to + std::string block_coinbase = caller; // TODO update this to this block's miner machine::context ctx = { is_debug, @@ -1254,7 +1292,7 @@ std::vector contract_invoke(chain::database& _db, wallet_name_typ int64_t energy_cost_incurred = 0; std::vector code(c.code.begin(), c.code.end()); - machine::chain_adapter adapter = make_chain_adapter(_db, c.owner, tx_origin, contract_hash, storage); + machine::chain_adapter adapter = make_chain_adapter(_db, o, caller, c.wallet, contract_hash, storage); machine::machine m(ctx, code, msg, adapter); std::string line; @@ -1283,6 +1321,23 @@ std::vector contract_invoke(chain::database& _db, wallet_name_typ w.energybar.use_energy( energy_cost_incurred ); }); + // Transfer value (C_xfer) if callvalue != 0 + // TODO XXX Value is dramatically adjusted for test purposes... + // Ethereum wei values are significantly larger than XGT g values + // 1 Ether = 1,000,000,000,000,000,000 wei + // 1 XGT = 100,000,000 g + if (value != 0) { + auto callvalue = asset( value / 1000000000, XGT_SYMBOL ); + + const auto& contract_wallet = _db.get_account(c.wallet); + + _db.adjust_balance( contract_wallet, callvalue ); + + const auto& caller_wallet = _db.get_account(caller); + + _db.adjust_balance( caller_wallet, -callvalue ); + } + // TODO make return value public in machine wlog("contract_invoke return value ${w}", ("w",m.get_return_value())); return m.get_return_value(); @@ -1291,23 +1346,33 @@ std::vector contract_invoke(chain::database& _db, wallet_name_typ void contract_create_evaluator::do_apply( const contract_create_operation& op ) { wlog("!!!!!! contract_create owner ${w} code size ${y}", ("w",op.owner)("y",op.code.size())); + + const auto& contract_wallet = wallet_create(_db); + auto base_contract = _db.create< contract_object >( [&](contract_object& c) { c.contract_hash = make_contract_hash(op.owner, op.code); wlog("!!!!!! contract_create contract_hash ${c}", ("c",c.contract_hash)); + c.wallet = contract_wallet.name; c.owner = op.owner; c.code = op.code; }); - const contract_storage_object* cs = _db.find_contract_storage(base_contract.contract_hash, op.owner); - map< fc::sha256, fc::sha256 > storage; - if (cs) - storage = cs->data; - else - storage = map< fc::sha256, fc::sha256 >(); + auto storage = map< fc::sha256, fc::sha256 >(); + _db.create< contract_storage_object >([&](contract_storage_object& cs) { + cs.contract = base_contract.contract_hash; + cs.caller = op.owner; + cs.data = storage; + }); + auto machine_return = contract_invoke(_db, op.owner, op.owner, base_contract.contract_hash, 0, 0, {}, storage); std::vector result(machine_return.begin(), machine_return.end()); + const contract_storage_object* cs = _db.find_contract_storage(base_contract.contract_hash, op.owner); + _db.modify< contract_storage_object >(*cs, [&](contract_storage_object& cs) { + cs.data = storage; + }); + const auto& contract = _db.get_contract(base_contract.contract_hash); _db.modify< contract_object >(contract, [&](contract_object& c) { c.code = result; @@ -1328,10 +1393,8 @@ std::string inspect(std::vector words) return ss.str(); } -machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type o, wallet_name_type c, contract_hash_type contract_hash, map& storage) +machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type owner, wallet_name_type caller, wallet_name_type contract_wallet, contract_hash_type contract_hash, map& storage) { - std::string owner(o); - std::string caller(c); std::function< std::string(std::vector) > sha3 = [&](std::vector memory) -> std::string { @@ -1352,10 +1415,13 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type return ss.str(); }; - std::function< uint64_t(std::string) > get_balance = [&](std::string address_ripemd160) -> uint64_t + std::function< machine::big_word(machine::big_word) > get_balance = [&](machine::big_word address_ripemd160) -> machine::big_word { - auto& wallet = _db.get_account_by_ripemd160(address_ripemd160); - return static_cast(wallet.balance.amount.value); + std::stringstream ss; + ss << std::hex << address_ripemd160; + const address_ripemd160_type r160 = ss.str(); + auto& wallet = _db.get_account_by_ripemd160(r160); + return static_cast(wallet.balance.amount.value); }; std::function< std::string(std::string) > get_code_hash = [&](std::string address) -> std::string @@ -1384,49 +1450,155 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type return item; }; - std::function< std::vector(std::string) > get_code_at_addr = [&](std::string address) -> std::vector + std::function< std::vector(machine::big_word) > get_code_at_addr = [&](machine::big_word address) -> std::vector { - const chain::contract_object& contract = _db.get_contract(fc::ripemd160(address)); + std::stringstream ss; + ss << std::hex << address; + const address_ripemd160_type r160 = ss.str(); + const auto& contract_wallet_account = _db.get_account_by_ripemd160(r160); + const contract_object& contract = _db.get_contract_by_wallet(contract_wallet_account.name); + return std::vector(contract.code.begin(), contract.code.end()); }; - std::function< std::string(std::vector, machine::big_word) > contract_create = [&](std::vector memory, machine::big_word value) -> std::string + std::function< machine::big_word(std::vector, machine::big_word) > contract_create = [&, caller, contract_hash](std::vector memory, machine::big_word value) -> machine::big_word { - // TODO value argument is amount of energy to load contract with - fc::ripemd160 contract_hash = generate_random_ripemd160(); - chain::contract_object contract = _db.create< contract_object >( [&](contract_object& c) { - c.contract_hash = contract_hash; - c.owner = owner; - c.code = reinterpret_cast< std::vector& >(memory); - }); - return contract_hash.str(); - }; + const wallet_name_type sender_address = _db.get_contract(contract_hash).wallet; + const auto& caller_contract_wallet = _db.get_account(sender_address); + + // TODO XXX Create wallet for contract + + if (caller_contract_wallet.balance.amount.value >= value) { + fc::ripemd160 new_contract_hash = generate_random_ripemd160(); + const wallet_object& contract_wallet_account = wallet_create(_db); + chain::contract_object contract = _db.create< contract_object >( [&](contract_object& c) { + c.contract_hash = new_contract_hash; + c.owner = sender_address; + c.code = reinterpret_cast< std::vector& >(memory); + c.wallet = contract_wallet_account.name; + }); - std::function< std::vector(std::string, uint64_t, machine::big_word, std::vector) > contract_call = [&](std::string address, uint64_t energy, machine::big_word value, std::vector args) -> std::vector - { - const contract_storage_object* cs = _db.find_contract_storage(contract_hash, caller); - map< fc::sha256, fc::sha256 > storage; - if (cs) - storage = cs->data; - else - storage = map< fc::sha256, fc::sha256 >(); + if (value != 0) { + // TODO XXX value is set to be compatible with eth value, needs to be adjusted + auto callvalue = asset( value, XGT_SYMBOL ); + // TODO this should be the calling contract's wallet + _db.adjust_balance( caller_contract_wallet, -callvalue ); + _db.adjust_balance( contract.wallet, callvalue ); + } - auto result = contract_invoke(_db, o, c, contract_hash, energy, static_cast(value), args, storage); + // Convert new contract's wallet address to uint256_t (big_word) + const std::string& address_ref = std::string(contract.wallet); + boost::multiprecision::uint256_t new_contract_wallet_address = address_to_uint256_t(address_ref); - if (cs) - _db.modify< contract_storage_object >(*cs, [&](contract_storage_object& cs) { - cs.contract = contract_hash; - cs.caller = caller; - cs.data = storage; - }); - else - _db.create< contract_storage_object >([&](contract_storage_object& cs) { - cs.contract = contract_hash; - cs.caller = caller; - cs.data = storage; - }); + return new_contract_wallet_address; + } + else { + return 0; + } + }; - return result; + std::function< std::pair< machine::word, std::vector >(machine::big_word, uint64_t, machine::big_word, std::vector) > contract_call = [&](machine::big_word address, uint64_t energy, machine::big_word value, std::vector args) -> std::pair< machine::word, std::vector > + { + // TODO Implement call depth limit + // TODO Refactor get_account_by_ripemd160 flow + std::stringstream ss; + // ss << std::hex << address; + ss << std::hex << address; + const address_ripemd160_type r160 = ss.str(); + const wallet_object* wallet = _db.find_account_by_ripemd160(r160); + + // TODO C_NEW if (wallet does not exist) { create new account } else { retrieve existing wallet } + if (wallet != nullptr) { + std::cout << "wallet exists" << std::endl; + } else { + ss << std::hex << contract_create(args, value); + // const address_ripemd160_type new_r160 = ss.str(); + // const wallet_object* new_wallet = _db.find_account_by_ripemd160(new_r160); + } + + if (value != 0) { + // C_XFER + const auto& caller_contract_wallet = _db.get_account(owner); + + if (caller_contract_wallet.balance.amount.value >= value) { + // TODO XXX value is set to be compatible with eth value, needs to be adjusted + auto callvalue = asset( value, XGT_SYMBOL ); + // TODO this should be the calling contract's wallet + const auto& caller_contract_wallet = _db.get_account(owner); + _db.adjust_balance( caller_contract_wallet, -callvalue ); + _db.adjust_balance( *wallet, callvalue ); + } else { + std::vector contract_return; + return std::make_pair(0, contract_return); + } + } + + // TODO C_EXTRA get code at wallet address + + // TODO C_CALL if (code length == 0) { result = 0; } else { create a new + // contract object using the code from address, along with new contract storage object; + // result = contract_invoke(new_contract); + // } + fc::ripemd160 contract_hash = generate_random_ripemd160(); + chain::contract_object contract = _db.create< contract_object >( [&](contract_object& c) { + c.contract_hash = contract_hash; + c.owner = owner; + // TODO Get code at address + c.code = reinterpret_cast< std::vector& >(args); + }); + + machine::word result = 1; + + // 1. Calculate energy cost + // 2. Value transfer if wallet exists, otherwise create wallet + // 3. Execute contract at address if code is not null + // 4. Return output of contract execution + // + // + // C_CALL + // C_CALLGAS + // C_GASCAP + // C_EXTRA + // C_XFER + // C_NEW + + // // Get contract at addr + // const contract_object& contract = _db.get_contract_by_wallet(dest); + // // If addr matches a contract, continue contract execution + // if (contract) { + // const contract_hash_type& c_hash= contract.contract_hash; + + // // TODO is caller the contract calling this function or the wallet calling the original contract? + // const contract_storage_object* cs = _db.find_contract_storage(c_hash, caller); + + // map< fc::sha256, fc::sha256 > storage; + // if (cs) + // storage = cs->data; + // else + // storage = map< fc::sha256, fc::sha256 >(); + + // // c_call, c_callgas + // auto result = contract_invoke(_db, dest, c, c_hash, static_cast(value), energy, args, storage); + + // // c_extra + // if (cs) + // _db.modify< contract_storage_object >(*cs, [&](contract_storage_object& cs) { + // cs.contract = c_hash; + // cs.caller = caller; + // cs.data = storage; + // }); + // else + // _db.create< contract_storage_object >([&](contract_storage_object& cs) { + // cs.contract = c_hash; + // cs.caller = caller; + // cs.data = storage; + // }); + // } else { + // } + + // TODO update to staticcall return + std::vector contract_return; + return std::make_pair(result, contract_return); }; std::function< std::vector(std::string, uint64_t, machine::big_word, std::vector) > contract_callcode = [&](std::string address, uint64_t energy, machine::big_word value, std::vector args) -> std::vector @@ -1437,48 +1609,110 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type std::function< std::vector(std::string, uint64_t, std::vector) > contract_delegatecall = [&](std::string address, uint64_t energy, std::vector args) -> std::vector { - const contract_storage_object* cs = _db.find_contract_storage(contract_hash, c); // TODO: Verify `c` is correct + const contract_storage_object* cs = _db.find_contract_storage(contract_hash, caller); // TODO: Verify `c` is correct map< fc::sha256, fc::sha256 > storage; if (cs) storage = cs->data; else storage = map< fc::sha256, fc::sha256 >(); - auto result = contract_invoke(_db, o, c, contract_hash, energy, 0, args, storage); + auto result = contract_invoke(_db, owner, caller, contract_hash, 0, energy, args, storage); if (cs) _db.modify< contract_storage_object >(*cs, [&](contract_storage_object& cs) { cs.contract = contract_hash; - cs.caller = c; + cs.caller = caller; cs.data = storage; }); else _db.create< contract_storage_object >([&](contract_storage_object& cs) { cs.contract = contract_hash; - cs.caller = c; + cs.caller = caller; cs.data = storage; }); return result; }; - std::function< std::vector(std::string, uint64_t, std::vector) > contract_staticcall = [&](std::string address, uint64_t energy, std::vector args) -> std::vector + std::function< std::pair< machine::word, std::vector >(machine::big_word, uint64_t, std::vector) > contract_staticcall = [&, caller, contract_hash](machine::big_word address, uint64_t energy, std::vector args) -> std::pair< machine::word, std::vector > { - map< fc::sha256, fc::sha256 > storage; // Should this be empty, or just immutable for `staticcall`? - auto result = contract_invoke(_db, o, c, contract_hash, energy, 0, args, storage); - return result; + contract_hash_type new_contract_hash; + + std::stringstream ss; + ss << std::hex << address; + address_ripemd160_type r160 = ss.str(); + const wallet_object* wallet = _db.find_account_by_ripemd160(r160); + + if (wallet != nullptr) { + new_contract_hash = _db.get_contract_by_wallet(wallet->name).contract_hash; + } else { + ss << std::hex << contract_create(args, 0); + r160 = ss.str(); + new_contract_hash = _db.get_contract_by_wallet( r160 ).contract_hash; + } + + const contract_storage_object* cs = _db.find_contract_storage(new_contract_hash, owner); + + map< fc::sha256, fc::sha256 > storage; + if (cs != nullptr) { + storage = cs->data; + } + else { + storage = map< fc::sha256, fc::sha256 >(); + } + + _db.create< contract_storage_object >([&](contract_storage_object& cs) { + cs.contract = new_contract_hash; + cs.caller = owner; + cs.data = storage; + }); + + const wallet_name_type sender_address = _db.get_contract(contract_hash).wallet; + + // TODO Exceptions should occupy return_value in the case of contract invoke failure (result == 0) + std::vector base_contract_return = contract_invoke(_db, owner, sender_address, new_contract_hash, 0, 0, {}, storage); + std::vector result(base_contract_return.begin(), base_contract_return.end()); + + cs = _db.find_contract_storage(new_contract_hash, owner); + _db.modify< contract_storage_object >(*cs, [&](contract_storage_object& cs) { + cs.data = storage; + }); + + const auto& contract = _db.get_contract(new_contract_hash); + _db.modify< contract_object >(contract, [&](contract_object& co) { + co.code = result; + }); + + std::vector contract_return = contract_invoke(_db, owner, sender_address, new_contract_hash, 0, energy, args, storage); + + if (cs != nullptr) { + _db.modify< contract_storage_object >(*cs, [&](contract_storage_object& cs) { + cs.contract = new_contract_hash; + cs.caller = owner; + cs.data = storage; + }); + } + else { + _db.create< contract_storage_object >([&](contract_storage_object& cs) { + cs.contract = new_contract_hash; + cs.caller = owner; + cs.data = storage; + }); + } + + return std::make_pair(machine::word(1), contract_return); }; - std::function< std::string(std::vector, machine::big_word, std::string) > contract_create2 = [&_db, &owner](std::vector memory, machine::big_word value, std::string salt) -> std::string + std::function< machine::big_word(std::vector, machine::big_word, std::string) > contract_create2 = [&_db, owner](std::vector memory, machine::big_word value, std::string salt) -> machine::big_word { // TODO: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1014.md - chain::contract_object contract = _db.create< contract_object >( [&](contract_object& c) + chain::contract_object contract = _db.create< contract_object >( [&](contract_object& co) { - //c.contract_hash = generate_random_ripemd160(); - c.owner = owner; - //c.code = memory; + //co.contract_hash = generate_random_ripemd160(); + co.owner = owner; + //co.code = memory; }); - return ""; + return 0; }; std::function< bool(std::vector) > revert = [&](std::vector memory) -> bool @@ -1505,7 +1739,27 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type std::function< bool(std::string) > self_destruct = [&](std::string address) -> bool { - contract_object contract = _db.get_contract(fc::ripemd160(address)); + // TODO send all funds from contract to address + // + std::stringstream ss; + ss << std::hex << address; + const address_ripemd160_type r160 = ss.str(); + const auto& destination_wallet = _db.get_account_by_ripemd160(r160); + // const contract_object& contract = _db.get_contract(contract_hash); + + const auto& caller_contract_wallet = _db.get_account(owner); + + const auto value = caller_contract_wallet.balance.amount.value; + + if (value != 0) { + // TODO XXX value is set to be compatible with eth value, needs to be adjusted + auto callvalue = asset( value, XGT_SYMBOL ); + // TODO this should be the calling contract's wallet + _db.adjust_balance( caller_contract_wallet, -callvalue ); + _db.adjust_balance( destination_wallet, callvalue ); + } + + contract_object contract = _db.get_contract_by_wallet(owner); _db.remove(contract); return true; @@ -1522,7 +1776,7 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type _db.create< contract_log_object >( [&](contract_log_object& cl) { cl.contract_hash = contract_hash; - cl.owner = o; + cl.owner = owner; cl.topics.reserve(log.topics.size()); for (auto topic : log.topics) cl.topics.push_back(_db.bigint_to_hash(topic)); @@ -1562,7 +1816,7 @@ void contract_invoke_evaluator::do_apply( const contract_invoke_operation& op ) const auto& c = _db.get_contract(contract_hash); uint64_t energy = 0; // TODO - const contract_storage_object* cs = _db.find_contract_storage(contract_hash, op.caller); + const contract_storage_object* cs = _db.find_contract_storage(contract_hash, c.owner); map< fc::sha256, fc::sha256 > storage; if (cs != nullptr) { @@ -1574,19 +1828,19 @@ void contract_invoke_evaluator::do_apply( const contract_invoke_operation& op ) std::vector unsigned_args; std::copy(op.args.begin(), op.args.end(), std::back_inserter(unsigned_args)); - auto result = contract_invoke(_db, c.owner, op.caller, contract_hash, energy, op.value, unsigned_args, storage); + auto result = contract_invoke(_db, c.owner, op.caller, contract_hash, op.value, energy, unsigned_args, storage); if (cs != nullptr) { _db.modify< contract_storage_object >(*cs, [&](contract_storage_object& cs) { cs.contract = contract_hash; - cs.caller = op.caller; + cs.caller = c.owner; cs.data = storage; }); } else { _db.create< contract_storage_object >([&](contract_storage_object& cs) { cs.contract = contract_hash; - cs.caller = op.caller; + cs.caller = c.owner; cs.data = storage; }); } diff --git a/libraries/vendor/xgtvm/libraries/machine.cpp b/libraries/vendor/xgtvm/libraries/machine.cpp index 5bc61004..f2071911 100644 --- a/libraries/vendor/xgtvm/libraries/machine.cpp +++ b/libraries/vendor/xgtvm/libraries/machine.cpp @@ -106,32 +106,32 @@ namespace machine word z, word aa, word ab, word ac, word ad, word ae, word af) { big_word va = ((big_word)a << 8) | b; - big_word vb = (va << 8) | c; - big_word vc = (vb << 8) | d; - big_word vd = (vc << 8) | e; - big_word ve = (vd << 8) | f; - big_word vf = (ve << 8) | g; - big_word vg = (vf << 8) | h; - big_word vh = (vg << 8) | i; - big_word vi = (vh << 8) | j; - big_word vj = (vi << 8) | k; - big_word vk = (vj << 8) | l; - big_word vl = (vk << 8) | m; - big_word vm = (vl << 8) | n; - big_word vn = (vm << 8) | o; - big_word vo = (vn << 8) | p; - big_word vp = (vo << 8) | q; - big_word vq = (vp << 8) | r; - big_word vr = (vq << 8) | s; - big_word vs = (vr << 8) | t; - big_word vt = (vs << 8) | u; - big_word vu = (vt << 8) | v; - big_word vv = (vu << 8) | w; - big_word vw = (vv << 8) | x; - big_word vx = (vw << 8) | y; - big_word vy = (vx << 8) | z; - big_word vz = (vy << 8) | aa; - big_word vaa = (vz << 8) | ab; + big_word vb = (va << 8) | c; + big_word vc = (vb << 8) | d; + big_word vd = (vc << 8) | e; + big_word ve = (vd << 8) | f; + big_word vf = (ve << 8) | g; + big_word vg = (vf << 8) | h; + big_word vh = (vg << 8) | i; + big_word vi = (vh << 8) | j; + big_word vj = (vi << 8) | k; + big_word vk = (vj << 8) | l; + big_word vl = (vk << 8) | m; + big_word vm = (vl << 8) | n; + big_word vn = (vm << 8) | o; + big_word vo = (vn << 8) | p; + big_word vp = (vo << 8) | q; + big_word vq = (vp << 8) | r; + big_word vr = (vq << 8) | s; + big_word vs = (vr << 8) | t; + big_word vt = (vs << 8) | u; + big_word vu = (vt << 8) | v; + big_word vv = (vu << 8) | w; + big_word vw = (vv << 8) | x; + big_word vx = (vw << 8) | y; + big_word vy = (vx << 8) | z; + big_word vz = (vy << 8) | aa; + big_word vaa = (vz << 8) | ab; big_word vab = (vaa << 8) | ac; big_word vac = (vab << 8) | ad; big_word vad = (vac << 8) | ae; @@ -142,8 +142,9 @@ namespace machine std::vector from_big_word(big_word a) { std::vector vec; + vec.push_back(static_cast(a & 0xFF)); for (size_t i = 0; i < 31; i++) { - vec.push_back(static_cast(((a >>= (8 * i)) & 0xFF))); + vec.push_back(static_cast(((a >>= 8) & 0xFF))); } return vec; @@ -267,6 +268,7 @@ namespace machine std::vector contract_args; std::vector retval; std::vector ext_contract_code; + std::pair< word, std::vector > contract_call_return; std::vector::const_iterator first, last; std::string* ss; std::stringstream sstream; @@ -460,7 +462,7 @@ namespace machine va = pop_word(); // shift vb = pop_word(); // value - vc = vb << va.convert_to(); + vc = vb << static_cast(va); push_word(vc); break; @@ -488,7 +490,9 @@ namespace machine va = pop_word(); // offset vb = pop_word(); // length - for (size_t i = static_cast(va); i < static_cast(vb); i++) { + // TODO handle case where length of memory segment is 0, stack needs a 0 pushed + + for (size_t i = static_cast(va); i < static_cast(va) + static_cast(vb); i++) { std::map::iterator it; it = memory.find(i); if (it != memory.end()) { @@ -510,20 +514,8 @@ namespace machine break; case balance_opcode: logger << "op balance" << std::endl; - { - sv = stack.front(); // addr - stack.pop_front(); - ss = boost::get(&sv); - if (ss) - { - push_word( adapter.get_balance(*ss) ); - } - else - { - state = machine_state::error; - error_message.emplace("Balance operation type error"); - } - } + va = pop_word(); + push_word( adapter.get_balance(va) ); break; case origin_opcode: logger << "op origin" << std::endl; @@ -623,47 +615,27 @@ namespace machine break; case extcodesize_opcode: logger << "op extcodesize" << std::endl; - sv = stack.front(); // addr - ss = boost::get(&sv); - if (ss) - { - stack.pop_front(); - ext_contract_code = adapter.get_code_at_addr(*ss); - push_word( sizeof(ext_contract_code) / sizeof(ext_contract_code[0]) ); - } - else - { - state = machine_state::error; - error_message.emplace("Extcodesize operation type error"); - } + va = pop_word(); // Address + ext_contract_code = adapter.get_code_at_addr(va); + push_word( sizeof(ext_contract_code) / sizeof(ext_contract_code[0]) ); break; case extcodecopy_opcode: logger << "op extcodecopy" << std::endl; - sv = stack.front(); // addr - ss = boost::get(&sv); - if (ss) - { - stack.pop_front(); - ext_contract_code = adapter.get_code_at_addr(*ss); - code_size = sizeof(ext_contract_code) / sizeof(ext_contract_code[0]); - dest_offset = static_cast( pop_word() ); - offset = static_cast( pop_word() ); - length = static_cast( pop_word() ); - - if ((offset + length) > code_size) { - logger << "codecopy end index exceeds external contract code length" << std::endl; - break; - } + va = pop_word(); // address + ext_contract_code = adapter.get_code_at_addr(va); + code_size = sizeof(ext_contract_code) / sizeof(ext_contract_code[0]); + dest_offset = static_cast( pop_word() ); + offset = static_cast( pop_word() ); + length = static_cast( pop_word() ); - for (size_t i = 0; i < length; ++i) - memory[dest_offset + i] = ext_contract_code[offset + i]; - } - else - { - state = machine_state::error; - error_message.emplace("Extcodecopy operation type error"); + if ((offset + length) > code_size) { + logger << "codecopy end index exceeds external contract code length" << std::endl; + break; } + for (size_t i = 0; i < length; ++i) + memory[dest_offset + i] = ext_contract_code[offset + i]; + break; case returndatasize_opcode: logger << "op returndatasize" << std::endl; @@ -724,6 +696,10 @@ namespace machine logger << "op energylimit" << std::endl; push_word( ctx.block_energylimit ); break; + case selfbalance_opcode: + logger << "op selfbalance" << std::endl; + push_word( adapter.get_balance(msg.destination) ); + break; case pop_opcode: logger << "op pop" << std::endl; pop_word(); @@ -820,38 +796,16 @@ namespace machine break; case sload_opcode: logger << "op sload" << std::endl; - sv = stack.front(); - stack.pop_front(); - if (big_word* it = boost::get(&sv)) - { - va = adapter.get_storage(*it); - } - else { - throw; // TODO - } - push_word(va); + va = pop_word(); + vb = adapter.get_storage(va); + + push_word(vb); break; case sstore_opcode: logger << "op sstore" << std::endl; - sv = stack.front(); - stack.pop_front(); - if (big_word* it = boost::get(&sv)) - { - va = *it; - } - else { - throw; // TODO - } + va = pop_word(); + vb = pop_word(); - sv = stack.front(); - stack.pop_front(); - if (big_word* it = boost::get(&sv)) - { - vb = *it; - } - else { - throw; // TODO - } adapter.set_storage(va, vb); break; case jump_opcode: @@ -2753,7 +2707,7 @@ namespace machine vb = pop_word(); // offset vc = pop_word(); // length - for (size_t i = static_cast(vb); i < static_cast(vc); i++) { + for (size_t i = static_cast(vb); i < static_cast(vb) + static_cast(vc); i++) { std::map::iterator it; it = memory.find(i); if (it != memory.end()) { @@ -2770,41 +2724,27 @@ namespace machine logger << "op call" << std::endl; va = pop_word(); // energy - sv = stack.front(); // addr - ss = boost::get(&sv); - if (ss) - { - stack.pop_front(); - vb = pop_word(); // value - vc = pop_word(); // argsOffset - vd = pop_word(); // argsLength - ve = pop_word(); // retOffset - vf = pop_word(); // retLength + vb = pop_word(); // address + vc = pop_word(); // value + vd = pop_word(); // argsOffset + ve = pop_word(); // argsLength + vf = pop_word(); // retOffset + vg = pop_word(); // retLength - for (size_t i = static_cast(vc); i < static_cast(vd); i++) { - std::map::iterator it; - it = memory.find(i); - if (it != memory.end()) { - contract_args.push_back(it->second); - } - else { - contract_args.push_back(word(0)); - } + for (size_t i = static_cast(vd); i < static_cast(vd) + static_cast(ve); i++) { + std::map::iterator it; + it = memory.find(i); + if (it != memory.end()) { + contract_args.push_back(it->second); } + else { + contract_args.push_back(word(0)); + } + } - std::vector contract_call_return = adapter.contract_call(*ss, static_cast(va), vb, contract_args); - - for (size_t i = 0; i < static_cast(vf); i++) - memory[static_cast(ve) + i] = contract_call_return[i]; + contract_call_return = adapter.contract_call(vb, static_cast(va), vc, contract_args); - // TODO revise stack return value? - push_word("Success"); // success - } - else { - push_word("Failure"); // success - state = machine_state::error; - error_message.emplace("Call operation type error"); - } + push_word(big_word(contract_call_return.first)); break; case callcode_opcode: logger << "op callcode" << std::endl; @@ -2952,40 +2892,31 @@ namespace machine logger << "op staticcall" << std::endl; va = pop_word(); // energy - sv = stack.front(); // addr - ss = boost::get(&sv); - if (ss) - { - stack.pop_front(); - vb = pop_word(); // argsOffset - vc = pop_word(); // argsLength - vd = pop_word(); // retOffset - ve = pop_word(); // retLength + vb = pop_word(); // address + vc = pop_word(); // argsOffset + vd = pop_word(); // argsLength + ve = pop_word(); // retOffset + vf = pop_word(); // retLength - for (size_t i = static_cast(vb); i < static_cast(vc); i++) { - std::map::iterator it; - it = memory.find(i); - if (it != memory.end()) { - contract_args.push_back(it->second); - } - else { - contract_args.push_back(word(0)); - } + for (size_t i = static_cast(vc); i < static_cast(vc) + static_cast(vd); i++) { + std::map::iterator it; + it = memory.find(i); + if (it != memory.end()) { + contract_args.push_back(it->second); + } + else { + contract_args.push_back(word(0)); } + } - std::vector contract_staticcall_return = adapter.contract_staticcall(*ss, static_cast(va), contract_args); + contract_call_return = adapter.contract_staticcall(vb, static_cast(va), contract_args); - for (size_t i = 0; i < static_cast(ve); i++) - memory[static_cast(vd) + i] = contract_staticcall_return[i]; + ext_return_data = contract_call_return.second; - // TODO revise stack return value? - push_word("Success"); // success - } - else { - push_word("Failure"); // success - state = machine_state::error; - error_message.emplace("Staticcall operation type error"); - } + for (size_t i = 0; i < static_cast(vf); i++) + memory[static_cast(ve) + i] = contract_call_return.second[i]; + + push_word(big_word(contract_call_return.first)); break; case revert_opcode: logger << "op revert" << std::endl; diff --git a/libraries/vendor/xgtvm/libraries/machine.hpp b/libraries/vendor/xgtvm/libraries/machine.hpp index c32e3a14..3320b858 100644 --- a/libraries/vendor/xgtvm/libraries/machine.hpp +++ b/libraries/vendor/xgtvm/libraries/machine.hpp @@ -75,6 +75,7 @@ namespace machine number_opcode = 0x43, difficulty_opcode = 0x44, energylimit_opcode = 0x45, + selfbalance_opcode = 0x47, pop_opcode = 0x50, mload_opcode = 0x51, mstore_opcode = 0x52, @@ -223,7 +224,7 @@ namespace machine // TODO sha3 opcode std::function< std::string(std::vector) > sha3; - std::function< uint64_t(std::string) > get_balance; + std::function< big_word(big_word) > get_balance; // TODO for hashing address -- extcodehash opcode std::function< std::string(std::string) > get_code_hash; @@ -232,13 +233,13 @@ namespace machine std::function< machine::big_word(uint64_t) > get_block_hash; // TODO get contract bytecode at address - std::function< std::vector(std::string) > get_code_at_addr; + std::function< std::vector(big_word) > get_code_at_addr; // TODO creates a child contract -- create opcode - std::function< std::string(std::vector, big_word) > contract_create; + std::function< big_word(std::vector, big_word) > contract_create; // TODO call a method from another contract -- call opcode -- address, energy, value, args - std::function< std::vector(std::string, uint64_t, big_word, std::vector) > contract_call; + std::function< std::pair< word, std::vector >(big_word, uint64_t, big_word, std::vector) > contract_call; // TODO call a method from another contract(?) -- callcode opcode -- address, energy, value, args std::function< std::vector(std::string, uint64_t, big_word, std::vector) > contract_callcode; @@ -248,10 +249,10 @@ namespace machine std::function< std::vector(std::string, uint64_t, std::vector) > contract_delegatecall; // TODO call a method from another contract with state changes disallowed -- staticcall opcode -- address, energy, args - std::function< std::vector(std::string, uint64_t, std::vector) > contract_staticcall; + std::function< std::pair< word, std::vector >(big_word, uint64_t, std::vector) > contract_staticcall; // TODO creates a child contract -- create2 opcode - std::function< std::string(std::vector, big_word, std::string) > contract_create2; + std::function< big_word(std::vector, big_word, std::string) > contract_create2; // TODO revert opcode std::function< bool(std::vector) > revert; diff --git a/libraries/vendor/xgtvm/programs/xgtvm.cpp b/libraries/vendor/xgtvm/programs/xgtvm.cpp index b1129c9c..45d50340 100644 --- a/libraries/vendor/xgtvm/programs/xgtvm.cpp +++ b/libraries/vendor/xgtvm/programs/xgtvm.cpp @@ -60,7 +60,7 @@ machine::chain_adapter make_chain_adapter() return 0; }; - std::function< uint64_t(std::string) > get_balance = [](std::string address_ripemd160) -> uint64_t + std::function< machine::big_word(machine::big_word) > get_balance = [](machine::big_word address_ripemd160) -> machine::big_word { return 0; }; @@ -75,17 +75,17 @@ machine::chain_adapter make_chain_adapter() return {}; }; - std::function< std::vector(std::string) > get_code_at_addr = [](std::string address) -> std::vector + std::function< std::vector(machine::big_word) > get_code_at_addr = [](machine::big_word address) -> std::vector { return {}; }; - std::function< std::string(std::vector, machine::big_word) > contract_create = [](std::vector memory, machine::big_word value) -> std::string + std::function< machine::big_word(std::vector, machine::big_word) > contract_create = [](std::vector memory, machine::big_word value) -> machine::big_word { return {}; }; - std::function< std::vector(std::string, uint64_t, machine::big_word, std::vector) > contract_call = [](std::string address, uint64_t energy, machine::big_word value, std::vector args) -> std::vector + std::function< std::pair< machine::word, std::vector >(machine::big_word, uint64_t, machine::big_word, std::vector) > contract_call = [](machine::big_word address, uint64_t energy, machine::big_word value, std::vector args) -> std::pair< machine::word, std::vector > { return {}; }; @@ -100,12 +100,12 @@ machine::chain_adapter make_chain_adapter() return {}; }; - std::function< std::vector(std::string, uint64_t, std::vector) > contract_staticcall = [](std::string address, uint64_t energy, std::vector args) -> std::vector + std::function< std::pair< machine::word, std::vector >(machine::big_word, uint64_t, std::vector) > contract_staticcall = [](machine::big_word address, uint64_t energy, std::vector args) -> std::pair< machine::word, std::vector > { return {}; }; - std::function< std::string(std::vector, machine::big_word, std::string) > contract_create2 = [](std::vector memory, machine::big_word value, std::string salt) -> std::string + std::function< machine::big_word(std::vector, machine::big_word, std::string) > contract_create2 = [](std::vector memory, machine::big_word value, std::string salt) -> machine::big_word { return {}; }; diff --git a/libraries/vendor/xgtvm/programs/xgtvm_tests.cpp b/libraries/vendor/xgtvm/programs/xgtvm_tests.cpp index 4bb8a191..08044f4a 100644 --- a/libraries/vendor/xgtvm/programs/xgtvm_tests.cpp +++ b/libraries/vendor/xgtvm/programs/xgtvm_tests.cpp @@ -17,7 +17,7 @@ machine::chain_adapter make_chain_adapter() return 0; }; - std::function< uint64_t(std::string) > get_balance = [](std::string address_ripemd160) -> uint64_t + std::function< machine::big_word(machine::big_word) > get_balance = [](machine::big_word address_ripemd160) -> machine::big_word { std::cout << "chain_adapter::get_balance" << std::endl; return 0; @@ -35,19 +35,19 @@ machine::chain_adapter make_chain_adapter() return {}; }; - std::function< std::vector(std::string) > get_code_at_addr = [](std::string address) -> std::vector + std::function< std::vector(machine::big_word) > get_code_at_addr = [](machine::big_word address) -> std::vector { std::cout << "chain_adapter::get_code_at_addr" << std::endl; return {}; }; - std::function< std::string(std::vector, machine::big_word) > contract_create = [](std::vector memory, machine::big_word value) -> std::string + std::function< machine::big_word(std::vector, machine::big_word) > contract_create = [](std::vector memory, machine::big_word value) -> machine::big_word { std::cout << "chain_adapter::contract_create" << std::endl; return {}; }; - std::function< std::vector(std::string, uint64_t, machine::big_word, std::vector) > contract_call = [](std::string address, uint64_t energy, machine::big_word value, std::vector args) -> std::vector + std::function< std::pair< machine::word, std::vector >(machine::big_word, uint64_t, machine::big_word, std::vector) > contract_call = [](machine::big_word address, uint64_t energy, machine::big_word value, std::vector args) -> std::pair< machine::word, std::vector > { std::cout << "chain_adapter::contract_call" << std::endl; return {}; @@ -65,13 +65,13 @@ machine::chain_adapter make_chain_adapter() return {}; }; - std::function< std::vector(std::string, uint64_t, std::vector) > contract_staticcall = [](std::string address, uint64_t energy, std::vector args) -> std::vector + std::function< std::pair< machine::word, std::vector >(machine::big_word, uint64_t, std::vector) > contract_staticcall = [](machine::big_word address, uint64_t energy, std::vector args) -> std::pair< machine::word, std::vector > { std::cout << "chain_adapter::contract_staticcall" << std::endl; return {}; }; - std::function< std::string(std::vector, machine::big_word, std::string) > contract_create2 = [](std::vector memory, machine::big_word value, std::string salt) -> std::string + std::function< machine::big_word(std::vector, machine::big_word, std::string) > contract_create2 = [](std::vector memory, machine::big_word value, std::string salt) -> machine::big_word { std::cout << "chain_adapter::contract_create2" << std::endl; return {}; From 6776ee6dd812f30a1e211e461cd70e4d29eab835 Mon Sep 17 00:00:00 2001 From: Liam Noroian Date: Tue, 18 Jan 2022 04:17:18 -0800 Subject: [PATCH 86/96] Refactor rakefile, update call, staticcall, delegatecall --- libraries/chain/database.cpp | 10 + .../chain/include/xgt/chain/database.hpp | 2 + libraries/chain/xgt_evaluator.cpp | 372 +++++++++-------- .../apis/contract_api/contract_api.cpp | 14 + .../xgt/plugins/contract_api/contract_api.hpp | 4 +- libraries/vendor/xgtvm/libraries/machine.cpp | 57 ++- libraries/vendor/xgtvm/libraries/machine.hpp | 2 +- libraries/vendor/xgtvm/programs/xgtvm.cpp | 2 +- .../vendor/xgtvm/programs/xgtvm_tests.cpp | 2 +- tasks/contracts.rake | 379 ++++++++++++++++++ tasks/lazy_wallets.rake | 70 ++++ 11 files changed, 705 insertions(+), 209 deletions(-) create mode 100644 tasks/contracts.rake create mode 100644 tasks/lazy_wallets.rake diff --git a/libraries/chain/database.cpp b/libraries/chain/database.cpp index 9e706e41..de636e3c 100644 --- a/libraries/chain/database.cpp +++ b/libraries/chain/database.cpp @@ -614,6 +614,16 @@ const contract_object& database::get_contract_by_wallet( const wallet_name_type& return get< contract_object, by_wallet >( wallet ); } FC_CAPTURE_AND_RETHROW( (wallet) ) } +const contract_object* database::find_contract( const contract_hash_type& hash )const +{ + return find< contract_object, by_contract_hash >( hash ); +} + +const contract_object* database::find_contract_by_wallet( const wallet_name_type& wallet )const +{ + return find< contract_object, by_wallet >( wallet ); +} + const wallet_object& database::get_account( const wallet_name_type& name )const { try { return get< wallet_object, by_name >( name ); diff --git a/libraries/chain/include/xgt/chain/database.hpp b/libraries/chain/include/xgt/chain/database.hpp index 3925f982..c810dae8 100644 --- a/libraries/chain/include/xgt/chain/database.hpp +++ b/libraries/chain/include/xgt/chain/database.hpp @@ -208,6 +208,8 @@ namespace xgt { namespace chain { const contract_object& get_contract( const contract_hash_type& hash )const; const contract_object& get_contract_by_wallet( const wallet_name_type& wallet )const; + const contract_object* find_contract( const contract_hash_type& hash )const; + const contract_object* find_contract_by_wallet( const wallet_name_type& wallet )const; const wallet_object& get_account( const wallet_name_type& name )const; const wallet_object& get_account_by_ripemd160( const address_ripemd160_type& address_ripemd160 )const; diff --git a/libraries/chain/xgt_evaluator.cpp b/libraries/chain/xgt_evaluator.cpp index 0bcc5161..c875c4f6 100644 --- a/libraries/chain/xgt_evaluator.cpp +++ b/libraries/chain/xgt_evaluator.cpp @@ -1264,7 +1264,8 @@ std::vector contract_invoke(chain::database& _db, wallet_name_typ converted_caller, converted_destination, value, - args.size(), + // TODO args size is inaccurate + args.size() * 2, args, 0 }; @@ -1461,7 +1462,7 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type return std::vector(contract.code.begin(), contract.code.end()); }; - std::function< machine::big_word(std::vector, machine::big_word) > contract_create = [&, caller, contract_hash](std::vector memory, machine::big_word value) -> machine::big_word + std::function< machine::big_word(std::vector, machine::big_word) > contract_create = [&, owner, caller, contract_hash](std::vector memory, machine::big_word value) -> machine::big_word { const wallet_name_type sender_address = _db.get_contract(contract_hash).wallet; const auto& caller_contract_wallet = _db.get_account(sender_address); @@ -1471,7 +1472,7 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type if (caller_contract_wallet.balance.amount.value >= value) { fc::ripemd160 new_contract_hash = generate_random_ripemd160(); const wallet_object& contract_wallet_account = wallet_create(_db); - chain::contract_object contract = _db.create< contract_object >( [&](contract_object& c) { + chain::contract_object base_contract = _db.create< contract_object >( [&](contract_object& c) { c.contract_hash = new_contract_hash; c.owner = sender_address; c.code = reinterpret_cast< std::vector& >(memory); @@ -1483,11 +1484,41 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type auto callvalue = asset( value, XGT_SYMBOL ); // TODO this should be the calling contract's wallet _db.adjust_balance( caller_contract_wallet, -callvalue ); - _db.adjust_balance( contract.wallet, callvalue ); + _db.adjust_balance( base_contract.wallet, callvalue ); } + const contract_storage_object* cs = _db.find_contract_storage(new_contract_hash, sender_address); + + map< fc::sha256, fc::sha256 > storage; + if (cs != nullptr) { + storage = cs->data; + } + else { + storage = map< fc::sha256, fc::sha256 >(); + } + + _db.create< contract_storage_object >([&](contract_storage_object& cs) { + cs.contract = new_contract_hash; + cs.caller = sender_address; + cs.data = storage; + }); + + // TODO Exceptions should occupy return_value in the case of contract invoke failure (result == 0) + std::vector base_contract_return = contract_invoke(_db, owner, sender_address, new_contract_hash, 0, 0, {}, storage); + std::vector result(base_contract_return.begin(), base_contract_return.end()); + + cs = _db.find_contract_storage(new_contract_hash, sender_address); + _db.modify< contract_storage_object >(*cs, [&](contract_storage_object& cs) { + cs.data = storage; + }); + + const auto& deployed_contract = _db.get_contract(new_contract_hash); + _db.modify< contract_object >(deployed_contract, [&](contract_object& co) { + co.code = result; + }); + // Convert new contract's wallet address to uint256_t (big_word) - const std::string& address_ref = std::string(contract.wallet); + const std::string& address_ref = std::string(deployed_contract.wallet); boost::multiprecision::uint256_t new_contract_wallet_address = address_to_uint256_t(address_ref); return new_contract_wallet_address; @@ -1497,108 +1528,76 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type } }; - std::function< std::pair< machine::word, std::vector >(machine::big_word, uint64_t, machine::big_word, std::vector) > contract_call = [&](machine::big_word address, uint64_t energy, machine::big_word value, std::vector args) -> std::pair< machine::word, std::vector > + std::function< std::pair< machine::word, std::vector >(machine::big_word, uint64_t, machine::big_word, std::vector) > contract_call = [&, caller, contract_hash](machine::big_word address, uint64_t energy, machine::big_word value, std::vector args) -> std::pair< machine::word, std::vector > { // TODO Implement call depth limit - // TODO Refactor get_account_by_ripemd160 flow + // TODO Refactor get_account_by_ripemd160 flow -- uint256_t_to_ripemd160() std::stringstream ss; - // ss << std::hex << address; ss << std::hex << address; const address_ripemd160_type r160 = ss.str(); - const wallet_object* wallet = _db.find_account_by_ripemd160(r160); + const wallet_object* ext_wallet = _db.find_account_by_ripemd160(r160); + wallet_name_type ext_wallet_name; - // TODO C_NEW if (wallet does not exist) { create new account } else { retrieve existing wallet } - if (wallet != nullptr) { - std::cout << "wallet exists" << std::endl; + if (ext_wallet != nullptr) { + ext_wallet_name = ext_wallet->name; } else { + // TODO Check energy before creating contract ss << std::hex << contract_create(args, value); - // const address_ripemd160_type new_r160 = ss.str(); - // const wallet_object* new_wallet = _db.find_account_by_ripemd160(new_r160); + const address_ripemd160_type new_r160 = ss.str(); + const wallet_object* new_wallet = _db.find_account_by_ripemd160(new_r160); + ext_wallet_name = new_wallet->name; } + const wallet_name_type sender_address = _db.get_contract(contract_hash).wallet; + const auto& caller_contract_wallet = _db.get_account(sender_address); + if (value != 0) { - // C_XFER - const auto& caller_contract_wallet = _db.get_account(owner); - - if (caller_contract_wallet.balance.amount.value >= value) { - // TODO XXX value is set to be compatible with eth value, needs to be adjusted - auto callvalue = asset( value, XGT_SYMBOL ); - // TODO this should be the calling contract's wallet - const auto& caller_contract_wallet = _db.get_account(owner); - _db.adjust_balance( caller_contract_wallet, -callvalue ); - _db.adjust_balance( *wallet, callvalue ); - } else { - std::vector contract_return; - return std::make_pair(0, contract_return); - } + if (caller_contract_wallet.balance.amount.value >= value) { + // TODO XXX value is set to be compatible with eth value, needs to be adjusted + auto callvalue = asset( value, XGT_SYMBOL ); + _db.adjust_balance( caller_contract_wallet, -callvalue ); + _db.adjust_balance( ext_wallet_name, callvalue ); + } else { + return std::make_pair(0, std::vector()); + } } - - // TODO C_EXTRA get code at wallet address - - // TODO C_CALL if (code length == 0) { result = 0; } else { create a new - // contract object using the code from address, along with new contract storage object; - // result = contract_invoke(new_contract); - // } - fc::ripemd160 contract_hash = generate_random_ripemd160(); - chain::contract_object contract = _db.create< contract_object >( [&](contract_object& c) { - c.contract_hash = contract_hash; - c.owner = owner; - // TODO Get code at address - c.code = reinterpret_cast< std::vector& >(args); - }); - - machine::word result = 1; - - // 1. Calculate energy cost - // 2. Value transfer if wallet exists, otherwise create wallet - // 3. Execute contract at address if code is not null - // 4. Return output of contract execution - // - // - // C_CALL - // C_CALLGAS - // C_GASCAP - // C_EXTRA - // C_XFER - // C_NEW - - // // Get contract at addr - // const contract_object& contract = _db.get_contract_by_wallet(dest); - // // If addr matches a contract, continue contract execution - // if (contract) { - // const contract_hash_type& c_hash= contract.contract_hash; - - // // TODO is caller the contract calling this function or the wallet calling the original contract? - // const contract_storage_object* cs = _db.find_contract_storage(c_hash, caller); - - // map< fc::sha256, fc::sha256 > storage; - // if (cs) - // storage = cs->data; - // else - // storage = map< fc::sha256, fc::sha256 >(); - - // // c_call, c_callgas - // auto result = contract_invoke(_db, dest, c, c_hash, static_cast(value), energy, args, storage); - - // // c_extra - // if (cs) - // _db.modify< contract_storage_object >(*cs, [&](contract_storage_object& cs) { - // cs.contract = c_hash; - // cs.caller = caller; - // cs.data = storage; - // }); - // else - // _db.create< contract_storage_object >([&](contract_storage_object& cs) { - // cs.contract = c_hash; - // cs.caller = caller; - // cs.data = storage; - // }); - // } else { - // } - - // TODO update to staticcall return - std::vector contract_return; - return std::make_pair(result, contract_return); + const contract_object* contract = _db.find_contract_by_wallet(ext_wallet_name); + + std::vector contract_return = {}; + + if (args.size() > 0) { + if (contract) { + const contract_storage_object* cs = _db.find_contract_storage(contract->contract_hash, owner); + map< fc::sha256, fc::sha256 > storage; + if (cs) + storage = cs->data; + else + storage = map< fc::sha256, fc::sha256 >(); + + contract_return = contract_invoke(_db, contract->owner, sender_address, contract->contract_hash, (uint64_t)value, energy, args, storage); + + if (cs != nullptr) { + _db.modify< contract_storage_object >(*cs, [&](contract_storage_object& cs) { + cs.contract = contract->contract_hash; + cs.caller = caller; + cs.data = storage; + }); + } + else { + _db.create< contract_storage_object >([&](contract_storage_object& cs) { + cs.contract = contract->contract_hash; + cs.caller = caller; + cs.data = storage; + }); + } + } else { + ss << std::hex << contract_create(args, value); + const address_ripemd160_type new_contract_r160 = ss.str(); + const wallet_object* new_contract_wallet = _db.find_account_by_ripemd160(new_contract_r160); + ext_wallet_name = new_contract_wallet->name; + } + } + return std::make_pair(machine::word(1), contract_return); }; std::function< std::vector(std::string, uint64_t, machine::big_word, std::vector) > contract_callcode = [&](std::string address, uint64_t energy, machine::big_word value, std::vector args) -> std::vector @@ -1607,99 +1606,121 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type return std::vector(); }; - std::function< std::vector(std::string, uint64_t, std::vector) > contract_delegatecall = [&](std::string address, uint64_t energy, std::vector args) -> std::vector - { - const contract_storage_object* cs = _db.find_contract_storage(contract_hash, caller); // TODO: Verify `c` is correct - map< fc::sha256, fc::sha256 > storage; - if (cs) - storage = cs->data; - else - storage = map< fc::sha256, fc::sha256 >(); - - auto result = contract_invoke(_db, owner, caller, contract_hash, 0, energy, args, storage); - - if (cs) - _db.modify< contract_storage_object >(*cs, [&](contract_storage_object& cs) { - cs.contract = contract_hash; - cs.caller = caller; - cs.data = storage; - }); - else - _db.create< contract_storage_object >([&](contract_storage_object& cs) { - cs.contract = contract_hash; - cs.caller = caller; - cs.data = storage; - }); - - return result; - }; - - std::function< std::pair< machine::word, std::vector >(machine::big_word, uint64_t, std::vector) > contract_staticcall = [&, caller, contract_hash](machine::big_word address, uint64_t energy, std::vector args) -> std::pair< machine::word, std::vector > + std::function< std::pair< machine::word, std::vector >(machine::big_word, uint64_t, std::vector) > contract_delegatecall = [&, owner](machine::big_word address, uint64_t energy, std::vector args) -> std::pair< machine::word, std::vector > { - contract_hash_type new_contract_hash; - + // TODO Implement call depth limit + // TODO Refactor get_account_by_ripemd160 flow -- uint256_t_to_ripemd160() std::stringstream ss; ss << std::hex << address; - address_ripemd160_type r160 = ss.str(); - const wallet_object* wallet = _db.find_account_by_ripemd160(r160); + const address_ripemd160_type r160 = ss.str(); + const wallet_object* ext_wallet = _db.find_account_by_ripemd160(r160); + wallet_name_type ext_wallet_name; - if (wallet != nullptr) { - new_contract_hash = _db.get_contract_by_wallet(wallet->name).contract_hash; + if (ext_wallet != nullptr) { + ext_wallet_name = ext_wallet->name; } else { + // TODO Check energy before creating contract ss << std::hex << contract_create(args, 0); - r160 = ss.str(); - new_contract_hash = _db.get_contract_by_wallet( r160 ).contract_hash; + const address_ripemd160_type new_r160 = ss.str(); + const wallet_object* new_wallet = _db.find_account_by_ripemd160(new_r160); + ext_wallet_name = new_wallet->name; } - const contract_storage_object* cs = _db.find_contract_storage(new_contract_hash, owner); - - map< fc::sha256, fc::sha256 > storage; - if (cs != nullptr) { - storage = cs->data; - } - else { - storage = map< fc::sha256, fc::sha256 >(); + const contract_object* contract = _db.find_contract_by_wallet(ext_wallet_name); + + std::vector contract_return = {}; + + if (args.size() > 0) { + if (contract) { + const contract_storage_object* cs = _db.find_contract_storage(contract->contract_hash, owner); + map< fc::sha256, fc::sha256 > storage; + if (cs) + storage = cs->data; + else + storage = map< fc::sha256, fc::sha256 >(); + + std::vector unsigned_args; + std::copy(args.begin(), args.end(), std::back_inserter(unsigned_args)); + contract_return = contract_invoke(_db, contract->owner, owner, contract->contract_hash, 0, energy, unsigned_args, storage); + + if (cs != nullptr) { + _db.modify< contract_storage_object >(*cs, [&](contract_storage_object& cs) { + cs.contract = contract->contract_hash; + cs.caller = caller; + cs.data = storage; + }); + } + else { + _db.create< contract_storage_object >([&](contract_storage_object& cs) { + cs.contract = contract->contract_hash; + cs.caller = caller; + cs.data = storage; + }); + } + } else { + ss << std::hex << contract_create(args, 0); + const address_ripemd160_type new_contract_r160 = ss.str(); + const wallet_object* new_contract_wallet = _db.find_account_by_ripemd160(new_contract_r160); + ext_wallet_name = new_contract_wallet->name; + } } + return std::make_pair(machine::word(1), contract_return); + }; - _db.create< contract_storage_object >([&](contract_storage_object& cs) { - cs.contract = new_contract_hash; - cs.caller = owner; - cs.data = storage; - }); - - const wallet_name_type sender_address = _db.get_contract(contract_hash).wallet; - - // TODO Exceptions should occupy return_value in the case of contract invoke failure (result == 0) - std::vector base_contract_return = contract_invoke(_db, owner, sender_address, new_contract_hash, 0, 0, {}, storage); - std::vector result(base_contract_return.begin(), base_contract_return.end()); - - cs = _db.find_contract_storage(new_contract_hash, owner); - _db.modify< contract_storage_object >(*cs, [&](contract_storage_object& cs) { - cs.data = storage; - }); - - const auto& contract = _db.get_contract(new_contract_hash); - _db.modify< contract_object >(contract, [&](contract_object& co) { - co.code = result; - }); - - std::vector contract_return = contract_invoke(_db, owner, sender_address, new_contract_hash, 0, energy, args, storage); + std::function< std::pair< machine::word, std::vector >(machine::big_word, uint64_t, std::vector) > contract_staticcall = [&, owner, caller, contract_hash](machine::big_word address, uint64_t energy, std::vector args) -> std::pair< machine::word, std::vector > + { + std::stringstream ss; + ss << std::hex << address; + const address_ripemd160_type r160 = ss.str(); + const wallet_object* ext_wallet = _db.find_account_by_ripemd160(r160); + wallet_name_type ext_wallet_name; - if (cs != nullptr) { - _db.modify< contract_storage_object >(*cs, [&](contract_storage_object& cs) { - cs.contract = new_contract_hash; - cs.caller = owner; - cs.data = storage; - }); - } - else { - _db.create< contract_storage_object >([&](contract_storage_object& cs) { - cs.contract = new_contract_hash; - cs.caller = owner; - cs.data = storage; - }); + if (ext_wallet != nullptr) { + ext_wallet_name = ext_wallet->name; + } else { + ss << std::hex << contract_create(args, 0); + const address_ripemd160_type new_r160 = ss.str(); + const wallet_object* new_wallet = _db.find_account_by_ripemd160(new_r160); + ext_wallet_name = new_wallet->name; } + const wallet_name_type sender_address = _db.get_contract(contract_hash).wallet; + const contract_object* contract = _db.find_contract_by_wallet(ext_wallet_name); + + std::vector contract_return = {}; + + if (args.size() > 0) { + if (!contract) { + ss << std::hex << contract_create(args, 0); + const address_ripemd160_type new_contract_r160 = ss.str(); + const wallet_object* new_contract_wallet = _db.find_account_by_ripemd160(new_contract_r160); + ext_wallet_name = new_contract_wallet->name; + contract = _db.find_contract_by_wallet(ext_wallet_name); + } + const contract_storage_object* cs = _db.find_contract_storage(contract->contract_hash, owner); + map< fc::sha256, fc::sha256 > storage; + if (cs) + storage = cs->data; + else + storage = map< fc::sha256, fc::sha256 >(); + + contract_return = contract_invoke(_db, contract->owner, sender_address, contract->contract_hash, 0, energy, args, storage); + + if (cs != nullptr) { + _db.modify< contract_storage_object >(*cs, [&](contract_storage_object& cs) { + cs.contract = contract->contract_hash; + cs.caller = caller; + cs.data = storage; + }); + } + else { + _db.create< contract_storage_object >([&](contract_storage_object& cs) { + cs.contract = contract->contract_hash; + cs.caller = caller; + cs.data = storage; + }); + } + } return std::make_pair(machine::word(1), contract_return); }; @@ -1745,7 +1766,6 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type ss << std::hex << address; const address_ripemd160_type r160 = ss.str(); const auto& destination_wallet = _db.get_account_by_ripemd160(r160); - // const contract_object& contract = _db.get_contract(contract_hash); const auto& caller_contract_wallet = _db.get_account(owner); diff --git a/libraries/plugins/apis/contract_api/contract_api.cpp b/libraries/plugins/apis/contract_api/contract_api.cpp index 0662c7b7..9b17eb3b 100644 --- a/libraries/plugins/apis/contract_api/contract_api.cpp +++ b/libraries/plugins/apis/contract_api/contract_api.cpp @@ -68,12 +68,26 @@ DEFINE_API_IMPL( contract_api_impl, list_owner_contracts ) if (c.owner != args.owner) break; wlog("!!!!!! LIST_OWNER_CONTRACTS ${w}", ("w",c.owner)); + const std::string& wallet_name_ref = std::string(c.wallet); + + std::string prefix( XGT_ADDRESS_PREFIX ); + + const size_t prefix_len = prefix.size(); + auto b58 = wallet_name_ref.substr( prefix_len ); + auto r160 = fc::ripemd160::hash(b58); + + std::stringstream ss; + ss << std::hex << r160.str(); + std::string en_address; + ss >> en_address; + api_contract_object ac; ac.id = c.id; ac.owner = c.owner; ac.contract_hash = c.contract_hash; ac.wallet = c.wallet; ac.code = c.code; + ac.en_address = en_address; result.contracts.push_back(ac); ++itr; } diff --git a/libraries/plugins/apis/contract_api/include/xgt/plugins/contract_api/contract_api.hpp b/libraries/plugins/apis/contract_api/include/xgt/plugins/contract_api/contract_api.hpp index 2277c6e9..596bc631 100644 --- a/libraries/plugins/apis/contract_api/include/xgt/plugins/contract_api/contract_api.hpp +++ b/libraries/plugins/apis/contract_api/include/xgt/plugins/contract_api/contract_api.hpp @@ -19,6 +19,7 @@ struct api_contract_object chain::wallet_name_type owner; chain::wallet_name_type wallet; chain::contract_hash_type contract_hash; + std::string en_address; vector code; }; @@ -67,7 +68,8 @@ FC_REFLECT( xgt::plugins::contract::api_contract_object, (owner) (wallet) (contract_hash) - (code) ) + (code) + (en_address) ) FC_REFLECT( xgt::plugins::contract::get_contract_args, (contract_hash) ) FC_REFLECT( xgt::plugins::contract::get_contract_return, (contract) ) diff --git a/libraries/vendor/xgtvm/libraries/machine.cpp b/libraries/vendor/xgtvm/libraries/machine.cpp index f2071911..070106db 100644 --- a/libraries/vendor/xgtvm/libraries/machine.cpp +++ b/libraries/vendor/xgtvm/libraries/machine.cpp @@ -2744,6 +2744,13 @@ namespace machine contract_call_return = adapter.contract_call(vb, static_cast(va), vc, contract_args); + if (contract_call_return.second.size() > 0) { + ext_return_data = contract_call_return.second; + + for (size_t i = 0; i < static_cast(vf); i++) + memory[static_cast(ve) + i] = contract_call_return.second[i]; + } + push_word(big_word(contract_call_return.first)); break; case callcode_opcode: @@ -2822,41 +2829,33 @@ namespace machine case delegatecall_opcode: logger << "op delegatecall" << std::endl; va = pop_word(); // energy + vb = pop_word(); // addr + vc = pop_word(); // argsOffset + vd = pop_word(); // argsLength + ve = pop_word(); // retOffset + vf = pop_word(); // retLength - sv = stack.front(); // addr - ss = boost::get(&sv); - if (ss) - { - stack.pop_front(); - vb = pop_word(); // argsOffset - vc = pop_word(); // argsLength - vd = pop_word(); // retOffset - ve = pop_word(); // retLength - - for (size_t i = static_cast(va); i < static_cast(vb); i++) { - std::map::iterator it; - it = memory.find(i); - if (it != memory.end()) { - contract_args.push_back(it->second); - } - else { - contract_args.push_back(word(0)); - } + for (size_t i = static_cast(vc); i < static_cast(vc) + static_cast(vd); i++) { + std::map::iterator it; + it = memory.find(i); + if (it != memory.end()) { + contract_args.push_back(it->second); + } + else { + contract_args.push_back(word(0)); } + } - std::vector contract_delegatecall_return = adapter.contract_delegatecall(*ss, static_cast(va), contract_args); + contract_call_return = adapter.contract_delegatecall(vb, static_cast(va), contract_args); - for (size_t i = 0; i < static_cast(ve); i++) - memory[static_cast(vd) + i] = contract_delegatecall_return[i]; + if (contract_call_return.second.size() > 0) { + ext_return_data = contract_call_return.second; - // TODO revise stack return value? - push_word("Success"); // success - } - else { - push_word("Failure"); // success - state = machine_state::error; - error_message.emplace("Delegatecall operation type error"); + for (size_t i = 0; i < static_cast(vf); i++) + memory[static_cast(ve) + i] = contract_call_return.second[i]; } + + push_word(contract_call_return.first); break; case create2_opcode: logger << "op create2" << std::endl; diff --git a/libraries/vendor/xgtvm/libraries/machine.hpp b/libraries/vendor/xgtvm/libraries/machine.hpp index 3320b858..e57deb8e 100644 --- a/libraries/vendor/xgtvm/libraries/machine.hpp +++ b/libraries/vendor/xgtvm/libraries/machine.hpp @@ -246,7 +246,7 @@ namespace machine // TODO call a method from another contract using the storage of the current // opcode -- delegatecall opcode -- address, energy, args - std::function< std::vector(std::string, uint64_t, std::vector) > contract_delegatecall; + std::function< std::pair< word, std::vector >(big_word, uint64_t, std::vector) > contract_delegatecall; // TODO call a method from another contract with state changes disallowed -- staticcall opcode -- address, energy, args std::function< std::pair< word, std::vector >(big_word, uint64_t, std::vector) > contract_staticcall; diff --git a/libraries/vendor/xgtvm/programs/xgtvm.cpp b/libraries/vendor/xgtvm/programs/xgtvm.cpp index 45d50340..4df85086 100644 --- a/libraries/vendor/xgtvm/programs/xgtvm.cpp +++ b/libraries/vendor/xgtvm/programs/xgtvm.cpp @@ -95,7 +95,7 @@ machine::chain_adapter make_chain_adapter() return {}; }; - std::function< std::vector(std::string, uint64_t, std::vector) > contract_delegatecall = [](std::string address, uint64_t energy, std::vector args) -> std::vector + std::function< std::pair< machine::word, std::vector >(machine::big_word, uint64_t, std::vector) > contract_delegatecall = [](machine::big_word address, uint64_t energy, std::vector args) -> std::pair< machine::word, std::vector > { return {}; }; diff --git a/libraries/vendor/xgtvm/programs/xgtvm_tests.cpp b/libraries/vendor/xgtvm/programs/xgtvm_tests.cpp index 08044f4a..f39e70d0 100644 --- a/libraries/vendor/xgtvm/programs/xgtvm_tests.cpp +++ b/libraries/vendor/xgtvm/programs/xgtvm_tests.cpp @@ -59,7 +59,7 @@ machine::chain_adapter make_chain_adapter() return {}; }; - std::function< std::vector(std::string, uint64_t, std::vector) > contract_delegatecall = [](std::string address, uint64_t energy, std::vector args) -> std::vector + std::function< std::pair< machine::word, std::vector >(machine::big_word, uint64_t, std::vector) > contract_delegatecall = [](machine::big_word address, uint64_t energy, std::vector args) -> std::pair< machine::word, std::vector > { std::cout << "chain_adapter::contract_delegatecall" << std::endl; return {}; diff --git a/tasks/contracts.rake b/tasks/contracts.rake new file mode 100644 index 00000000..fe613617 --- /dev/null +++ b/tasks/contracts.rake @@ -0,0 +1,379 @@ +require 'digest' + +def create_contract!(owner, keys, code, private_key = wif) + txn = { + 'extensions' => [], + 'operations' => [ + { + 'type' => 'contract_create_operation', + 'value' => { + 'owner' => owner, + 'wallet' => keys['wallet_name'], + 'code' => code + } + } + ] + } + signed = Xgt::Ruby::Auth.sign_transaction(rpc, txn, [private_key], chain_id) + $stderr.puts(%(Registering contract... #{signed.to_json})) + response = nil + begin + response = rpc.call('transaction_api.broadcast_transaction', [signed]) + rescue => e + $stderr.puts e + end + $stderr.puts(%(Received response contract... #{response})) +end + +def invoke_contract!(contract_hash, invoker, value, args) + txn = { + 'extensions' => [], + 'operations' => [ + { + 'type' => 'contract_invoke_operation', + 'value' => { + 'contract_hash' => contract_hash, + 'caller' => invoker, + 'value' => value, + 'args' => args + } + } + ] + } + $stderr.puts(%(Signing contract contract... #{txn.to_json})) + signed = Xgt::Ruby::Auth.sign_transaction(rpc, txn, [wif], chain_id) + $stderr.puts(%(Registering contract... #{signed.to_json})) + response = rpc.call('transaction_api.broadcast_transaction', [signed]) + $stderr.puts(%(Received response contract... #{response})) + response +end + +namespace :contracts do + desc 'Create a sample contract' + task :create do + keys = generate_keys + create_wallet!(keys) + # Bytecode explanation: + # + # 60 03 60 04 01 00 + # PUSH 3 PUSH 4 ADD HALT + # + create_contract!(wallet, keys, '600360040100') + + response = rpc.call('contract_api.list_owner_contracts', { 'owner' => wallet }) || {} + p response + contract_hash = response['contracts'].first['contract_hash'] + response = rpc.call('contract_api.get_contract', { 'contract_hash' => contract_hash }) || {} + p response + + invoke_contract!(contract_hash, keys['wallet_name'], 0, '') + end + + desc 'Create a sample contract which calls another' + task :create_and_call do + create_contract = lambda { |code| + keys = generate_keys + create_wallet!(keys) + create_contract!(wallet, keys, code) + + response = rpc.call('contract_api.list_owner_contracts', { 'owner' => wallet }) || {} + p response + contract_hash = response['contracts'].first['contract_hash'] + response = rpc.call('contract_api.get_contract', { 'contract_hash' => contract_hash }) || {} + p response + + [contract_hash, keys] + } + + # Arguments to `call` opcode are: + # + # energy contract_hash value argsOffset argsLength retOffset retLength + # + # Bytecode explanation: + # + # PUSH 0 PUSH 0 RETURN HALT + # 60 00 60 00 F3 00 + # + contract_hash1, keys1 = create_contract.(%(60006000F300)) + # + # Bytecode explanation: + # + # PUSH 0 PUSH #{contract_hash1} 0 0 0 0 0 CALL HALT + # 60 00 60 #{contract_hash1} 60 00 60 00 60 00 60 00 60 00 F1 00 + # + contract_hash2, keys2 = create_contract.(%(600060#{contract_hash1}60006000600060006000F100)) + + invoke_contract!(contract_hash2, keys2['wallet_name'], 0, '') + end + + desc 'Calling a method in another contract' + task :call_method do + %w( + PUSH1 0x4 CALLDATASIZE LT # Is message data size < 4 bytes + PUSH2 0x41 JUMPI PUSH1 0x0 CALLDATALOAD PUSH29 0x100000000000000000000000000000000000000000000000000000000 SWAP1 DIV PUSH4 0xFFFFFFFF AND DUP1 PUSH4 0x8976762D EQ PUSH2 0x46 JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST CALLVALUE ISZERO PUSH2 0x51 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x67 PUSH1 0x4 DUP1 DUP1 CALLDATALOAD + ) + end + + desc 'The "Do Nothing" contract' + task :do_nothing do + create_contract = lambda { |code| + keys = generate_keys + create_wallet!(keys) + create_contract!(wallet, keys, code) + + response = rpc.call('contract_api.list_owner_contracts', { 'owner' => wallet }) || {} + p response + contract_hash = response['contracts'].first['contract_hash'] + response = rpc.call('contract_api.get_contract', { 'contract_hash' => contract_hash }) || {} + p response + + [contract_hash, keys] + } + + contract_hash, keys = create_contract.(%(6080604052348015600f57600080fd5b50606d80601d6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c80632f576f2014602d575b600080fd5b60336035565b005b56fea2646970667358221220975bdb6949442538b90c14c420b0a2f547f0437e85a73da12faf4e6834f0817264736f6c63430008070033)) + + invoke_contract!(contract_hash, keys['wallet_name'], 0, '') + end + + desc 'Basic contract create contract' + task :basic_create do + + code = '6080604052604051806101a0016040528061017d815260200161021861017d913960009080519060200190610035929190610048565b5034801561004257600080fd5b506100f3565b828054600181600116156101000203166002900490600052602060002090601f01602090048101928261007e57600085556100c5565b82601f1061009757805160ff19168380011785556100c5565b828001600101855582156100c5579182015b828111156100c45782518255916020019190600101906100a9565b5b5090506100d291906100d6565b5090565b5b808211156100ef5760008160009055506001016100d7565b5090565b610116806101026000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c8063775c300c14602d575b600080fd5b60336035565b005b6000808054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801560c85780601f10609e5761010080835404028352916020019160c8565b820191906000526020600020905b81548152906001019060200180831160ac57829003601f168201915b5050505050905060008151602083016000f09050505056fea26469706673582212207ebdd3e8a24dd18c61ea1cc0033ad3ac21de43f853f03cfeea42954a7d60c12864736f6c63430007060033608060405234801561001057600080fd5b5061015d806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c806306fdde031461003b5780637872ab4914610059575b600080fd5b61004361009d565b6040518082815260200191505060405180910390f35b61009b6004803603602081101561006f57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506100c5565b005b60007f736d617278000000000000000000000000000000000000000000000000000000905090565b8073ffffffffffffffffffffffffffffffffffffffff1663380c7a676040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561010d57600080fd5b505af1158015610121573d6000803e3d6000fd5b505050505056fea265627a7a72315820fb2fc7a07f0eebf799c680bb1526641d2d905c19393adf340a04e48c9b527de964736f6c634300050c0032' + end + + desc 'Basic lottery contract' + task :basic_lottery do + def transfer_xgt(from, to, amount) + txn = { + 'extensions' => [], + 'operations' => [ + { + 'type' => 'transfer_operation', + 'value' => { + 'amount' => { + 'amount' => amount.to_s, + 'precision' => 8, + 'nai' => '@@000000021' + }, + 'from' => from, + 'to' => to, + 'json_metadata' => '', + 'extensions' => [] + } + } + ] + } + + id = rpc.broadcast_transaction(txn, [wif], chain_id) + (puts 'Waiting...' or sleep 1) until rpc.transaction_ready?(id) + end + + def get_wallet(address) + response = rpc.call('database_api.find_wallets', { 'wallets' => [address] }) + response['wallets'].first + end + + code = %(608060405234801561001057600080fd5b50336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506108b5806100606000396000f3fe60806040526004361061004a5760003560e01c8063481c6a751461004f5780635d495aea1461007a5780638b5b9ccc14610091578063e97dcb62146100bc578063f71d96cb146100c6575b600080fd5b34801561005b57600080fd5b50610064610103565b6040516100719190610657565b60405180910390f35b34801561008657600080fd5b5061008f610127565b005b34801561009d57600080fd5b506100a6610283565b6040516100b39190610672565b60405180910390f35b6100c4610311565b005b3480156100d257600080fd5b506100ed60048036038101906100e891906104ba565b610389565b6040516100fa9190610657565b60405180910390f35b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461017f57600080fd5b600060018054905061018f6103c8565b6101999190610785565b9050600181815481106101af576101ae6107e5565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc479081150290604051600060405180830381858888f1935050505015801561021f573d6000803e3d6000fd5b50600067ffffffffffffffff81111561023b5761023a610814565b5b6040519080825280602002602001820160405280156102695781602001602082028036833780820191505090505b506001908051906020019061027f9291906103fe565b5050565b6060600180548060200260200160405190810160405280929190818152602001828054801561030757602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190600101908083116102bd575b5050505050905090565b662386f26fc10000341161032457600080fd5b6001339080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b6001818154811061039957600080fd5b906000526020600020016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000444260016040516020016103e09392919061061e565b6040516020818303038152906040528051906020012060001c905090565b828054828255906000526020600020908101928215610477579160200282015b828111156104765782518260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055509160200191906001019061041e565b5b5090506104849190610488565b5090565b5b808211156104a1576000816000905550600101610489565b5090565b6000813590506104b481610868565b92915050565b6000602082840312156104d0576104cf610856565b5b60006104de848285016104a5565b91505092915050565b60006104f38383610517565b60208301905092915050565b600061050b8383610535565b60208301905092915050565b61052081610725565b82525050565b61052f81610725565b82525050565b61053e81610725565b82525050565b600061054f826106b9565b61055981856106e9565b935061056483610694565b8060005b8381101561059557815161057c88826104e7565b9750610587836106cf565b925050600181019050610568565b5085935050505092915050565b60006105ad826106c4565b6105b781856106fa565b93506105c2836106a4565b8060005b838110156105fa576105d782610843565b6105e188826104ff565b97506105ec836106dc565b9250506001810190506105c6565b5085935050505092915050565b61061861061382610757565b61077b565b82525050565b600061062a8286610607565b60208201915061063a8285610607565b60208201915061064a82846105a2565b9150819050949350505050565b600060208201905061066c6000830184610526565b92915050565b6000602082019050818103600083015261068c8184610544565b905092915050565b6000819050602082019050919050565b60008190508160005260206000209050919050565b600081519050919050565b600081549050919050565b6000602082019050919050565b6000600182019050919050565b600082825260208201905092915050565b600081905092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061073082610737565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600061077461076f8361085b565b610705565b9050919050565b6000819050919050565b600061079082610757565b915061079b83610757565b9250826107ab576107aa6107b6565b5b828206905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600061084f8254610761565b9050919050565b600080fd5b60008160001c9050919050565b61087181610757565b811461087c57600080fd5b5056fea2646970667358221220729e8e8f09800dda1a73c44653546f8c8e4ee6c848019a56bd0d59c47e7aa72564736f6c63430008070033) + + xgt_wallet_0 = 'XGT0000000000000000000000000000000000000000' + + creator_keys = generate_keys + creator = create_wallet!(creator_keys) + transfer_xgt(xgt_wallet_0, creator, 10_000_000) + + alice_keys = generate_keys + alice = create_wallet!(alice_keys) + transfer_xgt(xgt_wallet_0, alice, 20_000_000) + + bob_keys = generate_keys + bob = create_wallet!(bob_keys) + transfer_xgt(xgt_wallet_0, bob, 30_000_000) + + charlie_keys = generate_keys + charlie = create_wallet!(charlie_keys) + transfer_xgt(xgt_wallet_0, charlie, 40_000_000) + + contract_keys = generate_keys + + create_wallet!(contract_keys) + + sleep(2) + + create_contract!(creator, contract_keys, code, creator_keys['recovery_private']) + + sleep(2) + + # Go and get most recently created contract + response = rpc.call('contract_api.list_owner_contracts', { 'owner' => creator }) || {} + p response + contract_hash = response['contracts'].first['contract_hash'] + contract = response['contracts'].first['wallet'] + # Inspect returned contract + # response = rpc.call('contract_api.get_contract', { 'contract_hash' => contract_hash }) || {} + # p response + # + + sleep(2) + + contract_balance_before = get_wallet(contract)['balance']['amount'] + creator_balance_before = get_wallet(creator)['balance']['amount'] + alice_balance_before = get_wallet(alice)['balance']['amount'] + bob_balance_before = get_wallet(bob)['balance']['amount'] + charlie_balance_before = get_wallet(charlie)['balance']['amount'] + + creator_address_r160 = get_wallet(creator)['address_ripemd160'] + alice_address_r160 = get_wallet(alice)['address_ripemd160'] + bob_address_r160 = get_wallet(bob)['address_ripemd160'] + charlie_address_r160 = get_wallet(charlie)['address_ripemd160'] + + puts "\n\nCreator address: #{creator}\nRipemd160: #{creator_address_r160}" + puts "\n\nAlice address: #{alice}\nRipemd160: #{alice_address_r160}" + puts "\n\nBob address: #{bob}\nRipemd160: #{bob_address_r160}" + puts "\n\nCharlie address: #{charlie}\nRipemd160: #{charlie_address_r160}\n\n" + + # Creator calls the enter() function + invoke_contract!(contract_hash, creator, 10000000000000001, 'e97dcb62') + sleep(1) + # Alice calls the enter() function + invoke_contract!(contract_hash, alice, 20000000000000002, 'e97dcb62') + sleep(1) + # Bob calls the enter() function + invoke_contract!(contract_hash, bob, 30000000000000003, 'e97dcb62') + sleep(1) + # Charlie calls the enter() function + invoke_contract!(contract_hash, charlie, 40000000000000004, 'e97dcb62') + sleep(1) + # Call the getPlayers() function + invoke_contract!(contract_hash, creator, 0, '8b5b9ccc') + sleep(1) + # Call the pickWinner() function + invoke_contract!(contract_hash, creator, 0, '5d495aea') + + sleep(5) + + contract_balance_after = get_wallet(contract)['balance']['amount'] + creator_balance_after = get_wallet(creator)['balance']['amount'] + alice_balance_after = get_wallet(alice)['balance']['amount'] + bob_balance_after = get_wallet(bob)['balance']['amount'] + charlie_balance_after = get_wallet(charlie)['balance']['amount'] + + puts "\n\nCreator address: #{creator}" + puts "Alice address: #{alice}" + puts "Bob address: #{bob}" + puts "Charlie address: #{charlie}" + + + puts "\n\nContract balance before: #{contract_balance_before}" + puts "\n\nCreator balance before: #{creator_balance_before}" + puts "Alice balance before: #{alice_balance_before}" + puts "Bob balance before: #{bob_balance_before}" + puts "Charlie balance before: #{charlie_balance_before}" + + puts "\n\nContract balance after: #{contract_balance_after}" + puts "\n\nCreator balance after: #{creator_balance_after}" + puts "Alice balance after: #{alice_balance_after}" + puts "Bob balance after: #{bob_balance_after}" + puts "Charlie balance after: #{charlie_balance_after}" + end + + task :test_create do + xgt_wallet_0 = 'XGT0000000000000000000000000000000000000000' + + creator_keys = generate_keys + creator = create_wallet!(creator_keys) + contract_keys = generate_keys + + create_wallet!(contract_keys) + + sleep(2) + + code = %(608060405260046040516100129061008a565b80828152602001915050604051809103906000f080158015610038573d6000803e3d6000fd5b506000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555034801561008457600080fd5b50610096565b60d0806103d683390190565b610331806100a56000396000f3fe6080604052600436106100295760003560e01c80638dcd64cc1461002e57806395fe0e6514610066575b600080fd5b6100646004803603604081101561004457600080fd5b8101908080359060200190929190803590602001909291905050506100a1565b005b34801561007257600080fd5b5061009f6004803603602081101561008957600080fd5b8101908080359060200190929190505050610162565b005b600081836040516100b190610220565b808281526020019150506040518091039082f0801580156100d6573d6000803e3d6000fd5b50905090508073ffffffffffffffffffffffffffffffffffffffff16630c55699c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561012157600080fd5b505afa158015610135573d6000803e3d6000fd5b505050506040513d602081101561014b57600080fd5b810190808051906020019092919050505050505050565b60008160405161017190610220565b80828152602001915050604051809103906000f080158015610197573d6000803e3d6000fd5b5090508073ffffffffffffffffffffffffffffffffffffffff16630c55699c6040518163ffffffff1660e01b815260040160206040518083038186803b1580156101e057600080fd5b505afa1580156101f4573d6000803e3d6000fd5b505050506040513d602081101561020a57600080fd5b8101908080519060200190929190505050505050565b60d08061022d8339019056fe60806040526040516100d03803806100d083398181016040526020811015602557600080fd5b8101908080519060200190929190505050806000819055505060848061004c6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c80630c55699c14602d575b600080fd5b60336049565b6040518082815260200191505060405180910390f35b6000548156fea265627a7a723158203e3e89f6c037d9933d5bdef0a2770bf1f37edb6a783aa6541fa6959d9e3dc29364736f6c63430005110032a265627a7a72315820a054097388070f7dcd34b458b35e036d10e3f9defdd31fc4e1d4df5f83232c7564736f6c6343000511003260806040526040516100d03803806100d083398181016040526020811015602557600080fd5b8101908080519060200190929190505050806000819055505060848061004c6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c80630c55699c14602d575b600080fd5b60336049565b6040518082815260200191505060405180910390f35b6000548156fea265627a7a723158203e3e89f6c037d9933d5bdef0a2770bf1f37edb6a783aa6541fa6959d9e3dc29364736f6c63430005110032) + create_contract!(creator, contract_keys, code, creator_keys['recovery_private']) + + sleep(2) + + response = rpc.call('contract_api.list_owner_contracts', { 'owner' => creator }) || {} + p response + contract_hash = response['contracts'].first['contract_hash'] + + invoke_contract!(contract_hash, creator, 0, '95fe0e650000000000000000000000000000000000000000000000000000000000000001') + + response = rpc.call('contract_api.list_owner_contracts', { 'owner' => creator }) || {} + puts "Creator contracts: \n\n\n" + puts JSON.pretty_generate response + + contract_wallet = response['contracts'].first['wallet'] + + response = rpc.call('contract_api.list_owner_contracts', { 'owner' => contract_wallet }) || {} + puts "Contract contracts: " + puts JSON.pretty_generate response + end + + task :delegatecall do + xgt_wallet_0 = 'XGT0000000000000000000000000000000000000000' + + # Create wallets for each contract + creator_keys = generate_keys + creator = create_wallet!(creator_keys) + + storage_keys = generate_keys + create_wallet!(storage_keys) + + calculator_keys = generate_keys + create_wallet!(calculator_keys) + + machine_keys = generate_keys + create_wallet!(machine_keys) + + sleep(2) + + puts "Wallets created" + + # Create storage contract to be called from machine + storage_code = %(608060405234801561001057600080fd5b5060405161011d38038061011d8339818101604052602081101561003357600080fd5b8101908080519060200190929190505050806000819055505060c38061005a6000396000f3fe6080604052348015600f57600080fd5b506004361060325760003560e01c80633c6bb43614603757806355241077146053575b600080fd5b603d607e565b6040518082815260200191505060405180910390f35b607c60048036036020811015606757600080fd5b81019080803590602001909291905050506084565b005b60005481565b806000819055505056fea265627a7a7231582074b793eb6e6838ddcd002ac1df0e6b92009ef3e4437800f9b467f4a9e71251fc64736f6c63430005110032) + create_contract!(creator, storage_keys, storage_code, creator_keys['recovery_private']) + + puts "Created storage contract" + + sleep(2) + + # Create calculator contract to be called using delegatecall from machine + calculator_code = %(608060405234801561001057600080fd5b506101fd806100206000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c80634f8632ba146100465780636e008b3514610090578063771602f7146100ae575b600080fd5b61004e6100fa565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610098610120565b6040518082815260200191505060405180910390f35b6100e4600480360360408110156100c457600080fd5b810190808035906020019092919080359060200190929190505050610126565b6040518082815260200191505060405180910390f35b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60005481565b600081830160008190555082600054101561013d57fe5b7f7afbe4f1c55b5f72ea356f5b4d5615831867af31454a5ca5557f315e6d11a3698383604051808381526020018281526020019250505060405180910390a133600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060005490509291505056fea265627a7a7231582050376063d00c2b0fa378da9e1c7614c28dfbbaa59458fc67fc68b2d54fed57dd64736f6c63430005110032) + stripped_calculator_code = %(608060405234801561001057600080fd5b50600436106100415760003560e01c80634f8632ba146100465780636e008b3514610090578063771602f7146100ae575b600080fd5b61004e6100fa565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610098610120565b6040518082815260200191505060405180910390f35b6100e4600480360360408110156100c457600080fd5b810190808035906020019092919080359060200190929190505050610126565b6040518082815260200191505060405180910390f35b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60005481565b600081830160008190555082600054101561013d57fe5b7f7afbe4f1c55b5f72ea356f5b4d5615831867af31454a5ca5557f315e6d11a3698383604051808381526020018281526020019250505060405180910390a133600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060005490509291505056fea265627a7a7231582050376063d00c2b0fa378da9e1c7614c28dfbbaa59458fc67fc68b2d54fed57dd64736f6c63430005110032) + create_contract!(creator, calculator_keys, calculator_code, creator_keys['recovery_private']) + + puts "Created calculator contract" + + sleep(2) + + # Calling contract aka machine + machine_code = %(608060405234801561001057600080fd5b50600080819055506107d1806100276000396000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c806386b714e21161005b57806386b714e2146101085780639b7e450c14610152578063c14731ca146101be578063f98f34d8146102045761007d565b806320965255146100825780634f8632ba146100a05780636e008b35146100ea575b600080fd5b61008a610270565b6040518082815260200191505060405180910390f35b6100a861031a565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6100f2610340565b6040518082815260200191505060405180910390f35b610110610346565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6101a86004803603606081101561016857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019092919050505061036c565b6040518082815260200191505060405180910390f35b6101ea600480360360208110156101d457600080fd5b8101908080359060200190929190505050610537565b604051808215151515815260200191505060405180910390f35b61025a6004803603606081101561021a57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803590602001909291905050506105cf565b6040518082815260200191505060405180910390f35b6000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16633c6bb4366040518163ffffffff1660e01b815260040160206040518083038186803b1580156102da57600080fd5b505afa1580156102ee573d6000803e3d6000fd5b505050506040513d602081101561030457600080fd5b8101908080519060200190929190505050905090565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60005481565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008060608573ffffffffffffffffffffffffffffffffffffffff16858560405160240180838152602001828152602001925050506040516020818303038152906040527f771602f7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040518082805190602001908083835b60208310610451578051825260208201915060208101905060208303925061042e565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855af49150503d80600081146104b1576040519150601f19603f3d011682016040523d82523d6000602084013e6104b6565b606091505b50915091507fb3cc7c40ae5fe031ec021a55a5c5cbddcb0837657bfaa8e8249801f67f7296458585846040518084815260200183815260200182151515158152602001935050505060405180910390a180806020019051602081101561051b57600080fd5b8101908080519060200190929190505050925050509392505050565b6000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166355241077836040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b1580156105ae57600080fd5b505af11580156105c2573d6000803e3d6000fd5b5050505060019050919050565b60008060608573ffffffffffffffffffffffffffffffffffffffff16858560405160240180838152602001828152602001925050506040516020818303038152906040527f771602f7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040518082805190602001908083835b602083106106b45780518252602082019150602081019050602083039250610691565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114610716576040519150601f19603f3d011682016040523d82523d6000602084013e61071b565b606091505b50915091507f81f50033f40bab548b88ccfd816202734d9325c0718e0395b473afe5454d599e8585846040518084815260200183815260200182151515158152602001935050505060405180910390a180806020019051602081101561078057600080fd5b810190808051906020019092919050505092505050939250505056fea265627a7a72315820a7fa96064b10ab27cbf9ae8932450561f061b789db57f9413d7820936dfcd47b64736f6c63430005110032) + create_contract!(creator, machine_keys, machine_code, creator_keys['recovery_private']) + + puts "Created machine contract" + + sleep(2) + + # Values to be added together + val1 = "00000000000000000000000000000001" + val2 = "00000000000000000000000000000002" + + response = rpc.call('contract_api.list_owner_contracts', { 'owner' => creator }) || {} + puts "\n\n\n\n" + puts machine_keys['wallet_name'] + puts "\n\n\n\n" + puts JSON.pretty_generate response + contract_hash = response['contracts'].first['contract_hash'] + + calculator_contract_address = response['contracts'].select { |contract| contract['code'] == stripped_calculator_code}.first['en_address'] + packed_calculator_contract_address = "000000000000000000000000#{calculator_contract_address}" + + puts "\n\nCalculator contract address: ", calculator_contract_address, "\n" + puts "\nContract args: 9b7e450c#{calculator_contract_address}#{val1}#{val2}\n\n" + + # Invoke contract with packed address (2 32-byte words) and args for addValuesWithDelegateCall + invoke_contract!(contract_hash, creator, 0, "9b7e450c#{packed_calculator_contract_address}#{val1}#{val2}") + + puts "Invoked machine contract" + end +end diff --git a/tasks/lazy_wallets.rake b/tasks/lazy_wallets.rake new file mode 100644 index 00000000..015ee696 --- /dev/null +++ b/tasks/lazy_wallets.rake @@ -0,0 +1,70 @@ +namespace :lazy_wallets do + task :name_test do + master = Xgt::Ruby::Auth.random_wif + private_key = Xgt::Ruby::Auth.generate_wif(wallet, master, 'recovery') + public_key = Xgt::Ruby::Auth.wif_to_public_key(private_key, address_prefix) + + response = rpc.call('wallet_by_key_api.generate_wallet_name', { + 'recovery_keys' => [public_key] + }) + wallet_name = response['wallet_name'] + + txn = { + 'extensions' => [], + 'operations' => [ + { + 'type' => 'transfer_operation', + 'value' => { + 'amount' => { + 'amount' => '1', + 'precision' => 8, + 'nai' => '@@000000021' + }, + 'from' => 'XGT0000000000000000000000000000000000000000', + 'to' => wallet_name, + 'json_metadata' => '', + 'extensions' => [] + } + } + ] + } + + id = rpc.broadcast_transaction(txn, [wif], chain_id) + (puts 'Waiting...' or sleep 1) until rpc.transaction_ready?(id) + + keys = generate_keys + txn = { + 'extensions' => [], + 'operations' => [ + { + 'type' => 'wallet_update_operation', + 'value' => { + 'wallet' => wallet_name, + 'recovery' => { + 'weight_threshold' => 1, + 'account_auths' => [], + 'key_auths' => [[keys['recovery_public'], 1]] + }, + 'money' => { + 'weight_threshold' => 1, + 'account_auths' => [], + 'key_auths' => [[keys['money_public'], 1]] + }, + 'social' => { + 'weight_threshold' => 1, + 'account_auths' => [], + 'key_auths' => [[keys['social_public'], 1]] + }, + 'memo_key' => keys['memo_public'], + 'json_metadata' => '', + 'extensions' => [] + } + } + ] + } + + p txn + id = rpc.broadcast_transaction(txn, [private_key], chain_id) + (puts 'Waiting...' or sleep 1) until rpc.transaction_ready?(id) + end +end From fc909918368db26f7e4e7ca25375c70ec4798dd1 Mon Sep 17 00:00:00 2001 From: Liam Noroian Date: Tue, 5 Apr 2022 10:12:52 -0700 Subject: [PATCH 87/96] WIP Create2 --- Rakefile | 212 +----- libraries/chain/include/attributes.h | 31 + libraries/chain/include/hash_types.h | 41 ++ libraries/chain/include/keccak.h | 27 + libraries/chain/include/rlpvalue | 1 + .../chain/include/xgt/chain/wallet_object.hpp | 1 + libraries/chain/keccak.c | 382 +++++++++++ libraries/chain/xgt_evaluator.cpp | 648 ++++++++++++++---- libraries/fc/include/fc/crypto/ripemd160.hpp | 2 +- libraries/fc/vendor/rlpvalue | 1 + .../apis/contract_api/contract_api.cpp | 6 +- .../xgt/plugins/contract_api/contract_api.hpp | 4 +- libraries/vendor/xgtvm/libraries/machine.cpp | 123 ++-- libraries/vendor/xgtvm/libraries/machine.hpp | 4 +- libraries/vendor/xgtvm/programs/xgtvm.cpp | 4 +- .../vendor/xgtvm/programs/xgtvm_tests.cpp | 4 +- tasks/contracts.rake | 103 ++- 17 files changed, 1149 insertions(+), 445 deletions(-) create mode 100644 libraries/chain/include/attributes.h create mode 100644 libraries/chain/include/hash_types.h create mode 100644 libraries/chain/include/keccak.h create mode 160000 libraries/chain/include/rlpvalue create mode 100644 libraries/chain/keccak.c create mode 160000 libraries/fc/vendor/rlpvalue diff --git a/Rakefile b/Rakefile index cf306ef2..eda8db54 100644 --- a/Rakefile +++ b/Rakefile @@ -5,6 +5,8 @@ require 'json' require 'bigdecimal' require 'shellwords' require 'rake/testtask' +import 'tasks/contracts.rake' +import 'tasks/lazy_wallets.rake' autoload :Xgt, 'xgt/ruby' autoload :Etc, 'etc' @@ -24,7 +26,7 @@ def from_genesis? end def mining_disabled? - ENV['MINING_DISABLED']&.upcase == 'TRUE' + ENV['MINING_DISABLED']&.upcase == 'FALSE' end def mining_threads @@ -51,23 +53,23 @@ def mining_error(message) end def wallet - ENV['XGT_WALLET'] || mining_error("Wallet not specificed, please specify a wallet with 'XGT_WALLET'") + 'XGT0000000000000000000000000000000000000000' end def wif - ENV['XGT_WIF'] || mining_error("XGT_WIF not specified") + '5JQMNhd5L9ML99ZoH2FaZ1PUHrYb4Jw7U3CgA73V8rgBfoipkxt' end def recovery_private_key - ENV['XGT_RECOVERY_PRIVATE_KEY'] || mining_error("XGT_RECOVERY_PRIVATE_KEY not specified") + '5JQMNhd5L9ML99ZoH2FaZ1PUHrYb4Jw7U3CgA73V8rgBfoipkxt' end def witness_private_key - ENV['XGT_WITNESS_PRIVATE_KEY'] || mining_error("XGT_WITNESS_PRIVATE_KEY not specified") + '5JQMNhd5L9ML99ZoH2FaZ1PUHrYb4Jw7U3CgA73V8rgBfoipkxt' end def host - ENV['XGT_HOST'] || 'http://localhost:8799' + ENV['XGT_HOST'] || 'http://localhost:8755' end def seed_hosts @@ -118,7 +120,7 @@ end desc 'Runs CMake to prepare the project' task :configure => "../xgt-build" do - sh %( cmake -G Ninja -B ../xgt-build -S . -D CMAKE_BUILD_TYPE=RelWithDebInfo ) + sh %( cmake -G Ninja -B ../xgt-build -S . -D CMAKE_BUILD_TYPE=debug ) end task :test do @@ -377,201 +379,7 @@ def create_wallet!(keys) $stderr.puts(%(Creating wallet with master key "#{keys['master']}"...)) signed = Xgt::Ruby::Auth.sign_transaction(rpc, txn, [wif], chain_id) rpc.call('transaction_api.broadcast_transaction', [signed]) -end - -def create_contract!(owner, keys, code) - txn = { - 'extensions' => [], - 'operations' => [ - { - 'type' => 'contract_create_operation', - 'value' => { - 'owner' => owner, - 'wallet' => keys['wallet_name'], - 'code' => code - #'code' => '600260030100', - #'code' => '00', - } - } - ] - } - signed = Xgt::Ruby::Auth.sign_transaction(rpc, txn, [wif], chain_id) - $stderr.puts(%(Registering contract... #{signed.to_json})) - response = rpc.call('transaction_api.broadcast_transaction', [signed]) - $stderr.puts(%(Received response contract... #{response})) -end - -def invoke_contract!(contract_hash, invoker, args) - txn = { - 'extensions' => [], - 'operations' => [ - { - 'type' => 'contract_invoke_operation', - 'value' => { - 'contract_hash' => contract_hash, - 'caller' => invoker, - 'args' => args - } - } - ] - } - $stderr.puts(%(Signing contract contract... #{txn.to_json})) - signed = Xgt::Ruby::Auth.sign_transaction(rpc, txn, [wif], chain_id) - $stderr.puts(%(Registering contract... #{signed.to_json})) - response = rpc.call('transaction_api.broadcast_transaction', [signed]) - $stderr.puts(%(Received response contract... #{response})) - response -end - -namespace :contracts do - desc 'Create a sample contract' - task :create do - keys = generate_keys - create_wallet!(keys) - # Bytecode explanation: - # - # 60 03 60 04 01 00 - # PUSH 3 PUSH 4 ADD HALT - # - create_contract!(wallet, keys, '600360040100') - - response = rpc.call('contract_api.list_owner_contracts', { 'owner' => wallet }) || {} - p response - contract_hash = response['contracts'].first['contract_hash'] - response = rpc.call('contract_api.get_contract', { 'contract_hash' => contract_hash }) || {} - p response - - invoke_contract!(contract_hash, keys['wallet_name'], []) - end - - desc 'Create a sample contract which calls another' - task :create_and_call do - create_contract = lambda { |code| - keys = generate_keys - create_wallet!(keys) - create_contract!(wallet, keys, code) - - response = rpc.call('contract_api.list_owner_contracts', { 'owner' => wallet }) || {} - p response - contract_hash = response['contracts'].first['contract_hash'] - response = rpc.call('contract_api.get_contract', { 'contract_hash' => contract_hash }) || {} - p response - - [contract_hash, keys] - } - - # Arguments to `call` opcode are: - # - # energy contract_hash value argsOffset argsLength retOffset retLength - # - # Bytecode explanation: - # - # PUSH 0 PUSH 0 RETURN HALT - # 60 00 60 00 F3 00 - # - contract_hash1, keys1 = create_contract.(%(60006000F300)) - # - # Bytecode explanation: - # - # PUSH 0 PUSH #{contract_hash1} 0 0 0 0 0 CALL HALT - # 60 00 60 #{contract_hash1} 60 00 60 00 60 00 60 00 60 00 F1 00 - # - contract_hash2, keys2 = create_contract.(%(600060#{contract_hash1}60006000600060006000F100)) - - invoke_contract!(contract_hash2, keys2['wallet_name'], []) - end - - desc 'The "Do Nothing" contract' - task :do_nothing do - create_contract = lambda { |code| - keys = generate_keys - create_wallet!(keys) - create_contract!(wallet, keys, code) - - response = rpc.call('contract_api.list_owner_contracts', { 'owner' => wallet }) || {} - p response - contract_hash = response['contracts'].first['contract_hash'] - response = rpc.call('contract_api.get_contract', { 'contract_hash' => contract_hash }) || {} - p response - - [contract_hash, keys] - } - - contract_hash, keys = create_contract.(%(6080604052348015600f57600080fd5b50606d80601d6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c80632f576f2014602d575b600080fd5b60336035565b005b56fea2646970667358221220975bdb6949442538b90c14c420b0a2f547f0437e85a73da12faf4e6834f0817264736f6c63430008070033)) - - invoke_contract!(contract_hash, keys['wallet_name'], []) - end -end - -namespace :lazy_wallets do - task :name_test do - master = Xgt::Ruby::Auth.random_wif - private_key = Xgt::Ruby::Auth.generate_wif(wallet, master, 'recovery') - public_key = Xgt::Ruby::Auth.wif_to_public_key(private_key, address_prefix) - - response = rpc.call('wallet_by_key_api.generate_wallet_name', { - 'recovery_keys' => [public_key] - }) - wallet_name = response['wallet_name'] - - txn = { - 'extensions' => [], - 'operations' => [ - { - 'type' => 'transfer_operation', - 'value' => { - 'amount' => { - 'amount' => '1', - 'precision' => 8, - 'nai' => '@@000000021' - }, - 'from' => 'XGT0000000000000000000000000000000000000000', - 'to' => wallet_name, - 'json_metadata' => '', - 'extensions' => [] - } - } - ] - } - - id = rpc.broadcast_transaction(txn, [wif], chain_id) - (puts 'Waiting...' or sleep 1) until rpc.transaction_ready?(id) - - keys = generate_keys - txn = { - 'extensions' => [], - 'operations' => [ - { - 'type' => 'wallet_update_operation', - 'value' => { - 'wallet' => wallet_name, - 'recovery' => { - 'weight_threshold' => 1, - 'account_auths' => [], - 'key_auths' => [[keys['recovery_public'], 1]] - }, - 'money' => { - 'weight_threshold' => 1, - 'account_auths' => [], - 'key_auths' => [[keys['money_public'], 1]] - }, - 'social' => { - 'weight_threshold' => 1, - 'account_auths' => [], - 'key_auths' => [[keys['social_public'], 1]] - }, - 'memo_key' => keys['memo_public'], - 'json_metadata' => '', - 'extensions' => [] - } - } - ] - } - - p txn - id = rpc.broadcast_transaction(txn, [private_key], chain_id) - (puts 'Waiting...' or sleep 1) until rpc.transaction_ready?(id) - end + name end namespace :machine do diff --git a/libraries/chain/include/attributes.h b/libraries/chain/include/attributes.h new file mode 100644 index 00000000..f03aa255 --- /dev/null +++ b/libraries/chain/include/attributes.h @@ -0,0 +1,31 @@ +// ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm. +// Copyright 2018 Pawel Bylica. +// Licensed under the Apache License, Version 2.0. + +#pragma once + +// Provide __has_attribute macro if not defined. +#ifndef __has_attribute +#define __has_attribute(name) 0 +#endif + +// Provide __has_builtin macro if not defined. +#ifndef __has_builtin +#define __has_builtin(x) 0 +#endif + +// [[always_inline]] +#if defined(_MSC_VER) +#define ALWAYS_INLINE __forceinline +#elif __has_attribute(always_inline) +#define ALWAYS_INLINE __attribute__((always_inline)) +#else +#define ALWAYS_INLINE +#endif + +// [[no_sanitize()]] +#if defined(__clang__) +#define NO_SANITIZE(sanitizer) __attribute__((no_sanitize(sanitizer))) +#else +#define NO_SANITIZE(sanitizer) +#endif diff --git a/libraries/chain/include/hash_types.h b/libraries/chain/include/hash_types.h new file mode 100644 index 00000000..caf6c288 --- /dev/null +++ b/libraries/chain/include/hash_types.h @@ -0,0 +1,41 @@ +/* ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm. + * Copyright 2018-2019 Pawel Bylica. + * Licensed under the Apache License, Version 2.0. + */ + +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +union ethash_hash256 +{ + uint64_t word64s[4]; + uint32_t word32s[8]; + uint8_t bytes[32]; + char str[32]; +}; + +union ethash_hash512 +{ + uint64_t word64s[8]; + uint32_t word32s[16]; + uint8_t bytes[64]; + char str[64]; +}; + +union ethash_hash1024 +{ + union ethash_hash512 hash512s[2]; + uint64_t word64s[16]; + uint32_t word32s[32]; + uint8_t bytes[128]; + char str[128]; +}; + +#ifdef __cplusplus +} +#endif diff --git a/libraries/chain/include/keccak.h b/libraries/chain/include/keccak.h new file mode 100644 index 00000000..355b8dd2 --- /dev/null +++ b/libraries/chain/include/keccak.h @@ -0,0 +1,27 @@ +/* ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm. + * Copyright 2018-2019 Pawel Bylica. + * Licensed under the Apache License, Version 2.0. + */ + +#pragma once + +#include + +#include + +#ifndef __cplusplus +#define noexcept // Ignore noexcept in C code. +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +union ethash_hash256 ethash_keccak256(const uint8_t* data, size_t size); +union ethash_hash256 ethash_keccak256_32(const uint8_t data[32]); +union ethash_hash512 ethash_keccak512(const uint8_t* data, size_t size); +union ethash_hash512 ethash_keccak512_64(const uint8_t data[64]); + +#ifdef __cplusplus +} +#endif diff --git a/libraries/chain/include/rlpvalue b/libraries/chain/include/rlpvalue new file mode 160000 index 00000000..1e58dcec --- /dev/null +++ b/libraries/chain/include/rlpvalue @@ -0,0 +1 @@ +Subproject commit 1e58dcec547dd19da4c325344d6f363d533dabe0 diff --git a/libraries/chain/include/xgt/chain/wallet_object.hpp b/libraries/chain/include/xgt/chain/wallet_object.hpp index f630db2f..eb7fe6c9 100644 --- a/libraries/chain/include/xgt/chain/wallet_object.hpp +++ b/libraries/chain/include/xgt/chain/wallet_object.hpp @@ -44,6 +44,7 @@ namespace xgt { namespace chain { uint32_t comment_count = 0; uint32_t lifetime_vote_count = 0; uint32_t post_count = 0; + uint32_t nonce = 0; bool can_vote = true; util::energybar energybar; diff --git a/libraries/chain/keccak.c b/libraries/chain/keccak.c new file mode 100644 index 00000000..04b38a38 --- /dev/null +++ b/libraries/chain/keccak.c @@ -0,0 +1,382 @@ +// ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm. +// Copyright 2018 Pawel Bylica. +// SPDX-License-Identifier: Apache-2.0 + +#include "attributes.h" +#include "keccak.h" + +#if !__has_builtin(__builtin_memcpy) && !defined(__GNUC__) +#include +#define __builtin_memcpy memcpy +#endif + +#if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +#define to_le64(X) __builtin_bswap64(X) +#else +#define to_le64(X) X +#endif + +/// Loads 64-bit integer from given memory location as little-endian number. +static inline ALWAYS_INLINE uint64_t load_le(const uint8_t* data) +{ + /* memcpy is the best way of expressing the intention. Every compiler will + optimize is to single load instruction if the target architecture + supports unaligned memory access (GCC and clang even in O0). + This is great trick because we are violating C/C++ memory alignment + restrictions with no performance penalty. */ + uint64_t word; + __builtin_memcpy(&word, data, sizeof(word)); + return to_le64(word); +} + +/// Rotates the bits of x left by the count value specified by s. +/// The s must be in range <0, 64> exclusively, otherwise the result is undefined. +static inline uint64_t rol(uint64_t x, unsigned s) +{ + return (x << s) | (x >> (64 - s)); +} + +static const uint64_t round_constants[24] = { // + 0x0000000000000001, 0x0000000000008082, 0x800000000000808a, 0x8000000080008000, + 0x000000000000808b, 0x0000000080000001, 0x8000000080008081, 0x8000000000008009, + 0x000000000000008a, 0x0000000000000088, 0x0000000080008009, 0x000000008000000a, + 0x000000008000808b, 0x800000000000008b, 0x8000000000008089, 0x8000000000008003, + 0x8000000000008002, 0x8000000000000080, 0x000000000000800a, 0x800000008000000a, + 0x8000000080008081, 0x8000000000008080, 0x0000000080000001, 0x8000000080008008}; + + +/// The Keccak-f[1600] function. +/// +/// The implementation of the Keccak-f function with 1600-bit width of the permutation (b). +/// The size of the state is also 1600 bit what gives 25 64-bit words. +/// +/// @param state The state of 25 64-bit words on which the permutation is to be performed. +/// +/// The implementation based on: +/// - "simple" implementation by Ronny Van Keer, included in "Reference and optimized code in C", +/// https://keccak.team/archives.html, CC0-1.0 / Public Domain. +static inline ALWAYS_INLINE void keccakf1600_implementation(uint64_t state[25]) +{ + uint64_t Aba, Abe, Abi, Abo, Abu; + uint64_t Aga, Age, Agi, Ago, Agu; + uint64_t Aka, Ake, Aki, Ako, Aku; + uint64_t Ama, Ame, Ami, Amo, Amu; + uint64_t Asa, Ase, Asi, Aso, Asu; + + uint64_t Eba, Ebe, Ebi, Ebo, Ebu; + uint64_t Ega, Ege, Egi, Ego, Egu; + uint64_t Eka, Eke, Eki, Eko, Eku; + uint64_t Ema, Eme, Emi, Emo, Emu; + uint64_t Esa, Ese, Esi, Eso, Esu; + + uint64_t Ba, Be, Bi, Bo, Bu; + + uint64_t Da, De, Di, Do, Du; + + Aba = state[0]; + Abe = state[1]; + Abi = state[2]; + Abo = state[3]; + Abu = state[4]; + Aga = state[5]; + Age = state[6]; + Agi = state[7]; + Ago = state[8]; + Agu = state[9]; + Aka = state[10]; + Ake = state[11]; + Aki = state[12]; + Ako = state[13]; + Aku = state[14]; + Ama = state[15]; + Ame = state[16]; + Ami = state[17]; + Amo = state[18]; + Amu = state[19]; + Asa = state[20]; + Ase = state[21]; + Asi = state[22]; + Aso = state[23]; + Asu = state[24]; + + for (size_t n = 0; n < 24; n += 2) + { + // Round (n + 0): Axx -> Exx + + Ba = Aba ^ Aga ^ Aka ^ Ama ^ Asa; + Be = Abe ^ Age ^ Ake ^ Ame ^ Ase; + Bi = Abi ^ Agi ^ Aki ^ Ami ^ Asi; + Bo = Abo ^ Ago ^ Ako ^ Amo ^ Aso; + Bu = Abu ^ Agu ^ Aku ^ Amu ^ Asu; + + Da = Bu ^ rol(Be, 1); + De = Ba ^ rol(Bi, 1); + Di = Be ^ rol(Bo, 1); + Do = Bi ^ rol(Bu, 1); + Du = Bo ^ rol(Ba, 1); + + Ba = Aba ^ Da; + Be = rol(Age ^ De, 44); + Bi = rol(Aki ^ Di, 43); + Bo = rol(Amo ^ Do, 21); + Bu = rol(Asu ^ Du, 14); + Eba = Ba ^ (~Be & Bi) ^ round_constants[n]; + Ebe = Be ^ (~Bi & Bo); + Ebi = Bi ^ (~Bo & Bu); + Ebo = Bo ^ (~Bu & Ba); + Ebu = Bu ^ (~Ba & Be); + + Ba = rol(Abo ^ Do, 28); + Be = rol(Agu ^ Du, 20); + Bi = rol(Aka ^ Da, 3); + Bo = rol(Ame ^ De, 45); + Bu = rol(Asi ^ Di, 61); + Ega = Ba ^ (~Be & Bi); + Ege = Be ^ (~Bi & Bo); + Egi = Bi ^ (~Bo & Bu); + Ego = Bo ^ (~Bu & Ba); + Egu = Bu ^ (~Ba & Be); + + Ba = rol(Abe ^ De, 1); + Be = rol(Agi ^ Di, 6); + Bi = rol(Ako ^ Do, 25); + Bo = rol(Amu ^ Du, 8); + Bu = rol(Asa ^ Da, 18); + Eka = Ba ^ (~Be & Bi); + Eke = Be ^ (~Bi & Bo); + Eki = Bi ^ (~Bo & Bu); + Eko = Bo ^ (~Bu & Ba); + Eku = Bu ^ (~Ba & Be); + + Ba = rol(Abu ^ Du, 27); + Be = rol(Aga ^ Da, 36); + Bi = rol(Ake ^ De, 10); + Bo = rol(Ami ^ Di, 15); + Bu = rol(Aso ^ Do, 56); + Ema = Ba ^ (~Be & Bi); + Eme = Be ^ (~Bi & Bo); + Emi = Bi ^ (~Bo & Bu); + Emo = Bo ^ (~Bu & Ba); + Emu = Bu ^ (~Ba & Be); + + Ba = rol(Abi ^ Di, 62); + Be = rol(Ago ^ Do, 55); + Bi = rol(Aku ^ Du, 39); + Bo = rol(Ama ^ Da, 41); + Bu = rol(Ase ^ De, 2); + Esa = Ba ^ (~Be & Bi); + Ese = Be ^ (~Bi & Bo); + Esi = Bi ^ (~Bo & Bu); + Eso = Bo ^ (~Bu & Ba); + Esu = Bu ^ (~Ba & Be); + + + // Round (n + 1): Exx -> Axx + + Ba = Eba ^ Ega ^ Eka ^ Ema ^ Esa; + Be = Ebe ^ Ege ^ Eke ^ Eme ^ Ese; + Bi = Ebi ^ Egi ^ Eki ^ Emi ^ Esi; + Bo = Ebo ^ Ego ^ Eko ^ Emo ^ Eso; + Bu = Ebu ^ Egu ^ Eku ^ Emu ^ Esu; + + Da = Bu ^ rol(Be, 1); + De = Ba ^ rol(Bi, 1); + Di = Be ^ rol(Bo, 1); + Do = Bi ^ rol(Bu, 1); + Du = Bo ^ rol(Ba, 1); + + Ba = Eba ^ Da; + Be = rol(Ege ^ De, 44); + Bi = rol(Eki ^ Di, 43); + Bo = rol(Emo ^ Do, 21); + Bu = rol(Esu ^ Du, 14); + Aba = Ba ^ (~Be & Bi) ^ round_constants[n + 1]; + Abe = Be ^ (~Bi & Bo); + Abi = Bi ^ (~Bo & Bu); + Abo = Bo ^ (~Bu & Ba); + Abu = Bu ^ (~Ba & Be); + + Ba = rol(Ebo ^ Do, 28); + Be = rol(Egu ^ Du, 20); + Bi = rol(Eka ^ Da, 3); + Bo = rol(Eme ^ De, 45); + Bu = rol(Esi ^ Di, 61); + Aga = Ba ^ (~Be & Bi); + Age = Be ^ (~Bi & Bo); + Agi = Bi ^ (~Bo & Bu); + Ago = Bo ^ (~Bu & Ba); + Agu = Bu ^ (~Ba & Be); + + Ba = rol(Ebe ^ De, 1); + Be = rol(Egi ^ Di, 6); + Bi = rol(Eko ^ Do, 25); + Bo = rol(Emu ^ Du, 8); + Bu = rol(Esa ^ Da, 18); + Aka = Ba ^ (~Be & Bi); + Ake = Be ^ (~Bi & Bo); + Aki = Bi ^ (~Bo & Bu); + Ako = Bo ^ (~Bu & Ba); + Aku = Bu ^ (~Ba & Be); + + Ba = rol(Ebu ^ Du, 27); + Be = rol(Ega ^ Da, 36); + Bi = rol(Eke ^ De, 10); + Bo = rol(Emi ^ Di, 15); + Bu = rol(Eso ^ Do, 56); + Ama = Ba ^ (~Be & Bi); + Ame = Be ^ (~Bi & Bo); + Ami = Bi ^ (~Bo & Bu); + Amo = Bo ^ (~Bu & Ba); + Amu = Bu ^ (~Ba & Be); + + Ba = rol(Ebi ^ Di, 62); + Be = rol(Ego ^ Do, 55); + Bi = rol(Eku ^ Du, 39); + Bo = rol(Ema ^ Da, 41); + Bu = rol(Ese ^ De, 2); + Asa = Ba ^ (~Be & Bi); + Ase = Be ^ (~Bi & Bo); + Asi = Bi ^ (~Bo & Bu); + Aso = Bo ^ (~Bu & Ba); + Asu = Bu ^ (~Ba & Be); + } + + state[0] = Aba; + state[1] = Abe; + state[2] = Abi; + state[3] = Abo; + state[4] = Abu; + state[5] = Aga; + state[6] = Age; + state[7] = Agi; + state[8] = Ago; + state[9] = Agu; + state[10] = Aka; + state[11] = Ake; + state[12] = Aki; + state[13] = Ako; + state[14] = Aku; + state[15] = Ama; + state[16] = Ame; + state[17] = Ami; + state[18] = Amo; + state[19] = Amu; + state[20] = Asa; + state[21] = Ase; + state[22] = Asi; + state[23] = Aso; + state[24] = Asu; +} + +static void keccakf1600_generic(uint64_t state[25]) +{ + keccakf1600_implementation(state); +} + +/// The pointer to the best Keccak-f[1600] function implementation, +/// selected during runtime initialization. +static void (*keccakf1600_best)(uint64_t[25]) = keccakf1600_generic; + + +#if !defined(_MSC_VER) && defined(__x86_64__) && __has_attribute(target) +__attribute__((target("bmi,bmi2"))) static void keccakf1600_bmi(uint64_t state[25]) +{ + keccakf1600_implementation(state); +} + +__attribute__((constructor)) static void select_keccakf1600_implementation() +{ + // Init CPU information. + // This is needed on macOS because of the bug: https://bugs.llvm.org/show_bug.cgi?id=48459. + __builtin_cpu_init(); + + // Check if both BMI and BMI2 are supported. Some CPUs like Intel E5-2697 v2 incorrectly + // report BMI2 but not BMI being available. + if (__builtin_cpu_supports("bmi") && __builtin_cpu_supports("bmi2")) + keccakf1600_best = keccakf1600_bmi; +} +#endif + + +static inline ALWAYS_INLINE void keccak( + uint64_t* out, size_t bits, const uint8_t* data, size_t size) +{ + static const size_t word_size = sizeof(uint64_t); + const size_t hash_size = bits / 8; + const size_t block_size = (1600 - bits * 2) / 8; + + size_t i; + uint64_t* state_iter; + uint64_t last_word = 0; + uint8_t* last_word_iter = (uint8_t*)&last_word; + + uint64_t state[25] = {0}; + + while (size >= block_size) + { + for (i = 0; i < (block_size / word_size); ++i) + { + state[i] ^= load_le(data); + data += word_size; + } + + keccakf1600_best(state); + + size -= block_size; + } + + state_iter = state; + + while (size >= word_size) + { + *state_iter ^= load_le(data); + ++state_iter; + data += word_size; + size -= word_size; + } + + while (size > 0) + { + *last_word_iter = *data; + ++last_word_iter; + ++data; + --size; + } + *last_word_iter = 0x01; + *state_iter ^= to_le64(last_word); + + state[(block_size / word_size) - 1] ^= 0x8000000000000000; + + keccakf1600_best(state); + + for (i = 0; i < (hash_size / word_size); ++i) + out[i] = to_le64(state[i]); +} + +union ethash_hash256 ethash_keccak256(const uint8_t* data, size_t size) +{ + union ethash_hash256 hash; + keccak(hash.word64s, 256, data, size); + return hash; +} + +union ethash_hash256 ethash_keccak256_32(const uint8_t data[32]) +{ + union ethash_hash256 hash; + keccak(hash.word64s, 256, data, 32); + return hash; +} + +union ethash_hash512 ethash_keccak512(const uint8_t* data, size_t size) +{ + union ethash_hash512 hash; + keccak(hash.word64s, 512, data, size); + return hash; +} + +union ethash_hash512 ethash_keccak512_64(const uint8_t data[64]) +{ + union ethash_hash512 hash; + keccak(hash.word64s, 512, data, 64); + return hash; +} diff --git a/libraries/chain/xgt_evaluator.cpp b/libraries/chain/xgt_evaluator.cpp index c875c4f6..5cfa3e48 100644 --- a/libraries/chain/xgt_evaluator.cpp +++ b/libraries/chain/xgt_evaluator.cpp @@ -11,7 +11,9 @@ #include #include -#include "keccak256.h" +#include +#include +#include #include #include @@ -21,6 +23,12 @@ #include #include #include +#include "rlpvalue/include/rlpvalue.h" +#include "rlpvalue/include/rlpvalue.h" +#include "rlpvalue/lib/rlpvalue.cpp" +#include "rlpvalue/lib/rlpvalue_get.cpp" +#include "rlpvalue/lib/rlpvalue_write.cpp" +#include "rlpvalue/test/utilstrencodings.cpp" #include @@ -143,15 +151,16 @@ void verify_authority_accounts_exist( } void initialize_wallet_object( wallet_object& acc, const wallet_name_type& name, const public_key_type& key, - const dynamic_global_property_object& props, bool mined, const wallet_name_type& recovery_account, uint32_t hardfork ) + const dynamic_global_property_object& props, bool mined, const wallet_name_type& recovery_account, uint32_t hardfork, uint32_t nonce, std::string address_ripemd160 = "" ) { wlog("?????? initialize_wallet_object name ${n}", ("n", name)); wlog("?????? initialize_wallet_object key ${n}", ("n", key)); wlog("?????? initialize_wallet_object created ${n}", ("n", props.time)); acc.name = name; - acc.address_ripemd160 = fc::ripemd160::hex_digest(name); + acc.address_ripemd160 = address_ripemd160 == "" ? fc::ripemd160::hex_digest(name) : address_ripemd160; acc.memo_key = key; acc.created = props.time; + acc.nonce = nonce; //acc.energybar.last_update_time = props.time.sec_since_epoch(); //acc.mined = mined; @@ -201,7 +210,7 @@ void wallet_create_evaluator::do_apply( const wallet_create_operation& o ) _db.create< wallet_object >( [&]( wallet_object& acc ) { - initialize_wallet_object( acc, wallet_name, o.memo_key, props, false /*mined*/, o.creator, _db.get_hardfork() ); + initialize_wallet_object( acc, wallet_name, o.memo_key, props, false /*mined*/, o.creator, _db.get_hardfork(), 0 ); }); _db.create< account_authority_object >( [&]( account_authority_object& auth ) @@ -235,7 +244,7 @@ void wallet_update_evaluator::do_apply( const wallet_update_operation& o ) const auto& props = _db.get_dynamic_global_properties(); _db.create< wallet_object >( [&]( wallet_object& acc ) { - initialize_wallet_object( acc, o.wallet, *o.memo_key, props, false /*mined*/, XGT_INIT_MINER_NAME, _db.get_hardfork() ); + initialize_wallet_object( acc, o.wallet, *o.memo_key, props, false /*mined*/, XGT_INIT_MINER_NAME, _db.get_hardfork(), 0 ); }); _db.create< account_authority_object >( [&]( account_authority_object& auth ) @@ -725,7 +734,7 @@ void transfer_evaluator::do_apply( const transfer_operation& o ) _db.create< wallet_object >( [&]( wallet_object& w ) { - initialize_wallet_object( w, o.to, memo_pubkey, props, false /*mined*/, XGT_INIT_MINER_NAME, _db.get_hardfork() ); + initialize_wallet_object( w, o.to, memo_pubkey, props, false /*mined*/, XGT_INIT_MINER_NAME, _db.get_hardfork(), 0 ); }); _db.create< account_authority_object >( [&]( account_authority_object& auth ) @@ -977,7 +986,7 @@ void pow_evaluator::do_apply( const pow_operation& o ) db.create< wallet_object >( [&]( wallet_object& acc ) { - initialize_wallet_object( acc, worker_account, *o.new_recovery_key, dgp, true /*mined*/, wallet_name_type(), _db.get_hardfork() ); + initialize_wallet_object( acc, worker_account, *o.new_recovery_key, dgp, true /*mined*/, wallet_name_type(), _db.get_hardfork(), 0 ); // ^ empty recovery account parameter means highest voted witness at time of recovery }); @@ -1019,29 +1028,6 @@ void report_over_production_evaluator::do_apply( const report_over_production_op { } -// TODO: Revisit this -fc::ripemd160 generate_random_ripemd160() -{ - const size_t buflen = 128; - char buf[buflen]; - fc::rand_bytes(buf, buflen); - return fc::ripemd160::hash(buf, buflen); -} - -// XXX Needs work -- does not consistently convert values -boost::multiprecision::uint256_t ripemd160_to_uint256_t(fc::ripemd160 h) -{ - boost::multiprecision::uint256_t n(0); - boost::multiprecision::uint256_t m; - for (int i = 0; i < 5; i++) - { - m = h._hash[i]; - m = m << (8 * i); - n |= m; - } - return n; -} - fc::ripemd160 make_contract_hash(const wallet_name_type& owner, const vector code) { string s(code.begin(), code.end()); @@ -1198,6 +1184,15 @@ std::map< uint64_t, std::function > energy_cost { {machine::selfdestruct_opcode, [](machine::machine& m){ return 0; }} // TODO -- selfdestruct -- variable }; +// TODO: Revisit this +fc::ripemd160 generate_random_ripemd160() +{ + const size_t buflen = 128; + char buf[buflen]; + fc::rand_bytes(buf, buflen); + return fc::ripemd160::hash(buf, buflen); +} + boost::multiprecision::uint256_t address_to_uint256_t(const std::string& base58str) { std::string prefix( XGT_ADDRESS_PREFIX ); @@ -1212,7 +1207,224 @@ boost::multiprecision::uint256_t address_to_uint256_t(const std::string& base58s return x; }; -const wallet_object& wallet_create(chain::database& _db) +boost::multiprecision::uint256_t ripemd160_to_uint256_t(fc::ripemd160 h) +{ + boost::multiprecision::uint256_t n(0); + boost::multiprecision::uint256_t m; + for (int i = 0; i < 5; i++) + { + m = h._hash[i]; + m = m << (8 * i); + n |= m; + } + return n; +} + +address_ripemd160_type uint256_t_to_ripemd160(boost::multiprecision::uint256_t address) { + std::stringstream ss; + ss << std::hex << address; + return ss.str(); +} + +int char2int(char input) +{ + if(input >= '0' && input <= '9') + return input - '0'; + if(input >= 'A' && input <= 'F') + return input - 'A' + 10; + if(input >= 'a' && input <= 'f') + return input - 'a' + 10; + throw std::invalid_argument("Invalid input string"); +} + +// This function assumes src to be a zero terminated sanitized string with +// an even number of [0-9a-f] characters, and target to be sufficiently large +void hex2bin(const char* src, char* target) +{ + while(*src && src[1]) + { + *(target++) = char2int(*src)*16 + char2int(src[1]); + src += 2; + } +} + +template +inline std::string to_hex(const Hash& h) +{ + static const auto hex_chars = "0123456789abcdef"; + std::string str; + str.reserve(sizeof(h) * 2); + for (auto b : h.bytes) + { + str.push_back(hex_chars[uint8_t(b) >> 4]); + str.push_back(hex_chars[uint8_t(b) & 0xf]); + } + return str; +} + +void hex_to_uint8(std::string hex, uint8_t bytes[]) { + if ( hex.size() >= 2 && hex[0] == '0' && (hex[1] == 'x' || hex[1] == 'X') ) + hex.erase(0, 2); + if (hex.size() % 2 != 0) + hex = '0' + hex; + for (size_t i = 0; i < hex.size(); i += 2) { + if (hex.substr(i, 2) == "0x") + continue; + uint8_t code = std::stoi(hex.substr(i, 2), 0, 16); + bytes[i / 2] = code; + } + return; +} + +void generate_create2_input(std::string sender, std::string salt, std::string init_code, std::string target_address) { + std::stringstream ss; + + // Recipe: keccak256( 0xff ++ address ++ salt ++ keccak256(init_code))[12:] + + size_t init_code_size = init_code.size() / 2; + uint8_t init_code_bytes[init_code_size]; + hex_to_uint8(init_code, init_code_bytes); + auto init_code_output = ethash_keccak256( init_code_bytes, init_code_size ); + // keccak256(init_code) + std::string init_code_hash = to_hex(init_code_output); + + // 0xff ++ address ++ salt ++ keccak256(init_code) + ss << "ff" << sender << salt << init_code_hash; + std::string keccak_input_str = ss.str(); + + std::cout << "Keccak input string: " << keccak_input_str << std::endl; + + size_t size = keccak_input_str.size() / 2; + uint8_t bytes[size]; + hex_to_uint8(keccak_input_str, bytes); + + auto keccak_output = ethash_keccak256( bytes, size ); + std::string untrimmed_address = to_hex(keccak_output); + std::string generated_create2_address = untrimmed_address.substr(24, 40); + + std::cout << "Input sender : " << sender << std::endl; + std::cout << "Input salt : " << salt << std::endl; + std::cout << "Input init_code : " << init_code << std::endl; + std::cout << "Hashed init_code : " << init_code_hash << std::endl; + std::cout << "Target create2 address : " << target_address << std::endl; + std::cout << "Generated untrimmed create2 address: " << untrimmed_address << std::endl; + std::cout << "Generated create2 address : " << generated_create2_address << std::endl; + std::cout << "************************************************************************************************" << std::endl; + + return; +} + +// TODO sender is address_ripemd160 +const std::string generate_rlp_wallet_name(std::string sender, uint32_t nonce, std::string salt = "", std::vector init_code = {}) { + if (salt == "") { + std::string rlp_input; + rlp_input += sender += nonce; + + RLPValue v = RLPValue(rlp_input); + + // Generate output rlp-encoded hex + std::string genOutput = v.write(); + std::string genHexStr = HexStr( genOutput.begin(), genOutput.end() ); + + std::stringstream ss; + unsigned char output[32]; + SHA3_CTX ctx; + keccak_init(&ctx); + keccak_update( &ctx, (unsigned char*)genHexStr.c_str(), genHexStr.size() ); + keccak_final(&ctx, output); + for (size_t i = 0; i < 32; i++) { + ss << std::hex << (machine::opcode)output[i]; + } + std::string gen_hex_hash = ss.str(); + std::vector rlp_vec( gen_hex_hash.begin(), gen_hex_hash.end() ); + std::string base58Str = fc::to_base58(rlp_vec); + std::string rlp_address = base58Str.substr(base58Str.size() - 40); + + return "XGT" + rlp_address; + } else { + std::stringstream ss; + std::string leader = "ff"; + // init_code = {0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef}; + // for (size_t i = 0; i < init_code.size(); i++) { + // if ((machine::opcode)init_code[i] < 0x10) + // ss << "0"; + // // ss << "00000000000000000000000000000000000000000000000000000000000000"; + // ss << std::hex << (machine::opcode)init_code[i]; + // } + // std::string init_code_str = ss.str(); + // std::string init_code_str_seed = "6080604060806040"; + // std::string init_code_str = ""; + // for (size_t i = 0; i < 16; i++) { + // init_code_str += init_code_str_seed; + // } + // std::string init_code_str = "00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000052000000000000000000000000000000000000000000000000000000000000003400000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000015000000000000000000000000000000000000000000000000000000000000006100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000005700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000fd000000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000005100000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000006800000000000000000000000000000000000000000000000000000000000000380000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000006800000000000000000000000000000000000000000000000000000000000000830000000000000000000000000000000000000000000000000000000000000039000000000000000000000000000000000000000000000000000000000000008100000000000000000000000000000000000000000000000000000000000000810000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000052000000000000000000000000000000000000000000000000000000000000008100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000090000000000000000000000000000000000000000000000000000000000000006100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000009100000000000000000000000000000000000000000000000000000000000000900000000000000000000000000000000000000000000000000000000000000061000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000540000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008100000000000000000000000000000000000000000000000000000000000000900000000000000000000000000000000000000000000000000000000000000055000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000061000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a70000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005b00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008100000000000000000000000000000000000000000000000000000000000000510000000000000000000000000000000000000000000000000000000000000090000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004e00000000000000000000000000000000000000000000000000000000000000810000000000000000000000000000000000000000000000000000000000000061000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000900000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005b00000000000000000000000000000000000000000000000000000000000000920000000000000000000000000000000000000000000000000000000000000091000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005b00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000082000000000000000000000000000000000000000000000000000000000000008400000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000001500000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006a000000000000000000000000000000000000000000000000000000000000005700000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006900000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008b0000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000000000000000000000000000000000005b00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000078000000000000000000000000000000000000000000000000000000000000008400000000000000000000000000000000000000000000000000000000000000820000000000000000000000000000000000000000000000000000000000000085000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003f0000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005b00000000000000000000000000000000000000000000000000000000000000910000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000920000000000000000000000000000000000000000000000000000000000000091000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000081000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000091000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005b00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000fd000000000000000000000000000000000000000000000000000000000000005b00000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009900000000000000000000000000000000000000000000000000000000000000810000000000000000000000000000000000000000000000000000000000000061000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000810000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000000000000000000000000000000000008100000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000061000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a4000000000000000000000000000000000000000000000000000000000000005700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000fd000000000000000000000000000000000000000000000000000000000000005b00000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000b300000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000061000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b50000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000390000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f300000000000000000000000000000000000000000000000000000000000000fe000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000520000000000000000000000000000000000000000000000000000000000000034000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000150000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000005700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000fd000000000000000000000000000000000000000000000000000000000000005b00000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000360000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000057000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000035000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000001c00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000063000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000550000000000000000000000000000000000000000000000000000000000000069000000000000000000000000000000000000000000000000000000000000009c00000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000002d0000000000000000000000000000000000000000000000000000000000000057000000000000000000000000000000000000000000000000000000000000005b00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000fd000000000000000000000000000000000000000000000000000000000000005b00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000033000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000470000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005b0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000510000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000003e000000000000000000000000000000000000000000000000000000000000009100000000000000000000000000000000000000000000000000000000000000900000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000005a0000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000051000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000910000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000f3000000000000000000000000000000000000000000000000000000000000005b00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005400000000000000000000000000000000000000000000000000000000000000810000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000540000000000000000000000000000000000000000000000000000000000000081000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000730000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005b00000000000000000000000000000000000000000000000000000000000000820000000000000000000000000000000000000000000000000000000000000052000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000820000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000006d000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000840000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000004d0000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005b00000000000000000000000000000000000000000000000000000000000000920000000000000000000000000000000000000000000000000000000000000091000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005b00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008100000000000000000000000000000000000000000000000000000000000000900000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000009100000000000000000000000000000000000000000000000000000000000000900000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000005600000000000000000000000000000000000000000000000000000000000000fe00000000000000000000000000000000000000000000000000000000000000a20000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000000000000000000000000000000000006900000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000066000000000000000000000000000000000000000000000000000000000000007300000000000000000000000000000000000000000000000000000000000000580000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000017000000000000000000000000000000000000000000000000000000000000006e000000000000000000000000000000000000000000000000000000000000007e000000000000000000000000000000000000000000000000000000000000009500000000000000000000000000000000000000000000000000000000000000770000000000000000000000000000000000000000000000000000000000000062000000000000000000000000000000000000000000000000000000000000006c000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c200000000000000000000000000000000000000000000000000000000000000b500000000000000000000000000000000000000000000000000000000000000e4000000000000000000000000000000000000000000000000000000000000006d0000000000000000000000000000000000000000000000000000000000000069000000000000000000000000000000000000000000000000000000000000007700000000000000000000000000000000000000000000000000000000000000770000000000000000000000000000000000000000000000000000000000000036000000000000000000000000000000000000000000000000000000000000008d00000000000000000000000000000000000000000000000000000000000000aa000000000000000000000000000000000000000000000000000000000000003100000000000000000000000000000000000000000000000000000000000000a6000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000c600000000000000000000000000000000000000000000000000000000000000c300000000000000000000000000000000000000000000000000000000000000fd000000000000000000000000000000000000000000000000000000000000006c00000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000bb00000000000000000000000000000000000000000000000000000000000000c500000000000000000000000000000000000000000000000000000000000000bd000000000000000000000000000000000000000000000000000000000000004f000000000000000000000000000000000000000000000000000000000000008f000000000000000000000000000000000000000000000000000000000000002a00000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000073000000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000006c00000000000000000000000000000000000000000000000000000000000000630000000000000000000000000000000000000000000000000000000000000043000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000007000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000334e00000000000000000000000000000000000000000000000000000000000000810000000000000000000000000000000000000000000000000000000000000061000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000900000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005b00000000000000000000000000000000000000000000000000000000000000920000000000000000000000000000000000000000000000000000000000000091000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005b00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000082000000000000000000000000000000000000000000000000000000000000008400000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000001500000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006a000000000000000000000000000000000000000000000000000000000000005700000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006900000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008b0000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000000000000000000000000000000000005b00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000078000000000000000000000000000000000000000000000000000000000000008400000000000000000000000000000000000000000000000000000000000000820000000000000000000000000000000000000000000000000000000000000085000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003f0000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005b00000000000000000000000000000000000000000000000000000000000000910000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000920000000000000000000000000000000000000000000000000000000000000091000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000081000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000091000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005b00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000fd000000000000000000000000000000000000000000000000000000000000005b00000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009900000000000000000000000000000000000000000000000000000000000000810000000000000000000000000000000000000000000000000000000000000061000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000810000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000000000000000000000000000000000008100000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000061000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a4000000000000000000000000000000000000000000000000000000000000005700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000fd000000000000000000000000000000000000000000000000000000000000005b00000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000b300000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000061000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b50000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000390000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f300000000000000000000000000000000000000000000000000000000000000fe000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000520000000000000000000000000000000000000000000000000000000000000034000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000150000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000005700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000fd000000000000000000000000000000000000000000000000000000000000005b00000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000360000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000057000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000035000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000001c00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000063000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000550000000000000000000000000000000000000000000000000000000000000069000000000000000000000000000000000000000000000000000000000000009c00000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000002d0000000000000000000000000000000000000000000000000000000000000057000000000000000000000000000000000000000000000000000000000000005b00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000fd000000000000000000000000000000000000000000000000000000000000005b00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000033000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000470000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005b0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000510000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000003e000000000000000000000000000000000000000000000000000000000000009100000000000000000000000000000000000000000000000000000000000000900000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000005a0000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000051000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000910000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000f3000000000000000000000000000000000000000000000000000000000000005b00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005400000000000000000000000000000000000000000000000000000000000000810000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000540000000000000000000000000000000000000000000000000000000000000081000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000730000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005b00000000000000000000000000000000000000000000000000000000000000820000000000000000000000000000000000000000000000000000000000000052000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000820000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000006d000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000840000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000004d0000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005b00000000000000000000000000000000000000000000000000000000000000920000000000000000000000000000000000000000000000000000000000000091000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005b00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008100000000000000000000000000000000000000000000000000000000000000900000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000009100000000000000000000000000000000000000000000000000000000000000900000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000005600000000000000000000000000000000000000000000000000000000000000fe00000000000000000000000000000000000000000000000000000000000000a20000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000000000000000000000000000000000006900000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000066000000000000000000000000000000000000000000000000000000000000007300000000000000000000000000000000000000000000000000000000000000580000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000017000000000000000000000000000000000000000000000000000000000000006e000000000000000000000000000000000000000000000000000000000000007e000000000000000000000000000000000000000000000000000000000000009500000000000000000000000000000000000000000000000000000000000000770000000000000000000000000000000000000000000000000000000000000062000000000000000000000000000000000000000000000000000000000000006c000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c200000000000000000000000000000000000000000000000000000000000000b500000000000000000000000000000000000000000000000000000000000000e4000000000000000000000000000000000000000000000000000000000000006d0000000000000000000000000000000000000000000000000000000000000069000000000000000000000000000000000000000000000000000000000000007700000000000000000000000000000000000000000000000000000000000000770000000000000000000000000000000000000000000000000000000000000036000000000000000000000000000000000000000000000000000000000000008d00000000000000000000000000000000000000000000000000000000000000aa000000000000000000000000000000000000000000000000000000000000003100000000000000000000000000000000000000000000000000000000000000a6000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000c600000000000000000000000000000000000000000000000000000000000000c300000000000000000000000000000000000000000000000000000000000000fd000000000000000000000000000000000000000000000000000000000000006c00000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000bb00000000000000000000000000000000000000000000000000000000000000c500000000000000000000000000000000000000000000000000000000000000bd000000000000000000000000000000000000000000000000000000000000004f000000000000000000000000000000000000000000000000000000000000008f000000000000000000000000000000000000000000000000000000000000002a00000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000073000000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000006c0000000000000000000000000000000000000000000000000000000000000063000000000000000000000000000000000000000000000000000000000000004300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000033"; + + // keccak of init_code should be 0xb91f1af43fc85861a7387def4ed8cc83894a0670b024458827bed13d552cc66f + // std::string init_code_str = "608060405234801561001057600080fd5b5060405161016838038061016883398181016040528101906100329190610054565b80600081905550506100a7565b60008151905061004e81610090565b92915050565b60006020828403121561006a5761006961008b565b5b60006100788482850161003f565b91505092915050565b6000819050919050565b600080fd5b61009981610081565b81146100a457600080fd5b50565b60b3806100b56000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c80630c55699c14602d575b600080fd5b60336047565b604051603e9190605a565b60405180910390f35b60005481565b6054816073565b82525050565b6000602082019050606d6000830184604d565b92915050565b600081905091905056fea26469706673582212204dd788e7581ff606469b19a0b4e5fd41a3ea60158d0668e73bf0b59cab258acd64736f6c63430008070033000000000000000000000000000000000000000000000000000000000000002d"; + // size_t size = init_code_str.size() / 2; + // uint8_t bytes[size]; + // hex_to_uint8(init_code_str, bytes); + // std::cout << "INIT_CODE: " << init_code_str << std::endl; + // auto keccak_output = ethash_keccak256( bytes, size ); + // std::cout << "KECCAK OUTPUT: " << to_hex(keccak_output) << std::endl; + + // char init_code_arr[1200]; + // hex2bin(init_code_input, init_code_arr); + // std::string init_code_str = init_code_arr; + + // unsigned char init_code_output[64]; + // SHA3_CTX init_code_ctx; + // keccak_init(&init_code_ctx); + // keccak_update( &init_code_ctx, (unsigned char*)init_code_str.c_str(), init_code_str.size() ); + // keccak_final(&init_code_ctx, init_code_output); + // for (size_t i = 0; i < 32; i++) { + // ss << std::hex << (machine::opcode)init_code_output[i]; + // } + + generate_create2_input("0000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000000", "00", "4d1a2e2bb4f88f0250f26ffff098b0b30b26bf38"); + generate_create2_input("deadbeef00000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000000", "00", "b928f69bb1d91cd65274e3c79d8986362984fda3"); + generate_create2_input("deadbeef00000000000000000000000000000000", "000000000000000000000000feed000000000000000000000000000000000000", "00", "d04116cdd17bebe565eb2422f2497e06cc1c9833"); + generate_create2_input("0000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000000", "deadbeef", "70f2b2914a2a4b783faefb75f459a580616fcb5e"); + generate_create2_input("00000000000000000000000000000000deadbeef", "00000000000000000000000000000000000000000000000000000000cafebabe", "deadbeef", "60f3f640a8508fc6a86d45Df051962668e1e8ac7"); + generate_create2_input("00000000000000000000000000000000deadbeef", "00000000000000000000000000000000000000000000000000000000cafebabe", "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef", "1d8bfdc5d46dc4f61d6b6115972536ebe6a8854c"); + generate_create2_input("0000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000000", "", "e33c0c7f7df4809055c3eba6c09cfe4baf1bd9e0"); + + // std::string hashed_init_code = ss.str(); + // ss.str(""); + // ss << leader << "5FD6eB55D12E759a21C09eF703fe0CBa1DC9d88D" << "1a40000000000000000000000000000000000000000000000000000000000045"; + // ss << hashed_init_code; + + // std::string sha3_input = ss.str(); + // ss.str(""); + + // unsigned char output[32]; + // SHA3_CTX ctx; + // keccak_init(&ctx); + // keccak_update( &ctx, (unsigned char*)sha3_input.c_str(), sha3_input.size() ); + // keccak_final(&ctx, output); + // for (size_t i = 0; i < 32; i++) { + // ss << std::hex << (machine::opcode)output[i]; + // } + // TODO XXX MAKE SURE CONVERSION TO ADDRESS_RIPEMD160 IN THE VM USES THE WALLET'S ADDRESS_RIPEMD160 RATHER THAN GENERATING IT + + std::string untrimmed_wallet_name = ss.str(); + // std::vector rlp_vec( untrimmed_wallet_name.begin(), untrimmed_wallet_name.end() ); + // std::string base58Str = fc::to_base58(rlp_vec); + // std::string rlp_address = base58Str.substr(base58Str.size() - 40); + + // return "XGT" + rlp_address; + + const std::string& address_ref = std::string(trimmed_wallet_name); + boost::multiprecision::uint256_t new_contract_wallet_address = address_to_uint256_t(address_ref); + + ss.str(""); + ss << new_contract_wallet_address << std::endl; + + return ss.str(); + } +}; + +const wallet_object& wallet_create(chain::database& _db, uint32_t nonce, std::string predetermined_en_wallet_name = "") { fc::ecc::private_key recovery_privkey = generate_random_private_key(); fc::ecc::public_key recovery_pubkey = recovery_privkey.get_public_key(); @@ -1225,11 +1437,12 @@ const wallet_object& wallet_create(chain::database& _db) std::vector recovery_pubkeys = {recovery_pubkey}; const auto& props = _db.get_dynamic_global_properties(); - string wallet_name = wallet_create_operation::get_wallet_name(recovery_pubkeys); + std::string wallet_name = wallet_create_operation::get_wallet_name(recovery_pubkeys); + // TODO Add en name to wallet create operation const wallet_object& wallet = _db.create< wallet_object >( [&]( wallet_object& w ) { - initialize_wallet_object( w, wallet_name, memo_pubkey, props, false /*mined*/, XGT_INIT_MINER_NAME, _db.get_hardfork() ); + initialize_wallet_object( w, wallet_name, memo_pubkey, props, false /*mined*/, XGT_INIT_MINER_NAME, _db.get_hardfork(), nonce, predetermined_en_wallet_name ); }); _db.create< account_authority_object >( [&]( account_authority_object& auth ) @@ -1252,17 +1465,22 @@ std::vector contract_invoke(chain::database& _db, wallet_name_typ wlog("contract_invoke another contract ${w}", ("w",contract_hash)); const auto& c = _db.get_contract(contract_hash); const std::string& caller_address_ref = std::string(caller); - const std::string& destination_address_ref = std::string(c.wallet); boost::multiprecision::uint256_t converted_caller = address_to_uint256_t(caller_address_ref); - boost::multiprecision::uint256_t converted_destination = address_to_uint256_t(destination_address_ref); + + auto r160 = fc::ripemd160::hash("D7ACd2a9FD159E69Bb102A1ca21C9a3e3A5F771B"); + + std::stringstream ss; + ss << std::hex << r160.str(); + boost::multiprecision::uint256_t x; + ss >> x; machine::message msg = { 0, 0, int64_t(energy), converted_caller, - converted_destination, + x, value, // TODO args size is inaccurate args.size() * 2, @@ -1276,7 +1494,7 @@ std::vector contract_invoke(chain::database& _db, wallet_name_typ const uint64_t block_difficulty = static_cast( _db.get_pow_summary_target() ); const uint64_t block_energylimit = 0; const uint64_t tx_energyprice = 0; - std::string tx_origin = caller; // TODO update this to + std::string tx_origin = caller; // TODO update this std::string block_coinbase = caller; // TODO update this to this block's miner machine::context ctx = { @@ -1324,7 +1542,7 @@ std::vector contract_invoke(chain::database& _db, wallet_name_typ // Transfer value (C_xfer) if callvalue != 0 // TODO XXX Value is dramatically adjusted for test purposes... - // Ethereum wei values are significantly larger than XGT g values + // Ethereum wei values are significantly smaller proportionally than XGT g values // 1 Ether = 1,000,000,000,000,000,000 wei // 1 XGT = 100,000,000 g if (value != 0) { @@ -1339,7 +1557,6 @@ std::vector contract_invoke(chain::database& _db, wallet_name_typ _db.adjust_balance( caller_wallet, -callvalue ); } - // TODO make return value public in machine wlog("contract_invoke return value ${w}", ("w",m.get_return_value())); return m.get_return_value(); } @@ -1348,7 +1565,7 @@ void contract_create_evaluator::do_apply( const contract_create_operation& op ) { wlog("!!!!!! contract_create owner ${w} code size ${y}", ("w",op.owner)("y",op.code.size())); - const auto& contract_wallet = wallet_create(_db); + const auto& contract_wallet = wallet_create(_db, 1); auto base_contract = _db.create< contract_object >( [&](contract_object& c) { @@ -1401,9 +1618,19 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type { std::stringstream ss; std::string message; - for (int i = 0; i < 32; i++) { - message += std::to_string(memory[i]); + std::string return_str; + for (size_t i = 0; i < memory.size(); i++) { + auto op = std::stoi(std::to_string(memory[i])); + std::cout << op << std::endl; + if (op < 16) + ss << "0"; + ss << std::hex << op; + std::cout << ss.str() << std::endl; } + message = ss.str(); + ss.str(""); + // SHOULD EQUAL ff#{en_address}1a40000000000000000000000000000000000000000000000000000000000045dcc46d1ba759dfe92ef5276dd4690465c85cb217de3af9892e0a1b976c37eb7a + std::cout << "SHA3 message input: " << message << std::endl; unsigned char output[32]; SHA3_CTX ctx; keccak_init(&ctx); @@ -1411,9 +1638,11 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type keccak_final(&ctx, output); for (size_t i = 0; i < 32; i++) { ss << std::hex << (machine::opcode)output[i]; + std::cout << std::hex << (machine::opcode)output[i] << std::endl; } - // std::string fin((char*)output, 32); - return ss.str(); + return_str = ss.str(); + std::cout << "RETURN STRING: " << return_str << std::endl; + return return_str; }; std::function< machine::big_word(machine::big_word) > get_balance = [&](machine::big_word address_ripemd160) -> machine::big_word @@ -1467,22 +1696,22 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type const wallet_name_type sender_address = _db.get_contract(contract_hash).wallet; const auto& caller_contract_wallet = _db.get_account(sender_address); - // TODO XXX Create wallet for contract - if (caller_contract_wallet.balance.amount.value >= value) { fc::ripemd160 new_contract_hash = generate_random_ripemd160(); - const wallet_object& contract_wallet_account = wallet_create(_db); + + std::string new_wallet_name = generate_rlp_wallet_name(std::string(sender_address), caller_contract_wallet.nonce); + + wallet_create(_db, 1, new_wallet_name); chain::contract_object base_contract = _db.create< contract_object >( [&](contract_object& c) { c.contract_hash = new_contract_hash; c.owner = sender_address; c.code = reinterpret_cast< std::vector& >(memory); - c.wallet = contract_wallet_account.name; + c.wallet = new_wallet_name; }); if (value != 0) { // TODO XXX value is set to be compatible with eth value, needs to be adjusted auto callvalue = asset( value, XGT_SYMBOL ); - // TODO this should be the calling contract's wallet _db.adjust_balance( caller_contract_wallet, -callvalue ); _db.adjust_balance( base_contract.wallet, callvalue ); } @@ -1517,10 +1746,17 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type co.code = result; }); - // Convert new contract's wallet address to uint256_t (big_word) const std::string& address_ref = std::string(deployed_contract.wallet); boost::multiprecision::uint256_t new_contract_wallet_address = address_to_uint256_t(address_ref); + _db.modify( caller_contract_wallet, [&]( wallet_object& acc ) + { + if (acc.nonce) + acc.nonce += 1; + else + acc.nonce = 1; + }); + return new_contract_wallet_address; } else { @@ -1531,10 +1767,9 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type std::function< std::pair< machine::word, std::vector >(machine::big_word, uint64_t, machine::big_word, std::vector) > contract_call = [&, caller, contract_hash](machine::big_word address, uint64_t energy, machine::big_word value, std::vector args) -> std::pair< machine::word, std::vector > { // TODO Implement call depth limit - // TODO Refactor get_account_by_ripemd160 flow -- uint256_t_to_ripemd160() std::stringstream ss; - ss << std::hex << address; - const address_ripemd160_type r160 = ss.str(); + + const address_ripemd160_type r160 = uint256_t_to_ripemd160(address); const wallet_object* ext_wallet = _db.find_account_by_ripemd160(r160); wallet_name_type ext_wallet_name; @@ -1561,58 +1796,117 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type return std::make_pair(0, std::vector()); } } - const contract_object* contract = _db.find_contract_by_wallet(ext_wallet_name); + const contract_object* ext_contract = _db.find_contract_by_wallet(ext_wallet_name); std::vector contract_return = {}; if (args.size() > 0) { - if (contract) { - const contract_storage_object* cs = _db.find_contract_storage(contract->contract_hash, owner); - map< fc::sha256, fc::sha256 > storage; - if (cs) - storage = cs->data; - else - storage = map< fc::sha256, fc::sha256 >(); - - contract_return = contract_invoke(_db, contract->owner, sender_address, contract->contract_hash, (uint64_t)value, energy, args, storage); - - if (cs != nullptr) { - _db.modify< contract_storage_object >(*cs, [&](contract_storage_object& cs) { - cs.contract = contract->contract_hash; - cs.caller = caller; - cs.data = storage; - }); - } - else { - _db.create< contract_storage_object >([&](contract_storage_object& cs) { - cs.contract = contract->contract_hash; - cs.caller = caller; - cs.data = storage; - }); - } - } else { - ss << std::hex << contract_create(args, value); - const address_ripemd160_type new_contract_r160 = ss.str(); + if (!ext_contract) { + const address_ripemd160_type new_contract_r160 = uint256_t_to_ripemd160( contract_create(args, 0) ); const wallet_object* new_contract_wallet = _db.find_account_by_ripemd160(new_contract_r160); ext_wallet_name = new_contract_wallet->name; + ext_contract = _db.find_contract_by_wallet(ext_wallet_name); + } + const contract_storage_object* cs = _db.find_contract_storage(ext_contract->contract_hash, owner); + map< fc::sha256, fc::sha256 > storage; + if (cs) + storage = cs->data; + else + storage = map< fc::sha256, fc::sha256 >(); + + contract_return = contract_invoke(_db, ext_contract->owner, sender_address, ext_contract->contract_hash, (uint64_t)value, energy, args, storage); + + if (cs != nullptr) { + _db.modify< contract_storage_object >(*cs, [&](contract_storage_object& cs) { + cs.contract = ext_contract->contract_hash; + cs.caller = caller; + cs.data = storage; + }); + } else { + _db.create< contract_storage_object >([&](contract_storage_object& cs) { + cs.contract = ext_contract->contract_hash; + cs.caller = caller; + cs.data = storage; + }); } } return std::make_pair(machine::word(1), contract_return); }; - std::function< std::vector(std::string, uint64_t, machine::big_word, std::vector) > contract_callcode = [&](std::string address, uint64_t energy, machine::big_word value, std::vector args) -> std::vector + std::function< std::pair< machine::word, std::vector >(machine::big_word, uint64_t, machine::big_word, std::vector) > contract_callcode = [&, caller, contract_hash](machine::big_word address, uint64_t energy, machine::big_word value, std::vector args) -> std::pair< machine::word, std::vector > { - // TODO - return std::vector(); + // TODO Implement call depth limit + std::stringstream ss; + + const address_ripemd160_type r160 = uint256_t_to_ripemd160(address); + const wallet_object* ext_wallet = _db.find_account_by_ripemd160(r160); + wallet_name_type ext_wallet_name; + + if (ext_wallet != nullptr) { + ext_wallet_name = ext_wallet->name; + } else { + // TODO Check energy before creating contract + ss << std::hex << contract_create(args, value); + const address_ripemd160_type new_r160 = ss.str(); + const wallet_object* new_wallet = _db.find_account_by_ripemd160(new_r160); + ext_wallet_name = new_wallet->name; + } + + const auto& caller_wallet = _db.get_account(caller); + + if (value != 0) { + if (caller_wallet.balance.amount.value >= value) { + // TODO XXX value is set to be compatible with eth value, needs to be adjusted + auto callvalue = asset( value, XGT_SYMBOL ); + _db.adjust_balance( caller, -callvalue ); + _db.adjust_balance( caller, callvalue ); + } else { + return std::make_pair(0, std::vector()); + } + } + const contract_object* ext_contract = _db.find_contract_by_wallet(ext_wallet_name); + + std::vector contract_return = {}; + + if (args.size() > 0) { + if (!ext_contract) { + const address_ripemd160_type new_contract_r160 = uint256_t_to_ripemd160( contract_create(args, 0) ); + const wallet_object* new_contract_wallet = _db.find_account_by_ripemd160(new_contract_r160); + ext_wallet_name = new_contract_wallet->name; + ext_contract = _db.find_contract_by_wallet(ext_wallet_name); + } + const contract_storage_object* cs = _db.find_contract_storage(contract_hash, caller); + map< fc::sha256, fc::sha256 > storage; + if (cs) + storage = cs->data; + else + storage = map< fc::sha256, fc::sha256 >(); + + contract_return = contract_invoke(_db, ext_contract->owner, caller, ext_contract->contract_hash, (uint64_t)value, energy, args, storage); + + if (cs != nullptr) { + _db.modify< contract_storage_object >(*cs, [&](contract_storage_object& cs) { + cs.contract = contract_hash; + cs.caller = caller; + cs.data = storage; + }); + } else { + _db.create< contract_storage_object >([&](contract_storage_object& cs) { + cs.contract = contract_hash; + cs.caller = caller; + cs.data = storage; + }); + } + } + return std::make_pair(machine::word(1), contract_return); }; - std::function< std::pair< machine::word, std::vector >(machine::big_word, uint64_t, std::vector) > contract_delegatecall = [&, owner](machine::big_word address, uint64_t energy, std::vector args) -> std::pair< machine::word, std::vector > + std::function< std::pair< machine::word, std::vector >(machine::big_word, uint64_t, std::vector) > contract_delegatecall = [&, caller, owner, contract_hash](machine::big_word address, uint64_t energy, std::vector args) -> std::pair< machine::word, std::vector > { // TODO Implement call depth limit - // TODO Refactor get_account_by_ripemd160 flow -- uint256_t_to_ripemd160() std::stringstream ss; - ss << std::hex << address; - const address_ripemd160_type r160 = ss.str(); + + const address_ripemd160_type r160 = uint256_t_to_ripemd160(address); const wallet_object* ext_wallet = _db.find_account_by_ripemd160(r160); wallet_name_type ext_wallet_name; @@ -1626,42 +1920,38 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type ext_wallet_name = new_wallet->name; } - const contract_object* contract = _db.find_contract_by_wallet(ext_wallet_name); + const contract_object* ext_contract = _db.find_contract_by_wallet(ext_wallet_name); std::vector contract_return = {}; if (args.size() > 0) { - if (contract) { - const contract_storage_object* cs = _db.find_contract_storage(contract->contract_hash, owner); - map< fc::sha256, fc::sha256 > storage; - if (cs) - storage = cs->data; - else - storage = map< fc::sha256, fc::sha256 >(); - - std::vector unsigned_args; - std::copy(args.begin(), args.end(), std::back_inserter(unsigned_args)); - contract_return = contract_invoke(_db, contract->owner, owner, contract->contract_hash, 0, energy, unsigned_args, storage); - - if (cs != nullptr) { - _db.modify< contract_storage_object >(*cs, [&](contract_storage_object& cs) { - cs.contract = contract->contract_hash; - cs.caller = caller; - cs.data = storage; - }); - } - else { - _db.create< contract_storage_object >([&](contract_storage_object& cs) { - cs.contract = contract->contract_hash; - cs.caller = caller; - cs.data = storage; - }); - } - } else { - ss << std::hex << contract_create(args, 0); - const address_ripemd160_type new_contract_r160 = ss.str(); + if (!ext_contract) { + const address_ripemd160_type new_contract_r160 = uint256_t_to_ripemd160( contract_create(args, 0) ); const wallet_object* new_contract_wallet = _db.find_account_by_ripemd160(new_contract_r160); ext_wallet_name = new_contract_wallet->name; + ext_contract = _db.find_contract_by_wallet(ext_wallet_name); + } + const contract_storage_object* cs = _db.find_contract_storage(contract_hash, caller); + map< fc::sha256, fc::sha256 > storage; + if (cs) + storage = cs->data; + else + storage = map< fc::sha256, fc::sha256 >(); + + contract_return = contract_invoke(_db, ext_contract->owner, caller, ext_contract->contract_hash, 0, energy, args, storage); + + if (cs != nullptr) { + _db.modify< contract_storage_object >(*cs, [&](contract_storage_object& cs) { + cs.contract = contract_hash; + cs.caller = caller; + cs.data = storage; + }); + } else { + _db.create< contract_storage_object >([&](contract_storage_object& cs) { + cs.contract = contract_hash; + cs.caller = caller; + cs.data = storage; + }); } } return std::make_pair(machine::word(1), contract_return); @@ -1670,8 +1960,8 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type std::function< std::pair< machine::word, std::vector >(machine::big_word, uint64_t, std::vector) > contract_staticcall = [&, owner, caller, contract_hash](machine::big_word address, uint64_t energy, std::vector args) -> std::pair< machine::word, std::vector > { std::stringstream ss; - ss << std::hex << address; - const address_ripemd160_type r160 = ss.str(); + + const address_ripemd160_type r160 = uint256_t_to_ripemd160(address); const wallet_object* ext_wallet = _db.find_account_by_ripemd160(r160); wallet_name_type ext_wallet_name; @@ -1685,37 +1975,35 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type } const wallet_name_type sender_address = _db.get_contract(contract_hash).wallet; - const contract_object* contract = _db.find_contract_by_wallet(ext_wallet_name); + const contract_object* ext_contract = _db.find_contract_by_wallet(ext_wallet_name); std::vector contract_return = {}; if (args.size() > 0) { - if (!contract) { - ss << std::hex << contract_create(args, 0); - const address_ripemd160_type new_contract_r160 = ss.str(); + if (!ext_contract) { + const address_ripemd160_type new_contract_r160 = uint256_t_to_ripemd160( contract_create(args, 0) ); const wallet_object* new_contract_wallet = _db.find_account_by_ripemd160(new_contract_r160); ext_wallet_name = new_contract_wallet->name; - contract = _db.find_contract_by_wallet(ext_wallet_name); + ext_contract = _db.find_contract_by_wallet(ext_wallet_name); } - const contract_storage_object* cs = _db.find_contract_storage(contract->contract_hash, owner); + const contract_storage_object* cs = _db.find_contract_storage(ext_contract->contract_hash, owner); map< fc::sha256, fc::sha256 > storage; if (cs) storage = cs->data; else storage = map< fc::sha256, fc::sha256 >(); - contract_return = contract_invoke(_db, contract->owner, sender_address, contract->contract_hash, 0, energy, args, storage); + contract_return = contract_invoke(_db, ext_contract->owner, sender_address, ext_contract->contract_hash, 0, energy, args, storage); if (cs != nullptr) { _db.modify< contract_storage_object >(*cs, [&](contract_storage_object& cs) { - cs.contract = contract->contract_hash; + cs.contract = ext_contract->contract_hash; cs.caller = caller; cs.data = storage; }); - } - else { + } else { _db.create< contract_storage_object >([&](contract_storage_object& cs) { - cs.contract = contract->contract_hash; + cs.contract = ext_contract->contract_hash; cs.caller = caller; cs.data = storage; }); @@ -1724,16 +2012,98 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type return std::make_pair(machine::word(1), contract_return); }; - std::function< machine::big_word(std::vector, machine::big_word, std::string) > contract_create2 = [&_db, owner](std::vector memory, machine::big_word value, std::string salt) -> machine::big_word + std::function< machine::big_word(std::vector, machine::big_word, machine::big_word) > contract_create2 = [&_db, sha3, owner, caller, contract_hash](std::vector memory, machine::big_word value, machine::big_word salt) -> machine::big_word { // TODO: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1014.md - chain::contract_object contract = _db.create< contract_object >( [&](contract_object& co) - { - //co.contract_hash = generate_random_ripemd160(); - co.owner = owner; - //co.code = memory; - }); - return 0; + const wallet_name_type sender_address = _db.get_contract(contract_hash).wallet; + const auto& caller_contract_wallet = _db.get_account(sender_address); + + // TODO XXX Create wallet for contract + + if (caller_contract_wallet.balance.amount.value >= value) { + fc::ripemd160 new_contract_hash = generate_random_ripemd160(); + + std::stringstream ss; + ss << salt; + std::string salt_str = ss.str(); + + std::string new_rlp_wallet_name = generate_rlp_wallet_name(std::string(sender_address), caller_contract_wallet.nonce, salt_str, memory); + std::cout << "NEW RLP WALLET NAME: " << new_rlp_wallet_name << std::endl; + + wallet_create(_db, caller_contract_wallet.nonce, new_rlp_wallet_name); + + const auto& new_wallet_name = _db.get_account_by_ripemd160(new_rlp_wallet_name).name; + + chain::contract_object base_contract = _db.create< contract_object >( [&](contract_object& c) { + c.contract_hash = new_contract_hash; + c.owner = sender_address; + c.code = reinterpret_cast< std::vector& >(memory); + c.wallet = new_wallet_name; + }); + + if (value != 0) { + // TODO XXX value is set to be compatible with eth value, needs to be adjusted + auto callvalue = asset( value, XGT_SYMBOL ); + // TODO this should be the calling contract's wallet + _db.adjust_balance( caller_contract_wallet, -callvalue ); + _db.adjust_balance( base_contract.wallet, callvalue ); + } + + const contract_storage_object* cs = _db.find_contract_storage(new_contract_hash, sender_address); + + map< fc::sha256, fc::sha256 > storage; + if (cs != nullptr) { + storage = cs->data; + } + else { + storage = map< fc::sha256, fc::sha256 >(); + } + + _db.create< contract_storage_object >([&](contract_storage_object& cs) { + cs.contract = new_contract_hash; + cs.caller = sender_address; + cs.data = storage; + }); + + // TODO Exceptions should occupy return_value in the case of contract invoke failure (result == 0) + std::vector base_contract_return = contract_invoke(_db, owner, sender_address, new_contract_hash, 0, 0, {}, storage); + std::vector result(base_contract_return.begin(), base_contract_return.end()); + + cs = _db.find_contract_storage(new_contract_hash, sender_address); + _db.modify< contract_storage_object >(*cs, [&](contract_storage_object& cs) { + cs.data = storage; + }); + + const auto& deployed_contract = _db.get_contract(new_contract_hash); + _db.modify< contract_object >(deployed_contract, [&](contract_object& co) { + co.code = result; + }); + + const std::string& address_ref = std::string(new_rlp_wallet_name); + + std::cout << "Address ref: " << address_ref << std::endl; + + ss.str(""); + ss << std::hex << address_ref; + boost::multiprecision::uint256_t x; + ss >> x; + boost::multiprecision::uint256_t new_contract_wallet_address = x; + + _db.modify( caller_contract_wallet, [&]( wallet_object& acc ) + { + if (acc.nonce) + acc.nonce = acc.nonce + 1; + else + acc.nonce = 1; + }); + + std::cout << "NEW CONTRACT WALLET ADDRESS: " << new_contract_wallet_address << std::endl; + + return new_contract_wallet_address; + } + else { + return 0; + } }; std::function< bool(std::vector) > revert = [&](std::vector memory) -> bool diff --git a/libraries/fc/include/fc/crypto/ripemd160.hpp b/libraries/fc/include/fc/crypto/ripemd160.hpp index 3235e4bc..73dc82c8 100644 --- a/libraries/fc/include/fc/crypto/ripemd160.hpp +++ b/libraries/fc/include/fc/crypto/ripemd160.hpp @@ -26,7 +26,7 @@ class ripemd160 static ripemd160 hash( const char* d, uint32_t dlen ); static ripemd160 hash( const string& ); static string hex_digest( const string wallet_name ); - static string uint256_t_digest( const string wallet_name ); + static boost::multiprecision::uint256_t uint256_t_digest( const string wallet_name ); template static ripemd160 hash( const T& t ) diff --git a/libraries/fc/vendor/rlpvalue b/libraries/fc/vendor/rlpvalue new file mode 160000 index 00000000..1e58dcec --- /dev/null +++ b/libraries/fc/vendor/rlpvalue @@ -0,0 +1 @@ +Subproject commit 1e58dcec547dd19da4c325344d6f363d533dabe0 diff --git a/libraries/plugins/apis/contract_api/contract_api.cpp b/libraries/plugins/apis/contract_api/contract_api.cpp index 9b17eb3b..81ee1aed 100644 --- a/libraries/plugins/apis/contract_api/contract_api.cpp +++ b/libraries/plugins/apis/contract_api/contract_api.cpp @@ -78,8 +78,8 @@ DEFINE_API_IMPL( contract_api_impl, list_owner_contracts ) std::stringstream ss; ss << std::hex << r160.str(); - std::string en_address; - ss >> en_address; + std::string address_ripemd160; + ss >> address_ripemd160; api_contract_object ac; ac.id = c.id; @@ -87,7 +87,7 @@ DEFINE_API_IMPL( contract_api_impl, list_owner_contracts ) ac.contract_hash = c.contract_hash; ac.wallet = c.wallet; ac.code = c.code; - ac.en_address = en_address; + ac.address_ripemd160 = address_ripemd160; result.contracts.push_back(ac); ++itr; } diff --git a/libraries/plugins/apis/contract_api/include/xgt/plugins/contract_api/contract_api.hpp b/libraries/plugins/apis/contract_api/include/xgt/plugins/contract_api/contract_api.hpp index 596bc631..1471be34 100644 --- a/libraries/plugins/apis/contract_api/include/xgt/plugins/contract_api/contract_api.hpp +++ b/libraries/plugins/apis/contract_api/include/xgt/plugins/contract_api/contract_api.hpp @@ -19,7 +19,7 @@ struct api_contract_object chain::wallet_name_type owner; chain::wallet_name_type wallet; chain::contract_hash_type contract_hash; - std::string en_address; + std::string address_ripemd160; vector code; }; @@ -69,7 +69,7 @@ FC_REFLECT( xgt::plugins::contract::api_contract_object, (wallet) (contract_hash) (code) - (en_address) ) + (address_ripemd160) ) FC_REFLECT( xgt::plugins::contract::get_contract_args, (contract_hash) ) FC_REFLECT( xgt::plugins::contract::get_contract_return, (contract) ) diff --git a/libraries/vendor/xgtvm/libraries/machine.cpp b/libraries/vendor/xgtvm/libraries/machine.cpp index 070106db..12e79620 100644 --- a/libraries/vendor/xgtvm/libraries/machine.cpp +++ b/libraries/vendor/xgtvm/libraries/machine.cpp @@ -492,20 +492,24 @@ namespace machine // TODO handle case where length of memory segment is 0, stack needs a 0 pushed - for (size_t i = static_cast(va); i < static_cast(va) + static_cast(vb); i++) { - std::map::iterator it; - it = memory.find(i); - if (it != memory.end()) { - retval.push_back(it->second); - } - else { - retval.push_back(word(0)); + if (vb == 0) { + push_word(0); + } else { + for (size_t i = static_cast(va); i < static_cast(va) + static_cast(vb); i++) { + std::map::iterator it; + it = memory.find(i); + if (it != memory.end()) { + retval.push_back(it->second); + } + else { + retval.push_back(word(0)); + } } - } - sstream << std::hex << adapter.sha3( retval ); - sstream >> vc; - push_word( vc ); // hash + sstream << std::hex << adapter.sha3( retval ); + sstream >> vc; + push_word( vc ); // hash + } break; case address_opcode: @@ -2757,41 +2761,34 @@ namespace machine logger << "op callcode" << std::endl; va = pop_word(); // energy - sv = stack.front(); // addr - ss = boost::get(&sv); - if (ss) - { - stack.pop_front(); - vb = pop_word(); // value - vc = pop_word(); // argsOffset - vd = pop_word(); // argsLength - ve = pop_word(); // retOffset - vf = pop_word(); // retLength + vb = pop_word(); // address + vc = pop_word(); // value + vd = pop_word(); // argsOffset + ve = pop_word(); // argsLength + vf = pop_word(); // retOffset + vg = pop_word(); // retLength - for (size_t i = static_cast(vc); i < static_cast(vd); i++) { - std::map::iterator it; - it = memory.find(i); - if (it != memory.end()) { - contract_args.push_back(it->second); - } - else { - contract_args.push_back(word(0)); - } + for (size_t i = static_cast(vd); i < static_cast(vd) + static_cast(ve); i++) { + std::map::iterator it; + it = memory.find(i); + if (it != memory.end()) { + contract_args.push_back(it->second); } + else { + contract_args.push_back(word(0)); + } + } - std::vector contract_callcode_return = adapter.contract_callcode(*ss, static_cast(va), vb, contract_args); + contract_call_return = adapter.contract_callcode(vb, static_cast(va), vc, contract_args); - for (size_t i = 0; i < static_cast(vf); i++) - memory[static_cast(ve) + i] = contract_callcode_return[i]; + if (contract_call_return.second.size() > 0) { + ext_return_data = contract_call_return.second; - // TODO revise stack return value? - push_word("Success"); // success - } - else { - push_word("Failure"); // success - state = machine_state::error; - error_message.emplace("Callcode operation type error"); + for (size_t i = 0; i < static_cast(vf); i++) + memory[static_cast(ve) + i] = contract_call_return.second[i]; } + + push_word(big_word(contract_call_return.first)); break; case return_opcode: logger << "op return" << std::endl; @@ -2862,30 +2859,26 @@ namespace machine va = pop_word(); // value vb = pop_word(); // offset vc = pop_word(); // length + vd = pop_word(); // salt - sv = stack.front(); // salt - ss = boost::get(&sv); - if (ss) - { - std::vector args; - - for (size_t i = static_cast(vb); i < static_cast(vc); i++) { - std::map::iterator it; - it = memory.find(i); - if (it != memory.end()) { - args.push_back(it->second); + for (size_t i = static_cast(vb); i < static_cast(vb) + static_cast(vc); i++) { + std::map::iterator it; + it = memory.find(i); + if (it != memory.end()) { + for (size_t i = 0; i < 31; i++) { + contract_args.push_back(word(0)); } - else { - args.push_back(word(0)); + contract_args.push_back(it->second); + } + else { + for (size_t i = 0; i < 32; i++) { + contract_args.push_back(word(0)); } } - - push_word( adapter.contract_create2( args, va, *ss ) ); - } - else { - state = machine_state::error; - error_message.emplace("Create2 operation type error"); } + + push_word( adapter.contract_create2( contract_args, va, vd ) ); + break; case staticcall_opcode: logger << "op staticcall" << std::endl; @@ -3020,9 +3013,13 @@ namespace machine } s << "\","; - word current_instruction = code[pc]; - opcode op = (opcode)current_instruction; - s << "\"opcode\":" << std::hex << op << ","; + if (code.size() != 0) { + word current_instruction = code[pc]; + opcode op = (opcode)current_instruction; + s << "\"opcode\":" << std::hex << op << ","; + } else { + s << "\"opcode\":null,"; + } if (error_message == boost::none) s << "\"exceptionError\":" << "null"; diff --git a/libraries/vendor/xgtvm/libraries/machine.hpp b/libraries/vendor/xgtvm/libraries/machine.hpp index e57deb8e..16452a48 100644 --- a/libraries/vendor/xgtvm/libraries/machine.hpp +++ b/libraries/vendor/xgtvm/libraries/machine.hpp @@ -242,7 +242,7 @@ namespace machine std::function< std::pair< word, std::vector >(big_word, uint64_t, big_word, std::vector) > contract_call; // TODO call a method from another contract(?) -- callcode opcode -- address, energy, value, args - std::function< std::vector(std::string, uint64_t, big_word, std::vector) > contract_callcode; + std::function< std::pair< word, std::vector >(big_word, uint64_t, big_word, std::vector) > contract_callcode; // TODO call a method from another contract using the storage of the current // opcode -- delegatecall opcode -- address, energy, args @@ -252,7 +252,7 @@ namespace machine std::function< std::pair< word, std::vector >(big_word, uint64_t, std::vector) > contract_staticcall; // TODO creates a child contract -- create2 opcode - std::function< big_word(std::vector, big_word, std::string) > contract_create2; + std::function< big_word(std::vector, big_word, big_word) > contract_create2; // TODO revert opcode std::function< bool(std::vector) > revert; diff --git a/libraries/vendor/xgtvm/programs/xgtvm.cpp b/libraries/vendor/xgtvm/programs/xgtvm.cpp index 4df85086..fd6a33d0 100644 --- a/libraries/vendor/xgtvm/programs/xgtvm.cpp +++ b/libraries/vendor/xgtvm/programs/xgtvm.cpp @@ -90,7 +90,7 @@ machine::chain_adapter make_chain_adapter() return {}; }; - std::function< std::vector(std::string, uint64_t, machine::big_word, std::vector) > contract_callcode = [](std::string address, uint64_t energy, machine::big_word value, std::vector args) -> std::vector + std::function< std::pair< machine::word, std::vector >(machine::big_word, uint64_t, machine::big_word, std::vector) > contract_callcode = [](machine::big_word address, uint64_t energy, machine::big_word value, std::vector args) -> std::pair< machine::word, std::vector > { return {}; }; @@ -105,7 +105,7 @@ machine::chain_adapter make_chain_adapter() return {}; }; - std::function< machine::big_word(std::vector, machine::big_word, std::string) > contract_create2 = [](std::vector memory, machine::big_word value, std::string salt) -> machine::big_word + std::function< machine::big_word(std::vector, machine::big_word, machine::big_word) > contract_create2 = [](std::vector memory, machine::big_word value, machine::big_word salt) -> machine::big_word { return {}; }; diff --git a/libraries/vendor/xgtvm/programs/xgtvm_tests.cpp b/libraries/vendor/xgtvm/programs/xgtvm_tests.cpp index f39e70d0..cac11934 100644 --- a/libraries/vendor/xgtvm/programs/xgtvm_tests.cpp +++ b/libraries/vendor/xgtvm/programs/xgtvm_tests.cpp @@ -53,7 +53,7 @@ machine::chain_adapter make_chain_adapter() return {}; }; - std::function< std::vector(std::string, uint64_t, machine::big_word, std::vector) > contract_callcode = [](std::string address, uint64_t energy, machine::big_word value, std::vector args) -> std::vector + std::function< std::pair< machine::word, std::vector >(machine::big_word, uint64_t, machine::big_word, std::vector) > contract_callcode = [](machine::big_word address, uint64_t energy, machine::big_word value, std::vector args) -> std::pair< machine::word, std::vector > { std::cout << "chain_adapter::contract_callcode" << std::endl; return {}; @@ -71,7 +71,7 @@ machine::chain_adapter make_chain_adapter() return {}; }; - std::function< machine::big_word(std::vector, machine::big_word, std::string) > contract_create2 = [](std::vector memory, machine::big_word value, std::string salt) -> machine::big_word + std::function< machine::big_word(std::vector, machine::big_word, machine::big_word) > contract_create2 = [](std::vector memory, machine::big_word value, machine::big_word salt) -> machine::big_word { std::cout << "chain_adapter::contract_create2" << std::endl; return {}; diff --git a/tasks/contracts.rake b/tasks/contracts.rake index fe613617..9391a65b 100644 --- a/tasks/contracts.rake +++ b/tasks/contracts.rake @@ -1,5 +1,30 @@ require 'digest' +def transfer_xgt(from, to, amount) + txn = { + 'extensions' => [], + 'operations' => [ + { + 'type' => 'transfer_operation', + 'value' => { + 'amount' => { + 'amount' => amount.to_s, + 'precision' => 8, + 'nai' => '@@000000021' + }, + 'from' => from, + 'to' => to, + 'json_metadata' => '', + 'extensions' => [] + } + } + ] + } + + id = rpc.broadcast_transaction(txn, [wif], chain_id) + (puts 'Waiting...' or sleep 1) until rpc.transaction_ready?(id) +end + def create_contract!(owner, keys, code, private_key = wif) txn = { 'extensions' => [], @@ -143,30 +168,6 @@ namespace :contracts do desc 'Basic lottery contract' task :basic_lottery do - def transfer_xgt(from, to, amount) - txn = { - 'extensions' => [], - 'operations' => [ - { - 'type' => 'transfer_operation', - 'value' => { - 'amount' => { - 'amount' => amount.to_s, - 'precision' => 8, - 'nai' => '@@000000021' - }, - 'from' => from, - 'to' => to, - 'json_metadata' => '', - 'extensions' => [] - } - } - ] - } - - id = rpc.broadcast_transaction(txn, [wif], chain_id) - (puts 'Waiting...' or sleep 1) until rpc.transaction_ready?(id) - end def get_wallet(address) response = rpc.call('database_api.find_wallets', { 'wallets' => [address] }) @@ -283,20 +284,23 @@ namespace :contracts do creator = create_wallet!(creator_keys) contract_keys = generate_keys + transfer_xgt(xgt_wallet_0, creator, 20_000_000) + create_wallet!(contract_keys) sleep(2) code = %(608060405260046040516100129061008a565b80828152602001915050604051809103906000f080158015610038573d6000803e3d6000fd5b506000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555034801561008457600080fd5b50610096565b60d0806103d683390190565b610331806100a56000396000f3fe6080604052600436106100295760003560e01c80638dcd64cc1461002e57806395fe0e6514610066575b600080fd5b6100646004803603604081101561004457600080fd5b8101908080359060200190929190803590602001909291905050506100a1565b005b34801561007257600080fd5b5061009f6004803603602081101561008957600080fd5b8101908080359060200190929190505050610162565b005b600081836040516100b190610220565b808281526020019150506040518091039082f0801580156100d6573d6000803e3d6000fd5b50905090508073ffffffffffffffffffffffffffffffffffffffff16630c55699c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561012157600080fd5b505afa158015610135573d6000803e3d6000fd5b505050506040513d602081101561014b57600080fd5b810190808051906020019092919050505050505050565b60008160405161017190610220565b80828152602001915050604051809103906000f080158015610197573d6000803e3d6000fd5b5090508073ffffffffffffffffffffffffffffffffffffffff16630c55699c6040518163ffffffff1660e01b815260040160206040518083038186803b1580156101e057600080fd5b505afa1580156101f4573d6000803e3d6000fd5b505050506040513d602081101561020a57600080fd5b8101908080519060200190929190505050505050565b60d08061022d8339019056fe60806040526040516100d03803806100d083398181016040526020811015602557600080fd5b8101908080519060200190929190505050806000819055505060848061004c6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c80630c55699c14602d575b600080fd5b60336049565b6040518082815260200191505060405180910390f35b6000548156fea265627a7a723158203e3e89f6c037d9933d5bdef0a2770bf1f37edb6a783aa6541fa6959d9e3dc29364736f6c63430005110032a265627a7a72315820a054097388070f7dcd34b458b35e036d10e3f9defdd31fc4e1d4df5f83232c7564736f6c6343000511003260806040526040516100d03803806100d083398181016040526020811015602557600080fd5b8101908080519060200190929190505050806000819055505060848061004c6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c80630c55699c14602d575b600080fd5b60336049565b6040518082815260200191505060405180910390f35b6000548156fea265627a7a723158203e3e89f6c037d9933d5bdef0a2770bf1f37edb6a783aa6541fa6959d9e3dc29364736f6c63430005110032) + stripped_code = %(6080604052600436106100295760003560e01c80638dcd64cc1461002e57806395fe0e6514610066575b600080fd5b6100646004803603604081101561004457600080fd5b8101908080359060200190929190803590602001909291905050506100a1565b005b34801561007257600080fd5b5061009f6004803603602081101561008957600080fd5b8101908080359060200190929190505050610162565b005b600081836040516100b190610220565b808281526020019150506040518091039082f0801580156100d6573d6000803e3d6000fd5b50905090508073ffffffffffffffffffffffffffffffffffffffff16630c55699c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561012157600080fd5b505afa158015610135573d6000803e3d6000fd5b505050506040513d602081101561014b57600080fd5b810190808051906020019092919050505050505050565b60008160405161017190610220565b80828152602001915050604051809103906000f080158015610197573d6000803e3d6000fd5b5090508073ffffffffffffffffffffffffffffffffffffffff16630c55699c6040518163ffffffff1660e01b815260040160206040518083038186803b1580156101e057600080fd5b505afa1580156101f4573d6000803e3d6000fd5b505050506040513d602081101561020a57600080fd5b8101908080519060200190929190505050505050565b60d08061022d8339019056fe60806040526040516100d03803806100d083398181016040526020811015602557600080fd5b8101908080519060200190929190505050806000819055505060848061004c6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c80630c55699c14602d575b600080fd5b60336049565b6040518082815260200191505060405180910390f35b6000548156fea265627a7a723158203e3e89f6c037d9933d5bdef0a2770bf1f37edb6a783aa6541fa6959d9e3dc29364736f6c63430005110032a265627a7a72315820a054097388070f7dcd34b458b35e036d10e3f9defdd31fc4e1d4df5f83232c7564736f6c6343000511003260806040526040516100d03803806100d083398181016040526020811015602557600080fd5b8101908080519060200190929190505050806000819055505060848061004c6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c80630c55699c14602d575b600080fd5b60336049565b6040518082815260200191505060405180910390f35b6000548156fea265627a7a723158203e3e89f6c037d9933d5bdef0a2770bf1f37edb6a783aa6541fa6959d9e3dc29364736f6c63430005110032) create_contract!(creator, contract_keys, code, creator_keys['recovery_private']) sleep(2) response = rpc.call('contract_api.list_owner_contracts', { 'owner' => creator }) || {} p response - contract_hash = response['contracts'].first['contract_hash'] + contract_hash = response['contracts'].kind_of?(Array) ? response['contracts'].first['contract_hash'] : response['contracts'].select { |contract| contract['code'] == stripped_code}.first['contract_hash'] - invoke_contract!(contract_hash, creator, 0, '95fe0e650000000000000000000000000000000000000000000000000000000000000001') + invoke_contract!(contract_hash, creator, 00000000000000000, '95fe0e650000000000000000000000000000000000000000000000000000000000000001') response = rpc.call('contract_api.list_owner_contracts', { 'owner' => creator }) || {} puts "Creator contracts: \n\n\n" @@ -309,6 +313,7 @@ namespace :contracts do puts JSON.pretty_generate response end + desc 'Create and execute contract which uses delegatecall opcode' task :delegatecall do xgt_wallet_0 = 'XGT0000000000000000000000000000000000000000' @@ -348,32 +353,72 @@ namespace :contracts do # Calling contract aka machine machine_code = %(608060405234801561001057600080fd5b50600080819055506107d1806100276000396000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c806386b714e21161005b57806386b714e2146101085780639b7e450c14610152578063c14731ca146101be578063f98f34d8146102045761007d565b806320965255146100825780634f8632ba146100a05780636e008b35146100ea575b600080fd5b61008a610270565b6040518082815260200191505060405180910390f35b6100a861031a565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6100f2610340565b6040518082815260200191505060405180910390f35b610110610346565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6101a86004803603606081101561016857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019092919050505061036c565b6040518082815260200191505060405180910390f35b6101ea600480360360208110156101d457600080fd5b8101908080359060200190929190505050610537565b604051808215151515815260200191505060405180910390f35b61025a6004803603606081101561021a57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803590602001909291905050506105cf565b6040518082815260200191505060405180910390f35b6000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16633c6bb4366040518163ffffffff1660e01b815260040160206040518083038186803b1580156102da57600080fd5b505afa1580156102ee573d6000803e3d6000fd5b505050506040513d602081101561030457600080fd5b8101908080519060200190929190505050905090565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60005481565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008060608573ffffffffffffffffffffffffffffffffffffffff16858560405160240180838152602001828152602001925050506040516020818303038152906040527f771602f7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040518082805190602001908083835b60208310610451578051825260208201915060208101905060208303925061042e565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855af49150503d80600081146104b1576040519150601f19603f3d011682016040523d82523d6000602084013e6104b6565b606091505b50915091507fb3cc7c40ae5fe031ec021a55a5c5cbddcb0837657bfaa8e8249801f67f7296458585846040518084815260200183815260200182151515158152602001935050505060405180910390a180806020019051602081101561051b57600080fd5b8101908080519060200190929190505050925050509392505050565b6000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166355241077836040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b1580156105ae57600080fd5b505af11580156105c2573d6000803e3d6000fd5b5050505060019050919050565b60008060608573ffffffffffffffffffffffffffffffffffffffff16858560405160240180838152602001828152602001925050506040516020818303038152906040527f771602f7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040518082805190602001908083835b602083106106b45780518252602082019150602081019050602083039250610691565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114610716576040519150601f19603f3d011682016040523d82523d6000602084013e61071b565b606091505b50915091507f81f50033f40bab548b88ccfd816202734d9325c0718e0395b473afe5454d599e8585846040518084815260200183815260200182151515158152602001935050505060405180910390a180806020019051602081101561078057600080fd5b810190808051906020019092919050505092505050939250505056fea265627a7a72315820a7fa96064b10ab27cbf9ae8932450561f061b789db57f9413d7820936dfcd47b64736f6c63430005110032) + stripped_machine_code = %(608060405234801561001057600080fd5b506004361061007d5760003560e01c806386b714e21161005b57806386b714e2146101085780639b7e450c14610152578063c14731ca146101be578063f98f34d8146102045761007d565b806320965255146100825780634f8632ba146100a05780636e008b35146100ea575b600080fd5b61008a610270565b6040518082815260200191505060405180910390f35b6100a861031a565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6100f2610340565b6040518082815260200191505060405180910390f35b610110610346565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6101a86004803603606081101561016857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019092919050505061036c565b6040518082815260200191505060405180910390f35b6101ea600480360360208110156101d457600080fd5b8101908080359060200190929190505050610537565b604051808215151515815260200191505060405180910390f35b61025a6004803603606081101561021a57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803590602001909291905050506105cf565b6040518082815260200191505060405180910390f35b6000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16633c6bb4366040518163ffffffff1660e01b815260040160206040518083038186803b1580156102da57600080fd5b505afa1580156102ee573d6000803e3d6000fd5b505050506040513d602081101561030457600080fd5b8101908080519060200190929190505050905090565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60005481565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008060608573ffffffffffffffffffffffffffffffffffffffff16858560405160240180838152602001828152602001925050506040516020818303038152906040527f771602f7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040518082805190602001908083835b60208310610451578051825260208201915060208101905060208303925061042e565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855af49150503d80600081146104b1576040519150601f19603f3d011682016040523d82523d6000602084013e6104b6565b606091505b50915091507fb3cc7c40ae5fe031ec021a55a5c5cbddcb0837657bfaa8e8249801f67f7296458585846040518084815260200183815260200182151515158152602001935050505060405180910390a180806020019051602081101561051b57600080fd5b8101908080519060200190929190505050925050509392505050565b6000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166355241077836040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b1580156105ae57600080fd5b505af11580156105c2573d6000803e3d6000fd5b5050505060019050919050565b60008060608573ffffffffffffffffffffffffffffffffffffffff16858560405160240180838152602001828152602001925050506040516020818303038152906040527f771602f7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040518082805190602001908083835b602083106106b45780518252602082019150602081019050602083039250610691565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114610716576040519150601f19603f3d011682016040523d82523d6000602084013e61071b565b606091505b50915091507f81f50033f40bab548b88ccfd816202734d9325c0718e0395b473afe5454d599e8585846040518084815260200183815260200182151515158152602001935050505060405180910390a180806020019051602081101561078057600080fd5b810190808051906020019092919050505092505050939250505056fea265627a7a72315820a7fa96064b10ab27cbf9ae8932450561f061b789db57f9413d7820936dfcd47b64736f6c63430005110032) create_contract!(creator, machine_keys, machine_code, creator_keys['recovery_private']) puts "Created machine contract" sleep(2) + # Refer to https://docs.soliditylang.org/en/develop/abi-spec.html#function-selector-and-argument-encoding + # for rules around argument encoding and calling functions + # Values to be added together - val1 = "00000000000000000000000000000001" - val2 = "00000000000000000000000000000002" + val1 = "0000000000000000000000000000000000000000000000000000000000000003" + val2 = "0000000000000000000000000000000000000000000000000000000000000004" response = rpc.call('contract_api.list_owner_contracts', { 'owner' => creator }) || {} + puts "\n\n\n\n" puts machine_keys['wallet_name'] puts "\n\n\n\n" puts JSON.pretty_generate response contract_hash = response['contracts'].first['contract_hash'] - calculator_contract_address = response['contracts'].select { |contract| contract['code'] == stripped_calculator_code}.first['en_address'] + calculator_contract_address = response['contracts'].select { |contract| contract['code'] == stripped_calculator_code}.first['address_ripemd160'] packed_calculator_contract_address = "000000000000000000000000#{calculator_contract_address}" puts "\n\nCalculator contract address: ", calculator_contract_address, "\n" puts "\nContract args: 9b7e450c#{calculator_contract_address}#{val1}#{val2}\n\n" + contract_hash = response['contracts'].select { |contract| contract['code'] == stripped_machine_code}.first['contract_hash'] + # Invoke contract with packed address (2 32-byte words) and args for addValuesWithDelegateCall invoke_contract!(contract_hash, creator, 0, "9b7e450c#{packed_calculator_contract_address}#{val1}#{val2}") puts "Invoked machine contract" end + + desc 'Create and execute contract which uses create2 opcode' + task :create2 do + # Create wallets for each contract + creator_keys = generate_keys + creator = create_wallet!(creator_keys) + + create2_keys = generate_keys + create2 = create_wallet!(create2_keys) + + sleep(2) + + puts "Wallets created" + + # Create contract to execute create2 + create2_code = %(608060405234801561001057600080fd5b506105c9806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c80630bd38f2f14610030575b600080fd5b61004a60048036038101906100459190610181565b61004c565b005b600060ff60f81b3084604051806020016100659061014a565b6020820181038252601f19601f820116604052508560405160200161008b9291906102ab565b604051602081830303815290604052805190602001206040516020016100b4949392919061025d565b6040516020818303038152906040528051906020012060001c9050600083836040516100df9061014a565b6100e991906102d3565b8190604051809103906000f5905080158015610109573d6000803e3d6000fd5b5090508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161461014457600080fd5b50505050565b6101688061042c83390190565b600081359050610166816103fd565b92915050565b60008135905061017b81610414565b92915050565b60008060408385031215610198576101976103eb565b5b60006101a685828601610157565b92505060206101b78582860161016c565b9150509250929050565b6101d26101cd82610304565b6103a9565b82525050565b6101e96101e482610316565b6103bb565b82525050565b6102006101fb82610342565b6103c5565b82525050565b6000610211826102ee565b61021b81856102f9565b935061022b818560208601610376565b80840191505092915050565b6102408161036c565b82525050565b6102576102528261036c565b6103e1565b82525050565b600061026982876101d8565b60018201915061027982866101c1565b60148201915061028982856101ef565b60208201915061029982846101ef565b60208201915081905095945050505050565b60006102b78285610206565b91506102c38284610246565b6020820191508190509392505050565b60006020820190506102e86000830184610237565b92915050565b600081519050919050565b600081905092915050565b600061030f8261034c565b9050919050565b60007fff0000000000000000000000000000000000000000000000000000000000000082169050919050565b6000819050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60005b83811015610394578082015181840152602081019050610379565b838111156103a3576000848401525b50505050565b60006103b4826103cf565b9050919050565b6000819050919050565b6000819050919050565b60006103da826103f0565b9050919050565b6000819050919050565b600080fd5b60008160601b9050919050565b61040681610342565b811461041157600080fd5b50565b61041d8161036c565b811461042857600080fd5b5056fe608060405234801561001057600080fd5b5060405161016838038061016883398181016040528101906100329190610054565b80600081905550506100a7565b60008151905061004e81610090565b92915050565b60006020828403121561006a5761006961008b565b5b60006100788482850161003f565b91505092915050565b6000819050919050565b600080fd5b61009981610081565b81146100a457600080fd5b50565b60b3806100b56000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c80630c55699c14602d575b600080fd5b60336047565b604051603e9190605a565b60405180910390f35b60005481565b6054816073565b82525050565b6000602082019050606d6000830184604d565b92915050565b600081905091905056fea2646970667358221220176e7e9577626c01c2b5e46d697777368daa31a61ac6c3fd6cc0bbc5bd4f8f2a64736f6c63430008070033a26469706673582212207eeeb4606f11d013f69f6590f362ffeb0f059f2c641869e03b23a03eb30252f264736f6c63430008070033) + create_contract!(creator, create2_keys, create2_code, creator_keys['recovery_private']) + + puts "Created create2 contract" + + response = rpc.call('contract_api.list_owner_contracts', { 'owner' => creator }) || {} + + stripped_create2_code = %(608060405234801561001057600080fd5b506004361061002b5760003560e01c80630bd38f2f14610030575b600080fd5b61004a60048036038101906100459190610181565b61004c565b005b600060ff60f81b3084604051806020016100659061014a565b6020820181038252601f19601f820116604052508560405160200161008b9291906102ab565b604051602081830303815290604052805190602001206040516020016100b4949392919061025d565b6040516020818303038152906040528051906020012060001c9050600083836040516100df9061014a565b6100e991906102d3565b8190604051809103906000f5905080158015610109573d6000803e3d6000fd5b5090508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161461014457600080fd5b50505050565b6101688061042c83390190565b600081359050610166816103fd565b92915050565b60008135905061017b81610414565b92915050565b60008060408385031215610198576101976103eb565b5b60006101a685828601610157565b92505060206101b78582860161016c565b9150509250929050565b6101d26101cd82610304565b6103a9565b82525050565b6101e96101e482610316565b6103bb565b82525050565b6102006101fb82610342565b6103c5565b82525050565b6000610211826102ee565b61021b81856102f9565b935061022b818560208601610376565b80840191505092915050565b6102408161036c565b82525050565b6102576102528261036c565b6103e1565b82525050565b600061026982876101d8565b60018201915061027982866101c1565b60148201915061028982856101ef565b60208201915061029982846101ef565b60208201915081905095945050505050565b60006102b78285610206565b91506102c38284610246565b6020820191508190509392505050565b60006020820190506102e86000830184610237565b92915050565b600081519050919050565b600081905092915050565b600061030f8261034c565b9050919050565b60007fff0000000000000000000000000000000000000000000000000000000000000082169050919050565b6000819050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60005b83811015610394578082015181840152602081019050610379565b838111156103a3576000848401525b50505050565b60006103b4826103cf565b9050919050565b6000819050919050565b6000819050919050565b60006103da826103f0565b9050919050565b6000819050919050565b600080fd5b60008160601b9050919050565b61040681610342565b811461041157600080fd5b50565b61041d8161036c565b811461042857600080fd5b5056fe608060405234801561001057600080fd5b5060405161016838038061016883398181016040528101906100329190610054565b80600081905550506100a7565b60008151905061004e81610090565b92915050565b60006020828403121561006a5761006961008b565b5b60006100788482850161003f565b91505092915050565b6000819050919050565b600080fd5b61009981610081565b81146100a457600080fd5b50565b60b3806100b56000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c80630c55699c14602d575b600080fd5b60336047565b604051603e9190605a565b60405180910390f35b60005481565b6054816073565b82525050565b6000602082019050606d6000830184604d565b92915050565b600081905091905056fea2646970667358221220176e7e9577626c01c2b5e46d697777368daa31a61ac6c3fd6cc0bbc5bd4f8f2a64736f6c63430008070033a26469706673582212207eeeb4606f11d013f69f6590f362ffeb0f059f2c641869e03b23a03eb30252f264736f6c63430008070033) + contract_hash = response['contracts'].select { |contract| contract['code'] == stripped_create2_code}.first['contract_hash'] + salt = "1a40000000000000000000000000000000000000000000000000000000000045" + arg1 = "000000000000000000000000000000000000000000000000000000000000002d" + invoke_contract!(contract_hash, creator_keys['wallet_name'], 0, "0bd38f2f#{salt}#{arg1}") + + response = rpc.call('contract_api.list_owner_contracts', { 'owner' => create2 }) || {} + + puts "response" + puts response + end end From 07bac194991a7bbc56b610544b252ffe49f8ec0c Mon Sep 17 00:00:00 2001 From: Liam Noroian Date: Mon, 11 Apr 2022 11:01:42 -0700 Subject: [PATCH 88/96] init code hash returning correct value --- libraries/chain/database.cpp | 28 +- .../chain/include/xgt/chain/database.hpp | 4 +- .../chain/include/xgt/chain/wallet_object.hpp | 11 +- .../include/xgt/chain/xgt_object_types.hpp | 4 +- libraries/chain/xgt_evaluator.cpp | 348 +++++++----------- .../apis/contract_api/contract_api.cpp | 6 +- .../xgt/plugins/contract_api/contract_api.hpp | 4 +- .../database_api/database_api_objects.hpp | 6 +- .../schema_types/wallet_name_type.hpp | 6 +- .../protocol/include/xgt/protocol/types.hpp | 2 +- .../include/xgt/protocol/xgt_operations.hpp | 2 +- libraries/vendor/xgtvm/libraries/machine.cpp | 3 +- libraries/vendor/xgtvm/libraries/machine.hpp | 2 +- libraries/vendor/xgtvm/programs/xgtvm.cpp | 2 +- .../vendor/xgtvm/programs/xgtvm_tests.cpp | 2 +- tasks/contracts.rake | 10 +- 16 files changed, 183 insertions(+), 257 deletions(-) diff --git a/libraries/chain/database.cpp b/libraries/chain/database.cpp index de636e3c..08b733b5 100644 --- a/libraries/chain/database.cpp +++ b/libraries/chain/database.cpp @@ -629,19 +629,19 @@ const wallet_object& database::get_account( const wallet_name_type& name )const return get< wallet_object, by_name >( name ); } FC_CAPTURE_AND_RETHROW( (name) ) } -const wallet_object& database::get_account_by_ripemd160( const address_ripemd160_type& address_ripemd160 )const +const wallet_object& database::get_account_by_en_address( const en_address_type& en_address )const { try { - return get< wallet_object, by_address_ripemd160 >( address_ripemd160 ); -} FC_CAPTURE_AND_RETHROW( (address_ripemd160) ) } + return get< wallet_object, by_en_address >( en_address ); +} FC_CAPTURE_AND_RETHROW( (en_address) ) } const wallet_object* database::find_account( const wallet_name_type& name )const { return find< wallet_object, by_name >( name ); } -const wallet_object* database::find_account_by_ripemd160( const address_ripemd160_type& address_ripemd160 )const +const wallet_object* database::find_account_by_en_address( const en_address_type& en_address )const { - return find< wallet_object, by_address_ripemd160 >( address_ripemd160 ); + return find< wallet_object, by_en_address >( en_address ); } const comment_object& database::get_comment( const wallet_name_type& author, const shared_string& permlink )const @@ -1365,13 +1365,13 @@ void database::init_genesis( uint64_t init_supply ) create< wallet_object >( [&]( wallet_object& a ) { a.name = XGT_MINER_WALLET; - a.address_ripemd160 = fc::ripemd160::hex_digest(XGT_MINER_WALLET); + a.en_address = fc::ripemd160::hex_digest(XGT_MINER_WALLET); } ); create< account_authority_object >( [&]( account_authority_object& auth ) { auth.account = XGT_MINER_WALLET; - auth.address_ripemd160 = fc::ripemd160::hex_digest(XGT_MINER_WALLET); + auth.en_address = fc::ripemd160::hex_digest(XGT_MINER_WALLET); auth.recovery.weight_threshold = 1; auth.money.weight_threshold = 1; }); @@ -1379,7 +1379,7 @@ void database::init_genesis( uint64_t init_supply ) create< wallet_object >( [&]( wallet_object& a ) { a.name = XGT_INIT_MINER_NAME; - a.address_ripemd160 = fc::ripemd160::hex_digest(XGT_INIT_MINER_NAME); + a.en_address = fc::ripemd160::hex_digest(XGT_INIT_MINER_NAME); a.memo_key = init_public_key; a.balance = asset( init_supply, XGT_SYMBOL ); } ); @@ -1387,7 +1387,7 @@ void database::init_genesis( uint64_t init_supply ) create< account_authority_object >( [&]( account_authority_object& auth ) { auth.account = XGT_INIT_MINER_NAME; - auth.address_ripemd160 = fc::ripemd160::hex_digest(XGT_INIT_MINER_NAME); + auth.en_address = fc::ripemd160::hex_digest(XGT_INIT_MINER_NAME); auth.recovery.add_authority( init_public_key, 1 ); auth.recovery.weight_threshold = 1; auth.money = auth.recovery; @@ -1403,13 +1403,13 @@ void database::init_genesis( uint64_t init_supply ) create< wallet_object >( [&]( wallet_object& a ) { a.name = XGT_NULL_WALLET; - a.address_ripemd160 = fc::ripemd160::hex_digest(XGT_NULL_WALLET); + a.en_address = fc::ripemd160::hex_digest(XGT_NULL_WALLET); } ); create< account_authority_object >( [&]( account_authority_object& auth ) { auth.account = XGT_NULL_WALLET; - auth.address_ripemd160 = fc::ripemd160::hex_digest(XGT_NULL_WALLET); + auth.en_address = fc::ripemd160::hex_digest(XGT_NULL_WALLET); auth.recovery.weight_threshold = 1; auth.money.weight_threshold = 1; }); @@ -1417,19 +1417,19 @@ void database::init_genesis( uint64_t init_supply ) create< wallet_object >( [&]( wallet_object& a ) { a.name = XGT_TREASURY_WALLET; - a.address_ripemd160 = fc::ripemd160::hex_digest(XGT_TREASURY_WALLET); + a.en_address = fc::ripemd160::hex_digest(XGT_TREASURY_WALLET); } ); create< wallet_object >( [&]( wallet_object& a ) { a.name = XGT_TEMP_WALLET; - a.address_ripemd160 = fc::ripemd160::hex_digest(XGT_TEMP_WALLET); + a.en_address = fc::ripemd160::hex_digest(XGT_TEMP_WALLET); } ); create< account_authority_object >( [&]( account_authority_object& auth ) { auth.account = XGT_TEMP_WALLET; - auth.address_ripemd160 = fc::ripemd160::hex_digest(XGT_TEMP_WALLET); + auth.en_address = fc::ripemd160::hex_digest(XGT_TEMP_WALLET); auth.recovery.weight_threshold = 0; auth.money.weight_threshold = 0; }); diff --git a/libraries/chain/include/xgt/chain/database.hpp b/libraries/chain/include/xgt/chain/database.hpp index c810dae8..33d08fbd 100644 --- a/libraries/chain/include/xgt/chain/database.hpp +++ b/libraries/chain/include/xgt/chain/database.hpp @@ -212,9 +212,9 @@ namespace xgt { namespace chain { const contract_object* find_contract_by_wallet( const wallet_name_type& wallet )const; const wallet_object& get_account( const wallet_name_type& name )const; - const wallet_object& get_account_by_ripemd160( const address_ripemd160_type& address_ripemd160 )const; + const wallet_object& get_account_by_en_address( const en_address_type& en_address )const; const wallet_object* find_account( const wallet_name_type& name )const; - const wallet_object* find_account_by_ripemd160( const address_ripemd160_type& address_ripemd160 )const; + const wallet_object* find_account_by_en_address( const en_address_type& en_address )const; const comment_object& get_comment( const wallet_name_type& author, const shared_string& permlink )const; const comment_object* find_comment( const wallet_name_type& author, const shared_string& permlink )const; diff --git a/libraries/chain/include/xgt/chain/wallet_object.hpp b/libraries/chain/include/xgt/chain/wallet_object.hpp index eb7fe6c9..ea4ad90b 100644 --- a/libraries/chain/include/xgt/chain/wallet_object.hpp +++ b/libraries/chain/include/xgt/chain/wallet_object.hpp @@ -31,7 +31,10 @@ namespace xgt { namespace chain { id_type id; wallet_name_type name; - address_ripemd160_type address_ripemd160; + // TODO EN_ADDRESS INSTEAD OF en_address if possible, in addition to otherwise. + // Machine processes en_address_type as a uint256_t, but en_address needs to be preserved + // Maybe lookup wallet based on en_address and grab en_address + en_address_type en_address; public_key_type memo_key; time_point_sec last_account_update; @@ -92,7 +95,7 @@ namespace xgt { namespace chain { id_type id; wallet_name_type account; - address_ripemd160_type address_ripemd160; + en_address_type en_address; shared_authority recovery; ///< used for backup control, can set recovery or money shared_authority money; ///< used for all monetary operations, can set money or social @@ -167,8 +170,8 @@ namespace xgt { namespace chain { member< wallet_object, wallet_id_type, &wallet_object::id > >, ordered_unique< tag< by_name >, member< wallet_object, wallet_name_type, &wallet_object::name > >, - ordered_unique< tag< by_address_ripemd160 >, - member< wallet_object, address_ripemd160_type, &wallet_object::address_ripemd160 > > + ordered_unique< tag< by_en_address >, + member< wallet_object, en_address_type, &wallet_object::en_address > > >, allocator< wallet_object > > wallet_index; diff --git a/libraries/chain/include/xgt/chain/xgt_object_types.hpp b/libraries/chain/include/xgt/chain/xgt_object_types.hpp index 7528a946..6ffc46da 100644 --- a/libraries/chain/include/xgt/chain/xgt_object_types.hpp +++ b/libraries/chain/include/xgt/chain/xgt_object_types.hpp @@ -42,7 +42,7 @@ using xgt::protocol::block_id_type; using xgt::protocol::transaction_id_type; using xgt::protocol::chain_id_type; using xgt::protocol::wallet_name_type; -using xgt::protocol::address_ripemd160_type; +using xgt::protocol::en_address_type; using xgt::protocol::share_type; using chainbase::shared_string; @@ -52,7 +52,7 @@ inline void from_string( shared_string& out, const string& in ){ out.assign( in. struct by_id; struct by_name; -struct by_address_ripemd160; +struct by_en_address; enum object_type { diff --git a/libraries/chain/xgt_evaluator.cpp b/libraries/chain/xgt_evaluator.cpp index 5cfa3e48..572f4f38 100644 --- a/libraries/chain/xgt_evaluator.cpp +++ b/libraries/chain/xgt_evaluator.cpp @@ -151,13 +151,13 @@ void verify_authority_accounts_exist( } void initialize_wallet_object( wallet_object& acc, const wallet_name_type& name, const public_key_type& key, - const dynamic_global_property_object& props, bool mined, const wallet_name_type& recovery_account, uint32_t hardfork, uint32_t nonce, std::string address_ripemd160 = "" ) + const dynamic_global_property_object& props, bool mined, const wallet_name_type& recovery_account, uint32_t hardfork, uint32_t nonce, std::string en_address = "" ) { wlog("?????? initialize_wallet_object name ${n}", ("n", name)); wlog("?????? initialize_wallet_object key ${n}", ("n", key)); wlog("?????? initialize_wallet_object created ${n}", ("n", props.time)); acc.name = name; - acc.address_ripemd160 = address_ripemd160 == "" ? fc::ripemd160::hex_digest(name) : address_ripemd160; + acc.en_address = en_address == "" ? fc::ripemd160::hex_digest(name) : en_address; acc.memo_key = key; acc.created = props.time; acc.nonce = nonce; @@ -219,7 +219,7 @@ void wallet_create_evaluator::do_apply( const wallet_create_operation& o ) auth.recovery = o.recovery; auth.money = o.money; auth.social = o.social; - auth.address_ripemd160 = fc::ripemd160::hex_digest(wallet_name); + auth.en_address = fc::ripemd160::hex_digest(wallet_name); auth.last_recovery_update = fc::time_point_sec::min(); }); } @@ -1067,7 +1067,7 @@ std::map< uint64_t, std::function > energy_cost { {machine::shl_opcode, [](machine::machine& m){ return 3; }}, {machine::shr_opcode, [](machine::machine& m){ return 3; }}, {machine::sar_opcode, [](machine::machine& m){ return 3; }}, - {machine::sha3_opcode, [](machine::machine& m){ return 0; }}, // TODO -- SHA3 -- variab; le + {machine::sha3_opcode, [](machine::machine& m){ return 0; }}, // TODO -- SHA3 -- variable {machine::address_opcode, [](machine::machine& m){ return 2; }}, {machine::balance_opcode, [](machine::machine& m){ return 700; }}, {machine::origin_opcode, [](machine::machine& m){ return 2; }}, @@ -1193,24 +1193,10 @@ fc::ripemd160 generate_random_ripemd160() return fc::ripemd160::hash(buf, buflen); } -boost::multiprecision::uint256_t address_to_uint256_t(const std::string& base58str) { - std::string prefix( XGT_ADDRESS_PREFIX ); - - const size_t prefix_len = prefix.size(); - auto b58 = base58str.substr( prefix_len ); - auto r160 = fc::ripemd160::hash(b58); - - std::stringstream ss; - ss << std::hex << r160.str(); - boost::multiprecision::uint256_t x; - ss >> x; - return x; -}; - -boost::multiprecision::uint256_t ripemd160_to_uint256_t(fc::ripemd160 h) +uint256_t ripemd160_to_uint256_t(fc::ripemd160 h) { - boost::multiprecision::uint256_t n(0); - boost::multiprecision::uint256_t m; + uint256_t n(0); + uint256_t m; for (int i = 0; i < 5; i++) { m = h._hash[i]; @@ -1220,7 +1206,7 @@ boost::multiprecision::uint256_t ripemd160_to_uint256_t(fc::ripemd160 h) return n; } -address_ripemd160_type uint256_t_to_ripemd160(boost::multiprecision::uint256_t address) { +en_address_type uint256_t_to_ripemd160(uint256_t address) { std::stringstream ss; ss << std::hex << address; return ss.str(); @@ -1276,23 +1262,24 @@ void hex_to_uint8(std::string hex, uint8_t bytes[]) { return; } -void generate_create2_input(std::string sender, std::string salt, std::string init_code, std::string target_address) { +std::string generate_create2_address(std::string sender, std::string salt, std::string init_code, std::string target_address = "TODO MIGRATE TO TESTS") { std::stringstream ss; // Recipe: keccak256( 0xff ++ address ++ salt ++ keccak256(init_code))[12:] + std::cout << "INIT CODE CREATE2: " << init_code << std::endl; size_t init_code_size = init_code.size() / 2; uint8_t init_code_bytes[init_code_size]; hex_to_uint8(init_code, init_code_bytes); auto init_code_output = ethash_keccak256( init_code_bytes, init_code_size ); - // keccak256(init_code) std::string init_code_hash = to_hex(init_code_output); - // 0xff ++ address ++ salt ++ keccak256(init_code) + std::cout << "INIT CODE HASH CREATE2: " << init_code_hash << std::endl; + ss << "ff" << sender << salt << init_code_hash; std::string keccak_input_str = ss.str(); - std::cout << "Keccak input string: " << keccak_input_str << std::endl; + std::cout << "KECCAK INPUT CREATE2: " << keccak_input_str << std::endl; size_t size = keccak_input_str.size() / 2; uint8_t bytes[size]; @@ -1302,20 +1289,14 @@ void generate_create2_input(std::string sender, std::string salt, std::string in std::string untrimmed_address = to_hex(keccak_output); std::string generated_create2_address = untrimmed_address.substr(24, 40); - std::cout << "Input sender : " << sender << std::endl; - std::cout << "Input salt : " << salt << std::endl; - std::cout << "Input init_code : " << init_code << std::endl; - std::cout << "Hashed init_code : " << init_code_hash << std::endl; - std::cout << "Target create2 address : " << target_address << std::endl; - std::cout << "Generated untrimmed create2 address: " << untrimmed_address << std::endl; - std::cout << "Generated create2 address : " << generated_create2_address << std::endl; - std::cout << "************************************************************************************************" << std::endl; + std::cout << "Target create2 address: " << target_address << std::endl; + std::cout << "Actual create2 address: " << generated_create2_address << std::endl; - return; + return generated_create2_address; } -// TODO sender is address_ripemd160 -const std::string generate_rlp_wallet_name(std::string sender, uint32_t nonce, std::string salt = "", std::vector init_code = {}) { +// TODO sender is en_address +const std::string generate_en_address(std::string sender, uint32_t nonce, std::string salt = "", std::vector init_code = {}) { if (salt == "") { std::string rlp_input; rlp_input += sender += nonce; @@ -1326,101 +1307,35 @@ const std::string generate_rlp_wallet_name(std::string sender, uint32_t nonce, s std::string genOutput = v.write(); std::string genHexStr = HexStr( genOutput.begin(), genOutput.end() ); - std::stringstream ss; - unsigned char output[32]; - SHA3_CTX ctx; - keccak_init(&ctx); - keccak_update( &ctx, (unsigned char*)genHexStr.c_str(), genHexStr.size() ); - keccak_final(&ctx, output); - for (size_t i = 0; i < 32; i++) { - ss << std::hex << (machine::opcode)output[i]; - } - std::string gen_hex_hash = ss.str(); - std::vector rlp_vec( gen_hex_hash.begin(), gen_hex_hash.end() ); - std::string base58Str = fc::to_base58(rlp_vec); - std::string rlp_address = base58Str.substr(base58Str.size() - 40); + size_t size = genHexStr.size() / 2; + uint8_t bytes[size]; + hex_to_uint8(genHexStr, bytes); - return "XGT" + rlp_address; + auto keccak_output = ethash_keccak256( bytes, size ); + std::string untrimmed_address = to_hex(keccak_output); + std::string generated_rlp_address = untrimmed_address.substr(untrimmed_address.size() - 40); + + return generated_rlp_address; } else { std::stringstream ss; - std::string leader = "ff"; - // init_code = {0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef}; - // for (size_t i = 0; i < init_code.size(); i++) { - // if ((machine::opcode)init_code[i] < 0x10) - // ss << "0"; - // // ss << "00000000000000000000000000000000000000000000000000000000000000"; - // ss << std::hex << (machine::opcode)init_code[i]; - // } - // std::string init_code_str = ss.str(); - // std::string init_code_str_seed = "6080604060806040"; - // std::string init_code_str = ""; - // for (size_t i = 0; i < 16; i++) { - // init_code_str += init_code_str_seed; - // } - // std::string init_code_str = "00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000052000000000000000000000000000000000000000000000000000000000000003400000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000015000000000000000000000000000000000000000000000000000000000000006100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000005700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000fd000000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000005100000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000006800000000000000000000000000000000000000000000000000000000000000380000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000006800000000000000000000000000000000000000000000000000000000000000830000000000000000000000000000000000000000000000000000000000000039000000000000000000000000000000000000000000000000000000000000008100000000000000000000000000000000000000000000000000000000000000810000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000052000000000000000000000000000000000000000000000000000000000000008100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000090000000000000000000000000000000000000000000000000000000000000006100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000009100000000000000000000000000000000000000000000000000000000000000900000000000000000000000000000000000000000000000000000000000000061000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000540000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008100000000000000000000000000000000000000000000000000000000000000900000000000000000000000000000000000000000000000000000000000000055000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000061000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a70000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005b00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008100000000000000000000000000000000000000000000000000000000000000510000000000000000000000000000000000000000000000000000000000000090000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004e00000000000000000000000000000000000000000000000000000000000000810000000000000000000000000000000000000000000000000000000000000061000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000900000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005b00000000000000000000000000000000000000000000000000000000000000920000000000000000000000000000000000000000000000000000000000000091000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005b00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000082000000000000000000000000000000000000000000000000000000000000008400000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000001500000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006a000000000000000000000000000000000000000000000000000000000000005700000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006900000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008b0000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000000000000000000000000000000000005b00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000078000000000000000000000000000000000000000000000000000000000000008400000000000000000000000000000000000000000000000000000000000000820000000000000000000000000000000000000000000000000000000000000085000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003f0000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005b00000000000000000000000000000000000000000000000000000000000000910000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000920000000000000000000000000000000000000000000000000000000000000091000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000081000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000091000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005b00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000fd000000000000000000000000000000000000000000000000000000000000005b00000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009900000000000000000000000000000000000000000000000000000000000000810000000000000000000000000000000000000000000000000000000000000061000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000810000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000000000000000000000000000000000008100000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000061000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a4000000000000000000000000000000000000000000000000000000000000005700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000fd000000000000000000000000000000000000000000000000000000000000005b00000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000b300000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000061000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b50000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000390000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f300000000000000000000000000000000000000000000000000000000000000fe000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000520000000000000000000000000000000000000000000000000000000000000034000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000150000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000005700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000fd000000000000000000000000000000000000000000000000000000000000005b00000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000360000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000057000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000035000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000001c00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000063000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000550000000000000000000000000000000000000000000000000000000000000069000000000000000000000000000000000000000000000000000000000000009c00000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000002d0000000000000000000000000000000000000000000000000000000000000057000000000000000000000000000000000000000000000000000000000000005b00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000fd000000000000000000000000000000000000000000000000000000000000005b00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000033000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000470000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005b0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000510000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000003e000000000000000000000000000000000000000000000000000000000000009100000000000000000000000000000000000000000000000000000000000000900000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000005a0000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000051000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000910000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000f3000000000000000000000000000000000000000000000000000000000000005b00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005400000000000000000000000000000000000000000000000000000000000000810000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000540000000000000000000000000000000000000000000000000000000000000081000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000730000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005b00000000000000000000000000000000000000000000000000000000000000820000000000000000000000000000000000000000000000000000000000000052000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000820000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000006d000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000840000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000004d0000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005b00000000000000000000000000000000000000000000000000000000000000920000000000000000000000000000000000000000000000000000000000000091000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005b00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008100000000000000000000000000000000000000000000000000000000000000900000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000009100000000000000000000000000000000000000000000000000000000000000900000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000005600000000000000000000000000000000000000000000000000000000000000fe00000000000000000000000000000000000000000000000000000000000000a20000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000000000000000000000000000000000006900000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000066000000000000000000000000000000000000000000000000000000000000007300000000000000000000000000000000000000000000000000000000000000580000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000017000000000000000000000000000000000000000000000000000000000000006e000000000000000000000000000000000000000000000000000000000000007e000000000000000000000000000000000000000000000000000000000000009500000000000000000000000000000000000000000000000000000000000000770000000000000000000000000000000000000000000000000000000000000062000000000000000000000000000000000000000000000000000000000000006c000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c200000000000000000000000000000000000000000000000000000000000000b500000000000000000000000000000000000000000000000000000000000000e4000000000000000000000000000000000000000000000000000000000000006d0000000000000000000000000000000000000000000000000000000000000069000000000000000000000000000000000000000000000000000000000000007700000000000000000000000000000000000000000000000000000000000000770000000000000000000000000000000000000000000000000000000000000036000000000000000000000000000000000000000000000000000000000000008d00000000000000000000000000000000000000000000000000000000000000aa000000000000000000000000000000000000000000000000000000000000003100000000000000000000000000000000000000000000000000000000000000a6000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000c600000000000000000000000000000000000000000000000000000000000000c300000000000000000000000000000000000000000000000000000000000000fd000000000000000000000000000000000000000000000000000000000000006c00000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000bb00000000000000000000000000000000000000000000000000000000000000c500000000000000000000000000000000000000000000000000000000000000bd000000000000000000000000000000000000000000000000000000000000004f000000000000000000000000000000000000000000000000000000000000008f000000000000000000000000000000000000000000000000000000000000002a00000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000073000000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000006c00000000000000000000000000000000000000000000000000000000000000630000000000000000000000000000000000000000000000000000000000000043000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000007000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000334e00000000000000000000000000000000000000000000000000000000000000810000000000000000000000000000000000000000000000000000000000000061000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000900000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005b00000000000000000000000000000000000000000000000000000000000000920000000000000000000000000000000000000000000000000000000000000091000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005b00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000082000000000000000000000000000000000000000000000000000000000000008400000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000001500000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006a000000000000000000000000000000000000000000000000000000000000005700000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006900000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008b0000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000000000000000000000000000000000005b00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000078000000000000000000000000000000000000000000000000000000000000008400000000000000000000000000000000000000000000000000000000000000820000000000000000000000000000000000000000000000000000000000000085000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003f0000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005b00000000000000000000000000000000000000000000000000000000000000910000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000920000000000000000000000000000000000000000000000000000000000000091000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000081000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000091000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005b00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000fd000000000000000000000000000000000000000000000000000000000000005b00000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009900000000000000000000000000000000000000000000000000000000000000810000000000000000000000000000000000000000000000000000000000000061000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000810000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000000000000000000000000000000000008100000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000061000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a4000000000000000000000000000000000000000000000000000000000000005700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000fd000000000000000000000000000000000000000000000000000000000000005b00000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000b300000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000061000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b50000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000390000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f300000000000000000000000000000000000000000000000000000000000000fe000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000520000000000000000000000000000000000000000000000000000000000000034000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000150000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000005700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000fd000000000000000000000000000000000000000000000000000000000000005b00000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000360000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000057000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000035000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000001c00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000063000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000550000000000000000000000000000000000000000000000000000000000000069000000000000000000000000000000000000000000000000000000000000009c00000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000002d0000000000000000000000000000000000000000000000000000000000000057000000000000000000000000000000000000000000000000000000000000005b00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000fd000000000000000000000000000000000000000000000000000000000000005b00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000033000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000470000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005b0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000510000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000003e000000000000000000000000000000000000000000000000000000000000009100000000000000000000000000000000000000000000000000000000000000900000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000005a0000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000051000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000910000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000f3000000000000000000000000000000000000000000000000000000000000005b00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005400000000000000000000000000000000000000000000000000000000000000810000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000540000000000000000000000000000000000000000000000000000000000000081000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000730000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005b00000000000000000000000000000000000000000000000000000000000000820000000000000000000000000000000000000000000000000000000000000052000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000820000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000006d000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000840000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000004d0000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005b00000000000000000000000000000000000000000000000000000000000000920000000000000000000000000000000000000000000000000000000000000091000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005b00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008100000000000000000000000000000000000000000000000000000000000000900000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000009100000000000000000000000000000000000000000000000000000000000000900000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000005600000000000000000000000000000000000000000000000000000000000000fe00000000000000000000000000000000000000000000000000000000000000a20000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000000000000000000000000000000000006900000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000066000000000000000000000000000000000000000000000000000000000000007300000000000000000000000000000000000000000000000000000000000000580000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000017000000000000000000000000000000000000000000000000000000000000006e000000000000000000000000000000000000000000000000000000000000007e000000000000000000000000000000000000000000000000000000000000009500000000000000000000000000000000000000000000000000000000000000770000000000000000000000000000000000000000000000000000000000000062000000000000000000000000000000000000000000000000000000000000006c000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c200000000000000000000000000000000000000000000000000000000000000b500000000000000000000000000000000000000000000000000000000000000e4000000000000000000000000000000000000000000000000000000000000006d0000000000000000000000000000000000000000000000000000000000000069000000000000000000000000000000000000000000000000000000000000007700000000000000000000000000000000000000000000000000000000000000770000000000000000000000000000000000000000000000000000000000000036000000000000000000000000000000000000000000000000000000000000008d00000000000000000000000000000000000000000000000000000000000000aa000000000000000000000000000000000000000000000000000000000000003100000000000000000000000000000000000000000000000000000000000000a6000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000c600000000000000000000000000000000000000000000000000000000000000c300000000000000000000000000000000000000000000000000000000000000fd000000000000000000000000000000000000000000000000000000000000006c00000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000bb00000000000000000000000000000000000000000000000000000000000000c500000000000000000000000000000000000000000000000000000000000000bd000000000000000000000000000000000000000000000000000000000000004f000000000000000000000000000000000000000000000000000000000000008f000000000000000000000000000000000000000000000000000000000000002a00000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000073000000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000006c0000000000000000000000000000000000000000000000000000000000000063000000000000000000000000000000000000000000000000000000000000004300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000033"; - - // keccak of init_code should be 0xb91f1af43fc85861a7387def4ed8cc83894a0670b024458827bed13d552cc66f - // std::string init_code_str = "608060405234801561001057600080fd5b5060405161016838038061016883398181016040528101906100329190610054565b80600081905550506100a7565b60008151905061004e81610090565b92915050565b60006020828403121561006a5761006961008b565b5b60006100788482850161003f565b91505092915050565b6000819050919050565b600080fd5b61009981610081565b81146100a457600080fd5b50565b60b3806100b56000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c80630c55699c14602d575b600080fd5b60336047565b604051603e9190605a565b60405180910390f35b60005481565b6054816073565b82525050565b6000602082019050606d6000830184604d565b92915050565b600081905091905056fea26469706673582212204dd788e7581ff606469b19a0b4e5fd41a3ea60158d0668e73bf0b59cab258acd64736f6c63430008070033000000000000000000000000000000000000000000000000000000000000002d"; - // size_t size = init_code_str.size() / 2; - // uint8_t bytes[size]; - // hex_to_uint8(init_code_str, bytes); - // std::cout << "INIT_CODE: " << init_code_str << std::endl; - // auto keccak_output = ethash_keccak256( bytes, size ); - // std::cout << "KECCAK OUTPUT: " << to_hex(keccak_output) << std::endl; - - // char init_code_arr[1200]; - // hex2bin(init_code_input, init_code_arr); - // std::string init_code_str = init_code_arr; - - // unsigned char init_code_output[64]; - // SHA3_CTX init_code_ctx; - // keccak_init(&init_code_ctx); - // keccak_update( &init_code_ctx, (unsigned char*)init_code_str.c_str(), init_code_str.size() ); - // keccak_final(&init_code_ctx, init_code_output); - // for (size_t i = 0; i < 32; i++) { - // ss << std::hex << (machine::opcode)init_code_output[i]; - // } - - generate_create2_input("0000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000000", "00", "4d1a2e2bb4f88f0250f26ffff098b0b30b26bf38"); - generate_create2_input("deadbeef00000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000000", "00", "b928f69bb1d91cd65274e3c79d8986362984fda3"); - generate_create2_input("deadbeef00000000000000000000000000000000", "000000000000000000000000feed000000000000000000000000000000000000", "00", "d04116cdd17bebe565eb2422f2497e06cc1c9833"); - generate_create2_input("0000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000000", "deadbeef", "70f2b2914a2a4b783faefb75f459a580616fcb5e"); - generate_create2_input("00000000000000000000000000000000deadbeef", "00000000000000000000000000000000000000000000000000000000cafebabe", "deadbeef", "60f3f640a8508fc6a86d45Df051962668e1e8ac7"); - generate_create2_input("00000000000000000000000000000000deadbeef", "00000000000000000000000000000000000000000000000000000000cafebabe", "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef", "1d8bfdc5d46dc4f61d6b6115972536ebe6a8854c"); - generate_create2_input("0000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000000", "", "e33c0c7f7df4809055c3eba6c09cfe4baf1bd9e0"); - - // std::string hashed_init_code = ss.str(); - // ss.str(""); - // ss << leader << "5FD6eB55D12E759a21C09eF703fe0CBa1DC9d88D" << "1a40000000000000000000000000000000000000000000000000000000000045"; - // ss << hashed_init_code; - - // std::string sha3_input = ss.str(); - // ss.str(""); - - // unsigned char output[32]; - // SHA3_CTX ctx; - // keccak_init(&ctx); - // keccak_update( &ctx, (unsigned char*)sha3_input.c_str(), sha3_input.size() ); - // keccak_final(&ctx, output); - // for (size_t i = 0; i < 32; i++) { - // ss << std::hex << (machine::opcode)output[i]; - // } - // TODO XXX MAKE SURE CONVERSION TO ADDRESS_RIPEMD160 IN THE VM USES THE WALLET'S ADDRESS_RIPEMD160 RATHER THAN GENERATING IT - - std::string untrimmed_wallet_name = ss.str(); - // std::vector rlp_vec( untrimmed_wallet_name.begin(), untrimmed_wallet_name.end() ); - // std::string base58Str = fc::to_base58(rlp_vec); - // std::string rlp_address = base58Str.substr(base58Str.size() - 40); - - // return "XGT" + rlp_address; - - const std::string& address_ref = std::string(trimmed_wallet_name); - boost::multiprecision::uint256_t new_contract_wallet_address = address_to_uint256_t(address_ref); - ss.str(""); - ss << new_contract_wallet_address << std::endl; + // TODO migrate to tests + // generate_create2_address("0000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000000", "00", "4d1a2e2bb4f88f0250f26ffff098b0b30b26bf38"); + // generate_create2_address("deadbeef00000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000000", "00", "b928f69bb1d91cd65274e3c79d8986362984fda3"); + // generate_create2_address("deadbeef00000000000000000000000000000000", "000000000000000000000000feed000000000000000000000000000000000000", "00", "d04116cdd17bebe565eb2422f2497e06cc1c9833"); + // generate_create2_address("0000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000000", "deadbeef", "70f2b2914a2a4b783faefb75f459a580616fcb5e"); + // generate_create2_address("00000000000000000000000000000000deadbeef", "00000000000000000000000000000000000000000000000000000000cafebabe", "deadbeef", "60f3f640a8508fc6a86d45Df051962668e1e8ac7"); + // generate_create2_address("00000000000000000000000000000000deadbeef", "00000000000000000000000000000000000000000000000000000000cafebabe", "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef", "1d8bfdc5d46dc4f61d6b6115972536ebe6a8854c"); + // generate_create2_address("0000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000000", "", "e33c0c7f7df4809055c3eba6c09cfe4baf1bd9e0"); + + for (size_t i = 0; i < init_code.size(); i++) { + ss << std::hex << (machine::opcode)init_code[i]; + } + + std::string init_code_str = ss.str(); + std::string trimmed_wallet_name = generate_create2_address(sender, salt, init_code_str); - return ss.str(); + return trimmed_wallet_name; } }; @@ -1463,24 +1378,29 @@ const wallet_object& wallet_create(chain::database& _db, uint32_t nonce, std::st std::vector contract_invoke(chain::database& _db, wallet_name_type o, wallet_name_type caller, contract_hash_type contract_hash, uint64_t value, uint64_t energy, std::vector args, map< fc::sha256, fc::sha256 >& storage) { wlog("contract_invoke another contract ${w}", ("w",contract_hash)); + + std::stringstream ss; const auto& c = _db.get_contract(contract_hash); - const std::string& caller_address_ref = std::string(caller); + const wallet_object& destination_wallet = _db.get_account(c.wallet); - boost::multiprecision::uint256_t converted_caller = address_to_uint256_t(caller_address_ref); + ss << std::hex << std::string(destination_wallet.en_address); + uint256_t destination_en_address; + ss >> destination_en_address; + ss.str(""); - auto r160 = fc::ripemd160::hash("D7ACd2a9FD159E69Bb102A1ca21C9a3e3A5F771B"); + const wallet_object& wallet = _db.get_account(caller); - std::stringstream ss; - ss << std::hex << r160.str(); - boost::multiprecision::uint256_t x; - ss >> x; + ss << std::hex << std::string(wallet.en_address); + uint256_t caller_en_address; + ss >> caller_en_address; + ss.str(""); machine::message msg = { 0, 0, int64_t(energy), - converted_caller, - x, + caller_en_address, + destination_en_address, value, // TODO args size is inaccurate args.size() * 2, @@ -1531,8 +1451,6 @@ std::vector contract_invoke(chain::database& _db, wallet_name_typ std::cerr << "\e[36m" << "LOG: " << line << "\e[0m" << std::endl; std::cout << m.to_json() << std::endl; - const wallet_object& wallet = _db.get_account(caller); - uint32_t energy_regen_period = XGT_ENERGY_REGENERATION_SECONDS; // TODO: Hardcode this for now (should be a constant I think) _db.modify(wallet, [&](wallet_object& w) { @@ -1614,50 +1532,53 @@ std::string inspect(std::vector words) machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type owner, wallet_name_type caller, wallet_name_type contract_wallet, contract_hash_type contract_hash, map& storage) { - std::function< std::string(std::vector) > sha3 = [&](std::vector memory) -> std::string + std::function< machine::big_word(std::vector) > sha3 = [&](std::vector memory) -> machine::big_word { std::stringstream ss; - std::string message; - std::string return_str; - for (size_t i = 0; i < memory.size(); i++) { - auto op = std::stoi(std::to_string(memory[i])); - std::cout << op << std::endl; - if (op < 16) - ss << "0"; - ss << std::hex << op; - std::cout << ss.str() << std::endl; + if (memory.size() > 32) { + for (size_t i = 0; i < memory.size(); i++) { + ss << "0000000000000000000000000000000"; + ss << std::hex << (machine::opcode)memory[i]; + } + } else { + for (size_t i = 0; i < memory.size(); i++) { + if ( (machine::opcode)memory[i] < 0x10 ) + ss << "0"; + ss << std::hex << (machine::opcode)memory[i]; + } } - message = ss.str(); + + std::string memory_str = ss.str(); + std::cout << "KECCAK INPUT SHA3: " << memory_str << std::endl; + + size_t memory_size = memory_str.size() / 2; + uint8_t memory_bytes[memory_size]; + hex_to_uint8(memory_str, memory_bytes); + auto memory_output = ethash_keccak256( memory_bytes, memory_size ); + std::string memory_hash = to_hex(memory_output); + ss.str(""); - // SHOULD EQUAL ff#{en_address}1a40000000000000000000000000000000000000000000000000000000000045dcc46d1ba759dfe92ef5276dd4690465c85cb217de3af9892e0a1b976c37eb7a - std::cout << "SHA3 message input: " << message << std::endl; - unsigned char output[32]; - SHA3_CTX ctx; - keccak_init(&ctx); - keccak_update(&ctx, (unsigned char*)message.c_str(), message.size()); - keccak_final(&ctx, output); - for (size_t i = 0; i < 32; i++) { - ss << std::hex << (machine::opcode)output[i]; - std::cout << std::hex << (machine::opcode)output[i] << std::endl; - } - return_str = ss.str(); - std::cout << "RETURN STRING: " << return_str << std::endl; - return return_str; + ss << std::hex << memory_hash; + uint256_t sha3_return; + ss >> sha3_return; + std::cout << "INIT CODE HASH SHA3: " << memory_hash << std::endl; + + return sha3_return; }; - std::function< machine::big_word(machine::big_word) > get_balance = [&](machine::big_word address_ripemd160) -> machine::big_word + std::function< machine::big_word(machine::big_word) > get_balance = [&](machine::big_word en_address) -> machine::big_word { std::stringstream ss; - ss << std::hex << address_ripemd160; - const address_ripemd160_type r160 = ss.str(); - auto& wallet = _db.get_account_by_ripemd160(r160); + ss << std::hex << en_address; + const en_address_type r160 = ss.str(); + auto& wallet = _db.get_account_by_en_address(r160); return static_cast(wallet.balance.amount.value); }; std::function< std::string(std::string) > get_code_hash = [&](std::string address) -> std::string { - fc::ripemd160 address_ripemd160(address); - const auto& contract = _db.get_contract(address_ripemd160); + fc::ripemd160 en_address(address); + const auto& contract = _db.get_contract(en_address); std::string message(contract.code.begin(), contract.code.end()); unsigned char output[32]; SHA3_CTX ctx; @@ -1684,8 +1605,8 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type { std::stringstream ss; ss << std::hex << address; - const address_ripemd160_type r160 = ss.str(); - const auto& contract_wallet_account = _db.get_account_by_ripemd160(r160); + const en_address_type r160 = ss.str(); + const auto& contract_wallet_account = _db.get_account_by_en_address(r160); const contract_object& contract = _db.get_contract_by_wallet(contract_wallet_account.name); return std::vector(contract.code.begin(), contract.code.end()); @@ -1693,13 +1614,15 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type std::function< machine::big_word(std::vector, machine::big_word) > contract_create = [&, owner, caller, contract_hash](std::vector memory, machine::big_word value) -> machine::big_word { + std::stringstream ss; + const wallet_name_type sender_address = _db.get_contract(contract_hash).wallet; const auto& caller_contract_wallet = _db.get_account(sender_address); if (caller_contract_wallet.balance.amount.value >= value) { fc::ripemd160 new_contract_hash = generate_random_ripemd160(); - std::string new_wallet_name = generate_rlp_wallet_name(std::string(sender_address), caller_contract_wallet.nonce); + std::string new_wallet_name = generate_en_address(std::string(sender_address), caller_contract_wallet.nonce); wallet_create(_db, 1, new_wallet_name); chain::contract_object base_contract = _db.create< contract_object >( [&](contract_object& c) { @@ -1746,8 +1669,10 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type co.code = result; }); - const std::string& address_ref = std::string(deployed_contract.wallet); - boost::multiprecision::uint256_t new_contract_wallet_address = address_to_uint256_t(address_ref); + const wallet_object& deployed_contract_wallet = _db.get_account(deployed_contract.wallet); + ss << std::hex << std::string(deployed_contract_wallet.en_address); + uint256_t new_contract_wallet_address; + ss >> new_contract_wallet_address; _db.modify( caller_contract_wallet, [&]( wallet_object& acc ) { @@ -1769,8 +1694,8 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type // TODO Implement call depth limit std::stringstream ss; - const address_ripemd160_type r160 = uint256_t_to_ripemd160(address); - const wallet_object* ext_wallet = _db.find_account_by_ripemd160(r160); + const en_address_type r160 = uint256_t_to_ripemd160(address); + const wallet_object* ext_wallet = _db.find_account_by_en_address(r160); wallet_name_type ext_wallet_name; if (ext_wallet != nullptr) { @@ -1778,8 +1703,8 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type } else { // TODO Check energy before creating contract ss << std::hex << contract_create(args, value); - const address_ripemd160_type new_r160 = ss.str(); - const wallet_object* new_wallet = _db.find_account_by_ripemd160(new_r160); + const en_address_type new_r160 = ss.str(); + const wallet_object* new_wallet = _db.find_account_by_en_address(new_r160); ext_wallet_name = new_wallet->name; } @@ -1802,8 +1727,8 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type if (args.size() > 0) { if (!ext_contract) { - const address_ripemd160_type new_contract_r160 = uint256_t_to_ripemd160( contract_create(args, 0) ); - const wallet_object* new_contract_wallet = _db.find_account_by_ripemd160(new_contract_r160); + const en_address_type new_contract_r160 = uint256_t_to_ripemd160( contract_create(args, 0) ); + const wallet_object* new_contract_wallet = _db.find_account_by_en_address(new_contract_r160); ext_wallet_name = new_contract_wallet->name; ext_contract = _db.find_contract_by_wallet(ext_wallet_name); } @@ -1838,8 +1763,8 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type // TODO Implement call depth limit std::stringstream ss; - const address_ripemd160_type r160 = uint256_t_to_ripemd160(address); - const wallet_object* ext_wallet = _db.find_account_by_ripemd160(r160); + const en_address_type r160 = uint256_t_to_ripemd160(address); + const wallet_object* ext_wallet = _db.find_account_by_en_address(r160); wallet_name_type ext_wallet_name; if (ext_wallet != nullptr) { @@ -1847,8 +1772,8 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type } else { // TODO Check energy before creating contract ss << std::hex << contract_create(args, value); - const address_ripemd160_type new_r160 = ss.str(); - const wallet_object* new_wallet = _db.find_account_by_ripemd160(new_r160); + const en_address_type new_r160 = ss.str(); + const wallet_object* new_wallet = _db.find_account_by_en_address(new_r160); ext_wallet_name = new_wallet->name; } @@ -1870,8 +1795,8 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type if (args.size() > 0) { if (!ext_contract) { - const address_ripemd160_type new_contract_r160 = uint256_t_to_ripemd160( contract_create(args, 0) ); - const wallet_object* new_contract_wallet = _db.find_account_by_ripemd160(new_contract_r160); + const en_address_type new_contract_r160 = uint256_t_to_ripemd160( contract_create(args, 0) ); + const wallet_object* new_contract_wallet = _db.find_account_by_en_address(new_contract_r160); ext_wallet_name = new_contract_wallet->name; ext_contract = _db.find_contract_by_wallet(ext_wallet_name); } @@ -1906,8 +1831,8 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type // TODO Implement call depth limit std::stringstream ss; - const address_ripemd160_type r160 = uint256_t_to_ripemd160(address); - const wallet_object* ext_wallet = _db.find_account_by_ripemd160(r160); + const en_address_type r160 = uint256_t_to_ripemd160(address); + const wallet_object* ext_wallet = _db.find_account_by_en_address(r160); wallet_name_type ext_wallet_name; if (ext_wallet != nullptr) { @@ -1915,8 +1840,8 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type } else { // TODO Check energy before creating contract ss << std::hex << contract_create(args, 0); - const address_ripemd160_type new_r160 = ss.str(); - const wallet_object* new_wallet = _db.find_account_by_ripemd160(new_r160); + const en_address_type new_r160 = ss.str(); + const wallet_object* new_wallet = _db.find_account_by_en_address(new_r160); ext_wallet_name = new_wallet->name; } @@ -1926,8 +1851,8 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type if (args.size() > 0) { if (!ext_contract) { - const address_ripemd160_type new_contract_r160 = uint256_t_to_ripemd160( contract_create(args, 0) ); - const wallet_object* new_contract_wallet = _db.find_account_by_ripemd160(new_contract_r160); + const en_address_type new_contract_r160 = uint256_t_to_ripemd160( contract_create(args, 0) ); + const wallet_object* new_contract_wallet = _db.find_account_by_en_address(new_contract_r160); ext_wallet_name = new_contract_wallet->name; ext_contract = _db.find_contract_by_wallet(ext_wallet_name); } @@ -1961,16 +1886,16 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type { std::stringstream ss; - const address_ripemd160_type r160 = uint256_t_to_ripemd160(address); - const wallet_object* ext_wallet = _db.find_account_by_ripemd160(r160); + const en_address_type r160 = uint256_t_to_ripemd160(address); + const wallet_object* ext_wallet = _db.find_account_by_en_address(r160); wallet_name_type ext_wallet_name; if (ext_wallet != nullptr) { ext_wallet_name = ext_wallet->name; } else { ss << std::hex << contract_create(args, 0); - const address_ripemd160_type new_r160 = ss.str(); - const wallet_object* new_wallet = _db.find_account_by_ripemd160(new_r160); + const en_address_type new_r160 = ss.str(); + const wallet_object* new_wallet = _db.find_account_by_en_address(new_r160); ext_wallet_name = new_wallet->name; } @@ -1981,8 +1906,8 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type if (args.size() > 0) { if (!ext_contract) { - const address_ripemd160_type new_contract_r160 = uint256_t_to_ripemd160( contract_create(args, 0) ); - const wallet_object* new_contract_wallet = _db.find_account_by_ripemd160(new_contract_r160); + const en_address_type new_contract_r160 = uint256_t_to_ripemd160( contract_create(args, 0) ); + const wallet_object* new_contract_wallet = _db.find_account_by_en_address(new_contract_r160); ext_wallet_name = new_contract_wallet->name; ext_contract = _db.find_contract_by_wallet(ext_wallet_name); } @@ -2012,7 +1937,7 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type return std::make_pair(machine::word(1), contract_return); }; - std::function< machine::big_word(std::vector, machine::big_word, machine::big_word) > contract_create2 = [&_db, sha3, owner, caller, contract_hash](std::vector memory, machine::big_word value, machine::big_word salt) -> machine::big_word + std::function< machine::big_word(std::vector, machine::big_word, machine::big_word) > contract_create2 = [&_db, owner, caller, contract_hash](std::vector memory, machine::big_word value, machine::big_word salt) -> machine::big_word { // TODO: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1014.md const wallet_name_type sender_address = _db.get_contract(contract_hash).wallet; @@ -2026,13 +1951,16 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type std::stringstream ss; ss << salt; std::string salt_str = ss.str(); + ss.str(""); - std::string new_rlp_wallet_name = generate_rlp_wallet_name(std::string(sender_address), caller_contract_wallet.nonce, salt_str, memory); - std::cout << "NEW RLP WALLET NAME: " << new_rlp_wallet_name << std::endl; + std::string caller_en_address = caller_contract_wallet.en_address; + std::cout << "CALLER EN ADDRESS: " << caller_en_address << std::endl; + std::string new_wallet_en_address = generate_en_address(caller_en_address, caller_contract_wallet.nonce, salt_str, memory); + std::cout << "NEW EN WALLET NAME: " << new_wallet_en_address << std::endl; - wallet_create(_db, caller_contract_wallet.nonce, new_rlp_wallet_name); + wallet_create(_db, caller_contract_wallet.nonce, new_wallet_en_address); - const auto& new_wallet_name = _db.get_account_by_ripemd160(new_rlp_wallet_name).name; + const auto& new_wallet_name = _db.get_account_by_en_address(new_wallet_en_address).name; chain::contract_object base_contract = _db.create< contract_object >( [&](contract_object& c) { c.contract_hash = new_contract_hash; @@ -2079,15 +2007,12 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type co.code = result; }); - const std::string& address_ref = std::string(new_rlp_wallet_name); - - std::cout << "Address ref: " << address_ref << std::endl; + const std::string& address_ref = std::string(new_wallet_en_address); ss.str(""); ss << std::hex << address_ref; - boost::multiprecision::uint256_t x; - ss >> x; - boost::multiprecision::uint256_t new_contract_wallet_address = x; + uint256_t new_contract_wallet_address; + ss >> new_contract_wallet_address; _db.modify( caller_contract_wallet, [&]( wallet_object& acc ) { @@ -2131,11 +2056,10 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type std::function< bool(std::string) > self_destruct = [&](std::string address) -> bool { // TODO send all funds from contract to address - // std::stringstream ss; ss << std::hex << address; - const address_ripemd160_type r160 = ss.str(); - const auto& destination_wallet = _db.get_account_by_ripemd160(r160); + const en_address_type r160 = ss.str(); + const auto& destination_wallet = _db.get_account_by_en_address(r160); const auto& caller_contract_wallet = _db.get_account(owner); diff --git a/libraries/plugins/apis/contract_api/contract_api.cpp b/libraries/plugins/apis/contract_api/contract_api.cpp index 81ee1aed..9b17eb3b 100644 --- a/libraries/plugins/apis/contract_api/contract_api.cpp +++ b/libraries/plugins/apis/contract_api/contract_api.cpp @@ -78,8 +78,8 @@ DEFINE_API_IMPL( contract_api_impl, list_owner_contracts ) std::stringstream ss; ss << std::hex << r160.str(); - std::string address_ripemd160; - ss >> address_ripemd160; + std::string en_address; + ss >> en_address; api_contract_object ac; ac.id = c.id; @@ -87,7 +87,7 @@ DEFINE_API_IMPL( contract_api_impl, list_owner_contracts ) ac.contract_hash = c.contract_hash; ac.wallet = c.wallet; ac.code = c.code; - ac.address_ripemd160 = address_ripemd160; + ac.en_address = en_address; result.contracts.push_back(ac); ++itr; } diff --git a/libraries/plugins/apis/contract_api/include/xgt/plugins/contract_api/contract_api.hpp b/libraries/plugins/apis/contract_api/include/xgt/plugins/contract_api/contract_api.hpp index 1471be34..596bc631 100644 --- a/libraries/plugins/apis/contract_api/include/xgt/plugins/contract_api/contract_api.hpp +++ b/libraries/plugins/apis/contract_api/include/xgt/plugins/contract_api/contract_api.hpp @@ -19,7 +19,7 @@ struct api_contract_object chain::wallet_name_type owner; chain::wallet_name_type wallet; chain::contract_hash_type contract_hash; - std::string address_ripemd160; + std::string en_address; vector code; }; @@ -69,7 +69,7 @@ FC_REFLECT( xgt::plugins::contract::api_contract_object, (wallet) (contract_hash) (code) - (address_ripemd160) ) + (en_address) ) FC_REFLECT( xgt::plugins::contract::get_contract_args, (contract_hash) ) FC_REFLECT( xgt::plugins::contract::get_contract_return, (contract) ) diff --git a/libraries/plugins/apis/database_api/include/xgt/plugins/database_api/database_api_objects.hpp b/libraries/plugins/apis/database_api/include/xgt/plugins/database_api/database_api_objects.hpp index 6e6fcef4..a066e68c 100644 --- a/libraries/plugins/apis/database_api/include/xgt/plugins/database_api/database_api_objects.hpp +++ b/libraries/plugins/apis/database_api/include/xgt/plugins/database_api/database_api_objects.hpp @@ -106,7 +106,7 @@ struct api_wallet_object api_wallet_object( const wallet_object& a, const database& db ) : id( a.id ), name( a.name ), - address_ripemd160( a.address_ripemd160 ), + en_address( a.en_address ), memo_key( a.memo_key ), last_account_update( a.last_account_update ), created( a.created ), @@ -151,7 +151,7 @@ struct api_wallet_object wallet_id_type id; wallet_name_type name; - address_ripemd160_type address_ripemd160; + en_address_type en_address; authority recovery; authority money; authority social; @@ -372,7 +372,7 @@ FC_REFLECT( xgt::plugins::database_api::api_comment_vote_object, ) FC_REFLECT( xgt::plugins::database_api::api_wallet_object, - (id)(name)(address_ripemd160)(recovery)(money)(social)(memo_key)(json_metadata)(social_json_metadata)(last_recovery_update)(last_account_update) + (id)(name)(en_address)(recovery)(money)(social)(memo_key)(json_metadata)(social_json_metadata)(last_recovery_update)(last_account_update) (created)(mined) (recovery_account)(last_account_recovery)(reset_account) (comment_count)(lifetime_vote_count)(post_count)(can_vote)(energybar) diff --git a/libraries/protocol/include/xgt/protocol/schema_types/wallet_name_type.hpp b/libraries/protocol/include/xgt/protocol/schema_types/wallet_name_type.hpp index ff86c941..c2cd1f37 100644 --- a/libraries/protocol/include/xgt/protocol/schema_types/wallet_name_type.hpp +++ b/libraries/protocol/include/xgt/protocol/schema_types/wallet_name_type.hpp @@ -46,12 +46,12 @@ namespace xgt { namespace detail { ////////////////////////////////////////////// - // address_ripemd160_type // + // en_address_type // ////////////////////////////////////////////// - struct schema_address_ripemd160_type_impl : public abstract_schema + struct schema_en_address_type_impl : public abstract_schema { - XGT_SCHEMA_CLASS_BODY( schema_address_ripemd160_type_impl ) + XGT_SCHEMA_CLASS_BODY( schema_en_address_type_impl ) }; } diff --git a/libraries/protocol/include/xgt/protocol/types.hpp b/libraries/protocol/include/xgt/protocol/types.hpp index 47f9e891..b1b256e1 100644 --- a/libraries/protocol/include/xgt/protocol/types.hpp +++ b/libraries/protocol/include/xgt/protocol/types.hpp @@ -73,7 +73,7 @@ namespace xgt { typedef fc::sha256 chain_id_type; typedef fixed_string<8> xtt_ticker_type; typedef fixed_string<256> wallet_name_type; - typedef fixed_string<256> address_ripemd160_type; + typedef fixed_string<256> en_address_type; typedef fc::ripemd160 block_id_type; typedef fc::ripemd160 checksum_type; typedef fc::ripemd160 transaction_id_type; diff --git a/libraries/protocol/include/xgt/protocol/xgt_operations.hpp b/libraries/protocol/include/xgt/protocol/xgt_operations.hpp index 3f6af86d..66ec9aba 100644 --- a/libraries/protocol/include/xgt/protocol/xgt_operations.hpp +++ b/libraries/protocol/include/xgt/protocol/xgt_operations.hpp @@ -16,7 +16,7 @@ namespace xgt { namespace protocol { asset fee; wallet_name_type creator; wallet_name_type new_wallet_name; - string address_ripemd160; + string en_address; authority recovery; authority money; authority social; diff --git a/libraries/vendor/xgtvm/libraries/machine.cpp b/libraries/vendor/xgtvm/libraries/machine.cpp index 12e79620..e8a6493b 100644 --- a/libraries/vendor/xgtvm/libraries/machine.cpp +++ b/libraries/vendor/xgtvm/libraries/machine.cpp @@ -506,8 +506,7 @@ namespace machine } } - sstream << std::hex << adapter.sha3( retval ); - sstream >> vc; + vc = adapter.sha3( retval ); push_word( vc ); // hash } diff --git a/libraries/vendor/xgtvm/libraries/machine.hpp b/libraries/vendor/xgtvm/libraries/machine.hpp index 16452a48..93d552b3 100644 --- a/libraries/vendor/xgtvm/libraries/machine.hpp +++ b/libraries/vendor/xgtvm/libraries/machine.hpp @@ -222,7 +222,7 @@ namespace machine struct chain_adapter { // TODO sha3 opcode - std::function< std::string(std::vector) > sha3; + std::function< big_word(std::vector) > sha3; std::function< big_word(big_word) > get_balance; diff --git a/libraries/vendor/xgtvm/programs/xgtvm.cpp b/libraries/vendor/xgtvm/programs/xgtvm.cpp index fd6a33d0..c38e0beb 100644 --- a/libraries/vendor/xgtvm/programs/xgtvm.cpp +++ b/libraries/vendor/xgtvm/programs/xgtvm.cpp @@ -55,7 +55,7 @@ static struct option long_options[] = { // chain_adapter is state.host equivalent in evmone machine::chain_adapter make_chain_adapter() { - std::function< std::string(std::vector) > sha3 = [](std::vector memory) -> std::string + std::function< machine::big_word(std::vector) > sha3 = [](std::vector memory) -> machine::big_word { return 0; }; diff --git a/libraries/vendor/xgtvm/programs/xgtvm_tests.cpp b/libraries/vendor/xgtvm/programs/xgtvm_tests.cpp index cac11934..81db371f 100644 --- a/libraries/vendor/xgtvm/programs/xgtvm_tests.cpp +++ b/libraries/vendor/xgtvm/programs/xgtvm_tests.cpp @@ -11,7 +11,7 @@ machine::chain_adapter make_chain_adapter() { - std::function< std::string(std::vector) > sha3 = [](std::vector memory) -> std::string + std::function< machine::big_word(std::vector) > sha3 = [](std::vector memory) -> machine::big_word { std::cout << "chain_adapter::sha3" << std::endl; return 0; diff --git a/tasks/contracts.rake b/tasks/contracts.rake index 9391a65b..5028580c 100644 --- a/tasks/contracts.rake +++ b/tasks/contracts.rake @@ -222,10 +222,10 @@ namespace :contracts do bob_balance_before = get_wallet(bob)['balance']['amount'] charlie_balance_before = get_wallet(charlie)['balance']['amount'] - creator_address_r160 = get_wallet(creator)['address_ripemd160'] - alice_address_r160 = get_wallet(alice)['address_ripemd160'] - bob_address_r160 = get_wallet(bob)['address_ripemd160'] - charlie_address_r160 = get_wallet(charlie)['address_ripemd160'] + creator_address_r160 = get_wallet(creator)['en_address'] + alice_address_r160 = get_wallet(alice)['en_address'] + bob_address_r160 = get_wallet(bob)['en_address'] + charlie_address_r160 = get_wallet(charlie)['en_address'] puts "\n\nCreator address: #{creator}\nRipemd160: #{creator_address_r160}" puts "\n\nAlice address: #{alice}\nRipemd160: #{alice_address_r160}" @@ -375,7 +375,7 @@ namespace :contracts do puts JSON.pretty_generate response contract_hash = response['contracts'].first['contract_hash'] - calculator_contract_address = response['contracts'].select { |contract| contract['code'] == stripped_calculator_code}.first['address_ripemd160'] + calculator_contract_address = response['contracts'].select { |contract| contract['code'] == stripped_calculator_code}.first['en_address'] packed_calculator_contract_address = "000000000000000000000000#{calculator_contract_address}" puts "\n\nCalculator contract address: ", calculator_contract_address, "\n" From 284d65924b36af272f55982f0ff84300cf3ff066 Mon Sep 17 00:00:00 2001 From: Liam Noroian Date: Fri, 15 Apr 2022 10:55:49 -0700 Subject: [PATCH 89/96] add xgtvm typing system --- libraries/chain/xgt_evaluator.cpp | 61 +- libraries/vendor/xgtvm/libraries/machine.cpp | 933 ++++++++---------- libraries/vendor/xgtvm/libraries/machine.hpp | 303 +++++- libraries/vendor/xgtvm/programs/xgtvm.cpp | 40 +- .../vendor/xgtvm/programs/xgtvm_tests.cpp | 22 +- 5 files changed, 749 insertions(+), 610 deletions(-) diff --git a/libraries/chain/xgt_evaluator.cpp b/libraries/chain/xgt_evaluator.cpp index 572f4f38..5b280930 100644 --- a/libraries/chain/xgt_evaluator.cpp +++ b/libraries/chain/xgt_evaluator.cpp @@ -1267,20 +1267,15 @@ std::string generate_create2_address(std::string sender, std::string salt, std:: // Recipe: keccak256( 0xff ++ address ++ salt ++ keccak256(init_code))[12:] - std::cout << "INIT CODE CREATE2: " << init_code << std::endl; size_t init_code_size = init_code.size() / 2; uint8_t init_code_bytes[init_code_size]; hex_to_uint8(init_code, init_code_bytes); auto init_code_output = ethash_keccak256( init_code_bytes, init_code_size ); std::string init_code_hash = to_hex(init_code_output); - std::cout << "INIT CODE HASH CREATE2: " << init_code_hash << std::endl; - ss << "ff" << sender << salt << init_code_hash; std::string keccak_input_str = ss.str(); - std::cout << "KECCAK INPUT CREATE2: " << keccak_input_str << std::endl; - size_t size = keccak_input_str.size() / 2; uint8_t bytes[size]; hex_to_uint8(keccak_input_str, bytes); @@ -1289,9 +1284,6 @@ std::string generate_create2_address(std::string sender, std::string salt, std:: std::string untrimmed_address = to_hex(keccak_output); std::string generated_create2_address = untrimmed_address.substr(24, 40); - std::cout << "Target create2 address: " << target_address << std::endl; - std::cout << "Actual create2 address: " << generated_create2_address << std::endl; - return generated_create2_address; } @@ -1414,8 +1406,8 @@ std::vector contract_invoke(chain::database& _db, wallet_name_typ const uint64_t block_difficulty = static_cast( _db.get_pow_summary_target() ); const uint64_t block_energylimit = 0; const uint64_t tx_energyprice = 0; - std::string tx_origin = caller; // TODO update this - std::string block_coinbase = caller; // TODO update this to this block's miner + const uint256_t tx_origin = caller_en_address; // TODO update this + const uint256_t block_coinbase = caller_en_address; // TODO update this to this block's miner machine::context ctx = { is_debug, @@ -1535,21 +1527,11 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type std::function< machine::big_word(std::vector) > sha3 = [&](std::vector memory) -> machine::big_word { std::stringstream ss; - if (memory.size() > 32) { - for (size_t i = 0; i < memory.size(); i++) { - ss << "0000000000000000000000000000000"; - ss << std::hex << (machine::opcode)memory[i]; - } - } else { - for (size_t i = 0; i < memory.size(); i++) { - if ( (machine::opcode)memory[i] < 0x10 ) - ss << "0"; - ss << std::hex << (machine::opcode)memory[i]; - } + for (size_t i = 0; i < memory.size(); i++) { + ss << std::hex << (machine::opcode)memory[i]; } std::string memory_str = ss.str(); - std::cout << "KECCAK INPUT SHA3: " << memory_str << std::endl; size_t memory_size = memory_str.size() / 2; uint8_t memory_bytes[memory_size]; @@ -1561,7 +1543,6 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type ss << std::hex << memory_hash; uint256_t sha3_return; ss >> sha3_return; - std::cout << "INIT CODE HASH SHA3: " << memory_hash << std::endl; return sha3_return; }; @@ -1575,10 +1556,14 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type return static_cast(wallet.balance.amount.value); }; - std::function< std::string(std::string) > get_code_hash = [&](std::string address) -> std::string + std::function< machine::big_word(machine::big_word) > get_code_hash = [&](machine::big_word address) -> machine::big_word { - fc::ripemd160 en_address(address); - const auto& contract = _db.get_contract(en_address); + // TODO XXX: convert to ethash keccak256 + std::stringstream ss; + ss << address; + const en_address_type& en_address = ss.str(); + const wallet_object& contract_wallet = _db.get_account_by_en_address(en_address); + const auto& contract = _db.get_contract_by_wallet(contract_wallet.name); std::string message(contract.code.begin(), contract.code.end()); unsigned char output[32]; SHA3_CTX ctx; @@ -1586,7 +1571,10 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type keccak_update(&ctx, (unsigned char*)message.c_str(), message.size()); keccak_final(&ctx, output); std::string fin((char*)output, 32); - return fin; + uint256_t x; + ss << std::hex << fin; + ss >> x; + return x; }; // TODO: Revisit this, we may want to use the original sha256 hash @@ -1954,9 +1942,7 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type ss.str(""); std::string caller_en_address = caller_contract_wallet.en_address; - std::cout << "CALLER EN ADDRESS: " << caller_en_address << std::endl; std::string new_wallet_en_address = generate_en_address(caller_en_address, caller_contract_wallet.nonce, salt_str, memory); - std::cout << "NEW EN WALLET NAME: " << new_wallet_en_address << std::endl; wallet_create(_db, caller_contract_wallet.nonce, new_wallet_en_address); @@ -2022,8 +2008,6 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type acc.nonce = 1; }); - std::cout << "NEW CONTRACT WALLET ADDRESS: " << new_contract_wallet_address << std::endl; - return new_contract_wallet_address; } else { @@ -2053,13 +2037,13 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type return memory; }; - std::function< bool(std::string) > self_destruct = [&](std::string address) -> bool + std::function< bool(machine::big_word) > self_destruct = [&](machine::big_word address) -> bool { // TODO send all funds from contract to address std::stringstream ss; - ss << std::hex << address; - const en_address_type r160 = ss.str(); - const auto& destination_wallet = _db.get_account_by_en_address(r160); + ss << address; + const en_address_type en_address = ss.str(); + const auto& destination_wallet = _db.get_account_by_en_address(en_address); const auto& caller_contract_wallet = _db.get_account(owner); @@ -2079,12 +2063,6 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type return true; }; - std::function< std::vector(std::string) > get_input_data = [&](std::string input) -> std::vector - { - // TODO - return std::vector(); - }; - std::function< void(const machine::log_object&) > emit_log = [&](const machine::log_object& log) { _db.create< contract_log_object >( [&](contract_log_object& cl) @@ -2117,7 +2095,6 @@ machine::chain_adapter make_chain_adapter(chain::database& _db, wallet_name_type set_storage, contract_return, self_destruct, - get_input_data, emit_log }; diff --git a/libraries/vendor/xgtvm/libraries/machine.cpp b/libraries/vendor/xgtvm/libraries/machine.cpp index e8a6493b..e7b799d4 100644 --- a/libraries/vendor/xgtvm/libraries/machine.cpp +++ b/libraries/vendor/xgtvm/libraries/machine.cpp @@ -38,125 +38,130 @@ namespace machine return x.convert_to(); } - big_word to_big_word(int64_t a) + typed_big_word to_typed_big_word(int64_t a, bool is_sparse = false) { - return a; + return typed_big_word(a, is_sparse); } - big_word to_big_word(size_t a) + typed_big_word to_typed_big_word(size_t a, bool is_sparse = false) { - return a; + return typed_big_word(a, is_sparse); } - big_word to_big_word(word a) + typed_big_word to_typed_big_word(typed_word a, bool is_sparse = false) { - return a; + return typed_big_word(a.value, is_sparse); } - big_word to_big_word(word a, word b) + typed_big_word to_typed_big_word(typed_word a, typed_word b, bool is_sparse = false) { - big_word va = ((big_word)a << 8) | b; + typed_big_word va = (to_typed_big_word(a).value << 8) | to_typed_big_word(b).value; + va.is_sparse = is_sparse; return va; } - big_word to_big_word(word a, word b, word c, word d) + typed_big_word to_typed_big_word(typed_word a, typed_word b, typed_word c, typed_word d, bool is_sparse = false) { - big_word va = ((big_word)a << 8) | b; - big_word vb = (va << 8) | c; - big_word vc = (vb << 8) | d; + typed_big_word va = (to_typed_big_word(a).value << 8) | to_typed_big_word(b).value; + typed_big_word vb = (va.value << 8) | c.value; + typed_big_word vc = (vb.value << 8) | d.value; + vc.is_sparse = is_sparse; return vc; } - big_word to_big_word(word a, word b, word c, word d, word e, word f, word g, word h) + typed_big_word to_typed_big_word(typed_word a, typed_word b, typed_word c, typed_word d, typed_word e, typed_word f, typed_word g, typed_word h, bool is_sparse = false) { - big_word va = ((big_word)a << 8) | b; - big_word vb = (va << 8) | c; - big_word vc = (vb << 8) | d; - big_word vd = (vc << 8) | e; - big_word ve = (vd << 8) | f; - big_word vf = (ve << 8) | g; - big_word vg = (vf << 8) | h; + typed_big_word va = (to_typed_big_word(a).value << 8) | to_typed_big_word(b).value; + typed_big_word vb = (va.value << 8) | c.value; + typed_big_word vc = (vb.value << 8) | d.value; + typed_big_word vd = (vc.value << 8) | e.value; + typed_big_word ve = (vd.value << 8) | f.value; + typed_big_word vf = (ve.value << 8) | g.value; + typed_big_word vg = (vf.value << 8) | h.value; + vg.is_sparse = is_sparse; return vg; } - big_word to_big_word(word a, word b, word c, word d, word e, word f, word g, - word h, word i, word j, word k, word l, word m, word n, word o, word p) + typed_big_word to_typed_big_word(typed_word a, typed_word b, typed_word c, typed_word d, typed_word e, typed_word f, typed_word g, + typed_word h, typed_word i, typed_word j, typed_word k, typed_word l, typed_word m, typed_word n, typed_word o, typed_word p, bool is_sparse = false) { - big_word va = ((big_word)a << 8) | b; - big_word vb = (va << 8) | c; - big_word vc = (vb << 8) | d; - big_word vd = (vc << 8) | e; - big_word ve = (vd << 8) | f; - big_word vf = (ve << 8) | g; - big_word vg = (vf << 8) | h; - big_word vh = (vg << 8) | i; - big_word vi = (vh << 8) | j; - big_word vj = (vi << 8) | k; - big_word vk = (vj << 8) | l; - big_word vl = (vk << 8) | m; - big_word vm = (vl << 8) | n; - big_word vn = (vm << 8) | o; - big_word vo = (vn << 8) | p; + typed_big_word va = (to_typed_big_word(a).value << 8) | to_typed_big_word(b).value; + typed_big_word vb = (va.value << 8) | c.value; + typed_big_word vc = (vb.value << 8) | d.value; + typed_big_word vd = (vc.value << 8) | e.value; + typed_big_word ve = (vd.value << 8) | f.value; + typed_big_word vf = (ve.value << 8) | g.value; + typed_big_word vg = (vf.value << 8) | h.value; + typed_big_word vh = (vg.value << 8) | i.value; + typed_big_word vi = (vh.value << 8) | j.value; + typed_big_word vj = (vi.value << 8) | k.value; + typed_big_word vk = (vj.value << 8) | l.value; + typed_big_word vl = (vk.value << 8) | m.value; + typed_big_word vm = (vl.value << 8) | n.value; + typed_big_word vn = (vm.value << 8) | o.value; + typed_big_word vo = (vn.value << 8) | p.value; + vo.is_sparse = is_sparse; return vo; } - big_word to_big_word(word a, word b, word c, word d, word e, word f, word g, - word h, word i, word j, word k, word l, word m, word n, word o, word p, - word q, word r, word s, word t, word u, word v, word w, word x, word y, - word z, word aa, word ab, word ac, word ad, word ae, word af) + typed_big_word to_typed_big_word(typed_word a, typed_word b, typed_word c, typed_word d, typed_word e, typed_word f, typed_word g, + typed_word h, typed_word i, typed_word j, typed_word k, typed_word l, typed_word m, typed_word n, typed_word o, typed_word p, + typed_word q, typed_word r, typed_word s, typed_word t, typed_word u, typed_word v, typed_word w, typed_word x, typed_word y, + typed_word z, typed_word aa, typed_word ab, typed_word ac, typed_word ad, typed_word ae, typed_word af, bool is_sparse = false) { - big_word va = ((big_word)a << 8) | b; - big_word vb = (va << 8) | c; - big_word vc = (vb << 8) | d; - big_word vd = (vc << 8) | e; - big_word ve = (vd << 8) | f; - big_word vf = (ve << 8) | g; - big_word vg = (vf << 8) | h; - big_word vh = (vg << 8) | i; - big_word vi = (vh << 8) | j; - big_word vj = (vi << 8) | k; - big_word vk = (vj << 8) | l; - big_word vl = (vk << 8) | m; - big_word vm = (vl << 8) | n; - big_word vn = (vm << 8) | o; - big_word vo = (vn << 8) | p; - big_word vp = (vo << 8) | q; - big_word vq = (vp << 8) | r; - big_word vr = (vq << 8) | s; - big_word vs = (vr << 8) | t; - big_word vt = (vs << 8) | u; - big_word vu = (vt << 8) | v; - big_word vv = (vu << 8) | w; - big_word vw = (vv << 8) | x; - big_word vx = (vw << 8) | y; - big_word vy = (vx << 8) | z; - big_word vz = (vy << 8) | aa; - big_word vaa = (vz << 8) | ab; - big_word vab = (vaa << 8) | ac; - big_word vac = (vab << 8) | ad; - big_word vad = (vac << 8) | ae; - big_word vae = (vad << 8) | af; + typed_big_word va = (to_typed_big_word(a).value << 8) | to_typed_big_word(b).value; + typed_big_word vb = (va.value << 8) | c.value; + typed_big_word vc = (vb.value << 8) | d.value; + typed_big_word vd = (vc.value << 8) | e.value; + typed_big_word ve = (vd.value << 8) | f.value; + typed_big_word vf = (ve.value << 8) | g.value; + typed_big_word vg = (vf.value << 8) | h.value; + typed_big_word vh = (vg.value << 8) | i.value; + typed_big_word vi = (vh.value << 8) | j.value; + typed_big_word vj = (vi.value << 8) | k.value; + typed_big_word vk = (vj.value << 8) | l.value; + typed_big_word vl = (vk.value << 8) | m.value; + typed_big_word vm = (vl.value << 8) | n.value; + typed_big_word vn = (vm.value << 8) | o.value; + typed_big_word vo = (vn.value << 8) | p.value; + typed_big_word vp = (vo.value << 8) | q.value; + typed_big_word vq = (vp.value << 8) | r.value; + typed_big_word vr = (vq.value << 8) | s.value; + typed_big_word vs = (vr.value << 8) | t.value; + typed_big_word vt = (vs.value << 8) | u.value; + typed_big_word vu = (vt.value << 8) | v.value; + typed_big_word vv = (vu.value << 8) | w.value; + typed_big_word vw = (vv.value << 8) | x.value; + typed_big_word vx = (vw.value << 8) | y.value; + typed_big_word vy = (vx.value << 8) | z.value; + typed_big_word vz = (vy.value << 8) | aa.value; + typed_big_word vaa = (vz.value << 8) | ab.value; + typed_big_word vab = (vaa.value << 8) | ac.value; + typed_big_word vac = (vab.value << 8) | ad.value; + typed_big_word vad = (vac.value << 8) | ae.value; + typed_big_word vae = (vad.value << 8) | af.value; + vae.is_sparse = is_sparse; return vae; } - std::vector from_big_word(big_word a) + std::vector from_typed_big_word(typed_big_word a) { - std::vector vec; - vec.push_back(static_cast(a & 0xFF)); + std::vector vec; + vec.push_back( typed_word( static_cast(a.value & 0xFF), a.is_sparse ) ); for (size_t i = 0; i < 31; i++) { - vec.push_back(static_cast(((a >>= 8) & 0xFF))); + vec.push_back( typed_word( static_cast( (a.value >>= 8) & 0xFF ), a.is_sparse ) ); } return vec; } - std::string inspect(std::vector words) + std::string inspect(std::vector words) { std::stringstream ss; ss << "["; for (size_t i = 0; i < words.size(); i++) { - ss << std::to_string(words.at(i)); + ss << std::to_string(words.at(i).value); if (i != words.size() - 1) ss << ", "; } @@ -164,21 +169,21 @@ namespace machine return ss.str(); } - std::string inspect(std::map words) + std::string inspect(std::map words) { std::stringstream ss; ss << "["; - std::map::iterator it; + std::map::iterator it; size_t i = 0; while(true) { it = words.find(i); if (it != words.end()) { - ss << std::to_string(it->second); + ss << std::to_string(it->second.value); ss << ", "; } else { - ss << std::to_string(it->second); + ss << std::to_string(it->second.value); break; } i++; @@ -187,46 +192,30 @@ namespace machine return ss.str(); } - void machine::push_word(stack_variant v) + void machine::push_word(typed_big_word v) { stack.push_front(v); } - big_word machine::pop_word() + typed_big_word machine::pop_word() { - stack_variant& stack_object = stack.front(); - if (big_word* it = boost::get(&stack_object)) - { - stack.pop_front(); - return *it; - } - throw; - } - - big_word machine::peek_word() - { - stack_variant& stack_object = stack.front(); - if (big_word* it = boost::get(&stack_object)) - { - stack.pop_front(); - return *it; - } - else { - throw; - } + typed_big_word& stack_object = stack.front(); + stack.pop_front(); + return stack_object; } - void machine::push_string(std::string s) + typed_big_word machine::peek_word() { - stack.push_front(s); + typed_big_word& stack_object = stack.front(); + return stack_object; } void machine::print_stack() { for (auto it = stack.cbegin(); it != stack.cend(); ++it) { - stack_variant w = *it; - logger << w; + typed_big_word w = *it; + logger << w.value; if (it + 1 != stack.cend()) logger << " "; } @@ -255,22 +244,21 @@ namespace machine // Allow to skip evaluation by throwing exception. // TODO: Verify this behavior. - word a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, + typed_word a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, aa, ab, ac, ad, ae, af; - big_word va, vb, vc, vd, ve, vf, vg, vh, vi, vj, vk, vl, vm, vn, vo, vp, vq; + typed_big_word va, vb, vc, vd, ve, vf, vg, vh, vi, vj, vk, vl, vm, vn, vo, vp, vq; word jumpdest_instruction; opcode jumpdest_op; - stack_variant sv; - signed_big_word sa, sb, sc; + typed_signed_big_word sa, sb, sc; size_t offset, dest_offset, length, code_size = 0; - std::vector vec1; + // TODO XXX convert words to typed_words + std::vector vec1; std::vector contract_args; std::vector retval; std::vector ext_contract_code; std::pair< word, std::vector > contract_call_return; - std::vector::const_iterator first, last; - std::string* ss; + std::vector::const_iterator first, last; std::stringstream sstream; switch (op) { @@ -304,18 +292,18 @@ namespace machine logger << "op div" << std::endl; va = pop_word(); vb = pop_word(); - if (vb == 0) - push_word(word(0)); + if ( vb == typed_big_word(0) ) + push_word( typed_big_word(0) ); else vc = va / vb; push_word(vc); break; case sdiv_opcode: logger << "op sdiv" << std::endl; - sa = alias_to_int256_t( pop_word() ); - sb = alias_to_int256_t( pop_word() ); + sa = alias_to_int256_t( pop_word().value ); + sb = alias_to_int256_t( pop_word().value ); sc = sa / sb; - push_word( alias_to_uint256_t(sc) ); + push_word( alias_to_uint256_t(sc.value) ); break; case mod_opcode: logger << "op mod" << std::endl; @@ -326,10 +314,10 @@ namespace machine break; case smod_opcode: logger << "op smod" << std::endl; - sa = alias_to_int256_t( pop_word() ); - sb = alias_to_int256_t( pop_word() ); + sa = alias_to_int256_t( pop_word().value ); + sb = alias_to_int256_t( pop_word().value ); sc = sa % sb; - push_word( alias_to_uint256_t(sc) ); + push_word( alias_to_uint256_t(sc.value) ); break; case addmod_opcode: logger << "op addmod" << std::endl; @@ -354,69 +342,69 @@ namespace machine logger << "op exp" << std::endl; va = pop_word(); // base vb = pop_word(); // exponent - vc = 1; - for (int i = 0; i < vb; i++) { + vc = typed_big_word(1); + for (int i = 0; i < vb.value; i++) { vc *= va; } push_word(vc); break; case signextend_opcode: logger << "op signextend" << std::endl; - sa = alias_to_int256_t( pop_word() ); // b - sb = alias_to_int256_t( pop_word() ); // x + sa = alias_to_int256_t( pop_word().value ); // b + sb = alias_to_int256_t( pop_word().value ); // x - if (sa < 31) + if (sa.value < 31) { - unsigned testBit = static_cast(sa) * 8 + 7; - big_word one = 1; - big_word mask = ((one << testBit) - 1); - if (sb & (one << testBit)) - sc = sb | ~mask; + unsigned testBit = static_cast(sa.value) * 8 + 7; + typed_big_word one(1); + typed_big_word mask = ((one.value << testBit) - 1); + if ( (sb & static_cast( (one.value << testBit) ) ) != typed_signed_big_word(0) ) + sc = sb.value | static_cast(~mask.value); else - sc = sb & mask; + sc = sb.value & static_cast(mask.value); } - push_word( alias_to_uint256_t(sc) ); + push_word( alias_to_uint256_t(sc.value) ); break; case lt_opcode: logger << "op lt" << std::endl; va = pop_word(); vb = pop_word(); - vc = va < vb; + vc = typed_big_word(va < vb); push_word(vc); break; case gt_opcode: logger << "op gt" << std::endl; va = pop_word(); vb = pop_word(); - vc = va > vb; + vc = typed_big_word(va > vb); push_word(vc); break; case slt_opcode: logger << "op stl" << std::endl; - sa = alias_to_int256_t( pop_word() ); - sb = alias_to_int256_t( pop_word() ); - sc = sa < sb; - push_word( alias_to_uint256_t(sc) ); + sa = alias_to_int256_t( pop_word().value ); + sb = alias_to_int256_t( pop_word().value ); + sc = sa < sb ? typed_signed_big_word(1) : typed_signed_big_word(0); + push_word( alias_to_uint256_t(sc.value) ); break; case sgt_opcode: logger << "op sgt" << std::endl; - sa = alias_to_int256_t( pop_word() ); - sb = alias_to_int256_t( pop_word() ); - sc = sa > sb; - push_word( alias_to_uint256_t(sc) ); + sa = alias_to_int256_t( pop_word().value ); + sb = alias_to_int256_t( pop_word().value ); + sc = sa > sb ? typed_signed_big_word(1) : typed_signed_big_word(0); + push_word( alias_to_uint256_t(sc.value) ); break; case eq_opcode: logger << "op eq" << std::endl; va = pop_word(); vb = pop_word(); - vc = va == vb; + vc = va == vb ? typed_big_word(1) : typed_big_word(0); push_word(vc); break; case iszero_opcode: logger << "op iszero" << std::endl; va = pop_word(); - vb = va == 0; + vb = va == typed_big_word(0) ? typed_big_word(1) : typed_big_word(0); push_word(vb); break; case and_opcode: @@ -449,12 +437,12 @@ namespace machine case byte_opcode: logger << "op byte" << std::endl; - sa = pop_word(); // index - sb = pop_word(); // num + sa = static_cast( pop_word().value ); // index + sb = static_cast( pop_word().value ); // num - sc = sa < 32 ? (sb >> (unsigned)(8 * (31 - sa))) & 0xff : 0; + sc = sa.value < 32 ? (sb.value >> (unsigned)(8 * (31 - sa.value))) & 0xff : 0; - push_word( alias_to_uint256_t(sc) ); + push_word( alias_to_uint256_t(sc.value) ); break; case shl_opcode: logger << "op shl" << std::endl; @@ -462,7 +450,7 @@ namespace machine va = pop_word(); // shift vb = pop_word(); // value - vc = vb << static_cast(va); + vc = vb.value << static_cast(va.value); push_word(vc); break; @@ -472,17 +460,17 @@ namespace machine vb = pop_word(); // value // TODO Implement shift in a loop for va sizes larger than 256 - vc = vb >> static_cast(va); + vc = vb.value >> static_cast(va.value); push_word(vc); break; case sar_opcode: logger << "op sar" << std::endl; - sa = alias_to_int256_t( pop_word() ); // shift - sb = pop_word(); // value + sa = alias_to_int256_t( pop_word().value ); // shift + sb = static_cast( pop_word().value ); // value - sc = sb >> sa.convert_to(); - push_word( alias_to_uint256_t(sc) ); + sc = sb.value >> static_cast(sa.value); + push_word( alias_to_uint256_t(sc.value) ); break; case sha3_opcode: @@ -490,19 +478,28 @@ namespace machine va = pop_word(); // offset vb = pop_word(); // length - // TODO handle case where length of memory segment is 0, stack needs a 0 pushed - - if (vb == 0) { - push_word(0); + if ( vb == typed_big_word(0) ) { + push_word( typed_big_word(0) ); } else { - for (size_t i = static_cast(va); i < static_cast(va) + static_cast(vb); i++) { - std::map::iterator it; + for (size_t i = static_cast(va.value); i < static_cast(va.value) + static_cast(vb.value); i++) { + std::map::iterator it; it = memory.find(i); if (it != memory.end()) { - retval.push_back(it->second); + if ( it->second.is_sparse ) { + for (size_t i = 0; i < 31; i++) { + retval.push_back( word(0) ); + } + } + retval.push_back( word(it->second.value) ); } else { - retval.push_back(word(0)); + if ( it->second.is_sparse ) { + for (size_t i = 0; i < 32; i++) { + retval.push_back( word(0) ); + } + } else { + retval.push_back( word(0) ); + } } } @@ -513,12 +510,12 @@ namespace machine break; case address_opcode: logger << "op address" << std::endl; - push_word( msg.destination ); + push_word( typed_big_word(msg.destination) ); break; case balance_opcode: logger << "op balance" << std::endl; va = pop_word(); - push_word( adapter.get_balance(va) ); + push_word( typed_big_word( adapter.get_balance(va.value) ) ); break; case origin_opcode: logger << "op origin" << std::endl; @@ -530,18 +527,19 @@ namespace machine break; case callvalue_opcode: logger << "op callvalue" << std::endl; - push_word( msg.value ); + push_word( typed_big_word(msg.value) ); break; case calldataload_opcode: logger << "op calldataload" << std::endl; - offset = static_cast( pop_word() ); + va = pop_word(); + offset = static_cast( va.value ); if (offset > msg.input_size) { logger << "calldataload start index is larger than message input_size" << std::endl; break; } - va = to_big_word( + vb = to_typed_big_word( msg.input_data[offset + 0], msg.input_data[offset + 1], msg.input_data[offset + 2], @@ -573,82 +571,93 @@ namespace machine msg.input_data[offset + 28], msg.input_data[offset + 29], msg.input_data[offset + 30], - msg.input_data[offset + 31] + msg.input_data[offset + 31], + true ); - push_word(va); + + push_word(vb); break; case calldatasize_opcode: logger << "op calldatasize" << std::endl; - push_word( to_big_word(msg.input_size) ); + push_word( to_typed_big_word(msg.input_size) ); break; case calldatacopy_opcode: logger << "op calldatacopy" << std::endl; - dest_offset = static_cast( pop_word() ); - offset = static_cast( pop_word() ); - length = static_cast( pop_word() ); + dest_offset = static_cast( pop_word().value ); + offset = static_cast( pop_word().value ); + length = static_cast( pop_word().value ); if ((offset + length) > msg.input_size) { logger << "calldatacopy end index is larger than message input_size" << std::endl; break; } - for (size_t i = 0; i < length; ++i) - memory[dest_offset + i] = msg.input_data[offset + i]; + for (size_t i = 0; i < length; ++i) { + memory[dest_offset + i] = typed_word(msg.input_data[offset + i], true); + // TODO This isn't being set correctly in the constructor + memory[dest_offset + i].is_sparse = true; + } break; case codesize_opcode: logger << "op codesize" << std::endl; - push_word( to_big_word( code.size() ) ); + push_word( to_typed_big_word( code.size() ) ); break; case codecopy_opcode: logger << "op codecopy" << std::endl; - dest_offset = static_cast( pop_word() ); - offset = static_cast( pop_word() ); - length = static_cast( pop_word() ); + dest_offset = static_cast( pop_word().value ); + offset = static_cast( pop_word().value ); + length = static_cast( pop_word().value ); - for (size_t i = 0; i < length; ++i) - memory[dest_offset + i] = code[offset + i]; + for (size_t i = 0; i < length; ++i) { + memory[dest_offset + i] = typed_word(code[offset + i], true); + // TODO This isn't being set correctly in the constructor + memory[dest_offset + i].is_sparse = true; + } break; case energyprice_opcode: logger << "op energyprice" << std::endl; - push_word( to_big_word( ctx.tx_energyprice ) ); + push_word( to_typed_big_word( ctx.tx_energyprice ) ); break; case extcodesize_opcode: logger << "op extcodesize" << std::endl; va = pop_word(); // Address - ext_contract_code = adapter.get_code_at_addr(va); - push_word( sizeof(ext_contract_code) / sizeof(ext_contract_code[0]) ); + ext_contract_code = adapter.get_code_at_addr(va.value); + push_word( typed_big_word( sizeof(ext_contract_code) / sizeof(ext_contract_code[0]) ) ); break; case extcodecopy_opcode: logger << "op extcodecopy" << std::endl; va = pop_word(); // address - ext_contract_code = adapter.get_code_at_addr(va); + ext_contract_code = adapter.get_code_at_addr(va.value); code_size = sizeof(ext_contract_code) / sizeof(ext_contract_code[0]); - dest_offset = static_cast( pop_word() ); - offset = static_cast( pop_word() ); - length = static_cast( pop_word() ); + dest_offset = static_cast( pop_word().value ); + offset = static_cast( pop_word().value ); + length = static_cast( pop_word().value ); if ((offset + length) > code_size) { logger << "codecopy end index exceeds external contract code length" << std::endl; break; } - for (size_t i = 0; i < length; ++i) - memory[dest_offset + i] = ext_contract_code[offset + i]; + for (size_t i = 0; i < length; ++i) { + memory[dest_offset + i] = typed_word(ext_contract_code[offset + i], true); + // TODO This isn't being set correctly in the constructor + memory[dest_offset + i].is_sparse = true; + } break; case returndatasize_opcode: logger << "op returndatasize" << std::endl; - push_word( ext_return_data.size() ); + push_word( typed_big_word( ext_return_data.size() ) ); break; case returndatacopy_opcode: logger << "op returndatacopy" << std::endl; - dest_offset = static_cast( pop_word() ); - offset = static_cast( pop_word() ); - length = static_cast( pop_word() ); + dest_offset = static_cast( pop_word().value ); + offset = static_cast( pop_word().value ); + length = static_cast( pop_word().value ); if ( (offset + length) > ext_return_data.size() ) { logger << "returndatacopy end index exceeds return data size" << std::endl; @@ -661,47 +670,37 @@ namespace machine break; case extcodehash_opcode: logger << "op extcodehash" << std::endl; - sv = stack.front(); // addr - ss = boost::get(&sv); - if (ss) - { - stack.pop_front(); - push_word( adapter.get_code_hash(*ss) ); - } - else - { - state = machine_state::error; - error_message.emplace("Extcodehash operation type error"); - } + va = pop_word(); // addr + push_word( typed_big_word( adapter.get_code_hash(va.value) ) ); break; case blockhash_opcode: logger << "op blockhash" << std::endl; va = pop_word(); - push_word( adapter.get_block_hash( static_cast(va) ) ); + push_word( adapter.get_block_hash( static_cast(va.value) ) ); break; case coinbase_opcode: logger << "op coinbase" << std::endl; - push_word( ctx.block_coinbase ); + push_word( typed_big_word(ctx.block_coinbase) ); break; case timestamp_opcode: logger << "op timestamp" << std::endl; - push_word( ctx.block_timestamp ); + push_word( typed_big_word(ctx.block_timestamp) ); break; case number_opcode: logger << "op number" << std::endl; - push_word( ctx.block_number ); + push_word( typed_big_word(ctx.block_number) ); break; case difficulty_opcode: logger << "op difficulty" << std::endl; - push_word( ctx.block_difficulty ); + push_word( typed_big_word(ctx.block_difficulty) ); break; case energylimit_opcode: logger << "op energylimit" << std::endl; - push_word( ctx.block_energylimit ); + push_word( typed_big_word(ctx.block_energylimit) ); break; case selfbalance_opcode: logger << "op selfbalance" << std::endl; - push_word( adapter.get_balance(msg.destination) ); + push_word( adapter.get_balance( msg.destination ) ); break; case pop_opcode: logger << "op pop" << std::endl; @@ -710,40 +709,42 @@ namespace machine case mload_opcode: logger << "op mload" << std::endl; va = pop_word(); // offset - vb = to_big_word( - memory[static_cast(va) + 0], - memory[static_cast(va) + 1], - memory[static_cast(va) + 2], - memory[static_cast(va) + 3], - memory[static_cast(va) + 4], - memory[static_cast(va) + 5], - memory[static_cast(va) + 6], - memory[static_cast(va) + 7], - memory[static_cast(va) + 8], - memory[static_cast(va) + 9], - memory[static_cast(va) + 10], - memory[static_cast(va) + 11], - memory[static_cast(va) + 12], - memory[static_cast(va) + 13], - memory[static_cast(va) + 14], - memory[static_cast(va) + 15], - memory[static_cast(va) + 16], - memory[static_cast(va) + 17], - memory[static_cast(va) + 18], - memory[static_cast(va) + 19], - memory[static_cast(va) + 20], - memory[static_cast(va) + 21], - memory[static_cast(va) + 22], - memory[static_cast(va) + 23], - memory[static_cast(va) + 24], - memory[static_cast(va) + 25], - memory[static_cast(va) + 26], - memory[static_cast(va) + 27], - memory[static_cast(va) + 28], - memory[static_cast(va) + 29], - memory[static_cast(va) + 30], - memory[static_cast(va) + 31] + vb = to_typed_big_word( + memory[static_cast(va.value) + 0], + memory[static_cast(va.value) + 1], + memory[static_cast(va.value) + 2], + memory[static_cast(va.value) + 3], + memory[static_cast(va.value) + 4], + memory[static_cast(va.value) + 5], + memory[static_cast(va.value) + 6], + memory[static_cast(va.value) + 7], + memory[static_cast(va.value) + 8], + memory[static_cast(va.value) + 9], + memory[static_cast(va.value) + 10], + memory[static_cast(va.value) + 11], + memory[static_cast(va.value) + 12], + memory[static_cast(va.value) + 13], + memory[static_cast(va.value) + 14], + memory[static_cast(va.value) + 15], + memory[static_cast(va.value) + 16], + memory[static_cast(va.value) + 17], + memory[static_cast(va.value) + 18], + memory[static_cast(va.value) + 19], + memory[static_cast(va.value) + 20], + memory[static_cast(va.value) + 21], + memory[static_cast(va.value) + 22], + memory[static_cast(va.value) + 23], + memory[static_cast(va.value) + 24], + memory[static_cast(va.value) + 25], + memory[static_cast(va.value) + 26], + memory[static_cast(va.value) + 27], + memory[static_cast(va.value) + 28], + memory[static_cast(va.value) + 29], + memory[static_cast(va.value) + 30], + memory[static_cast(va.value) + 31], + memory[static_cast(va.value)].is_sparse ); + push_word(vb); break; case mstore_opcode: @@ -752,40 +753,10 @@ namespace machine vb = pop_word(); // value logger << "memory before: " << inspect(memory) << std::endl; - vec1 = from_big_word(vb); - - memory[static_cast(va) + 0] = vec1[31]; - memory[static_cast(va) + 1] = vec1[30]; - memory[static_cast(va) + 2] = vec1[29]; - memory[static_cast(va) + 3] = vec1[28]; - memory[static_cast(va) + 4] = vec1[27]; - memory[static_cast(va) + 5] = vec1[26]; - memory[static_cast(va) + 6] = vec1[25]; - memory[static_cast(va) + 7] = vec1[24]; - memory[static_cast(va) + 8] = vec1[23]; - memory[static_cast(va) + 9] = vec1[22]; - memory[static_cast(va) + 10] = vec1[21]; - memory[static_cast(va) + 11] = vec1[20]; - memory[static_cast(va) + 12] = vec1[19]; - memory[static_cast(va) + 13] = vec1[18]; - memory[static_cast(va) + 14] = vec1[17]; - memory[static_cast(va) + 15] = vec1[16]; - memory[static_cast(va) + 16] = vec1[15]; - memory[static_cast(va) + 17] = vec1[14]; - memory[static_cast(va) + 18] = vec1[13]; - memory[static_cast(va) + 19] = vec1[12]; - memory[static_cast(va) + 20] = vec1[11]; - memory[static_cast(va) + 21] = vec1[10]; - memory[static_cast(va) + 22] = vec1[9]; - memory[static_cast(va) + 23] = vec1[8]; - memory[static_cast(va) + 24] = vec1[7]; - memory[static_cast(va) + 25] = vec1[6]; - memory[static_cast(va) + 26] = vec1[5]; - memory[static_cast(va) + 27] = vec1[4]; - memory[static_cast(va) + 28] = vec1[3]; - memory[static_cast(va) + 29] = vec1[2]; - memory[static_cast(va) + 30] = vec1[1]; - memory[static_cast(va) + 31] = vec1[0]; + vec1 = from_typed_big_word(vb); + for (size_t i = 0; i < 32; i++) + memory[static_cast(va.value) + i] = vec1[31 - i]; + logger << "memory after: " << inspect(memory) << std::endl; break; case mstore8_opcode: @@ -793,14 +764,13 @@ namespace machine va = pop_word(); // offset vb = pop_word(); // value logger << "memory before: " << inspect(memory) << std::endl; - // TODO: Verify order - memory[static_cast(va)] = get_byte(vb, 0); // TODO verify byte of big_word vb + memory[static_cast(va.value)] = get_byte(vb.value, 0); // TODO verify byte of typed_big_word vb logger << "memory after: " << inspect(memory) << std::endl; break; case sload_opcode: logger << "op sload" << std::endl; va = pop_word(); - vb = adapter.get_storage(va); + vb = typed_big_word( adapter.get_storage(va.value) ); push_word(vb); break; @@ -809,16 +779,16 @@ namespace machine va = pop_word(); vb = pop_word(); - adapter.set_storage(va, vb); + adapter.set_storage(va.value, vb.value); break; case jump_opcode: logger << "op jump" << std::endl; va = pop_word(); // destination - jumpdest_instruction = code[get_bytes(va, 0)]; + jumpdest_instruction = code[get_bytes( va.value, 0 )]; jumpdest_op = (opcode)jumpdest_instruction; if (jumpdest_op == jumpdest_opcode) - pc = get_bytes(va, 0); + pc = get_bytes( va.value, 0 ); break; case jumpi_opcode: logger << "op jumpi" << std::endl; @@ -826,21 +796,21 @@ namespace machine va = pop_word(); // destination vb = pop_word(); // condition - if (vb != 0) { - jumpdest_instruction = code[get_bytes(va, 0)]; + if (vb != typed_big_word(0)) { + jumpdest_instruction = code[get_bytes( va.value, 0 )]; jumpdest_op = (opcode)jumpdest_instruction; if (jumpdest_op == jumpdest_opcode) - pc = get_bytes(va, 0); + pc = get_bytes( va.value, 0 ); } break; case pc_opcode: logger << "op pc" << std::endl; - va = pc; + va = typed_big_word(pc); push_word(va); break; case msize_opcode: logger << "op msize" << std::endl; - push_word( to_big_word( memory.size() ) ); + push_word( to_typed_big_word( memory.size() ) ); break; case energy_opcode: logger << "op energy" << std::endl; @@ -853,7 +823,7 @@ namespace machine logger << "op push1" << std::endl; a = code[pc]; pc++; - push_word(a); + push_word(to_typed_big_word(a)); break; case push2_opcode: logger << "op push2" << std::endl; @@ -861,7 +831,7 @@ namespace machine pc++; b = code[pc]; pc++; - va = to_big_word(a, b); + va = to_typed_big_word(a, b); push_word(va); break; case push3_opcode: @@ -872,7 +842,7 @@ namespace machine pc++; c = code[pc]; pc++; - va = to_big_word(0, a, b, c); + va = to_typed_big_word(0, a, b, c); push_word(va); break; case push4_opcode: @@ -885,7 +855,7 @@ namespace machine pc++; d = code[pc]; pc++; - va = to_big_word(a, b, c, d); + va = to_typed_big_word(a, b, c, d); push_word(va); break; case push5_opcode: @@ -900,7 +870,7 @@ namespace machine pc++; e = code[pc]; pc++; - va = to_big_word(0, 0, 0, a, b, c, d, e); + va = to_typed_big_word(0, 0, 0, a, b, c, d, e); push_word(va); break; case push6_opcode: @@ -917,7 +887,7 @@ namespace machine pc++; f = code[pc]; pc++; - va = to_big_word(0, 0, a, b, c, d, e, f); + va = to_typed_big_word(0, 0, a, b, c, d, e, f); push_word(va); break; case push7_opcode: @@ -936,7 +906,7 @@ namespace machine pc++; g = code[pc]; pc++; - va = to_big_word(0, a, b, c, d, e, f, g); + va = to_typed_big_word(0, a, b, c, d, e, f, g); push_word(va); break; case push8_opcode: @@ -957,7 +927,7 @@ namespace machine pc++; h = code[pc]; pc++; - va = to_big_word(a, b, c, d, e, f, g, h); + va = to_typed_big_word(a, b, c, d, e, f, g, h); push_word(va); break; case push9_opcode: @@ -980,7 +950,7 @@ namespace machine pc++; i = code[pc]; pc++; - va = to_big_word(0, 0, 0, 0, 0, 0, 0, a, b, c, d, e, f, g, h, i); + va = to_typed_big_word(0, 0, 0, 0, 0, 0, 0, a, b, c, d, e, f, g, h, i); push_word(va); break; case push10_opcode: @@ -1005,7 +975,7 @@ namespace machine pc++; j = code[pc]; pc++; - va = to_big_word(0, 0, 0, 0, 0, 0, a, b, c, d, e, f, g, h, i, j); + va = to_typed_big_word(0, 0, 0, 0, 0, 0, a, b, c, d, e, f, g, h, i, j); push_word(va); break; case push11_opcode: @@ -1032,7 +1002,7 @@ namespace machine pc++; k = code[pc]; pc++; - va = to_big_word(0, 0, 0, 0, 0, a, b, c, d, e, f, g, h, i, j, k); + va = to_typed_big_word(0, 0, 0, 0, 0, a, b, c, d, e, f, g, h, i, j, k); push_word(va); break; case push12_opcode: @@ -1061,7 +1031,7 @@ namespace machine pc++; l = code[pc]; pc++; - va = to_big_word(0, 0, 0, 0, a, b, c, d, e, f, g, h, i, j, k, l); + va = to_typed_big_word(0, 0, 0, 0, a, b, c, d, e, f, g, h, i, j, k, l); push_word(va); break; case push13_opcode: @@ -1092,7 +1062,7 @@ namespace machine pc++; m = code[pc]; pc++; - va = to_big_word(0, 0, 0, a, b, c, d, e, f, g, h, i, j, k, l, m); + va = to_typed_big_word(0, 0, 0, a, b, c, d, e, f, g, h, i, j, k, l, m); push_word(va); break; case push14_opcode: @@ -1125,7 +1095,7 @@ namespace machine pc++; n = code[pc]; pc++; - va = to_big_word(0, 0, a, b, c, d, e, f, g, h, i, j, k, l, m, n); + va = to_typed_big_word(0, 0, a, b, c, d, e, f, g, h, i, j, k, l, m, n); push_word(va); break; case push15_opcode: @@ -1160,7 +1130,7 @@ namespace machine pc++; o = code[pc]; pc++; - va = to_big_word(0, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o); + va = to_typed_big_word(0, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o); push_word(va); break; case push16_opcode: @@ -1197,7 +1167,7 @@ namespace machine pc++; p = code[pc]; pc++; - va = to_big_word(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p); + va = to_typed_big_word(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p); push_word(va); break; case push17_opcode: @@ -1236,7 +1206,7 @@ namespace machine pc++; q = code[pc]; pc++; - va = to_big_word(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d, + va = to_typed_big_word(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q); push_word(va); break; @@ -1278,7 +1248,7 @@ namespace machine pc++; r = code[pc]; pc++; - va = to_big_word(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d, e, + va = to_typed_big_word(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r); push_word(va); break; @@ -1322,7 +1292,7 @@ namespace machine pc++; s = code[pc]; pc++; - va = to_big_word(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d, e, f, + va = to_typed_big_word(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s); push_word(va); break; @@ -1368,7 +1338,7 @@ namespace machine pc++; t = code[pc]; pc++; - va = to_big_word(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d, e, f, g, + va = to_typed_big_word(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t); push_word(va); break; @@ -1416,7 +1386,7 @@ namespace machine pc++; u = code[pc]; pc++; - va = to_big_word(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d, e, f, g, h, + va = to_typed_big_word(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u); push_word(va); break; @@ -1466,7 +1436,7 @@ namespace machine pc++; v = code[pc]; pc++; - va = to_big_word(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d, e, f, g, h, i, + va = to_typed_big_word(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v); push_word(va); break; @@ -1518,7 +1488,7 @@ namespace machine pc++; w = code[pc]; pc++; - va = to_big_word(0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d, e, f, g, h, i, j, + va = to_typed_big_word(0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w); push_word(va); break; @@ -1572,7 +1542,7 @@ namespace machine pc++; x = code[pc]; pc++; - va = to_big_word(0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d, e, f, g, h, i, j, k, + va = to_typed_big_word(0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x); push_word(va); break; @@ -1628,7 +1598,7 @@ namespace machine pc++; y = code[pc]; pc++; - va = to_big_word(0, 0, 0, 0, 0, 0, 0, a, b, c, d, e, f, g, h, i, j, k, l, + va = to_typed_big_word(0, 0, 0, 0, 0, 0, 0, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y); push_word(va); break; @@ -1686,7 +1656,7 @@ namespace machine pc++; z = code[pc]; pc++; - va = to_big_word(0, 0, 0, 0, 0, 0, a, b, c, d, e, f, g, h, i, j, k, l, m, + va = to_typed_big_word(0, 0, 0, 0, 0, 0, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z); push_word(va); break; @@ -1746,7 +1716,7 @@ namespace machine pc++; aa = code[pc]; pc++; - va = to_big_word(0, 0, 0, 0, 0, a, b, c, d, e, f, g, h, i, j, k, l, m, n, + va = to_typed_big_word(0, 0, 0, 0, 0, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, aa); push_word(va); break; @@ -1808,7 +1778,7 @@ namespace machine pc++; ab = code[pc]; pc++; - va = to_big_word(0, 0, 0, 0, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, + va = to_typed_big_word(0, 0, 0, 0, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, aa, ab); push_word(va); break; @@ -1872,7 +1842,7 @@ namespace machine pc++; ac = code[pc]; pc++; - va = to_big_word(0, 0, 0, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, + va = to_typed_big_word(0, 0, 0, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, aa, ab, ac); push_word(va); break; @@ -1938,7 +1908,7 @@ namespace machine pc++; ad = code[pc]; pc++; - va = to_big_word(0, 0, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, + va = to_typed_big_word(0, 0, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, aa, ab, ac, ad); push_word(va); break; @@ -2006,7 +1976,7 @@ namespace machine pc++; ae = code[pc]; pc++; - va = to_big_word(0, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, + va = to_typed_big_word(0, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, aa, ab, ac, ad, ae); push_word(va); break; @@ -2076,89 +2046,89 @@ namespace machine pc++; af = code[pc]; pc++; - va = to_big_word(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, + va = to_typed_big_word(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, aa, ab, ac, ad, ae, af); push_word(va); break; case dup1_opcode: logger << "op dup1" << std::endl; - sv = stack.at(0); - push_word(sv); + va = stack.at(0); + push_word(va); break; case dup2_opcode: logger << "op dup2" << std::endl; - sv = stack.at(1); - push_word(sv); + va = stack.at(1); + push_word(va); break; case dup3_opcode: logger << "op dup3" << std::endl; - sv = stack.at(2); - push_word(sv); + va = stack.at(2); + push_word(va); break; case dup4_opcode: logger << "op dup4" << std::endl; - sv = stack.at(3); - push_word(sv); + va = stack.at(3); + push_word(va); break; case dup5_opcode: logger << "op dup5" << std::endl; - sv = stack.at(4); - push_word(sv); + va = stack.at(4); + push_word(va); break; case dup6_opcode: logger << "op dup6" << std::endl; - sv = stack.at(5); - push_word(sv); + va = stack.at(5); + push_word(va); break; case dup7_opcode: logger << "op dup7" << std::endl; - sv = stack.at(6); - push_word(sv); + va = stack.at(6); + push_word(va); break; case dup8_opcode: logger << "op dup8" << std::endl; - sv = stack.at(7); - push_word(sv); + va = stack.at(7); + push_word(va); break; case dup9_opcode: logger << "op dup9" << std::endl; - sv = stack.at(8); - push_word(sv); + va = stack.at(8); + push_word(va); break; case dup10_opcode: logger << "op dup10" << std::endl; - sv = stack.at(9); - push_word(sv); + va = stack.at(9); + push_word(va); break; case dup11_opcode: logger << "op dup11" << std::endl; - sv = stack.at(10); - push_word(sv); + va = stack.at(10); + push_word(va); break; case dup12_opcode: logger << "op dup12" << std::endl; - sv = stack.at(11); - push_word(sv); + va = stack.at(11); + push_word(va); break; case dup13_opcode: logger << "op dup13" << std::endl; - sv = stack.at(12); - push_word(sv); + va = stack.at(12); + push_word(va); break; case dup14_opcode: logger << "op dup14" << std::endl; - sv = stack.at(13); - push_word(sv); + va = stack.at(13); + push_word(va); break; case dup15_opcode: logger << "op dup15" << std::endl; - sv = stack.at(14); - push_word(sv); + va = stack.at(14); + push_word(va); break; case dup16_opcode: logger << "op dup16" << std::endl; - sv = stack.at(15); - push_word(sv); + va = stack.at(15); + push_word(va); break; case swap1_opcode: logger << "op swap1" << std::endl; @@ -2517,12 +2487,12 @@ namespace machine logger << "op log0" << std::endl; va = pop_word(); // offset vb = pop_word(); // length - offset = size_t(va); - length = size_t(vb); + offset = static_cast(va.value); + length = static_cast(vb.value); std::vector slice; slice.resize(length); for (size_t i = 0; i < length; i++) { - slice[i] = memory[offset + i]; + slice[i] = memory[offset + i].value; } const log_object o = { slice, {} }; this->emit_log(o); @@ -2533,24 +2503,17 @@ namespace machine logger << "op log1" << std::endl; va = pop_word(); // offset vb = pop_word(); // length - offset = size_t(va); - length = size_t(vb); + offset = static_cast(va.value); + length = static_cast(vb.value); std::vector slice; slice.resize(length); for (size_t i = 0; i < length; i++) { - slice[i] = memory[offset + i]; + slice[i] = memory[offset + i].value; } std::vector topics; - stack_variant& stack_object = stack.front(); - if (big_word* it = boost::get(&stack_object)) - { - stack.pop_front(); - topics.push_back(*it); - } - else { - throw; - } + + topics.push_back( pop_word().value ); const log_object o = { slice, topics }; this->emit_log(o); @@ -2561,34 +2524,18 @@ namespace machine logger << "op log2" << std::endl; va = pop_word(); // offset vb = pop_word(); // length - offset = size_t(va); - length = size_t(vb); + offset = static_cast(va.value); + length = static_cast(vb.value); std::vector slice; slice.resize(length); for (size_t i = 0; i < length; i++) { - slice[i] = memory[offset + i]; + slice[i] = memory[offset + i].value; } std::vector topics; - stack_variant& stack_object = stack.front(); - if (big_word* it = boost::get(&stack_object)) - { - stack.pop_front(); - topics.push_back(*it); - } - else { - throw; - } - - stack_object = stack.front(); - if (big_word* it = boost::get(&stack_object)) - { - stack.pop_front(); - topics.push_back(*it); - } - else { - throw; + for (size_t i = 0; i < 2; i++) { + topics.push_back( pop_word().value ); } const log_object o = { slice, topics }; @@ -2600,44 +2547,18 @@ namespace machine logger << "op log3" << std::endl; va = pop_word(); // offset vb = pop_word(); // length - offset = size_t(va); - length = size_t(vb); + offset = static_cast(va.value); + length = static_cast(vb.value); std::vector slice; slice.resize(length); for (size_t i = 0; i < length; i++) { - slice[i] = memory[offset + i]; + slice[i] = memory[offset + i].value; } std::vector topics; - stack_variant& stack_object = stack.front(); - if (big_word* it = boost::get(&stack_object)) - { - stack.pop_front(); - topics.push_back(*it); - } - else { - throw; - } - - stack_object = stack.front(); - if (big_word* it = boost::get(&stack_object)) - { - stack.pop_front(); - topics.push_back(*it); - } - else { - throw; - } - - stack_object = stack.front(); - if (big_word* it = boost::get(&stack_object)) - { - stack.pop_front(); - topics.push_back(*it); - } - else { - throw; + for (size_t i = 0; i < 3; i++) { + topics.push_back( pop_word().value ); } const log_object o = { slice, topics }; @@ -2649,54 +2570,18 @@ namespace machine logger << "op log4" << std::endl; va = pop_word(); // offset vb = pop_word(); // length - offset = size_t(va); - length = size_t(vb); + offset = static_cast(va.value); + length = static_cast(vb.value); std::vector slice; slice.resize(length); for (size_t i = 0; i < length; i++) { - slice[i] = memory[offset + i]; + slice[i] = memory[offset + i].value; } std::vector topics; - stack_variant& stack_object = stack.front(); - if (big_word* it = boost::get(&stack_object)) - { - stack.pop_front(); - topics.push_back(*it); - } - else { - throw; - } - - stack_object = stack.front(); - if (big_word* it = boost::get(&stack_object)) - { - stack.pop_front(); - topics.push_back(*it); - } - else { - throw; - } - - stack_object = stack.front(); - if (big_word* it = boost::get(&stack_object)) - { - stack.pop_front(); - topics.push_back(*it); - } - else { - throw; - } - - stack_object = stack.front(); - if (big_word* it = boost::get(&stack_object)) - { - stack.pop_front(); - topics.push_back(*it); - } - else { - throw; + for (size_t i = 0; i < 4; i++) { + topics.push_back( pop_word().value ); } const log_object o = { slice, topics }; @@ -2710,18 +2595,18 @@ namespace machine vb = pop_word(); // offset vc = pop_word(); // length - for (size_t i = static_cast(vb); i < static_cast(vb) + static_cast(vc); i++) { - std::map::iterator it; + for (size_t i = static_cast(vb.value); i < static_cast(vb.value) + static_cast(vc.value); i++) { + std::map::iterator it; it = memory.find(i); if (it != memory.end()) { - retval.push_back(it->second); + retval.push_back(it->second.value); } else { retval.push_back(word(0)); } } - push_word( adapter.contract_create( retval, va ) ); // addr + push_word( typed_big_word( adapter.contract_create( retval, va.value ) ) ); // addr break; case call_opcode: logger << "op call" << std::endl; @@ -2734,27 +2619,27 @@ namespace machine vf = pop_word(); // retOffset vg = pop_word(); // retLength - for (size_t i = static_cast(vd); i < static_cast(vd) + static_cast(ve); i++) { - std::map::iterator it; + for (size_t i = static_cast(vd.value); i < static_cast(vd.value) + static_cast(ve.value); i++) { + std::map::iterator it; it = memory.find(i); if (it != memory.end()) { - contract_args.push_back(it->second); + contract_args.push_back(it->second.value); } else { contract_args.push_back(word(0)); } } - contract_call_return = adapter.contract_call(vb, static_cast(va), vc, contract_args); + contract_call_return = adapter.contract_call(vb.value, static_cast(va.value), vc.value, contract_args); if (contract_call_return.second.size() > 0) { ext_return_data = contract_call_return.second; - for (size_t i = 0; i < static_cast(vf); i++) - memory[static_cast(ve) + i] = contract_call_return.second[i]; + for (size_t i = 0; i < static_cast(vf.value); i++) + memory[static_cast(ve.value) + i] = contract_call_return.second[i]; } - push_word(big_word(contract_call_return.first)); + push_word(typed_big_word(contract_call_return.first)); break; case callcode_opcode: logger << "op callcode" << std::endl; @@ -2767,27 +2652,27 @@ namespace machine vf = pop_word(); // retOffset vg = pop_word(); // retLength - for (size_t i = static_cast(vd); i < static_cast(vd) + static_cast(ve); i++) { - std::map::iterator it; + for (size_t i = static_cast(vd.value); i < static_cast(vd.value) + static_cast(ve.value); i++) { + std::map::iterator it; it = memory.find(i); if (it != memory.end()) { - contract_args.push_back(it->second); + contract_args.push_back(it->second.value); } else { contract_args.push_back(word(0)); } } - contract_call_return = adapter.contract_callcode(vb, static_cast(va), vc, contract_args); + contract_call_return = adapter.contract_callcode(vb.value, static_cast(va.value), vc.value, contract_args); if (contract_call_return.second.size() > 0) { ext_return_data = contract_call_return.second; - for (size_t i = 0; i < static_cast(vf); i++) - memory[static_cast(ve) + i] = contract_call_return.second[i]; + for (size_t i = 0; i < static_cast(vf.value); i++) + memory[static_cast(ve.value) + i] = contract_call_return.second[i]; } - push_word(big_word(contract_call_return.first)); + push_word(typed_big_word(contract_call_return.first)); break; case return_opcode: logger << "op return" << std::endl; @@ -2807,11 +2692,11 @@ namespace machine va = pop_word(); // offset vb = pop_word(); // length - for (size_t i = static_cast(va); i < static_cast(va + vb); i++) { - std::map::iterator it; + for (size_t i = static_cast(va.value); i < static_cast(va.value + vb.value); i++) { + std::map::iterator it; it = memory.find(i); if (it != memory.end()) { - retval.push_back(it->second); + retval.push_back(it->second.value); } else { retval.push_back(word(0)); @@ -2831,27 +2716,27 @@ namespace machine ve = pop_word(); // retOffset vf = pop_word(); // retLength - for (size_t i = static_cast(vc); i < static_cast(vc) + static_cast(vd); i++) { - std::map::iterator it; + for (size_t i = static_cast(vc.value); i < static_cast(vc.value) + static_cast(vd.value); i++) { + std::map::iterator it; it = memory.find(i); if (it != memory.end()) { - contract_args.push_back(it->second); + contract_args.push_back(it->second.value); } else { contract_args.push_back(word(0)); } } - contract_call_return = adapter.contract_delegatecall(vb, static_cast(va), contract_args); + contract_call_return = adapter.contract_delegatecall(vb.value, static_cast(va.value), contract_args); if (contract_call_return.second.size() > 0) { ext_return_data = contract_call_return.second; - for (size_t i = 0; i < static_cast(vf); i++) - memory[static_cast(ve) + i] = contract_call_return.second[i]; + for (size_t i = 0; i < static_cast(vf.value); i++) + memory[static_cast(ve.value) + i] = contract_call_return.second[i]; } - push_word(contract_call_return.first); + push_word( typed_big_word(contract_call_return.first) ); break; case create2_opcode: logger << "op create2" << std::endl; @@ -2860,23 +2745,29 @@ namespace machine vc = pop_word(); // length vd = pop_word(); // salt - for (size_t i = static_cast(vb); i < static_cast(vb) + static_cast(vc); i++) { - std::map::iterator it; + for (size_t i = static_cast(vb.value); i < static_cast(vb.value) + static_cast(vc.value); i++) { + std::map::iterator it; it = memory.find(i); if (it != memory.end()) { - for (size_t i = 0; i < 31; i++) { - contract_args.push_back(word(0)); + if ( it->second.is_sparse ) { + for (size_t i = 0; i < 31; i++) { + contract_args.push_back( word(0) ); + } } - contract_args.push_back(it->second); + contract_args.push_back( word(it->second.value) ); } else { - for (size_t i = 0; i < 32; i++) { - contract_args.push_back(word(0)); + if ( it->second.is_sparse ) { + for (size_t i = 0; i < 32; i++) { + contract_args.push_back( word(0) ); + } + } else { + contract_args.push_back( word(0) ); } } } - push_word( adapter.contract_create2( contract_args, va, vd ) ); + push_word( typed_big_word( adapter.contract_create2( contract_args, va.value, vd.value ) ) ); break; case staticcall_opcode: @@ -2889,36 +2780,36 @@ namespace machine ve = pop_word(); // retOffset vf = pop_word(); // retLength - for (size_t i = static_cast(vc); i < static_cast(vc) + static_cast(vd); i++) { - std::map::iterator it; + for (size_t i = static_cast(vc.value); i < static_cast(vc.value) + static_cast(vd.value); i++) { + std::map::iterator it; it = memory.find(i); if (it != memory.end()) { - contract_args.push_back(it->second); + contract_args.push_back(it->second.value); } else { contract_args.push_back(word(0)); } } - contract_call_return = adapter.contract_staticcall(vb, static_cast(va), contract_args); + contract_call_return = adapter.contract_staticcall(vb.value, static_cast(va.value), contract_args); ext_return_data = contract_call_return.second; - for (size_t i = 0; i < static_cast(vf); i++) - memory[static_cast(ve) + i] = contract_call_return.second[i]; + for (size_t i = 0; i < static_cast(vf.value); i++) + memory[static_cast(ve.value) + i] = contract_call_return.second[i]; - push_word(big_word(contract_call_return.first)); + push_word(typed_big_word(contract_call_return.first)); break; case revert_opcode: logger << "op revert" << std::endl; va = pop_word(); // offset vb = pop_word(); // length - for (size_t i = static_cast(va); i < static_cast(vb); i++) { - std::map::iterator it; + for (size_t i = static_cast(va.value); i < static_cast(vb.value); i++) { + std::map::iterator it; it = memory.find(i); if (it != memory.end()) { - retval.push_back(it->second); + retval.push_back(it->second.value); } else { retval.push_back(word(0)); @@ -2934,12 +2825,8 @@ namespace machine break; case selfdestruct_opcode: logger << "op selfdestruct" << std::endl; - sv = stack.front(); // addr - ss = boost::get(&sv); - if (ss) - { - adapter.self_destruct(*ss); - } + va = stack.front(); // addr + adapter.self_destruct(va.value); break; } } @@ -2980,8 +2867,10 @@ namespace machine s << "\"stack\":" << "["; for (auto it = stack.cbegin(); it != stack.cend(); ++it) { - stack_variant sv = *it; - s << sv; + typed_big_word bw = *it; + s << bw.value; + s << ":"; + s << bw.is_sparse; if (stack.size() > 1 && std::next(it, 1) != stack.cend()) s << ","; } @@ -3031,7 +2920,9 @@ namespace machine { s << "\"" << it->first << "\""; s << ":"; - s << unsigned(it->second); + s << unsigned(it->second.value); + s << " : "; + s << it->second.is_sparse; if (memory.size() > 1 && std::next(it, 1) != memory.cend()) s << ","; } diff --git a/libraries/vendor/xgtvm/libraries/machine.hpp b/libraries/vendor/xgtvm/libraries/machine.hpp index 93d552b3..8c9fa99e 100644 --- a/libraries/vendor/xgtvm/libraries/machine.hpp +++ b/libraries/vendor/xgtvm/libraries/machine.hpp @@ -15,7 +15,273 @@ namespace machine typedef uint8_t word; typedef boost::multiprecision::uint256_t big_word; typedef boost::multiprecision::int256_t signed_big_word; - typedef boost::variant stack_variant; + + struct typed_word + { + word value; + bool is_sparse; + + typed_word(const word _value = 0) : value(_value), is_sparse(false) {} + typed_word(const word _value, const bool _is_sparse) : value(_value), is_sparse(_is_sparse) {} + + bool operator==(const typed_word &other) const { + return this->value == other.value; + } + + bool operator!=(const typed_word &other) const { + return !(*this == other); + } + + bool operator<(const typed_word &other) const { + return this->value < other.value; + } + + bool operator>(const typed_word &other) const { + return this->value > other.value; + } + + typed_word operator+(const typed_word &rhs) const { + return typed_word(this->value + rhs.value); + } + + typed_word operator-(const typed_word &rhs) const { + return typed_word(this->value - rhs.value); + } + + typed_word operator*(const typed_word &rhs) const { + return typed_word(this->value * rhs.value); + } + + typed_word operator/(const typed_word &rhs) const { + return typed_word(this->value / rhs.value); + } + + typed_word operator%(const typed_word &rhs) const { + return typed_word(this->value % rhs.value); + } + + typed_word operator=(const typed_word &rhs) { + if (this == &rhs) + return *this; + this->value = rhs.value; + this->is_sparse = rhs.is_sparse; + return *this; + } + + typed_word operator+=(const typed_word &rhs) { + this->value = this->value+ rhs.value; + return *this; + } + + typed_word operator-=(const typed_word &rhs) { + this->value = this->value - rhs.value; + return *this; + } + + typed_word operator*=(const typed_word &rhs) { + this->value = this->value * rhs.value; + return *this; + } + + typed_word operator/=(const typed_word &rhs) { + this->value = this->value / rhs.value; + return *this; + } + + typed_word operator&(const typed_word &other) const { + return typed_word(this->value & other.value); + } + + typed_word operator|(const typed_word &other) const { + return typed_word(this->value | other.value); + } + + typed_word operator^(const typed_word &other) const { + return typed_word(this->value ^ other.value); + } + + typed_word operator~() const { + return typed_word(~this->value); + } + }; + + struct typed_big_word + { + big_word value; + bool is_sparse; + + typed_big_word(const big_word _value = 0) : value(_value), is_sparse(false) {} + typed_big_word(const big_word _value, const bool _is_sparse) : value(_value), is_sparse(_is_sparse) {} + + bool operator==(const typed_big_word &other) const { + return this->value == other.value; + } + + bool operator!=(const typed_big_word &other) const { + return !(*this == other); + } + + bool operator<(const typed_big_word &other) const { + return this->value < other.value; + } + + bool operator>(const typed_big_word &other) const { + return this->value > other.value; + } + + typed_big_word operator+(const typed_big_word &rhs) const { + return typed_big_word(this->value + rhs.value); + } + + typed_big_word operator-(const typed_big_word &rhs) const { + return typed_big_word(this->value - rhs.value); + } + + typed_big_word operator*(const typed_big_word &rhs) const { + return typed_big_word(this->value * rhs.value); + } + + typed_big_word operator/(const typed_big_word &rhs) const { + return typed_big_word(this->value / rhs.value); + } + + typed_big_word operator%(const typed_big_word &rhs) const { + return typed_big_word(this->value % rhs.value); + } + + typed_big_word operator=(const typed_big_word &rhs) { + if (this == &rhs) + return *this; + this->value = rhs.value; + this->is_sparse = rhs.is_sparse; + return *this; + } + + typed_big_word operator+=(const typed_big_word &rhs) { + this->value = this->value + rhs.value; + return *this; + } + + typed_big_word operator-=(const typed_big_word &rhs) { + this->value = this->value - rhs.value; + return *this; + } + + typed_big_word operator*=(const typed_big_word &rhs) { + this->value = this->value * rhs.value; + return *this; + } + + typed_big_word operator/=(const typed_big_word &rhs) { + this->value = this->value / rhs.value; + return *this; + } + + typed_big_word operator&(const typed_big_word &other) const { + return typed_big_word(this->value & other.value); + } + + typed_big_word operator|(const typed_big_word &other) const { + return typed_big_word(this->value | other.value); + } + + typed_big_word operator^(const typed_big_word &other) const { + return typed_big_word(this->value ^ other.value); + } + + typed_big_word operator~() const { + return typed_big_word(~this->value); + } + }; + + struct typed_signed_big_word + { + signed_big_word value; + bool is_sparse; + + typed_signed_big_word(const signed_big_word _value = 0) : value(_value), is_sparse(false) {} + typed_signed_big_word(const signed_big_word _value, const bool _is_sparse) : value(_value), is_sparse(_is_sparse) {} + + bool operator==(const typed_signed_big_word &other) const { + return this->value == other.value; + } + + bool operator!=(const typed_signed_big_word &other) const { + return !(*this == other); + } + + bool operator<(const typed_signed_big_word &other) const { + return this->value < other.value; + } + + bool operator>(const typed_signed_big_word &other) const { + return this->value > other.value; + } + + typed_signed_big_word operator+(const typed_signed_big_word &rhs) const { + return typed_signed_big_word(this->value + rhs.value); + } + + typed_signed_big_word operator-(const typed_signed_big_word &rhs) const { + return typed_signed_big_word(this->value - rhs.value); + } + + typed_signed_big_word operator*(const typed_signed_big_word &rhs) const { + return typed_signed_big_word(this->value * rhs.value); + } + + typed_signed_big_word operator/(const typed_signed_big_word &rhs) const { + return typed_signed_big_word(this->value / rhs.value); + } + + typed_signed_big_word operator%(const typed_signed_big_word &rhs) const { + return typed_signed_big_word(this->value % rhs.value); + } + + typed_signed_big_word operator=(const typed_signed_big_word &rhs) { + if (this == &rhs) + return *this; + this->value = rhs.value; + this->is_sparse = rhs.is_sparse; + return *this; + } + + typed_signed_big_word operator+=(const typed_signed_big_word &rhs) { + this->value = this->value + rhs.value; + return *this; + } + + typed_signed_big_word operator-=(const typed_signed_big_word &rhs) { + this->value = this->value - rhs.value; + return *this; + } + + typed_signed_big_word operator*=(const typed_signed_big_word &rhs) { + this->value = this->value * rhs.value; + return *this; + } + + typed_signed_big_word operator/=(const typed_signed_big_word &rhs) { + this->value = this->value / rhs.value; + return *this; + } + + typed_signed_big_word operator&(const typed_signed_big_word &other) const { + return typed_signed_big_word(this->value & other.value); + } + + typed_signed_big_word operator|(const typed_signed_big_word &other) const { + return typed_signed_big_word(this->value | other.value); + } + + typed_signed_big_word operator^(const typed_signed_big_word &other) const { + return typed_signed_big_word(this->value ^ other.value); + } + + typed_signed_big_word operator~() const { + return typed_signed_big_word(~this->value); + } + }; enum opcode { @@ -187,7 +453,7 @@ namespace machine struct log_object { - std::vector data; + std::vector data; std::vector topics; }; @@ -200,7 +466,7 @@ namespace machine big_word sender; big_word destination; - big_word value; + uint64_t value; size_t input_size; std::vector input_data = {}; size_t code_size; @@ -215,8 +481,8 @@ namespace machine uint64_t block_difficulty; uint64_t block_energylimit; int64_t tx_energyprice; - std::string tx_origin; - std::string block_coinbase; + big_word tx_origin; + big_word block_coinbase; }; struct chain_adapter @@ -227,7 +493,7 @@ namespace machine std::function< big_word(big_word) > get_balance; // TODO for hashing address -- extcodehash opcode - std::function< std::string(std::string) > get_code_hash; + std::function< big_word(big_word) > get_code_hash; // TODO for hashing block number -- blockhash opcode std::function< machine::big_word(uint64_t) > get_block_hash; @@ -267,10 +533,7 @@ namespace machine std::function< std::vector(std::vector) > contract_return; // TODO selfdestruct opcode - std::function< bool(std::string) > self_destruct; - - // TODO used to initialize message data - std::function< std::vector(std::string) > get_input_data; + std::function< bool(big_word) > self_destruct; std::function< void(const log_object&) > emit_log; }; @@ -278,23 +541,27 @@ namespace machine class machine { size_t pc = 0; - std::deque stack; + std::deque stack; machine_state state = machine_state::running; context ctx; std::vector code; message msg; - std::map memory; - std::map storage; + std::map memory; + // TODO writing to memory requires type information to be added to memory_type_data + // 0 for string and bytes / tightly packed + // 1 for array / sparsely packed data + // XXX Refers to non-standard packed mode in solidity ABI spec + std::map storage; std::vector return_value; std::vector ext_return_data; boost::optional error_message; std::stringstream logger; chain_adapter adapter; - big_word energy_left; + typed_big_word energy_left; opcode current_opcode = stop_opcode; - void push_word(stack_variant v); - big_word pop_word(); + void push_word(typed_big_word v); + typed_big_word pop_word(); void log(std::string output); public: @@ -303,8 +570,7 @@ namespace machine { } - big_word peek_word(); - void push_string(std::string s); + typed_big_word peek_word(); void print_stack(); size_t stack_length(); void step(); @@ -318,5 +584,4 @@ namespace machine void emit_log(const log_object& o); }; - } diff --git a/libraries/vendor/xgtvm/programs/xgtvm.cpp b/libraries/vendor/xgtvm/programs/xgtvm.cpp index c38e0beb..10d13d5a 100644 --- a/libraries/vendor/xgtvm/programs/xgtvm.cpp +++ b/libraries/vendor/xgtvm/programs/xgtvm.cpp @@ -57,85 +57,98 @@ machine::chain_adapter make_chain_adapter() { std::function< machine::big_word(std::vector) > sha3 = [](std::vector memory) -> machine::big_word { - return 0; + std::cout << "chain_adapter::sha3" << std::endl; + return machine::big_word(0); }; std::function< machine::big_word(machine::big_word) > get_balance = [](machine::big_word address_ripemd160) -> machine::big_word { - return 0; + std::cout << "chain_adapter::get_balance" << std::endl; + return machine::big_word(0); }; - std::function< std::string(std::string) > get_code_hash = [](std::string address) -> std::string + std::function< machine::big_word(machine::big_word) > get_code_hash = [](machine::big_word address) -> machine::big_word { - return ""; + std::cout << "chain_adapter::get_code_hash" << std::endl; + return machine::big_word(0); }; std::function< machine::big_word(uint64_t) > get_block_hash = [](uint64_t block_num) -> machine::big_word { - return {}; + std::cout << "chain_adapter::get_block_hash" << std::endl; + return machine::big_word(0); }; std::function< std::vector(machine::big_word) > get_code_at_addr = [](machine::big_word address) -> std::vector { + std::cout << "chain_adapter::get_code_at_addr" << std::endl; return {}; }; std::function< machine::big_word(std::vector, machine::big_word) > contract_create = [](std::vector memory, machine::big_word value) -> machine::big_word { + std::cout << "chain_adapter::contract_create" << std::endl; return {}; }; std::function< std::pair< machine::word, std::vector >(machine::big_word, uint64_t, machine::big_word, std::vector) > contract_call = [](machine::big_word address, uint64_t energy, machine::big_word value, std::vector args) -> std::pair< machine::word, std::vector > { + std::cout << "chain_adapter::contract_call" << std::endl; return {}; }; std::function< std::pair< machine::word, std::vector >(machine::big_word, uint64_t, machine::big_word, std::vector) > contract_callcode = [](machine::big_word address, uint64_t energy, machine::big_word value, std::vector args) -> std::pair< machine::word, std::vector > { + std::cout << "chain_adapter::contract_callcode" << std::endl; return {}; }; std::function< std::pair< machine::word, std::vector >(machine::big_word, uint64_t, std::vector) > contract_delegatecall = [](machine::big_word address, uint64_t energy, std::vector args) -> std::pair< machine::word, std::vector > { + std::cout << "chain_adapter::contract_delegatecall" << std::endl; return {}; }; std::function< std::pair< machine::word, std::vector >(machine::big_word, uint64_t, std::vector) > contract_staticcall = [](machine::big_word address, uint64_t energy, std::vector args) -> std::pair< machine::word, std::vector > { + std::cout << "chain_adapter::contract_staticcall" << std::endl; return {}; }; std::function< machine::big_word(std::vector, machine::big_word, machine::big_word) > contract_create2 = [](std::vector memory, machine::big_word value, machine::big_word salt) -> machine::big_word { + std::cout << "chain_adapter::contract_create2" << std::endl; return {}; }; std::function< bool(std::vector) > revert = [](std::vector memory) -> bool { + std::cout << "chain_adapter::revert" << std::endl; return {}; }; std::function< machine::big_word(machine::big_word) > get_storage = [](machine::big_word) -> machine::big_word { - return 0; - }; + std::cout << "chain_adapter::get_storage" << std::endl; - std::function< void(machine::big_word, machine::big_word) > set_storage = [](machine::big_word, machine::big_word value) -> void - { + return machine::big_word(0); }; - std::function< std::vector(std::vector) > contract_return = [](std::vector memory) -> std::vector + std::function< bool(machine::big_word, machine::big_word) > set_storage = [](machine::big_word, machine::big_word value) -> bool { - return {}; + std::cout << "chain_adapter::set_storage" << std::endl; + return false; }; - std::function< bool(std::string) > self_destruct = [](std::string address) -> bool + std::function< std::vector(std::vector) > contract_return = [](std::vector memory) -> std::vector { + std::cout << "chain_adapter::contract_return" << std::endl; return {}; }; - std::function< std::vector(std::string) > get_input_data = [](std::string address) -> std::vector + std::function< bool(machine::big_word) > self_destruct = [](machine::big_word address) -> bool { + std::cout << "chain_adapter::self_destruct" << std::endl; return {}; }; @@ -156,7 +169,6 @@ machine::chain_adapter make_chain_adapter() set_storage, contract_return, self_destruct, - get_input_data }; return adapter; diff --git a/libraries/vendor/xgtvm/programs/xgtvm_tests.cpp b/libraries/vendor/xgtvm/programs/xgtvm_tests.cpp index 81db371f..2fdf80b4 100644 --- a/libraries/vendor/xgtvm/programs/xgtvm_tests.cpp +++ b/libraries/vendor/xgtvm/programs/xgtvm_tests.cpp @@ -14,25 +14,25 @@ machine::chain_adapter make_chain_adapter() std::function< machine::big_word(std::vector) > sha3 = [](std::vector memory) -> machine::big_word { std::cout << "chain_adapter::sha3" << std::endl; - return 0; + return machine::big_word(0); }; std::function< machine::big_word(machine::big_word) > get_balance = [](machine::big_word address_ripemd160) -> machine::big_word { std::cout << "chain_adapter::get_balance" << std::endl; - return 0; + return machine::big_word(0); }; - std::function< std::string(std::string) > get_code_hash = [](std::string address) -> std::string + std::function< machine::big_word(machine::big_word) > get_code_hash = [](machine::big_word address) -> machine::big_word { std::cout << "chain_adapter::get_code_hash" << std::endl; - return ""; + return machine::big_word(0); }; std::function< machine::big_word(uint64_t) > get_block_hash = [](uint64_t block_num) -> machine::big_word { std::cout << "chain_adapter::get_block_hash" << std::endl; - return {}; + return machine::big_word(0); }; std::function< std::vector(machine::big_word) > get_code_at_addr = [](machine::big_word address) -> std::vector @@ -86,7 +86,8 @@ machine::chain_adapter make_chain_adapter() std::function< machine::big_word(machine::big_word) > get_storage = [](machine::big_word) -> machine::big_word { std::cout << "chain_adapter::get_storage" << std::endl; - return 0; + + return machine::big_word(0); }; std::function< bool(machine::big_word, machine::big_word) > set_storage = [](machine::big_word, machine::big_word value) -> bool @@ -101,18 +102,12 @@ machine::chain_adapter make_chain_adapter() return {}; }; - std::function< bool(std::string) > self_destruct = [](std::string address) -> bool + std::function< bool(machine::big_word) > self_destruct = [](machine::big_word address) -> bool { std::cout << "chain_adapter::self_destruct" << std::endl; return {}; }; - std::function< std::vector(std::string) > get_input_data = [](std::string address) -> std::vector - { - std::cout << "chain_adapter::get_input_data" << std::endl; - return {}; - }; - machine::chain_adapter adapter = { sha3, get_balance, @@ -130,7 +125,6 @@ machine::chain_adapter make_chain_adapter() set_storage, contract_return, self_destruct, - get_input_data }; return adapter; From 49cd77fe27b40e7b91c71cf8b488f9dd412b956e Mon Sep 17 00:00:00 2001 From: Liam Noroian Date: Fri, 15 Apr 2022 11:06:26 -0700 Subject: [PATCH 90/96] Clean up todos --- libraries/vendor/xgtvm/libraries/machine.cpp | 20 -------------------- libraries/vendor/xgtvm/libraries/machine.hpp | 4 ---- 2 files changed, 24 deletions(-) diff --git a/libraries/vendor/xgtvm/libraries/machine.cpp b/libraries/vendor/xgtvm/libraries/machine.cpp index e7b799d4..5a45c224 100644 --- a/libraries/vendor/xgtvm/libraries/machine.cpp +++ b/libraries/vendor/xgtvm/libraries/machine.cpp @@ -595,8 +595,6 @@ namespace machine for (size_t i = 0; i < length; ++i) { memory[dest_offset + i] = typed_word(msg.input_data[offset + i], true); - // TODO This isn't being set correctly in the constructor - memory[dest_offset + i].is_sparse = true; } break; @@ -613,8 +611,6 @@ namespace machine for (size_t i = 0; i < length; ++i) { memory[dest_offset + i] = typed_word(code[offset + i], true); - // TODO This isn't being set correctly in the constructor - memory[dest_offset + i].is_sparse = true; } break; @@ -644,8 +640,6 @@ namespace machine for (size_t i = 0; i < length; ++i) { memory[dest_offset + i] = typed_word(ext_contract_code[offset + i], true); - // TODO This isn't being set correctly in the constructor - memory[dest_offset + i].is_sparse = true; } break; @@ -2590,7 +2584,6 @@ namespace machine } case create_opcode: logger << "op create" << std::endl; - // TODO REVIEW va = pop_word(); // value vb = pop_word(); // offset vc = pop_word(); // length @@ -2676,19 +2669,6 @@ namespace machine break; case return_opcode: logger << "op return" << std::endl; - // XXX - // TODO REVIEW - // a = pop_word(); // offset - // b = pop_word(); // length - // logger << std::to_string(a) << std::endl; - // logger << std::to_string(b) << std::endl; // return_value.resize(b); - // // TODO: Bounds checking - // // TODO: Check if size needs to be capped - // // TODO: Optimize - // for (int i = 0; i < return_value.size(); i++) - // return_value[i] = memory[a + i]; - // state = machine_state::stopped; - va = pop_word(); // offset vb = pop_word(); // length diff --git a/libraries/vendor/xgtvm/libraries/machine.hpp b/libraries/vendor/xgtvm/libraries/machine.hpp index 8c9fa99e..d36bc4a7 100644 --- a/libraries/vendor/xgtvm/libraries/machine.hpp +++ b/libraries/vendor/xgtvm/libraries/machine.hpp @@ -547,10 +547,6 @@ namespace machine std::vector code; message msg; std::map memory; - // TODO writing to memory requires type information to be added to memory_type_data - // 0 for string and bytes / tightly packed - // 1 for array / sparsely packed data - // XXX Refers to non-standard packed mode in solidity ABI spec std::map storage; std::vector return_value; std::vector ext_return_data; From 2fa58a39fd719e790eacce82f28bbd0813beb601 Mon Sep 17 00:00:00 2001 From: Liam Noroian Date: Mon, 18 Apr 2022 16:03:21 -0700 Subject: [PATCH 91/96] Clean up old files --- temp.txt | 10 ---------- todo.rb | 1 - 2 files changed, 11 deletions(-) delete mode 100644 temp.txt delete mode 100644 todo.rb diff --git a/temp.txt b/temp.txt deleted file mode 100644 index 3fd6db4e..00000000 --- a/temp.txt +++ /dev/null @@ -1,10 +0,0 @@ -master 5KKXW4SrwihYQaKnbTEp5uXvKFs26zs4PbqnYJbF8vfDCWpUUBk -recovery_private 5KDxgvTZ17SZeiAzUv87vAxMwQ9T9jvakYurSdc1zHGdSdXJZCF -recovery_public XGT6dfSiYnACaq3xWc1txTvoWN5td8VRWkaphYD9WesxiBEGL9TQz -money_private 5KS5wwV3qiezKB6VnsPpMCVUL9C418zaDSaHjA5dLGxZEjCNmC8 -money_public XGT5c7krPv7qm9AUpm9PpLosjL31Q4DkJNWJf6veZaCjGX2LsR3x3 -social_private 5JkfetxX2hJUnUdqknuEcnrha46bzVcHcC3CBkuKTHkyEw3bHm2 -social_public XGT6CNSdP78Yev11WozNSbi9x5rvw5sHzftpx1n8CsJRNnsRWz51Y -memo_private 5KKMpo3y3aiuvygo7AtoDp14Hh5Kg2HMXNATTDUAdFqAwauc3jo -memo_public XGT7ZWLwEdFFXyeDYrbS6j5hei7m6Ri6jWhzr9CKWeBr1ZqE9KGJg -wallet_name XGTFnjnrACfmLLi4fZSK5TfRi6NvFCLrukk4ZfZBZXQ diff --git a/todo.rb b/todo.rb deleted file mode 100644 index 86ca6b82..00000000 --- a/todo.rb +++ /dev/null @@ -1 +0,0 @@ -# 1. tests/tests/block_tests.cpp From 579d774dfacf815bc3107f8d3aaaafde752b3c55 Mon Sep 17 00:00:00 2001 From: Liam Noroian Date: Mon, 18 Apr 2022 16:35:42 -0700 Subject: [PATCH 92/96] Bring in rlpvalue --- libraries/chain/include/rlpvalue | 1 - libraries/chain/include/rlpvalue/.gitignore | 32 + libraries/chain/include/rlpvalue/.gitmodules | 3 + libraries/chain/include/rlpvalue/.travis.yml | 58 + libraries/chain/include/rlpvalue/COPYING | 19 + libraries/chain/include/rlpvalue/Makefile.am | 61 + libraries/chain/include/rlpvalue/README.md | 22 + libraries/chain/include/rlpvalue/TODO.md | 21 + libraries/chain/include/rlpvalue/a.out | Bin 0 -> 108976 bytes libraries/chain/include/rlpvalue/autogen.sh | 18 + libraries/chain/include/rlpvalue/configure.ac | 78 + libraries/chain/include/rlpvalue/gen/gen.cpp | 82 + .../chain/include/rlpvalue/include/rlpvalue.h | 126 ++ .../chain/include/rlpvalue/lib/.gitignore | 2 + .../chain/include/rlpvalue/lib/rlpvalue.cpp | 84 + .../include/rlpvalue/lib/rlpvalue_get.cpp | 38 + .../include/rlpvalue/lib/rlpvalue_read.cpp | 216 +++ .../include/rlpvalue/lib/rlpvalue_utffilter.h | 119 ++ .../include/rlpvalue/lib/rlpvalue_write.cpp | 83 + libraries/chain/include/rlpvalue/main.cpp | 48 + .../rlpvalue/pc/librlpvalue-uninstalled.pc.in | 9 + .../include/rlpvalue/pc/librlpvalue.pc.in | 10 + .../chain/include/rlpvalue/src/.gitignore | 3 + libraries/chain/include/rlpvalue/src/InfInt.h | 1371 +++++++++++++++++ .../chain/include/rlpvalue/src/rlp2json.cpp | 107 ++ libraries/chain/include/rlpvalue/src/tool.cpp | 189 +++ .../chain/include/rlpvalue/test/.gitignore | 8 + .../include/rlpvalue/test/data/example.json | 6 + .../rlpvalue/test/data/invalidRLPTest.json | 46 + .../include/rlpvalue/test/data/longlist.json | 48 + .../include/rlpvalue/test/data/rlptest.json | 111 ++ .../chain/include/rlpvalue/test/object.cpp | 171 ++ .../chain/include/rlpvalue/test/test_json.cpp | 24 + .../chain/include/rlpvalue/test/unitester.cpp | 207 +++ .../rlpvalue/test/utilstrencodings.cpp | 226 +++ .../include/rlpvalue/test/utilstrencodings.h | 62 + libraries/chain/include/rlpvalue/univalue | 1 + libraries/fc/vendor/rlpvalue | 1 - libraries/fc/vendor/rlpvalue/.gitignore | 32 + libraries/fc/vendor/rlpvalue/.gitmodules | 3 + libraries/fc/vendor/rlpvalue/.travis.yml | 58 + libraries/fc/vendor/rlpvalue/COPYING | 19 + libraries/fc/vendor/rlpvalue/Makefile.am | 61 + libraries/fc/vendor/rlpvalue/README.md | 22 + libraries/fc/vendor/rlpvalue/TODO.md | 21 + libraries/fc/vendor/rlpvalue/a.out | Bin 0 -> 108976 bytes libraries/fc/vendor/rlpvalue/autogen.sh | 18 + libraries/fc/vendor/rlpvalue/configure.ac | 78 + libraries/fc/vendor/rlpvalue/gen/gen.cpp | 82 + .../fc/vendor/rlpvalue/include/rlpvalue.h | 126 ++ libraries/fc/vendor/rlpvalue/lib/.gitignore | 2 + libraries/fc/vendor/rlpvalue/lib/rlpvalue.cpp | 84 + .../fc/vendor/rlpvalue/lib/rlpvalue_get.cpp | 38 + .../fc/vendor/rlpvalue/lib/rlpvalue_read.cpp | 216 +++ .../vendor/rlpvalue/lib/rlpvalue_utffilter.h | 119 ++ .../fc/vendor/rlpvalue/lib/rlpvalue_write.cpp | 83 + libraries/fc/vendor/rlpvalue/main.cpp | 48 + .../rlpvalue/pc/librlpvalue-uninstalled.pc.in | 9 + .../fc/vendor/rlpvalue/pc/librlpvalue.pc.in | 10 + libraries/fc/vendor/rlpvalue/src/.gitignore | 3 + libraries/fc/vendor/rlpvalue/src/InfInt.h | 1371 +++++++++++++++++ libraries/fc/vendor/rlpvalue/src/rlp2json.cpp | 107 ++ libraries/fc/vendor/rlpvalue/src/tool.cpp | 189 +++ libraries/fc/vendor/rlpvalue/test/.gitignore | 8 + .../fc/vendor/rlpvalue/test/data/example.json | 6 + .../rlpvalue/test/data/invalidRLPTest.json | 46 + .../vendor/rlpvalue/test/data/longlist.json | 48 + .../fc/vendor/rlpvalue/test/data/rlptest.json | 111 ++ libraries/fc/vendor/rlpvalue/test/object.cpp | 171 ++ .../fc/vendor/rlpvalue/test/test_json.cpp | 24 + .../fc/vendor/rlpvalue/test/unitester.cpp | 207 +++ .../vendor/rlpvalue/test/utilstrencodings.cpp | 226 +++ .../vendor/rlpvalue/test/utilstrencodings.h | 62 + libraries/fc/vendor/rlpvalue/univalue | 1 + 74 files changed, 7418 insertions(+), 2 deletions(-) delete mode 160000 libraries/chain/include/rlpvalue create mode 100644 libraries/chain/include/rlpvalue/.gitignore create mode 100644 libraries/chain/include/rlpvalue/.gitmodules create mode 100644 libraries/chain/include/rlpvalue/.travis.yml create mode 100644 libraries/chain/include/rlpvalue/COPYING create mode 100644 libraries/chain/include/rlpvalue/Makefile.am create mode 100644 libraries/chain/include/rlpvalue/README.md create mode 100644 libraries/chain/include/rlpvalue/TODO.md create mode 100755 libraries/chain/include/rlpvalue/a.out create mode 100755 libraries/chain/include/rlpvalue/autogen.sh create mode 100644 libraries/chain/include/rlpvalue/configure.ac create mode 100644 libraries/chain/include/rlpvalue/gen/gen.cpp create mode 100644 libraries/chain/include/rlpvalue/include/rlpvalue.h create mode 100644 libraries/chain/include/rlpvalue/lib/.gitignore create mode 100644 libraries/chain/include/rlpvalue/lib/rlpvalue.cpp create mode 100644 libraries/chain/include/rlpvalue/lib/rlpvalue_get.cpp create mode 100644 libraries/chain/include/rlpvalue/lib/rlpvalue_read.cpp create mode 100644 libraries/chain/include/rlpvalue/lib/rlpvalue_utffilter.h create mode 100644 libraries/chain/include/rlpvalue/lib/rlpvalue_write.cpp create mode 100644 libraries/chain/include/rlpvalue/main.cpp create mode 100644 libraries/chain/include/rlpvalue/pc/librlpvalue-uninstalled.pc.in create mode 100644 libraries/chain/include/rlpvalue/pc/librlpvalue.pc.in create mode 100644 libraries/chain/include/rlpvalue/src/.gitignore create mode 100644 libraries/chain/include/rlpvalue/src/InfInt.h create mode 100644 libraries/chain/include/rlpvalue/src/rlp2json.cpp create mode 100644 libraries/chain/include/rlpvalue/src/tool.cpp create mode 100644 libraries/chain/include/rlpvalue/test/.gitignore create mode 100644 libraries/chain/include/rlpvalue/test/data/example.json create mode 100644 libraries/chain/include/rlpvalue/test/data/invalidRLPTest.json create mode 100644 libraries/chain/include/rlpvalue/test/data/longlist.json create mode 100644 libraries/chain/include/rlpvalue/test/data/rlptest.json create mode 100644 libraries/chain/include/rlpvalue/test/object.cpp create mode 100644 libraries/chain/include/rlpvalue/test/test_json.cpp create mode 100644 libraries/chain/include/rlpvalue/test/unitester.cpp create mode 100644 libraries/chain/include/rlpvalue/test/utilstrencodings.cpp create mode 100644 libraries/chain/include/rlpvalue/test/utilstrencodings.h create mode 160000 libraries/chain/include/rlpvalue/univalue delete mode 160000 libraries/fc/vendor/rlpvalue create mode 100644 libraries/fc/vendor/rlpvalue/.gitignore create mode 100644 libraries/fc/vendor/rlpvalue/.gitmodules create mode 100644 libraries/fc/vendor/rlpvalue/.travis.yml create mode 100644 libraries/fc/vendor/rlpvalue/COPYING create mode 100644 libraries/fc/vendor/rlpvalue/Makefile.am create mode 100644 libraries/fc/vendor/rlpvalue/README.md create mode 100644 libraries/fc/vendor/rlpvalue/TODO.md create mode 100755 libraries/fc/vendor/rlpvalue/a.out create mode 100755 libraries/fc/vendor/rlpvalue/autogen.sh create mode 100644 libraries/fc/vendor/rlpvalue/configure.ac create mode 100644 libraries/fc/vendor/rlpvalue/gen/gen.cpp create mode 100644 libraries/fc/vendor/rlpvalue/include/rlpvalue.h create mode 100644 libraries/fc/vendor/rlpvalue/lib/.gitignore create mode 100644 libraries/fc/vendor/rlpvalue/lib/rlpvalue.cpp create mode 100644 libraries/fc/vendor/rlpvalue/lib/rlpvalue_get.cpp create mode 100644 libraries/fc/vendor/rlpvalue/lib/rlpvalue_read.cpp create mode 100644 libraries/fc/vendor/rlpvalue/lib/rlpvalue_utffilter.h create mode 100644 libraries/fc/vendor/rlpvalue/lib/rlpvalue_write.cpp create mode 100644 libraries/fc/vendor/rlpvalue/main.cpp create mode 100644 libraries/fc/vendor/rlpvalue/pc/librlpvalue-uninstalled.pc.in create mode 100644 libraries/fc/vendor/rlpvalue/pc/librlpvalue.pc.in create mode 100644 libraries/fc/vendor/rlpvalue/src/.gitignore create mode 100644 libraries/fc/vendor/rlpvalue/src/InfInt.h create mode 100644 libraries/fc/vendor/rlpvalue/src/rlp2json.cpp create mode 100644 libraries/fc/vendor/rlpvalue/src/tool.cpp create mode 100644 libraries/fc/vendor/rlpvalue/test/.gitignore create mode 100644 libraries/fc/vendor/rlpvalue/test/data/example.json create mode 100644 libraries/fc/vendor/rlpvalue/test/data/invalidRLPTest.json create mode 100644 libraries/fc/vendor/rlpvalue/test/data/longlist.json create mode 100644 libraries/fc/vendor/rlpvalue/test/data/rlptest.json create mode 100644 libraries/fc/vendor/rlpvalue/test/object.cpp create mode 100644 libraries/fc/vendor/rlpvalue/test/test_json.cpp create mode 100644 libraries/fc/vendor/rlpvalue/test/unitester.cpp create mode 100644 libraries/fc/vendor/rlpvalue/test/utilstrencodings.cpp create mode 100644 libraries/fc/vendor/rlpvalue/test/utilstrencodings.h create mode 160000 libraries/fc/vendor/rlpvalue/univalue diff --git a/libraries/chain/include/rlpvalue b/libraries/chain/include/rlpvalue deleted file mode 160000 index 1e58dcec..00000000 --- a/libraries/chain/include/rlpvalue +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 1e58dcec547dd19da4c325344d6f363d533dabe0 diff --git a/libraries/chain/include/rlpvalue/.gitignore b/libraries/chain/include/rlpvalue/.gitignore new file mode 100644 index 00000000..0203b4bb --- /dev/null +++ b/libraries/chain/include/rlpvalue/.gitignore @@ -0,0 +1,32 @@ +.deps/ +INSTALL +Makefile +Makefile.in +aclocal.m4 +autom4te.cache/ +compile +config.log +config.status +config.guess +config.sub +configure +depcomp +install-sh +missing +stamp-h1 +rlpvalue-config.h* +test-driver +libtool +ltmain.sh +test-suite.log + +*.a +*.la +*.lo +*.logs +*.o +*.pc +*.trs + +.dirstamp +.libs diff --git a/libraries/chain/include/rlpvalue/.gitmodules b/libraries/chain/include/rlpvalue/.gitmodules new file mode 100644 index 00000000..a740b3a7 --- /dev/null +++ b/libraries/chain/include/rlpvalue/.gitmodules @@ -0,0 +1,3 @@ +[submodule "univalue"] + path = univalue + url = https://github.com/jgarzik/univalue diff --git a/libraries/chain/include/rlpvalue/.travis.yml b/libraries/chain/include/rlpvalue/.travis.yml new file mode 100644 index 00000000..b5170879 --- /dev/null +++ b/libraries/chain/include/rlpvalue/.travis.yml @@ -0,0 +1,58 @@ +language: cpp + +compiler: + - clang + - gcc + +os: + - linux + - osx + +sudo: true + +env: + global: + - MAKEJOBS=-j3 + - RUN_TESTS=true + - BASE_OUTDIR=$TRAVIS_BUILD_DIR/out + +cache: + apt: true + +addons: + apt: + packages: + - pkg-config + +before_install: + - if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew update; fi + +install: + - if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew install gettext; fi + - if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew install argp-standalone; fi + +before_script: + - if [ -n "$USE_SHELL" ]; then export CONFIG_SHELL="$USE_SHELL"; fi + - test -n "$USE_SHELL" && eval '"$USE_SHELL" -c "./autogen.sh"' || ./autogen.sh + +script: + - if [ -n "$RLPVALUE_CONFIG" ]; then unset CC; unset CXX; fi + - OUTDIR=$BASE_OUTDIR/$TRAVIS_PULL_REQUEST/$TRAVIS_JOB_NUMBER-$HOST + - RLPVALUE_CONFIG_ALL="--prefix=$TRAVIS_BUILD_DIR/depends/$HOST --bindir=$OUTDIR/bin --libdir=$OUTDIR/lib" + - ./configure --cache-file=config.cache $RLPVALUE_CONFIG_ALL $RLPVALUE_CONFIG || ( cat config.log && false) + - make -s $MAKEJOBS $GOAL || ( echo "Build failure. Verbose build follows." && make $GOAL ; false ) + - export LD_LIBRARY_PATH=$TRAVIS_BUILD_DIR/depends/$HOST/lib + - if [ "$RUN_TESTS" = "true" ]; then make $MAKEJOBS distcheck; fi + +#matrix: +# fast_finish: true +# include: +# - os: linux +# compiler: gcc +# env: RLPVALUE_CONFIG=--host=x86_64-w64-mingw32 RUN_TESTS=false +# addons: +# apt: +# packages: +# - g++-mingw-w64-x86-64 +# - gcc-mingw-w64-x86-64 +# - binutils-mingw-w64-x86-64 diff --git a/libraries/chain/include/rlpvalue/COPYING b/libraries/chain/include/rlpvalue/COPYING new file mode 100644 index 00000000..1fb429f3 --- /dev/null +++ b/libraries/chain/include/rlpvalue/COPYING @@ -0,0 +1,19 @@ + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + diff --git a/libraries/chain/include/rlpvalue/Makefile.am b/libraries/chain/include/rlpvalue/Makefile.am new file mode 100644 index 00000000..f83246df --- /dev/null +++ b/libraries/chain/include/rlpvalue/Makefile.am @@ -0,0 +1,61 @@ +ACLOCAL_AMFLAGS = -I build-aux/m4 + +SUBDIRS = univalue + +UNIVALUE_CFLAGS = -I$(top_srcdir)/univalue/include + +include_HEADERS = include/rlpvalue.h +noinst_HEADERS = lib/rlpvalue_utffilter.h + +lib_LTLIBRARIES = librlpvalue.la + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = pc/librlpvalue.pc + +librlpvalue_la_SOURCES = \ + lib/rlpvalue.cpp \ + lib/rlpvalue_get.cpp \ + lib/rlpvalue_read.cpp \ + lib/rlpvalue_write.cpp + +librlpvalue_la_LDFLAGS = \ + -version-info $(LIBRLPVALUE_CURRENT):$(LIBRLPVALUE_REVISION):$(LIBRLPVALUE_AGE) \ + -no-undefined +librlpvalue_la_CXXFLAGS = -I$(top_srcdir)/include + +TESTS = test/object test/unitester + +noinst_PROGRAMS = src/rlp $(TESTS) + +src_rlp_SOURCES = \ + src/InfInt.h \ + src/tool.cpp \ + src/rlp2json.cpp \ + test/utilstrencodings.cpp +src_rlp_LDADD = librlpvalue.la univalue/.libs/libunivalue.a $(ARGP_LIBS) +src_rlp_CXXFLAGS = -I$(top_srcdir)/include $(UNIVALUE_CFLAGS) +src_rlp_LDFLAGS = -static $(LIBTOOL_APP_LDFLAGS) + +TEST_DATA_DIR=test/data + +test_unitester_SOURCES = \ + src/rlp2json.cpp \ + test/unitester.cpp \ + test/utilstrencodings.h test/utilstrencodings.cpp +test_unitester_LDADD = librlpvalue.la univalue/.libs/libunivalue.a +test_unitester_CXXFLAGS = -I$(top_srcdir)/include $(UNIVALUE_CFLAGS) \ + -DJSON_TEST_SRC=\"$(srcdir)/$(TEST_DATA_DIR)\" +test_unitester_LDFLAGS = -static $(LIBTOOL_APP_LDFLAGS) + +test_object_SOURCES = test/object.cpp +test_object_LDADD = librlpvalue.la +test_object_CXXFLAGS = -I$(top_srcdir)/include +test_object_LDFLAGS = -static $(LIBTOOL_APP_LDFLAGS) + +TEST_FILES = \ + test/data/example.json \ + test/data/invalidRLPTest.json \ + test/data/longlist.json \ + test/data/rlptest.json + +EXTRA_DIST=$(TEST_FILES) diff --git a/libraries/chain/include/rlpvalue/README.md b/libraries/chain/include/rlpvalue/README.md new file mode 100644 index 00000000..8df996c1 --- /dev/null +++ b/libraries/chain/include/rlpvalue/README.md @@ -0,0 +1,22 @@ + +# RLPValue + +## Summary + +A universal value class for use with Ethereum RLP encoding/decoding. + +See https://github.com/ethereum/wiki/wiki/RLP for more. + +## Installation + +This project is a standard GNU +[autotools](https://www.gnu.org/software/automake/manual/html_node/Autotools-Introduction.html) +project. Build and install instructions are available in the `INSTALL` +file provided with GNU autotools. + +``` +$ ./autogen.sh +$ ./configure +$ make +``` + diff --git a/libraries/chain/include/rlpvalue/TODO.md b/libraries/chain/include/rlpvalue/TODO.md new file mode 100644 index 00000000..8e9b7dc0 --- /dev/null +++ b/libraries/chain/include/rlpvalue/TODO.md @@ -0,0 +1,21 @@ + +# TO-DO + +## Technical debt + +* univalue included as a git subtree because of difficulty in + installing dependencies across all travis test platforms. + Ideally: remove submodule, discover via configure. + +* win64 build disabled in travis due to lack of argp-standalone + on that platform. find argp-standalone, and re-enable win64. + +## Low priority + +Rearrange tree for easier 'git subtree' style use + +Namespace support - must come up with useful shorthand, avoiding +long Univalue::Univalue::Univalue usages forced upon library users. + +Improve test suite + diff --git a/libraries/chain/include/rlpvalue/a.out b/libraries/chain/include/rlpvalue/a.out new file mode 100755 index 0000000000000000000000000000000000000000..1a3af65dec71ee0d7151f8143f7c510d0071d90a GIT binary patch literal 108976 zcmeEveS8!}^7m|#g~(f?0!Bq$5EKD1K!AXt;bnEfpb>~hMUxN$1R=z{0D2(NfRYQ* zpx`TNR8-`AiHgd3s6mnB6fr1jRMhC9ZVY;n^Cf!dKHsYDp6Qw03Ci#Hd7kGFM>jQH zRb5?OU0q$>GrKJJr=An#@kAT)iZ;$NJh)FhRUlF%zTkesiYvuPHo6)qMsLGsbO0&_ zpAnTB)KAwg^?GERjsF$&jh#sYlqFmuJK-ZHx}=_DE(xFld#e#w&4mn4rkeMHjW zqJ@Kpa>G=O+901g_xyAN!%|B)X+|E4?y^kuzxVn1=%Ojtk6e20f&W%s^+cDOvd284 zWKf&LLl@PTLu{5)a7R4c|M)v`-^C!@czh<{(~!Gs!83b@z58a;d96L}=t3yhYaJRr zDgyQ8PLc7qqJxq6GoVZ){7>jWB>ZRSR3v=7i$2p`+O2cZa{~+%N&Zq7`DE=#{P(!@ zE5}9uPhI%?V1h-G|APzuuSZ1YFLdee1Q-4ymwp{|(Lc#W{w^2%&o1&yT;#bGG==p?;-MlXPKjPvKc`o>4J4W`Cvt0T$ z&qe>|UF3vZ@RzyZPj<2Mr!MV&?P8x{F7|)lWqey)`g;=m(}$1qTIbU4xh~^U5?e>A5y^RE;R^}B6lIJy-{i8zyC^RQ4Ho9*&zY1nt$4_goVnSBnZ@y9rAM)KAoC?A)q1!?zmz%v{()7&fiJAUs zBQvL-=iY;9Ntx4zXHFlI>GyL_N&AUI{EH5++Y?01X~jvo`LpIn($?>;=m?D8;n;da zUVc$-VX=R~)br4r!;>+xFc&fw<+7#St>tQdbo>I@_<4WaTSgR>z^e=W3uv6t`jBCT zCHcj93vz`QLik}j;;4d>qPdwfvvaQWAEqaY)?wRW(zeNY3yUDJC^uE+~NC_~kfa#$}5+39G;;n1f=5&di>bnLU60!W?)hGtI<& z&&O;j&Y26=>65}NNM=2ZaT!M1&{UW;KTWm84QCf)XqM#U78K_#%s))w$>!`P(Q}q8 z$t=h%ELxbKJs&eZb5SCR4eN+$?LTZ>F^n`vvXIJOziLGW+`g&J!3weZIlbbnvK{2{<&EW|jG7S0_4ix-=;L8d z(4?ZgYgi839+AupkcY9pv4IeAv*(MnhGq=r$0#)v^B2xRR;1@lhY@ava~wb1kTPUw z<~UjuGUw(Y1Eg@5V+FfE94;+g*nG1KbM=UiEObr|0w5)!LyXMy{Ka{&@6_C)k_EYx zqUNaV6p3lhm67Q{3r&0y}oN%IaS5Dt_WppAIGu@p_GpQbsiH z=|4IHBwmsr+NHYDvc3nWOgCZ=q4qCnr(BJbIn4#IdNhigzdkPB2fIdR>Q+A z=2frZ$D3H3*=cy%v#P66!w*+Tz$OhpO2Y>=Jnbpf)vDpgC?sH;hCf@wC&>O%?}ll3 zwNE5}8K>dZevt4JG`!JG*azE59&bg8)$qdK1SMX>V=HT32^t<-R`c>{cxqc+{WUy| zjk*#wJn5vaWDT#zo@gl=9u90?0Szx*kZEZezKh9i7#SKK6T`f+G<-J`YZ!Aie4K_a z(C{>`)U`yzAE}Ulr5av8FIc7FkJk9BG(4SGtLqL8-$Nk*t2KO24Zl&tAEV)GG`u=% zAo3Osf2_t|tKpB+@bw!0cn#m6;nlMuA~$My`ACRsHEH-0H90{I@6+(D8osxNZ`1I7 zG`u0_7x~)B8a`IT_to(68or-~PtfqEXn3E7mm!R){WZJ{g^W+s@TX~Vk~RDQ4WFXn z2Wt3$h99Ki(=`0)8a_kA57zKm8vYCoKUc%kdZMlZ4bRJ?BrMVJLlrY%sfJI|@T)ZZ z2n}DQ;YVutJ2ZTQgG-sP-TBr{+ zUuc#o0Xxt<&Meb{eV}=WS*C^hKyz=iObhgZ<|EBAEzAd+J!Y8}pN>I`NUseBoT>i`~)53`Un`K%M(SNf{ z3nBV%mT3V*|IIQjeCWSfrUeiEH_Nopq5o!?7C7|ZEYre<{+nf5(9nOgObZ$MZ9OaK4<#!$B zHy!2I9OV}sj{hrlcVzwKvN(laP z<{wV=1E>8KC~pmH`}XX>wzlYiXGdW7Z^hjqV7L?z8)}-(aY5Cm^|*8_xua1sFg;K< z_U*558z}#xxJ#g7Y)@1RKKkEKC^!p?+YT?endfrUHQT59&5PB_myU|a4&npl%i01J z{a)6-p`tTr}KUKhLzYlkfRsQgKP!>Ib_tDF~5?P;i1G+AF3!3Bm$_(To{#wFyNAL@j?+BEC8oXFE!RUJ!?Qc|UW3fg-SW}=f9UtJ! z-=o^sp^+7}#Uo9rOsWgUp9Z&m4*%B*(Wj7T&|ZR0P^vCij*2Z0RH0sQR$!P=w%8kd zj+!moo_yKmR?o&wr@oPCg6LZlRSAd=G?ApE(bS~!?Lc$!F$hkD$B1^%2eAqQ<1ZUG z$@R7`1v{kyQU!2ToPvTXlxGsa!6jX^{k9D&KU@=I9Z zOf*1_%6j;bWCTX}TjOr6g=Y{?Ht`(8Ja$W612z6>j!OBmgBAXRWZSYfPjTm#qfoVZ z1*&$#&6jlJWusf;sCx#yf( zb-GyU^wUqQQ_a7WPPct3bh_ym)(O)uT@B9cu%J63yy^kJ)gOo0|QNEaG*Gd2AF6G7N7#0PCUd(0o_`W%<-x z+4c-acjl_@lsByMuXpLwI?@k)8o787saF0<+;jf*9#n{^;)yg%U(W5 z0af<$8ECA;l+})Ok@PE#lHF7vYNpEn9<~^!MpjC`gpeH-l5JcUoCu^e&?O|mHeF`yY&Ya|7uro2^WXg{_t82axbe ze<>u8$cNiYU5kpw#t7HK?k4Oz#W0g9%aiYm5hnE zVlzT>BCR3%pto@j#Zmrq>KF1}_!F0}r~a2CJ*!N|2Y4}@JCKqhK^ZPkb-~L|6e;UV zwXjD%%vT%i2)a!4QWRS(hNxwOlKmd_2{GV!g?J5!vL+93B^^1#l92$$ozkXfT05bo zmHUV_xd6RdrT2=mh&q1_EQHzaUqvG|i&`vei&`{OVGgie{je22;8=@}A&iVkEIC`T zyd_ww!BYK_SYqmeVkTgzsHD}YE;vKhTVmH7Hi#u9u(-mxILy}sDoR!b>bAj1uxwqh zhQza5BWb0?6}VoiNm-u%Z{nra(y2wb3D1bLG3n64*#cD;ycK0Azsi4m+)Mu3A!i?g zmKcey{~$Yz+e&}2_Opz-;9029vT58_?vhRbkl*<6gV zsA}<4Ic9M`J%ixs@DmP6EI}CSd(^1&?;&iRzfll5L)#MY zAiKmSk~YR?`kUg);^0$U5<^%^!;B5Be{b2cJyCHhZbfCfTmB~g8pWOQ*Hb*9nM4OF zdh~+q3jf}1ZBd9~9x?n4q=y`{{h<(%n_|kE63hLKP>DRa`8HAellNuqn9dmHNCL(v z0a0a5V}t;jp)DC`yIR%m;8y#$78(@qVq#3+8_0RP?DMlDX!$x z7fO!eW+JP14>#bie`zf7V$@axK^7{xfQ(?GOMq?}W34GX@KxxWbkTM2F-4W97&E^% zsf$5%IJ`GlNVSQ#YTk#Nzbho?~ zf1`@C>F@H*_{*NX*He5<^W$Kt@bAMML4)kAcQdAGTT@i|E1+y^i#Y;Yg^w_4KY|uY z#dooD1+}axPE=(-&B1vMykFLfid63&RWDl9!=BG*8OZfIaJ@*C=Ax3cN0oSzgzd~0 zIPI^pgK;Y=)ZNX^;x4LqAaytH<_|;}+?167=PC9!Z^x||B2P0Vqh-sQjFNHE%45cs zjG$WtAPN{dDJukBu^$m<{-XTVhV^;0y?ZQJ?6^mW0mc)TX3(fRPBu!%CM*>$1>5T3D&+s~=QnMMtXzTzvID3q5rya1D+ z8BRc>#SY^wVre1id=6C?JO&Ty_*{WD@O8mo@Z5|J%PP~~qD}4%e>` z_grBD9vnK3yik0t0m<}ru3qZqbQ9v!iJt{gsF3K%UK zWg_JL!(MeKQ{`Y_lUzA`sH_)duUE$P)@8BXWXtRtoAIUGP_Q3(9^;6OWV~8$~rwFl!cBH3LBMra-B6 z?&qu`_x4P_H;1Z|uvRG~c#0xNjU}s@ z%5Uhv#U@F8UNG0n;zkr5+mE;vcOw2Y-;6(II5Tx##a8C5y%JpwXP5(q=1~#rrVT19rV`Sz{=Kee6m)*ntOUy$KJlL;8Z_jDujnY?}fUD8(_L zc-Tw)Uy<`Y%g#sl^oZh&BCCFj#5-9|hx$f-zYz z=1InKFk0KgN})h^sv)d!Ea~FNbbAolp5?woeSH~LGJ@~J(Y13LdYCC5nzhC~7Y|Ww ztKzF7)5EbkqxNK!dbk5t)1Q4}KN*jNrHxu3`Zb53Z-@W1SKpN`p8(>dyH%#&--)JZ z#zcCucmS>!v88ZH!x1{b>XcO8y2}4OcdRn~d)eq}IC?~>=)ZZEScb?H=_#hP(F!K3 z*4o`1NzXWr{E8pJV2?s!Pi&OT29IJKB6j*$U_;bWxy5&%prRD=EbbkdoOVPZnX0IQ z@WFMTVkTBonM4Z5GoL0o$GsP(n44Y5FPhr18`0Mug6`@UWK;Q6V58U`QrSl`YbaKM zE}rP?+L6r@)Da6<=mBIbRmqh*OeJCgi@A|H zlNHOhCm@(bwxHB_j1Xb==q8BJ^;R>j!q6t|Ax?|v8HJ_&4bn#XG11n&Y$xrQ$T_-8 zVFqh{IIY)IK>;RM&VSjG6|h*@E3hbMONn%3t_&qeFc_0=#XhN}kKLF&5Nkg!FZ8M$+x7XT4;#EQdLJEWnL8CN51w*2SxLAs{_LHP9JuE8YWP ziIj=qod;|zQ_H_31?F&bcsHVad@MyEEZ^$AlL`6>6coTIyESc&{>aL_qyn=o>JJ$7 zpn*Reo7~=-;L#C-CR{Ea%4mipSJG{VL)KtV${i}w>7hY)^?JtbALvtnpD$Q*&=$j~ zgVd3Z)az0HhPd15ZHz8RIhyjYQ15!5&B-jCbe6akr(h*lwKH*46TqXC;4}<8>Q7*T z^-jWnFcP3QDgOUrCebib;}r$uNPyIfCeq~~xLa}sGKDAD1ZrA7swao53l3on{JEq- z2>pPtJa$?;G-HLsLOwezw<8>O6%n~*dOKh;%uevAz-d^IUMJtVmV$8OX4x!$hu^h>l*YTRwYCE05Ck1M{05|u}4``hSM_qs-ja%%c2wyl2I8RjLB4v$S0Gx z-g_|ldDbBq;(Z$`dccK|l^k*J05!@VTy!ij%=GKq0<+lmR8u^gGKx=vi!~6dnGD|Z zF13M~i<7?=JRMc7vj-aR3?fdZV?mmY*yoqOAH0NGr5Pt)0931tZJlM$X_KDZ3-vXF zJ5z!nwNb@wBtUKx6|dtWLgK4&>u_irmJKD6!OBbagiRq4$tnYwoTM76b|bKuhbFZ!*MKF8x_(Q zHZFl-(`}n!env<^cZvw4!o^2Zw8A*hie|p>`5OF6w~fk!{$K<>+a5uasTm5~Rs_XK zA?BJhg8udQM$oXRw*=oUK`UYA|9-bE>a}Nm=o4oA2`*yqVX?o@TOy9?*CN1#={wP> zZ#>5vVgFW|GH-Lucwy3bM~qFe1(@Z83*N`U&+Kl4oWY+8G_<0Hwl3J0 zx=&W2h0c0c;}S;ifJ4>FP{Q0#3uEy;_bLEl2hQvkaeBB!oP}@Md#Fbot!bY*)a3|dlqHZui!5OV zj6@^yFuud3RxLq!`b`egZI%^S3@?qy*H!w$4r8rGh~kOLS0ctZ;zxD`&oI42>9UD* zh%nby?b7F3#IdMg=QYP-DHmPF!m^TkFDxE=?2b20$tJ7|p3j~wG6rEc!Z>D+sKu6( z^NZc?6>wVC{Uf`qZ)L02E^9Sm=D4)_0 zsJNWG8MwM&_8X$xoZP6*WiOJ(I|17wbs6-x&P1hvPIym7>ggrtx1WDf`vJ6HPdi{N zgG#pvrx$!Fhr=`m_8^tHewp5h{oPuBqh+43bQEs?SV2BQbRZlhSM*nr?w)H?Kvr$AevE(J%F<~??!sG>zE z)Id>RV}0hVrT|&CtkozM-(%odIR){FllRUpZELc{ZmJC~f=V20ThS?$c_a^tG{g~_ z;k=RFy`o61#`7DQ_vi*I{3jbsKS`6eu=EL^Gvw;L&WH%aa^*f)==cRtVKalDxr-Ux zLe1J|2FA#4!E%~w)O(nYd(Y17F!>w*=0 z5JS@iT)d?M7t1UY=S9>fpweQsZGzKt-eVzk!JAnPa}1RKIQNEj53%Atdk5YHryU|P z24S=fWHj-$6)T`afkd-|NS!HO>EVLYCJJGcLLZ@tS;DF zG#G3-TTK1BVBBl$qCytl#*~A0J?aNfh8i+N1Q+982Hw?l8@4edN5LdglS+8SmwYM( zudsR9zkt=efciHVwKt-6HKybp`Ur@Cy%DkRm5U6+d}DSW3q~xaFA!81aL9Ub%NaKY z3}|@e0(vR29N*ijOvlF$={%=yBQxMlJy8Yk918T4e8>#<<{c`(Kzj#C@tM6KQe(h_ zy$i`__x_nIU+3RKAuRYD-eW)zze>>Sf+h6gIlVzaP2*i1Hh&_|1RfDSQd=mR-GW!Z zwqQ>yG(Xc`voF^)P;(0($dz-=;j(7SLRBrsUhNywyu#UFvoM~$!Pjvzt*QD9*K{`c zq^ucy^J~0A*y=%F`>3YNSpbbSnZI6|XC+~IkkTHJ}eA|GdwoA|&Fy{A6% zNgoG2ylY2M1?En}F&`$N8DQg9+ytA`_tNC!^Sa=;SI`>0WLAQ&19EkYmaNVre-1jp zJ5k813%*C+LMkVfVO0uiJfd%l?VmuC{@<;h*)DBctCfsv+C)cyWzE^VQ-uI$Rh+LoD1iNX>w?qZp-Y<%cZkZX*l>7na577sma(ZV6~ zz`1;;9d-tj1vL4y?F?qzwg`)eW^55v6L}Vr+e+KB+nx@r7F97)zw1H9u3EiG4r7{k z{?6EZ%7t2NK28J)%pID{hFffYl^-;P#pa!&wlg+&79pFQ2E%K`=DzSaI<(}32`}X~ zMF&n3faW!LE4xIoBIYxOd-Z_53k5x3M{z_o19mn&bqR}~&j}SdekKdyb-{XGam|{i za!pjW1?;7=rWLU17cjK2+sco85@qm0l;k*nZ=?nkea+77p{;`|_96{)9sobPXGT?-O4X9K*3B`MhdB`eM^ z#l4L4Yj7J}{~~GghvWRA<4Jf7`lDx-H;W*MuwXxDYlZ=>td}Nrf|>Tpoc2TZp9G8@ z3{e++L%P#xuTs||MrUzkZ^nAJr&QQvSWmomV!ok?Fa-lP1)(3M<&Bi^I-@G*y|Hiu zq`o${^1vGrAMFnUX1KK1_z&G6vb`X$N-o;~`Ev^Ex>7_4-x5>+Uxl98!g-;y6|vH* z6LpyR0eYp>{E9xku#RY77px#O2e4N0=4I1)_?ZCA2qSneWQOgol|*_VMmrvdVH~R( z8fh0}JNdV*@AOPqUt_{NHr%zuqcW`4;=$_}p zkdM^tV|>%!*`xnQd;ENs%lRsLz)h_IDr}Gc#D~;TObfhC@B(fRYmdJklI?r^L^Brr zuBS&;5D@0-H*V1J<-gL}Y8}S^g^PH!%n`;uP!a1-w%0#X*2nY1Tf(0oVx;v0 zCFk)+_|Zo^^~#Eols>^Mn2jX}R<=n%51M};=O(e1>gV(BVwXu~8r^OCBR{_mSLVO` zwYzla83q4u3sl52;Qf;-;_*JsGw@)owRO=p@;m$?Y(K*i)gd@i3#-)VoG2K6zLs+k zmZuP>(nFE(@B0oWG!jF{A~o?j-G%G}ATr$-C<4kTk>FIzXAW06mK;9cQfFK=gd(u^ zwbwESm`sI1=B=3-Eu2mh`OGXiTqFlrbN4~c++Uw!P=@C)j$3iME0^3I;=SE@cm-fp zLfHE(BqIPB_3+19I@#9kuN`VX0LRe|?oay!MVeqAqRm>o_=2f|bQiyiMBnwn`SLR~ zB`NpA+x{Qhs(#BwC@PM~p)kj#fOWoHTOfE2uK(*>rfqn|$`JH-u1{ zh+MwRtXVIYe?T&|%AKI@LLhhdZD`tDF64jLX`4vKJ*ZXpmkP?8)}B9`)Ih z&~NbGv)u_%P4^D{sV2n9GiKQ;y=cw9c6E6JCcw+d=xT5Wo@wLBV`}-gspVeo)re%oKlNuU-AZ@ay{6*E_fB$r=5tl{0Xw3 z;Pvwum{mt`5f-yYw8#08wjtiTGM)YiVzx!J%SjPiL_3c*nGqw})lYJ#onLxRK!0Hr zo)v5y5B>0l710iSM@1FU+SzoOYm04_jQHGRC(fDvx1M`E!ADv4=N>n~;Ff!}8)Yl0 zdbydlU(3Y^QFbvAes`2z4sJ)3wQ_s$YaUs!`$pKknw~BoHK=l~o|WlUn5iJ~Onnrq z89mMIhi{Z%E>^*x6lpl?te!jY+us}c3{y2tkoDjQUffiuaYhqM$rXS{EGsZ{fGRQ~HE3FLE3B zaifYU(tI31e+0UD7axt0Nzrx6H!TyKLguC3K*VDH+9B=gpegB6LXu#tx?rdOP$7x2RUGB=S;Sa2$?5Crg&!pGBaY8{?~94jh0KAQp-P+-++EVyy^l*HWM1K?W%3k zxufU|b&5OMl{)$bkNK2ZR<*Ln>@nz^Api6W4|Toh1O;w(yi;fkP>y$R`27ezVBfA46W%XgwF{ViTboIaJ?k12NUukB$*HT;cSP(j5tGOwyt1{V3k?i z49VZZR^fp?+R?;rUX^G`l!hXxy17Fv%fO`L!|OPpxsFFVRD>azSzFwbEGg({ylBdN zMg-g0#szM`Z!Zazu*|n))7nJ+K6xYAO_=6br8h6|kjul?!)mG?uB*^b<9oot9-FKq z!93i{jrg^=CCggRrSRj8S3e4R+4d~k@7N#+wIK+#>ibec+0s-5bf01ruP2Bzj@Pjc z^UM=FA*t`hoo%s?qVHTi);Z%Gb-uF4l2O`e{arMd%2hi3MMYz9>*TCgMM(ihZ33fTlm4#}PuWA>s6sP>+u&fjG}m>)*qTnqJwmk`X^x(O+u&%> zFn#Drs@lHU5*_<_48C53;q?E$Qx^J1hV^X0eM^NDj_i#oTNhl26UN_HD~I3Pb3c!X zh0C@&LY7!c(9q!=&-@KvwzBdsm?;qfAjnDP?>f!vO9r8Sn$Oh{zy6NVx1SOE960DW6|dq(Fr$jVOd$?#`Ux9 zu-3(JmO>~}`Bw2&EN}4Z`+2CjPv@ggR)f~>%9?=*^y*98zHR!;bKU65XC(-Pbv zTttFPzqPWBfAjZ~;9x>Je+bq&Y%WJ}e$=&eGe?9>MSE4UNw_hry@EA77B1XEY=wje z>?3QNCTQ+Ve=Gme9?y1(R!elx)`e_L|PNA}4=&cpW8*CX+W9O$~BpYul!QYeev zGRblr5S|RBtnRC=2EvB@DG_fTkrVM(m|0jKTGr(^nupO(jg0a)#@$Yf34hbyvjc0* zN8&4aL$SX-vzpxji<Opc7`@V#fNJj5i39Q%k@D7AJc!%|FR>lXYR?ZuFu+;^# z=o^3G?`B#jnGBpHLnIgBE3ZTY!xcfuXd}*sqDl9 z02Lul9C}@kz^Qp_5f>@nhL&{N6)1lzSU^a7m!+?AkDcQw@>aN^m>vr_gG9XJG7m*1 z1XiJJ3pbNtaBE=EfGq@UK=ws;TZ*a?xcE$5WJUV<@D@9_3LNF?Y}g;POr!#ihH=h| z$Y;L~awGa|5}LD4n2yl8*DKDMbg0=dlurR{vw?@fF&lcoJ1ldAkFs{Wc`4M?M*2K1 zM%Z{?O9cC9hs%}TbE9465-vKtr{oXFd)_W@Vd) z4J(~H87Zjq^!~A}5l`<`q}DS3@W8>D9->4ghb~Mno-ZdLJ;Z_JD8wob9?zhx4dpEU zS}^a-{A3)-)q@S?4<@(NV6FvQ&Qx0<-`x~aXbq+#GH&5s?1_WP=(7qZt8p*G$^CR| zf7LTgaXkizbGrue`%|F;6sOnT>!B8K+}gz7DpfIc4j;iAj#%YeeQSEE~f&AKwZdPmPIPg_1M> zF3e!m(sp=fwj?Qw?z+D{5f&P&8_zZK>F8hNWk> z<9AcE3X!ymSMig^eb9@}cqhozLM1e_-UX>VgycxMmmE9#bsH`3DuX0#QWT>ovMo~R zMkeYf@tX(}AqBG(wQn%ifZv|bB%;TSy5mzavt`mPed+%weX%d)*0B`WfAV-B|H?Kz z&HkRwI5<=Lc{hd%-_|9eTK+oVb{^kW$G!rbrFZDDOa@Cc6L3j0qaj`!ad7fK-ZFc9MU}#P;=(vb%5q{BU6_ zQ<19DhM_VonF5VCG|=LWdM=be&Q3`-xEjd)YVdZFcqRn2d?xhtvpgf^GojD$QjGJN z(8J)6&x9tEztS5Y;+YUdOa93wC?#J&RVZ3*sD0tGh{4qUG1!f3PfcREhzX&6kzCc6 z0gkIX{gS`bitojf=S{ME3Z5Eg!dSyjWS^dwv|btEOq{6SC4Q(-B}u{LE~bF^Ri6#Z7QD8QVzZu09Qwk3GC&e# zVy!>hw$NDi;-R1Qx(k&whc@+MZ^ysngM%aIoG^p9weE&xJdj#%#`rV+4aEb1!4TF3 z-)+PA!L+Snd5~P)-DQ4)YQsY&bz06jU^HhMv3@m)zH^?jqn!cMW~9wI zX3}oBLT}ySJs_+YZr#G@mZUm9UA=D0B9U0V#Wd0wnA zzU^6rd9denMAWqW%XG`|1@@c0)Sye$_RtuGMQ!#6A~=2&%x3godE0;oX*L_Rvs%vn z!Ip4cjH0$$22iwC%Q_aWua={D63Bo2D6BU&OV~yh9kge+^qtSJ>~?1rIS8R0*{%D; zwePXcgTneAtAaaVhE0Pz%X_RFh$8n`ajoK0B;3)g0AkyePQwM z7Ux;Km~D32>-w0Uq>ZTwPtrW#kV)D@bGO%jElu^y<@@{`$BTufdyx$a(m6i=Fgt5#9lnkHhF4tXf)B zYjJ`mf(@nLblUaXz3N`8e_r6C~u}xN}gDyN5>b0+`(>-3*Vmxbh zie0lCsWzRP)&d4pdp{Nc~y^ouL)MwLIq*7MzOd+8m(XWMG(;jy*l@! zvJU#X{TbOGesylPQtN665*sY;^1Pq>pZ6Pg`M4{rB`xygFyl|VvtuY$=OB8-v*R;Z zJos$*?6~1An_b7@S%&n%BcLsoHRn-ViR$4gIJ&H$74cE)Yu3*?v^ zQ1H-G=6yWZ*WBP1sx79>RlG|O<6i;e>r>`IqFGbs1JMxAkz%-tHf6eU(K%)Aruy33 zna6XpE>k96^(gX`aeZsWZkKEE=A^W)HIHHui5eWIG$KiaXJT3%FWwSkH@%U97xkH^ zRh}BPEXdWS)tek#C}MD>e7q;3O{8+4+<84O`~gOymPtec$o7p=exFlRYxj^O-MtqJ*~+mQc;0QP%^e3ISaMn`fu`iG6sI{mJzwjHsz9(l;);Vh0Jr#+Bu zM=blGJ(6o@`%7={YKO%~e?ulRr%McqRv8KgN(j9H~wvz`7e`Q81S z2U}`(zszp;RGZze3F}`Gu^(ptvhDp-TWoovxsHCvEaIURMMCm5OgKy|S~>W5$vQ)N z*e*ES4PiLjGUYM=^>}Al8-PPU$Sc7+$F>Ub<~$b9rl2&t>uhL8iyD2?BWyFyGT9P z6V@}9@*q&SL`K5>d;E1oymPO$BHrD&ml3aqZk;ErVn8sP?e7`!vn|?&#Y4Eu?LyT4-AwxJ6p0uybq%ZEv8?+ZVtxC9*XoZ?p+ z;X|EMjJr6sa_rx-@sE~XG^zZ(ap{xFe;7A?T=~KDK;`KhfS#6m+OIH1Z1B?(NZa;n zbn!_;K8ic36v|=iNgL6Lf@5H(PZppmy7M*xXf2)&mJ6i(h6ed zA0v8ILXt_GRQ~h&(*l25;7<$uX@UQ@7VsF@9<+aD7Zzq;ZOkm0Jv+D1m^|%*^L>l5 z=a=OA@``-<3yXc(`M!lS=jG-U`xX}ZnAewG=CkBr_Novc8hbDaVWZb&HpQuapNaU^q+HXVAACCQm34M zLE42=r%g}4=;Dk^F3p~qGb?xYoVj`PuAILhe__E@g+;|Bixw}r`kKTcLx&{|A2Bj{ z)W9>;__)FUE1mdXYUC_*LKk&5%1QVP$7cjSBk@Vb2jBQIM&olPKKL4FZXrZtfm@KhBvVM|O87G~yC{!MfE8@?XmlWFVLl8}f@Ltj zWd3|!8L>>}sRhtI8oNhuD^9CcF=x%#EhKu5k3KUAK_?dhDr;^iG#B?xSK_T>3Pkfm zp^bnA3qzqaz)K54p;iQ?I{@Pmmzxy*d<1Kmg48ODL2ASO%B{ zco8VSD6}8&?>MCGj-WZ{`cQ~|Sm<+{-)8~7xiS>00W?;J zLInusM^!>!z=43Z=;wKWO@P^e6pV`jeSm8LQvf#uW&!R2ECu`?up02hn@}I{EWjqf zxquYN*8=(gw*aO9z6V$exEk-UYy^A^upV$HU=VOWU@Yw1r3!WeoD3KM+yz(w7_|oD z1K1O=25=r=1K=vaRp?izTSB2mzyW}5fENKKVBuHI?kp$A|FU=83>zy`pLfUSV_fbm$U2HFW_Fl@%WCwLBI^aURdO60LK8v;+$dz;1z&N0Y3p; z4>))|>I2>YxR>yN2LZd_3ktokK)ww)2C&<`s1JBP;8MWNfa?MO3Ah!o`+cYnm<)Ij z@Gih!SX@5@90T|p;0(a-)u<0h-?Ul}SO~Zk@Rs{Aet<_kfPP~^UiBdC4Y(071Mow@ zC4gT8-T~NmLnyQba0Fl@;4Hv4z|DXOShRNlCIb$72>u2*6R;HU6~GOELBQ>RT^${0A~Si z0bE^!c>?$ZASERYfIh&_0aE}+J%xS)-UPS;@I$~2fRmp_zX59i_W^dmWBnK;G)aJc z0nY)P2$%sl3-Eft6@Y62HvkUZjQIu_01N`&0T}CpUjp_AjK_oCG{AEJ3jps1tOEQ9 zum-T#bMSM(fq<=mmjlKlk-8Bu5pXkL8sOJ}1%N5fqds5>U=83WfDM3MwxB-Xc))lh zVOfBQfa?I$05<{_0PY8@0^Iv|*d4If3m7-R!GPZb-T;_@1g-`!8SrJm48ZRImjE9B z57-@W0N@tD;V)v`00V$+fG+{|Me_H=ONcXoF)zbk0M7(m4Y(HYF~I$R4S+psp*LV( zz<4B#HQUiH;H!WcfbRk>0X*t8v60@@IQc*p!UJpvk!0o3rfC;CA{yyR%;26Lefb<>QrGUEuHv;YhtOxAd zi1`J$6fkx$_BbD4egR$rmdI*-4hL?4KNAt^u4GLSPEDS_yXWsz0;J8+2Y^1n ziA@-9z)JwL0Ivir1*CsBz8Y{RU@c%PU=yJCGt?gjzW^KrxC$^8@OHrYfDZ$%27G8A z^ak7vxCd}M;P-%uL9Aa%hOr!Q4B%G48GyS0mjZqPxE^q5GuAJ_>j9epYXEuE`!(jr zaKsD1iGZnqvjFb`Tmkqt;0C~w7K|6*gMj-1{{t950_(_r_$lC6z%;-#zyiRR0M`Nr z0XG9)^bO(>UX-=pEw;AYAfULhB5Sc{B>$;?L=p zFgdRC;@DE-?Bhlc7}gh&T-2Wd7|4Rp5JFzmUNJstz!y+`c~M)d@yWSP^835R-w-vS zYln-W5b#8QOwxM-8j3!}qVELy64XChr%$%%`+-jd9ZRKE|00Xt1^sT1KIjni)I-qc zOFBZJ)qb|s{%X)KYDd4vB;Bq4PSCSZA0g6`Khu)GAN2X4W2v<0ms<2LQP?Aaj#R{= zr(1MFd#*`KWl!mN_ZO3~BrAU*zo5_gsQ)Zr%#DLA8UC{9s7EY0#b{?Q_}s=}?IGx! z4?*8^2>SPuJ{EeKepD>SHI=VXKT52AjDi1NggqHTl*Kd8qR#+* z9_T#Bl#KH%`clxZ0DZb%KT0r=zpn@V7SP?sV=L%0vqPas{qUjwUeHTH|3H^deRxCY zKs-ha;?m4eXsXV0?&|2Wn5gl@MSAoF&n)m@3AFk-%j(BO&3?V+Nl8pcjIUCB@Ps&uV7_#®%R!Dg8M8#$ zT=ZularOmmCyhV&o+G}FVSEoOKJt@!h<|?}zWqpi?DDQue7#`jm%#TZ@il0CWb3;v z{U(C%?A%c3E#iCD!MDxgn-9J(!RNz#jk(*-7k!k68L1y@!S~7RP-qkJ-Kg;e%A%w1 zwD`zR=uD)E_?A2P-V%Id-!2^x@8`M4he4np5BfXcHEj{~I_u*DDi!oypx=UaOgh^> z`g&@GbPiw)$IQq2L%JNN=|Z+TAZ$Ro+yPnL7lcBW;og)LHP!5U735q1`XY=`%x6eu z)!0Bz^xP;@rzXg`XJIH*q|2eUaz$ID(_YBh51!{p)+UFnjY1aj#dwkH7vjAGx?f}G zi~87-Hwb)f*M>sZ6W>w?pB87PgRe&s;sn zxgOos^0g(g$mdH#A$WkrmnCHJ_=A2O=t!e1`T~o-1@zlNkJIVr2)YlrM$m5n{W{$j z$v28D9S(wLAL2a43scvqMJ$AL=ye3rp6ijT+UOHZ`WVm)Ku@#L&o${YK(7Yfr_;53 zW~ro~tkbpics=MFP~UA_w}M^+dZcxf+T4tBC;Cj>$6SAk*2ha&N8)J&&$r+S5YJ4F zM~*Amp>HSbfyHR_90D8KOE*c>H0-%2gx|=V}1%32NcVAfr`aICx^xFvf1E9O@#$Fk!8RBpl<>_MW<`y69D~n(A~yoF6i+$x{uE)(7m9ar^^>9 z2>Z`Q&=WzYIBfc$NDY`?4|)>l@)*!f8xs}GLYN&R09-Un7;|AqUQ*EL?6 zb2MRqC%(<#`vrW9C>}p;=Zl_e#le_v@ZY~ijw58dzLFj(?;`p{&@V;(NU@mcvp}B= zI<}rxzX~kdtN?u$=tt@FNfvzr=of)LSf|VNo8)ho_1)s|KG4^?$R|7Pg>T#d`fS|C z+}YdGk?fga=`jc$+z!4-W9&oSz8K>VLC+#NmuqsOM9?Q)3m~IsMJR+wYqfK^)kYQQ zy+C(c6KX*BfsW$=tA4&!zX9}-pkJcXqtcjx+HVED0Q6KFU94$jiy->29`pxsA9J72 zYJ+UC&T1zarvb;Tj=c9EIf<}&66haALC#{koai@2PDT2ZLQe3ePzctt+R|)J&(XdH zJ<=LS^=l>F%{QAsKZyG1wk2QY2~^)W61gAfZocUQy~EA!zL^4g8|u6HW>!1(eQ2JZ zH&Xo)+{Y|NFICPIC4vX(NY4Z(LkBk-Z3jKI9Ub?9epWm6V=(bjK+i^7R{LTQsD1kP zQLY0$(ms>u6G6Whbhlh>7U-Knk2D74D>E=g8$dr5`;?f)*zGDCz~`cmjW&JvG053) zi@P0mg8pzj^!=c31RcO?LyI$AaBy@N=#kc7AF2!jeK+XodVQJ~BIV{{ zWUB(u2ZLUq%ZQp|_L2S_rE5W_SY+BEN(2b1UjzDf&}}+IS$RkU=)ZvO=8vtQ$F6m^ zK|BsCsJ@$x5<%Y&`T$+OY%4CLf&QaQeIM!+fF1<>UcElqu*#CL7CbYdV^5t&JLlUB zdIsoeI$aI|*=P^wt6cg>{ziUs4d@*2&p-{$-}HFjs|TKSgKxOrj<%+c0eu(fZeuY6 z^yqc&Imc4aPi}|49`uQzN18X(&#j;j1AVBjpF9sC`d-lepu3ILLC`M%{dB#)cCOP4 z126-0w|PAV^g_@t((6Zwfui|Ks|?TGWq;Hd)7NbsBOX?a)% z=#PMYiB6Y!m=Cxmpf`b@q0=4XwjMm)?{*)zt)QO>dL+A2oZF0X?*clVtHxxapzI>f zLzrynK`Jgw0jwRTlYx8t9=zBpQqSNPE^&bQM8_?b2*-p?~KtDsTKijIm zAM{^9AFtD|7IYtQT`-uv9t?%%=yY**&KnpS>qPv?1dp4I(m*c;-A#uA&{u%&W`iow zmw@hO!y3?+gFZ&rQ9Gw-0R3*zZSyKhoa6XVrxo;fKwqiXr+K$n*n#|&{3L0E+ygB} zGNJja+5?fSF((+tli;)EAtYUJtqN2dhEv1G-y2R||R~=x#pI z1o~jm-R7==iayZY#?uG-2+-a3qbZ<|0^QBtS)gC#q-$}G>`3oKJp>*%I}*=E@a%4f z2g7RY1kbPFakKS)(9e1}@_J46yI}h@6ZA;FNq!LnTc(5lce-B=i|T&yH_Lwpf$vN3 zrFpZ=Jg=MSI;g;vE6VGi3=^<-Npu&^v(cHg;P8PDsWq^JP=x*b_ z1oSgOM>b^D*Y>z~fIbxTfjWJrwXSRdeJtn*X;yu0Z_^0+7|dvG5U zjSNza7un%vs~sPhH?`AF3g{a_ck5>s=r4jE$-il=Nr#6X=ozQ5_I^fZkqw=?k7L@VJfPM9`;# zeu1t-lsIH1y~p6sb)fUQ`6M1n=)NY`P4b1+kaN`I?d1QU`#_&zYiAl8o9gcbeFo?y zHo7=)Ao_mLp8|cJjV=zah~5QB=RwfjY&i(@??896Ln`S10^Myc%m=*<^g(+2a&JoQ zuLeEl3HPyn4D?vgBk4ymcmu}zSIFlWoYTp&bA%Y&23g}F%dIa75SRoyBDp0;J2y`T z{bUz9jd=#>M}Z!S((0dgQ*>p_YHwMG=oZ@CQ=d!0*IeV?PBrL_E_775zV zudH@5==7M{34*W7=Ey!u^jJ*5GeIAVds7Z#;X+xzKj;~tyV)xM`ee|t%eLx^$ICnq z=Yl>C^eH-Bd%t28==q?xwqvAPlDc_ zz4n5KzU$!D*Mp$9f*xr;QD1st@%;kyNc#aF=wm={1iii3nFXFc&qdCwNJc5>gFtUj z#s=^#0*_liwu4>)dL%umANxSRwjCW}5Rg_KLWlm~dAl7Q0-%2dy4yND7j*g^*JS8p z&M%r=D3Xq=KsTOu@54sW|I<$U^`OV1zS~|W2>P+0yXB0rI0U~C^hh=)zojn@&jy|I zrD0yH4~~2(4RZE^Zzk1I>zwu;LILO};(IVDIvp}pZd(QVS)g;9s=l_~*MLsnvvKp; z2GB=>K2Mh)CDu4hJ)<7|xDIq)Bg$ed9V4s}y)gN9fHzXiBmKI=rmLoc?!jE1pvgji zqGPOm?kvbDoE8e&@H*Fy|jKTmSLheB-+%jPDjdzFVvjkE--ti#s3(qhns7kf+lu z?~NX#+5{>kt2=l%cQWql@R;YmPR3J5{0GZC^iiMgezZ2*`;N!h?D2l*fiZ->hoX1s zkE6Hg-pdU7*LtXbxvzM(L>as3-#S4tcC>e#ajCe+2#4-I!E@9=6sLMG_xz>PN{?|n z^%~wNuF&26Jjb1RDUzs*KVG{h{om&~}S=sSCd~qkX_xrI%bF5zf_v&=W zz8&j{yTrTLv&PfuZjbS}-f`~t>>OK|$>T;%IAFyN&g?*|^^S@v@tFk!T>fBMXl z{NfVdsKLVqC!RiJWC<6CTst&zaAMMF0&TAru@sFIJRv%q6m3Kq$r16XRe!#~HN|@$p7tg!LgBFMX?cu1kxiU#6?kG2%WNzgAcKd?b8#qwSSQ_#Q^% zcaiWt&2>YkM&sA-)OumZCm6L6;#D+$B`;DOi^l4s;=WxDRw?P%c6=`*B_jR=osI8l zR>TZyay+NX-85^)+Y5Fz7Mz00^q4#l@CxI zx~|5@gI^R>>oX(q=MH=#>3=`-A7%LDxQo{DOi*{#P?|WL*M`!q&$M{}Gt;23t15f(Y zP7r)_Mn~7960hyQ>@O@y1^HQmv_#H}u1rk5|PAcL2hUFSYB_N-73bgt6Q^`N{ zLV?1OAzvL3e@Xtaw~Df=J3!)V$nkKgJS|P)S6v|RGX*fNk@)lT1VXB7+%NIhtP%L( zl7A=gsx66P@R{V_IbC31lf=pJ7t(W})Kkg1LE?+^1>*?Gk3&Z0KS#>pb92x>k@#LW z2u3BR4-z(#|LcPS&(9)oJ4fPM?-O|0ZR16W?;$&?+Wi9fNc|d##F*p{O%rmG1u(9V z_yvyndiSBd}eGJ%lO()gRi?_VkKDu4ANAtw11*9*Mr*93{*T`BNNw>c8OcZ$F- z7r^+d#6KhLpyce7_>T$&BgIF$&c_5l3hh2E9cqF=8}k@13mRAfJn8xQbpknF(w>(1 z@%Iaa>aX_*!QXbi!22ZsNfN(tgFxg<{CN_8|15#v=b^a0UE(+U1%80!e@x_I)X*QTmVa=V%60P@VUy(lMe^TNE%+gpug=E`IT_Lqm7h$K_#L+hJ{89bB>ug%0*~S2>u(Z&j*P>~ z|LY~*ndkf>@i)nUI!wyxjDtL~zcW5hkofa51*2LY%YaupOA!p7ko75*ZLpCbiG zvhjw*7fcoW3jdYF7t6R*BFILs6NLP?FA)g(jRCq=NxZR8l!psod;$ECQO6tVd_|&- z1Cqb*?E<6Z)At5Q{~KlqyoyUJCH|a3fmiWxi^M-5t&zd-?2uN2MS>PBJuZ5 z7YG#xs(K6l6d4G!CI8P7|H-2Qp>!V6N6g0w(!t-6{3VQ+1r59mJlW^NFF!@S7i#kiszS0{5Q7>{4@cK7bSkr zMFN2$U&r?oa&9|El%JLOQ4;T5A1{&kpwzR6^SErpK^m$swE2U=+@T%{!Nd_-Se&_o8jthV9Q-%CgN8A`D@nfolbh&IB&jTN+ z-OnU{!BWA0v{dSd{*n0y08iuVoGJc ztCT}O`9iZQE|IBp)e})uCzkf^o1Md(B)y#bo z-zUc|hkh5A_?`Lr4-&ugVZkq#Lt_*s6!FKD2|UcsSCPcOw^)?BNxTOEf%TDc)V!N2 z@dsqwQ+nPg@y@t$!XP1MuJmVwFTRFK{DzxFIYj_tsl;FUfIuWm{3F0C8%h*|-z0yM zUtpE|K?q!={}1;Iyju7D65r=?fzJ}a$d~vL%z?vAGlNS$4NPRB!2oi0)a5aS2OVJZzDumhAo5s<(NozSPDGpIZrlN zFXhxrd?)FLaC^SaON=b%9^gq%{vyGbF8MpakqE!%Vu4WO-XD0<^ER|Y7yULMT~{++ z-0Oeqq@13U1y+sM9x2B+OyHFrK9l_4tr2)EuY4VYfgpXHc~pPkBiU!X3;sDNr;GHr zDN_DEi9a`AAmAQ+B|<-H*SStjlK5HI2|lRJ*UJ*`Jb!DJ_yrdR+3h9Z$^QFC2|WF#AYFST|A8w-xu*bz2MrNF%^SKN6~H(VcVAkrlMGKs(M|MYex zK(bZk`6@0bK|u?AiQBV8B@)N!*`MoM<^s*UH*cIC5RiE3>Ar8eVS2jl?wR)|1>hb43!;gno08Z_nDe?qj*<3dll>d;F&&CISAn>eS-t|m>zn1|{{hlj= zO6l{cDSt|EmC)OZWjt>*aCvZU9|xS;xk}`-;^!`b*94!!mcin)xcqBwecgU-Ci*92EFNpUv%jO7MJ|z#D-3=?M1cLBjPo)n|Gjwz>=yXzrTpiG za6TsR_Zzr8IJeJAJLkWLfy$>p6?jAV{eaY&*~{a+{@v;FRe`_c7KSU%-wL??&A;%! z_X19MyGZc=1o?6AK8CM|+`C!eZNPo)yjIHZm-1TXlL9{|;{-dK>(u@Jc4~mrcy4_m zmwShl|A4?7FJQogz`qGN`KQ_V@V!$0-U=5~dN>^jr1qCDV)&KP&b0#nuUi%1O-^`>?{eKo^H3{0E9Lh<-ci4AdOHK&A@Fwsu6+r} z+7Ct0zYw+;c^S!De%vuJ-T$99~Jo5L@#SQ{{;A{*#Fgib`5|30B|23 zo&$S=#&#w{q2Zf%6J%XPIJR6UqeLkAk`67R`ecG4Rzh#K#_EstXHCZn$^HqUQ zx4CpvDxGkM+kdRk?NbH*Xo0_7#;^Q4FYpItxa5{!+koE&?*QFG~4W2|jnpk3R#P_N}t}CJ#Q${eBngPuE#| z3#JABt)mQ}cmL4!Nr7kS_KSd%J~}83yo`$nKffRK`sWd=PNL&)Z?A(DgmO1wWSZcSHWs^?1GoCol6jKZiSA=kqPN zSm4)*yj8hzgTQYTLheZUe+B#z^0#~Ysg%D`_*%=%fdL86d*8yPVJ@2MWdi@Dj8pmI zdV#;;wOmfy`FDX||7M0OzaN0XM(zJV*6We{bI=p`O)p}=UV(o};6LADfT+pfBp`&^ zsjo6z+b;_|OV39I{%TP~3)23b0`FhK03H8N0Vlf6>hTAnKK1)J%#SXm^C^M9^cse% zoV*QiZIgfDf4?W?|Kk<>401Ks9talSyp9U|c`xU3inn(I?rZ;V4IFw<_;Eto|DLpS z!k;tXGJ&55`lfy#_BsaW`hHB{|Mq%@Z%Fz77WlOy4|NRB#sU$Y|3KQ0rTihlsr`%5 zKV5sxzj)_@z^@T`sO{e?@CUWHAeO^i?Th{M{WRdz{!;}%Pm%KfY094x{OI=?@M(cR z4sw>tKUvlbW|g@v68Ow{{0wnzuHynfN$CG{fxjGZox6a{?JH9L6=DyVbLIHu{{(*H zpK|G^Nu^Uke>9$5kc)IZk#E76z~6NX19Utq0>8g7y2_cJz+ZO*msfppgTVWsJGxHe zTkv&(-zxT=_Ip1((|9hGcK$%hKOJ!2eCMV7=i6LxM#{fQ;O`eZN9Ef`3)=azl%IVi zH&B&!9t-=M#*>Z99Rl1po((Dg-7Ys^-U*05|5@PQ7Xct-5&T%-ACmG)|Bs5e-v40*`Ji_1YXzR&zx%Sl z|N2^PK;=mQ1QOn|bnU*LfWg_~(Q^K_2G1Lf{X$lAm>bKPK=qr5zE+!4CzV zjT`(@;2(G+w{tq*g2$sGjq?=2!!ChW0Dpx1?cOez@>&1uW`SPvXJVW4@ivH4Z)&M8@cET(dr0<5%^)e}c|7CtweBKTCZU&|P z{h5@{+Qaj89?#vl)1`Rc68KLpV7Lr7_=>>KEi?Qoz6IYAcs3tn7v@iRUKTs&iBf(U za37v8D}cX3+R65NgTQYU{3{*)g}|SC3wQWz>GvA~|HZo*aG}5#kNC&)b_0i8dM_7z zpp^eG;54tdgbdJi{EWcAFN8cT<;P$sQu&pm4A6dGBJdL+59op#GS~YA{<1DVPYC?B z`>|hkso1x30>4MfXZM{?Zg9WZ{G7JHYwzF&6mM?^+_x?tmhvaAr_29b;IBJ};fjYR zHM!rLU~kd|w43W{fq(WgejXF}djR+K`#(}XyYKT5)F*si_i}FFanjB#;Jf8-_jb0F zze4QHhslqBCGadieof%n_}Gb;bH7iJbyvISRKR`xo+ah8`h7v*pV{Jp2zv)t0`9}Z z-%I)R44zNIdOQKAsx;qT<=7bDgrC#T^Z~qy9(|De7B^OkB2x{GaufKWZ$XG3?$K80X+3UyMsNafe>+OxW7erCL z9j&dmSF7t$9bX^sMb*t?L9N~DtjGPhJ~lT#Gwv@G9cgYfqiVNXJs!my{qFJLNVnRG zqxxp6bsSZkCw#WN*-sU1Rht`QwN599F0S+smiBa-aVMyp|9(+AGow_J(#9b7thU$l7sAqIA$&37;0p{c#U+KXqV_D|Q29V?ZV78RU% z-N0t1qJDLCoyLNR%tcYNO_RmrR4KwY;H!On2b~~IeC_-SJheBX>P9`P$NV{TdLC~! zgXo-thxhM0h$@?_Q8`+~N7D7v@xbNT%li(6QMfoCMR+=A@%$(}SAgfvF9*^5MT`3m zl@H*z6sGHG07ipv$7@fA&px{nu0$*Q_8$z<>cxwd{tSQHz1*l&%Z)HB?TIQ8KL6h6 zwvXZq^!WZfJ^~+B`lZ?CMn7Kbf@I8URX6(O)q|_0F!VN4t%S=9m6GXWq0*m?B7^4A zg!_^Bat-a4YK=04sLVyc&wj#Br9S~2CIelq)-FF=MOdXy99j zK_h7*FeJ^fi~`_+t>u--P%ldP$$nhPz66H1*fA&}v;b=}U2uH66;*4sxYx62hu~NX z(KFYf&X!i9r3EZ?Wrl{BUR%W%MjvfLPFj8>@&-{3%T_bhPKU4van|zj6*#pJ{ZqZ> z70eC5%6N1@MRwU@{Jdqufm@i-eCIImZty%8&6C(`A1^O88sQe!qQnbJQ8%tO6}=v_8O27 zwaY=%q?ed~^1}fCqDh#!H5`!$~Iu0E&RqX zrpE3BaF7?qMsJ5DSY-U0*aBWfF^L6WK@EL9omur#PS7Q0;UEJt`CW`67K??ZPLUpi z0huT=M~{FQRksUOkkl3lHxY@FCQp#j0a`Zx3KaJsKJ*fcVGGtD37<|G8I<(8tx1gq zIfOA-RYBUH#P^~@;FkIwo8eFd+iMM8Wg~_jHZ>ff_HA`Qa9iW^@@m>_aXtTQR5ZkuP zen805qI|9w_xDlAfm$dZhJ#&iZje0;R~H7>&ZW0)F_~F<5y?8mt^jL&>!kP{z6`$_ zva%M#pt`f_OcJk0B+6yhs;Dw+mUrF;&1DgK7#h%Y*~s)eUUjv-WJUu+y9- zsQlnYljCj=JFvQDRXnjJA;y*=2_kcjV60Z*s;(o7k&YvHmsqGA!w>;gs4d|BWwnK4 z%_l0tc%9z9lI4@Q1$u2kFewFPM75<3cwR%;ib*e)mD2=2tkfE;(Mc_J@n)PRqJnX^ z+a^mFirwRF=FB~ceW=y#P*`54TD_%MO6Dopgj-&LxI7jar`6&$QAFYiYR4iyud zu0is3Gme%7#4G|5BM?&?wg>XZ)6r2fMMr98TOB=7?UPzII6^>~f~1)U7bdzMZ{(t0 z#Z+MtV0=+wxj}y0f z0vr*Rbzf*RTqfq=0B9RCjH|6OoAikNq!>hSqn1y^njS;Rl2OX8A*od=m3!yL#}+qR zt8sVq)k_fFYPvx+M{zpN9vp*h{FPG90s=l^1CbX4MzAYa8b8`a5P~)R@`!X->2Jhn zp2B#tX5h3$RTrr8J>dDZxF4-_k|>2Lfn2o64mgBV)=mEt6j? zM4UDyL`NkvGR}fAJ~)DE+elgW+ZtTC#?(Id@(*O86Ypps+F_(4#s1RHJZVo>!eC|W z)37?o>H?nSu#&1YgB7zpYMhqA;@Rpz$DAdLZ=NEFFt3kP*AZhS4}}L+tX)RjBS{cl zK!&Q6v5S`>!NA+GiYG9MW>_Y+-#BX*h!o;9yqek{5#s}?5kUi_vcB9i% z`H)9WrYccQ7%P@V5egMa5No?bb|6e@LDqTb6N|=`jK|m@cpu#X$X&m?5WaBH#WP?-B`8+Oq`r!a=_iR zF&#%Y8i)53NX2>S-Q8Yco??;W$OkX4+Bp}jt}&F%{vPl#EKh;N{C;d=!40BZ-}u}x zA{4DGu8G_tibphU7TPu8MA{-(qu6fE5}ePk729pls8gOT%m5-gPOCWDt#$^I?Z8PR zU}6Gq&~H0o;n6g+>_{yxBtFx0zYR-3GJveTZ;dcxq$P^YSjFT`WVes){K6@!q7CT+ z*q_y;GKSs!^T)u3V@T0Bb}Z_|-Cmpg;QsMw3#nIx``|1U-1= zvu302?2W)bCZ3O2Zp8jT=uJUL7*{bb;kXeZCX%w?lQ0PpsF^*yJivS^5-mUqQ*R(2 z_zVe{KT9R? zBE;Oz9xTkx`IXvw8d_Vg_m6ZUCU=;;Ii5g90Sm4|CV=k@_rvC36_!KC@bqXWhscJ~ z1!`z{ZV3pFVaf9&h_SE%^@A52l#QZ065g)#CtJ;patjl{%0YaKca%1vB|)kvrywn5 zax!8V(VkFnVZa(`dNewBdlNAU+9Y>23p27eLsxc)VQDX(!$%ss`sJ7}UECyQLXbeNJ8{%ZFiYFrz~#DV2B43e3lB#82%d z%XChB#YPP6U_)kTN2qB1d`y9Iyhc%lMylBqx&d_PT@GjtiCs;Mi_LGhf+@?82Uh6n zrI^@w;0@j>Pm)Fp1%NBN6Uw#t)5T8WGzoE$S>xL+o|uI$?R49n>KYQ;zDDDjawCcAPn}4R(zO$s1Hd zc#!aEjo1hEq;q~jOE3!a9%b=>3zN5EI+} z+d+e7mrY_eTa861KuB?jjXeofx+;;yo5nDQv8f!=_HF|e1$MLP8JL1|iUiYWVTKXp738kCe^V5mE4z_9!|1uN z9o#F9+8yR(_4@i!I*wL=FRw3UiAB$LxH1{~h-t;7rK8ybiW^Az7UhXbOPTqUsw7?6 z;KT?n|2EQenC&Z{{Y$#r?}+4guT1(YEkZ(4KFh}<#T-BwYy%;=fGK1IJp;R9ATe?7 zn=|H79A%EzYLGR1KxRColTO>`5jh8B93N>3w66Xt@M|)zD}4;MTHo4P>bymF0SzKW z5ef$MzWwkr%$2k%$w!Ie)s6JbAtA!SuX{*nz#@$%ylmD!ls||)qx*gND~Mf%Q0d+f zl|Ag>m|bLbZ5&NU{xW>xr8y5nx?YHbjf~fVaF~fSX#&r%4yPtm74D{)Z9mCKOU%hV zlulyK$+Bu8A)88zBVCuWfihGj7HgW8(8@?*;e&ejv>`;o2KJuW*&CSH;klPWQm zfeYiSB~pRRO-kZSZ#kJ0bRKa)r0phU$RS}nN!kpS{T#KJt*inkFL&QzHHv zp0|mcaZI?7pK~aJql}aW^5!UlNAEi@NACOrI)tCrg10s!qs#ca8gTWTlQ7$X(aNC% z`f7xfXK1NWgOIL}8373s12-^y*vE-_%x#_yksCXB$EP}cjivW*O$wNLNO{V4Qs{FF zgpdUGE6rA#d1HjxPs0!mg}~$m)#cB|(LrUB0GfRUvq8>pgQpFB7uIuykx%s|axocd z&L_;ch3Nxr1yn;}0VPB^|CL0w3j)vvIc_?5=QwRpO6HiAcHrXTWEx11M9P`9@g;4L zEUO{;8%)x}`y{Gsls#@(v|u_m6l8WSM6o4?f;l;v(7lyhsVM5;&6{k}!x04s z_?#v(7KTN>YiVHgbRZrmM)=mXHj;zO&@`FwTh^{KP8^jnf^<`()%;Ev=AB{9JS1~r zSl$dta4y^~d(_hNS{Rhb#8=4;7E$jtq7wQcCQ!3Y1F+i&-+WgI;nGGWVHSi1t}>0K z-Q;W22GmeL)? z<+#8c0aIfRT&piIiKP(wTx8yVVJPI5s=w{cWSi5Q%m5*s#m24iK4-J|R75`8+h>EKP!PH4=gO)LB2V zXOgT;`z_4%E!fJVU+KaO`Z0{PxNR)>}$~NPk zQJGkN|Lavq$7Iy)NUP#Cve2u=pMQ4}#4(TRh4}|lMn){T8Lh}f=X02Co}?jKQ1V8t^p59t zJLrX5@+RLh$!c}%-+VAb1oS{VAQ8w3yNI(20r{LVQlm9UO_USghEs_lloT!%N+6p zZxVZgaMI)Qret^q>ex)+os6tg1!^Ur(ID)USNiuw>KD`?@591UDd@cD+()$9>$%!b zjlmq!oE9cIr|rW|CS1>|XjjeXr-#DZ=2CM9%eWU20s&o$ey z`K!Hnsti6Ros^m)=(jY!xkVW&i#TYOxXjZRn5-3|ZxD%RdwG~G_GG0JFHc`?HQWZf z2R-4=H`THFsr?SkN8$JL4SLz=AjzN1GNDJuc(qC(T5qn_qFQg$yjC|YK`7KVn%TdD zT~YHs1gs`FAUTMuuO>`JPyRmd&)Q9&;Y~Y`sdIjQpdsK}S0-eBiNo*%Nc3Wg;B&j6 z`AASIae0aT7K@$IxP1ZV1r*;&mfA=j2%hwU=9|wOG0<;`0aGNB#k@mm!;&%lhR2A! zw%44W_J*Y#JI>CR#3`Bj{JLe%i%g6_h8ivCphB%w_kFIuyh{>QNQVIyt#Hc(y&%mX zvaI^Z#>AXJmAZz5m~@bVRgXDTn4eDiWC11hJDCc^eOS57@F`}8P*y8$k;N}`Xft3P zbgRyX`bxi!mX6TiKT4lR^L|epM{ih67b;_R^NdxC_Y`>F7X)(Jah8*hSzDUfv_1J- zx{`zJL{OdsidmyOVKc=Pg%{*>Grdr72g=z*5X8@bBG~3ggW^&8ay%XPU2qQZk@Lc= z;UNOhuoeB3+z4G-t=I8dpI-Y&@JAb^cFfMYIktjIAzRE5v>2gv4GMxI_IC+BSqVF6SRT&q7>^iM zpuBy8H%TxA_kcF$E^=H%x!X}Dpl0Wk39Qlk%)B0VZo(=9JTV}fl#`*i^d`OjXosR& z4h~%Y-E6=fX~4nnXCom^#4lMJ24}VlA`U<9k|G9&M&N_Q((g%gz9K>7=i=ArMvS;Y z!E{$%p|_&yXFZSzK_B&4k?&CqlC*X}mK-~hfxLGC9pUX8S6 z&T&heHTDo?xJul@CH9P5r60d&rxpu)eOXTvdwQ6jz7%s5LU7%4%p4+o)SY??P;ibz zxa>=GOq?wGpbX(Lv04e4fI!6+C8P|Rn=i-*MXD(*=4~y`M(Iv>)-8#EFqFC+y|Y{t z4~9+QMyMR4(Gbw!lUym6$GqnhvTWO&5#W%Bp0%Ar^!K4KazuruHzhV#qLRf)^jcS<4` z++{1YU8F3Xi>hEMq%w;XW{zG&GHbSR?)Thkg1@u*X2Y+mewqbqQRMv(XIKgate6j; zq>dh>A}&S*nPaBH6~hnR%-?>n$+zY2cg)CcW8ci5!jMC>Qh-^KbeJ`*{1QRLYK+eW zVic)xtM>@T4wl=Sz!!}5j<@htFx>lHzBlwQ^PcriFow@+#bfv+(-<9e$0wSOJD}Cg z=6d~U&ANc_s^F*5A%0W5QSCK?vHI~1biwz2mw(y9i-Yh|m()Xq->@H2r3&&_XT2Yc zQO;*DhCj#F+VV#)t_5Q_|BFYXhsU~Y^I3_pxFMf%Yt+%2KB1c$-bur+o#!v0nO6Cr z3%8+vQ#&*aG--xhZ8gysw~k$kU<{v|YvB`e@{PM+=k{n+#wQ#D`HW|<>jZ91?~lne zPG#NeiFkN0{@40*QeW@8-NN|$#LP2&-_xysq14y=8JY4A$UK)b^|7-obq`uxSm5MY+!kyOF?;_%Jk^xoG`g0G( z11`NkpBi_rEdJ?p;lFamf319YRqxkGT^+ynqxV0;@4s~F?>e0;==~O{PvfU?>i7j5 zydHlLPPM(;q`uy7kO6D|T3_dXz0}_?4KB$KdO!1l`~%hhJ^Y`o|2Dv=3vEBxjR(4R zn|}kMZ}-Zs|4sPOt-pIWm)850vYy(;De{Nj--Bnj{w+`B0(##q<@KiZ^!`Eo;MTuG z>g&BTp#M)~>W@E#d(!*#)!H-PwO@sP8h^O`H{Q#?=>23ZDEBP>?v(nv{sB#hF1g=9 zgyUShoxkbNFW`UbU+drTae@Yc-lsD3pY8vvDC^e$$zPi4f!@Ea9}Z=(r5||=zMZLm z*AMv@z2Ba}f42W0qd0xLRg2wv5{)JZZvDBr;R~bbOX*kdC!qMlQAF$CCiQQV`dUs~ z(PzCs9QCP3t*_r*y+i6NpK1Nw`iI;fgUZA^TK_KT|1KTBEQ~Ir_N()HAL_dO-*YlO z1;IVPFt=crE-XJ<{A)W;LUFf#a0=IFXb|j{dV14(`g|6O6HLdySL*LJtp>q0+MHC_ zs}G#k?N?!^;tyZ_>07wuo=k/dev/null || \ + (echo "configuration failed, please install autoconf first" && exit 1) +autoreconf --install --force --warnings=all + +cd univalue && ./autogen.sh + diff --git a/libraries/chain/include/rlpvalue/configure.ac b/libraries/chain/include/rlpvalue/configure.ac new file mode 100644 index 00000000..24737780 --- /dev/null +++ b/libraries/chain/include/rlpvalue/configure.ac @@ -0,0 +1,78 @@ +m4_define([librlpvalue_major_version], [1]) +m4_define([librlpvalue_minor_version], [1]) +m4_define([librlpvalue_micro_version], [4]) +m4_define([librlpvalue_interface_age], [4]) +# If you need a modifier for the version number. +# Normally empty, but can be used to make "fixup" releases. +m4_define([librlpvalue_extraversion], []) + +dnl libtool versioning from librlpvalue +m4_define([librlpvalue_current], [m4_eval(100 * librlpvalue_minor_version + librlpvalue_micro_version - librlpvalue_interface_age)]) +m4_define([librlpvalue_binary_age], [m4_eval(100 * librlpvalue_minor_version + librlpvalue_micro_version)]) +m4_define([librlpvalue_revision], [librlpvalue_interface_age]) +m4_define([librlpvalue_age], [m4_eval(librlpvalue_binary_age - librlpvalue_interface_age)]) +m4_define([librlpvalue_version], [librlpvalue_major_version().librlpvalue_minor_version().librlpvalue_micro_version()librlpvalue_extraversion()]) + + +AC_INIT([rlpvalue], [0.0.1], + [http://github.com/jgarzik/rlpvalue/]) + +dnl make the compilation flags quiet unless V=1 is used +m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) + +AC_PREREQ(2.60) +AC_CONFIG_SRCDIR([lib/rlpvalue.cpp]) +AC_CONFIG_AUX_DIR([build-aux]) +AC_CONFIG_MACRO_DIR([build-aux/m4]) +AC_CONFIG_HEADERS([rlpvalue-config.h]) +AX_SUBDIRS_CONFIGURE([univalue], [--disable-shared]) +AM_INIT_AUTOMAKE([subdir-objects foreign]) + +dnl Require C++11 compiler (no GNU extensions) +AC_PROG_CXX +AX_CXX_COMPILE_STDCXX([11], [noext], [mandatory], [nodefault]) +AC_LANG(C++) + +LIBRLPVALUE_MAJOR_VERSION=librlpvalue_major_version +LIBRLPVALUE_MINOR_VERSION=librlpvalue_minor_version +LIBRLPVALUE_MICRO_VERSION=librlpvalue_micro_version +LIBRLPVALUE_INTERFACE_AGE=librlpvalue_interface_age + +# ABI version +# http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html +LIBRLPVALUE_CURRENT=librlpvalue_current +LIBRLPVALUE_REVISION=librlpvalue_revision +LIBRLPVALUE_AGE=librlpvalue_age + +AC_CHECK_LIB(argp, argp_parse, ARGP_LIBS=-largp) +AC_SUBST(ARGP_LIBS) + +AC_SUBST(LIBRLPVALUE_CURRENT) +AC_SUBST(LIBRLPVALUE_REVISION) +AC_SUBST(LIBRLPVALUE_AGE) + +LT_INIT +LT_LANG([C++]) + +case $host in + *mingw*) + LIBTOOL_APP_LDFLAGS="$LIBTOOL_APP_LDFLAGS -all-static" + ;; +esac + +BUILD_EXEEXT= +case $build in + *mingw*) + BUILD_EXEEXT=".exe" + ;; +esac + +AC_CONFIG_FILES([ + Makefile + pc/librlpvalue.pc + pc/librlpvalue-uninstalled.pc]) + +AC_SUBST(LIBTOOL_APP_LDFLAGS) +AC_SUBST(BUILD_EXEEXT) +AC_OUTPUT + diff --git a/libraries/chain/include/rlpvalue/gen/gen.cpp b/libraries/chain/include/rlpvalue/gen/gen.cpp new file mode 100644 index 00000000..be3d4ccf --- /dev/null +++ b/libraries/chain/include/rlpvalue/gen/gen.cpp @@ -0,0 +1,82 @@ +// Copyright 2014 BitPay Inc. +// Distributed under the MIT software license, see the accompanying +// file COPYING or https://opensource.org/licenses/mit-license.php. + +// +// To re-create univalue_escapes.h: +// $ g++ -o gen gen.cpp +// $ ./gen > univalue_escapes.h +// + +#include +#include +#include "univalue.h" + +static bool initEscapes; +static std::string escapes[256]; + +static void initJsonEscape() +{ + // Escape all lower control characters (some get overridden with smaller sequences below) + for (int ch=0x00; ch<0x20; ++ch) { + char tmpbuf[20]; + snprintf(tmpbuf, sizeof(tmpbuf), "\\u%04x", ch); + escapes[ch] = std::string(tmpbuf); + } + + escapes[(int)'"'] = "\\\""; + escapes[(int)'\\'] = "\\\\"; + escapes[(int)'\b'] = "\\b"; + escapes[(int)'\f'] = "\\f"; + escapes[(int)'\n'] = "\\n"; + escapes[(int)'\r'] = "\\r"; + escapes[(int)'\t'] = "\\t"; + escapes[(int)'\x7f'] = "\\u007f"; // U+007F DELETE + + initEscapes = true; +} + +static void outputEscape() +{ + printf( "// Automatically generated file. Do not modify.\n" + "#ifndef BITCOIN_UNIVALUE_UNIVALUE_ESCAPES_H\n" + "#define BITCOIN_UNIVALUE_UNIVALUE_ESCAPES_H\n" + "static const char *escapes[256] = {\n"); + + for (unsigned int i = 0; i < 256; i++) { + if (escapes[i].empty()) { + printf("\tNULL,\n"); + } else { + printf("\t\""); + + unsigned int si; + for (si = 0; si < escapes[i].size(); si++) { + char ch = escapes[i][si]; + switch (ch) { + case '"': + printf("\\\""); + break; + case '\\': + printf("\\\\"); + break; + default: + printf("%c", escapes[i][si]); + break; + } + } + + printf("\",\n"); + } + } + + printf( "};\n" + "#endif // BITCOIN_UNIVALUE_UNIVALUE_ESCAPES_H\n"); +} + +int main (int argc, char *argv[]) +{ + initJsonEscape(); + outputEscape(); + return 0; +} + diff --git a/libraries/chain/include/rlpvalue/include/rlpvalue.h b/libraries/chain/include/rlpvalue/include/rlpvalue.h new file mode 100644 index 00000000..afebcd7d --- /dev/null +++ b/libraries/chain/include/rlpvalue/include/rlpvalue.h @@ -0,0 +1,126 @@ +// Copyright 2014 BitPay Inc. +// Copyright 2015 Bitcoin Core Developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or https://opensource.org/licenses/mit-license.php. + +#ifndef __RLPVALUE_H__ +#define __RLPVALUE_H__ + +#include +#include + +#include +#include +#include +#include + +#include // std::pair + +enum RLP_constants { + RLP_maxUintLen = 8, + RLP_bufferLenStart = 0x80, + RLP_listStart = 0xc0, +}; + +// really, a generic buffer, but we are in the global namespace, hence a prefix +class RLPBuffer { +public: + std::vector data; + + RLPBuffer() {} + RLPBuffer(const RLPBuffer& other) : data(other.data) {} + + void clear() { data.clear(); } + void reserve(size_t n) { data.reserve(n); } + void push_back(unsigned char ch) { data.push_back(ch); } + + std::vector::iterator begin() { return data.begin(); } + std::vector::iterator end() { return data.end(); } + + const unsigned char *get() const { return &data[0]; } + size_t size() const { return data.size(); } + std::string toStr() const { + std::string rs((const char *) &data[0], data.size()); + return rs; + } +}; + +// a single RLP value... which could be a nested list of RLP values +class RLPValue { +public: + enum VType { VARR, VBUF, }; + + RLPValue() { typ = VBUF; } + RLPValue(RLPValue::VType initialType) { + typ = initialType; + } + RLPValue(const std::string& val_) { + assign(val_); + } + RLPValue(const char *val_) { + std::string s(val_); + assign(s); + } + ~RLPValue() {} + + void clear(); + + void assign(const std::vector& val); + void assign(const std::string& val); + + bool setArray(); + + enum VType getType() const { return typ; } + std::string getValStr() const { return val.toStr(); } + bool empty() const { return (values.size() == 0); } + + size_t size() const { return values.size(); } + + const RLPValue& operator[](size_t index) const; + + bool isBuffer() const { return (typ == VBUF); } + bool isArray() const { return (typ == VARR); } + + bool push_back(const RLPValue& val); + bool push_back(const std::string& val_) { + RLPValue tmpVal; + tmpVal.assign(val_); + return push_back(tmpVal); + } + bool push_back(const char *val_) { + std::string s(val_); + return push_back(s); + } + bool push_backV(const std::vector& vec); + + std::string write() const; + + bool read(const unsigned char *raw, size_t len, + size_t& consumed, size_t& wanted); + +private: + bool readArray(const unsigned char *raw, size_t len, + size_t uintlen, size_t payloadlen, + size_t& consumed, size_t& wanted); + RLPValue::VType typ; + RLPBuffer val; + std::vector values; + + void writeBuffer(std::string& s) const; + void writeArray(std::string& s) const; + +public: + // Strict type-specific getters, these throw std::runtime_error if the + // value is of unexpected type + const std::vector& getValues() const; + std::string get_str() const; + const RLPValue& get_array() const; + + enum VType type() const { return getType(); } +}; + +extern const char *uvTypeName(RLPValue::VType t); + +extern const RLPValue NullRLPValue; + +#endif // __RLPVALUE_H__ diff --git a/libraries/chain/include/rlpvalue/lib/.gitignore b/libraries/chain/include/rlpvalue/lib/.gitignore new file mode 100644 index 00000000..ee7fc285 --- /dev/null +++ b/libraries/chain/include/rlpvalue/lib/.gitignore @@ -0,0 +1,2 @@ +gen +.libs diff --git a/libraries/chain/include/rlpvalue/lib/rlpvalue.cpp b/libraries/chain/include/rlpvalue/lib/rlpvalue.cpp new file mode 100644 index 00000000..6872f0e2 --- /dev/null +++ b/libraries/chain/include/rlpvalue/lib/rlpvalue.cpp @@ -0,0 +1,84 @@ +// Copyright 2014 BitPay Inc. +// Copyright 2015 Bitcoin Core Developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or https://opensource.org/licenses/mit-license.php. + +#include +#include +#include +#include + +#include "../include/rlpvalue.h" + +const RLPValue NullRLPValue; + +void RLPValue::clear() +{ + typ = VBUF; + val.clear(); + values.clear(); +} + +void RLPValue::assign(const std::string& s) +{ + clear(); + + val.reserve(s.size()); + + for (auto it = s.begin(); it != s.end(); it++) { + val.push_back((unsigned char) *it); + } +} + +void RLPValue::assign(const std::vector& buf) +{ + val.data.assign(buf.begin(), buf.end()); +} + +bool RLPValue::setArray() +{ + clear(); + typ = VARR; + return true; +} + +bool RLPValue::push_back(const RLPValue& val_) +{ + if (typ != VARR) + return false; + + values.push_back(val_); + return true; +} + +bool RLPValue::push_backV(const std::vector& vec) +{ + if (typ != VARR) + return false; + + values.insert(values.end(), vec.begin(), vec.end()); + + return true; +} + +const RLPValue& RLPValue::operator[](size_t index) const +{ + if (typ != VARR) + return NullRLPValue; + if (index >= values.size()) + return NullRLPValue; + + return values.at(index); +} + +const char *uvTypeName(RLPValue::VType t) +{ + switch (t) { + case RLPValue::VARR: return "array"; + case RLPValue::VBUF: return "buffer"; + } + + // not reached + return NULL; +} + diff --git a/libraries/chain/include/rlpvalue/lib/rlpvalue_get.cpp b/libraries/chain/include/rlpvalue/lib/rlpvalue_get.cpp new file mode 100644 index 00000000..82fb663b --- /dev/null +++ b/libraries/chain/include/rlpvalue/lib/rlpvalue_get.cpp @@ -0,0 +1,38 @@ +// Copyright 2014 BitPay Inc. +// Copyright 2015 Bitcoin Core Developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or https://opensource.org/licenses/mit-license.php. + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../include/rlpvalue.h" + +const std::vector& RLPValue::getValues() const +{ + if (typ != VARR) + throw std::runtime_error("JSON value is not an object or array as expected"); + return values; +} + +std::string RLPValue::get_str() const +{ + if (typ != VBUF) + throw std::runtime_error("JSON value is not a string as expected"); + return getValStr(); +} + +const RLPValue& RLPValue::get_array() const +{ + if (typ != VARR) + throw std::runtime_error("JSON value is not an array as expected"); + return *this; +} + diff --git a/libraries/chain/include/rlpvalue/lib/rlpvalue_read.cpp b/libraries/chain/include/rlpvalue/lib/rlpvalue_read.cpp new file mode 100644 index 00000000..5b317a28 --- /dev/null +++ b/libraries/chain/include/rlpvalue/lib/rlpvalue_read.cpp @@ -0,0 +1,216 @@ +// Copyright 2014 BitPay Inc. +// Copyright 2019 Bloq Inc. +// Distributed under the MIT software license, see the accompanying +// file COPYING or https://opensource.org/licenses/mit-license.php. + +#include +#include +#include "../include/rlpvalue.h" + +uint64_t toInteger(const unsigned char *raw, size_t len) +{ + if (len == 0) + return 0; + else if (len == 1) + return *raw; + else + return (raw[len - 1]) + (toInteger(raw, len - 1) * 256); +} + +bool RLPValue::readArray(const unsigned char *raw, size_t len, + size_t uintlen, size_t payloadlen, + size_t& consumed, size_t& wanted) +{ + const size_t prefixlen = 1; + + // validate list length, including possible addition overflows. + size_t expected = prefixlen + uintlen + payloadlen; + if ((expected > len) || (payloadlen > len)) { + wanted = expected > payloadlen ? expected : payloadlen; + return false; + } + + // we are type=array + if (!setArray()) + return false; + + size_t child_len = payloadlen; + size_t child_wanted = 0; + size_t total_consumed = 0; + + const unsigned char *list_ent = raw + prefixlen + uintlen; + + // recursively read until payloadlen bytes parsed, or error + while (child_len > 0) { + RLPValue childVal; + size_t child_consumed = 0; + + if (!childVal.read(list_ent, child_len, + child_consumed, child_wanted)) + return false; + + total_consumed += child_consumed; + list_ent += child_consumed; + child_len -= child_consumed; + + values.push_back(childVal); + } + + consumed = total_consumed; + return true; +} + +bool RLPValue::read(const unsigned char *raw, size_t len, + size_t& consumed, size_t& wanted) +{ + clear(); + consumed = 0; + wanted = 0; + + std::vector stack; + std::vector buf; + const unsigned char* end = raw + len; + + const size_t prefixlen = 1; + + unsigned char ch = *raw; + + if (len < 1) { + wanted = 1; + goto out_fail; + } + + // Case 1: [prefix is 1-byte data buffer] + if (ch <= 0x7f) { + const unsigned char *tok_start = raw; + const unsigned char *tok_end = tok_start + prefixlen; + assert(tok_end <= end); + + // parsing done; assign data buffer value. + buf.assign(tok_start, tok_end); + assign(buf); + + consumed = buf.size(); + + // Case 2: [prefix, including buffer length][data] + } else if ((ch >= 0x80) && (ch <= 0xb7)) { + size_t blen = ch - 0x80; + size_t expected = prefixlen + blen; + + if (len < expected) { + wanted = expected; + goto out_fail; + } + + const unsigned char *tok_start = raw + 1; + const unsigned char *tok_end = tok_start + blen; + assert(tok_end <= end); + + // require minimal encoding + if ((blen == 1) && (tok_start[0] <= 0x7f)) + goto out_fail; + + // parsing done; assign data buffer value. + buf.assign(tok_start, tok_end); + assign(buf); + + consumed = expected; + + // Case 3: [prefix][buffer length][data] + } else if ((ch >= 0xb8) && (ch <= 0xbf)) { + size_t uintlen = ch - 0xb7; + size_t expected = prefixlen + uintlen; + + if (len < expected) { + wanted = expected; + goto out_fail; + } + + assert(uintlen > 0 && uintlen <= RLP_maxUintLen); + + const unsigned char *tok_start = raw + prefixlen; + if ((uintlen > 1) && (tok_start[0] == 0)) // no leading zeroes + goto out_fail; + + // read buffer length + uint64_t slen = toInteger(tok_start, uintlen); + + // validate buffer length, including possible addition overflows. + expected = prefixlen + uintlen + slen; + if ((slen < (RLP_listStart - RLP_bufferLenStart - RLP_maxUintLen)) || + (expected > len) || (slen > len)) { + wanted = slen > expected ? slen : expected; + goto out_fail; + } + + // parsing done; assign data buffer value. + tok_start = raw + prefixlen + uintlen; + const unsigned char *tok_end = tok_start + slen; + buf.assign(tok_start, tok_end); + assign(buf); + + consumed = expected; + + // Case 4: [prefix][list] + } else if ((ch >= 0xc0) && (ch <= 0xf7)) { + size_t payloadlen = ch - 0xc0; + size_t expected = prefixlen + payloadlen; + size_t list_consumed = 0; + size_t list_wanted = 0; + + // read list payload + if (!readArray(raw, len, 0, payloadlen, list_consumed, list_wanted)) { + wanted = list_wanted; + goto out_fail; + } + + assert(list_consumed == payloadlen); + + consumed = expected; + + // Case 5: [prefix][list length][list] + } else { + assert((ch >= 0xf8) && (ch <= 0xff)); + + size_t uintlen = ch - 0xf7; + size_t expected = prefixlen + uintlen; + + if (len < expected) { + wanted = expected; + goto out_fail; + } + + assert(uintlen > 0 && uintlen <= RLP_maxUintLen); + + const unsigned char *tok_start = raw + prefixlen; + if ((uintlen > 1) && (tok_start[0] == 0)) // no leading zeroes + goto out_fail; + + // read list length + size_t payloadlen = toInteger(tok_start, uintlen); + + // special requirement for non-immediate length + if (payloadlen < (0x100 - RLP_listStart - RLP_maxUintLen)) + goto out_fail; + + size_t list_consumed = 0; + size_t list_wanted = 0; + + // read list payload + if (!readArray(raw, len, uintlen, payloadlen, list_consumed, list_wanted)) { + wanted = list_wanted; + goto out_fail; + } + + assert(list_consumed == payloadlen); + + consumed = prefixlen + uintlen + payloadlen; + } + + return true; + +out_fail: + clear(); + return false; +} + diff --git a/libraries/chain/include/rlpvalue/lib/rlpvalue_utffilter.h b/libraries/chain/include/rlpvalue/lib/rlpvalue_utffilter.h new file mode 100644 index 00000000..da1bde02 --- /dev/null +++ b/libraries/chain/include/rlpvalue/lib/rlpvalue_utffilter.h @@ -0,0 +1,119 @@ +// Copyright 2016 Wladimir J. van der Laan +// Distributed under the MIT software license, see the accompanying +// file COPYING or https://opensource.org/licenses/mit-license.php. +#ifndef RLPVALUE_UTFFILTER_H +#define RLPVALUE_UTFFILTER_H + +#include + +/** + * Filter that generates and validates UTF-8, as well as collates UTF-16 + * surrogate pairs as specified in RFC4627. + */ +class JSONUTF8StringFilter +{ +public: + explicit JSONUTF8StringFilter(std::string &s): + str(s), is_valid(true), codepoint(0), state(0), surpair(0) + { + } + // Write single 8-bit char (may be part of UTF-8 sequence) + void push_back(unsigned char ch) + { + if (state == 0) { + if (ch < 0x80) // 7-bit ASCII, fast direct pass-through + str.push_back(ch); + else if (ch < 0xc0) // Mid-sequence character, invalid in this state + is_valid = false; + else if (ch < 0xe0) { // Start of 2-byte sequence + codepoint = (ch & 0x1f) << 6; + state = 6; + } else if (ch < 0xf0) { // Start of 3-byte sequence + codepoint = (ch & 0x0f) << 12; + state = 12; + } else if (ch < 0xf8) { // Start of 4-byte sequence + codepoint = (ch & 0x07) << 18; + state = 18; + } else // Reserved, invalid + is_valid = false; + } else { + if ((ch & 0xc0) != 0x80) // Not a continuation, invalid + is_valid = false; + state -= 6; + codepoint |= (ch & 0x3f) << state; + if (state == 0) + push_back_u(codepoint); + } + } + // Write codepoint directly, possibly collating surrogate pairs + void push_back_u(unsigned int codepoint_) + { + if (state) // Only accept full codepoints in open state + is_valid = false; + if (codepoint_ >= 0xD800 && codepoint_ < 0xDC00) { // First half of surrogate pair + if (surpair) // Two subsequent surrogate pair openers - fail + is_valid = false; + else + surpair = codepoint_; + } else if (codepoint_ >= 0xDC00 && codepoint_ < 0xE000) { // Second half of surrogate pair + if (surpair) { // Open surrogate pair, expect second half + // Compute code point from UTF-16 surrogate pair + append_codepoint(0x10000 | ((surpair - 0xD800)<<10) | (codepoint_ - 0xDC00)); + surpair = 0; + } else // Second half doesn't follow a first half - fail + is_valid = false; + } else { + if (surpair) // First half of surrogate pair not followed by second - fail + is_valid = false; + else + append_codepoint(codepoint_); + } + } + // Check that we're in a state where the string can be ended + // No open sequences, no open surrogate pairs, etc + bool finalize() + { + if (state || surpair) + is_valid = false; + return is_valid; + } +private: + std::string &str; + bool is_valid; + // Current UTF-8 decoding state + unsigned int codepoint; + int state; // Top bit to be filled in for next UTF-8 byte, or 0 + + // Keep track of the following state to handle the following section of + // RFC4627: + // + // To escape an extended character that is not in the Basic Multilingual + // Plane, the character is represented as a twelve-character sequence, + // encoding the UTF-16 surrogate pair. So, for example, a string + // containing only the G clef character (U+1D11E) may be represented as + // "\uD834\uDD1E". + // + // Two subsequent \u.... may have to be replaced with one actual codepoint. + unsigned int surpair; // First half of open UTF-16 surrogate pair, or 0 + + void append_codepoint(unsigned int codepoint_) + { + if (codepoint_ <= 0x7f) + str.push_back((char)codepoint_); + else if (codepoint_ <= 0x7FF) { + str.push_back((char)(0xC0 | (codepoint_ >> 6))); + str.push_back((char)(0x80 | (codepoint_ & 0x3F))); + } else if (codepoint_ <= 0xFFFF) { + str.push_back((char)(0xE0 | (codepoint_ >> 12))); + str.push_back((char)(0x80 | ((codepoint_ >> 6) & 0x3F))); + str.push_back((char)(0x80 | (codepoint_ & 0x3F))); + } else if (codepoint_ <= 0x1FFFFF) { + str.push_back((char)(0xF0 | (codepoint_ >> 18))); + str.push_back((char)(0x80 | ((codepoint_ >> 12) & 0x3F))); + str.push_back((char)(0x80 | ((codepoint_ >> 6) & 0x3F))); + str.push_back((char)(0x80 | (codepoint_ & 0x3F))); + } + } +}; + +#endif diff --git a/libraries/chain/include/rlpvalue/lib/rlpvalue_write.cpp b/libraries/chain/include/rlpvalue/lib/rlpvalue_write.cpp new file mode 100644 index 00000000..53449ecd --- /dev/null +++ b/libraries/chain/include/rlpvalue/lib/rlpvalue_write.cpp @@ -0,0 +1,83 @@ +// Copyright 2014 BitPay Inc. +// Distributed under the MIT software license, see the accompanying +// file COPYING or https://opensource.org/licenses/mit-license.php. + +#include +#include +#include "../include/rlpvalue.h" + +std::string RLPValue::write() const +{ + std::string s; + + switch (typ) { + case VARR: + writeArray(s); + break; + case VBUF: + writeBuffer(s); + break; + } + + return s; +} + +std::string encodeBinary(uint64_t n) +{ + std::string rs; + + if (n == 0) { + // do nothing; return empty string + } else { + rs.assign(encodeBinary(n / 256)); + + unsigned char ch = n % 256; + rs.append((const char *) &ch, 1); + } + + return rs; +} + +static std::string encodeLength(size_t n, unsigned char offset) +{ + std::string rs; + + if (n < 56) { + unsigned char ch = n + offset; + rs.assign((const char *) &ch, 1); + } + + else { + // assert(n too big); + std::string binlen = encodeBinary(n); + + unsigned char ch = binlen.size() + offset + 55; + rs.assign((const char *) &ch, 1); + rs.append(binlen); + } + + return rs; +} + +void RLPValue::writeBuffer(std::string& s) const +{ + const unsigned char *p = val.size() ? val.get() : nullptr; + size_t sz = val.size(); + + if ((sz == 1) && (p[0] < 0x80)) + s.append((const char *) p, 1); + else + s += encodeLength(sz, 0x80) + val.toStr(); +} + +void RLPValue::writeArray(std::string& s) const +{ + std::string tmp; + for (auto it = values.begin(); it != values.end(); it++) { + const RLPValue& val = *it; + tmp += val.write(); + } + + s += encodeLength(tmp.size(), 0xC0) + tmp; +} + diff --git a/libraries/chain/include/rlpvalue/main.cpp b/libraries/chain/include/rlpvalue/main.cpp new file mode 100644 index 00000000..11427efb --- /dev/null +++ b/libraries/chain/include/rlpvalue/main.cpp @@ -0,0 +1,48 @@ +#include "include/rlpvalue.h" +#include "lib/rlpvalue.cpp" +#include "lib/rlpvalue_get.cpp" +#include "lib/rlpvalue_write.cpp" +#include "test/utilstrencodings.cpp" +#include + +int main() { + std::string dogIns = "dog"; + std::string dogOuts = "83646f67"; + + // Parse input string + RLPValue dogV = RLPValue(dogIns); + + // Parse expected output, print corresponding input -- note that 0x has been stripped from hex output + std::vector outb = ParseHex(dogOuts); + std::string outbStr(outb.begin(), outb.end()); + + std::cout << "83646f67 to c_str:" << std::endl; + std::cout << outbStr << std::endl; + + // Generate output rlp-encoded hex + std::string dogGenOutput = dogV.write(); + std::string dogGenHex = HexStr( dogGenOutput.begin(), dogGenOutput.end() ); + + // Inspect type of RLP value -- buffer/array + std::cout << "\nRLPValue type: " << std::endl; + std::cout << uvTypeName( dogV.type() ) << "\n\n" << std::endl; + + + + std::string catIns = "cat"; + std::string catOuts = "83636174"; + + RLPValue catV = RLPValue(catIns); + + // Generate output rlp-encoded hex + std::string catGenOutput = catV.write(); + std::string catGenHex = HexStr( catGenOutput.begin(), catGenOutput.end() ); + + std::cout << "Cat to RLP:" << std::endl; + std::cout << catGenHex.c_str() << std::endl; + + std::cout << "\nRLPValue type: " << std::endl; + std::cout << uvTypeName( dogV.type() ) << std::endl; + + return 0; +} diff --git a/libraries/chain/include/rlpvalue/pc/librlpvalue-uninstalled.pc.in b/libraries/chain/include/rlpvalue/pc/librlpvalue-uninstalled.pc.in new file mode 100644 index 00000000..484bccfc --- /dev/null +++ b/libraries/chain/include/rlpvalue/pc/librlpvalue-uninstalled.pc.in @@ -0,0 +1,9 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: librlpvalue +Description: librlpvalue, C++ universal value object and JSON library +Version: @VERSION@ +Libs: ${pc_top_builddir}/${pcfiledir}/librlpvalue.la diff --git a/libraries/chain/include/rlpvalue/pc/librlpvalue.pc.in b/libraries/chain/include/rlpvalue/pc/librlpvalue.pc.in new file mode 100644 index 00000000..faf5e647 --- /dev/null +++ b/libraries/chain/include/rlpvalue/pc/librlpvalue.pc.in @@ -0,0 +1,10 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: librlpvalue +Description: librlpvalue, C++ universal value object and JSON library +Version: @VERSION@ +Libs: -L${libdir} -lrlpvalue +Cflags: -I${includedir} diff --git a/libraries/chain/include/rlpvalue/src/.gitignore b/libraries/chain/include/rlpvalue/src/.gitignore new file mode 100644 index 00000000..771e1508 --- /dev/null +++ b/libraries/chain/include/rlpvalue/src/.gitignore @@ -0,0 +1,3 @@ + +rlp + diff --git a/libraries/chain/include/rlpvalue/src/InfInt.h b/libraries/chain/include/rlpvalue/src/InfInt.h new file mode 100644 index 00000000..14ff2158 --- /dev/null +++ b/libraries/chain/include/rlpvalue/src/InfInt.h @@ -0,0 +1,1371 @@ +/* + * InfInt - Arbitrary-Precision Integer Arithmetic Library + * Copyright (C) 2013 Sercan Tutar + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * + * USAGE: + * It is pretty straight forward to use the library. Just create an instance of + * InfInt class and start using it. + * + * Useful methods: + * intSqrt: integer square root operation + * digitAt: returns digit at index + * numberOfDigits: returns number of digits + * size: returns size in bytes + * toString: converts it to a string + * + * There are also conversion methods which allow conversion to primitive types: + * toInt, toLong, toLongLong, toUnsignedInt, toUnsignedLong, toUnsignedLongLong. + * + * You may define INFINT_USE_EXCEPTIONS and library methods will start raising + * InfIntException in case of error instead of writing error messages using + * std::cerr. + * + * See ReadMe.txt for more info. + * + * + * No overflows, happy programmers! + * + */ + +#ifndef INFINT_H_ +#define INFINT_H_ + +#include +#include +#include +#include +#include + +//#include +//#include + +#ifndef LONG_LONG_MIN +#define LONG_LONG_MIN std::numeric_limits::min() +#define LONG_LONG_MAX std::numeric_limits::max() +#define ULONG_LONG_MAX std::numeric_limits::max() +#endif + +#ifdef INFINT_USE_EXCEPTIONS +#include +#endif + +typedef int ELEM_TYPE; +typedef long long PRODUCT_TYPE; +static const ELEM_TYPE BASE = 1000000000; +static const ELEM_TYPE UPPER_BOUND = 999999999; +static const ELEM_TYPE DIGIT_COUNT = 9; +static const int powersOfTen[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000 }; + +#ifdef INFINT_USE_EXCEPTIONS +class InfIntException: public std::exception +{ +public: + InfIntException(const std::string& txt) throw (); + ~InfIntException() throw (); + const char* what() const throw (); +private: + std::string txt; +}; + +inline InfIntException::InfIntException(const std::string& txt) throw () : +std::exception(), txt(txt) +{ +} + +inline InfIntException::~InfIntException() throw () +{ +} + +inline const char* InfIntException::what() const throw () +{ + return txt.c_str(); +} +#endif + +inline static div_t my_div(int num, int denom) +{ + div_t result; + result.quot = num / denom; + result.rem = num - denom * result.quot; + return result; +} + +inline static ldiv_t my_ldiv(long num, long denom) +{ + ldiv_t result; + result.quot = num / denom; + result.rem = num - denom * result.quot; + return result; +} + +inline static lldiv_t my_lldiv(long long num, long long denom) +{ + lldiv_t result; + result.quot = num / denom; + result.rem = num - denom * result.quot; + return result; +} + +class InfInt +{ + friend std::ostream& operator<<(std::ostream &s, const InfInt &n); + friend std::istream& operator>>(std::istream &s, InfInt &val); + +public: + /* constructors */ + InfInt(); + InfInt(const char* c); + InfInt(const std::string& s); + InfInt(int l); + InfInt(long l); + InfInt(long long l); + InfInt(unsigned int l); + InfInt(unsigned long l); + InfInt(unsigned long long l); + InfInt(const InfInt& l); + + /* assignment operators */ + const InfInt& operator=(const char* c); + const InfInt& operator=(const std::string& s); + const InfInt& operator=(int l); + const InfInt& operator=(long l); + const InfInt& operator=(long long l); + const InfInt& operator=(unsigned int l); + const InfInt& operator=(unsigned long l); + const InfInt& operator=(unsigned long long l); + const InfInt& operator=(const InfInt& l); + + /* unary increment/decrement operators */ + const InfInt& operator++(); + const InfInt& operator--(); + InfInt operator++(int); + InfInt operator--(int); + + /* operational assignments */ + const InfInt& operator+=(const InfInt& rhs); + const InfInt& operator-=(const InfInt& rhs); + const InfInt& operator*=(const InfInt& rhs); + const InfInt& operator/=(const InfInt& rhs); // throw + const InfInt& operator%=(const InfInt& rhs); // throw + const InfInt& operator*=(ELEM_TYPE rhs); + + /* operations */ + InfInt operator-() const; + InfInt operator+(const InfInt& rhs) const; + InfInt operator-(const InfInt& rhs) const; + InfInt operator*(const InfInt& rhs) const; + InfInt operator/(const InfInt& rhs) const; // throw + InfInt operator%(const InfInt& rhs) const; // throw + InfInt operator*(ELEM_TYPE rhs) const; + + /* relational operations */ + bool operator==(const InfInt& rhs) const; + bool operator!=(const InfInt& rhs) const; + bool operator<(const InfInt& rhs) const; + bool operator<=(const InfInt& rhs) const; + bool operator>(const InfInt& rhs) const; + bool operator>=(const InfInt& rhs) const; + + /* integer square root */ + InfInt intSqrt() const; // throw + + /* digit operations */ + char digitAt(size_t i) const; // throw + size_t numberOfDigits() const; + + /* size in bytes */ + size_t size() const; + + /* string conversion */ + std::string toString() const; + + /* conversion to primitive types */ + int toInt() const; // throw + long toLong() const; // throw + long long toLongLong() const; // throw + unsigned int toUnsignedInt() const; // throw + unsigned long toUnsignedLong() const; // throw + unsigned long long toUnsignedLongLong() const; // throw + +private: + static ELEM_TYPE dInR(const InfInt& R, const InfInt& D); + static void multiplyByDigit(ELEM_TYPE factor, std::vector& val); + + void correct(bool justCheckLeadingZeros = false, bool hasValidSign = false); + void fromString(const std::string& s); + void optimizeSqrtSearchBounds(InfInt& lo, InfInt& hi) const; + void truncateToBase(); + bool equalizeSigns(); + void removeLeadingZeros(); + + std::vector val; // number with base FACTOR + bool pos; // true if number is positive +}; + +inline InfInt::InfInt() : pos(true) +{ + //PROFINY_SCOPE + val.push_back((ELEM_TYPE) 0); +} + +inline InfInt::InfInt(const char* c) +{ + //PROFINY_SCOPE + fromString(c); +} + +inline InfInt::InfInt(const std::string& s) +{ + //PROFINY_SCOPE + fromString(s); +} + +inline InfInt::InfInt(int l) : pos(l >= 0) +{ + //PROFINY_SCOPE + bool subtractOne = false; + if (l == INT_MIN) + { + subtractOne = true; + ++l; + } + + if (!pos) + { + l = -l; + } + do + { + div_t dt = my_div(l, BASE); + val.push_back((ELEM_TYPE) dt.rem); + l = dt.quot; + } while (l > 0); + + if (subtractOne) + { + --*this; + } +} + +inline InfInt::InfInt(long l) : pos(l >= 0) +{ + //PROFINY_SCOPE + bool subtractOne = false; + if (l == LONG_MIN) + { + subtractOne = true; + ++l; + } + + if (!pos) + { + l = -l; + } + do + { + ldiv_t dt = my_ldiv(l, BASE); + val.push_back((ELEM_TYPE) dt.rem); + l = dt.quot; + } while (l > 0); + + if (subtractOne) + { + --*this; + } +} + +inline InfInt::InfInt(long long l) : pos(l >= 0) +{ + //PROFINY_SCOPE + bool subtractOne = false; + if (l == LONG_LONG_MIN) + { + subtractOne = true; + ++l; + } + + if (!pos) + { + l = -l; + } + do + { + lldiv_t dt = my_lldiv(l, BASE); + val.push_back((ELEM_TYPE) dt.rem); + l = dt.quot; + } while (l > 0); + + if (subtractOne) + { + --*this; + } +} + +inline InfInt::InfInt(unsigned int l) : pos(true) +{ + //PROFINY_SCOPE + do + { + val.push_back((ELEM_TYPE) (l % BASE)); + l = l / BASE; + } while (l > 0); +} + +inline InfInt::InfInt(unsigned long l) : pos(true) +{ + //PROFINY_SCOPE + do + { + val.push_back((ELEM_TYPE) (l % BASE)); + l = l / BASE; + } while (l > 0); +} + +inline InfInt::InfInt(unsigned long long l) : pos(true) +{ + //PROFINY_SCOPE + do + { + val.push_back((ELEM_TYPE) (l % BASE)); + l = l / BASE; + } while (l > 0); +} + +inline InfInt::InfInt(const InfInt& l) : val(l.val), pos(l.pos) +{ + //PROFINY_SCOPE +} + +inline const InfInt& InfInt::operator=(const char* c) +{ + //PROFINY_SCOPE + fromString(c); + return *this; +} + +inline const InfInt& InfInt::operator=(const std::string& s) +{ + //PROFINY_SCOPE + fromString(s); + return *this; +} + +inline const InfInt& InfInt::operator=(int l) +{ + //PROFINY_SCOPE + bool subtractOne = false; + if (l == INT_MIN) + { + subtractOne = true; + ++l; + } + + pos = l >= 0; + val.clear(); + if (!pos) + { + l = -l; + } + do + { + div_t dt = my_div(l, BASE); + val.push_back((ELEM_TYPE) dt.rem); + l = dt.quot; + } while (l > 0); + + return subtractOne ? --*this : *this; +} + +inline const InfInt& InfInt::operator=(long l) +{ + //PROFINY_SCOPE + bool subtractOne = false; + if (l == LONG_MIN) + { + subtractOne = true; + ++l; + } + + pos = l >= 0; + val.clear(); + if (!pos) + { + l = -l; + } + do + { + ldiv_t dt = my_ldiv(l, BASE); + val.push_back((ELEM_TYPE) dt.rem); + l = dt.quot; + } while (l > 0); + + return subtractOne ? --*this : *this; +} + +inline const InfInt& InfInt::operator=(long long l) +{ + //PROFINY_SCOPE + bool subtractOne = false; + if (l == LONG_LONG_MIN) + { + subtractOne = true; + ++l; + } + + pos = l >= 0; + val.clear(); + if (!pos) + { + l = -l; + } + do + { + lldiv_t dt = my_lldiv(l, BASE); + val.push_back((ELEM_TYPE) dt.rem); + l = dt.quot; + } while (l > 0); + + return subtractOne ? --*this : *this; +} + +inline const InfInt& InfInt::operator=(unsigned int l) +{ + //PROFINY_SCOPE + pos = true; + val.clear(); + do + { + val.push_back((ELEM_TYPE) (l % BASE)); + l = l / BASE; + } while (l > 0); + return *this; +} + +inline const InfInt& InfInt::operator=(unsigned long l) +{ + //PROFINY_SCOPE + pos = true; + val.clear(); + do + { + val.push_back((ELEM_TYPE) (l % BASE)); + l = l / BASE; + } while (l > 0); + return *this; +} + +inline const InfInt& InfInt::operator=(unsigned long long l) +{ + //PROFINY_SCOPE + pos = true; + val.clear(); + do + { + val.push_back((ELEM_TYPE) (l % BASE)); + l = l / BASE; + } while (l > 0); + return *this; +} + +inline const InfInt& InfInt::operator=(const InfInt& l) +{ + //PROFINY_SCOPE + pos = l.pos; + val = l.val; + return *this; +} + +inline const InfInt& InfInt::operator++() +{ + //PROFINY_SCOPE + val[0] += (pos ? 1 : -1); + this->correct(false, true); + return *this; +} + +inline const InfInt& InfInt::operator--() +{ + //PROFINY_SCOPE + val[0] -= (pos ? 1 : -1); + this->correct(false, true); + return *this; +} + +inline InfInt InfInt::operator++(int) +{ + //PROFINY_SCOPE + InfInt result = *this; + val[0] += (pos ? 1 : -1); + this->correct(false, true); + return result; +} + +inline InfInt InfInt::operator--(int) +{ + //PROFINY_SCOPE + InfInt result = *this; + val[0] -= (pos ? 1 : -1); + this->correct(false, true); + return result; +} + +inline const InfInt& InfInt::operator+=(const InfInt& rhs) +{ + //PROFINY_SCOPE + if (rhs.val.size() > val.size()) + { + val.resize(rhs.val.size(), 0); + } + for (size_t i = 0; i < val.size(); ++i) + { + val[i] = (pos ? val[i] : -val[i]) + (i < rhs.val.size() ? (rhs.pos ? rhs.val[i] : -rhs.val[i]) : 0); + } + correct(); + return *this; +} + +inline const InfInt& InfInt::operator-=(const InfInt& rhs) +{ + //PROFINY_SCOPE + if (rhs.val.size() > val.size()) + { + val.resize(rhs.val.size(), 0); + } + for (size_t i = 0; i < val.size(); ++i) + { + val[i] = (pos ? val[i] : -val[i]) - (i < rhs.val.size() ? (rhs.pos ? rhs.val[i] : -rhs.val[i]) : 0); + } + correct(); + return *this; +} + +inline const InfInt& InfInt::operator*=(const InfInt& rhs) +{ + //PROFINY_SCOPE + // TODO: optimize (do not use operator*) + *this = *this * rhs; + return *this; +} + +inline const InfInt& InfInt::operator/=(const InfInt& rhs) +{ + //PROFINY_SCOPE + if (rhs == 0) + { +#ifdef INFINT_USE_EXCEPTIONS + throw InfIntException("division by zero"); +#else + std::cerr << "Division by zero!" << std::endl; + return *this; +#endif + } + InfInt R, D = (rhs.pos ? rhs : -rhs), N = (pos ? *this : -*this); + bool oldpos = pos; + std::fill(val.begin(), val.end(), 0); + for (int i = (int) N.val.size() - 1; i >= 0; --i) + { + R.val.insert(R.val.begin(), N.val[i]); + R.correct(true); + ELEM_TYPE cnt = dInR(R, D); + R -= D * cnt; + val[i] += cnt; + } + correct(); + pos = (val.size() == 1 && val[0] == 0) ? true : (oldpos == rhs.pos); + return *this; +} + +inline const InfInt& InfInt::operator%=(const InfInt& rhs) +{ + //PROFINY_SCOPE + // TODO: optimize (do not use operator%) + *this = *this % rhs; + return *this; +// if (rhs == 0) +// { +//#ifdef INFINT_USE_EXCEPTIONS +// throw InfIntException("division by zero"); +//#else +// std::cerr << "Division by zero!" << std::endl; +// return *this; +//#endif +// } +// InfInt D = (rhs.pos ? rhs : -rhs), N = (pos ? *this : -*this); +// bool oldpos = pos; +// val.clear(); +// for (int i = (int) N.val.size() - 1; i >= 0; --i) +// { +// val.insert(val.begin(), N.val[i]); +// correct(true); +// *this -= D * dInR(*this, D); +// } +// correct(); +// pos = (val.size() == 1 && val[0] == 0) ? true : oldpos; +// return *this; +} + +inline const InfInt& InfInt::operator*=(ELEM_TYPE rhs) +{ + //PROFINY_SCOPE + ELEM_TYPE factor = rhs < 0 ? -rhs : rhs; + bool oldpos = pos; + multiplyByDigit(factor, val); + correct(); + pos = (val.size() == 1 && val[0] == 0) ? true : (oldpos == (rhs >= 0)); + return *this; +} + +inline InfInt InfInt::operator-() const +{ + //PROFINY_SCOPE + InfInt result = *this; + result.pos = !pos; + return result; +} + +inline InfInt InfInt::operator+(const InfInt& rhs) const +{ + //PROFINY_SCOPE + InfInt result; + result.val.resize(val.size() > rhs.val.size() ? val.size() : rhs.val.size(), 0); + for (size_t i = 0; i < val.size() || i < rhs.val.size(); ++i) + { + result.val[i] = (i < val.size() ? (pos ? val[i] : -val[i]) : 0) + (i < rhs.val.size() ? (rhs.pos ? rhs.val[i] : -rhs.val[i]) : 0); + } + result.correct(); + return result; +} + +inline InfInt InfInt::operator-(const InfInt& rhs) const +{ + //PROFINY_SCOPE + InfInt result; + result.val.resize(val.size() > rhs.val.size() ? val.size() : rhs.val.size(), 0); + for (size_t i = 0; i < val.size() || i < rhs.val.size(); ++i) + { + result.val[i] = (i < val.size() ? (pos ? val[i] : -val[i]) : 0) - (i < rhs.val.size() ? (rhs.pos ? rhs.val[i] : -rhs.val[i]) : 0); + } + result.correct(); + return result; +} + +inline InfInt InfInt::operator*(const InfInt& rhs) const +{ + //PROFINY_SCOPE + InfInt result; + result.val.resize(val.size() + rhs.val.size(), 0); + PRODUCT_TYPE carry = 0; + size_t digit = 0; + for (;; ++digit) + { + lldiv_t dt = my_lldiv(carry, BASE); + carry = dt.quot; + result.val[digit] = (ELEM_TYPE) dt.rem; + + bool found = false; + for (size_t i = digit < rhs.val.size() ? 0 : digit - rhs.val.size() + 1; i < val.size() && i <= digit; ++i) + { + PRODUCT_TYPE pval = result.val[digit] + val[i] * (PRODUCT_TYPE) rhs.val[digit - i]; + if (pval >= BASE || pval <= -BASE) + { + lldiv_t dt = my_lldiv(pval, BASE); + carry += dt.quot; + pval = dt.rem; + } + result.val[digit] = (ELEM_TYPE) pval; + found = true; + } + if (!found) + { + break; + } + } + for (; carry > 0; ++digit) + { + lldiv_t dt = my_lldiv(carry, BASE); + result.val[digit] = (ELEM_TYPE) dt.rem; + carry = dt.quot; + } + result.correct(); + result.pos = (result.val.size() == 1 && result.val[0] == 0) ? true : (pos == rhs.pos); + return result; +} + +inline InfInt InfInt::operator/(const InfInt& rhs) const +{ + //PROFINY_SCOPE + if (rhs == 0) + { +#ifdef INFINT_USE_EXCEPTIONS + throw InfIntException("division by zero"); +#else + std::cerr << "Division by zero!" << std::endl; + return 0; +#endif + } + InfInt Q, R, D = (rhs.pos ? rhs : -rhs), N = (pos ? *this : -*this); + Q.val.resize(N.val.size(), 0); + for (int i = (int) N.val.size() - 1; i >= 0; --i) + { + R.val.insert(R.val.begin(), N.val[i]); + R.correct(true); + ELEM_TYPE cnt = dInR(R, D); + R -= D * cnt; + Q.val[i] += cnt; + } + Q.correct(); + Q.pos = (Q.val.size() == 1 && Q.val[0] == 0) ? true : (pos == rhs.pos); + return Q; +} + +inline InfInt InfInt::operator%(const InfInt& rhs) const +{ + //PROFINY_SCOPE + if (rhs == 0) + { +#ifdef INFINT_USE_EXCEPTIONS + throw InfIntException("division by zero"); +#else + std::cerr << "Division by zero!" << std::endl; + return 0; +#endif + } + InfInt R, D = (rhs.pos ? rhs : -rhs), N = (pos ? *this : -*this); + for (int i = (int) N.val.size() - 1; i >= 0; --i) + { + R.val.insert(R.val.begin(), N.val[i]); + R.correct(true); + R -= D * dInR(R, D); + } + R.correct(); + R.pos = (R.val.size() == 1 && R.val[0] == 0) ? true : pos; + return R; +} + +inline InfInt InfInt::operator*(ELEM_TYPE rhs) const +{ + //PROFINY_SCOPE + InfInt result = *this; + ELEM_TYPE factor = rhs < 0 ? -rhs : rhs; + multiplyByDigit(factor, result.val); + result.correct(); + result.pos = (result.val.size() == 1 && result.val[0] == 0) ? true : (pos == (rhs >= 0)); + return result; +} + +inline bool InfInt::operator==(const InfInt& rhs) const +{ + //PROFINY_SCOPE + if (pos != rhs.pos || val.size() != rhs.val.size()) + { + return false; + } + for (int i = (int) val.size() - 1; i >= 0; --i) + { + if (val[i] != rhs.val[i]) + { + return false; + } + } + return true; +} + +inline bool InfInt::operator!=(const InfInt& rhs) const +{ + //PROFINY_SCOPE + if (pos != rhs.pos || val.size() != rhs.val.size()) + { + return true; + } + for (int i = (int) val.size() - 1; i >= 0; --i) + { + if (val[i] != rhs.val[i]) + { + return true; + } + } + return false; +} + +inline bool InfInt::operator<(const InfInt& rhs) const +{ + //PROFINY_SCOPE + if (pos && !rhs.pos) + { + return false; + } + if (!pos && rhs.pos) + { + return true; + } + if (val.size() > rhs.val.size()) + { + return pos ? false : true; + } + if (val.size() < rhs.val.size()) + { + return pos ? true : false; + } + for (int i = (int) val.size() - 1; i >= 0; --i) + { + if (val[i] < rhs.val[i]) + { + return pos ? true : false; + } + if (val[i] > rhs.val[i]) + { + return pos ? false : true; + } + } + return false; +} + +inline bool InfInt::operator<=(const InfInt& rhs) const +{ + //PROFINY_SCOPE + if (pos && !rhs.pos) + { + return false; + } + if (!pos && rhs.pos) + { + return true; + } + if (val.size() > rhs.val.size()) + { + return pos ? false : true; + } + if (val.size() < rhs.val.size()) + { + return pos ? true : false; + } + for (int i = (int) val.size() - 1; i >= 0; --i) + { + if (val[i] < rhs.val[i]) + { + return pos ? true : false; + } + if (val[i] > rhs.val[i]) + { + return pos ? false : true; + } + } + return true; +} + +inline bool InfInt::operator>(const InfInt& rhs) const +{ + //PROFINY_SCOPE + if (pos && !rhs.pos) + { + return true; + } + if (!pos && rhs.pos) + { + return false; + } + if (val.size() > rhs.val.size()) + { + return pos ? true : false; + } + if (val.size() < rhs.val.size()) + { + return pos ? false : true; + } + for (int i = (int) val.size() - 1; i >= 0; --i) + { + if (val[i] < rhs.val[i]) + { + return pos ? false : true; + } + if (val[i] > rhs.val[i]) + { + return pos ? true : false; + } + } + return false; +} + +inline bool InfInt::operator>=(const InfInt& rhs) const +{ + //PROFINY_SCOPE + if (pos && !rhs.pos) + { + return true; + } + if (!pos && rhs.pos) + { + return false; + } + if (val.size() > rhs.val.size()) + { + return pos ? true : false; + } + if (val.size() < rhs.val.size()) + { + return pos ? false : true; + } + for (int i = (int) val.size() - 1; i >= 0; --i) + { + if (val[i] < rhs.val[i]) + { + return pos ? false : true; + } + if (val[i] > rhs.val[i]) + { + return pos ? true : false; + } + } + return true; +} + +inline void InfInt::optimizeSqrtSearchBounds(InfInt& lo, InfInt& hi) const +{ + //PROFINY_SCOPE + InfInt hdn = 1; + for (int i = (int) this->numberOfDigits() / 2; i >= 2; --i) + { + hdn *= 10; + } + if (lo < hdn) + { + lo = hdn; + } + hdn *= 100; + if (hi > hdn) + { + hi = hdn; + } +} + +inline InfInt InfInt::intSqrt() const +{ + //PROFINY_SCOPE + if (*this <= 0) + { +#ifdef INFINT_USE_EXCEPTIONS + throw InfIntException("intSqrt called for non-positive integer"); +#else + std::cerr << "intSqrt called for non-positive integer: " << *this << std::endl; + return 0; +#endif + } + InfInt hi = *this / 2 + 1, lo = 0, mid, mid2; + optimizeSqrtSearchBounds(lo, hi); + do + { + mid = (hi + lo) / 2; // 8 factor + mid2 = mid * mid; // 1 factor + if (mid2 == *this) + { + lo = mid; + break; + } + else if (mid2 < *this) + { + lo = mid; + } + else + { + hi = mid; + } + } while (lo < hi - 1 && mid2 != *this); + return lo; +} + +inline char InfInt::digitAt(size_t i) const +{ + //PROFINY_SCOPE + if (numberOfDigits() <= i) + { +#ifdef INFINT_USE_EXCEPTIONS + throw InfIntException("invalid digit index"); +#else + std::cerr << "Invalid digit index: " << i << std::endl; + return -1; +#endif + } + return (val[i / DIGIT_COUNT] / powersOfTen[i % DIGIT_COUNT]) % 10; +} + +inline size_t InfInt::numberOfDigits() const +{ + //PROFINY_SCOPE + return (val.size() - 1) * DIGIT_COUNT + + (val.back() > 99999999 ? 9 : (val.back() > 9999999 ? 8 : (val.back() > 999999 ? 7 : (val.back() > 99999 ? 6 : + (val.back() > 9999 ? 5 : (val.back() > 999 ? 4 : (val.back() > 99 ? 3 : (val.back() > 9 ? 2 : 1)))))))); +} + +inline std::string InfInt::toString() const +{ + //PROFINY_SCOPE + std::ostringstream oss; + oss << *this; + return oss.str(); +} + +inline size_t InfInt::size() const +{ + //PROFINY_SCOPE + return val.size() * sizeof(ELEM_TYPE) + sizeof(bool); +} + +inline int InfInt::toInt() const +{ + //PROFINY_SCOPE + if (*this > INT_MAX || *this < INT_MIN) + { +#ifdef INFINT_USE_EXCEPTIONS + throw InfIntException("out of bounds"); +#else + std::cerr << "Out of INT bounds: " << *this << std::endl; +#endif + } + int result = 0; + for (int i = (int) val.size() - 1; i >= 0; --i) + { + result = result * BASE + val[i]; + } + return pos ? result : -result; +} + +inline long InfInt::toLong() const +{ + //PROFINY_SCOPE + if (*this > LONG_MAX || *this < LONG_MIN) + { +#ifdef INFINT_USE_EXCEPTIONS + throw InfIntException("out of bounds"); +#else + std::cerr << "Out of LONG bounds: " << *this << std::endl; +#endif + } + long result = 0; + for (int i = (int) val.size() - 1; i >= 0; --i) + { + result = result * BASE + val[i]; + } + return pos ? result : -result; +} + +inline long long InfInt::toLongLong() const +{ + //PROFINY_SCOPE + if (*this > LONG_LONG_MAX || *this < LONG_LONG_MIN) + { +#ifdef INFINT_USE_EXCEPTIONS + throw InfIntException("out of bounds"); +#else + std::cerr << "Out of LLONG bounds: " << *this << std::endl; +#endif + } + long long result = 0; + for (int i = (int) val.size() - 1; i >= 0; --i) + { + result = result * BASE + val[i]; + } + return pos ? result : -result; +} + +inline unsigned int InfInt::toUnsignedInt() const +{ + //PROFINY_SCOPE + if (!pos || *this > UINT_MAX) + { +#ifdef INFINT_USE_EXCEPTIONS + throw InfIntException("out of bounds"); +#else + std::cerr << "Out of UINT bounds: " << *this << std::endl; +#endif + } + unsigned int result = 0; + for (int i = (int) val.size() - 1; i >= 0; --i) + { + result = result * BASE + val[i]; + } + return result; +} + +inline unsigned long InfInt::toUnsignedLong() const +{ + //PROFINY_SCOPE + if (!pos || *this > ULONG_MAX) + { +#ifdef INFINT_USE_EXCEPTIONS + throw InfIntException("out of bounds"); +#else + std::cerr << "Out of ULONG bounds: " << *this << std::endl; +#endif + } + unsigned long result = 0; + for (int i = (int) val.size() - 1; i >= 0; --i) + { + result = result * BASE + val[i]; + } + return result; +} + +inline unsigned long long InfInt::toUnsignedLongLong() const +{ + //PROFINY_SCOPE + if (!pos || *this > ULONG_LONG_MAX) + { +#ifdef INFINT_USE_EXCEPTIONS + throw InfIntException("out of bounds"); +#else + std::cerr << "Out of ULLONG bounds: " << *this << std::endl; +#endif + } + unsigned long long result = 0; + for (int i = (int) val.size() - 1; i >= 0; --i) + { + result = result * BASE + val[i]; + } + return result; +} + +inline void InfInt::truncateToBase() +{ + //PROFINY_SCOPE + for (size_t i = 0; i < val.size(); ++i) // truncate each + { + if (val[i] >= BASE || val[i] <= -BASE) + { + div_t dt = my_div(val[i], BASE); + val[i] = dt.rem; + if (i + 1 >= val.size()) + { + val.push_back(dt.quot); + } + else + { + val[i + 1] += dt.quot; + } + } + } +} + +inline bool InfInt::equalizeSigns() +{ + //PROFINY_SCOPE + bool isPositive = true; + int i = (int) ((val.size())) - 1; + for (; i >= 0; --i) + { + if (val[i] != 0) + { + isPositive = val[i--] > 0; + break; + } + } + + if (isPositive) + { + for (; i >= 0; --i) + { + if (val[i] < 0) + { + int k = 0, index = i + 1; + for (; (size_t)(index) < val.size() && val[index] == 0; ++k, ++index) + ; // count adjacent zeros on left + //if ((size_t)(index) < val.size() && val[index] > 0) + { // number on the left is positive + val[index] -= 1; + val[i] += BASE; + for (; k > 0; --k) + { + val[i + k] = UPPER_BOUND; + } + } + } + } + } + else + { + for (; i >= 0; --i) + { + if (val[i] > 0) + { + int k = 0, index = i + 1; + for (; (size_t)(index) < val.size() && val[index] == 0; ++k, ++index) + ; // count adjacent zeros on right + //if ((size_t)(index) < val.size() && val[index] < 0) + { // number on the left is negative + val[index] += 1; + val[i] -= BASE; + for (; k > 0; --k) + { + val[i + k] = -UPPER_BOUND; + } + } + } + } + } + + return isPositive; +} + +inline void InfInt::removeLeadingZeros() +{ + //PROFINY_SCOPE + for (int i = (int) (val.size()) - 1; i > 0; --i) // remove leading 0's + { + if (val[i] != 0) + { + return; + } + else + { + val.erase(val.begin() + i); + } + } +} + +inline void InfInt::correct(bool justCheckLeadingZeros, bool hasValidSign) +{ + //PROFINY_SCOPE + if (!justCheckLeadingZeros) + { + truncateToBase(); + + if (equalizeSigns()) + { + pos = ((val.size() == 1 && val[0] == 0) || !hasValidSign) ? true : pos; + } + else + { + pos = hasValidSign ? !pos : false; + for (size_t i = 0; i < val.size(); ++i) + { + val[i] = abs(val[i]); + } + } + } + + removeLeadingZeros(); +} + +inline void InfInt::fromString(const std::string& s) +{ + //PROFINY_SCOPE + pos = true; + val.clear(); + val.reserve(s.size() / DIGIT_COUNT + 1); + int i = (int) s.size() - DIGIT_COUNT; + for (; i >= 0; i -= DIGIT_COUNT) + { + val.push_back(atoi(s.substr(i, DIGIT_COUNT).c_str())); + } + if (i > -DIGIT_COUNT) + { + std::string ss = s.substr(0, i + DIGIT_COUNT); + if (ss.size() == 1 && ss[0] == '-') + { + pos = false; + } + else + { + val.push_back(atoi(ss.c_str())); + } + } + if (val.back() < 0) + { + val.back() = -val.back(); + pos = false; + } + correct(true); +} + +inline ELEM_TYPE InfInt::dInR(const InfInt& R, const InfInt& D) +{ + //PROFINY_SCOPE + ELEM_TYPE min = 0, max = UPPER_BOUND; + while (max > min) + { + ELEM_TYPE avg = max + min; + div_t dt = my_div(avg, 2); + avg = dt.rem ? (dt.quot + 1) : dt.quot; + InfInt prod = D * avg; + if (R == prod) + { + return avg; + } + else if (R > prod) + { + min = avg; + } + else + { + max = avg - 1; + } + } + return min; +} + +inline void InfInt::multiplyByDigit(ELEM_TYPE factor, std::vector& val) +{ + //PROFINY_SCOPE + ELEM_TYPE carry = 0; + for (size_t i = 0; i < val.size(); ++i) + { + PRODUCT_TYPE pval = val[i] * (PRODUCT_TYPE) factor + carry; + if (pval >= BASE || pval <= -BASE) + { + lldiv_t dt = my_lldiv(pval, BASE); + carry = (ELEM_TYPE) dt.quot; + pval = dt.rem; + } + else + { + carry = 0; + } + val[i] = (ELEM_TYPE) pval; + } + if (carry > 0) + { + val.push_back(carry); + } +} + +/**************************************************************/ +/******************** NON-MEMBER OPERATORS ********************/ +/**************************************************************/ + +inline std::istream& operator>>(std::istream &s, InfInt &n) +{ + //PROFINY_SCOPE + std::string str; + s >> str; + n.fromString(str); + return s; +} + +inline std::ostream& operator<<(std::ostream &s, const InfInt &n) +{ + //PROFINY_SCOPE + if (!n.pos) + { + s << '-'; + } + bool first = true; + for (int i = (int) n.val.size() - 1; i >= 0; --i) + { + if (first) + { + s << n.val[i]; + first = false; + } + else + { + s << std::setfill('0') << std::setw(DIGIT_COUNT) << n.val[i]; + } + } + return s; +} + +#endif diff --git a/libraries/chain/include/rlpvalue/src/rlp2json.cpp b/libraries/chain/include/rlpvalue/src/rlp2json.cpp new file mode 100644 index 00000000..c50ede3c --- /dev/null +++ b/libraries/chain/include/rlpvalue/src/rlp2json.cpp @@ -0,0 +1,107 @@ + +#include +#include +#include "rlpvalue.h" +#include "InfInt.h" + +extern void RLPtoJSON(const RLPValue& rval, UniValue& jval); +extern std::string encodeBinary(uint64_t n); + +static void assignJsonArray(UniValue& jval, const RLPValue& rval) +{ + jval.setArray(); + + const std::vector& values = rval.getValues(); + for (auto it = values.begin(); it != values.end(); it++) { + const RLPValue& childVal = *it; + UniValue childJval; + + RLPtoJSON(childVal, childJval); + + jval.push_back(childJval); + } +} + +static void assignJsonBuffer(UniValue& jval, const RLPValue& rval) +{ + jval.setStr(rval.getValStr()); +} + +void RLPtoJSON(const RLPValue& rval, UniValue& jval) +{ + if (rval.isBuffer()) + assignJsonBuffer(jval, rval); + else + assignJsonArray(jval, rval); +} + +static bool isBigNumStr(const std::string& s) +{ + // first char must be # + if (s.empty() || s[0] != '#') + return false; + + // remaining chars must be digits + for (unsigned int i = 1; i < s.size(); i++) + if (!isdigit(s[i])) + return false; + + return true; +} + +static std::string encodeBigNum(const InfInt& n) +{ + std::string rs; + + if (n == 0) { + // do nothing; return empty string + } else { + rs.assign(encodeBigNum(n / 256)); + + InfInt iich = n % 256; + unsigned char ch = iich.toUnsignedLong(); + rs.append((const char *) &ch, 1); + } + + return rs; +} + +static std::string encodeBigNumStr(const std::string& s) +{ + InfInt n(s); + return encodeBigNum(n); +} + +bool JSONtoRLP(const UniValue& jval, RLPValue& rval) +{ + if (jval.isStr()) { + std::string ins = jval.getValStr(); + if (isBigNumStr(ins)) + ins = encodeBigNumStr(ins.substr(1)); + + rval.assign(ins); + return true; + } + + if (jval.isNum()) { + uint64_t val = jval.get_int64(); + std::string val_enc = encodeBinary(val); + rval.assign(val_enc); + return true; + } + + if (jval.isArray()) { + rval.setArray(); + const std::vector& arrVals = jval.getValues(); + for (auto it = arrVals.begin(); it != arrVals.end(); it++) { + const UniValue& childJval = *it; + RLPValue tmp; + if (!JSONtoRLP(childJval, tmp)) + return false; + rval.push_back(tmp); + } + return true; + } + + return false; +} diff --git a/libraries/chain/include/rlpvalue/src/tool.cpp b/libraries/chain/include/rlpvalue/src/tool.cpp new file mode 100644 index 00000000..d17158e7 --- /dev/null +++ b/libraries/chain/include/rlpvalue/src/tool.cpp @@ -0,0 +1,189 @@ + +/* + * Copyright 2019 Bloq Inc. + * + */ + +#ifndef HAVE_CONFIG_H +#error missing autoconf-generated config.h. +#endif +#include "rlpvalue-config.h" + +#include +#include +#include +#include +#include "rlpvalue.h" +#include "../test/utilstrencodings.h" + +using namespace std; + +extern void RLPtoJSON(const RLPValue& rval, UniValue& jval); +extern bool JSONtoRLP(const UniValue& jval, RLPValue& rval); + +static const char doc[] = +"rlp - encode or decode RLP protocol encoding"; + +static struct argp_option options[] = { + { "decode", 'd', NULL, 0, + "Decode RLP to JSON" }, + { "encode", 'e', NULL, 0, + "Encode JSON to RLP (default)" }, + { } +}; + +static error_t parse_opt (int key, char *arg, struct argp_state *state); +static const struct argp argp = { options, parse_opt, NULL, doc }; + +static bool opt_decode = false; +static bool inp_json, inp_rlp, outp_json, outp_rlp; +static vector file_args; +static UniValue global_jval; +static RLPValue global_rval; + +static error_t parse_opt (int key, char *arg, struct argp_state *state) +{ + switch (key) { + case 'd': opt_decode = true; break; + case 'e': opt_decode = false; break; + + case ARGP_KEY_ARG: + file_args.push_back(arg); + break; + + default: + return ARGP_ERR_UNKNOWN; + } + + return 0; +} + +static bool parseJsonInput(const std::string& body) +{ + bool rc = global_jval.read(body); + + if (!rc) + fprintf(stderr, "JSON input validation failed\n"); + + return rc; +} + +static bool parseRlpInput(const std::string& body) +{ + std::vector buf; + + if (body.substr(0, 2) == "0x") { + string tmp = body.substr(2); + buf = ParseHex(tmp); + } else + buf = ParseHex(body); + + size_t consumed, wanted; + bool rc = global_rval.read(&buf[0], buf.size(), consumed, wanted); + + if (!rc) + fprintf(stderr, "RLP input validation failed (%zu wanted)\n", + wanted); + + return rc; +} + +static bool readInput() +{ + if (opt_decode) { + inp_json = false; + inp_rlp = true; + outp_json = true; + outp_rlp = false; + } else { + inp_json = true; + inp_rlp = false; + outp_json = false; + outp_rlp = true; + } + + const char *filename = nullptr; + FILE *inf; + if (file_args.empty()) { + filename = "(standard input)"; + inf = stdin; + } else { + filename = file_args[0].c_str(); + inf = ::fopen(filename, "r"); + if (!inf) { + perror(filename); + return false; + } + } + + string body; + + while (1) { + vector buf(4096); + size_t rrc = fread(&buf[0], 1, buf.size(), inf); + body.append((char *) &buf[0], rrc); + if (rrc < buf.size()) + break; + } + bool haveErr = ferror(inf); + if (inf != stdin) + fclose(inf); + + if (haveErr) { + perror(filename); + return false; + } + + if (inp_json) + return parseJsonInput(body); + else + return parseRlpInput(body); +} + +static bool mutateInput() +{ + if (inp_rlp) + RLPtoJSON(global_rval, global_jval); + else + JSONtoRLP(global_jval, global_rval); + return true; +} + +static bool writeJsonOutput() +{ + string body = global_jval.write(2); + printf("%s\n", body.c_str()); + return true; +} + +static bool writeRlpOutput() +{ + string body = global_rval.write(); + string hex = HexStr(body.begin(), body.end()); + printf("%s\n", hex.c_str()); + return true; +} + +static bool writeOutput() +{ + if (outp_json) + return writeJsonOutput(); + else + return writeRlpOutput(); +} + +int main (int argc, char *argv[]) +{ + error_t argp_rc = argp_parse(&argp, argc, argv, 0, NULL, NULL); + if (argp_rc) { + fprintf(stderr, "%s: argp_parse failed: %s\n", + argv[0], strerror(argp_rc)); + return EXIT_FAILURE; + } + + if (!readInput() || !mutateInput() || !writeOutput()) + return 1; + + return 0; +} + diff --git a/libraries/chain/include/rlpvalue/test/.gitignore b/libraries/chain/include/rlpvalue/test/.gitignore new file mode 100644 index 00000000..7b27cf0d --- /dev/null +++ b/libraries/chain/include/rlpvalue/test/.gitignore @@ -0,0 +1,8 @@ + +object +unitester +test_json +no_nul + +*.trs +*.log diff --git a/libraries/chain/include/rlpvalue/test/data/example.json b/libraries/chain/include/rlpvalue/test/data/example.json new file mode 100644 index 00000000..e395204d --- /dev/null +++ b/libraries/chain/include/rlpvalue/test/data/example.json @@ -0,0 +1,6 @@ +{ + "listsoflists2": { + "in": "VALID", + "out": "c7c0c1c0c3c0c1c0" + } +} diff --git a/libraries/chain/include/rlpvalue/test/data/invalidRLPTest.json b/libraries/chain/include/rlpvalue/test/data/invalidRLPTest.json new file mode 100644 index 00000000..1f9b806c --- /dev/null +++ b/libraries/chain/include/rlpvalue/test/data/invalidRLPTest.json @@ -0,0 +1,46 @@ +{ + "int32Overflow": { + "in": "INVALID", + "out": "bf0f000000000000021111" + }, + + "int32Overflow2": { + "in": "INVALID", + "out": "ff0f000000000000021111" + }, + + "wrongSizeList": { + "in": "INVALID", + "out": "f80180" + }, + + "wrongSizeList2": { + "in": "INVALID", + "out": "f80100" + }, + + "incorrectLengthInArray": { + "in": "INVALID", + "out": "b9002100dc2b275d0f74e8a53e6f4ec61b27f24278820be3f82ea2110e582081b0565df0" + }, + + "randomRLP": { + "in": "INVALID", + "out": "f861f83eb9002100dc2b275d0f74e8a53e6f4ec61b27f24278820be3f82ea2110e582081b0565df027b90015002d5ef8325ae4d034df55d4b58d0dfba64d61ddd17be00000b9001a00dae30907045a2f66fa36f2bb8aa9029cbb0b8a7b3b5c435ab331" + }, + + "bytesShouldBeSingleByte00": { + "in": "INVALID", + "out": "8100" + }, + + "bytesShouldBeSingleByte01": { + "in": "INVALID", + "out": "8101" + }, + + "bytesShouldBeSingleByte7F": { + "in": "INVALID", + "out": "817F" + } +} diff --git a/libraries/chain/include/rlpvalue/test/data/longlist.json b/libraries/chain/include/rlpvalue/test/data/longlist.json new file mode 100644 index 00000000..525fe167 --- /dev/null +++ b/libraries/chain/include/rlpvalue/test/data/longlist.json @@ -0,0 +1,48 @@ +{ + "longList1" : { + "in" : [ + ["asdf","qwer","zxcv"], + ["asdf","qwer","zxcv"], + ["asdf","qwer","zxcv"], + ["asdf","qwer","zxcv"] + ], + "out": "0xf840cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376" + }, + "longList2" : { + "in" : [ + ["asdf","qwer","zxcv"], + ["asdf","qwer","zxcv"], + ["asdf","qwer","zxcv"], + ["asdf","qwer","zxcv"], + ["asdf","qwer","zxcv"], + ["asdf","qwer","zxcv"], + ["asdf","qwer","zxcv"], + ["asdf","qwer","zxcv"], + ["asdf","qwer","zxcv"], + ["asdf","qwer","zxcv"], + ["asdf","qwer","zxcv"], + ["asdf","qwer","zxcv"], + ["asdf","qwer","zxcv"], + ["asdf","qwer","zxcv"], + ["asdf","qwer","zxcv"], + ["asdf","qwer","zxcv"], + ["asdf","qwer","zxcv"], + ["asdf","qwer","zxcv"], + ["asdf","qwer","zxcv"], + ["asdf","qwer","zxcv"], + ["asdf","qwer","zxcv"], + ["asdf","qwer","zxcv"], + ["asdf","qwer","zxcv"], + ["asdf","qwer","zxcv"], + ["asdf","qwer","zxcv"], + ["asdf","qwer","zxcv"], + ["asdf","qwer","zxcv"], + ["asdf","qwer","zxcv"], + ["asdf","qwer","zxcv"], + ["asdf","qwer","zxcv"], + ["asdf","qwer","zxcv"], + ["asdf","qwer","zxcv"] + ], + "out": "0xf90200cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376" + } +} diff --git a/libraries/chain/include/rlpvalue/test/data/rlptest.json b/libraries/chain/include/rlpvalue/test/data/rlptest.json new file mode 100644 index 00000000..725022de --- /dev/null +++ b/libraries/chain/include/rlpvalue/test/data/rlptest.json @@ -0,0 +1,111 @@ +{ + "emptystring": { + "in": "", + "out": "0x80" + }, + "bytestring00": { + "in": "\u0000", + "out": "0x00" + }, + "bytestring01": { + "in": "\u0001", + "out": "0x01" + }, + "bytestring7F": { + "in": "\u007F", + "out": "0x7f" + }, + "shortstring": { + "in": "dog", + "out": "0x83646f67" + }, + "shortstring2": { + "in": "Lorem ipsum dolor sit amet, consectetur adipisicing eli", + "out": "0xb74c6f72656d20697073756d20646f6c6f722073697420616d65742c20636f6e7365637465747572206164697069736963696e6720656c69" + }, + "longstring": { + "in": "Lorem ipsum dolor sit amet, consectetur adipisicing elit", + "out": "0xb8384c6f72656d20697073756d20646f6c6f722073697420616d65742c20636f6e7365637465747572206164697069736963696e6720656c6974" + }, + "longstring2": { + "in": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur mauris magna, suscipit sed vehicula non, iaculis faucibus tortor. Proin suscipit ultricies malesuada. Duis tortor elit, dictum quis tristique eu, ultrices at risus. Morbi a est imperdiet mi ullamcorper aliquet suscipit nec lorem. Aenean quis leo mollis, vulputate elit varius, consequat enim. Nulla ultrices turpis justo, et posuere urna consectetur nec. Proin non convallis metus. Donec tempor ipsum in mauris congue sollicitudin. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Suspendisse convallis sem vel massa faucibus, eget lacinia lacus tempor. Nulla quis ultricies purus. Proin auctor rhoncus nibh condimentum mollis. Aliquam consequat enim at metus luctus, a eleifend purus egestas. Curabitur at nibh metus. Nam bibendum, neque at auctor tristique, lorem libero aliquet arcu, non interdum tellus lectus sit amet eros. Cras rhoncus, metus ac ornare cursus, dolor justo ultrices metus, at ullamcorper volutpat", + "out": "0xb904004c6f72656d20697073756d20646f6c6f722073697420616d65742c20636f6e73656374657475722061646970697363696e6720656c69742e20437572616269747572206d6175726973206d61676e612c20737573636970697420736564207665686963756c61206e6f6e2c20696163756c697320666175636962757320746f72746f722e2050726f696e20737573636970697420756c74726963696573206d616c6573756164612e204475697320746f72746f7220656c69742c2064696374756d2071756973207472697374697175652065752c20756c7472696365732061742072697375732e204d6f72626920612065737420696d70657264696574206d6920756c6c616d636f7270657220616c6971756574207375736369706974206e6563206c6f72656d2e2041656e65616e2071756973206c656f206d6f6c6c69732c2076756c70757461746520656c6974207661726975732c20636f6e73657175617420656e696d2e204e756c6c6120756c74726963657320747572706973206a7573746f2c20657420706f73756572652075726e6120636f6e7365637465747572206e65632e2050726f696e206e6f6e20636f6e76616c6c6973206d657475732e20446f6e65632074656d706f7220697073756d20696e206d617572697320636f6e67756520736f6c6c696369747564696e2e20566573746962756c756d20616e746520697073756d207072696d697320696e206661756369627573206f726369206c756374757320657420756c74726963657320706f737565726520637562696c69612043757261653b2053757370656e646973736520636f6e76616c6c69732073656d2076656c206d617373612066617563696275732c2065676574206c6163696e6961206c616375732074656d706f722e204e756c6c61207175697320756c747269636965732070757275732e2050726f696e20617563746f722072686f6e637573206e69626820636f6e64696d656e74756d206d6f6c6c69732e20416c697175616d20636f6e73657175617420656e696d206174206d65747573206c75637475732c206120656c656966656e6420707572757320656765737461732e20437572616269747572206174206e696268206d657475732e204e616d20626962656e64756d2c206e6571756520617420617563746f72207472697374697175652c206c6f72656d206c696265726f20616c697175657420617263752c206e6f6e20696e74657264756d2074656c6c7573206c65637475732073697420616d65742065726f732e20437261732072686f6e6375732c206d65747573206163206f726e617265206375727375732c20646f6c6f72206a7573746f20756c747269636573206d657475732c20617420756c6c616d636f7270657220766f6c7574706174" + }, + "zero": { + "in": 0, + "out": "0x80" + }, + "smallint": { + "in": 1, + "out": "0x01" + }, + "smallint2": { + "in": 16, + "out": "0x10" + }, + "smallint3": { + "in": 79, + "out": "0x4f" + }, + "smallint4": { + "in": 127, + "out": "0x7f" + }, + "mediumint1": { + "in": 128, + "out": "0x8180" + }, + "mediumint2": { + "in": 1000, + "out": "0x8203e8" + }, + "mediumint3": { + "in": 100000, + "out": "0x830186a0" + }, + "mediumint4": { + "in": "#83729609699884896815286331701780722", + "out": "0x8f102030405060708090a0b0c0d0e0f2" + }, + "mediumint5": { + "in": "#105315505618206987246253880190783558935785933862974822347068935681", + "out": "0x9c0100020003000400050006000700080009000a000b000c000d000e01" + }, + "emptylist": { + "in": [], + "out": "0xc0" + }, + "stringlist": { + "in": [ "dog", "god", "cat" ], + "out": "0xcc83646f6783676f6483636174" + }, + "multilist": { + "in": [ "zw", [ 4 ], 1 ], + "out": "0xc6827a77c10401" + }, + "shortListMax1": { + "in": [ "asdf", "qwer", "zxcv", "asdf","qwer", "zxcv", "asdf", "qwer", "zxcv", "asdf", "qwer"], + "out": "0xf784617364668471776572847a78637684617364668471776572847a78637684617364668471776572847a78637684617364668471776572" + }, + "listsoflists": { + "in": [ [ [], [] ], [] ], + "out": "0xc4c2c0c0c0" + }, + "listsoflists2": { + "in": [ [], [[]], [ [], [[]] ] ], + "out": "0xc7c0c1c0c3c0c1c0" + }, + "dictTest1" : { + "in" : [ + ["key1", "val1"], + ["key2", "val2"], + ["key3", "val3"], + ["key4", "val4"] + ], + "out" : "0xecca846b6579318476616c31ca846b6579328476616c32ca846b6579338476616c33ca846b6579348476616c34" + }, + "bigint": { + "in": "#115792089237316195423570985008687907853269984665640564039457584007913129639936", + "out": "0xa1010000000000000000000000000000000000000000000000000000000000000000" + } +} diff --git a/libraries/chain/include/rlpvalue/test/object.cpp b/libraries/chain/include/rlpvalue/test/object.cpp new file mode 100644 index 00000000..9918f659 --- /dev/null +++ b/libraries/chain/include/rlpvalue/test/object.cpp @@ -0,0 +1,171 @@ +// Copyright (c) 2014 BitPay Inc. +// Copyright (c) 2014-2016 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or https://opensource.org/licenses/mit-license.php. + +#include +#include +#include +#include +#include +#include +#include +#include + +#define BOOST_FIXTURE_TEST_SUITE(a, b) +#define BOOST_AUTO_TEST_CASE(funcName) void funcName() +#define BOOST_AUTO_TEST_SUITE_END() +#define BOOST_CHECK(expr) assert(expr) +#define BOOST_CHECK_EQUAL(v1, v2) assert((v1) == (v2)) +#define BOOST_CHECK_THROW(stmt, excMatch) { \ + try { \ + (stmt); \ + assert(0 && "No exception caught"); \ + } catch (excMatch & e) { \ + } catch (...) { \ + assert(0 && "Wrong exception caught"); \ + } \ + } +#define BOOST_CHECK_NO_THROW(stmt) { \ + try { \ + (stmt); \ + } catch (...) { \ + assert(0); \ + } \ + } + +BOOST_FIXTURE_TEST_SUITE(rlpvalue_tests, BasicTestingSetup) + +BOOST_AUTO_TEST_CASE(rlpvalue_constructor) +{ + RLPValue v2(RLPValue::VBUF); + BOOST_CHECK(v2.isBuffer()); + + RLPValue v3(RLPValue::VBUF); + v3.assign("foo"); + BOOST_CHECK(v3.isBuffer()); + BOOST_CHECK_EQUAL(v3.getValStr(), "foo"); + + std::string vs("yawn"); + RLPValue v8(vs); + BOOST_CHECK(v8.isBuffer()); + BOOST_CHECK_EQUAL(v8.getValStr(), "yawn"); + + const char *vcs = "zappa"; + RLPValue v9(vcs); + BOOST_CHECK(v9.isBuffer()); + BOOST_CHECK_EQUAL(v9.getValStr(), "zappa"); +} + +BOOST_AUTO_TEST_CASE(rlpvalue_set) +{ + RLPValue v("foo"); + v.clear(); + BOOST_CHECK_EQUAL(v.getValStr(), ""); + + BOOST_CHECK(v.setArray()); + BOOST_CHECK(v.isArray()); + BOOST_CHECK_EQUAL(v.size(), 0); + + v.assign("zum"); + BOOST_CHECK(v.isBuffer()); + BOOST_CHECK_EQUAL(v.getValStr(), "zum"); +} + +BOOST_AUTO_TEST_CASE(rlpvalue_array) +{ + RLPValue arr(RLPValue::VARR); + + std::string vStr("zippy"); + BOOST_CHECK(arr.push_back(vStr)); + + const char *s = "pippy"; + BOOST_CHECK(arr.push_back(s)); + + RLPValue v; + + std::vector vec; + v.assign("boing"); + vec.push_back(v); + + v.assign("going"); + vec.push_back(v); + + BOOST_CHECK(arr.push_backV(vec)); + + BOOST_CHECK_EQUAL(arr.empty(), false); + BOOST_CHECK_EQUAL(arr.size(), 4); + + BOOST_CHECK_EQUAL(arr[0].getValStr(), "zippy"); + BOOST_CHECK_EQUAL(arr[1].getValStr(), "pippy"); + BOOST_CHECK_EQUAL(arr[2].getValStr(), "boing"); + BOOST_CHECK_EQUAL(arr[3].getValStr(), "going"); + + BOOST_CHECK_EQUAL(arr[999].getValStr(), ""); + + arr.clear(); + BOOST_CHECK(arr.empty()); + BOOST_CHECK_EQUAL(arr.size(), 0); +} + +BOOST_AUTO_TEST_CASE(rlpvalue_readwrite) +{ + unsigned char s1[] = { 0x83, 'd', 'o', 'g' }; + + RLPValue v; + size_t consumed, wanted; + bool rc = v.read(&s1[0], sizeof(s1), consumed, wanted); + BOOST_CHECK(rc); + BOOST_CHECK(v.isBuffer()); + BOOST_CHECK_EQUAL(v.getValStr(), "dog"); + BOOST_CHECK_EQUAL(consumed, sizeof(s1)); + BOOST_CHECK_EQUAL(wanted, 0); + + std::string s1_out = v.write(); + BOOST_CHECK_EQUAL(sizeof(s1), s1_out.size()); + BOOST_CHECK_EQUAL(memcmp(&s1[0], &s1_out[0], sizeof(s1)), 0); + + unsigned char s2[] = + { 0xc8, 0x83, 'c', 'a', 't', 0x83, 'd', 'o', 'g' }; + + RLPValue v2; + rc = v2.read(&s2[0], sizeof(s2), consumed, wanted); + BOOST_CHECK(rc); + BOOST_CHECK(v2.isArray()); + BOOST_CHECK_EQUAL(consumed, sizeof(s2)); + BOOST_CHECK_EQUAL(wanted, 0); + BOOST_CHECK_EQUAL(v2[0].getValStr(), "cat"); + BOOST_CHECK_EQUAL(v2[1].getValStr(), "dog"); + + std::string s2_out = v2.write(); + BOOST_CHECK_EQUAL(sizeof(s2), s2_out.size()); + BOOST_CHECK_EQUAL(memcmp(&s2[0], &s2_out[0], sizeof(s2)), 0); + + unsigned char s_empty_list[] = { 0xc0 }; + RLPValue v_empty_list; + rc = v_empty_list.read(&s_empty_list[0], sizeof(s_empty_list), consumed, wanted); + BOOST_CHECK(rc); + BOOST_CHECK(v_empty_list.isArray()); + BOOST_CHECK_EQUAL(v_empty_list.size(), 0); + + unsigned char s_null[] = { 0x80 }; + RLPValue v_null; + rc = v_null.read(&s_null[0], sizeof(s_null), consumed, wanted); + BOOST_CHECK(rc); + BOOST_CHECK(v_null.isBuffer()); + BOOST_CHECK_EQUAL(v_null.getValStr(), ""); + BOOST_CHECK_EQUAL(consumed, sizeof(s_null)); + BOOST_CHECK_EQUAL(wanted, 0); +} + +BOOST_AUTO_TEST_SUITE_END() + +int main (int argc, char *argv[]) +{ + rlpvalue_constructor(); + rlpvalue_set(); + rlpvalue_array(); + rlpvalue_readwrite(); + return 0; +} + diff --git a/libraries/chain/include/rlpvalue/test/test_json.cpp b/libraries/chain/include/rlpvalue/test/test_json.cpp new file mode 100644 index 00000000..26828505 --- /dev/null +++ b/libraries/chain/include/rlpvalue/test/test_json.cpp @@ -0,0 +1,24 @@ +// Test program that can be called by the JSON test suite at +// https://github.com/nst/JSONTestSuite. +// +// It reads JSON input from stdin and exits with code 0 if it can be parsed +// successfully. It also pretty prints the parsed JSON value to stdout. + +#include +#include +#include "rlpvalue.h" + +using namespace std; + +int main (int argc, char *argv[]) +{ + RLPValue val; + if (val.read(string(istreambuf_iterator(cin), + istreambuf_iterator()))) { + cout << val.write() << endl; + return 0; + } else { + cerr << "JSON Parse Error." << endl; + return 1; + } +} diff --git a/libraries/chain/include/rlpvalue/test/unitester.cpp b/libraries/chain/include/rlpvalue/test/unitester.cpp new file mode 100644 index 00000000..b487ff0e --- /dev/null +++ b/libraries/chain/include/rlpvalue/test/unitester.cpp @@ -0,0 +1,207 @@ +// Copyright 2014 BitPay Inc. +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or https://opensource.org/licenses/mit-license.php. + +#include +#include +#include +#include +#include +#include +#include +#include "utilstrencodings.h" +#include "rlpvalue.h" +#include "../src/InfInt.h" + +using namespace std; + +#ifndef JSON_TEST_SRC +#error JSON_TEST_SRC must point to test source directory +#endif + +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) +#endif + +std::string srcdir(JSON_TEST_SRC); +static bool test_failed = false; + +extern uint64_t toInteger(const unsigned char *raw, size_t len); +extern std::string encodeBinary(uint64_t n); +extern bool JSONtoRLP(const UniValue& jval, RLPValue& rval); + +static uint64_t toInteger(const char *raw, size_t len) { + return toInteger((const unsigned char *) raw, len); +} + +static bool isBigNumStr(const std::string& s) +{ + // first char must be # + if (s.empty() || s[0] != '#') + return false; + + // remaining chars must be digits + for (unsigned int i = 1; i < s.size(); i++) + if (!isdigit(s[i])) + return false; + + return true; +} + +static std::string encodeBigNum(const InfInt& n) +{ + std::string rs; + + if (n == 0) { + // do nothing; return empty string + } else { + rs.assign(encodeBigNum(n / 256)); + + InfInt iich = n % 256; + unsigned char ch = iich.toUnsignedLong(); + rs.append((const char *) &ch, 1); + } + + return rs; +} + +static std::string encodeBigNumStr(const std::string& s) +{ + InfInt n(s); + return encodeBigNum(n); +} + +static bool runtest(const std::string& filename, const std::string& key, + const UniValue& jval) +{ + if (!jval.isObject() || + !jval["out"].isStr()) { + fprintf(stderr, " %s: skipping test, invalid\n", + key.c_str()); + return true; + } + + string ins = jval["in"].getValStr(); + string outs = jval["out"].getValStr(); + + if (outs.substr(0, 2) == "0x") // remove 0x prefix + outs = outs.substr(2); + + // decode RLP binary output test string from hex to binary + std::vector outb = ParseHex(outs); + + // attempt to parse with RLP class + RLPValue v; + size_t consumed, wanted; + bool rrc = v.read(&outb[0], outb.size(), consumed, wanted); + + bool rc = false; + if (ins == "VALID" || ins == "INVALID") { + if (ins == "VALID" && rrc == true) + rc = true; + else if (ins == "INVALID" && rrc == false) + rc = true; + } else if (jval["in"].isStr()) { + if (isBigNumStr(ins)) + ins = encodeBigNumStr(ins.substr(1)); + + if (v.isBuffer() && (ins == v.getValStr())) + rc = true; + + } else if (jval["in"].isNum()) { + if (v.isBuffer()) { + uint64_t test_val = jval["in"].get_int64(); + string enc_val = v.getValStr(); + uint64_t dec_val = toInteger(&enc_val[0], + enc_val.size()); + if (test_val == dec_val) + rc = true; + } + } else if (jval["in"].isArray()) { + RLPValue root(RLPValue::VARR); + JSONtoRLP(jval["in"], root); + + std::string genOutput = root.write(); + if ((outb.size() == genOutput.size()) && + (memcmp(&outb[0], &genOutput[0], outb.size()) == 0)) { + rc = true; + } else { + std::string genHex = HexStr(genOutput.begin(), + genOutput.end()); + fprintf(stderr, "INS :%s\nGENS:%s\n", + outs.c_str(), + genHex.c_str()); + } + + } else { + fprintf(stderr, "ERR: test %s not implemented yet\n", key.c_str()); + } + + fprintf(stderr, " %s: %s\n", key.c_str(), + rc ? "ok" : "FAIL"); + return rc; +} + +static void runtest_jfile(std::string filename, const UniValue& jfile) +{ + assert(jfile.isObject()); + + const std::vector& keys = jfile.getKeys(); + + fprintf(stderr, "Running testfile %s (%zu tests)\n", + filename.c_str(), keys.size()); + + for (auto it = keys.begin(); it != keys.end(); it++) { + const std::string& key = *it; + if (!runtest(filename, key, jfile[key])) + test_failed = true; + } +} + +static void runtest_file(const char *filename_) +{ + std::string basename(filename_); + std::string filename = srcdir + "/" + basename; + FILE *f = fopen(filename.c_str(), "r"); + if (!f) { + perror(filename.c_str()); + exit(1); + } + + std::string jdata; + + char buf[4096]; + while (!feof(f)) { + int bread = fread(buf, 1, sizeof(buf), f); + assert(!ferror(f)); + + std::string s(buf, bread); + jdata += s; + } + + assert(!ferror(f)); + fclose(f); + + UniValue jfile; + bool rc = jfile.read(jdata); + assert(rc == true); + + runtest_jfile(basename, jfile); +} + +static const char *filenames[] = { + "example.json", + "invalidRLPTest.json", + "rlptest.json", +// "longlist.json", +}; + +int main (int argc, char *argv[]) +{ + for (unsigned int fidx = 0; fidx < ARRAY_SIZE(filenames); fidx++) { + runtest_file(filenames[fidx]); + } + + return test_failed ? 1 : 0; +} + diff --git a/libraries/chain/include/rlpvalue/test/utilstrencodings.cpp b/libraries/chain/include/rlpvalue/test/utilstrencodings.cpp new file mode 100644 index 00000000..901821c0 --- /dev/null +++ b/libraries/chain/include/rlpvalue/test/utilstrencodings.cpp @@ -0,0 +1,226 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2017 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "utilstrencodings.h" + +#include +#include +#include +#include + +static const std::string CHARS_ALPHA_NUM = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + +const signed char p_util_hexdigit[256] = +{ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 0,1,2,3,4,5,6,7,8,9,-1,-1,-1,-1,-1,-1, + -1,0xa,0xb,0xc,0xd,0xe,0xf,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,0xa,0xb,0xc,0xd,0xe,0xf,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, }; + +signed char HexDigit(char c) +{ + return p_util_hexdigit[(unsigned char)c]; +} + +bool IsHex(const std::string& str) +{ + for(std::string::const_iterator it(str.begin()); it != str.end(); ++it) + { + if (HexDigit(*it) < 0) + return false; + } + return (str.size() > 0) && (str.size()%2 == 0); +} + +bool IsHexNumber(const std::string& str) +{ + size_t starting_location = 0; + if (str.size() > 2 && *str.begin() == '0' && *(str.begin()+1) == 'x') { + starting_location = 2; + } + for (auto c : str.substr(starting_location)) { + if (HexDigit(c) < 0) return false; + } + // Return false for empty string or "0x". + return (str.size() > starting_location); +} + +std::vector ParseHex(const char* psz) +{ + // convert hex dump to vector + std::vector vch; + while (true) + { + while (isspace(*psz)) + psz++; + signed char c = HexDigit(*psz++); + if (c == (signed char)-1) + break; + unsigned char n = (c << 4); + c = HexDigit(*psz++); + if (c == (signed char)-1) + break; + n |= c; + vch.push_back(n); + } + return vch; +} + +std::vector ParseHex(const std::string& str) +{ + return ParseHex(str.c_str()); +} + +std::string EncodeBase64(const unsigned char* pch, size_t len) +{ + static const char *pbase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + + std::string strRet = ""; + strRet.reserve((len+2)/3*4); + + int mode=0, left=0; + const unsigned char *pchEnd = pch+len; + + while (pch> 2]; + left = (enc & 3) << 4; + mode = 1; + break; + + case 1: // we have two bits + strRet += pbase64[left | (enc >> 4)]; + left = (enc & 15) << 2; + mode = 2; + break; + + case 2: // we have four bits + strRet += pbase64[left | (enc >> 6)]; + strRet += pbase64[enc & 63]; + mode = 0; + break; + } + } + + if (mode) + { + strRet += pbase64[left]; + strRet += '='; + if (mode == 1) + strRet += '='; + } + + return strRet; +} + +std::string EncodeBase64(const std::string& str) +{ + return EncodeBase64((const unsigned char*)str.c_str(), str.size()); +} + +std::vector DecodeBase64(const char* p, bool* pfInvalid) +{ + static const int decode64_table[256] = + { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, + -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, + 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, + 49, 50, 51, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 + }; + + if (pfInvalid) + *pfInvalid = false; + + std::vector vchRet; + vchRet.reserve(strlen(p)*3/4); + + int mode = 0; + int left = 0; + + while (1) + { + int dec = decode64_table[(unsigned char)*p]; + if (dec == -1) break; + p++; + switch (mode) + { + case 0: // we have no bits and get 6 + left = dec; + mode = 1; + break; + + case 1: // we have 6 bits and keep 4 + vchRet.push_back((left<<2) | (dec>>4)); + left = dec & 15; + mode = 2; + break; + + case 2: // we have 4 bits and get 6, we keep 2 + vchRet.push_back((left<<4) | (dec>>2)); + left = dec & 3; + mode = 3; + break; + + case 3: // we have 2 bits and get 6 + vchRet.push_back((left<<6) | dec); + mode = 0; + break; + } + } + + if (pfInvalid) + switch (mode) + { + case 0: // 4n base64 characters processed: ok + break; + + case 1: // 4n+1 base64 character processed: impossible + *pfInvalid = true; + break; + + case 2: // 4n+2 base64 characters processed: require '==' + if (left || p[0] != '=' || p[1] != '=' || decode64_table[(unsigned char)p[2]] != -1) + *pfInvalid = true; + break; + + case 3: // 4n+3 base64 characters processed: require '=' + if (left || p[0] != '=' || decode64_table[(unsigned char)p[1]] != -1) + *pfInvalid = true; + break; + } + + return vchRet; +} + +std::string DecodeBase64(const std::string& str) +{ + std::vector vchRet = DecodeBase64(str.c_str()); + return std::string((const char*)vchRet.data(), vchRet.size()); +} + diff --git a/libraries/chain/include/rlpvalue/test/utilstrencodings.h b/libraries/chain/include/rlpvalue/test/utilstrencodings.h new file mode 100644 index 00000000..6621ce4f --- /dev/null +++ b/libraries/chain/include/rlpvalue/test/utilstrencodings.h @@ -0,0 +1,62 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2017 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +/** + * Utilities for converting data from/to strings. + */ +#ifndef JUP_UTILSTRENCODINGS_H +#define JUP_UTILSTRENCODINGS_H + +#include +#include +#include + +#define BEGIN(a) ((char*)&(a)) +#define END(a) ((char*)&((&(a))[1])) +#define UBEGIN(a) ((unsigned char*)&(a)) +#define UEND(a) ((unsigned char*)&((&(a))[1])) +#define ARRAYLEN(array) (sizeof(array)/sizeof((array)[0])) + +std::vector ParseHex(const char* psz); +std::vector ParseHex(const std::string& str); +signed char HexDigit(char c); +/* Returns true if each character in str is a hex character, and has an even + * number of hex digits.*/ +bool IsHex(const std::string& str); +/** +* Return true if the string is a hex number, optionally prefixed with "0x" +*/ +bool IsHexNumber(const std::string& str); +std::vector DecodeBase64(const char* p, bool* pfInvalid = nullptr); +std::string DecodeBase64(const std::string& str); +std::string EncodeBase64(const unsigned char* pch, size_t len); +std::string EncodeBase64(const std::string& str); + +template +std::string HexStr(const T itbegin, const T itend, bool fSpaces=false) +{ + std::string rv; + static const char hexmap[16] = { '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; + rv.reserve((itend-itbegin)*3); + for(T it = itbegin; it < itend; ++it) + { + unsigned char val = (unsigned char)(*it); + if(fSpaces && it != itbegin) + rv.push_back(' '); + rv.push_back(hexmap[val>>4]); + rv.push_back(hexmap[val&15]); + } + + return rv; +} + +template +inline std::string HexStr(const T& vch, bool fSpaces=false) +{ + return HexStr(vch.begin(), vch.end(), fSpaces); +} + +#endif // JUP_UTILSTRENCODINGS_H diff --git a/libraries/chain/include/rlpvalue/univalue b/libraries/chain/include/rlpvalue/univalue new file mode 160000 index 00000000..d6715ee1 --- /dev/null +++ b/libraries/chain/include/rlpvalue/univalue @@ -0,0 +1 @@ +Subproject commit d6715ee16ed57bfbfc64e023dcb05151b6654aa4 diff --git a/libraries/fc/vendor/rlpvalue b/libraries/fc/vendor/rlpvalue deleted file mode 160000 index 1e58dcec..00000000 --- a/libraries/fc/vendor/rlpvalue +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 1e58dcec547dd19da4c325344d6f363d533dabe0 diff --git a/libraries/fc/vendor/rlpvalue/.gitignore b/libraries/fc/vendor/rlpvalue/.gitignore new file mode 100644 index 00000000..0203b4bb --- /dev/null +++ b/libraries/fc/vendor/rlpvalue/.gitignore @@ -0,0 +1,32 @@ +.deps/ +INSTALL +Makefile +Makefile.in +aclocal.m4 +autom4te.cache/ +compile +config.log +config.status +config.guess +config.sub +configure +depcomp +install-sh +missing +stamp-h1 +rlpvalue-config.h* +test-driver +libtool +ltmain.sh +test-suite.log + +*.a +*.la +*.lo +*.logs +*.o +*.pc +*.trs + +.dirstamp +.libs diff --git a/libraries/fc/vendor/rlpvalue/.gitmodules b/libraries/fc/vendor/rlpvalue/.gitmodules new file mode 100644 index 00000000..a740b3a7 --- /dev/null +++ b/libraries/fc/vendor/rlpvalue/.gitmodules @@ -0,0 +1,3 @@ +[submodule "univalue"] + path = univalue + url = https://github.com/jgarzik/univalue diff --git a/libraries/fc/vendor/rlpvalue/.travis.yml b/libraries/fc/vendor/rlpvalue/.travis.yml new file mode 100644 index 00000000..b5170879 --- /dev/null +++ b/libraries/fc/vendor/rlpvalue/.travis.yml @@ -0,0 +1,58 @@ +language: cpp + +compiler: + - clang + - gcc + +os: + - linux + - osx + +sudo: true + +env: + global: + - MAKEJOBS=-j3 + - RUN_TESTS=true + - BASE_OUTDIR=$TRAVIS_BUILD_DIR/out + +cache: + apt: true + +addons: + apt: + packages: + - pkg-config + +before_install: + - if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew update; fi + +install: + - if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew install gettext; fi + - if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew install argp-standalone; fi + +before_script: + - if [ -n "$USE_SHELL" ]; then export CONFIG_SHELL="$USE_SHELL"; fi + - test -n "$USE_SHELL" && eval '"$USE_SHELL" -c "./autogen.sh"' || ./autogen.sh + +script: + - if [ -n "$RLPVALUE_CONFIG" ]; then unset CC; unset CXX; fi + - OUTDIR=$BASE_OUTDIR/$TRAVIS_PULL_REQUEST/$TRAVIS_JOB_NUMBER-$HOST + - RLPVALUE_CONFIG_ALL="--prefix=$TRAVIS_BUILD_DIR/depends/$HOST --bindir=$OUTDIR/bin --libdir=$OUTDIR/lib" + - ./configure --cache-file=config.cache $RLPVALUE_CONFIG_ALL $RLPVALUE_CONFIG || ( cat config.log && false) + - make -s $MAKEJOBS $GOAL || ( echo "Build failure. Verbose build follows." && make $GOAL ; false ) + - export LD_LIBRARY_PATH=$TRAVIS_BUILD_DIR/depends/$HOST/lib + - if [ "$RUN_TESTS" = "true" ]; then make $MAKEJOBS distcheck; fi + +#matrix: +# fast_finish: true +# include: +# - os: linux +# compiler: gcc +# env: RLPVALUE_CONFIG=--host=x86_64-w64-mingw32 RUN_TESTS=false +# addons: +# apt: +# packages: +# - g++-mingw-w64-x86-64 +# - gcc-mingw-w64-x86-64 +# - binutils-mingw-w64-x86-64 diff --git a/libraries/fc/vendor/rlpvalue/COPYING b/libraries/fc/vendor/rlpvalue/COPYING new file mode 100644 index 00000000..1fb429f3 --- /dev/null +++ b/libraries/fc/vendor/rlpvalue/COPYING @@ -0,0 +1,19 @@ + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + diff --git a/libraries/fc/vendor/rlpvalue/Makefile.am b/libraries/fc/vendor/rlpvalue/Makefile.am new file mode 100644 index 00000000..f83246df --- /dev/null +++ b/libraries/fc/vendor/rlpvalue/Makefile.am @@ -0,0 +1,61 @@ +ACLOCAL_AMFLAGS = -I build-aux/m4 + +SUBDIRS = univalue + +UNIVALUE_CFLAGS = -I$(top_srcdir)/univalue/include + +include_HEADERS = include/rlpvalue.h +noinst_HEADERS = lib/rlpvalue_utffilter.h + +lib_LTLIBRARIES = librlpvalue.la + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = pc/librlpvalue.pc + +librlpvalue_la_SOURCES = \ + lib/rlpvalue.cpp \ + lib/rlpvalue_get.cpp \ + lib/rlpvalue_read.cpp \ + lib/rlpvalue_write.cpp + +librlpvalue_la_LDFLAGS = \ + -version-info $(LIBRLPVALUE_CURRENT):$(LIBRLPVALUE_REVISION):$(LIBRLPVALUE_AGE) \ + -no-undefined +librlpvalue_la_CXXFLAGS = -I$(top_srcdir)/include + +TESTS = test/object test/unitester + +noinst_PROGRAMS = src/rlp $(TESTS) + +src_rlp_SOURCES = \ + src/InfInt.h \ + src/tool.cpp \ + src/rlp2json.cpp \ + test/utilstrencodings.cpp +src_rlp_LDADD = librlpvalue.la univalue/.libs/libunivalue.a $(ARGP_LIBS) +src_rlp_CXXFLAGS = -I$(top_srcdir)/include $(UNIVALUE_CFLAGS) +src_rlp_LDFLAGS = -static $(LIBTOOL_APP_LDFLAGS) + +TEST_DATA_DIR=test/data + +test_unitester_SOURCES = \ + src/rlp2json.cpp \ + test/unitester.cpp \ + test/utilstrencodings.h test/utilstrencodings.cpp +test_unitester_LDADD = librlpvalue.la univalue/.libs/libunivalue.a +test_unitester_CXXFLAGS = -I$(top_srcdir)/include $(UNIVALUE_CFLAGS) \ + -DJSON_TEST_SRC=\"$(srcdir)/$(TEST_DATA_DIR)\" +test_unitester_LDFLAGS = -static $(LIBTOOL_APP_LDFLAGS) + +test_object_SOURCES = test/object.cpp +test_object_LDADD = librlpvalue.la +test_object_CXXFLAGS = -I$(top_srcdir)/include +test_object_LDFLAGS = -static $(LIBTOOL_APP_LDFLAGS) + +TEST_FILES = \ + test/data/example.json \ + test/data/invalidRLPTest.json \ + test/data/longlist.json \ + test/data/rlptest.json + +EXTRA_DIST=$(TEST_FILES) diff --git a/libraries/fc/vendor/rlpvalue/README.md b/libraries/fc/vendor/rlpvalue/README.md new file mode 100644 index 00000000..8df996c1 --- /dev/null +++ b/libraries/fc/vendor/rlpvalue/README.md @@ -0,0 +1,22 @@ + +# RLPValue + +## Summary + +A universal value class for use with Ethereum RLP encoding/decoding. + +See https://github.com/ethereum/wiki/wiki/RLP for more. + +## Installation + +This project is a standard GNU +[autotools](https://www.gnu.org/software/automake/manual/html_node/Autotools-Introduction.html) +project. Build and install instructions are available in the `INSTALL` +file provided with GNU autotools. + +``` +$ ./autogen.sh +$ ./configure +$ make +``` + diff --git a/libraries/fc/vendor/rlpvalue/TODO.md b/libraries/fc/vendor/rlpvalue/TODO.md new file mode 100644 index 00000000..8e9b7dc0 --- /dev/null +++ b/libraries/fc/vendor/rlpvalue/TODO.md @@ -0,0 +1,21 @@ + +# TO-DO + +## Technical debt + +* univalue included as a git subtree because of difficulty in + installing dependencies across all travis test platforms. + Ideally: remove submodule, discover via configure. + +* win64 build disabled in travis due to lack of argp-standalone + on that platform. find argp-standalone, and re-enable win64. + +## Low priority + +Rearrange tree for easier 'git subtree' style use + +Namespace support - must come up with useful shorthand, avoiding +long Univalue::Univalue::Univalue usages forced upon library users. + +Improve test suite + diff --git a/libraries/fc/vendor/rlpvalue/a.out b/libraries/fc/vendor/rlpvalue/a.out new file mode 100755 index 0000000000000000000000000000000000000000..1a3af65dec71ee0d7151f8143f7c510d0071d90a GIT binary patch literal 108976 zcmeEveS8!}^7m|#g~(f?0!Bq$5EKD1K!AXt;bnEfpb>~hMUxN$1R=z{0D2(NfRYQ* zpx`TNR8-`AiHgd3s6mnB6fr1jRMhC9ZVY;n^Cf!dKHsYDp6Qw03Ci#Hd7kGFM>jQH zRb5?OU0q$>GrKJJr=An#@kAT)iZ;$NJh)FhRUlF%zTkesiYvuPHo6)qMsLGsbO0&_ zpAnTB)KAwg^?GERjsF$&jh#sYlqFmuJK-ZHx}=_DE(xFld#e#w&4mn4rkeMHjW zqJ@Kpa>G=O+901g_xyAN!%|B)X+|E4?y^kuzxVn1=%Ojtk6e20f&W%s^+cDOvd284 zWKf&LLl@PTLu{5)a7R4c|M)v`-^C!@czh<{(~!Gs!83b@z58a;d96L}=t3yhYaJRr zDgyQ8PLc7qqJxq6GoVZ){7>jWB>ZRSR3v=7i$2p`+O2cZa{~+%N&Zq7`DE=#{P(!@ zE5}9uPhI%?V1h-G|APzuuSZ1YFLdee1Q-4ymwp{|(Lc#W{w^2%&o1&yT;#bGG==p?;-MlXPKjPvKc`o>4J4W`Cvt0T$ z&qe>|UF3vZ@RzyZPj<2Mr!MV&?P8x{F7|)lWqey)`g;=m(}$1qTIbU4xh~^U5?e>A5y^RE;R^}B6lIJy-{i8zyC^RQ4Ho9*&zY1nt$4_goVnSBnZ@y9rAM)KAoC?A)q1!?zmz%v{()7&fiJAUs zBQvL-=iY;9Ntx4zXHFlI>GyL_N&AUI{EH5++Y?01X~jvo`LpIn($?>;=m?D8;n;da zUVc$-VX=R~)br4r!;>+xFc&fw<+7#St>tQdbo>I@_<4WaTSgR>z^e=W3uv6t`jBCT zCHcj93vz`QLik}j;;4d>qPdwfvvaQWAEqaY)?wRW(zeNY3yUDJC^uE+~NC_~kfa#$}5+39G;;n1f=5&di>bnLU60!W?)hGtI<& z&&O;j&Y26=>65}NNM=2ZaT!M1&{UW;KTWm84QCf)XqM#U78K_#%s))w$>!`P(Q}q8 z$t=h%ELxbKJs&eZb5SCR4eN+$?LTZ>F^n`vvXIJOziLGW+`g&J!3weZIlbbnvK{2{<&EW|jG7S0_4ix-=;L8d z(4?ZgYgi839+AupkcY9pv4IeAv*(MnhGq=r$0#)v^B2xRR;1@lhY@ava~wb1kTPUw z<~UjuGUw(Y1Eg@5V+FfE94;+g*nG1KbM=UiEObr|0w5)!LyXMy{Ka{&@6_C)k_EYx zqUNaV6p3lhm67Q{3r&0y}oN%IaS5Dt_WppAIGu@p_GpQbsiH z=|4IHBwmsr+NHYDvc3nWOgCZ=q4qCnr(BJbIn4#IdNhigzdkPB2fIdR>Q+A z=2frZ$D3H3*=cy%v#P66!w*+Tz$OhpO2Y>=Jnbpf)vDpgC?sH;hCf@wC&>O%?}ll3 zwNE5}8K>dZevt4JG`!JG*azE59&bg8)$qdK1SMX>V=HT32^t<-R`c>{cxqc+{WUy| zjk*#wJn5vaWDT#zo@gl=9u90?0Szx*kZEZezKh9i7#SKK6T`f+G<-J`YZ!Aie4K_a z(C{>`)U`yzAE}Ulr5av8FIc7FkJk9BG(4SGtLqL8-$Nk*t2KO24Zl&tAEV)GG`u=% zAo3Osf2_t|tKpB+@bw!0cn#m6;nlMuA~$My`ACRsHEH-0H90{I@6+(D8osxNZ`1I7 zG`u0_7x~)B8a`IT_to(68or-~PtfqEXn3E7mm!R){WZJ{g^W+s@TX~Vk~RDQ4WFXn z2Wt3$h99Ki(=`0)8a_kA57zKm8vYCoKUc%kdZMlZ4bRJ?BrMVJLlrY%sfJI|@T)ZZ z2n}DQ;YVutJ2ZTQgG-sP-TBr{+ zUuc#o0Xxt<&Meb{eV}=WS*C^hKyz=iObhgZ<|EBAEzAd+J!Y8}pN>I`NUseBoT>i`~)53`Un`K%M(SNf{ z3nBV%mT3V*|IIQjeCWSfrUeiEH_Nopq5o!?7C7|ZEYre<{+nf5(9nOgObZ$MZ9OaK4<#!$B zHy!2I9OV}sj{hrlcVzwKvN(laP z<{wV=1E>8KC~pmH`}XX>wzlYiXGdW7Z^hjqV7L?z8)}-(aY5Cm^|*8_xua1sFg;K< z_U*558z}#xxJ#g7Y)@1RKKkEKC^!p?+YT?endfrUHQT59&5PB_myU|a4&npl%i01J z{a)6-p`tTr}KUKhLzYlkfRsQgKP!>Ib_tDF~5?P;i1G+AF3!3Bm$_(To{#wFyNAL@j?+BEC8oXFE!RUJ!?Qc|UW3fg-SW}=f9UtJ! z-=o^sp^+7}#Uo9rOsWgUp9Z&m4*%B*(Wj7T&|ZR0P^vCij*2Z0RH0sQR$!P=w%8kd zj+!moo_yKmR?o&wr@oPCg6LZlRSAd=G?ApE(bS~!?Lc$!F$hkD$B1^%2eAqQ<1ZUG z$@R7`1v{kyQU!2ToPvTXlxGsa!6jX^{k9D&KU@=I9Z zOf*1_%6j;bWCTX}TjOr6g=Y{?Ht`(8Ja$W612z6>j!OBmgBAXRWZSYfPjTm#qfoVZ z1*&$#&6jlJWusf;sCx#yf( zb-GyU^wUqQQ_a7WPPct3bh_ym)(O)uT@B9cu%J63yy^kJ)gOo0|QNEaG*Gd2AF6G7N7#0PCUd(0o_`W%<-x z+4c-acjl_@lsByMuXpLwI?@k)8o787saF0<+;jf*9#n{^;)yg%U(W5 z0af<$8ECA;l+})Ok@PE#lHF7vYNpEn9<~^!MpjC`gpeH-l5JcUoCu^e&?O|mHeF`yY&Ya|7uro2^WXg{_t82axbe ze<>u8$cNiYU5kpw#t7HK?k4Oz#W0g9%aiYm5hnE zVlzT>BCR3%pto@j#Zmrq>KF1}_!F0}r~a2CJ*!N|2Y4}@JCKqhK^ZPkb-~L|6e;UV zwXjD%%vT%i2)a!4QWRS(hNxwOlKmd_2{GV!g?J5!vL+93B^^1#l92$$ozkXfT05bo zmHUV_xd6RdrT2=mh&q1_EQHzaUqvG|i&`vei&`{OVGgie{je22;8=@}A&iVkEIC`T zyd_ww!BYK_SYqmeVkTgzsHD}YE;vKhTVmH7Hi#u9u(-mxILy}sDoR!b>bAj1uxwqh zhQza5BWb0?6}VoiNm-u%Z{nra(y2wb3D1bLG3n64*#cD;ycK0Azsi4m+)Mu3A!i?g zmKcey{~$Yz+e&}2_Opz-;9029vT58_?vhRbkl*<6gV zsA}<4Ic9M`J%ixs@DmP6EI}CSd(^1&?;&iRzfll5L)#MY zAiKmSk~YR?`kUg);^0$U5<^%^!;B5Be{b2cJyCHhZbfCfTmB~g8pWOQ*Hb*9nM4OF zdh~+q3jf}1ZBd9~9x?n4q=y`{{h<(%n_|kE63hLKP>DRa`8HAellNuqn9dmHNCL(v z0a0a5V}t;jp)DC`yIR%m;8y#$78(@qVq#3+8_0RP?DMlDX!$x z7fO!eW+JP14>#bie`zf7V$@axK^7{xfQ(?GOMq?}W34GX@KxxWbkTM2F-4W97&E^% zsf$5%IJ`GlNVSQ#YTk#Nzbho?~ zf1`@C>F@H*_{*NX*He5<^W$Kt@bAMML4)kAcQdAGTT@i|E1+y^i#Y;Yg^w_4KY|uY z#dooD1+}axPE=(-&B1vMykFLfid63&RWDl9!=BG*8OZfIaJ@*C=Ax3cN0oSzgzd~0 zIPI^pgK;Y=)ZNX^;x4LqAaytH<_|;}+?167=PC9!Z^x||B2P0Vqh-sQjFNHE%45cs zjG$WtAPN{dDJukBu^$m<{-XTVhV^;0y?ZQJ?6^mW0mc)TX3(fRPBu!%CM*>$1>5T3D&+s~=QnMMtXzTzvID3q5rya1D+ z8BRc>#SY^wVre1id=6C?JO&Ty_*{WD@O8mo@Z5|J%PP~~qD}4%e>` z_grBD9vnK3yik0t0m<}ru3qZqbQ9v!iJt{gsF3K%UK zWg_JL!(MeKQ{`Y_lUzA`sH_)duUE$P)@8BXWXtRtoAIUGP_Q3(9^;6OWV~8$~rwFl!cBH3LBMra-B6 z?&qu`_x4P_H;1Z|uvRG~c#0xNjU}s@ z%5Uhv#U@F8UNG0n;zkr5+mE;vcOw2Y-;6(II5Tx##a8C5y%JpwXP5(q=1~#rrVT19rV`Sz{=Kee6m)*ntOUy$KJlL;8Z_jDujnY?}fUD8(_L zc-Tw)Uy<`Y%g#sl^oZh&BCCFj#5-9|hx$f-zYz z=1InKFk0KgN})h^sv)d!Ea~FNbbAolp5?woeSH~LGJ@~J(Y13LdYCC5nzhC~7Y|Ww ztKzF7)5EbkqxNK!dbk5t)1Q4}KN*jNrHxu3`Zb53Z-@W1SKpN`p8(>dyH%#&--)JZ z#zcCucmS>!v88ZH!x1{b>XcO8y2}4OcdRn~d)eq}IC?~>=)ZZEScb?H=_#hP(F!K3 z*4o`1NzXWr{E8pJV2?s!Pi&OT29IJKB6j*$U_;bWxy5&%prRD=EbbkdoOVPZnX0IQ z@WFMTVkTBonM4Z5GoL0o$GsP(n44Y5FPhr18`0Mug6`@UWK;Q6V58U`QrSl`YbaKM zE}rP?+L6r@)Da6<=mBIbRmqh*OeJCgi@A|H zlNHOhCm@(bwxHB_j1Xb==q8BJ^;R>j!q6t|Ax?|v8HJ_&4bn#XG11n&Y$xrQ$T_-8 zVFqh{IIY)IK>;RM&VSjG6|h*@E3hbMONn%3t_&qeFc_0=#XhN}kKLF&5Nkg!FZ8M$+x7XT4;#EQdLJEWnL8CN51w*2SxLAs{_LHP9JuE8YWP ziIj=qod;|zQ_H_31?F&bcsHVad@MyEEZ^$AlL`6>6coTIyESc&{>aL_qyn=o>JJ$7 zpn*Reo7~=-;L#C-CR{Ea%4mipSJG{VL)KtV${i}w>7hY)^?JtbALvtnpD$Q*&=$j~ zgVd3Z)az0HhPd15ZHz8RIhyjYQ15!5&B-jCbe6akr(h*lwKH*46TqXC;4}<8>Q7*T z^-jWnFcP3QDgOUrCebib;}r$uNPyIfCeq~~xLa}sGKDAD1ZrA7swao53l3on{JEq- z2>pPtJa$?;G-HLsLOwezw<8>O6%n~*dOKh;%uevAz-d^IUMJtVmV$8OX4x!$hu^h>l*YTRwYCE05Ck1M{05|u}4``hSM_qs-ja%%c2wyl2I8RjLB4v$S0Gx z-g_|ldDbBq;(Z$`dccK|l^k*J05!@VTy!ij%=GKq0<+lmR8u^gGKx=vi!~6dnGD|Z zF13M~i<7?=JRMc7vj-aR3?fdZV?mmY*yoqOAH0NGr5Pt)0931tZJlM$X_KDZ3-vXF zJ5z!nwNb@wBtUKx6|dtWLgK4&>u_irmJKD6!OBbagiRq4$tnYwoTM76b|bKuhbFZ!*MKF8x_(Q zHZFl-(`}n!env<^cZvw4!o^2Zw8A*hie|p>`5OF6w~fk!{$K<>+a5uasTm5~Rs_XK zA?BJhg8udQM$oXRw*=oUK`UYA|9-bE>a}Nm=o4oA2`*yqVX?o@TOy9?*CN1#={wP> zZ#>5vVgFW|GH-Lucwy3bM~qFe1(@Z83*N`U&+Kl4oWY+8G_<0Hwl3J0 zx=&W2h0c0c;}S;ifJ4>FP{Q0#3uEy;_bLEl2hQvkaeBB!oP}@Md#Fbot!bY*)a3|dlqHZui!5OV zj6@^yFuud3RxLq!`b`egZI%^S3@?qy*H!w$4r8rGh~kOLS0ctZ;zxD`&oI42>9UD* zh%nby?b7F3#IdMg=QYP-DHmPF!m^TkFDxE=?2b20$tJ7|p3j~wG6rEc!Z>D+sKu6( z^NZc?6>wVC{Uf`qZ)L02E^9Sm=D4)_0 zsJNWG8MwM&_8X$xoZP6*WiOJ(I|17wbs6-x&P1hvPIym7>ggrtx1WDf`vJ6HPdi{N zgG#pvrx$!Fhr=`m_8^tHewp5h{oPuBqh+43bQEs?SV2BQbRZlhSM*nr?w)H?Kvr$AevE(J%F<~??!sG>zE z)Id>RV}0hVrT|&CtkozM-(%odIR){FllRUpZELc{ZmJC~f=V20ThS?$c_a^tG{g~_ z;k=RFy`o61#`7DQ_vi*I{3jbsKS`6eu=EL^Gvw;L&WH%aa^*f)==cRtVKalDxr-Ux zLe1J|2FA#4!E%~w)O(nYd(Y17F!>w*=0 z5JS@iT)d?M7t1UY=S9>fpweQsZGzKt-eVzk!JAnPa}1RKIQNEj53%Atdk5YHryU|P z24S=fWHj-$6)T`afkd-|NS!HO>EVLYCJJGcLLZ@tS;DF zG#G3-TTK1BVBBl$qCytl#*~A0J?aNfh8i+N1Q+982Hw?l8@4edN5LdglS+8SmwYM( zudsR9zkt=efciHVwKt-6HKybp`Ur@Cy%DkRm5U6+d}DSW3q~xaFA!81aL9Ub%NaKY z3}|@e0(vR29N*ijOvlF$={%=yBQxMlJy8Yk918T4e8>#<<{c`(Kzj#C@tM6KQe(h_ zy$i`__x_nIU+3RKAuRYD-eW)zze>>Sf+h6gIlVzaP2*i1Hh&_|1RfDSQd=mR-GW!Z zwqQ>yG(Xc`voF^)P;(0($dz-=;j(7SLRBrsUhNywyu#UFvoM~$!Pjvzt*QD9*K{`c zq^ucy^J~0A*y=%F`>3YNSpbbSnZI6|XC+~IkkTHJ}eA|GdwoA|&Fy{A6% zNgoG2ylY2M1?En}F&`$N8DQg9+ytA`_tNC!^Sa=;SI`>0WLAQ&19EkYmaNVre-1jp zJ5k813%*C+LMkVfVO0uiJfd%l?VmuC{@<;h*)DBctCfsv+C)cyWzE^VQ-uI$Rh+LoD1iNX>w?qZp-Y<%cZkZX*l>7na577sma(ZV6~ zz`1;;9d-tj1vL4y?F?qzwg`)eW^55v6L}Vr+e+KB+nx@r7F97)zw1H9u3EiG4r7{k z{?6EZ%7t2NK28J)%pID{hFffYl^-;P#pa!&wlg+&79pFQ2E%K`=DzSaI<(}32`}X~ zMF&n3faW!LE4xIoBIYxOd-Z_53k5x3M{z_o19mn&bqR}~&j}SdekKdyb-{XGam|{i za!pjW1?;7=rWLU17cjK2+sco85@qm0l;k*nZ=?nkea+77p{;`|_96{)9sobPXGT?-O4X9K*3B`MhdB`eM^ z#l4L4Yj7J}{~~GghvWRA<4Jf7`lDx-H;W*MuwXxDYlZ=>td}Nrf|>Tpoc2TZp9G8@ z3{e++L%P#xuTs||MrUzkZ^nAJr&QQvSWmomV!ok?Fa-lP1)(3M<&Bi^I-@G*y|Hiu zq`o${^1vGrAMFnUX1KK1_z&G6vb`X$N-o;~`Ev^Ex>7_4-x5>+Uxl98!g-;y6|vH* z6LpyR0eYp>{E9xku#RY77px#O2e4N0=4I1)_?ZCA2qSneWQOgol|*_VMmrvdVH~R( z8fh0}JNdV*@AOPqUt_{NHr%zuqcW`4;=$_}p zkdM^tV|>%!*`xnQd;ENs%lRsLz)h_IDr}Gc#D~;TObfhC@B(fRYmdJklI?r^L^Brr zuBS&;5D@0-H*V1J<-gL}Y8}S^g^PH!%n`;uP!a1-w%0#X*2nY1Tf(0oVx;v0 zCFk)+_|Zo^^~#Eols>^Mn2jX}R<=n%51M};=O(e1>gV(BVwXu~8r^OCBR{_mSLVO` zwYzla83q4u3sl52;Qf;-;_*JsGw@)owRO=p@;m$?Y(K*i)gd@i3#-)VoG2K6zLs+k zmZuP>(nFE(@B0oWG!jF{A~o?j-G%G}ATr$-C<4kTk>FIzXAW06mK;9cQfFK=gd(u^ zwbwESm`sI1=B=3-Eu2mh`OGXiTqFlrbN4~c++Uw!P=@C)j$3iME0^3I;=SE@cm-fp zLfHE(BqIPB_3+19I@#9kuN`VX0LRe|?oay!MVeqAqRm>o_=2f|bQiyiMBnwn`SLR~ zB`NpA+x{Qhs(#BwC@PM~p)kj#fOWoHTOfE2uK(*>rfqn|$`JH-u1{ zh+MwRtXVIYe?T&|%AKI@LLhhdZD`tDF64jLX`4vKJ*ZXpmkP?8)}B9`)Ih z&~NbGv)u_%P4^D{sV2n9GiKQ;y=cw9c6E6JCcw+d=xT5Wo@wLBV`}-gspVeo)re%oKlNuU-AZ@ay{6*E_fB$r=5tl{0Xw3 z;Pvwum{mt`5f-yYw8#08wjtiTGM)YiVzx!J%SjPiL_3c*nGqw})lYJ#onLxRK!0Hr zo)v5y5B>0l710iSM@1FU+SzoOYm04_jQHGRC(fDvx1M`E!ADv4=N>n~;Ff!}8)Yl0 zdbydlU(3Y^QFbvAes`2z4sJ)3wQ_s$YaUs!`$pKknw~BoHK=l~o|WlUn5iJ~Onnrq z89mMIhi{Z%E>^*x6lpl?te!jY+us}c3{y2tkoDjQUffiuaYhqM$rXS{EGsZ{fGRQ~HE3FLE3B zaifYU(tI31e+0UD7axt0Nzrx6H!TyKLguC3K*VDH+9B=gpegB6LXu#tx?rdOP$7x2RUGB=S;Sa2$?5Crg&!pGBaY8{?~94jh0KAQp-P+-++EVyy^l*HWM1K?W%3k zxufU|b&5OMl{)$bkNK2ZR<*Ln>@nz^Api6W4|Toh1O;w(yi;fkP>y$R`27ezVBfA46W%XgwF{ViTboIaJ?k12NUukB$*HT;cSP(j5tGOwyt1{V3k?i z49VZZR^fp?+R?;rUX^G`l!hXxy17Fv%fO`L!|OPpxsFFVRD>azSzFwbEGg({ylBdN zMg-g0#szM`Z!Zazu*|n))7nJ+K6xYAO_=6br8h6|kjul?!)mG?uB*^b<9oot9-FKq z!93i{jrg^=CCggRrSRj8S3e4R+4d~k@7N#+wIK+#>ibec+0s-5bf01ruP2Bzj@Pjc z^UM=FA*t`hoo%s?qVHTi);Z%Gb-uF4l2O`e{arMd%2hi3MMYz9>*TCgMM(ihZ33fTlm4#}PuWA>s6sP>+u&fjG}m>)*qTnqJwmk`X^x(O+u&%> zFn#Drs@lHU5*_<_48C53;q?E$Qx^J1hV^X0eM^NDj_i#oTNhl26UN_HD~I3Pb3c!X zh0C@&LY7!c(9q!=&-@KvwzBdsm?;qfAjnDP?>f!vO9r8Sn$Oh{zy6NVx1SOE960DW6|dq(Fr$jVOd$?#`Ux9 zu-3(JmO>~}`Bw2&EN}4Z`+2CjPv@ggR)f~>%9?=*^y*98zHR!;bKU65XC(-Pbv zTttFPzqPWBfAjZ~;9x>Je+bq&Y%WJ}e$=&eGe?9>MSE4UNw_hry@EA77B1XEY=wje z>?3QNCTQ+Ve=Gme9?y1(R!elx)`e_L|PNA}4=&cpW8*CX+W9O$~BpYul!QYeev zGRblr5S|RBtnRC=2EvB@DG_fTkrVM(m|0jKTGr(^nupO(jg0a)#@$Yf34hbyvjc0* zN8&4aL$SX-vzpxji<Opc7`@V#fNJj5i39Q%k@D7AJc!%|FR>lXYR?ZuFu+;^# z=o^3G?`B#jnGBpHLnIgBE3ZTY!xcfuXd}*sqDl9 z02Lul9C}@kz^Qp_5f>@nhL&{N6)1lzSU^a7m!+?AkDcQw@>aN^m>vr_gG9XJG7m*1 z1XiJJ3pbNtaBE=EfGq@UK=ws;TZ*a?xcE$5WJUV<@D@9_3LNF?Y}g;POr!#ihH=h| z$Y;L~awGa|5}LD4n2yl8*DKDMbg0=dlurR{vw?@fF&lcoJ1ldAkFs{Wc`4M?M*2K1 zM%Z{?O9cC9hs%}TbE9465-vKtr{oXFd)_W@Vd) z4J(~H87Zjq^!~A}5l`<`q}DS3@W8>D9->4ghb~Mno-ZdLJ;Z_JD8wob9?zhx4dpEU zS}^a-{A3)-)q@S?4<@(NV6FvQ&Qx0<-`x~aXbq+#GH&5s?1_WP=(7qZt8p*G$^CR| zf7LTgaXkizbGrue`%|F;6sOnT>!B8K+}gz7DpfIc4j;iAj#%YeeQSEE~f&AKwZdPmPIPg_1M> zF3e!m(sp=fwj?Qw?z+D{5f&P&8_zZK>F8hNWk> z<9AcE3X!ymSMig^eb9@}cqhozLM1e_-UX>VgycxMmmE9#bsH`3DuX0#QWT>ovMo~R zMkeYf@tX(}AqBG(wQn%ifZv|bB%;TSy5mzavt`mPed+%weX%d)*0B`WfAV-B|H?Kz z&HkRwI5<=Lc{hd%-_|9eTK+oVb{^kW$G!rbrFZDDOa@Cc6L3j0qaj`!ad7fK-ZFc9MU}#P;=(vb%5q{BU6_ zQ<19DhM_VonF5VCG|=LWdM=be&Q3`-xEjd)YVdZFcqRn2d?xhtvpgf^GojD$QjGJN z(8J)6&x9tEztS5Y;+YUdOa93wC?#J&RVZ3*sD0tGh{4qUG1!f3PfcREhzX&6kzCc6 z0gkIX{gS`bitojf=S{ME3Z5Eg!dSyjWS^dwv|btEOq{6SC4Q(-B}u{LE~bF^Ri6#Z7QD8QVzZu09Qwk3GC&e# zVy!>hw$NDi;-R1Qx(k&whc@+MZ^ysngM%aIoG^p9weE&xJdj#%#`rV+4aEb1!4TF3 z-)+PA!L+Snd5~P)-DQ4)YQsY&bz06jU^HhMv3@m)zH^?jqn!cMW~9wI zX3}oBLT}ySJs_+YZr#G@mZUm9UA=D0B9U0V#Wd0wnA zzU^6rd9denMAWqW%XG`|1@@c0)Sye$_RtuGMQ!#6A~=2&%x3godE0;oX*L_Rvs%vn z!Ip4cjH0$$22iwC%Q_aWua={D63Bo2D6BU&OV~yh9kge+^qtSJ>~?1rIS8R0*{%D; zwePXcgTneAtAaaVhE0Pz%X_RFh$8n`ajoK0B;3)g0AkyePQwM z7Ux;Km~D32>-w0Uq>ZTwPtrW#kV)D@bGO%jElu^y<@@{`$BTufdyx$a(m6i=Fgt5#9lnkHhF4tXf)B zYjJ`mf(@nLblUaXz3N`8e_r6C~u}xN}gDyN5>b0+`(>-3*Vmxbh zie0lCsWzRP)&d4pdp{Nc~y^ouL)MwLIq*7MzOd+8m(XWMG(;jy*l@! zvJU#X{TbOGesylPQtN665*sY;^1Pq>pZ6Pg`M4{rB`xygFyl|VvtuY$=OB8-v*R;Z zJos$*?6~1An_b7@S%&n%BcLsoHRn-ViR$4gIJ&H$74cE)Yu3*?v^ zQ1H-G=6yWZ*WBP1sx79>RlG|O<6i;e>r>`IqFGbs1JMxAkz%-tHf6eU(K%)Aruy33 zna6XpE>k96^(gX`aeZsWZkKEE=A^W)HIHHui5eWIG$KiaXJT3%FWwSkH@%U97xkH^ zRh}BPEXdWS)tek#C}MD>e7q;3O{8+4+<84O`~gOymPtec$o7p=exFlRYxj^O-MtqJ*~+mQc;0QP%^e3ISaMn`fu`iG6sI{mJzwjHsz9(l;);Vh0Jr#+Bu zM=blGJ(6o@`%7={YKO%~e?ulRr%McqRv8KgN(j9H~wvz`7e`Q81S z2U}`(zszp;RGZze3F}`Gu^(ptvhDp-TWoovxsHCvEaIURMMCm5OgKy|S~>W5$vQ)N z*e*ES4PiLjGUYM=^>}Al8-PPU$Sc7+$F>Ub<~$b9rl2&t>uhL8iyD2?BWyFyGT9P z6V@}9@*q&SL`K5>d;E1oymPO$BHrD&ml3aqZk;ErVn8sP?e7`!vn|?&#Y4Eu?LyT4-AwxJ6p0uybq%ZEv8?+ZVtxC9*XoZ?p+ z;X|EMjJr6sa_rx-@sE~XG^zZ(ap{xFe;7A?T=~KDK;`KhfS#6m+OIH1Z1B?(NZa;n zbn!_;K8ic36v|=iNgL6Lf@5H(PZppmy7M*xXf2)&mJ6i(h6ed zA0v8ILXt_GRQ~h&(*l25;7<$uX@UQ@7VsF@9<+aD7Zzq;ZOkm0Jv+D1m^|%*^L>l5 z=a=OA@``-<3yXc(`M!lS=jG-U`xX}ZnAewG=CkBr_Novc8hbDaVWZb&HpQuapNaU^q+HXVAACCQm34M zLE42=r%g}4=;Dk^F3p~qGb?xYoVj`PuAILhe__E@g+;|Bixw}r`kKTcLx&{|A2Bj{ z)W9>;__)FUE1mdXYUC_*LKk&5%1QVP$7cjSBk@Vb2jBQIM&olPKKL4FZXrZtfm@KhBvVM|O87G~yC{!MfE8@?XmlWFVLl8}f@Ltj zWd3|!8L>>}sRhtI8oNhuD^9CcF=x%#EhKu5k3KUAK_?dhDr;^iG#B?xSK_T>3Pkfm zp^bnA3qzqaz)K54p;iQ?I{@Pmmzxy*d<1Kmg48ODL2ASO%B{ zco8VSD6}8&?>MCGj-WZ{`cQ~|Sm<+{-)8~7xiS>00W?;J zLInusM^!>!z=43Z=;wKWO@P^e6pV`jeSm8LQvf#uW&!R2ECu`?up02hn@}I{EWjqf zxquYN*8=(gw*aO9z6V$exEk-UYy^A^upV$HU=VOWU@Yw1r3!WeoD3KM+yz(w7_|oD z1K1O=25=r=1K=vaRp?izTSB2mzyW}5fENKKVBuHI?kp$A|FU=83>zy`pLfUSV_fbm$U2HFW_Fl@%WCwLBI^aURdO60LK8v;+$dz;1z&N0Y3p; z4>))|>I2>YxR>yN2LZd_3ktokK)ww)2C&<`s1JBP;8MWNfa?MO3Ah!o`+cYnm<)Ij z@Gih!SX@5@90T|p;0(a-)u<0h-?Ul}SO~Zk@Rs{Aet<_kfPP~^UiBdC4Y(071Mow@ zC4gT8-T~NmLnyQba0Fl@;4Hv4z|DXOShRNlCIb$72>u2*6R;HU6~GOELBQ>RT^${0A~Si z0bE^!c>?$ZASERYfIh&_0aE}+J%xS)-UPS;@I$~2fRmp_zX59i_W^dmWBnK;G)aJc z0nY)P2$%sl3-Eft6@Y62HvkUZjQIu_01N`&0T}CpUjp_AjK_oCG{AEJ3jps1tOEQ9 zum-T#bMSM(fq<=mmjlKlk-8Bu5pXkL8sOJ}1%N5fqds5>U=83WfDM3MwxB-Xc))lh zVOfBQfa?I$05<{_0PY8@0^Iv|*d4If3m7-R!GPZb-T;_@1g-`!8SrJm48ZRImjE9B z57-@W0N@tD;V)v`00V$+fG+{|Me_H=ONcXoF)zbk0M7(m4Y(HYF~I$R4S+psp*LV( zz<4B#HQUiH;H!WcfbRk>0X*t8v60@@IQc*p!UJpvk!0o3rfC;CA{yyR%;26Lefb<>QrGUEuHv;YhtOxAd zi1`J$6fkx$_BbD4egR$rmdI*-4hL?4KNAt^u4GLSPEDS_yXWsz0;J8+2Y^1n ziA@-9z)JwL0Ivir1*CsBz8Y{RU@c%PU=yJCGt?gjzW^KrxC$^8@OHrYfDZ$%27G8A z^ak7vxCd}M;P-%uL9Aa%hOr!Q4B%G48GyS0mjZqPxE^q5GuAJ_>j9epYXEuE`!(jr zaKsD1iGZnqvjFb`Tmkqt;0C~w7K|6*gMj-1{{t950_(_r_$lC6z%;-#zyiRR0M`Nr z0XG9)^bO(>UX-=pEw;AYAfULhB5Sc{B>$;?L=p zFgdRC;@DE-?Bhlc7}gh&T-2Wd7|4Rp5JFzmUNJstz!y+`c~M)d@yWSP^835R-w-vS zYln-W5b#8QOwxM-8j3!}qVELy64XChr%$%%`+-jd9ZRKE|00Xt1^sT1KIjni)I-qc zOFBZJ)qb|s{%X)KYDd4vB;Bq4PSCSZA0g6`Khu)GAN2X4W2v<0ms<2LQP?Aaj#R{= zr(1MFd#*`KWl!mN_ZO3~BrAU*zo5_gsQ)Zr%#DLA8UC{9s7EY0#b{?Q_}s=}?IGx! z4?*8^2>SPuJ{EeKepD>SHI=VXKT52AjDi1NggqHTl*Kd8qR#+* z9_T#Bl#KH%`clxZ0DZb%KT0r=zpn@V7SP?sV=L%0vqPas{qUjwUeHTH|3H^deRxCY zKs-ha;?m4eXsXV0?&|2Wn5gl@MSAoF&n)m@3AFk-%j(BO&3?V+Nl8pcjIUCB@Ps&uV7_#®%R!Dg8M8#$ zT=ZularOmmCyhV&o+G}FVSEoOKJt@!h<|?}zWqpi?DDQue7#`jm%#TZ@il0CWb3;v z{U(C%?A%c3E#iCD!MDxgn-9J(!RNz#jk(*-7k!k68L1y@!S~7RP-qkJ-Kg;e%A%w1 zwD`zR=uD)E_?A2P-V%Id-!2^x@8`M4he4np5BfXcHEj{~I_u*DDi!oypx=UaOgh^> z`g&@GbPiw)$IQq2L%JNN=|Z+TAZ$Ro+yPnL7lcBW;og)LHP!5U735q1`XY=`%x6eu z)!0Bz^xP;@rzXg`XJIH*q|2eUaz$ID(_YBh51!{p)+UFnjY1aj#dwkH7vjAGx?f}G zi~87-Hwb)f*M>sZ6W>w?pB87PgRe&s;sn zxgOos^0g(g$mdH#A$WkrmnCHJ_=A2O=t!e1`T~o-1@zlNkJIVr2)YlrM$m5n{W{$j z$v28D9S(wLAL2a43scvqMJ$AL=ye3rp6ijT+UOHZ`WVm)Ku@#L&o${YK(7Yfr_;53 zW~ro~tkbpics=MFP~UA_w}M^+dZcxf+T4tBC;Cj>$6SAk*2ha&N8)J&&$r+S5YJ4F zM~*Amp>HSbfyHR_90D8KOE*c>H0-%2gx|=V}1%32NcVAfr`aICx^xFvf1E9O@#$Fk!8RBpl<>_MW<`y69D~n(A~yoF6i+$x{uE)(7m9ar^^>9 z2>Z`Q&=WzYIBfc$NDY`?4|)>l@)*!f8xs}GLYN&R09-Un7;|AqUQ*EL?6 zb2MRqC%(<#`vrW9C>}p;=Zl_e#le_v@ZY~ijw58dzLFj(?;`p{&@V;(NU@mcvp}B= zI<}rxzX~kdtN?u$=tt@FNfvzr=of)LSf|VNo8)ho_1)s|KG4^?$R|7Pg>T#d`fS|C z+}YdGk?fga=`jc$+z!4-W9&oSz8K>VLC+#NmuqsOM9?Q)3m~IsMJR+wYqfK^)kYQQ zy+C(c6KX*BfsW$=tA4&!zX9}-pkJcXqtcjx+HVED0Q6KFU94$jiy->29`pxsA9J72 zYJ+UC&T1zarvb;Tj=c9EIf<}&66haALC#{koai@2PDT2ZLQe3ePzctt+R|)J&(XdH zJ<=LS^=l>F%{QAsKZyG1wk2QY2~^)W61gAfZocUQy~EA!zL^4g8|u6HW>!1(eQ2JZ zH&Xo)+{Y|NFICPIC4vX(NY4Z(LkBk-Z3jKI9Ub?9epWm6V=(bjK+i^7R{LTQsD1kP zQLY0$(ms>u6G6Whbhlh>7U-Knk2D74D>E=g8$dr5`;?f)*zGDCz~`cmjW&JvG053) zi@P0mg8pzj^!=c31RcO?LyI$AaBy@N=#kc7AF2!jeK+XodVQJ~BIV{{ zWUB(u2ZLUq%ZQp|_L2S_rE5W_SY+BEN(2b1UjzDf&}}+IS$RkU=)ZvO=8vtQ$F6m^ zK|BsCsJ@$x5<%Y&`T$+OY%4CLf&QaQeIM!+fF1<>UcElqu*#CL7CbYdV^5t&JLlUB zdIsoeI$aI|*=P^wt6cg>{ziUs4d@*2&p-{$-}HFjs|TKSgKxOrj<%+c0eu(fZeuY6 z^yqc&Imc4aPi}|49`uQzN18X(&#j;j1AVBjpF9sC`d-lepu3ILLC`M%{dB#)cCOP4 z126-0w|PAV^g_@t((6Zwfui|Ks|?TGWq;Hd)7NbsBOX?a)% z=#PMYiB6Y!m=Cxmpf`b@q0=4XwjMm)?{*)zt)QO>dL+A2oZF0X?*clVtHxxapzI>f zLzrynK`Jgw0jwRTlYx8t9=zBpQqSNPE^&bQM8_?b2*-p?~KtDsTKijIm zAM{^9AFtD|7IYtQT`-uv9t?%%=yY**&KnpS>qPv?1dp4I(m*c;-A#uA&{u%&W`iow zmw@hO!y3?+gFZ&rQ9Gw-0R3*zZSyKhoa6XVrxo;fKwqiXr+K$n*n#|&{3L0E+ygB} zGNJja+5?fSF((+tli;)EAtYUJtqN2dhEv1G-y2R||R~=x#pI z1o~jm-R7==iayZY#?uG-2+-a3qbZ<|0^QBtS)gC#q-$}G>`3oKJp>*%I}*=E@a%4f z2g7RY1kbPFakKS)(9e1}@_J46yI}h@6ZA;FNq!LnTc(5lce-B=i|T&yH_Lwpf$vN3 zrFpZ=Jg=MSI;g;vE6VGi3=^<-Npu&^v(cHg;P8PDsWq^JP=x*b_ z1oSgOM>b^D*Y>z~fIbxTfjWJrwXSRdeJtn*X;yu0Z_^0+7|dvG5U zjSNza7un%vs~sPhH?`AF3g{a_ck5>s=r4jE$-il=Nr#6X=ozQ5_I^fZkqw=?k7L@VJfPM9`;# zeu1t-lsIH1y~p6sb)fUQ`6M1n=)NY`P4b1+kaN`I?d1QU`#_&zYiAl8o9gcbeFo?y zHo7=)Ao_mLp8|cJjV=zah~5QB=RwfjY&i(@??896Ln`S10^Myc%m=*<^g(+2a&JoQ zuLeEl3HPyn4D?vgBk4ymcmu}zSIFlWoYTp&bA%Y&23g}F%dIa75SRoyBDp0;J2y`T z{bUz9jd=#>M}Z!S((0dgQ*>p_YHwMG=oZ@CQ=d!0*IeV?PBrL_E_775zV zudH@5==7M{34*W7=Ey!u^jJ*5GeIAVds7Z#;X+xzKj;~tyV)xM`ee|t%eLx^$ICnq z=Yl>C^eH-Bd%t28==q?xwqvAPlDc_ zz4n5KzU$!D*Mp$9f*xr;QD1st@%;kyNc#aF=wm={1iii3nFXFc&qdCwNJc5>gFtUj z#s=^#0*_liwu4>)dL%umANxSRwjCW}5Rg_KLWlm~dAl7Q0-%2dy4yND7j*g^*JS8p z&M%r=D3Xq=KsTOu@54sW|I<$U^`OV1zS~|W2>P+0yXB0rI0U~C^hh=)zojn@&jy|I zrD0yH4~~2(4RZE^Zzk1I>zwu;LILO};(IVDIvp}pZd(QVS)g;9s=l_~*MLsnvvKp; z2GB=>K2Mh)CDu4hJ)<7|xDIq)Bg$ed9V4s}y)gN9fHzXiBmKI=rmLoc?!jE1pvgji zqGPOm?kvbDoE8e&@H*Fy|jKTmSLheB-+%jPDjdzFVvjkE--ti#s3(qhns7kf+lu z?~NX#+5{>kt2=l%cQWql@R;YmPR3J5{0GZC^iiMgezZ2*`;N!h?D2l*fiZ->hoX1s zkE6Hg-pdU7*LtXbxvzM(L>as3-#S4tcC>e#ajCe+2#4-I!E@9=6sLMG_xz>PN{?|n z^%~wNuF&26Jjb1RDUzs*KVG{h{om&~}S=sSCd~qkX_xrI%bF5zf_v&=W zz8&j{yTrTLv&PfuZjbS}-f`~t>>OK|$>T;%IAFyN&g?*|^^S@v@tFk!T>fBMXl z{NfVdsKLVqC!RiJWC<6CTst&zaAMMF0&TAru@sFIJRv%q6m3Kq$r16XRe!#~HN|@$p7tg!LgBFMX?cu1kxiU#6?kG2%WNzgAcKd?b8#qwSSQ_#Q^% zcaiWt&2>YkM&sA-)OumZCm6L6;#D+$B`;DOi^l4s;=WxDRw?P%c6=`*B_jR=osI8l zR>TZyay+NX-85^)+Y5Fz7Mz00^q4#l@CxI zx~|5@gI^R>>oX(q=MH=#>3=`-A7%LDxQo{DOi*{#P?|WL*M`!q&$M{}Gt;23t15f(Y zP7r)_Mn~7960hyQ>@O@y1^HQmv_#H}u1rk5|PAcL2hUFSYB_N-73bgt6Q^`N{ zLV?1OAzvL3e@Xtaw~Df=J3!)V$nkKgJS|P)S6v|RGX*fNk@)lT1VXB7+%NIhtP%L( zl7A=gsx66P@R{V_IbC31lf=pJ7t(W})Kkg1LE?+^1>*?Gk3&Z0KS#>pb92x>k@#LW z2u3BR4-z(#|LcPS&(9)oJ4fPM?-O|0ZR16W?;$&?+Wi9fNc|d##F*p{O%rmG1u(9V z_yvyndiSBd}eGJ%lO()gRi?_VkKDu4ANAtw11*9*Mr*93{*T`BNNw>c8OcZ$F- z7r^+d#6KhLpyce7_>T$&BgIF$&c_5l3hh2E9cqF=8}k@13mRAfJn8xQbpknF(w>(1 z@%Iaa>aX_*!QXbi!22ZsNfN(tgFxg<{CN_8|15#v=b^a0UE(+U1%80!e@x_I)X*QTmVa=V%60P@VUy(lMe^TNE%+gpug=E`IT_Lqm7h$K_#L+hJ{89bB>ug%0*~S2>u(Z&j*P>~ z|LY~*ndkf>@i)nUI!wyxjDtL~zcW5hkofa51*2LY%YaupOA!p7ko75*ZLpCbiG zvhjw*7fcoW3jdYF7t6R*BFILs6NLP?FA)g(jRCq=NxZR8l!psod;$ECQO6tVd_|&- z1Cqb*?E<6Z)At5Q{~KlqyoyUJCH|a3fmiWxi^M-5t&zd-?2uN2MS>PBJuZ5 z7YG#xs(K6l6d4G!CI8P7|H-2Qp>!V6N6g0w(!t-6{3VQ+1r59mJlW^NFF!@S7i#kiszS0{5Q7>{4@cK7bSkr zMFN2$U&r?oa&9|El%JLOQ4;T5A1{&kpwzR6^SErpK^m$swE2U=+@T%{!Nd_-Se&_o8jthV9Q-%CgN8A`D@nfolbh&IB&jTN+ z-OnU{!BWA0v{dSd{*n0y08iuVoGJc ztCT}O`9iZQE|IBp)e})uCzkf^o1Md(B)y#bo z-zUc|hkh5A_?`Lr4-&ugVZkq#Lt_*s6!FKD2|UcsSCPcOw^)?BNxTOEf%TDc)V!N2 z@dsqwQ+nPg@y@t$!XP1MuJmVwFTRFK{DzxFIYj_tsl;FUfIuWm{3F0C8%h*|-z0yM zUtpE|K?q!={}1;Iyju7D65r=?fzJ}a$d~vL%z?vAGlNS$4NPRB!2oi0)a5aS2OVJZzDumhAo5s<(NozSPDGpIZrlN zFXhxrd?)FLaC^SaON=b%9^gq%{vyGbF8MpakqE!%Vu4WO-XD0<^ER|Y7yULMT~{++ z-0Oeqq@13U1y+sM9x2B+OyHFrK9l_4tr2)EuY4VYfgpXHc~pPkBiU!X3;sDNr;GHr zDN_DEi9a`AAmAQ+B|<-H*SStjlK5HI2|lRJ*UJ*`Jb!DJ_yrdR+3h9Z$^QFC2|WF#AYFST|A8w-xu*bz2MrNF%^SKN6~H(VcVAkrlMGKs(M|MYex zK(bZk`6@0bK|u?AiQBV8B@)N!*`MoM<^s*UH*cIC5RiE3>Ar8eVS2jl?wR)|1>hb43!;gno08Z_nDe?qj*<3dll>d;F&&CISAn>eS-t|m>zn1|{{hlj= zO6l{cDSt|EmC)OZWjt>*aCvZU9|xS;xk}`-;^!`b*94!!mcin)xcqBwecgU-Ci*92EFNpUv%jO7MJ|z#D-3=?M1cLBjPo)n|Gjwz>=yXzrTpiG za6TsR_Zzr8IJeJAJLkWLfy$>p6?jAV{eaY&*~{a+{@v;FRe`_c7KSU%-wL??&A;%! z_X19MyGZc=1o?6AK8CM|+`C!eZNPo)yjIHZm-1TXlL9{|;{-dK>(u@Jc4~mrcy4_m zmwShl|A4?7FJQogz`qGN`KQ_V@V!$0-U=5~dN>^jr1qCDV)&KP&b0#nuUi%1O-^`>?{eKo^H3{0E9Lh<-ci4AdOHK&A@Fwsu6+r} z+7Ct0zYw+;c^S!De%vuJ-T$99~Jo5L@#SQ{{;A{*#Fgib`5|30B|23 zo&$S=#&#w{q2Zf%6J%XPIJR6UqeLkAk`67R`ecG4Rzh#K#_EstXHCZn$^HqUQ zx4CpvDxGkM+kdRk?NbH*Xo0_7#;^Q4FYpItxa5{!+koE&?*QFG~4W2|jnpk3R#P_N}t}CJ#Q${eBngPuE#| z3#JABt)mQ}cmL4!Nr7kS_KSd%J~}83yo`$nKffRK`sWd=PNL&)Z?A(DgmO1wWSZcSHWs^?1GoCol6jKZiSA=kqPN zSm4)*yj8hzgTQYTLheZUe+B#z^0#~Ysg%D`_*%=%fdL86d*8yPVJ@2MWdi@Dj8pmI zdV#;;wOmfy`FDX||7M0OzaN0XM(zJV*6We{bI=p`O)p}=UV(o};6LADfT+pfBp`&^ zsjo6z+b;_|OV39I{%TP~3)23b0`FhK03H8N0Vlf6>hTAnKK1)J%#SXm^C^M9^cse% zoV*QiZIgfDf4?W?|Kk<>401Ks9talSyp9U|c`xU3inn(I?rZ;V4IFw<_;Eto|DLpS z!k;tXGJ&55`lfy#_BsaW`hHB{|Mq%@Z%Fz77WlOy4|NRB#sU$Y|3KQ0rTihlsr`%5 zKV5sxzj)_@z^@T`sO{e?@CUWHAeO^i?Th{M{WRdz{!;}%Pm%KfY094x{OI=?@M(cR z4sw>tKUvlbW|g@v68Ow{{0wnzuHynfN$CG{fxjGZox6a{?JH9L6=DyVbLIHu{{(*H zpK|G^Nu^Uke>9$5kc)IZk#E76z~6NX19Utq0>8g7y2_cJz+ZO*msfppgTVWsJGxHe zTkv&(-zxT=_Ip1((|9hGcK$%hKOJ!2eCMV7=i6LxM#{fQ;O`eZN9Ef`3)=azl%IVi zH&B&!9t-=M#*>Z99Rl1po((Dg-7Ys^-U*05|5@PQ7Xct-5&T%-ACmG)|Bs5e-v40*`Ji_1YXzR&zx%Sl z|N2^PK;=mQ1QOn|bnU*LfWg_~(Q^K_2G1Lf{X$lAm>bKPK=qr5zE+!4CzV zjT`(@;2(G+w{tq*g2$sGjq?=2!!ChW0Dpx1?cOez@>&1uW`SPvXJVW4@ivH4Z)&M8@cET(dr0<5%^)e}c|7CtweBKTCZU&|P z{h5@{+Qaj89?#vl)1`Rc68KLpV7Lr7_=>>KEi?Qoz6IYAcs3tn7v@iRUKTs&iBf(U za37v8D}cX3+R65NgTQYU{3{*)g}|SC3wQWz>GvA~|HZo*aG}5#kNC&)b_0i8dM_7z zpp^eG;54tdgbdJi{EWcAFN8cT<;P$sQu&pm4A6dGBJdL+59op#GS~YA{<1DVPYC?B z`>|hkso1x30>4MfXZM{?Zg9WZ{G7JHYwzF&6mM?^+_x?tmhvaAr_29b;IBJ};fjYR zHM!rLU~kd|w43W{fq(WgejXF}djR+K`#(}XyYKT5)F*si_i}FFanjB#;Jf8-_jb0F zze4QHhslqBCGadieof%n_}Gb;bH7iJbyvISRKR`xo+ah8`h7v*pV{Jp2zv)t0`9}Z z-%I)R44zNIdOQKAsx;qT<=7bDgrC#T^Z~qy9(|De7B^OkB2x{GaufKWZ$XG3?$K80X+3UyMsNafe>+OxW7erCL z9j&dmSF7t$9bX^sMb*t?L9N~DtjGPhJ~lT#Gwv@G9cgYfqiVNXJs!my{qFJLNVnRG zqxxp6bsSZkCw#WN*-sU1Rht`QwN599F0S+smiBa-aVMyp|9(+AGow_J(#9b7thU$l7sAqIA$&37;0p{c#U+KXqV_D|Q29V?ZV78RU% z-N0t1qJDLCoyLNR%tcYNO_RmrR4KwY;H!On2b~~IeC_-SJheBX>P9`P$NV{TdLC~! zgXo-thxhM0h$@?_Q8`+~N7D7v@xbNT%li(6QMfoCMR+=A@%$(}SAgfvF9*^5MT`3m zl@H*z6sGHG07ipv$7@fA&px{nu0$*Q_8$z<>cxwd{tSQHz1*l&%Z)HB?TIQ8KL6h6 zwvXZq^!WZfJ^~+B`lZ?CMn7Kbf@I8URX6(O)q|_0F!VN4t%S=9m6GXWq0*m?B7^4A zg!_^Bat-a4YK=04sLVyc&wj#Br9S~2CIelq)-FF=MOdXy99j zK_h7*FeJ^fi~`_+t>u--P%ldP$$nhPz66H1*fA&}v;b=}U2uH66;*4sxYx62hu~NX z(KFYf&X!i9r3EZ?Wrl{BUR%W%MjvfLPFj8>@&-{3%T_bhPKU4van|zj6*#pJ{ZqZ> z70eC5%6N1@MRwU@{Jdqufm@i-eCIImZty%8&6C(`A1^O88sQe!qQnbJQ8%tO6}=v_8O27 zwaY=%q?ed~^1}fCqDh#!H5`!$~Iu0E&RqX zrpE3BaF7?qMsJ5DSY-U0*aBWfF^L6WK@EL9omur#PS7Q0;UEJt`CW`67K??ZPLUpi z0huT=M~{FQRksUOkkl3lHxY@FCQp#j0a`Zx3KaJsKJ*fcVGGtD37<|G8I<(8tx1gq zIfOA-RYBUH#P^~@;FkIwo8eFd+iMM8Wg~_jHZ>ff_HA`Qa9iW^@@m>_aXtTQR5ZkuP zen805qI|9w_xDlAfm$dZhJ#&iZje0;R~H7>&ZW0)F_~F<5y?8mt^jL&>!kP{z6`$_ zva%M#pt`f_OcJk0B+6yhs;Dw+mUrF;&1DgK7#h%Y*~s)eUUjv-WJUu+y9- zsQlnYljCj=JFvQDRXnjJA;y*=2_kcjV60Z*s;(o7k&YvHmsqGA!w>;gs4d|BWwnK4 z%_l0tc%9z9lI4@Q1$u2kFewFPM75<3cwR%;ib*e)mD2=2tkfE;(Mc_J@n)PRqJnX^ z+a^mFirwRF=FB~ceW=y#P*`54TD_%MO6Dopgj-&LxI7jar`6&$QAFYiYR4iyud zu0is3Gme%7#4G|5BM?&?wg>XZ)6r2fMMr98TOB=7?UPzII6^>~f~1)U7bdzMZ{(t0 z#Z+MtV0=+wxj}y0f z0vr*Rbzf*RTqfq=0B9RCjH|6OoAikNq!>hSqn1y^njS;Rl2OX8A*od=m3!yL#}+qR zt8sVq)k_fFYPvx+M{zpN9vp*h{FPG90s=l^1CbX4MzAYa8b8`a5P~)R@`!X->2Jhn zp2B#tX5h3$RTrr8J>dDZxF4-_k|>2Lfn2o64mgBV)=mEt6j? zM4UDyL`NkvGR}fAJ~)DE+elgW+ZtTC#?(Id@(*O86Ypps+F_(4#s1RHJZVo>!eC|W z)37?o>H?nSu#&1YgB7zpYMhqA;@Rpz$DAdLZ=NEFFt3kP*AZhS4}}L+tX)RjBS{cl zK!&Q6v5S`>!NA+GiYG9MW>_Y+-#BX*h!o;9yqek{5#s}?5kUi_vcB9i% z`H)9WrYccQ7%P@V5egMa5No?bb|6e@LDqTb6N|=`jK|m@cpu#X$X&m?5WaBH#WP?-B`8+Oq`r!a=_iR zF&#%Y8i)53NX2>S-Q8Yco??;W$OkX4+Bp}jt}&F%{vPl#EKh;N{C;d=!40BZ-}u}x zA{4DGu8G_tibphU7TPu8MA{-(qu6fE5}ePk729pls8gOT%m5-gPOCWDt#$^I?Z8PR zU}6Gq&~H0o;n6g+>_{yxBtFx0zYR-3GJveTZ;dcxq$P^YSjFT`WVes){K6@!q7CT+ z*q_y;GKSs!^T)u3V@T0Bb}Z_|-Cmpg;QsMw3#nIx``|1U-1= zvu302?2W)bCZ3O2Zp8jT=uJUL7*{bb;kXeZCX%w?lQ0PpsF^*yJivS^5-mUqQ*R(2 z_zVe{KT9R? zBE;Oz9xTkx`IXvw8d_Vg_m6ZUCU=;;Ii5g90Sm4|CV=k@_rvC36_!KC@bqXWhscJ~ z1!`z{ZV3pFVaf9&h_SE%^@A52l#QZ065g)#CtJ;patjl{%0YaKca%1vB|)kvrywn5 zax!8V(VkFnVZa(`dNewBdlNAU+9Y>23p27eLsxc)VQDX(!$%ss`sJ7}UECyQLXbeNJ8{%ZFiYFrz~#DV2B43e3lB#82%d z%XChB#YPP6U_)kTN2qB1d`y9Iyhc%lMylBqx&d_PT@GjtiCs;Mi_LGhf+@?82Uh6n zrI^@w;0@j>Pm)Fp1%NBN6Uw#t)5T8WGzoE$S>xL+o|uI$?R49n>KYQ;zDDDjawCcAPn}4R(zO$s1Hd zc#!aEjo1hEq;q~jOE3!a9%b=>3zN5EI+} z+d+e7mrY_eTa861KuB?jjXeofx+;;yo5nDQv8f!=_HF|e1$MLP8JL1|iUiYWVTKXp738kCe^V5mE4z_9!|1uN z9o#F9+8yR(_4@i!I*wL=FRw3UiAB$LxH1{~h-t;7rK8ybiW^Az7UhXbOPTqUsw7?6 z;KT?n|2EQenC&Z{{Y$#r?}+4guT1(YEkZ(4KFh}<#T-BwYy%;=fGK1IJp;R9ATe?7 zn=|H79A%EzYLGR1KxRColTO>`5jh8B93N>3w66Xt@M|)zD}4;MTHo4P>bymF0SzKW z5ef$MzWwkr%$2k%$w!Ie)s6JbAtA!SuX{*nz#@$%ylmD!ls||)qx*gND~Mf%Q0d+f zl|Ag>m|bLbZ5&NU{xW>xr8y5nx?YHbjf~fVaF~fSX#&r%4yPtm74D{)Z9mCKOU%hV zlulyK$+Bu8A)88zBVCuWfihGj7HgW8(8@?*;e&ejv>`;o2KJuW*&CSH;klPWQm zfeYiSB~pRRO-kZSZ#kJ0bRKa)r0phU$RS}nN!kpS{T#KJt*inkFL&QzHHv zp0|mcaZI?7pK~aJql}aW^5!UlNAEi@NACOrI)tCrg10s!qs#ca8gTWTlQ7$X(aNC% z`f7xfXK1NWgOIL}8373s12-^y*vE-_%x#_yksCXB$EP}cjivW*O$wNLNO{V4Qs{FF zgpdUGE6rA#d1HjxPs0!mg}~$m)#cB|(LrUB0GfRUvq8>pgQpFB7uIuykx%s|axocd z&L_;ch3Nxr1yn;}0VPB^|CL0w3j)vvIc_?5=QwRpO6HiAcHrXTWEx11M9P`9@g;4L zEUO{;8%)x}`y{Gsls#@(v|u_m6l8WSM6o4?f;l;v(7lyhsVM5;&6{k}!x04s z_?#v(7KTN>YiVHgbRZrmM)=mXHj;zO&@`FwTh^{KP8^jnf^<`()%;Ev=AB{9JS1~r zSl$dta4y^~d(_hNS{Rhb#8=4;7E$jtq7wQcCQ!3Y1F+i&-+WgI;nGGWVHSi1t}>0K z-Q;W22GmeL)? z<+#8c0aIfRT&piIiKP(wTx8yVVJPI5s=w{cWSi5Q%m5*s#m24iK4-J|R75`8+h>EKP!PH4=gO)LB2V zXOgT;`z_4%E!fJVU+KaO`Z0{PxNR)>}$~NPk zQJGkN|Lavq$7Iy)NUP#Cve2u=pMQ4}#4(TRh4}|lMn){T8Lh}f=X02Co}?jKQ1V8t^p59t zJLrX5@+RLh$!c}%-+VAb1oS{VAQ8w3yNI(20r{LVQlm9UO_USghEs_lloT!%N+6p zZxVZgaMI)Qret^q>ex)+os6tg1!^Ur(ID)USNiuw>KD`?@591UDd@cD+()$9>$%!b zjlmq!oE9cIr|rW|CS1>|XjjeXr-#DZ=2CM9%eWU20s&o$ey z`K!Hnsti6Ros^m)=(jY!xkVW&i#TYOxXjZRn5-3|ZxD%RdwG~G_GG0JFHc`?HQWZf z2R-4=H`THFsr?SkN8$JL4SLz=AjzN1GNDJuc(qC(T5qn_qFQg$yjC|YK`7KVn%TdD zT~YHs1gs`FAUTMuuO>`JPyRmd&)Q9&;Y~Y`sdIjQpdsK}S0-eBiNo*%Nc3Wg;B&j6 z`AASIae0aT7K@$IxP1ZV1r*;&mfA=j2%hwU=9|wOG0<;`0aGNB#k@mm!;&%lhR2A! zw%44W_J*Y#JI>CR#3`Bj{JLe%i%g6_h8ivCphB%w_kFIuyh{>QNQVIyt#Hc(y&%mX zvaI^Z#>AXJmAZz5m~@bVRgXDTn4eDiWC11hJDCc^eOS57@F`}8P*y8$k;N}`Xft3P zbgRyX`bxi!mX6TiKT4lR^L|epM{ih67b;_R^NdxC_Y`>F7X)(Jah8*hSzDUfv_1J- zx{`zJL{OdsidmyOVKc=Pg%{*>Grdr72g=z*5X8@bBG~3ggW^&8ay%XPU2qQZk@Lc= z;UNOhuoeB3+z4G-t=I8dpI-Y&@JAb^cFfMYIktjIAzRE5v>2gv4GMxI_IC+BSqVF6SRT&q7>^iM zpuBy8H%TxA_kcF$E^=H%x!X}Dpl0Wk39Qlk%)B0VZo(=9JTV}fl#`*i^d`OjXosR& z4h~%Y-E6=fX~4nnXCom^#4lMJ24}VlA`U<9k|G9&M&N_Q((g%gz9K>7=i=ArMvS;Y z!E{$%p|_&yXFZSzK_B&4k?&CqlC*X}mK-~hfxLGC9pUX8S6 z&T&heHTDo?xJul@CH9P5r60d&rxpu)eOXTvdwQ6jz7%s5LU7%4%p4+o)SY??P;ibz zxa>=GOq?wGpbX(Lv04e4fI!6+C8P|Rn=i-*MXD(*=4~y`M(Iv>)-8#EFqFC+y|Y{t z4~9+QMyMR4(Gbw!lUym6$GqnhvTWO&5#W%Bp0%Ar^!K4KazuruHzhV#qLRf)^jcS<4` z++{1YU8F3Xi>hEMq%w;XW{zG&GHbSR?)Thkg1@u*X2Y+mewqbqQRMv(XIKgate6j; zq>dh>A}&S*nPaBH6~hnR%-?>n$+zY2cg)CcW8ci5!jMC>Qh-^KbeJ`*{1QRLYK+eW zVic)xtM>@T4wl=Sz!!}5j<@htFx>lHzBlwQ^PcriFow@+#bfv+(-<9e$0wSOJD}Cg z=6d~U&ANc_s^F*5A%0W5QSCK?vHI~1biwz2mw(y9i-Yh|m()Xq->@H2r3&&_XT2Yc zQO;*DhCj#F+VV#)t_5Q_|BFYXhsU~Y^I3_pxFMf%Yt+%2KB1c$-bur+o#!v0nO6Cr z3%8+vQ#&*aG--xhZ8gysw~k$kU<{v|YvB`e@{PM+=k{n+#wQ#D`HW|<>jZ91?~lne zPG#NeiFkN0{@40*QeW@8-NN|$#LP2&-_xysq14y=8JY4A$UK)b^|7-obq`uxSm5MY+!kyOF?;_%Jk^xoG`g0G( z11`NkpBi_rEdJ?p;lFamf319YRqxkGT^+ynqxV0;@4s~F?>e0;==~O{PvfU?>i7j5 zydHlLPPM(;q`uy7kO6D|T3_dXz0}_?4KB$KdO!1l`~%hhJ^Y`o|2Dv=3vEBxjR(4R zn|}kMZ}-Zs|4sPOt-pIWm)850vYy(;De{Nj--Bnj{w+`B0(##q<@KiZ^!`Eo;MTuG z>g&BTp#M)~>W@E#d(!*#)!H-PwO@sP8h^O`H{Q#?=>23ZDEBP>?v(nv{sB#hF1g=9 zgyUShoxkbNFW`UbU+drTae@Yc-lsD3pY8vvDC^e$$zPi4f!@Ea9}Z=(r5||=zMZLm z*AMv@z2Ba}f42W0qd0xLRg2wv5{)JZZvDBr;R~bbOX*kdC!qMlQAF$CCiQQV`dUs~ z(PzCs9QCP3t*_r*y+i6NpK1Nw`iI;fgUZA^TK_KT|1KTBEQ~Ir_N()HAL_dO-*YlO z1;IVPFt=crE-XJ<{A)W;LUFf#a0=IFXb|j{dV14(`g|6O6HLdySL*LJtp>q0+MHC_ zs}G#k?N?!^;tyZ_>07wuo=k/dev/null || \ + (echo "configuration failed, please install autoconf first" && exit 1) +autoreconf --install --force --warnings=all + +cd univalue && ./autogen.sh + diff --git a/libraries/fc/vendor/rlpvalue/configure.ac b/libraries/fc/vendor/rlpvalue/configure.ac new file mode 100644 index 00000000..24737780 --- /dev/null +++ b/libraries/fc/vendor/rlpvalue/configure.ac @@ -0,0 +1,78 @@ +m4_define([librlpvalue_major_version], [1]) +m4_define([librlpvalue_minor_version], [1]) +m4_define([librlpvalue_micro_version], [4]) +m4_define([librlpvalue_interface_age], [4]) +# If you need a modifier for the version number. +# Normally empty, but can be used to make "fixup" releases. +m4_define([librlpvalue_extraversion], []) + +dnl libtool versioning from librlpvalue +m4_define([librlpvalue_current], [m4_eval(100 * librlpvalue_minor_version + librlpvalue_micro_version - librlpvalue_interface_age)]) +m4_define([librlpvalue_binary_age], [m4_eval(100 * librlpvalue_minor_version + librlpvalue_micro_version)]) +m4_define([librlpvalue_revision], [librlpvalue_interface_age]) +m4_define([librlpvalue_age], [m4_eval(librlpvalue_binary_age - librlpvalue_interface_age)]) +m4_define([librlpvalue_version], [librlpvalue_major_version().librlpvalue_minor_version().librlpvalue_micro_version()librlpvalue_extraversion()]) + + +AC_INIT([rlpvalue], [0.0.1], + [http://github.com/jgarzik/rlpvalue/]) + +dnl make the compilation flags quiet unless V=1 is used +m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) + +AC_PREREQ(2.60) +AC_CONFIG_SRCDIR([lib/rlpvalue.cpp]) +AC_CONFIG_AUX_DIR([build-aux]) +AC_CONFIG_MACRO_DIR([build-aux/m4]) +AC_CONFIG_HEADERS([rlpvalue-config.h]) +AX_SUBDIRS_CONFIGURE([univalue], [--disable-shared]) +AM_INIT_AUTOMAKE([subdir-objects foreign]) + +dnl Require C++11 compiler (no GNU extensions) +AC_PROG_CXX +AX_CXX_COMPILE_STDCXX([11], [noext], [mandatory], [nodefault]) +AC_LANG(C++) + +LIBRLPVALUE_MAJOR_VERSION=librlpvalue_major_version +LIBRLPVALUE_MINOR_VERSION=librlpvalue_minor_version +LIBRLPVALUE_MICRO_VERSION=librlpvalue_micro_version +LIBRLPVALUE_INTERFACE_AGE=librlpvalue_interface_age + +# ABI version +# http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html +LIBRLPVALUE_CURRENT=librlpvalue_current +LIBRLPVALUE_REVISION=librlpvalue_revision +LIBRLPVALUE_AGE=librlpvalue_age + +AC_CHECK_LIB(argp, argp_parse, ARGP_LIBS=-largp) +AC_SUBST(ARGP_LIBS) + +AC_SUBST(LIBRLPVALUE_CURRENT) +AC_SUBST(LIBRLPVALUE_REVISION) +AC_SUBST(LIBRLPVALUE_AGE) + +LT_INIT +LT_LANG([C++]) + +case $host in + *mingw*) + LIBTOOL_APP_LDFLAGS="$LIBTOOL_APP_LDFLAGS -all-static" + ;; +esac + +BUILD_EXEEXT= +case $build in + *mingw*) + BUILD_EXEEXT=".exe" + ;; +esac + +AC_CONFIG_FILES([ + Makefile + pc/librlpvalue.pc + pc/librlpvalue-uninstalled.pc]) + +AC_SUBST(LIBTOOL_APP_LDFLAGS) +AC_SUBST(BUILD_EXEEXT) +AC_OUTPUT + diff --git a/libraries/fc/vendor/rlpvalue/gen/gen.cpp b/libraries/fc/vendor/rlpvalue/gen/gen.cpp new file mode 100644 index 00000000..be3d4ccf --- /dev/null +++ b/libraries/fc/vendor/rlpvalue/gen/gen.cpp @@ -0,0 +1,82 @@ +// Copyright 2014 BitPay Inc. +// Distributed under the MIT software license, see the accompanying +// file COPYING or https://opensource.org/licenses/mit-license.php. + +// +// To re-create univalue_escapes.h: +// $ g++ -o gen gen.cpp +// $ ./gen > univalue_escapes.h +// + +#include +#include +#include "univalue.h" + +static bool initEscapes; +static std::string escapes[256]; + +static void initJsonEscape() +{ + // Escape all lower control characters (some get overridden with smaller sequences below) + for (int ch=0x00; ch<0x20; ++ch) { + char tmpbuf[20]; + snprintf(tmpbuf, sizeof(tmpbuf), "\\u%04x", ch); + escapes[ch] = std::string(tmpbuf); + } + + escapes[(int)'"'] = "\\\""; + escapes[(int)'\\'] = "\\\\"; + escapes[(int)'\b'] = "\\b"; + escapes[(int)'\f'] = "\\f"; + escapes[(int)'\n'] = "\\n"; + escapes[(int)'\r'] = "\\r"; + escapes[(int)'\t'] = "\\t"; + escapes[(int)'\x7f'] = "\\u007f"; // U+007F DELETE + + initEscapes = true; +} + +static void outputEscape() +{ + printf( "// Automatically generated file. Do not modify.\n" + "#ifndef BITCOIN_UNIVALUE_UNIVALUE_ESCAPES_H\n" + "#define BITCOIN_UNIVALUE_UNIVALUE_ESCAPES_H\n" + "static const char *escapes[256] = {\n"); + + for (unsigned int i = 0; i < 256; i++) { + if (escapes[i].empty()) { + printf("\tNULL,\n"); + } else { + printf("\t\""); + + unsigned int si; + for (si = 0; si < escapes[i].size(); si++) { + char ch = escapes[i][si]; + switch (ch) { + case '"': + printf("\\\""); + break; + case '\\': + printf("\\\\"); + break; + default: + printf("%c", escapes[i][si]); + break; + } + } + + printf("\",\n"); + } + } + + printf( "};\n" + "#endif // BITCOIN_UNIVALUE_UNIVALUE_ESCAPES_H\n"); +} + +int main (int argc, char *argv[]) +{ + initJsonEscape(); + outputEscape(); + return 0; +} + diff --git a/libraries/fc/vendor/rlpvalue/include/rlpvalue.h b/libraries/fc/vendor/rlpvalue/include/rlpvalue.h new file mode 100644 index 00000000..afebcd7d --- /dev/null +++ b/libraries/fc/vendor/rlpvalue/include/rlpvalue.h @@ -0,0 +1,126 @@ +// Copyright 2014 BitPay Inc. +// Copyright 2015 Bitcoin Core Developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or https://opensource.org/licenses/mit-license.php. + +#ifndef __RLPVALUE_H__ +#define __RLPVALUE_H__ + +#include +#include + +#include +#include +#include +#include + +#include // std::pair + +enum RLP_constants { + RLP_maxUintLen = 8, + RLP_bufferLenStart = 0x80, + RLP_listStart = 0xc0, +}; + +// really, a generic buffer, but we are in the global namespace, hence a prefix +class RLPBuffer { +public: + std::vector data; + + RLPBuffer() {} + RLPBuffer(const RLPBuffer& other) : data(other.data) {} + + void clear() { data.clear(); } + void reserve(size_t n) { data.reserve(n); } + void push_back(unsigned char ch) { data.push_back(ch); } + + std::vector::iterator begin() { return data.begin(); } + std::vector::iterator end() { return data.end(); } + + const unsigned char *get() const { return &data[0]; } + size_t size() const { return data.size(); } + std::string toStr() const { + std::string rs((const char *) &data[0], data.size()); + return rs; + } +}; + +// a single RLP value... which could be a nested list of RLP values +class RLPValue { +public: + enum VType { VARR, VBUF, }; + + RLPValue() { typ = VBUF; } + RLPValue(RLPValue::VType initialType) { + typ = initialType; + } + RLPValue(const std::string& val_) { + assign(val_); + } + RLPValue(const char *val_) { + std::string s(val_); + assign(s); + } + ~RLPValue() {} + + void clear(); + + void assign(const std::vector& val); + void assign(const std::string& val); + + bool setArray(); + + enum VType getType() const { return typ; } + std::string getValStr() const { return val.toStr(); } + bool empty() const { return (values.size() == 0); } + + size_t size() const { return values.size(); } + + const RLPValue& operator[](size_t index) const; + + bool isBuffer() const { return (typ == VBUF); } + bool isArray() const { return (typ == VARR); } + + bool push_back(const RLPValue& val); + bool push_back(const std::string& val_) { + RLPValue tmpVal; + tmpVal.assign(val_); + return push_back(tmpVal); + } + bool push_back(const char *val_) { + std::string s(val_); + return push_back(s); + } + bool push_backV(const std::vector& vec); + + std::string write() const; + + bool read(const unsigned char *raw, size_t len, + size_t& consumed, size_t& wanted); + +private: + bool readArray(const unsigned char *raw, size_t len, + size_t uintlen, size_t payloadlen, + size_t& consumed, size_t& wanted); + RLPValue::VType typ; + RLPBuffer val; + std::vector values; + + void writeBuffer(std::string& s) const; + void writeArray(std::string& s) const; + +public: + // Strict type-specific getters, these throw std::runtime_error if the + // value is of unexpected type + const std::vector& getValues() const; + std::string get_str() const; + const RLPValue& get_array() const; + + enum VType type() const { return getType(); } +}; + +extern const char *uvTypeName(RLPValue::VType t); + +extern const RLPValue NullRLPValue; + +#endif // __RLPVALUE_H__ diff --git a/libraries/fc/vendor/rlpvalue/lib/.gitignore b/libraries/fc/vendor/rlpvalue/lib/.gitignore new file mode 100644 index 00000000..ee7fc285 --- /dev/null +++ b/libraries/fc/vendor/rlpvalue/lib/.gitignore @@ -0,0 +1,2 @@ +gen +.libs diff --git a/libraries/fc/vendor/rlpvalue/lib/rlpvalue.cpp b/libraries/fc/vendor/rlpvalue/lib/rlpvalue.cpp new file mode 100644 index 00000000..6872f0e2 --- /dev/null +++ b/libraries/fc/vendor/rlpvalue/lib/rlpvalue.cpp @@ -0,0 +1,84 @@ +// Copyright 2014 BitPay Inc. +// Copyright 2015 Bitcoin Core Developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or https://opensource.org/licenses/mit-license.php. + +#include +#include +#include +#include + +#include "../include/rlpvalue.h" + +const RLPValue NullRLPValue; + +void RLPValue::clear() +{ + typ = VBUF; + val.clear(); + values.clear(); +} + +void RLPValue::assign(const std::string& s) +{ + clear(); + + val.reserve(s.size()); + + for (auto it = s.begin(); it != s.end(); it++) { + val.push_back((unsigned char) *it); + } +} + +void RLPValue::assign(const std::vector& buf) +{ + val.data.assign(buf.begin(), buf.end()); +} + +bool RLPValue::setArray() +{ + clear(); + typ = VARR; + return true; +} + +bool RLPValue::push_back(const RLPValue& val_) +{ + if (typ != VARR) + return false; + + values.push_back(val_); + return true; +} + +bool RLPValue::push_backV(const std::vector& vec) +{ + if (typ != VARR) + return false; + + values.insert(values.end(), vec.begin(), vec.end()); + + return true; +} + +const RLPValue& RLPValue::operator[](size_t index) const +{ + if (typ != VARR) + return NullRLPValue; + if (index >= values.size()) + return NullRLPValue; + + return values.at(index); +} + +const char *uvTypeName(RLPValue::VType t) +{ + switch (t) { + case RLPValue::VARR: return "array"; + case RLPValue::VBUF: return "buffer"; + } + + // not reached + return NULL; +} + diff --git a/libraries/fc/vendor/rlpvalue/lib/rlpvalue_get.cpp b/libraries/fc/vendor/rlpvalue/lib/rlpvalue_get.cpp new file mode 100644 index 00000000..82fb663b --- /dev/null +++ b/libraries/fc/vendor/rlpvalue/lib/rlpvalue_get.cpp @@ -0,0 +1,38 @@ +// Copyright 2014 BitPay Inc. +// Copyright 2015 Bitcoin Core Developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or https://opensource.org/licenses/mit-license.php. + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../include/rlpvalue.h" + +const std::vector& RLPValue::getValues() const +{ + if (typ != VARR) + throw std::runtime_error("JSON value is not an object or array as expected"); + return values; +} + +std::string RLPValue::get_str() const +{ + if (typ != VBUF) + throw std::runtime_error("JSON value is not a string as expected"); + return getValStr(); +} + +const RLPValue& RLPValue::get_array() const +{ + if (typ != VARR) + throw std::runtime_error("JSON value is not an array as expected"); + return *this; +} + diff --git a/libraries/fc/vendor/rlpvalue/lib/rlpvalue_read.cpp b/libraries/fc/vendor/rlpvalue/lib/rlpvalue_read.cpp new file mode 100644 index 00000000..5b317a28 --- /dev/null +++ b/libraries/fc/vendor/rlpvalue/lib/rlpvalue_read.cpp @@ -0,0 +1,216 @@ +// Copyright 2014 BitPay Inc. +// Copyright 2019 Bloq Inc. +// Distributed under the MIT software license, see the accompanying +// file COPYING or https://opensource.org/licenses/mit-license.php. + +#include +#include +#include "../include/rlpvalue.h" + +uint64_t toInteger(const unsigned char *raw, size_t len) +{ + if (len == 0) + return 0; + else if (len == 1) + return *raw; + else + return (raw[len - 1]) + (toInteger(raw, len - 1) * 256); +} + +bool RLPValue::readArray(const unsigned char *raw, size_t len, + size_t uintlen, size_t payloadlen, + size_t& consumed, size_t& wanted) +{ + const size_t prefixlen = 1; + + // validate list length, including possible addition overflows. + size_t expected = prefixlen + uintlen + payloadlen; + if ((expected > len) || (payloadlen > len)) { + wanted = expected > payloadlen ? expected : payloadlen; + return false; + } + + // we are type=array + if (!setArray()) + return false; + + size_t child_len = payloadlen; + size_t child_wanted = 0; + size_t total_consumed = 0; + + const unsigned char *list_ent = raw + prefixlen + uintlen; + + // recursively read until payloadlen bytes parsed, or error + while (child_len > 0) { + RLPValue childVal; + size_t child_consumed = 0; + + if (!childVal.read(list_ent, child_len, + child_consumed, child_wanted)) + return false; + + total_consumed += child_consumed; + list_ent += child_consumed; + child_len -= child_consumed; + + values.push_back(childVal); + } + + consumed = total_consumed; + return true; +} + +bool RLPValue::read(const unsigned char *raw, size_t len, + size_t& consumed, size_t& wanted) +{ + clear(); + consumed = 0; + wanted = 0; + + std::vector stack; + std::vector buf; + const unsigned char* end = raw + len; + + const size_t prefixlen = 1; + + unsigned char ch = *raw; + + if (len < 1) { + wanted = 1; + goto out_fail; + } + + // Case 1: [prefix is 1-byte data buffer] + if (ch <= 0x7f) { + const unsigned char *tok_start = raw; + const unsigned char *tok_end = tok_start + prefixlen; + assert(tok_end <= end); + + // parsing done; assign data buffer value. + buf.assign(tok_start, tok_end); + assign(buf); + + consumed = buf.size(); + + // Case 2: [prefix, including buffer length][data] + } else if ((ch >= 0x80) && (ch <= 0xb7)) { + size_t blen = ch - 0x80; + size_t expected = prefixlen + blen; + + if (len < expected) { + wanted = expected; + goto out_fail; + } + + const unsigned char *tok_start = raw + 1; + const unsigned char *tok_end = tok_start + blen; + assert(tok_end <= end); + + // require minimal encoding + if ((blen == 1) && (tok_start[0] <= 0x7f)) + goto out_fail; + + // parsing done; assign data buffer value. + buf.assign(tok_start, tok_end); + assign(buf); + + consumed = expected; + + // Case 3: [prefix][buffer length][data] + } else if ((ch >= 0xb8) && (ch <= 0xbf)) { + size_t uintlen = ch - 0xb7; + size_t expected = prefixlen + uintlen; + + if (len < expected) { + wanted = expected; + goto out_fail; + } + + assert(uintlen > 0 && uintlen <= RLP_maxUintLen); + + const unsigned char *tok_start = raw + prefixlen; + if ((uintlen > 1) && (tok_start[0] == 0)) // no leading zeroes + goto out_fail; + + // read buffer length + uint64_t slen = toInteger(tok_start, uintlen); + + // validate buffer length, including possible addition overflows. + expected = prefixlen + uintlen + slen; + if ((slen < (RLP_listStart - RLP_bufferLenStart - RLP_maxUintLen)) || + (expected > len) || (slen > len)) { + wanted = slen > expected ? slen : expected; + goto out_fail; + } + + // parsing done; assign data buffer value. + tok_start = raw + prefixlen + uintlen; + const unsigned char *tok_end = tok_start + slen; + buf.assign(tok_start, tok_end); + assign(buf); + + consumed = expected; + + // Case 4: [prefix][list] + } else if ((ch >= 0xc0) && (ch <= 0xf7)) { + size_t payloadlen = ch - 0xc0; + size_t expected = prefixlen + payloadlen; + size_t list_consumed = 0; + size_t list_wanted = 0; + + // read list payload + if (!readArray(raw, len, 0, payloadlen, list_consumed, list_wanted)) { + wanted = list_wanted; + goto out_fail; + } + + assert(list_consumed == payloadlen); + + consumed = expected; + + // Case 5: [prefix][list length][list] + } else { + assert((ch >= 0xf8) && (ch <= 0xff)); + + size_t uintlen = ch - 0xf7; + size_t expected = prefixlen + uintlen; + + if (len < expected) { + wanted = expected; + goto out_fail; + } + + assert(uintlen > 0 && uintlen <= RLP_maxUintLen); + + const unsigned char *tok_start = raw + prefixlen; + if ((uintlen > 1) && (tok_start[0] == 0)) // no leading zeroes + goto out_fail; + + // read list length + size_t payloadlen = toInteger(tok_start, uintlen); + + // special requirement for non-immediate length + if (payloadlen < (0x100 - RLP_listStart - RLP_maxUintLen)) + goto out_fail; + + size_t list_consumed = 0; + size_t list_wanted = 0; + + // read list payload + if (!readArray(raw, len, uintlen, payloadlen, list_consumed, list_wanted)) { + wanted = list_wanted; + goto out_fail; + } + + assert(list_consumed == payloadlen); + + consumed = prefixlen + uintlen + payloadlen; + } + + return true; + +out_fail: + clear(); + return false; +} + diff --git a/libraries/fc/vendor/rlpvalue/lib/rlpvalue_utffilter.h b/libraries/fc/vendor/rlpvalue/lib/rlpvalue_utffilter.h new file mode 100644 index 00000000..da1bde02 --- /dev/null +++ b/libraries/fc/vendor/rlpvalue/lib/rlpvalue_utffilter.h @@ -0,0 +1,119 @@ +// Copyright 2016 Wladimir J. van der Laan +// Distributed under the MIT software license, see the accompanying +// file COPYING or https://opensource.org/licenses/mit-license.php. +#ifndef RLPVALUE_UTFFILTER_H +#define RLPVALUE_UTFFILTER_H + +#include + +/** + * Filter that generates and validates UTF-8, as well as collates UTF-16 + * surrogate pairs as specified in RFC4627. + */ +class JSONUTF8StringFilter +{ +public: + explicit JSONUTF8StringFilter(std::string &s): + str(s), is_valid(true), codepoint(0), state(0), surpair(0) + { + } + // Write single 8-bit char (may be part of UTF-8 sequence) + void push_back(unsigned char ch) + { + if (state == 0) { + if (ch < 0x80) // 7-bit ASCII, fast direct pass-through + str.push_back(ch); + else if (ch < 0xc0) // Mid-sequence character, invalid in this state + is_valid = false; + else if (ch < 0xe0) { // Start of 2-byte sequence + codepoint = (ch & 0x1f) << 6; + state = 6; + } else if (ch < 0xf0) { // Start of 3-byte sequence + codepoint = (ch & 0x0f) << 12; + state = 12; + } else if (ch < 0xf8) { // Start of 4-byte sequence + codepoint = (ch & 0x07) << 18; + state = 18; + } else // Reserved, invalid + is_valid = false; + } else { + if ((ch & 0xc0) != 0x80) // Not a continuation, invalid + is_valid = false; + state -= 6; + codepoint |= (ch & 0x3f) << state; + if (state == 0) + push_back_u(codepoint); + } + } + // Write codepoint directly, possibly collating surrogate pairs + void push_back_u(unsigned int codepoint_) + { + if (state) // Only accept full codepoints in open state + is_valid = false; + if (codepoint_ >= 0xD800 && codepoint_ < 0xDC00) { // First half of surrogate pair + if (surpair) // Two subsequent surrogate pair openers - fail + is_valid = false; + else + surpair = codepoint_; + } else if (codepoint_ >= 0xDC00 && codepoint_ < 0xE000) { // Second half of surrogate pair + if (surpair) { // Open surrogate pair, expect second half + // Compute code point from UTF-16 surrogate pair + append_codepoint(0x10000 | ((surpair - 0xD800)<<10) | (codepoint_ - 0xDC00)); + surpair = 0; + } else // Second half doesn't follow a first half - fail + is_valid = false; + } else { + if (surpair) // First half of surrogate pair not followed by second - fail + is_valid = false; + else + append_codepoint(codepoint_); + } + } + // Check that we're in a state where the string can be ended + // No open sequences, no open surrogate pairs, etc + bool finalize() + { + if (state || surpair) + is_valid = false; + return is_valid; + } +private: + std::string &str; + bool is_valid; + // Current UTF-8 decoding state + unsigned int codepoint; + int state; // Top bit to be filled in for next UTF-8 byte, or 0 + + // Keep track of the following state to handle the following section of + // RFC4627: + // + // To escape an extended character that is not in the Basic Multilingual + // Plane, the character is represented as a twelve-character sequence, + // encoding the UTF-16 surrogate pair. So, for example, a string + // containing only the G clef character (U+1D11E) may be represented as + // "\uD834\uDD1E". + // + // Two subsequent \u.... may have to be replaced with one actual codepoint. + unsigned int surpair; // First half of open UTF-16 surrogate pair, or 0 + + void append_codepoint(unsigned int codepoint_) + { + if (codepoint_ <= 0x7f) + str.push_back((char)codepoint_); + else if (codepoint_ <= 0x7FF) { + str.push_back((char)(0xC0 | (codepoint_ >> 6))); + str.push_back((char)(0x80 | (codepoint_ & 0x3F))); + } else if (codepoint_ <= 0xFFFF) { + str.push_back((char)(0xE0 | (codepoint_ >> 12))); + str.push_back((char)(0x80 | ((codepoint_ >> 6) & 0x3F))); + str.push_back((char)(0x80 | (codepoint_ & 0x3F))); + } else if (codepoint_ <= 0x1FFFFF) { + str.push_back((char)(0xF0 | (codepoint_ >> 18))); + str.push_back((char)(0x80 | ((codepoint_ >> 12) & 0x3F))); + str.push_back((char)(0x80 | ((codepoint_ >> 6) & 0x3F))); + str.push_back((char)(0x80 | (codepoint_ & 0x3F))); + } + } +}; + +#endif diff --git a/libraries/fc/vendor/rlpvalue/lib/rlpvalue_write.cpp b/libraries/fc/vendor/rlpvalue/lib/rlpvalue_write.cpp new file mode 100644 index 00000000..53449ecd --- /dev/null +++ b/libraries/fc/vendor/rlpvalue/lib/rlpvalue_write.cpp @@ -0,0 +1,83 @@ +// Copyright 2014 BitPay Inc. +// Distributed under the MIT software license, see the accompanying +// file COPYING or https://opensource.org/licenses/mit-license.php. + +#include +#include +#include "../include/rlpvalue.h" + +std::string RLPValue::write() const +{ + std::string s; + + switch (typ) { + case VARR: + writeArray(s); + break; + case VBUF: + writeBuffer(s); + break; + } + + return s; +} + +std::string encodeBinary(uint64_t n) +{ + std::string rs; + + if (n == 0) { + // do nothing; return empty string + } else { + rs.assign(encodeBinary(n / 256)); + + unsigned char ch = n % 256; + rs.append((const char *) &ch, 1); + } + + return rs; +} + +static std::string encodeLength(size_t n, unsigned char offset) +{ + std::string rs; + + if (n < 56) { + unsigned char ch = n + offset; + rs.assign((const char *) &ch, 1); + } + + else { + // assert(n too big); + std::string binlen = encodeBinary(n); + + unsigned char ch = binlen.size() + offset + 55; + rs.assign((const char *) &ch, 1); + rs.append(binlen); + } + + return rs; +} + +void RLPValue::writeBuffer(std::string& s) const +{ + const unsigned char *p = val.size() ? val.get() : nullptr; + size_t sz = val.size(); + + if ((sz == 1) && (p[0] < 0x80)) + s.append((const char *) p, 1); + else + s += encodeLength(sz, 0x80) + val.toStr(); +} + +void RLPValue::writeArray(std::string& s) const +{ + std::string tmp; + for (auto it = values.begin(); it != values.end(); it++) { + const RLPValue& val = *it; + tmp += val.write(); + } + + s += encodeLength(tmp.size(), 0xC0) + tmp; +} + diff --git a/libraries/fc/vendor/rlpvalue/main.cpp b/libraries/fc/vendor/rlpvalue/main.cpp new file mode 100644 index 00000000..11427efb --- /dev/null +++ b/libraries/fc/vendor/rlpvalue/main.cpp @@ -0,0 +1,48 @@ +#include "include/rlpvalue.h" +#include "lib/rlpvalue.cpp" +#include "lib/rlpvalue_get.cpp" +#include "lib/rlpvalue_write.cpp" +#include "test/utilstrencodings.cpp" +#include + +int main() { + std::string dogIns = "dog"; + std::string dogOuts = "83646f67"; + + // Parse input string + RLPValue dogV = RLPValue(dogIns); + + // Parse expected output, print corresponding input -- note that 0x has been stripped from hex output + std::vector outb = ParseHex(dogOuts); + std::string outbStr(outb.begin(), outb.end()); + + std::cout << "83646f67 to c_str:" << std::endl; + std::cout << outbStr << std::endl; + + // Generate output rlp-encoded hex + std::string dogGenOutput = dogV.write(); + std::string dogGenHex = HexStr( dogGenOutput.begin(), dogGenOutput.end() ); + + // Inspect type of RLP value -- buffer/array + std::cout << "\nRLPValue type: " << std::endl; + std::cout << uvTypeName( dogV.type() ) << "\n\n" << std::endl; + + + + std::string catIns = "cat"; + std::string catOuts = "83636174"; + + RLPValue catV = RLPValue(catIns); + + // Generate output rlp-encoded hex + std::string catGenOutput = catV.write(); + std::string catGenHex = HexStr( catGenOutput.begin(), catGenOutput.end() ); + + std::cout << "Cat to RLP:" << std::endl; + std::cout << catGenHex.c_str() << std::endl; + + std::cout << "\nRLPValue type: " << std::endl; + std::cout << uvTypeName( dogV.type() ) << std::endl; + + return 0; +} diff --git a/libraries/fc/vendor/rlpvalue/pc/librlpvalue-uninstalled.pc.in b/libraries/fc/vendor/rlpvalue/pc/librlpvalue-uninstalled.pc.in new file mode 100644 index 00000000..484bccfc --- /dev/null +++ b/libraries/fc/vendor/rlpvalue/pc/librlpvalue-uninstalled.pc.in @@ -0,0 +1,9 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: librlpvalue +Description: librlpvalue, C++ universal value object and JSON library +Version: @VERSION@ +Libs: ${pc_top_builddir}/${pcfiledir}/librlpvalue.la diff --git a/libraries/fc/vendor/rlpvalue/pc/librlpvalue.pc.in b/libraries/fc/vendor/rlpvalue/pc/librlpvalue.pc.in new file mode 100644 index 00000000..faf5e647 --- /dev/null +++ b/libraries/fc/vendor/rlpvalue/pc/librlpvalue.pc.in @@ -0,0 +1,10 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: librlpvalue +Description: librlpvalue, C++ universal value object and JSON library +Version: @VERSION@ +Libs: -L${libdir} -lrlpvalue +Cflags: -I${includedir} diff --git a/libraries/fc/vendor/rlpvalue/src/.gitignore b/libraries/fc/vendor/rlpvalue/src/.gitignore new file mode 100644 index 00000000..771e1508 --- /dev/null +++ b/libraries/fc/vendor/rlpvalue/src/.gitignore @@ -0,0 +1,3 @@ + +rlp + diff --git a/libraries/fc/vendor/rlpvalue/src/InfInt.h b/libraries/fc/vendor/rlpvalue/src/InfInt.h new file mode 100644 index 00000000..14ff2158 --- /dev/null +++ b/libraries/fc/vendor/rlpvalue/src/InfInt.h @@ -0,0 +1,1371 @@ +/* + * InfInt - Arbitrary-Precision Integer Arithmetic Library + * Copyright (C) 2013 Sercan Tutar + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * + * USAGE: + * It is pretty straight forward to use the library. Just create an instance of + * InfInt class and start using it. + * + * Useful methods: + * intSqrt: integer square root operation + * digitAt: returns digit at index + * numberOfDigits: returns number of digits + * size: returns size in bytes + * toString: converts it to a string + * + * There are also conversion methods which allow conversion to primitive types: + * toInt, toLong, toLongLong, toUnsignedInt, toUnsignedLong, toUnsignedLongLong. + * + * You may define INFINT_USE_EXCEPTIONS and library methods will start raising + * InfIntException in case of error instead of writing error messages using + * std::cerr. + * + * See ReadMe.txt for more info. + * + * + * No overflows, happy programmers! + * + */ + +#ifndef INFINT_H_ +#define INFINT_H_ + +#include +#include +#include +#include +#include + +//#include +//#include + +#ifndef LONG_LONG_MIN +#define LONG_LONG_MIN std::numeric_limits::min() +#define LONG_LONG_MAX std::numeric_limits::max() +#define ULONG_LONG_MAX std::numeric_limits::max() +#endif + +#ifdef INFINT_USE_EXCEPTIONS +#include +#endif + +typedef int ELEM_TYPE; +typedef long long PRODUCT_TYPE; +static const ELEM_TYPE BASE = 1000000000; +static const ELEM_TYPE UPPER_BOUND = 999999999; +static const ELEM_TYPE DIGIT_COUNT = 9; +static const int powersOfTen[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000 }; + +#ifdef INFINT_USE_EXCEPTIONS +class InfIntException: public std::exception +{ +public: + InfIntException(const std::string& txt) throw (); + ~InfIntException() throw (); + const char* what() const throw (); +private: + std::string txt; +}; + +inline InfIntException::InfIntException(const std::string& txt) throw () : +std::exception(), txt(txt) +{ +} + +inline InfIntException::~InfIntException() throw () +{ +} + +inline const char* InfIntException::what() const throw () +{ + return txt.c_str(); +} +#endif + +inline static div_t my_div(int num, int denom) +{ + div_t result; + result.quot = num / denom; + result.rem = num - denom * result.quot; + return result; +} + +inline static ldiv_t my_ldiv(long num, long denom) +{ + ldiv_t result; + result.quot = num / denom; + result.rem = num - denom * result.quot; + return result; +} + +inline static lldiv_t my_lldiv(long long num, long long denom) +{ + lldiv_t result; + result.quot = num / denom; + result.rem = num - denom * result.quot; + return result; +} + +class InfInt +{ + friend std::ostream& operator<<(std::ostream &s, const InfInt &n); + friend std::istream& operator>>(std::istream &s, InfInt &val); + +public: + /* constructors */ + InfInt(); + InfInt(const char* c); + InfInt(const std::string& s); + InfInt(int l); + InfInt(long l); + InfInt(long long l); + InfInt(unsigned int l); + InfInt(unsigned long l); + InfInt(unsigned long long l); + InfInt(const InfInt& l); + + /* assignment operators */ + const InfInt& operator=(const char* c); + const InfInt& operator=(const std::string& s); + const InfInt& operator=(int l); + const InfInt& operator=(long l); + const InfInt& operator=(long long l); + const InfInt& operator=(unsigned int l); + const InfInt& operator=(unsigned long l); + const InfInt& operator=(unsigned long long l); + const InfInt& operator=(const InfInt& l); + + /* unary increment/decrement operators */ + const InfInt& operator++(); + const InfInt& operator--(); + InfInt operator++(int); + InfInt operator--(int); + + /* operational assignments */ + const InfInt& operator+=(const InfInt& rhs); + const InfInt& operator-=(const InfInt& rhs); + const InfInt& operator*=(const InfInt& rhs); + const InfInt& operator/=(const InfInt& rhs); // throw + const InfInt& operator%=(const InfInt& rhs); // throw + const InfInt& operator*=(ELEM_TYPE rhs); + + /* operations */ + InfInt operator-() const; + InfInt operator+(const InfInt& rhs) const; + InfInt operator-(const InfInt& rhs) const; + InfInt operator*(const InfInt& rhs) const; + InfInt operator/(const InfInt& rhs) const; // throw + InfInt operator%(const InfInt& rhs) const; // throw + InfInt operator*(ELEM_TYPE rhs) const; + + /* relational operations */ + bool operator==(const InfInt& rhs) const; + bool operator!=(const InfInt& rhs) const; + bool operator<(const InfInt& rhs) const; + bool operator<=(const InfInt& rhs) const; + bool operator>(const InfInt& rhs) const; + bool operator>=(const InfInt& rhs) const; + + /* integer square root */ + InfInt intSqrt() const; // throw + + /* digit operations */ + char digitAt(size_t i) const; // throw + size_t numberOfDigits() const; + + /* size in bytes */ + size_t size() const; + + /* string conversion */ + std::string toString() const; + + /* conversion to primitive types */ + int toInt() const; // throw + long toLong() const; // throw + long long toLongLong() const; // throw + unsigned int toUnsignedInt() const; // throw + unsigned long toUnsignedLong() const; // throw + unsigned long long toUnsignedLongLong() const; // throw + +private: + static ELEM_TYPE dInR(const InfInt& R, const InfInt& D); + static void multiplyByDigit(ELEM_TYPE factor, std::vector& val); + + void correct(bool justCheckLeadingZeros = false, bool hasValidSign = false); + void fromString(const std::string& s); + void optimizeSqrtSearchBounds(InfInt& lo, InfInt& hi) const; + void truncateToBase(); + bool equalizeSigns(); + void removeLeadingZeros(); + + std::vector val; // number with base FACTOR + bool pos; // true if number is positive +}; + +inline InfInt::InfInt() : pos(true) +{ + //PROFINY_SCOPE + val.push_back((ELEM_TYPE) 0); +} + +inline InfInt::InfInt(const char* c) +{ + //PROFINY_SCOPE + fromString(c); +} + +inline InfInt::InfInt(const std::string& s) +{ + //PROFINY_SCOPE + fromString(s); +} + +inline InfInt::InfInt(int l) : pos(l >= 0) +{ + //PROFINY_SCOPE + bool subtractOne = false; + if (l == INT_MIN) + { + subtractOne = true; + ++l; + } + + if (!pos) + { + l = -l; + } + do + { + div_t dt = my_div(l, BASE); + val.push_back((ELEM_TYPE) dt.rem); + l = dt.quot; + } while (l > 0); + + if (subtractOne) + { + --*this; + } +} + +inline InfInt::InfInt(long l) : pos(l >= 0) +{ + //PROFINY_SCOPE + bool subtractOne = false; + if (l == LONG_MIN) + { + subtractOne = true; + ++l; + } + + if (!pos) + { + l = -l; + } + do + { + ldiv_t dt = my_ldiv(l, BASE); + val.push_back((ELEM_TYPE) dt.rem); + l = dt.quot; + } while (l > 0); + + if (subtractOne) + { + --*this; + } +} + +inline InfInt::InfInt(long long l) : pos(l >= 0) +{ + //PROFINY_SCOPE + bool subtractOne = false; + if (l == LONG_LONG_MIN) + { + subtractOne = true; + ++l; + } + + if (!pos) + { + l = -l; + } + do + { + lldiv_t dt = my_lldiv(l, BASE); + val.push_back((ELEM_TYPE) dt.rem); + l = dt.quot; + } while (l > 0); + + if (subtractOne) + { + --*this; + } +} + +inline InfInt::InfInt(unsigned int l) : pos(true) +{ + //PROFINY_SCOPE + do + { + val.push_back((ELEM_TYPE) (l % BASE)); + l = l / BASE; + } while (l > 0); +} + +inline InfInt::InfInt(unsigned long l) : pos(true) +{ + //PROFINY_SCOPE + do + { + val.push_back((ELEM_TYPE) (l % BASE)); + l = l / BASE; + } while (l > 0); +} + +inline InfInt::InfInt(unsigned long long l) : pos(true) +{ + //PROFINY_SCOPE + do + { + val.push_back((ELEM_TYPE) (l % BASE)); + l = l / BASE; + } while (l > 0); +} + +inline InfInt::InfInt(const InfInt& l) : val(l.val), pos(l.pos) +{ + //PROFINY_SCOPE +} + +inline const InfInt& InfInt::operator=(const char* c) +{ + //PROFINY_SCOPE + fromString(c); + return *this; +} + +inline const InfInt& InfInt::operator=(const std::string& s) +{ + //PROFINY_SCOPE + fromString(s); + return *this; +} + +inline const InfInt& InfInt::operator=(int l) +{ + //PROFINY_SCOPE + bool subtractOne = false; + if (l == INT_MIN) + { + subtractOne = true; + ++l; + } + + pos = l >= 0; + val.clear(); + if (!pos) + { + l = -l; + } + do + { + div_t dt = my_div(l, BASE); + val.push_back((ELEM_TYPE) dt.rem); + l = dt.quot; + } while (l > 0); + + return subtractOne ? --*this : *this; +} + +inline const InfInt& InfInt::operator=(long l) +{ + //PROFINY_SCOPE + bool subtractOne = false; + if (l == LONG_MIN) + { + subtractOne = true; + ++l; + } + + pos = l >= 0; + val.clear(); + if (!pos) + { + l = -l; + } + do + { + ldiv_t dt = my_ldiv(l, BASE); + val.push_back((ELEM_TYPE) dt.rem); + l = dt.quot; + } while (l > 0); + + return subtractOne ? --*this : *this; +} + +inline const InfInt& InfInt::operator=(long long l) +{ + //PROFINY_SCOPE + bool subtractOne = false; + if (l == LONG_LONG_MIN) + { + subtractOne = true; + ++l; + } + + pos = l >= 0; + val.clear(); + if (!pos) + { + l = -l; + } + do + { + lldiv_t dt = my_lldiv(l, BASE); + val.push_back((ELEM_TYPE) dt.rem); + l = dt.quot; + } while (l > 0); + + return subtractOne ? --*this : *this; +} + +inline const InfInt& InfInt::operator=(unsigned int l) +{ + //PROFINY_SCOPE + pos = true; + val.clear(); + do + { + val.push_back((ELEM_TYPE) (l % BASE)); + l = l / BASE; + } while (l > 0); + return *this; +} + +inline const InfInt& InfInt::operator=(unsigned long l) +{ + //PROFINY_SCOPE + pos = true; + val.clear(); + do + { + val.push_back((ELEM_TYPE) (l % BASE)); + l = l / BASE; + } while (l > 0); + return *this; +} + +inline const InfInt& InfInt::operator=(unsigned long long l) +{ + //PROFINY_SCOPE + pos = true; + val.clear(); + do + { + val.push_back((ELEM_TYPE) (l % BASE)); + l = l / BASE; + } while (l > 0); + return *this; +} + +inline const InfInt& InfInt::operator=(const InfInt& l) +{ + //PROFINY_SCOPE + pos = l.pos; + val = l.val; + return *this; +} + +inline const InfInt& InfInt::operator++() +{ + //PROFINY_SCOPE + val[0] += (pos ? 1 : -1); + this->correct(false, true); + return *this; +} + +inline const InfInt& InfInt::operator--() +{ + //PROFINY_SCOPE + val[0] -= (pos ? 1 : -1); + this->correct(false, true); + return *this; +} + +inline InfInt InfInt::operator++(int) +{ + //PROFINY_SCOPE + InfInt result = *this; + val[0] += (pos ? 1 : -1); + this->correct(false, true); + return result; +} + +inline InfInt InfInt::operator--(int) +{ + //PROFINY_SCOPE + InfInt result = *this; + val[0] -= (pos ? 1 : -1); + this->correct(false, true); + return result; +} + +inline const InfInt& InfInt::operator+=(const InfInt& rhs) +{ + //PROFINY_SCOPE + if (rhs.val.size() > val.size()) + { + val.resize(rhs.val.size(), 0); + } + for (size_t i = 0; i < val.size(); ++i) + { + val[i] = (pos ? val[i] : -val[i]) + (i < rhs.val.size() ? (rhs.pos ? rhs.val[i] : -rhs.val[i]) : 0); + } + correct(); + return *this; +} + +inline const InfInt& InfInt::operator-=(const InfInt& rhs) +{ + //PROFINY_SCOPE + if (rhs.val.size() > val.size()) + { + val.resize(rhs.val.size(), 0); + } + for (size_t i = 0; i < val.size(); ++i) + { + val[i] = (pos ? val[i] : -val[i]) - (i < rhs.val.size() ? (rhs.pos ? rhs.val[i] : -rhs.val[i]) : 0); + } + correct(); + return *this; +} + +inline const InfInt& InfInt::operator*=(const InfInt& rhs) +{ + //PROFINY_SCOPE + // TODO: optimize (do not use operator*) + *this = *this * rhs; + return *this; +} + +inline const InfInt& InfInt::operator/=(const InfInt& rhs) +{ + //PROFINY_SCOPE + if (rhs == 0) + { +#ifdef INFINT_USE_EXCEPTIONS + throw InfIntException("division by zero"); +#else + std::cerr << "Division by zero!" << std::endl; + return *this; +#endif + } + InfInt R, D = (rhs.pos ? rhs : -rhs), N = (pos ? *this : -*this); + bool oldpos = pos; + std::fill(val.begin(), val.end(), 0); + for (int i = (int) N.val.size() - 1; i >= 0; --i) + { + R.val.insert(R.val.begin(), N.val[i]); + R.correct(true); + ELEM_TYPE cnt = dInR(R, D); + R -= D * cnt; + val[i] += cnt; + } + correct(); + pos = (val.size() == 1 && val[0] == 0) ? true : (oldpos == rhs.pos); + return *this; +} + +inline const InfInt& InfInt::operator%=(const InfInt& rhs) +{ + //PROFINY_SCOPE + // TODO: optimize (do not use operator%) + *this = *this % rhs; + return *this; +// if (rhs == 0) +// { +//#ifdef INFINT_USE_EXCEPTIONS +// throw InfIntException("division by zero"); +//#else +// std::cerr << "Division by zero!" << std::endl; +// return *this; +//#endif +// } +// InfInt D = (rhs.pos ? rhs : -rhs), N = (pos ? *this : -*this); +// bool oldpos = pos; +// val.clear(); +// for (int i = (int) N.val.size() - 1; i >= 0; --i) +// { +// val.insert(val.begin(), N.val[i]); +// correct(true); +// *this -= D * dInR(*this, D); +// } +// correct(); +// pos = (val.size() == 1 && val[0] == 0) ? true : oldpos; +// return *this; +} + +inline const InfInt& InfInt::operator*=(ELEM_TYPE rhs) +{ + //PROFINY_SCOPE + ELEM_TYPE factor = rhs < 0 ? -rhs : rhs; + bool oldpos = pos; + multiplyByDigit(factor, val); + correct(); + pos = (val.size() == 1 && val[0] == 0) ? true : (oldpos == (rhs >= 0)); + return *this; +} + +inline InfInt InfInt::operator-() const +{ + //PROFINY_SCOPE + InfInt result = *this; + result.pos = !pos; + return result; +} + +inline InfInt InfInt::operator+(const InfInt& rhs) const +{ + //PROFINY_SCOPE + InfInt result; + result.val.resize(val.size() > rhs.val.size() ? val.size() : rhs.val.size(), 0); + for (size_t i = 0; i < val.size() || i < rhs.val.size(); ++i) + { + result.val[i] = (i < val.size() ? (pos ? val[i] : -val[i]) : 0) + (i < rhs.val.size() ? (rhs.pos ? rhs.val[i] : -rhs.val[i]) : 0); + } + result.correct(); + return result; +} + +inline InfInt InfInt::operator-(const InfInt& rhs) const +{ + //PROFINY_SCOPE + InfInt result; + result.val.resize(val.size() > rhs.val.size() ? val.size() : rhs.val.size(), 0); + for (size_t i = 0; i < val.size() || i < rhs.val.size(); ++i) + { + result.val[i] = (i < val.size() ? (pos ? val[i] : -val[i]) : 0) - (i < rhs.val.size() ? (rhs.pos ? rhs.val[i] : -rhs.val[i]) : 0); + } + result.correct(); + return result; +} + +inline InfInt InfInt::operator*(const InfInt& rhs) const +{ + //PROFINY_SCOPE + InfInt result; + result.val.resize(val.size() + rhs.val.size(), 0); + PRODUCT_TYPE carry = 0; + size_t digit = 0; + for (;; ++digit) + { + lldiv_t dt = my_lldiv(carry, BASE); + carry = dt.quot; + result.val[digit] = (ELEM_TYPE) dt.rem; + + bool found = false; + for (size_t i = digit < rhs.val.size() ? 0 : digit - rhs.val.size() + 1; i < val.size() && i <= digit; ++i) + { + PRODUCT_TYPE pval = result.val[digit] + val[i] * (PRODUCT_TYPE) rhs.val[digit - i]; + if (pval >= BASE || pval <= -BASE) + { + lldiv_t dt = my_lldiv(pval, BASE); + carry += dt.quot; + pval = dt.rem; + } + result.val[digit] = (ELEM_TYPE) pval; + found = true; + } + if (!found) + { + break; + } + } + for (; carry > 0; ++digit) + { + lldiv_t dt = my_lldiv(carry, BASE); + result.val[digit] = (ELEM_TYPE) dt.rem; + carry = dt.quot; + } + result.correct(); + result.pos = (result.val.size() == 1 && result.val[0] == 0) ? true : (pos == rhs.pos); + return result; +} + +inline InfInt InfInt::operator/(const InfInt& rhs) const +{ + //PROFINY_SCOPE + if (rhs == 0) + { +#ifdef INFINT_USE_EXCEPTIONS + throw InfIntException("division by zero"); +#else + std::cerr << "Division by zero!" << std::endl; + return 0; +#endif + } + InfInt Q, R, D = (rhs.pos ? rhs : -rhs), N = (pos ? *this : -*this); + Q.val.resize(N.val.size(), 0); + for (int i = (int) N.val.size() - 1; i >= 0; --i) + { + R.val.insert(R.val.begin(), N.val[i]); + R.correct(true); + ELEM_TYPE cnt = dInR(R, D); + R -= D * cnt; + Q.val[i] += cnt; + } + Q.correct(); + Q.pos = (Q.val.size() == 1 && Q.val[0] == 0) ? true : (pos == rhs.pos); + return Q; +} + +inline InfInt InfInt::operator%(const InfInt& rhs) const +{ + //PROFINY_SCOPE + if (rhs == 0) + { +#ifdef INFINT_USE_EXCEPTIONS + throw InfIntException("division by zero"); +#else + std::cerr << "Division by zero!" << std::endl; + return 0; +#endif + } + InfInt R, D = (rhs.pos ? rhs : -rhs), N = (pos ? *this : -*this); + for (int i = (int) N.val.size() - 1; i >= 0; --i) + { + R.val.insert(R.val.begin(), N.val[i]); + R.correct(true); + R -= D * dInR(R, D); + } + R.correct(); + R.pos = (R.val.size() == 1 && R.val[0] == 0) ? true : pos; + return R; +} + +inline InfInt InfInt::operator*(ELEM_TYPE rhs) const +{ + //PROFINY_SCOPE + InfInt result = *this; + ELEM_TYPE factor = rhs < 0 ? -rhs : rhs; + multiplyByDigit(factor, result.val); + result.correct(); + result.pos = (result.val.size() == 1 && result.val[0] == 0) ? true : (pos == (rhs >= 0)); + return result; +} + +inline bool InfInt::operator==(const InfInt& rhs) const +{ + //PROFINY_SCOPE + if (pos != rhs.pos || val.size() != rhs.val.size()) + { + return false; + } + for (int i = (int) val.size() - 1; i >= 0; --i) + { + if (val[i] != rhs.val[i]) + { + return false; + } + } + return true; +} + +inline bool InfInt::operator!=(const InfInt& rhs) const +{ + //PROFINY_SCOPE + if (pos != rhs.pos || val.size() != rhs.val.size()) + { + return true; + } + for (int i = (int) val.size() - 1; i >= 0; --i) + { + if (val[i] != rhs.val[i]) + { + return true; + } + } + return false; +} + +inline bool InfInt::operator<(const InfInt& rhs) const +{ + //PROFINY_SCOPE + if (pos && !rhs.pos) + { + return false; + } + if (!pos && rhs.pos) + { + return true; + } + if (val.size() > rhs.val.size()) + { + return pos ? false : true; + } + if (val.size() < rhs.val.size()) + { + return pos ? true : false; + } + for (int i = (int) val.size() - 1; i >= 0; --i) + { + if (val[i] < rhs.val[i]) + { + return pos ? true : false; + } + if (val[i] > rhs.val[i]) + { + return pos ? false : true; + } + } + return false; +} + +inline bool InfInt::operator<=(const InfInt& rhs) const +{ + //PROFINY_SCOPE + if (pos && !rhs.pos) + { + return false; + } + if (!pos && rhs.pos) + { + return true; + } + if (val.size() > rhs.val.size()) + { + return pos ? false : true; + } + if (val.size() < rhs.val.size()) + { + return pos ? true : false; + } + for (int i = (int) val.size() - 1; i >= 0; --i) + { + if (val[i] < rhs.val[i]) + { + return pos ? true : false; + } + if (val[i] > rhs.val[i]) + { + return pos ? false : true; + } + } + return true; +} + +inline bool InfInt::operator>(const InfInt& rhs) const +{ + //PROFINY_SCOPE + if (pos && !rhs.pos) + { + return true; + } + if (!pos && rhs.pos) + { + return false; + } + if (val.size() > rhs.val.size()) + { + return pos ? true : false; + } + if (val.size() < rhs.val.size()) + { + return pos ? false : true; + } + for (int i = (int) val.size() - 1; i >= 0; --i) + { + if (val[i] < rhs.val[i]) + { + return pos ? false : true; + } + if (val[i] > rhs.val[i]) + { + return pos ? true : false; + } + } + return false; +} + +inline bool InfInt::operator>=(const InfInt& rhs) const +{ + //PROFINY_SCOPE + if (pos && !rhs.pos) + { + return true; + } + if (!pos && rhs.pos) + { + return false; + } + if (val.size() > rhs.val.size()) + { + return pos ? true : false; + } + if (val.size() < rhs.val.size()) + { + return pos ? false : true; + } + for (int i = (int) val.size() - 1; i >= 0; --i) + { + if (val[i] < rhs.val[i]) + { + return pos ? false : true; + } + if (val[i] > rhs.val[i]) + { + return pos ? true : false; + } + } + return true; +} + +inline void InfInt::optimizeSqrtSearchBounds(InfInt& lo, InfInt& hi) const +{ + //PROFINY_SCOPE + InfInt hdn = 1; + for (int i = (int) this->numberOfDigits() / 2; i >= 2; --i) + { + hdn *= 10; + } + if (lo < hdn) + { + lo = hdn; + } + hdn *= 100; + if (hi > hdn) + { + hi = hdn; + } +} + +inline InfInt InfInt::intSqrt() const +{ + //PROFINY_SCOPE + if (*this <= 0) + { +#ifdef INFINT_USE_EXCEPTIONS + throw InfIntException("intSqrt called for non-positive integer"); +#else + std::cerr << "intSqrt called for non-positive integer: " << *this << std::endl; + return 0; +#endif + } + InfInt hi = *this / 2 + 1, lo = 0, mid, mid2; + optimizeSqrtSearchBounds(lo, hi); + do + { + mid = (hi + lo) / 2; // 8 factor + mid2 = mid * mid; // 1 factor + if (mid2 == *this) + { + lo = mid; + break; + } + else if (mid2 < *this) + { + lo = mid; + } + else + { + hi = mid; + } + } while (lo < hi - 1 && mid2 != *this); + return lo; +} + +inline char InfInt::digitAt(size_t i) const +{ + //PROFINY_SCOPE + if (numberOfDigits() <= i) + { +#ifdef INFINT_USE_EXCEPTIONS + throw InfIntException("invalid digit index"); +#else + std::cerr << "Invalid digit index: " << i << std::endl; + return -1; +#endif + } + return (val[i / DIGIT_COUNT] / powersOfTen[i % DIGIT_COUNT]) % 10; +} + +inline size_t InfInt::numberOfDigits() const +{ + //PROFINY_SCOPE + return (val.size() - 1) * DIGIT_COUNT + + (val.back() > 99999999 ? 9 : (val.back() > 9999999 ? 8 : (val.back() > 999999 ? 7 : (val.back() > 99999 ? 6 : + (val.back() > 9999 ? 5 : (val.back() > 999 ? 4 : (val.back() > 99 ? 3 : (val.back() > 9 ? 2 : 1)))))))); +} + +inline std::string InfInt::toString() const +{ + //PROFINY_SCOPE + std::ostringstream oss; + oss << *this; + return oss.str(); +} + +inline size_t InfInt::size() const +{ + //PROFINY_SCOPE + return val.size() * sizeof(ELEM_TYPE) + sizeof(bool); +} + +inline int InfInt::toInt() const +{ + //PROFINY_SCOPE + if (*this > INT_MAX || *this < INT_MIN) + { +#ifdef INFINT_USE_EXCEPTIONS + throw InfIntException("out of bounds"); +#else + std::cerr << "Out of INT bounds: " << *this << std::endl; +#endif + } + int result = 0; + for (int i = (int) val.size() - 1; i >= 0; --i) + { + result = result * BASE + val[i]; + } + return pos ? result : -result; +} + +inline long InfInt::toLong() const +{ + //PROFINY_SCOPE + if (*this > LONG_MAX || *this < LONG_MIN) + { +#ifdef INFINT_USE_EXCEPTIONS + throw InfIntException("out of bounds"); +#else + std::cerr << "Out of LONG bounds: " << *this << std::endl; +#endif + } + long result = 0; + for (int i = (int) val.size() - 1; i >= 0; --i) + { + result = result * BASE + val[i]; + } + return pos ? result : -result; +} + +inline long long InfInt::toLongLong() const +{ + //PROFINY_SCOPE + if (*this > LONG_LONG_MAX || *this < LONG_LONG_MIN) + { +#ifdef INFINT_USE_EXCEPTIONS + throw InfIntException("out of bounds"); +#else + std::cerr << "Out of LLONG bounds: " << *this << std::endl; +#endif + } + long long result = 0; + for (int i = (int) val.size() - 1; i >= 0; --i) + { + result = result * BASE + val[i]; + } + return pos ? result : -result; +} + +inline unsigned int InfInt::toUnsignedInt() const +{ + //PROFINY_SCOPE + if (!pos || *this > UINT_MAX) + { +#ifdef INFINT_USE_EXCEPTIONS + throw InfIntException("out of bounds"); +#else + std::cerr << "Out of UINT bounds: " << *this << std::endl; +#endif + } + unsigned int result = 0; + for (int i = (int) val.size() - 1; i >= 0; --i) + { + result = result * BASE + val[i]; + } + return result; +} + +inline unsigned long InfInt::toUnsignedLong() const +{ + //PROFINY_SCOPE + if (!pos || *this > ULONG_MAX) + { +#ifdef INFINT_USE_EXCEPTIONS + throw InfIntException("out of bounds"); +#else + std::cerr << "Out of ULONG bounds: " << *this << std::endl; +#endif + } + unsigned long result = 0; + for (int i = (int) val.size() - 1; i >= 0; --i) + { + result = result * BASE + val[i]; + } + return result; +} + +inline unsigned long long InfInt::toUnsignedLongLong() const +{ + //PROFINY_SCOPE + if (!pos || *this > ULONG_LONG_MAX) + { +#ifdef INFINT_USE_EXCEPTIONS + throw InfIntException("out of bounds"); +#else + std::cerr << "Out of ULLONG bounds: " << *this << std::endl; +#endif + } + unsigned long long result = 0; + for (int i = (int) val.size() - 1; i >= 0; --i) + { + result = result * BASE + val[i]; + } + return result; +} + +inline void InfInt::truncateToBase() +{ + //PROFINY_SCOPE + for (size_t i = 0; i < val.size(); ++i) // truncate each + { + if (val[i] >= BASE || val[i] <= -BASE) + { + div_t dt = my_div(val[i], BASE); + val[i] = dt.rem; + if (i + 1 >= val.size()) + { + val.push_back(dt.quot); + } + else + { + val[i + 1] += dt.quot; + } + } + } +} + +inline bool InfInt::equalizeSigns() +{ + //PROFINY_SCOPE + bool isPositive = true; + int i = (int) ((val.size())) - 1; + for (; i >= 0; --i) + { + if (val[i] != 0) + { + isPositive = val[i--] > 0; + break; + } + } + + if (isPositive) + { + for (; i >= 0; --i) + { + if (val[i] < 0) + { + int k = 0, index = i + 1; + for (; (size_t)(index) < val.size() && val[index] == 0; ++k, ++index) + ; // count adjacent zeros on left + //if ((size_t)(index) < val.size() && val[index] > 0) + { // number on the left is positive + val[index] -= 1; + val[i] += BASE; + for (; k > 0; --k) + { + val[i + k] = UPPER_BOUND; + } + } + } + } + } + else + { + for (; i >= 0; --i) + { + if (val[i] > 0) + { + int k = 0, index = i + 1; + for (; (size_t)(index) < val.size() && val[index] == 0; ++k, ++index) + ; // count adjacent zeros on right + //if ((size_t)(index) < val.size() && val[index] < 0) + { // number on the left is negative + val[index] += 1; + val[i] -= BASE; + for (; k > 0; --k) + { + val[i + k] = -UPPER_BOUND; + } + } + } + } + } + + return isPositive; +} + +inline void InfInt::removeLeadingZeros() +{ + //PROFINY_SCOPE + for (int i = (int) (val.size()) - 1; i > 0; --i) // remove leading 0's + { + if (val[i] != 0) + { + return; + } + else + { + val.erase(val.begin() + i); + } + } +} + +inline void InfInt::correct(bool justCheckLeadingZeros, bool hasValidSign) +{ + //PROFINY_SCOPE + if (!justCheckLeadingZeros) + { + truncateToBase(); + + if (equalizeSigns()) + { + pos = ((val.size() == 1 && val[0] == 0) || !hasValidSign) ? true : pos; + } + else + { + pos = hasValidSign ? !pos : false; + for (size_t i = 0; i < val.size(); ++i) + { + val[i] = abs(val[i]); + } + } + } + + removeLeadingZeros(); +} + +inline void InfInt::fromString(const std::string& s) +{ + //PROFINY_SCOPE + pos = true; + val.clear(); + val.reserve(s.size() / DIGIT_COUNT + 1); + int i = (int) s.size() - DIGIT_COUNT; + for (; i >= 0; i -= DIGIT_COUNT) + { + val.push_back(atoi(s.substr(i, DIGIT_COUNT).c_str())); + } + if (i > -DIGIT_COUNT) + { + std::string ss = s.substr(0, i + DIGIT_COUNT); + if (ss.size() == 1 && ss[0] == '-') + { + pos = false; + } + else + { + val.push_back(atoi(ss.c_str())); + } + } + if (val.back() < 0) + { + val.back() = -val.back(); + pos = false; + } + correct(true); +} + +inline ELEM_TYPE InfInt::dInR(const InfInt& R, const InfInt& D) +{ + //PROFINY_SCOPE + ELEM_TYPE min = 0, max = UPPER_BOUND; + while (max > min) + { + ELEM_TYPE avg = max + min; + div_t dt = my_div(avg, 2); + avg = dt.rem ? (dt.quot + 1) : dt.quot; + InfInt prod = D * avg; + if (R == prod) + { + return avg; + } + else if (R > prod) + { + min = avg; + } + else + { + max = avg - 1; + } + } + return min; +} + +inline void InfInt::multiplyByDigit(ELEM_TYPE factor, std::vector& val) +{ + //PROFINY_SCOPE + ELEM_TYPE carry = 0; + for (size_t i = 0; i < val.size(); ++i) + { + PRODUCT_TYPE pval = val[i] * (PRODUCT_TYPE) factor + carry; + if (pval >= BASE || pval <= -BASE) + { + lldiv_t dt = my_lldiv(pval, BASE); + carry = (ELEM_TYPE) dt.quot; + pval = dt.rem; + } + else + { + carry = 0; + } + val[i] = (ELEM_TYPE) pval; + } + if (carry > 0) + { + val.push_back(carry); + } +} + +/**************************************************************/ +/******************** NON-MEMBER OPERATORS ********************/ +/**************************************************************/ + +inline std::istream& operator>>(std::istream &s, InfInt &n) +{ + //PROFINY_SCOPE + std::string str; + s >> str; + n.fromString(str); + return s; +} + +inline std::ostream& operator<<(std::ostream &s, const InfInt &n) +{ + //PROFINY_SCOPE + if (!n.pos) + { + s << '-'; + } + bool first = true; + for (int i = (int) n.val.size() - 1; i >= 0; --i) + { + if (first) + { + s << n.val[i]; + first = false; + } + else + { + s << std::setfill('0') << std::setw(DIGIT_COUNT) << n.val[i]; + } + } + return s; +} + +#endif diff --git a/libraries/fc/vendor/rlpvalue/src/rlp2json.cpp b/libraries/fc/vendor/rlpvalue/src/rlp2json.cpp new file mode 100644 index 00000000..c50ede3c --- /dev/null +++ b/libraries/fc/vendor/rlpvalue/src/rlp2json.cpp @@ -0,0 +1,107 @@ + +#include +#include +#include "rlpvalue.h" +#include "InfInt.h" + +extern void RLPtoJSON(const RLPValue& rval, UniValue& jval); +extern std::string encodeBinary(uint64_t n); + +static void assignJsonArray(UniValue& jval, const RLPValue& rval) +{ + jval.setArray(); + + const std::vector& values = rval.getValues(); + for (auto it = values.begin(); it != values.end(); it++) { + const RLPValue& childVal = *it; + UniValue childJval; + + RLPtoJSON(childVal, childJval); + + jval.push_back(childJval); + } +} + +static void assignJsonBuffer(UniValue& jval, const RLPValue& rval) +{ + jval.setStr(rval.getValStr()); +} + +void RLPtoJSON(const RLPValue& rval, UniValue& jval) +{ + if (rval.isBuffer()) + assignJsonBuffer(jval, rval); + else + assignJsonArray(jval, rval); +} + +static bool isBigNumStr(const std::string& s) +{ + // first char must be # + if (s.empty() || s[0] != '#') + return false; + + // remaining chars must be digits + for (unsigned int i = 1; i < s.size(); i++) + if (!isdigit(s[i])) + return false; + + return true; +} + +static std::string encodeBigNum(const InfInt& n) +{ + std::string rs; + + if (n == 0) { + // do nothing; return empty string + } else { + rs.assign(encodeBigNum(n / 256)); + + InfInt iich = n % 256; + unsigned char ch = iich.toUnsignedLong(); + rs.append((const char *) &ch, 1); + } + + return rs; +} + +static std::string encodeBigNumStr(const std::string& s) +{ + InfInt n(s); + return encodeBigNum(n); +} + +bool JSONtoRLP(const UniValue& jval, RLPValue& rval) +{ + if (jval.isStr()) { + std::string ins = jval.getValStr(); + if (isBigNumStr(ins)) + ins = encodeBigNumStr(ins.substr(1)); + + rval.assign(ins); + return true; + } + + if (jval.isNum()) { + uint64_t val = jval.get_int64(); + std::string val_enc = encodeBinary(val); + rval.assign(val_enc); + return true; + } + + if (jval.isArray()) { + rval.setArray(); + const std::vector& arrVals = jval.getValues(); + for (auto it = arrVals.begin(); it != arrVals.end(); it++) { + const UniValue& childJval = *it; + RLPValue tmp; + if (!JSONtoRLP(childJval, tmp)) + return false; + rval.push_back(tmp); + } + return true; + } + + return false; +} diff --git a/libraries/fc/vendor/rlpvalue/src/tool.cpp b/libraries/fc/vendor/rlpvalue/src/tool.cpp new file mode 100644 index 00000000..d17158e7 --- /dev/null +++ b/libraries/fc/vendor/rlpvalue/src/tool.cpp @@ -0,0 +1,189 @@ + +/* + * Copyright 2019 Bloq Inc. + * + */ + +#ifndef HAVE_CONFIG_H +#error missing autoconf-generated config.h. +#endif +#include "rlpvalue-config.h" + +#include +#include +#include +#include +#include "rlpvalue.h" +#include "../test/utilstrencodings.h" + +using namespace std; + +extern void RLPtoJSON(const RLPValue& rval, UniValue& jval); +extern bool JSONtoRLP(const UniValue& jval, RLPValue& rval); + +static const char doc[] = +"rlp - encode or decode RLP protocol encoding"; + +static struct argp_option options[] = { + { "decode", 'd', NULL, 0, + "Decode RLP to JSON" }, + { "encode", 'e', NULL, 0, + "Encode JSON to RLP (default)" }, + { } +}; + +static error_t parse_opt (int key, char *arg, struct argp_state *state); +static const struct argp argp = { options, parse_opt, NULL, doc }; + +static bool opt_decode = false; +static bool inp_json, inp_rlp, outp_json, outp_rlp; +static vector file_args; +static UniValue global_jval; +static RLPValue global_rval; + +static error_t parse_opt (int key, char *arg, struct argp_state *state) +{ + switch (key) { + case 'd': opt_decode = true; break; + case 'e': opt_decode = false; break; + + case ARGP_KEY_ARG: + file_args.push_back(arg); + break; + + default: + return ARGP_ERR_UNKNOWN; + } + + return 0; +} + +static bool parseJsonInput(const std::string& body) +{ + bool rc = global_jval.read(body); + + if (!rc) + fprintf(stderr, "JSON input validation failed\n"); + + return rc; +} + +static bool parseRlpInput(const std::string& body) +{ + std::vector buf; + + if (body.substr(0, 2) == "0x") { + string tmp = body.substr(2); + buf = ParseHex(tmp); + } else + buf = ParseHex(body); + + size_t consumed, wanted; + bool rc = global_rval.read(&buf[0], buf.size(), consumed, wanted); + + if (!rc) + fprintf(stderr, "RLP input validation failed (%zu wanted)\n", + wanted); + + return rc; +} + +static bool readInput() +{ + if (opt_decode) { + inp_json = false; + inp_rlp = true; + outp_json = true; + outp_rlp = false; + } else { + inp_json = true; + inp_rlp = false; + outp_json = false; + outp_rlp = true; + } + + const char *filename = nullptr; + FILE *inf; + if (file_args.empty()) { + filename = "(standard input)"; + inf = stdin; + } else { + filename = file_args[0].c_str(); + inf = ::fopen(filename, "r"); + if (!inf) { + perror(filename); + return false; + } + } + + string body; + + while (1) { + vector buf(4096); + size_t rrc = fread(&buf[0], 1, buf.size(), inf); + body.append((char *) &buf[0], rrc); + if (rrc < buf.size()) + break; + } + bool haveErr = ferror(inf); + if (inf != stdin) + fclose(inf); + + if (haveErr) { + perror(filename); + return false; + } + + if (inp_json) + return parseJsonInput(body); + else + return parseRlpInput(body); +} + +static bool mutateInput() +{ + if (inp_rlp) + RLPtoJSON(global_rval, global_jval); + else + JSONtoRLP(global_jval, global_rval); + return true; +} + +static bool writeJsonOutput() +{ + string body = global_jval.write(2); + printf("%s\n", body.c_str()); + return true; +} + +static bool writeRlpOutput() +{ + string body = global_rval.write(); + string hex = HexStr(body.begin(), body.end()); + printf("%s\n", hex.c_str()); + return true; +} + +static bool writeOutput() +{ + if (outp_json) + return writeJsonOutput(); + else + return writeRlpOutput(); +} + +int main (int argc, char *argv[]) +{ + error_t argp_rc = argp_parse(&argp, argc, argv, 0, NULL, NULL); + if (argp_rc) { + fprintf(stderr, "%s: argp_parse failed: %s\n", + argv[0], strerror(argp_rc)); + return EXIT_FAILURE; + } + + if (!readInput() || !mutateInput() || !writeOutput()) + return 1; + + return 0; +} + diff --git a/libraries/fc/vendor/rlpvalue/test/.gitignore b/libraries/fc/vendor/rlpvalue/test/.gitignore new file mode 100644 index 00000000..7b27cf0d --- /dev/null +++ b/libraries/fc/vendor/rlpvalue/test/.gitignore @@ -0,0 +1,8 @@ + +object +unitester +test_json +no_nul + +*.trs +*.log diff --git a/libraries/fc/vendor/rlpvalue/test/data/example.json b/libraries/fc/vendor/rlpvalue/test/data/example.json new file mode 100644 index 00000000..e395204d --- /dev/null +++ b/libraries/fc/vendor/rlpvalue/test/data/example.json @@ -0,0 +1,6 @@ +{ + "listsoflists2": { + "in": "VALID", + "out": "c7c0c1c0c3c0c1c0" + } +} diff --git a/libraries/fc/vendor/rlpvalue/test/data/invalidRLPTest.json b/libraries/fc/vendor/rlpvalue/test/data/invalidRLPTest.json new file mode 100644 index 00000000..1f9b806c --- /dev/null +++ b/libraries/fc/vendor/rlpvalue/test/data/invalidRLPTest.json @@ -0,0 +1,46 @@ +{ + "int32Overflow": { + "in": "INVALID", + "out": "bf0f000000000000021111" + }, + + "int32Overflow2": { + "in": "INVALID", + "out": "ff0f000000000000021111" + }, + + "wrongSizeList": { + "in": "INVALID", + "out": "f80180" + }, + + "wrongSizeList2": { + "in": "INVALID", + "out": "f80100" + }, + + "incorrectLengthInArray": { + "in": "INVALID", + "out": "b9002100dc2b275d0f74e8a53e6f4ec61b27f24278820be3f82ea2110e582081b0565df0" + }, + + "randomRLP": { + "in": "INVALID", + "out": "f861f83eb9002100dc2b275d0f74e8a53e6f4ec61b27f24278820be3f82ea2110e582081b0565df027b90015002d5ef8325ae4d034df55d4b58d0dfba64d61ddd17be00000b9001a00dae30907045a2f66fa36f2bb8aa9029cbb0b8a7b3b5c435ab331" + }, + + "bytesShouldBeSingleByte00": { + "in": "INVALID", + "out": "8100" + }, + + "bytesShouldBeSingleByte01": { + "in": "INVALID", + "out": "8101" + }, + + "bytesShouldBeSingleByte7F": { + "in": "INVALID", + "out": "817F" + } +} diff --git a/libraries/fc/vendor/rlpvalue/test/data/longlist.json b/libraries/fc/vendor/rlpvalue/test/data/longlist.json new file mode 100644 index 00000000..525fe167 --- /dev/null +++ b/libraries/fc/vendor/rlpvalue/test/data/longlist.json @@ -0,0 +1,48 @@ +{ + "longList1" : { + "in" : [ + ["asdf","qwer","zxcv"], + ["asdf","qwer","zxcv"], + ["asdf","qwer","zxcv"], + ["asdf","qwer","zxcv"] + ], + "out": "0xf840cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376" + }, + "longList2" : { + "in" : [ + ["asdf","qwer","zxcv"], + ["asdf","qwer","zxcv"], + ["asdf","qwer","zxcv"], + ["asdf","qwer","zxcv"], + ["asdf","qwer","zxcv"], + ["asdf","qwer","zxcv"], + ["asdf","qwer","zxcv"], + ["asdf","qwer","zxcv"], + ["asdf","qwer","zxcv"], + ["asdf","qwer","zxcv"], + ["asdf","qwer","zxcv"], + ["asdf","qwer","zxcv"], + ["asdf","qwer","zxcv"], + ["asdf","qwer","zxcv"], + ["asdf","qwer","zxcv"], + ["asdf","qwer","zxcv"], + ["asdf","qwer","zxcv"], + ["asdf","qwer","zxcv"], + ["asdf","qwer","zxcv"], + ["asdf","qwer","zxcv"], + ["asdf","qwer","zxcv"], + ["asdf","qwer","zxcv"], + ["asdf","qwer","zxcv"], + ["asdf","qwer","zxcv"], + ["asdf","qwer","zxcv"], + ["asdf","qwer","zxcv"], + ["asdf","qwer","zxcv"], + ["asdf","qwer","zxcv"], + ["asdf","qwer","zxcv"], + ["asdf","qwer","zxcv"], + ["asdf","qwer","zxcv"], + ["asdf","qwer","zxcv"] + ], + "out": "0xf90200cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376" + } +} diff --git a/libraries/fc/vendor/rlpvalue/test/data/rlptest.json b/libraries/fc/vendor/rlpvalue/test/data/rlptest.json new file mode 100644 index 00000000..725022de --- /dev/null +++ b/libraries/fc/vendor/rlpvalue/test/data/rlptest.json @@ -0,0 +1,111 @@ +{ + "emptystring": { + "in": "", + "out": "0x80" + }, + "bytestring00": { + "in": "\u0000", + "out": "0x00" + }, + "bytestring01": { + "in": "\u0001", + "out": "0x01" + }, + "bytestring7F": { + "in": "\u007F", + "out": "0x7f" + }, + "shortstring": { + "in": "dog", + "out": "0x83646f67" + }, + "shortstring2": { + "in": "Lorem ipsum dolor sit amet, consectetur adipisicing eli", + "out": "0xb74c6f72656d20697073756d20646f6c6f722073697420616d65742c20636f6e7365637465747572206164697069736963696e6720656c69" + }, + "longstring": { + "in": "Lorem ipsum dolor sit amet, consectetur adipisicing elit", + "out": "0xb8384c6f72656d20697073756d20646f6c6f722073697420616d65742c20636f6e7365637465747572206164697069736963696e6720656c6974" + }, + "longstring2": { + "in": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur mauris magna, suscipit sed vehicula non, iaculis faucibus tortor. Proin suscipit ultricies malesuada. Duis tortor elit, dictum quis tristique eu, ultrices at risus. Morbi a est imperdiet mi ullamcorper aliquet suscipit nec lorem. Aenean quis leo mollis, vulputate elit varius, consequat enim. Nulla ultrices turpis justo, et posuere urna consectetur nec. Proin non convallis metus. Donec tempor ipsum in mauris congue sollicitudin. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Suspendisse convallis sem vel massa faucibus, eget lacinia lacus tempor. Nulla quis ultricies purus. Proin auctor rhoncus nibh condimentum mollis. Aliquam consequat enim at metus luctus, a eleifend purus egestas. Curabitur at nibh metus. Nam bibendum, neque at auctor tristique, lorem libero aliquet arcu, non interdum tellus lectus sit amet eros. Cras rhoncus, metus ac ornare cursus, dolor justo ultrices metus, at ullamcorper volutpat", + "out": "0xb904004c6f72656d20697073756d20646f6c6f722073697420616d65742c20636f6e73656374657475722061646970697363696e6720656c69742e20437572616269747572206d6175726973206d61676e612c20737573636970697420736564207665686963756c61206e6f6e2c20696163756c697320666175636962757320746f72746f722e2050726f696e20737573636970697420756c74726963696573206d616c6573756164612e204475697320746f72746f7220656c69742c2064696374756d2071756973207472697374697175652065752c20756c7472696365732061742072697375732e204d6f72626920612065737420696d70657264696574206d6920756c6c616d636f7270657220616c6971756574207375736369706974206e6563206c6f72656d2e2041656e65616e2071756973206c656f206d6f6c6c69732c2076756c70757461746520656c6974207661726975732c20636f6e73657175617420656e696d2e204e756c6c6120756c74726963657320747572706973206a7573746f2c20657420706f73756572652075726e6120636f6e7365637465747572206e65632e2050726f696e206e6f6e20636f6e76616c6c6973206d657475732e20446f6e65632074656d706f7220697073756d20696e206d617572697320636f6e67756520736f6c6c696369747564696e2e20566573746962756c756d20616e746520697073756d207072696d697320696e206661756369627573206f726369206c756374757320657420756c74726963657320706f737565726520637562696c69612043757261653b2053757370656e646973736520636f6e76616c6c69732073656d2076656c206d617373612066617563696275732c2065676574206c6163696e6961206c616375732074656d706f722e204e756c6c61207175697320756c747269636965732070757275732e2050726f696e20617563746f722072686f6e637573206e69626820636f6e64696d656e74756d206d6f6c6c69732e20416c697175616d20636f6e73657175617420656e696d206174206d65747573206c75637475732c206120656c656966656e6420707572757320656765737461732e20437572616269747572206174206e696268206d657475732e204e616d20626962656e64756d2c206e6571756520617420617563746f72207472697374697175652c206c6f72656d206c696265726f20616c697175657420617263752c206e6f6e20696e74657264756d2074656c6c7573206c65637475732073697420616d65742065726f732e20437261732072686f6e6375732c206d65747573206163206f726e617265206375727375732c20646f6c6f72206a7573746f20756c747269636573206d657475732c20617420756c6c616d636f7270657220766f6c7574706174" + }, + "zero": { + "in": 0, + "out": "0x80" + }, + "smallint": { + "in": 1, + "out": "0x01" + }, + "smallint2": { + "in": 16, + "out": "0x10" + }, + "smallint3": { + "in": 79, + "out": "0x4f" + }, + "smallint4": { + "in": 127, + "out": "0x7f" + }, + "mediumint1": { + "in": 128, + "out": "0x8180" + }, + "mediumint2": { + "in": 1000, + "out": "0x8203e8" + }, + "mediumint3": { + "in": 100000, + "out": "0x830186a0" + }, + "mediumint4": { + "in": "#83729609699884896815286331701780722", + "out": "0x8f102030405060708090a0b0c0d0e0f2" + }, + "mediumint5": { + "in": "#105315505618206987246253880190783558935785933862974822347068935681", + "out": "0x9c0100020003000400050006000700080009000a000b000c000d000e01" + }, + "emptylist": { + "in": [], + "out": "0xc0" + }, + "stringlist": { + "in": [ "dog", "god", "cat" ], + "out": "0xcc83646f6783676f6483636174" + }, + "multilist": { + "in": [ "zw", [ 4 ], 1 ], + "out": "0xc6827a77c10401" + }, + "shortListMax1": { + "in": [ "asdf", "qwer", "zxcv", "asdf","qwer", "zxcv", "asdf", "qwer", "zxcv", "asdf", "qwer"], + "out": "0xf784617364668471776572847a78637684617364668471776572847a78637684617364668471776572847a78637684617364668471776572" + }, + "listsoflists": { + "in": [ [ [], [] ], [] ], + "out": "0xc4c2c0c0c0" + }, + "listsoflists2": { + "in": [ [], [[]], [ [], [[]] ] ], + "out": "0xc7c0c1c0c3c0c1c0" + }, + "dictTest1" : { + "in" : [ + ["key1", "val1"], + ["key2", "val2"], + ["key3", "val3"], + ["key4", "val4"] + ], + "out" : "0xecca846b6579318476616c31ca846b6579328476616c32ca846b6579338476616c33ca846b6579348476616c34" + }, + "bigint": { + "in": "#115792089237316195423570985008687907853269984665640564039457584007913129639936", + "out": "0xa1010000000000000000000000000000000000000000000000000000000000000000" + } +} diff --git a/libraries/fc/vendor/rlpvalue/test/object.cpp b/libraries/fc/vendor/rlpvalue/test/object.cpp new file mode 100644 index 00000000..9918f659 --- /dev/null +++ b/libraries/fc/vendor/rlpvalue/test/object.cpp @@ -0,0 +1,171 @@ +// Copyright (c) 2014 BitPay Inc. +// Copyright (c) 2014-2016 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or https://opensource.org/licenses/mit-license.php. + +#include +#include +#include +#include +#include +#include +#include +#include + +#define BOOST_FIXTURE_TEST_SUITE(a, b) +#define BOOST_AUTO_TEST_CASE(funcName) void funcName() +#define BOOST_AUTO_TEST_SUITE_END() +#define BOOST_CHECK(expr) assert(expr) +#define BOOST_CHECK_EQUAL(v1, v2) assert((v1) == (v2)) +#define BOOST_CHECK_THROW(stmt, excMatch) { \ + try { \ + (stmt); \ + assert(0 && "No exception caught"); \ + } catch (excMatch & e) { \ + } catch (...) { \ + assert(0 && "Wrong exception caught"); \ + } \ + } +#define BOOST_CHECK_NO_THROW(stmt) { \ + try { \ + (stmt); \ + } catch (...) { \ + assert(0); \ + } \ + } + +BOOST_FIXTURE_TEST_SUITE(rlpvalue_tests, BasicTestingSetup) + +BOOST_AUTO_TEST_CASE(rlpvalue_constructor) +{ + RLPValue v2(RLPValue::VBUF); + BOOST_CHECK(v2.isBuffer()); + + RLPValue v3(RLPValue::VBUF); + v3.assign("foo"); + BOOST_CHECK(v3.isBuffer()); + BOOST_CHECK_EQUAL(v3.getValStr(), "foo"); + + std::string vs("yawn"); + RLPValue v8(vs); + BOOST_CHECK(v8.isBuffer()); + BOOST_CHECK_EQUAL(v8.getValStr(), "yawn"); + + const char *vcs = "zappa"; + RLPValue v9(vcs); + BOOST_CHECK(v9.isBuffer()); + BOOST_CHECK_EQUAL(v9.getValStr(), "zappa"); +} + +BOOST_AUTO_TEST_CASE(rlpvalue_set) +{ + RLPValue v("foo"); + v.clear(); + BOOST_CHECK_EQUAL(v.getValStr(), ""); + + BOOST_CHECK(v.setArray()); + BOOST_CHECK(v.isArray()); + BOOST_CHECK_EQUAL(v.size(), 0); + + v.assign("zum"); + BOOST_CHECK(v.isBuffer()); + BOOST_CHECK_EQUAL(v.getValStr(), "zum"); +} + +BOOST_AUTO_TEST_CASE(rlpvalue_array) +{ + RLPValue arr(RLPValue::VARR); + + std::string vStr("zippy"); + BOOST_CHECK(arr.push_back(vStr)); + + const char *s = "pippy"; + BOOST_CHECK(arr.push_back(s)); + + RLPValue v; + + std::vector vec; + v.assign("boing"); + vec.push_back(v); + + v.assign("going"); + vec.push_back(v); + + BOOST_CHECK(arr.push_backV(vec)); + + BOOST_CHECK_EQUAL(arr.empty(), false); + BOOST_CHECK_EQUAL(arr.size(), 4); + + BOOST_CHECK_EQUAL(arr[0].getValStr(), "zippy"); + BOOST_CHECK_EQUAL(arr[1].getValStr(), "pippy"); + BOOST_CHECK_EQUAL(arr[2].getValStr(), "boing"); + BOOST_CHECK_EQUAL(arr[3].getValStr(), "going"); + + BOOST_CHECK_EQUAL(arr[999].getValStr(), ""); + + arr.clear(); + BOOST_CHECK(arr.empty()); + BOOST_CHECK_EQUAL(arr.size(), 0); +} + +BOOST_AUTO_TEST_CASE(rlpvalue_readwrite) +{ + unsigned char s1[] = { 0x83, 'd', 'o', 'g' }; + + RLPValue v; + size_t consumed, wanted; + bool rc = v.read(&s1[0], sizeof(s1), consumed, wanted); + BOOST_CHECK(rc); + BOOST_CHECK(v.isBuffer()); + BOOST_CHECK_EQUAL(v.getValStr(), "dog"); + BOOST_CHECK_EQUAL(consumed, sizeof(s1)); + BOOST_CHECK_EQUAL(wanted, 0); + + std::string s1_out = v.write(); + BOOST_CHECK_EQUAL(sizeof(s1), s1_out.size()); + BOOST_CHECK_EQUAL(memcmp(&s1[0], &s1_out[0], sizeof(s1)), 0); + + unsigned char s2[] = + { 0xc8, 0x83, 'c', 'a', 't', 0x83, 'd', 'o', 'g' }; + + RLPValue v2; + rc = v2.read(&s2[0], sizeof(s2), consumed, wanted); + BOOST_CHECK(rc); + BOOST_CHECK(v2.isArray()); + BOOST_CHECK_EQUAL(consumed, sizeof(s2)); + BOOST_CHECK_EQUAL(wanted, 0); + BOOST_CHECK_EQUAL(v2[0].getValStr(), "cat"); + BOOST_CHECK_EQUAL(v2[1].getValStr(), "dog"); + + std::string s2_out = v2.write(); + BOOST_CHECK_EQUAL(sizeof(s2), s2_out.size()); + BOOST_CHECK_EQUAL(memcmp(&s2[0], &s2_out[0], sizeof(s2)), 0); + + unsigned char s_empty_list[] = { 0xc0 }; + RLPValue v_empty_list; + rc = v_empty_list.read(&s_empty_list[0], sizeof(s_empty_list), consumed, wanted); + BOOST_CHECK(rc); + BOOST_CHECK(v_empty_list.isArray()); + BOOST_CHECK_EQUAL(v_empty_list.size(), 0); + + unsigned char s_null[] = { 0x80 }; + RLPValue v_null; + rc = v_null.read(&s_null[0], sizeof(s_null), consumed, wanted); + BOOST_CHECK(rc); + BOOST_CHECK(v_null.isBuffer()); + BOOST_CHECK_EQUAL(v_null.getValStr(), ""); + BOOST_CHECK_EQUAL(consumed, sizeof(s_null)); + BOOST_CHECK_EQUAL(wanted, 0); +} + +BOOST_AUTO_TEST_SUITE_END() + +int main (int argc, char *argv[]) +{ + rlpvalue_constructor(); + rlpvalue_set(); + rlpvalue_array(); + rlpvalue_readwrite(); + return 0; +} + diff --git a/libraries/fc/vendor/rlpvalue/test/test_json.cpp b/libraries/fc/vendor/rlpvalue/test/test_json.cpp new file mode 100644 index 00000000..26828505 --- /dev/null +++ b/libraries/fc/vendor/rlpvalue/test/test_json.cpp @@ -0,0 +1,24 @@ +// Test program that can be called by the JSON test suite at +// https://github.com/nst/JSONTestSuite. +// +// It reads JSON input from stdin and exits with code 0 if it can be parsed +// successfully. It also pretty prints the parsed JSON value to stdout. + +#include +#include +#include "rlpvalue.h" + +using namespace std; + +int main (int argc, char *argv[]) +{ + RLPValue val; + if (val.read(string(istreambuf_iterator(cin), + istreambuf_iterator()))) { + cout << val.write() << endl; + return 0; + } else { + cerr << "JSON Parse Error." << endl; + return 1; + } +} diff --git a/libraries/fc/vendor/rlpvalue/test/unitester.cpp b/libraries/fc/vendor/rlpvalue/test/unitester.cpp new file mode 100644 index 00000000..b487ff0e --- /dev/null +++ b/libraries/fc/vendor/rlpvalue/test/unitester.cpp @@ -0,0 +1,207 @@ +// Copyright 2014 BitPay Inc. +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or https://opensource.org/licenses/mit-license.php. + +#include +#include +#include +#include +#include +#include +#include +#include "utilstrencodings.h" +#include "rlpvalue.h" +#include "../src/InfInt.h" + +using namespace std; + +#ifndef JSON_TEST_SRC +#error JSON_TEST_SRC must point to test source directory +#endif + +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) +#endif + +std::string srcdir(JSON_TEST_SRC); +static bool test_failed = false; + +extern uint64_t toInteger(const unsigned char *raw, size_t len); +extern std::string encodeBinary(uint64_t n); +extern bool JSONtoRLP(const UniValue& jval, RLPValue& rval); + +static uint64_t toInteger(const char *raw, size_t len) { + return toInteger((const unsigned char *) raw, len); +} + +static bool isBigNumStr(const std::string& s) +{ + // first char must be # + if (s.empty() || s[0] != '#') + return false; + + // remaining chars must be digits + for (unsigned int i = 1; i < s.size(); i++) + if (!isdigit(s[i])) + return false; + + return true; +} + +static std::string encodeBigNum(const InfInt& n) +{ + std::string rs; + + if (n == 0) { + // do nothing; return empty string + } else { + rs.assign(encodeBigNum(n / 256)); + + InfInt iich = n % 256; + unsigned char ch = iich.toUnsignedLong(); + rs.append((const char *) &ch, 1); + } + + return rs; +} + +static std::string encodeBigNumStr(const std::string& s) +{ + InfInt n(s); + return encodeBigNum(n); +} + +static bool runtest(const std::string& filename, const std::string& key, + const UniValue& jval) +{ + if (!jval.isObject() || + !jval["out"].isStr()) { + fprintf(stderr, " %s: skipping test, invalid\n", + key.c_str()); + return true; + } + + string ins = jval["in"].getValStr(); + string outs = jval["out"].getValStr(); + + if (outs.substr(0, 2) == "0x") // remove 0x prefix + outs = outs.substr(2); + + // decode RLP binary output test string from hex to binary + std::vector outb = ParseHex(outs); + + // attempt to parse with RLP class + RLPValue v; + size_t consumed, wanted; + bool rrc = v.read(&outb[0], outb.size(), consumed, wanted); + + bool rc = false; + if (ins == "VALID" || ins == "INVALID") { + if (ins == "VALID" && rrc == true) + rc = true; + else if (ins == "INVALID" && rrc == false) + rc = true; + } else if (jval["in"].isStr()) { + if (isBigNumStr(ins)) + ins = encodeBigNumStr(ins.substr(1)); + + if (v.isBuffer() && (ins == v.getValStr())) + rc = true; + + } else if (jval["in"].isNum()) { + if (v.isBuffer()) { + uint64_t test_val = jval["in"].get_int64(); + string enc_val = v.getValStr(); + uint64_t dec_val = toInteger(&enc_val[0], + enc_val.size()); + if (test_val == dec_val) + rc = true; + } + } else if (jval["in"].isArray()) { + RLPValue root(RLPValue::VARR); + JSONtoRLP(jval["in"], root); + + std::string genOutput = root.write(); + if ((outb.size() == genOutput.size()) && + (memcmp(&outb[0], &genOutput[0], outb.size()) == 0)) { + rc = true; + } else { + std::string genHex = HexStr(genOutput.begin(), + genOutput.end()); + fprintf(stderr, "INS :%s\nGENS:%s\n", + outs.c_str(), + genHex.c_str()); + } + + } else { + fprintf(stderr, "ERR: test %s not implemented yet\n", key.c_str()); + } + + fprintf(stderr, " %s: %s\n", key.c_str(), + rc ? "ok" : "FAIL"); + return rc; +} + +static void runtest_jfile(std::string filename, const UniValue& jfile) +{ + assert(jfile.isObject()); + + const std::vector& keys = jfile.getKeys(); + + fprintf(stderr, "Running testfile %s (%zu tests)\n", + filename.c_str(), keys.size()); + + for (auto it = keys.begin(); it != keys.end(); it++) { + const std::string& key = *it; + if (!runtest(filename, key, jfile[key])) + test_failed = true; + } +} + +static void runtest_file(const char *filename_) +{ + std::string basename(filename_); + std::string filename = srcdir + "/" + basename; + FILE *f = fopen(filename.c_str(), "r"); + if (!f) { + perror(filename.c_str()); + exit(1); + } + + std::string jdata; + + char buf[4096]; + while (!feof(f)) { + int bread = fread(buf, 1, sizeof(buf), f); + assert(!ferror(f)); + + std::string s(buf, bread); + jdata += s; + } + + assert(!ferror(f)); + fclose(f); + + UniValue jfile; + bool rc = jfile.read(jdata); + assert(rc == true); + + runtest_jfile(basename, jfile); +} + +static const char *filenames[] = { + "example.json", + "invalidRLPTest.json", + "rlptest.json", +// "longlist.json", +}; + +int main (int argc, char *argv[]) +{ + for (unsigned int fidx = 0; fidx < ARRAY_SIZE(filenames); fidx++) { + runtest_file(filenames[fidx]); + } + + return test_failed ? 1 : 0; +} + diff --git a/libraries/fc/vendor/rlpvalue/test/utilstrencodings.cpp b/libraries/fc/vendor/rlpvalue/test/utilstrencodings.cpp new file mode 100644 index 00000000..901821c0 --- /dev/null +++ b/libraries/fc/vendor/rlpvalue/test/utilstrencodings.cpp @@ -0,0 +1,226 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2017 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "utilstrencodings.h" + +#include +#include +#include +#include + +static const std::string CHARS_ALPHA_NUM = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + +const signed char p_util_hexdigit[256] = +{ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 0,1,2,3,4,5,6,7,8,9,-1,-1,-1,-1,-1,-1, + -1,0xa,0xb,0xc,0xd,0xe,0xf,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,0xa,0xb,0xc,0xd,0xe,0xf,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, }; + +signed char HexDigit(char c) +{ + return p_util_hexdigit[(unsigned char)c]; +} + +bool IsHex(const std::string& str) +{ + for(std::string::const_iterator it(str.begin()); it != str.end(); ++it) + { + if (HexDigit(*it) < 0) + return false; + } + return (str.size() > 0) && (str.size()%2 == 0); +} + +bool IsHexNumber(const std::string& str) +{ + size_t starting_location = 0; + if (str.size() > 2 && *str.begin() == '0' && *(str.begin()+1) == 'x') { + starting_location = 2; + } + for (auto c : str.substr(starting_location)) { + if (HexDigit(c) < 0) return false; + } + // Return false for empty string or "0x". + return (str.size() > starting_location); +} + +std::vector ParseHex(const char* psz) +{ + // convert hex dump to vector + std::vector vch; + while (true) + { + while (isspace(*psz)) + psz++; + signed char c = HexDigit(*psz++); + if (c == (signed char)-1) + break; + unsigned char n = (c << 4); + c = HexDigit(*psz++); + if (c == (signed char)-1) + break; + n |= c; + vch.push_back(n); + } + return vch; +} + +std::vector ParseHex(const std::string& str) +{ + return ParseHex(str.c_str()); +} + +std::string EncodeBase64(const unsigned char* pch, size_t len) +{ + static const char *pbase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + + std::string strRet = ""; + strRet.reserve((len+2)/3*4); + + int mode=0, left=0; + const unsigned char *pchEnd = pch+len; + + while (pch> 2]; + left = (enc & 3) << 4; + mode = 1; + break; + + case 1: // we have two bits + strRet += pbase64[left | (enc >> 4)]; + left = (enc & 15) << 2; + mode = 2; + break; + + case 2: // we have four bits + strRet += pbase64[left | (enc >> 6)]; + strRet += pbase64[enc & 63]; + mode = 0; + break; + } + } + + if (mode) + { + strRet += pbase64[left]; + strRet += '='; + if (mode == 1) + strRet += '='; + } + + return strRet; +} + +std::string EncodeBase64(const std::string& str) +{ + return EncodeBase64((const unsigned char*)str.c_str(), str.size()); +} + +std::vector DecodeBase64(const char* p, bool* pfInvalid) +{ + static const int decode64_table[256] = + { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, + -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, + 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, + 49, 50, 51, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 + }; + + if (pfInvalid) + *pfInvalid = false; + + std::vector vchRet; + vchRet.reserve(strlen(p)*3/4); + + int mode = 0; + int left = 0; + + while (1) + { + int dec = decode64_table[(unsigned char)*p]; + if (dec == -1) break; + p++; + switch (mode) + { + case 0: // we have no bits and get 6 + left = dec; + mode = 1; + break; + + case 1: // we have 6 bits and keep 4 + vchRet.push_back((left<<2) | (dec>>4)); + left = dec & 15; + mode = 2; + break; + + case 2: // we have 4 bits and get 6, we keep 2 + vchRet.push_back((left<<4) | (dec>>2)); + left = dec & 3; + mode = 3; + break; + + case 3: // we have 2 bits and get 6 + vchRet.push_back((left<<6) | dec); + mode = 0; + break; + } + } + + if (pfInvalid) + switch (mode) + { + case 0: // 4n base64 characters processed: ok + break; + + case 1: // 4n+1 base64 character processed: impossible + *pfInvalid = true; + break; + + case 2: // 4n+2 base64 characters processed: require '==' + if (left || p[0] != '=' || p[1] != '=' || decode64_table[(unsigned char)p[2]] != -1) + *pfInvalid = true; + break; + + case 3: // 4n+3 base64 characters processed: require '=' + if (left || p[0] != '=' || decode64_table[(unsigned char)p[1]] != -1) + *pfInvalid = true; + break; + } + + return vchRet; +} + +std::string DecodeBase64(const std::string& str) +{ + std::vector vchRet = DecodeBase64(str.c_str()); + return std::string((const char*)vchRet.data(), vchRet.size()); +} + diff --git a/libraries/fc/vendor/rlpvalue/test/utilstrencodings.h b/libraries/fc/vendor/rlpvalue/test/utilstrencodings.h new file mode 100644 index 00000000..6621ce4f --- /dev/null +++ b/libraries/fc/vendor/rlpvalue/test/utilstrencodings.h @@ -0,0 +1,62 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2017 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +/** + * Utilities for converting data from/to strings. + */ +#ifndef JUP_UTILSTRENCODINGS_H +#define JUP_UTILSTRENCODINGS_H + +#include +#include +#include + +#define BEGIN(a) ((char*)&(a)) +#define END(a) ((char*)&((&(a))[1])) +#define UBEGIN(a) ((unsigned char*)&(a)) +#define UEND(a) ((unsigned char*)&((&(a))[1])) +#define ARRAYLEN(array) (sizeof(array)/sizeof((array)[0])) + +std::vector ParseHex(const char* psz); +std::vector ParseHex(const std::string& str); +signed char HexDigit(char c); +/* Returns true if each character in str is a hex character, and has an even + * number of hex digits.*/ +bool IsHex(const std::string& str); +/** +* Return true if the string is a hex number, optionally prefixed with "0x" +*/ +bool IsHexNumber(const std::string& str); +std::vector DecodeBase64(const char* p, bool* pfInvalid = nullptr); +std::string DecodeBase64(const std::string& str); +std::string EncodeBase64(const unsigned char* pch, size_t len); +std::string EncodeBase64(const std::string& str); + +template +std::string HexStr(const T itbegin, const T itend, bool fSpaces=false) +{ + std::string rv; + static const char hexmap[16] = { '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; + rv.reserve((itend-itbegin)*3); + for(T it = itbegin; it < itend; ++it) + { + unsigned char val = (unsigned char)(*it); + if(fSpaces && it != itbegin) + rv.push_back(' '); + rv.push_back(hexmap[val>>4]); + rv.push_back(hexmap[val&15]); + } + + return rv; +} + +template +inline std::string HexStr(const T& vch, bool fSpaces=false) +{ + return HexStr(vch.begin(), vch.end(), fSpaces); +} + +#endif // JUP_UTILSTRENCODINGS_H diff --git a/libraries/fc/vendor/rlpvalue/univalue b/libraries/fc/vendor/rlpvalue/univalue new file mode 160000 index 00000000..d6715ee1 --- /dev/null +++ b/libraries/fc/vendor/rlpvalue/univalue @@ -0,0 +1 @@ +Subproject commit d6715ee16ed57bfbfc64e023dcb05151b6654aa4 From 5906138cc564f90d37003ce9934953c68ed74854 Mon Sep 17 00:00:00 2001 From: Liam Noroian Date: Mon, 25 Apr 2022 10:37:54 -0700 Subject: [PATCH 93/96] Changes chain id when in testnet --- libraries/protocol/include/xgt/protocol/config.hpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/libraries/protocol/include/xgt/protocol/config.hpp b/libraries/protocol/include/xgt/protocol/config.hpp index 19634af0..d039f7b7 100644 --- a/libraries/protocol/include/xgt/protocol/config.hpp +++ b/libraries/protocol/include/xgt/protocol/config.hpp @@ -12,8 +12,14 @@ #define XGT_BLOCKCHAIN_VERSION ( version(0, 0, 0) ) #define XGT_ADDRESS_PREFIX "XGT" -#define XGT_CHAIN_ID fc::sha256::hash("xgt") /// All zeroes -#define XGT_WALLET_NAME_LENGTH 40 /// NOTE: If you change this, change XGT_INIT_MINER_NAME also. + +#ifdef IS_TEST_NET +#define XGT_CHAIN_ID fc::sha256::hash("testnet") +#else +#define XGT_CHAIN_ID fc::sha256::hash("xgt") +#endif + +#define XGT_WALLET_NAME_LENGTH 40 /// NOTE: If you change this, change XGT_INIT_MINER_NAME also. #ifdef IS_TEST_NET #define XGT_NETWORK_TYPE "testnet" From a162964d4f4c6d8cb57cdb86df2fa4aa12ccd1ec Mon Sep 17 00:00:00 2001 From: Liam Noroian Date: Tue, 26 Apr 2022 10:32:21 -0700 Subject: [PATCH 94/96] Configure testnet env --- Rakefile | 13 +++++++++++-- libraries/protocol/include/xgt/protocol/config.hpp | 6 ++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/Rakefile b/Rakefile index eda8db54..fe388258 100644 --- a/Rakefile +++ b/Rakefile @@ -80,6 +80,10 @@ def instance_index ENV['XGT_INSTANCE_INDEX'].to_i end +def port_offset + ENV['XGT_PORT_OFFSET'].to_i +end + def config rpc.call('database_api.get_config', {}) end @@ -123,6 +127,11 @@ task :configure => "../xgt-build" do sh %( cmake -G Ninja -B ../xgt-build -S . -D CMAKE_BUILD_TYPE=debug ) end +desc 'Runs CMake to prepare the project for testnet' +task :configure_testnet => "../xgt-build" do + sh %( cmake -G Ninja -B ../xgt-build -S . -D CMAKE_BUILD_TYPE=debug -D BUILD_XGT_TESTNET=ON ) +end + task :test do sh %( cmake @@ -286,8 +295,8 @@ task :run do shared-file-size = 12G - p2p-endpoint = #{my_host}:#{2001 + instance_index} - webserver-http-endpoint = #{my_host}:#{8751 + instance_index * 2} + p2p-endpoint = #{my_host}:#{2001 + port_offset + instance_index} + webserver-http-endpoint = #{my_host}:#{8751 + port_offset + instance_index * 2} miner = ["#{wallet}","#{wif}"] mining-threads = #{mining_threads} diff --git a/libraries/protocol/include/xgt/protocol/config.hpp b/libraries/protocol/include/xgt/protocol/config.hpp index 19634af0..aec8e792 100644 --- a/libraries/protocol/include/xgt/protocol/config.hpp +++ b/libraries/protocol/include/xgt/protocol/config.hpp @@ -12,7 +12,13 @@ #define XGT_BLOCKCHAIN_VERSION ( version(0, 0, 0) ) #define XGT_ADDRESS_PREFIX "XGT" + +#ifdef IS_TEST_NET +#define XGT_CHAIN_ID fc::sha256::hash("testnet") /// All zeroes +#else #define XGT_CHAIN_ID fc::sha256::hash("xgt") /// All zeroes +#endif + #define XGT_WALLET_NAME_LENGTH 40 /// NOTE: If you change this, change XGT_INIT_MINER_NAME also. #ifdef IS_TEST_NET From 3c723c9e98f7633bb8bec87dcd794d98376d8a19 Mon Sep 17 00:00:00 2001 From: Liam Noroian Date: Tue, 26 Apr 2022 12:15:30 -0700 Subject: [PATCH 95/96] Reset rakefile config, hardcode init_public_key for init miner --- Rakefile | 16 +++++++++++----- .../protocol/include/xgt/protocol/config.hpp | 5 +++-- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/Rakefile b/Rakefile index fe388258..6ba54fb0 100644 --- a/Rakefile +++ b/Rakefile @@ -53,23 +53,23 @@ def mining_error(message) end def wallet - 'XGT0000000000000000000000000000000000000000' + ENV['XGT_WALLET'] || mining_error("Wallet not specificed, please specify a wallet with 'XGT_WALLET'") end def wif - '5JQMNhd5L9ML99ZoH2FaZ1PUHrYb4Jw7U3CgA73V8rgBfoipkxt' + ENV['XGT_WIF'] || mining_error("XGT_WIF not specified") end def recovery_private_key - '5JQMNhd5L9ML99ZoH2FaZ1PUHrYb4Jw7U3CgA73V8rgBfoipkxt' + ENV['XGT_RECOVERY_PRIVATE_KEY'] || mining_error("XGT_RECOVERY_PRIVATE_KEY not specified") end def witness_private_key - '5JQMNhd5L9ML99ZoH2FaZ1PUHrYb4Jw7U3CgA73V8rgBfoipkxt' + ENV['XGT_WITNESS_PRIVATE_KEY'] || mining_error("XGT_WITNESS_PRIVATE_KEY not specified") end def host - ENV['XGT_HOST'] || 'http://localhost:8755' + ENV['XGT_HOST'] || 'http://localhost:8751' end def seed_hosts @@ -264,6 +264,12 @@ task :build_release => [:clean, :configure, :make, :strip] desc 'Runs a basic example instance locally' task :run do + puts wallet + puts wif + puts recovery_private_key + puts witness_private_key + exit + data_dir = "../xgt-chainstate-#{instance_index}" if flush_chainstate? diff --git a/libraries/protocol/include/xgt/protocol/config.hpp b/libraries/protocol/include/xgt/protocol/config.hpp index aec8e792..a1b06fc8 100644 --- a/libraries/protocol/include/xgt/protocol/config.hpp +++ b/libraries/protocol/include/xgt/protocol/config.hpp @@ -28,8 +28,9 @@ #endif #ifdef IS_TEST_NET -#define XGT_INIT_PRIVATE_KEY (fc::ecc::private_key::regenerate(fc::sha256::hash(std::string("init_key")))) -#define XGT_INIT_PUBLIC_KEY_STR (std::string( xgt::protocol::public_key_type(XGT_INIT_PRIVATE_KEY.get_public_key()) )) +// #define XGT_INIT_PRIVATE_KEY (fc::ecc::private_key::regenerate(fc::sha256::hash(std::string("init_key")))) +// #define XGT_INIT_PUBLIC_KEY_STR (std::string( xgt::protocol::public_key_type(XGT_INIT_PRIVATE_KEY.get_public_key()) )) +#define XGT_INIT_PUBLIC_KEY_STR "XGT5zYjtBDvJCQmmUSUwdh7kW2xLVhZB2moLERGHR3GW4vPpfLPrt" #else #define XGT_INIT_PUBLIC_KEY_STR "XGT7dDoJbrmueAw431pPbjLDoRhqFCC5Xs5o6f1cZLepWEpkcy3Tc" #endif From c0a7fdfd62801fbde557261b7487d5148032e630 Mon Sep 17 00:00:00 2001 From: Liam Noroian Date: Tue, 26 Apr 2022 12:16:00 -0700 Subject: [PATCH 96/96] Remove output --- Rakefile | 6 ------ 1 file changed, 6 deletions(-) diff --git a/Rakefile b/Rakefile index 6ba54fb0..e517668b 100644 --- a/Rakefile +++ b/Rakefile @@ -264,12 +264,6 @@ task :build_release => [:clean, :configure, :make, :strip] desc 'Runs a basic example instance locally' task :run do - puts wallet - puts wif - puts recovery_private_key - puts witness_private_key - exit - data_dir = "../xgt-chainstate-#{instance_index}" if flush_chainstate?