mirror of
https://github.com/ton-blockchain/ton
synced 2025-03-09 15:40:10 +00:00
Merge branch 'testnet' into block-generation
This commit is contained in:
commit
e4e77c16c5
463 changed files with 29976 additions and 2517 deletions
|
@ -4,7 +4,7 @@ if (NOT OPENSSL_FOUND)
|
|||
find_package(OpenSSL REQUIRED)
|
||||
endif()
|
||||
|
||||
set(TON_CRYPTO_SOURCE
|
||||
set(TON_CRYPTO_CORE_SOURCE
|
||||
Ed25519.cpp
|
||||
common/bigint.cpp
|
||||
common/refcnt.cpp
|
||||
|
@ -19,26 +19,8 @@ set(TON_CRYPTO_SOURCE
|
|||
openssl/bignum.cpp
|
||||
openssl/residue.cpp
|
||||
openssl/rand.cpp
|
||||
vm/stack.cpp
|
||||
vm/atom.cpp
|
||||
vm/continuation.cpp
|
||||
vm/dict.cpp
|
||||
vm/memo.cpp
|
||||
vm/dispatch.cpp
|
||||
vm/opctable.cpp
|
||||
vm/cp0.cpp
|
||||
vm/stackops.cpp
|
||||
vm/tupleops.cpp
|
||||
vm/arithops.cpp
|
||||
vm/cellops.cpp
|
||||
vm/contops.cpp
|
||||
vm/dictops.cpp
|
||||
vm/debugops.cpp
|
||||
vm/tonops.cpp
|
||||
vm/boc.cpp
|
||||
vm/large-boc-serializer.cpp
|
||||
vm/utils.cpp
|
||||
vm/vm.cpp
|
||||
tl/tlblib.cpp
|
||||
|
||||
Ed25519.h
|
||||
|
@ -66,34 +48,10 @@ set(TON_CRYPTO_SOURCE
|
|||
tl/tlbc-data.h
|
||||
tl/tlblib.hpp
|
||||
|
||||
vm/arithops.h
|
||||
vm/atom.h
|
||||
vm/boc.h
|
||||
vm/boc-writers.h
|
||||
vm/box.hpp
|
||||
vm/cellops.h
|
||||
vm/continuation.h
|
||||
vm/contops.h
|
||||
vm/cp0.h
|
||||
vm/debugops.h
|
||||
vm/dict.h
|
||||
vm/dictops.h
|
||||
vm/excno.hpp
|
||||
vm/fmt.hpp
|
||||
vm/log.h
|
||||
vm/memo.h
|
||||
vm/opctable.h
|
||||
vm/stack.hpp
|
||||
vm/stackops.h
|
||||
vm/tupleops.h
|
||||
vm/tonops.h
|
||||
vm/vmstate.h
|
||||
vm/utils.h
|
||||
vm/vm.h
|
||||
|
||||
vm/cells.h
|
||||
vm/cellslice.h
|
||||
keccak/keccak.h
|
||||
keccak/keccak.cpp
|
||||
|
||||
vm/dict.cpp
|
||||
vm/cells/Cell.cpp
|
||||
vm/cells/CellBuilder.cpp
|
||||
vm/cells/CellHash.cpp
|
||||
|
@ -106,6 +64,7 @@ set(TON_CRYPTO_SOURCE
|
|||
vm/cells/MerkleProof.cpp
|
||||
vm/cells/MerkleUpdate.cpp
|
||||
|
||||
vm/dict.h
|
||||
vm/cells/Cell.h
|
||||
vm/cells/CellBuilder.h
|
||||
vm/cells/CellHash.h
|
||||
|
@ -124,9 +83,64 @@ set(TON_CRYPTO_SOURCE
|
|||
vm/cells/VirtualCell.h
|
||||
vm/cells/VirtualizationParameters.h
|
||||
|
||||
vm/cells.h
|
||||
vm/cellslice.h
|
||||
|
||||
vm/db/StaticBagOfCellsDb.h
|
||||
vm/db/StaticBagOfCellsDb.cpp
|
||||
)
|
||||
|
||||
vm/Hasher.h
|
||||
vm/Hasher.cpp
|
||||
|
||||
ellcurve/secp256k1.h
|
||||
ellcurve/secp256k1.cpp
|
||||
ellcurve/p256.h
|
||||
ellcurve/p256.cpp)
|
||||
|
||||
set(TON_CRYPTO_SOURCE
|
||||
vm/stack.cpp
|
||||
vm/atom.cpp
|
||||
vm/continuation.cpp
|
||||
vm/memo.cpp
|
||||
vm/dispatch.cpp
|
||||
vm/opctable.cpp
|
||||
vm/cp0.cpp
|
||||
vm/stackops.cpp
|
||||
vm/tupleops.cpp
|
||||
vm/arithops.cpp
|
||||
vm/cellops.cpp
|
||||
vm/contops.cpp
|
||||
vm/dictops.cpp
|
||||
vm/debugops.cpp
|
||||
vm/tonops.cpp
|
||||
vm/utils.cpp
|
||||
vm/vm.cpp
|
||||
vm/bls.cpp
|
||||
|
||||
vm/arithops.h
|
||||
vm/atom.h
|
||||
vm/boc.h
|
||||
vm/boc-writers.h
|
||||
vm/box.hpp
|
||||
vm/cellops.h
|
||||
vm/continuation.h
|
||||
vm/contops.h
|
||||
vm/cp0.h
|
||||
vm/debugops.h
|
||||
vm/dictops.h
|
||||
vm/excno.hpp
|
||||
vm/fmt.hpp
|
||||
vm/log.h
|
||||
vm/memo.h
|
||||
vm/opctable.h
|
||||
vm/stack.hpp
|
||||
vm/stackops.h
|
||||
vm/tupleops.h
|
||||
vm/tonops.h
|
||||
vm/vmstate.h
|
||||
vm/utils.h
|
||||
vm/vm.h
|
||||
vm/bls.h)
|
||||
|
||||
set(TON_DB_SOURCE
|
||||
vm/db/DynamicBagOfCellsDb.cpp
|
||||
|
@ -271,17 +285,25 @@ set(BIGINT_TEST_SOURCE
|
|||
|
||||
set(USE_EMSCRIPTEN ${USE_EMSCRIPTEN} PARENT_SCOPE)
|
||||
|
||||
add_library(ton_crypto_core STATIC ${TON_CRYPTO_CORE_SOURCE})
|
||||
target_include_directories(ton_crypto_core PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/..>)
|
||||
target_link_libraries(ton_crypto_core PUBLIC ${OPENSSL_CRYPTO_LIBRARY} tdutils tddb_utils)
|
||||
if (NOT WIN32)
|
||||
target_link_libraries(ton_crypto_core PUBLIC dl z)
|
||||
endif()
|
||||
target_include_directories(ton_crypto_core SYSTEM PUBLIC $<BUILD_INTERFACE:${OPENSSL_INCLUDE_DIR}>)
|
||||
|
||||
add_library(ton_crypto STATIC ${TON_CRYPTO_SOURCE})
|
||||
target_include_directories(ton_crypto PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/..>)
|
||||
target_link_libraries(ton_crypto PUBLIC ${OPENSSL_CRYPTO_LIBRARY} tdutils tddb_utils)
|
||||
target_link_libraries(ton_crypto PUBLIC ${OPENSSL_CRYPTO_LIBRARY} tdutils tddb_utils ton_crypto_core ton_block)
|
||||
if (USE_EMSCRIPTEN)
|
||||
target_link_options(ton_crypto PRIVATE -fexceptions)
|
||||
target_compile_options(ton_crypto PRIVATE -fexceptions)
|
||||
endif()
|
||||
if (NOT WIN32)
|
||||
find_library(DL dl)
|
||||
find_library(DL dl)
|
||||
if (DL)
|
||||
target_link_libraries(ton_crypto PUBLIC dl z)
|
||||
else()
|
||||
|
@ -290,6 +312,39 @@ if (NOT WIN32)
|
|||
endif()
|
||||
target_include_directories(ton_crypto SYSTEM PUBLIC $<BUILD_INTERFACE:${OPENSSL_INCLUDE_DIR}>)
|
||||
|
||||
add_dependencies(ton_crypto blst)
|
||||
target_include_directories(ton_crypto PRIVATE ${BLST_INCLUDE_DIR})
|
||||
target_link_libraries(ton_crypto PRIVATE ${BLST_LIB})
|
||||
|
||||
if (NOT USE_EMSCRIPTEN)
|
||||
find_package(Secp256k1 REQUIRED)
|
||||
endif()
|
||||
|
||||
if (MSVC)
|
||||
find_package(Sodium REQUIRED)
|
||||
target_compile_definitions(ton_crypto PUBLIC SODIUM_STATIC)
|
||||
target_include_directories(ton_crypto_core PUBLIC $<BUILD_INTERFACE:${SECP256K1_INCLUDE_DIRS}>)
|
||||
target_link_libraries(ton_crypto PUBLIC ${SECP256K1_LIBRARIES})
|
||||
elseif (ANDROID)
|
||||
target_include_directories(ton_crypto_core PUBLIC $<BUILD_INTERFACE:${SECP256K1_INCLUDE_DIR}>)
|
||||
target_link_libraries(ton_crypto PUBLIC $<BUILD_INTERFACE:${SECP256K1_LIBRARY}>)
|
||||
else()
|
||||
if (NOT USE_EMSCRIPTEN)
|
||||
find_package(Sodium REQUIRED)
|
||||
target_include_directories(ton_crypto_core PUBLIC $<BUILD_INTERFACE:${SECP256K1_INCLUDE_DIRS}>)
|
||||
target_link_libraries(ton_crypto PUBLIC ${SECP256K1_LIBRARIES})
|
||||
else()
|
||||
target_include_directories(ton_crypto_core PUBLIC $<BUILD_INTERFACE:${SECP256K1_INCLUDE_DIR}>)
|
||||
target_link_libraries(ton_crypto PUBLIC ${SECP256K1_LIBRARY})
|
||||
endif()
|
||||
if (NOT APPLE AND NOT USE_EMSCRIPTEN)
|
||||
target_link_libraries(ton_crypto_core PUBLIC secp256k1)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
target_include_directories(ton_crypto_core PUBLIC $<BUILD_INTERFACE:${SODIUM_INCLUDE_DIR}>)
|
||||
target_link_libraries(ton_crypto PUBLIC ${SODIUM_LIBRARY_RELEASE})
|
||||
|
||||
add_library(ton_db STATIC ${TON_DB_SOURCE})
|
||||
target_include_directories(ton_db PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/..>)
|
||||
|
@ -316,12 +371,12 @@ endif()
|
|||
|
||||
add_library(src_parser ${PARSER_SOURCE})
|
||||
target_include_directories(src_parser PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>)
|
||||
target_link_libraries(src_parser PUBLIC ton_crypto)
|
||||
target_link_libraries(src_parser PUBLIC ton_crypto_core)
|
||||
|
||||
add_library(ton_block ${BLOCK_SOURCE})
|
||||
target_include_directories(ton_block PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/block> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/..>)
|
||||
target_link_libraries(ton_block PUBLIC ton_crypto tdutils tdactor tl_api)
|
||||
target_link_libraries(ton_block PUBLIC ton_crypto_core tdutils tdactor tl_api)
|
||||
|
||||
add_executable(func func/func-main.cpp ${FUNC_LIB_SOURCE})
|
||||
target_include_directories(func PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>)
|
||||
|
@ -347,12 +402,12 @@ if (USE_EMSCRIPTEN)
|
|||
target_link_options(funcfiftlib PRIVATE -sALLOW_TABLE_GROWTH=1)
|
||||
target_link_options(funcfiftlib PRIVATE --embed-file ${CMAKE_CURRENT_SOURCE_DIR}/fift/lib@/fiftlib)
|
||||
target_link_options(funcfiftlib PRIVATE -fexceptions)
|
||||
target_compile_options(funcfiftlib PRIVATE -fexceptions)
|
||||
target_compile_options(funcfiftlib PRIVATE -fexceptions -fno-stack-protector)
|
||||
endif()
|
||||
|
||||
add_executable(tlbc tl/tlbc.cpp)
|
||||
target_include_directories(tlbc PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>)
|
||||
target_link_libraries(tlbc PUBLIC ton_crypto src_parser)
|
||||
target_link_libraries(tlbc PUBLIC ton_crypto_core src_parser)
|
||||
if (WINGETOPT_FOUND)
|
||||
target_link_libraries_system(tlbc wingetopt)
|
||||
endif()
|
||||
|
|
|
@ -2292,5 +2292,37 @@ bool Aug_ShardFees::eval_leaf(vm::CellBuilder& cb, vm::CellSlice& cs) const {
|
|||
|
||||
const Aug_ShardFees aug_ShardFees;
|
||||
|
||||
bool validate_message_libs(const td::Ref<vm::Cell> &cell) {
|
||||
gen::Message::Record rec;
|
||||
if (!type_unpack_cell(cell, gen::t_Message_Any, rec)) {
|
||||
return false;
|
||||
}
|
||||
vm::CellSlice& state_init = rec.init.write();
|
||||
if (!state_init.fetch_long(1)) {
|
||||
return true;
|
||||
}
|
||||
if (state_init.fetch_long(1)) {
|
||||
return gen::t_StateInitWithLibs.validate_ref(state_init.prefetch_ref());
|
||||
} else {
|
||||
return gen::t_StateInitWithLibs.validate_csr(rec.init);
|
||||
}
|
||||
}
|
||||
|
||||
bool validate_message_relaxed_libs(const td::Ref<vm::Cell> &cell) {
|
||||
gen::MessageRelaxed::Record rec;
|
||||
if (!type_unpack_cell(cell, gen::t_MessageRelaxed_Any, rec)) {
|
||||
return false;
|
||||
}
|
||||
vm::CellSlice& state_init = rec.init.write();
|
||||
if (!state_init.fetch_long(1)) {
|
||||
return true;
|
||||
}
|
||||
if (state_init.fetch_long(1)) {
|
||||
return gen::t_StateInitWithLibs.validate_ref(state_init.prefetch_ref());
|
||||
} else {
|
||||
return gen::t_StateInitWithLibs.validate_csr(rec.init);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace tlb
|
||||
} // namespace block
|
||||
|
|
|
@ -1113,5 +1113,9 @@ struct Aug_ShardFees final : AugmentationCheckData {
|
|||
|
||||
extern const Aug_ShardFees aug_ShardFees;
|
||||
|
||||
// Validate dict of libraries in message: used when sending and receiving message
|
||||
bool validate_message_libs(const td::Ref<vm::Cell> &cell);
|
||||
bool validate_message_relaxed_libs(const td::Ref<vm::Cell> &cell);
|
||||
|
||||
} // namespace tlb
|
||||
} // namespace block
|
||||
|
|
|
@ -715,7 +715,7 @@ td::uint64 BlockLimitStatus::estimate_block_size(const vm::NewCellStorageStat::S
|
|||
sum += *extra;
|
||||
}
|
||||
return 2000 + (sum.bits >> 3) + sum.cells * 12 + sum.internal_refs * 3 + sum.external_refs * 40 + accounts * 200 +
|
||||
transactions * 200 + (extra ? 200 : 0);
|
||||
transactions * 200 + (extra ? 200 : 0) + extra_out_msgs * 300;
|
||||
}
|
||||
|
||||
int BlockLimitStatus::classify() const {
|
||||
|
@ -1364,42 +1364,61 @@ std::ostream& operator<<(std::ostream& os, const CurrencyCollection& cc) {
|
|||
bool ValueFlow::set_zero() {
|
||||
return from_prev_blk.set_zero() && to_next_blk.set_zero() && imported.set_zero() && exported.set_zero() &&
|
||||
fees_collected.set_zero() && fees_imported.set_zero() && recovered.set_zero() && created.set_zero() &&
|
||||
minted.set_zero();
|
||||
minted.set_zero() && burned.set_zero();
|
||||
}
|
||||
|
||||
bool ValueFlow::validate() const {
|
||||
return is_valid() && from_prev_blk + imported + fees_imported + created + minted + recovered ==
|
||||
to_next_blk + exported + fees_collected;
|
||||
to_next_blk + exported + fees_collected + burned;
|
||||
}
|
||||
|
||||
bool ValueFlow::store(vm::CellBuilder& cb) const {
|
||||
vm::CellBuilder cb2;
|
||||
return cb.store_long_bool(block::gen::ValueFlow::cons_tag[0], 32) // value_flow ^[
|
||||
&& from_prev_blk.store(cb2) // from_prev_blk:CurrencyCollection
|
||||
&& to_next_blk.store(cb2) // to_next_blk:CurrencyCollection
|
||||
&& imported.store(cb2) // imported:CurrencyCollection
|
||||
&& exported.store(cb2) // exported:CurrencyCollection
|
||||
&& cb.store_ref_bool(cb2.finalize()) // ]
|
||||
&& fees_collected.store(cb) // fees_collected:CurrencyCollection
|
||||
&& fees_imported.store(cb2) // ^[ fees_imported:CurrencyCollection
|
||||
&& recovered.store(cb2) // recovered:CurrencyCollection
|
||||
&& created.store(cb2) // created:CurrencyCollection
|
||||
&& minted.store(cb2) // minted:CurrencyCollection
|
||||
&& cb.store_ref_bool(cb2.finalize()); // ] = ValueFlow;
|
||||
auto type = burned.is_zero() ? block::gen::ValueFlow::value_flow : block::gen::ValueFlow::value_flow_v2;
|
||||
return cb.store_long_bool(block::gen::ValueFlow::cons_tag[type], 32) // ^[
|
||||
&& from_prev_blk.store(cb2) // from_prev_blk:CurrencyCollection
|
||||
&& to_next_blk.store(cb2) // to_next_blk:CurrencyCollection
|
||||
&& imported.store(cb2) // imported:CurrencyCollection
|
||||
&& exported.store(cb2) // exported:CurrencyCollection
|
||||
&& cb.store_ref_bool(cb2.finalize()) // ]
|
||||
&& fees_collected.store(cb) // fees_collected:CurrencyCollection
|
||||
&& (burned.is_zero() || burned.store(cb)) // fees_burned:CurrencyCollection
|
||||
&& fees_imported.store(cb2) // ^[ fees_imported:CurrencyCollection
|
||||
&& recovered.store(cb2) // recovered:CurrencyCollection
|
||||
&& created.store(cb2) // created:CurrencyCollection
|
||||
&& minted.store(cb2) // minted:CurrencyCollection
|
||||
&& cb.store_ref_bool(cb2.finalize()); // ] = ValueFlow;
|
||||
}
|
||||
|
||||
bool ValueFlow::fetch(vm::CellSlice& cs) {
|
||||
block::gen::ValueFlow::Record f;
|
||||
if (!(tlb::unpack(cs, f) && from_prev_blk.validate_unpack(std::move(f.r1.from_prev_blk)) &&
|
||||
to_next_blk.validate_unpack(std::move(f.r1.to_next_blk)) &&
|
||||
imported.validate_unpack(std::move(f.r1.imported)) && exported.validate_unpack(std::move(f.r1.exported)) &&
|
||||
fees_collected.validate_unpack(std::move(f.fees_collected)) &&
|
||||
fees_imported.validate_unpack(std::move(f.r2.fees_imported)) &&
|
||||
recovered.validate_unpack(std::move(f.r2.recovered)) && created.validate_unpack(std::move(f.r2.created)) &&
|
||||
minted.validate_unpack(std::move(f.r2.minted)))) {
|
||||
if (cs.size() < 32) {
|
||||
return invalidate();
|
||||
}
|
||||
return true;
|
||||
auto tag = cs.prefetch_ulong(32);
|
||||
block::gen::ValueFlow::Record_value_flow f1;
|
||||
if (tag == block::gen::ValueFlow::cons_tag[block::gen::ValueFlow::value_flow] && tlb::unpack(cs, f1) &&
|
||||
from_prev_blk.validate_unpack(std::move(f1.r1.from_prev_blk)) &&
|
||||
to_next_blk.validate_unpack(std::move(f1.r1.to_next_blk)) &&
|
||||
imported.validate_unpack(std::move(f1.r1.imported)) && exported.validate_unpack(std::move(f1.r1.exported)) &&
|
||||
fees_collected.validate_unpack(std::move(f1.fees_collected)) && burned.set_zero() &&
|
||||
fees_imported.validate_unpack(std::move(f1.r2.fees_imported)) &&
|
||||
recovered.validate_unpack(std::move(f1.r2.recovered)) && created.validate_unpack(std::move(f1.r2.created)) &&
|
||||
minted.validate_unpack(std::move(f1.r2.minted))) {
|
||||
return true;
|
||||
}
|
||||
block::gen::ValueFlow::Record_value_flow_v2 f2;
|
||||
if (tag == block::gen::ValueFlow::cons_tag[block::gen::ValueFlow::value_flow_v2] && tlb::unpack(cs, f2) &&
|
||||
from_prev_blk.validate_unpack(std::move(f2.r1.from_prev_blk)) &&
|
||||
to_next_blk.validate_unpack(std::move(f2.r1.to_next_blk)) &&
|
||||
imported.validate_unpack(std::move(f2.r1.imported)) && exported.validate_unpack(std::move(f2.r1.exported)) &&
|
||||
fees_collected.validate_unpack(std::move(f2.fees_collected)) &&
|
||||
burned.validate_unpack(std::move(f2.burned)) &&
|
||||
fees_imported.validate_unpack(std::move(f2.r2.fees_imported)) &&
|
||||
recovered.validate_unpack(std::move(f2.r2.recovered)) && created.validate_unpack(std::move(f2.r2.created)) &&
|
||||
minted.validate_unpack(std::move(f2.r2.minted))) {
|
||||
return true;
|
||||
}
|
||||
return invalidate();
|
||||
}
|
||||
|
||||
bool ValueFlow::unpack(Ref<vm::CellSlice> csr) {
|
||||
|
@ -1424,7 +1443,8 @@ bool ValueFlow::show(std::ostream& os) const {
|
|||
show_one(os, " to_next_blk:", to_next_blk) && show_one(os, " imported:", imported) &&
|
||||
show_one(os, " exported:", exported) && show_one(os, " fees_collected:", fees_collected) &&
|
||||
show_one(os, " fees_imported:", fees_imported) && show_one(os, " recovered:", recovered) &&
|
||||
show_one(os, " created:", created) && show_one(os, " minted:", minted) && say(os, ")")) ||
|
||||
show_one(os, " created:", created) && show_one(os, " minted:", minted) &&
|
||||
(burned.is_zero() || show_one(os, " burned:", burned)) && say(os, ")")) ||
|
||||
(say(os, "...<invalid-value-flow>)") && false);
|
||||
}
|
||||
|
||||
|
|
|
@ -261,7 +261,7 @@ struct BlockLimitStatus {
|
|||
ton::LogicalTime cur_lt;
|
||||
td::uint64 gas_used{};
|
||||
vm::NewCellStorageStat st_stat;
|
||||
unsigned accounts{}, transactions{};
|
||||
unsigned accounts{}, transactions{}, extra_out_msgs{};
|
||||
BlockLimitStatus(const BlockLimits& limits_, ton::LogicalTime lt = 0)
|
||||
: limits(limits_), cur_lt(std::max(limits_.start_lt, lt)) {
|
||||
}
|
||||
|
@ -270,6 +270,7 @@ struct BlockLimitStatus {
|
|||
st_stat.set_zero();
|
||||
transactions = accounts = 0;
|
||||
gas_used = 0;
|
||||
extra_out_msgs = 0;
|
||||
}
|
||||
td::uint64 estimate_block_size(const vm::NewCellStorageStat::Stat* extra = nullptr) const;
|
||||
int classify() const;
|
||||
|
@ -455,7 +456,7 @@ struct ShardState {
|
|||
struct ValueFlow {
|
||||
struct SetZero {};
|
||||
CurrencyCollection from_prev_blk, to_next_blk, imported, exported, fees_collected, fees_imported, recovered, created,
|
||||
minted;
|
||||
minted, burned;
|
||||
ValueFlow() = default;
|
||||
ValueFlow(SetZero)
|
||||
: from_prev_blk{0}
|
||||
|
@ -466,7 +467,8 @@ struct ValueFlow {
|
|||
, fees_imported{0}
|
||||
, recovered{0}
|
||||
, created{0}
|
||||
, minted{0} {
|
||||
, minted{0}
|
||||
, burned{0} {
|
||||
}
|
||||
bool is_valid() const {
|
||||
return from_prev_blk.is_valid() && minted.is_valid();
|
||||
|
|
|
@ -143,8 +143,13 @@ tick_tock$_ tick:Bool tock:Bool = TickTock;
|
|||
|
||||
_ split_depth:(Maybe (## 5)) special:(Maybe TickTock)
|
||||
code:(Maybe ^Cell) data:(Maybe ^Cell)
|
||||
library:(HashmapE 256 SimpleLib) = StateInit;
|
||||
|
||||
library:(Maybe ^Cell) = StateInit;
|
||||
|
||||
// StateInitWithLibs is used to validate sent and received messages
|
||||
_ split_depth:(Maybe (## 5)) special:(Maybe TickTock)
|
||||
code:(Maybe ^Cell) data:(Maybe ^Cell)
|
||||
library:(HashmapE 256 SimpleLib) = StateInitWithLibs;
|
||||
|
||||
simple_lib$_ public:Bool root:^Cell = SimpleLib;
|
||||
|
||||
message$_ {X:Type} info:CommonMsgInfo
|
||||
|
@ -379,7 +384,7 @@ action_reserve_currency#36e6b809 mode:(## 8)
|
|||
currency:CurrencyCollection = OutAction;
|
||||
libref_hash$0 lib_hash:bits256 = LibRef;
|
||||
libref_ref$1 library:^Cell = LibRef;
|
||||
action_change_library#26fa1dd4 mode:(## 7) { mode <= 2 }
|
||||
action_change_library#26fa1dd4 mode:(## 7)
|
||||
libref:LibRef = OutAction;
|
||||
|
||||
out_list_node$_ prev:^Cell action:OutAction = OutListNode;
|
||||
|
@ -467,6 +472,19 @@ value_flow#b8e48dfb ^[ from_prev_blk:CurrencyCollection
|
|||
minted:CurrencyCollection
|
||||
] = ValueFlow;
|
||||
|
||||
value_flow_v2#3ebf98b7 ^[ from_prev_blk:CurrencyCollection
|
||||
to_next_blk:CurrencyCollection
|
||||
imported:CurrencyCollection
|
||||
exported:CurrencyCollection ]
|
||||
fees_collected:CurrencyCollection
|
||||
burned:CurrencyCollection
|
||||
^[
|
||||
fees_imported:CurrencyCollection
|
||||
recovered:CurrencyCollection
|
||||
created:CurrencyCollection
|
||||
minted:CurrencyCollection
|
||||
] = ValueFlow;
|
||||
|
||||
//
|
||||
//
|
||||
bt_leaf$0 {X:Type} leaf:X = BinTree X;
|
||||
|
@ -590,6 +608,11 @@ _ minter_addr:bits256 = ConfigParam 2; // ConfigParam 0 is used if absent
|
|||
_ fee_collector_addr:bits256 = ConfigParam 3; // ConfigParam 1 is used if absent
|
||||
_ dns_root_addr:bits256 = ConfigParam 4; // root TON DNS resolver
|
||||
|
||||
burning_config#01
|
||||
blackhole_addr:(Maybe bits256)
|
||||
fee_burn_nom:# fee_burn_denom:# { fee_burn_nom <= fee_burn_denom } { fee_burn_denom >= 1 } = BurningConfig;
|
||||
_ BurningConfig = ConfigParam 5;
|
||||
|
||||
_ mint_new_price:Grams mint_add_price:Grams = ConfigParam 6;
|
||||
_ to_mint:ExtraCurrencyCollection = ConfigParam 7;
|
||||
|
||||
|
@ -663,6 +686,8 @@ _#cc utime_since:uint32 bit_price_ps:uint64 cell_price_ps:uint64
|
|||
mc_bit_price_ps:uint64 mc_cell_price_ps:uint64 = StoragePrices;
|
||||
_ (Hashmap 32 StoragePrices) = ConfigParam 18;
|
||||
|
||||
_ global_id:int32 = ConfigParam 19;
|
||||
|
||||
gas_prices#dd gas_price:uint64 gas_limit:uint64 gas_credit:uint64
|
||||
block_gas_limit:uint64 freeze_due_limit:uint64 delete_due_limit:uint64
|
||||
= GasLimitsPrices;
|
||||
|
@ -783,8 +808,8 @@ jetton_bridge_params_v0#00 bridge_address:bits256 oracles_address:bits256 oracle
|
|||
jetton_bridge_params_v1#01 bridge_address:bits256 oracles_address:bits256 oracles:(HashmapE 256 uint256) state_flags:uint8 prices:^JettonBridgePrices external_chain_address:bits256 = JettonBridgeParams;
|
||||
|
||||
_ JettonBridgeParams = ConfigParam 79; // ETH->TON token bridge
|
||||
_ JettonBridgeParams = ConfigParam 80; // BNB->TON token bridge
|
||||
_ JettonBridgeParams = ConfigParam 81; // Polygon->TON token bridge
|
||||
_ JettonBridgeParams = ConfigParam 81; // BNB->TON token bridge
|
||||
_ JettonBridgeParams = ConfigParam 82; // Polygon->TON token bridge
|
||||
|
||||
|
||||
//
|
||||
|
|
|
@ -855,11 +855,12 @@ Ref<McShardHash> McShardHash::from_block(Ref<vm::Cell> block_root, const ton::Fi
|
|||
ton::RootHash rhash = block_root->get_hash().bits();
|
||||
CurrencyCollection fees_collected, funds_created;
|
||||
if (init_fees) {
|
||||
block::gen::ValueFlow::Record flow;
|
||||
if (!(tlb::unpack_cell(rec.value_flow, flow) && fees_collected.unpack(flow.fees_collected) &&
|
||||
funds_created.unpack(flow.r2.created))) {
|
||||
block::ValueFlow flow;
|
||||
if (!flow.unpack(vm::load_cell_slice_ref(rec.value_flow))) {
|
||||
return {};
|
||||
}
|
||||
fees_collected = flow.fees_collected;
|
||||
funds_created = flow.created;
|
||||
}
|
||||
return Ref<McShardHash>(true, ton::BlockId{ton::ShardIdFull(shard), (unsigned)info.seq_no}, info.start_lt,
|
||||
info.end_lt, info.gen_utime, rhash, fhash, fees_collected, funds_created, ~0U,
|
||||
|
@ -909,11 +910,12 @@ Ref<McShardDescr> McShardDescr::from_block(Ref<vm::Cell> block_root, Ref<vm::Cel
|
|||
ton::RootHash rhash = block_root->get_hash().bits();
|
||||
CurrencyCollection fees_collected, funds_created;
|
||||
if (init_fees) {
|
||||
block::gen::ValueFlow::Record flow;
|
||||
if (!(tlb::unpack_cell(rec.value_flow, flow) && fees_collected.unpack(flow.fees_collected) &&
|
||||
funds_created.unpack(flow.r2.created))) {
|
||||
block::ValueFlow flow;
|
||||
if (!flow.unpack(vm::load_cell_slice_ref(rec.value_flow))) {
|
||||
return {};
|
||||
}
|
||||
fees_collected = flow.fees_collected;
|
||||
funds_created = flow.created;
|
||||
}
|
||||
auto res = Ref<McShardDescr>(true, ton::BlockId{ton::ShardIdFull(shard), (unsigned)info.seq_no}, info.start_lt,
|
||||
info.end_lt, info.gen_utime, rhash, fhash, fees_collected, funds_created, ~0U,
|
||||
|
@ -1954,6 +1956,24 @@ std::unique_ptr<vm::Dictionary> Config::get_suspended_addresses(ton::UnixTime no
|
|||
return std::make_unique<vm::Dictionary>(rec.addresses->prefetch_ref(), 288);
|
||||
}
|
||||
|
||||
BurningConfig Config::get_burning_config() const {
|
||||
td::Ref<vm::Cell> param = get_config_param(5);
|
||||
gen::BurningConfig::Record rec;
|
||||
if (param.is_null() || !tlb::unpack_cell(param, rec)) {
|
||||
return {};
|
||||
}
|
||||
BurningConfig c;
|
||||
c.fee_burn_nom = rec.fee_burn_nom;
|
||||
c.fee_burn_denom = rec.fee_burn_denom;
|
||||
vm::CellSlice& addr = rec.blackhole_addr.write();
|
||||
if (addr.fetch_long(1)) {
|
||||
td::Bits256 x;
|
||||
addr.fetch_bits_to(x.bits(), 256);
|
||||
c.blackhole_addr = x;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
td::Result<std::pair<ton::UnixTime, ton::UnixTime>> Config::unpack_validator_set_start_stop(Ref<vm::Cell> vset_root) {
|
||||
if (vset_root.is_null()) {
|
||||
return td::Status::Error("validator set absent");
|
||||
|
@ -2200,6 +2220,44 @@ Ref<vm::Cell> ConfigInfo::lookup_library(td::ConstBitPtr root_hash) const {
|
|||
return lib;
|
||||
}
|
||||
|
||||
td::Result<Ref<vm::Tuple>> ConfigInfo::get_prev_blocks_info() const {
|
||||
// [ wc:Integer shard:Integer seqno:Integer root_hash:Integer file_hash:Integer] = BlockId;
|
||||
// [ last_mc_blocks:[BlockId...]
|
||||
// prev_key_block:BlockId ] : PrevBlocksInfo
|
||||
auto block_id_to_tuple = [](const ton::BlockIdExt& block_id) -> vm::Ref<vm::Tuple> {
|
||||
td::RefInt256 shard = td::make_refint(block_id.id.shard);
|
||||
if (shard->sgn() < 0) {
|
||||
shard &= ((td::make_refint(1) << 64) - 1);
|
||||
}
|
||||
return vm::make_tuple_ref(
|
||||
td::make_refint(block_id.id.workchain),
|
||||
std::move(shard),
|
||||
td::make_refint(block_id.id.seqno),
|
||||
td::bits_to_refint(block_id.root_hash.bits(), 256),
|
||||
td::bits_to_refint(block_id.file_hash.bits(), 256));
|
||||
};
|
||||
std::vector<vm::StackEntry> last_mc_blocks;
|
||||
|
||||
last_mc_blocks.push_back(block_id_to_tuple(block_id));
|
||||
for (ton::BlockSeqno seqno = block_id.id.seqno; seqno > 0 && last_mc_blocks.size() < 16; ) {
|
||||
--seqno;
|
||||
ton::BlockIdExt block_id;
|
||||
if (!get_old_mc_block_id(seqno, block_id)) {
|
||||
return td::Status::Error("cannot fetch old mc block");
|
||||
}
|
||||
last_mc_blocks.push_back(block_id_to_tuple(block_id));
|
||||
}
|
||||
|
||||
ton::BlockIdExt last_key_block;
|
||||
ton::LogicalTime last_key_block_lt;
|
||||
if (!get_last_key_block(last_key_block, last_key_block_lt)) {
|
||||
return td::Status::Error("cannot fetch last key block");
|
||||
}
|
||||
return vm::make_tuple_ref(
|
||||
td::make_cnt_ref<std::vector<vm::StackEntry>>(std::move(last_mc_blocks)),
|
||||
block_id_to_tuple(last_key_block));
|
||||
}
|
||||
|
||||
CollatorConfig Config::get_collator_config(bool need_collator_nodes) const {
|
||||
CollatorConfig collator_config;
|
||||
gen::CollatorConfig::Record rec;
|
||||
|
|
|
@ -504,6 +504,22 @@ class ShardConfig {
|
|||
bool set_shard_info(ton::ShardIdFull shard, Ref<vm::Cell> value);
|
||||
};
|
||||
|
||||
struct BurningConfig {
|
||||
td::optional<td::Bits256> blackhole_addr;
|
||||
td::uint32 fee_burn_nom = 0, fee_burn_denom = 1;
|
||||
|
||||
td::RefInt256 calculate_burned_fees(const td::RefInt256& x) const {
|
||||
if (x.is_null()) {
|
||||
return x;
|
||||
}
|
||||
return x * fee_burn_nom / td::make_refint(fee_burn_denom);
|
||||
}
|
||||
|
||||
CurrencyCollection calculate_burned_fees(const CurrencyCollection& x) const {
|
||||
return CurrencyCollection{calculate_burned_fees(x.grams)};
|
||||
}
|
||||
};
|
||||
|
||||
struct CollatorNodeDescr {
|
||||
ton::ShardIdFull shard;
|
||||
ton::NodeIdShort adnl_id;
|
||||
|
@ -629,6 +645,7 @@ class Config {
|
|||
CollatorConfig get_collator_config(bool need_collator_nodes) const;
|
||||
td::Result<SizeLimitsConfig> get_size_limits_config() const;
|
||||
std::unique_ptr<vm::Dictionary> get_suspended_addresses(ton::UnixTime now) const;
|
||||
BurningConfig get_burning_config() const;
|
||||
static std::vector<ton::ValidatorDescr> do_compute_validator_set(const block::CatchainValidatorsConfig& ccv_conf,
|
||||
ton::ShardIdFull shard,
|
||||
const block::ValidatorSet& vset, ton::UnixTime time,
|
||||
|
@ -733,6 +750,7 @@ class ConfigInfo : public Config, public ShardConfig {
|
|||
ton::CatchainSeqno* cc_seqno_delta = nullptr) const;
|
||||
std::vector<ton::ValidatorDescr> compute_validator_set_cc(ton::ShardIdFull shard, ton::UnixTime time,
|
||||
ton::CatchainSeqno* cc_seqno_delta = nullptr) const;
|
||||
td::Result<Ref<vm::Tuple>> get_prev_blocks_info() const;
|
||||
static td::Result<std::unique_ptr<ConfigInfo>> extract_config(std::shared_ptr<vm::StaticBagOfCellsDb> static_boc,
|
||||
int mode = 0);
|
||||
static td::Result<std::unique_ptr<ConfigInfo>> extract_config(Ref<vm::Cell> mc_state_root, int mode = 0);
|
||||
|
|
|
@ -478,7 +478,7 @@ void add_partial_storage_payment(td::BigInt256& payment, ton::UnixTime delta, co
|
|||
b.mul_short(prices.bit_price);
|
||||
}
|
||||
b += c;
|
||||
b.mul_short(delta);
|
||||
b.mul_short(delta).normalize();
|
||||
CHECK(b.sgn() >= 0);
|
||||
payment += b;
|
||||
}
|
||||
|
@ -506,8 +506,7 @@ td::RefInt256 StoragePrices::compute_storage_fees(ton::UnixTime now, const std::
|
|||
}
|
||||
upto = valid_until;
|
||||
}
|
||||
total.unique_write().rshift(16, 1); // divide by 2^16 with ceil rounding to obtain nanograms
|
||||
return total;
|
||||
return td::rshift(total, 16, 1); // divide by 2^16 with ceil rounding to obtain nanograms
|
||||
}
|
||||
|
||||
td::RefInt256 Account::compute_storage_fees(ton::UnixTime now, const std::vector<block::StoragePrices>& pricing) const {
|
||||
|
@ -635,14 +634,15 @@ bool Transaction::unpack_input_msg(bool ihr_delivered, const ActionPhaseConfig*
|
|||
vm::CellBuilder cb;
|
||||
if (!(cs.advance(2) && block::gen::t_StateInit.fetch_to(cs, state_init) &&
|
||||
cb.append_cellslice_bool(std::move(state_init)) && cb.finalize_to(in_msg_state) &&
|
||||
block::gen::t_StateInit.validate_ref(in_msg_state))) {
|
||||
block::gen::t_StateInitWithLibs.validate_ref(in_msg_state))) {
|
||||
LOG(DEBUG) << "cannot parse StateInit in inbound message";
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 3: { // (just$1 (right$1 _:^StateInit ))
|
||||
if (!(cs.advance(2) && cs.fetch_ref_to(in_msg_state) && block::gen::t_StateInit.validate_ref(in_msg_state))) {
|
||||
if (!(cs.advance(2) && cs.fetch_ref_to(in_msg_state) &&
|
||||
block::gen::t_StateInitWithLibs.validate_ref(in_msg_state))) {
|
||||
LOG(DEBUG) << "cannot parse ^StateInit in inbound message";
|
||||
return false;
|
||||
}
|
||||
|
@ -671,6 +671,12 @@ bool Transaction::unpack_input_msg(bool ihr_delivered, const ActionPhaseConfig*
|
|||
return false;
|
||||
}
|
||||
total_fees += in_fwd_fee;
|
||||
if (account.workchain == ton::masterchainId && cfg->mc_blackhole_addr &&
|
||||
cfg->mc_blackhole_addr.value() == account.addr) {
|
||||
blackhole_burned.grams = msg_balance_remaining.grams;
|
||||
msg_balance_remaining.grams = td::zero_refint();
|
||||
LOG(DEBUG) << "Burning " << blackhole_burned.grams << " nanoton (blackhole address)";
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -724,6 +730,9 @@ bool Transaction::prepare_storage_phase(const StoragePhaseConfig& cfg, bool forc
|
|||
}
|
||||
break;
|
||||
}
|
||||
if (cfg.enable_due_payment) {
|
||||
due_payment = total_due;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (adjust_msg_value && msg_balance_remaining.grams > balance.grams) {
|
||||
|
@ -917,7 +926,7 @@ Ref<vm::Tuple> Transaction::prepare_vm_c7(const ComputePhaseConfig& cfg) const {
|
|||
throw CollatorError{"cannot generate valid SmartContractInfo"};
|
||||
return {};
|
||||
}
|
||||
auto tuple = vm::make_tuple_ref(
|
||||
std::vector<vm::StackEntry> tuple = {
|
||||
td::make_refint(0x076ef1ea), // [ magic:0x076ef1ea
|
||||
td::zero_refint(), // actions:Integer
|
||||
td::zero_refint(), // msgs_sent:Integer
|
||||
|
@ -926,10 +935,27 @@ Ref<vm::Tuple> Transaction::prepare_vm_c7(const ComputePhaseConfig& cfg) const {
|
|||
td::make_refint(start_lt), // trans_lt:Integer
|
||||
std::move(rand_seed_int), // rand_seed:Integer
|
||||
balance.as_vm_tuple(), // balance_remaining:[Integer (Maybe Cell)]
|
||||
my_addr, // myself:MsgAddressInt
|
||||
vm::StackEntry::maybe(cfg.global_config)); // global_config:(Maybe Cell) ] = SmartContractInfo;
|
||||
LOG(DEBUG) << "SmartContractInfo initialized with " << vm::StackEntry(tuple).to_string();
|
||||
return vm::make_tuple_ref(std::move(tuple));
|
||||
my_addr, // myself:MsgAddressInt
|
||||
vm::StackEntry::maybe(cfg.global_config) // global_config:(Maybe Cell) ] = SmartContractInfo;
|
||||
};
|
||||
if (cfg.global_version >= 4) {
|
||||
tuple.push_back(new_code); // code:Cell
|
||||
if (msg_balance_remaining.is_valid()) {
|
||||
tuple.push_back(msg_balance_remaining.as_vm_tuple()); // in_msg_value:[Integer (Maybe Cell)]
|
||||
} else {
|
||||
tuple.push_back(block::CurrencyCollection::zero().as_vm_tuple());
|
||||
}
|
||||
tuple.push_back(storage_phase->fees_collected); // storage_fees:Integer
|
||||
|
||||
// See crypto/block/mc-config.cpp#2115 (get_prev_blocks_info)
|
||||
// [ wc:Integer shard:Integer seqno:Integer root_hash:Integer file_hash:Integer] = BlockId;
|
||||
// [ last_mc_blocks:[BlockId...]
|
||||
// prev_key_block:BlockId ] : PrevBlocksInfo
|
||||
tuple.push_back(cfg.prev_blocks_info.not_null() ? vm::StackEntry(cfg.prev_blocks_info) : vm::StackEntry());
|
||||
}
|
||||
auto tuple_ref = td::make_cnt_ref<std::vector<vm::StackEntry>>(std::move(tuple));
|
||||
LOG(DEBUG) << "SmartContractInfo initialized with " << vm::StackEntry(tuple_ref).to_string();
|
||||
return vm::make_tuple_ref(std::move(tuple_ref));
|
||||
}
|
||||
|
||||
int output_actions_count(Ref<vm::Cell> list) {
|
||||
|
@ -1074,12 +1100,19 @@ bool Transaction::prepare_compute_phase(const ComputePhaseConfig& cfg) {
|
|||
if (cfg.vm_log_verbosity > 1) {
|
||||
vm_log.log_mask |= vm::VmLog::ExecLocation;
|
||||
if (cfg.vm_log_verbosity > 2) {
|
||||
vm_log.log_mask |= vm::VmLog::DumpStack | vm::VmLog::GasRemaining;
|
||||
vm_log.log_mask |= vm::VmLog::GasRemaining;
|
||||
if (cfg.vm_log_verbosity > 3) {
|
||||
vm_log.log_mask |= vm::VmLog::DumpStack;
|
||||
if (cfg.vm_log_verbosity > 4) {
|
||||
vm_log.log_mask |= vm::VmLog::DumpStackVerbose;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
vm::VmState vm{new_code, std::move(stack), gas, 1, new_data, vm_log, compute_vm_libraries(cfg)};
|
||||
vm.set_max_data_depth(cfg.max_vm_data_depth);
|
||||
vm.set_global_version(cfg.global_version);
|
||||
vm.set_c7(prepare_vm_c7(cfg)); // tuple with SmartContractInfo
|
||||
vm.set_chksig_always_succeed(cfg.ignore_chksig);
|
||||
// vm.incr_stack_trace(1); // enable stack dump after each step
|
||||
|
@ -1161,6 +1194,7 @@ bool Transaction::prepare_action_phase(const ActionPhaseConfig& cfg) {
|
|||
ap.total_fwd_fees = td::zero_refint();
|
||||
ap.total_action_fees = td::zero_refint();
|
||||
ap.reserved_balance.set_zero();
|
||||
ap.action_fine = td::zero_refint();
|
||||
|
||||
td::Ref<vm::Cell> old_code = new_code, old_data = new_data, old_library = new_library;
|
||||
auto enforce_state_limits = [&]() {
|
||||
|
@ -1227,6 +1261,7 @@ bool Transaction::prepare_action_phase(const ActionPhaseConfig& cfg) {
|
|||
int tag = block::gen::t_OutAction.get_tag(cs);
|
||||
CHECK(tag >= 0);
|
||||
int err_code = 34;
|
||||
ap.need_bounce_on_fail = false;
|
||||
switch (tag) {
|
||||
case block::gen::OutAction::action_set_code:
|
||||
err_code = try_action_set_code(cs, ap, cfg);
|
||||
|
@ -1257,12 +1292,24 @@ bool Transaction::prepare_action_phase(const ActionPhaseConfig& cfg) {
|
|||
ap.no_funds = true;
|
||||
}
|
||||
LOG(DEBUG) << "invalid action " << ap.result_arg << " in action list: error code " << ap.result_code;
|
||||
// This is reuqired here because changes to libraries are applied even if action phase fails
|
||||
// This is reuqired here because changes to libraries are applied even if actipn phase fails
|
||||
enforce_state_limits();
|
||||
if (cfg.action_fine_enabled) {
|
||||
ap.action_fine = std::min(ap.action_fine, balance.grams);
|
||||
ap.total_action_fees = ap.action_fine;
|
||||
balance.grams -= ap.action_fine;
|
||||
total_fees += ap.action_fine;
|
||||
}
|
||||
if (ap.need_bounce_on_fail) {
|
||||
ap.bounce = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (cfg.action_fine_enabled) {
|
||||
ap.total_action_fees += ap.action_fine;
|
||||
}
|
||||
end_lt = ap.end_lt;
|
||||
if (ap.new_code.not_null()) {
|
||||
new_code = ap.new_code;
|
||||
|
@ -1308,7 +1355,17 @@ int Transaction::try_action_change_library(vm::CellSlice& cs, ActionPhase& ap, c
|
|||
if (!tlb::unpack_exact(cs, rec)) {
|
||||
return -1;
|
||||
}
|
||||
// mode: +0 = remove library, +1 = add private library, +2 = add public library
|
||||
// mode: +0 = remove library, +1 = add private library, +2 = add public library, +16 - bounce on fail
|
||||
if (rec.mode & 16) {
|
||||
if (!cfg.bounce_on_fail_enabled) {
|
||||
return -1;
|
||||
}
|
||||
ap.need_bounce_on_fail = true;
|
||||
rec.mode &= ~16;
|
||||
}
|
||||
if (rec.mode > 2) {
|
||||
return -1;
|
||||
}
|
||||
Ref<vm::Cell> lib_ref = rec.libref->prefetch_ref();
|
||||
ton::Bits256 hash;
|
||||
if (lib_ref.not_null()) {
|
||||
|
@ -1522,9 +1579,22 @@ bool Transaction::check_rewrite_dest_addr(Ref<vm::CellSlice>& dest_addr, const A
|
|||
int Transaction::try_action_send_msg(const vm::CellSlice& cs0, ActionPhase& ap, const ActionPhaseConfig& cfg,
|
||||
int redoing) {
|
||||
block::gen::OutAction::Record_action_send_msg act_rec;
|
||||
// mode: +128 = attach all remaining balance, +64 = attach all remaining balance of the inbound message, +32 = delete smart contract if balance becomes zero, +1 = pay message fees, +2 = skip if message cannot be sent
|
||||
// mode:
|
||||
// +128 = attach all remaining balance
|
||||
// +64 = attach all remaining balance of the inbound message
|
||||
// +32 = delete smart contract if balance becomes zero
|
||||
// +1 = pay message fees
|
||||
// +2 = skip if message cannot be sent
|
||||
// +16 = bounce if action fails
|
||||
vm::CellSlice cs{cs0};
|
||||
if (!tlb::unpack_exact(cs, act_rec) || (act_rec.mode & ~0xe3) || (act_rec.mode & 0xc0) == 0xc0) {
|
||||
if (!tlb::unpack_exact(cs, act_rec)) {
|
||||
return -1;
|
||||
}
|
||||
if ((act_rec.mode & 16) && cfg.bounce_on_fail_enabled) {
|
||||
act_rec.mode &= ~16;
|
||||
ap.need_bounce_on_fail = true;
|
||||
}
|
||||
if ((act_rec.mode & ~0xe3) || (act_rec.mode & 0xc0) == 0xc0) {
|
||||
return -1;
|
||||
}
|
||||
bool skip_invalid = (act_rec.mode & 2);
|
||||
|
@ -1534,6 +1604,10 @@ int Transaction::try_action_send_msg(const vm::CellSlice& cs0, ActionPhase& ap,
|
|||
if (!tlb::type_unpack_cell(act_rec.out_msg, block::gen::t_MessageRelaxed_Any, msg)) {
|
||||
return -1;
|
||||
}
|
||||
if (!block::tlb::validate_message_relaxed_libs(act_rec.out_msg)) {
|
||||
LOG(DEBUG) << "outbound message has invalid libs in StateInit";
|
||||
return -1;
|
||||
}
|
||||
if (redoing >= 1) {
|
||||
if (msg.init->size_refs() >= 2) {
|
||||
LOG(DEBUG) << "moving the StateInit of a suggested outbound message into a separate cell";
|
||||
|
@ -1547,7 +1621,7 @@ int Transaction::try_action_send_msg(const vm::CellSlice& cs0, ActionPhase& ap,
|
|||
&& cb.store_long_bool(3, 2) // (just (right ... ))
|
||||
&& cb.store_ref_bool(std::move(cell)) // z:^StateInit
|
||||
&& cb.finalize_to(cell));
|
||||
msg.init = vm::load_cell_slice_ref(std::move(cell));
|
||||
msg.init = vm::load_cell_slice_ref(cell);
|
||||
} else {
|
||||
redoing = 2;
|
||||
}
|
||||
|
@ -1564,7 +1638,7 @@ int Transaction::try_action_send_msg(const vm::CellSlice& cs0, ActionPhase& ap,
|
|||
&& cb.store_long_bool(1, 1) // (right ... )
|
||||
&& cb.store_ref_bool(std::move(cell)) // x:^X
|
||||
&& cb.finalize_to(cell));
|
||||
msg.body = vm::load_cell_slice_ref(std::move(cell));
|
||||
msg.body = vm::load_cell_slice_ref(cell);
|
||||
}
|
||||
|
||||
block::gen::CommonMsgInfoRelaxed::Record_int_msg_info info;
|
||||
|
@ -1612,30 +1686,84 @@ int Transaction::try_action_send_msg(const vm::CellSlice& cs0, ActionPhase& ap,
|
|||
|
||||
// fetch message pricing info
|
||||
const MsgPrices& msg_prices = cfg.fetch_msg_prices(to_mc || account.is_masterchain());
|
||||
// If action fails, account is required to pay fine_per_cell for every visited cell
|
||||
// Number of visited cells is limited depending on available funds
|
||||
unsigned max_cells = cfg.size_limits.max_msg_cells;
|
||||
td::uint64 fine_per_cell = 0;
|
||||
if (cfg.action_fine_enabled && !account.is_special) {
|
||||
fine_per_cell = (msg_prices.cell_price >> 16) / 4;
|
||||
td::RefInt256 funds = ap.remaining_balance.grams;
|
||||
if (!ext_msg && !(act_rec.mode & 0x80) && !(act_rec.mode & 1)) {
|
||||
if (!block::tlb::t_CurrencyCollection.validate_csr(info.value)) {
|
||||
LOG(DEBUG) << "invalid value:CurrencyCollection in proposed outbound message";
|
||||
return skip_invalid ? 0 : 37;
|
||||
}
|
||||
block::CurrencyCollection value;
|
||||
CHECK(value.unpack(info.value));
|
||||
CHECK(value.grams.not_null());
|
||||
td::RefInt256 new_funds = value.grams;
|
||||
if (act_rec.mode & 0x40) {
|
||||
if (msg_balance_remaining.is_valid()) {
|
||||
new_funds += msg_balance_remaining.grams;
|
||||
}
|
||||
if (compute_phase) {
|
||||
new_funds -= compute_phase->gas_fees;
|
||||
}
|
||||
new_funds -= ap.action_fine;
|
||||
if (new_funds->sgn() < 0) {
|
||||
LOG(DEBUG)
|
||||
<< "not enough value to transfer with the message: all of the inbound message value has been consumed";
|
||||
return skip_invalid ? 0 : 37;
|
||||
}
|
||||
}
|
||||
funds = std::min(funds, new_funds);
|
||||
}
|
||||
if (funds->cmp(max_cells * fine_per_cell) < 0) {
|
||||
max_cells = static_cast<unsigned>((funds / td::make_refint(fine_per_cell))->to_long());
|
||||
}
|
||||
}
|
||||
// compute size of message
|
||||
vm::CellStorageStat sstat; // for message size
|
||||
vm::CellStorageStat sstat(max_cells); // for message size
|
||||
// preliminary storage estimation of the resulting message
|
||||
unsigned max_merkle_depth = 0;
|
||||
auto add_used_storage = [&](const auto& x, unsigned skip_root_count) {
|
||||
auto add_used_storage = [&](const auto& x, unsigned skip_root_count) -> td::Status {
|
||||
if (x.not_null()) {
|
||||
auto res = sstat.add_used_storage(x, true, skip_root_count).move_as_ok();
|
||||
TRY_RESULT(res, sstat.add_used_storage(x, true, skip_root_count));
|
||||
max_merkle_depth = std::max(max_merkle_depth, res.max_merkle_depth);
|
||||
}
|
||||
return td::Status::OK();
|
||||
};
|
||||
add_used_storage(msg.init, 3); // message init
|
||||
add_used_storage(msg.body, 3); // message body (the root cell itself is not counted)
|
||||
if (!ext_msg) {
|
||||
add_used_storage(info.value->prefetch_ref(), 0);
|
||||
}
|
||||
LOG(DEBUG) << "storage paid for a message: " << sstat.cells << " cells, " << sstat.bits << " bits";
|
||||
if (sstat.bits > cfg.size_limits.max_msg_bits || sstat.cells > cfg.size_limits.max_msg_cells) {
|
||||
auto collect_fine = [&] {
|
||||
if (cfg.action_fine_enabled && !account.is_special) {
|
||||
td::uint64 fine = fine_per_cell * std::min<td::uint64>(max_cells, sstat.cells);
|
||||
if (ap.remaining_balance.grams->cmp(fine) < 0) {
|
||||
fine = ap.remaining_balance.grams->to_long();
|
||||
}
|
||||
ap.action_fine += fine;
|
||||
ap.remaining_balance.grams -= fine;
|
||||
}
|
||||
};
|
||||
if (sstat.cells > max_cells && max_cells < cfg.size_limits.max_msg_cells) {
|
||||
LOG(DEBUG) << "not enough funds to process a message (max_cells=" << max_cells << ")";
|
||||
collect_fine();
|
||||
return skip_invalid ? 0 : 40;
|
||||
}
|
||||
if (sstat.bits > cfg.size_limits.max_msg_bits || sstat.cells > max_cells) {
|
||||
LOG(DEBUG) << "message too large, invalid";
|
||||
collect_fine();
|
||||
return skip_invalid ? 0 : 40;
|
||||
}
|
||||
if (max_merkle_depth > max_allowed_merkle_depth) {
|
||||
LOG(DEBUG) << "message has too big merkle depth, invalid";
|
||||
collect_fine();
|
||||
return skip_invalid ? 0 : 40;
|
||||
}
|
||||
LOG(DEBUG) << "storage paid for a message: " << sstat.cells << " cells, " << sstat.bits << " bits";
|
||||
|
||||
// compute forwarding fees
|
||||
auto fees_c = msg_prices.compute_fwd_ihr_fees(sstat.cells, sstat.bits, info.ihr_disabled);
|
||||
|
@ -1664,6 +1792,7 @@ int Transaction::try_action_send_msg(const vm::CellSlice& cs0, ActionPhase& ap,
|
|||
// ...
|
||||
if (!block::tlb::t_CurrencyCollection.validate_csr(info.value)) {
|
||||
LOG(DEBUG) << "invalid value:CurrencyCollection in proposed outbound message";
|
||||
collect_fine();
|
||||
return skip_invalid ? 0 : 37;
|
||||
}
|
||||
if (info.ihr_disabled) {
|
||||
|
@ -1682,11 +1811,15 @@ int Transaction::try_action_send_msg(const vm::CellSlice& cs0, ActionPhase& ap,
|
|||
} else if (act_rec.mode & 0x40) {
|
||||
// attach all remaining balance of the inbound message (in addition to the original value)
|
||||
req += msg_balance_remaining;
|
||||
if (!(act_rec.mode & 1) && compute_phase) {
|
||||
req -= compute_phase->gas_fees;
|
||||
if (!(act_rec.mode & 1)) {
|
||||
req -= ap.action_fine;
|
||||
if (compute_phase) {
|
||||
req -= compute_phase->gas_fees;
|
||||
}
|
||||
if (!req.is_valid()) {
|
||||
LOG(DEBUG)
|
||||
<< "not enough value to transfer with the message: all of the inbound message value has been consumed";
|
||||
collect_fine();
|
||||
return skip_invalid ? 0 : 37;
|
||||
}
|
||||
}
|
||||
|
@ -1702,6 +1835,7 @@ int Transaction::try_action_send_msg(const vm::CellSlice& cs0, ActionPhase& ap,
|
|||
// receiver pays the fees (but cannot)
|
||||
LOG(DEBUG) << "not enough value attached to the message to pay forwarding fees : have " << req.grams << ", need "
|
||||
<< fees_total;
|
||||
collect_fine();
|
||||
return skip_invalid ? 0 : 37; // not enough grams
|
||||
} else {
|
||||
// decrease message value
|
||||
|
@ -1712,6 +1846,7 @@ int Transaction::try_action_send_msg(const vm::CellSlice& cs0, ActionPhase& ap,
|
|||
if (ap.remaining_balance.grams < req_grams_brutto) {
|
||||
LOG(DEBUG) << "not enough grams to transfer with the message : remaining balance is "
|
||||
<< ap.remaining_balance.to_str() << ", need " << req_grams_brutto << " (including forwarding fees)";
|
||||
collect_fine();
|
||||
return skip_invalid ? 0 : 37; // not enough grams
|
||||
}
|
||||
|
||||
|
@ -1721,6 +1856,7 @@ int Transaction::try_action_send_msg(const vm::CellSlice& cs0, ActionPhase& ap,
|
|||
LOG(DEBUG) << "not enough extra currency to send with the message: "
|
||||
<< block::CurrencyCollection{0, req.extra}.to_str() << " required, only "
|
||||
<< block::CurrencyCollection{0, ap.remaining_balance.extra}.to_str() << " available";
|
||||
collect_fine();
|
||||
return skip_invalid ? 0 : 38; // not enough (extra) funds
|
||||
}
|
||||
if (ap.remaining_balance.extra.not_null() || req.extra.not_null()) {
|
||||
|
@ -1743,7 +1879,11 @@ int Transaction::try_action_send_msg(const vm::CellSlice& cs0, ActionPhase& ap,
|
|||
vm::CellBuilder cb;
|
||||
if (!tlb::type_pack(cb, block::gen::t_MessageRelaxed_Any, msg)) {
|
||||
LOG(DEBUG) << "outbound message does not fit into a cell after rewriting";
|
||||
return redoing < 2 ? -2 : (skip_invalid ? 0 : 39);
|
||||
if (redoing == 2) {
|
||||
collect_fine();
|
||||
return skip_invalid ? 0 : 39;
|
||||
}
|
||||
return -2;
|
||||
}
|
||||
|
||||
new_msg_bits = cb.size();
|
||||
|
@ -1765,6 +1905,7 @@ int Transaction::try_action_send_msg(const vm::CellSlice& cs0, ActionPhase& ap,
|
|||
// external messages also have forwarding fees
|
||||
if (ap.remaining_balance.grams < fwd_fee) {
|
||||
LOG(DEBUG) << "not enough funds to pay for an outbound external message";
|
||||
collect_fine();
|
||||
return skip_invalid ? 0 : 37; // not enough grams
|
||||
}
|
||||
// repack message
|
||||
|
@ -1778,7 +1919,11 @@ int Transaction::try_action_send_msg(const vm::CellSlice& cs0, ActionPhase& ap,
|
|||
vm::CellBuilder cb;
|
||||
if (!tlb::type_pack(cb, block::gen::t_MessageRelaxed_Any, msg)) {
|
||||
LOG(DEBUG) << "outbound message does not fit into a cell after rewriting";
|
||||
return redoing < 2 ? -2 : (skip_invalid ? 0 : 39);
|
||||
if (redoing == 2) {
|
||||
collect_fine();
|
||||
return (skip_invalid ? 0 : 39);
|
||||
}
|
||||
return -2;
|
||||
}
|
||||
|
||||
new_msg_bits = cb.size();
|
||||
|
@ -1793,12 +1938,14 @@ int Transaction::try_action_send_msg(const vm::CellSlice& cs0, ActionPhase& ap,
|
|||
|
||||
if (!block::tlb::t_Message.validate_ref(new_msg)) {
|
||||
LOG(ERROR) << "generated outbound message is not a valid (Message Any) according to hand-written check";
|
||||
collect_fine();
|
||||
return -1;
|
||||
}
|
||||
if (!block::gen::t_Message_Any.validate_ref(new_msg)) {
|
||||
LOG(ERROR) << "generated outbound message is not a valid (Message Any) according to automated check";
|
||||
block::gen::t_Message_Any.print_ref(std::cerr, new_msg);
|
||||
vm::load_cell_slice(new_msg).print_rec(std::cerr);
|
||||
collect_fine();
|
||||
return -1;
|
||||
}
|
||||
if (verbosity > 2) {
|
||||
|
@ -1826,7 +1973,14 @@ int Transaction::try_action_send_msg(const vm::CellSlice& cs0, ActionPhase& ap,
|
|||
|
||||
int Transaction::try_action_reserve_currency(vm::CellSlice& cs, ActionPhase& ap, const ActionPhaseConfig& cfg) {
|
||||
block::gen::OutAction::Record_action_reserve_currency rec;
|
||||
if (!tlb::unpack_exact(cs, rec) || (rec.mode & ~15)) {
|
||||
if (!tlb::unpack_exact(cs, rec)) {
|
||||
return -1;
|
||||
}
|
||||
if ((rec.mode & 16) && cfg.bounce_on_fail_enabled) {
|
||||
rec.mode &= ~16;
|
||||
ap.need_bounce_on_fail = true;
|
||||
}
|
||||
if (rec.mode & ~15) {
|
||||
return -1;
|
||||
}
|
||||
int mode = rec.mode;
|
||||
|
@ -1973,6 +2127,9 @@ bool Transaction::prepare_bounce_phase(const ActionPhaseConfig& cfg) {
|
|||
if (compute_phase && compute_phase->gas_fees.not_null()) {
|
||||
msg_balance.grams -= compute_phase->gas_fees;
|
||||
}
|
||||
if (action_phase && action_phase->action_fine.not_null()) {
|
||||
msg_balance.grams -= action_phase->action_fine;
|
||||
}
|
||||
if ((msg_balance.grams < 0) ||
|
||||
(msg_balance.grams->signed_fits_bits(64) && msg_balance.grams->to_long() < (long long)bp.fwd_fees)) {
|
||||
// not enough funds
|
||||
|
@ -2553,17 +2710,27 @@ bool Account::libraries_changed() const {
|
|||
}
|
||||
}
|
||||
|
||||
td::Status FetchConfigParams::fetch_config_params(const block::Config& config,
|
||||
Ref<vm::Cell>* old_mparams,
|
||||
std::vector<block::StoragePrices>* storage_prices,
|
||||
block::StoragePhaseConfig* storage_phase_cfg,
|
||||
td::BitArray<256>* rand_seed,
|
||||
block::ComputePhaseConfig* compute_phase_cfg,
|
||||
block::ActionPhaseConfig* action_phase_cfg,
|
||||
td::RefInt256* masterchain_create_fee,
|
||||
td::RefInt256* basechain_create_fee,
|
||||
ton::WorkchainId wc,
|
||||
ton::UnixTime now) {
|
||||
td::Status FetchConfigParams::fetch_config_params(
|
||||
const block::ConfigInfo& config, Ref<vm::Cell>* old_mparams, std::vector<block::StoragePrices>* storage_prices,
|
||||
StoragePhaseConfig* storage_phase_cfg, td::BitArray<256>* rand_seed, ComputePhaseConfig* compute_phase_cfg,
|
||||
ActionPhaseConfig* action_phase_cfg, td::RefInt256* masterchain_create_fee, td::RefInt256* basechain_create_fee,
|
||||
ton::WorkchainId wc, ton::UnixTime now) {
|
||||
auto prev_blocks_info = config.get_prev_blocks_info();
|
||||
if (prev_blocks_info.is_error()) {
|
||||
return prev_blocks_info.move_as_error_prefix(
|
||||
td::Status::Error(-668, "cannot fetch prev blocks info from masterchain configuration: "));
|
||||
}
|
||||
return fetch_config_params(config, prev_blocks_info.move_as_ok(), old_mparams, storage_prices, storage_phase_cfg,
|
||||
rand_seed, compute_phase_cfg, action_phase_cfg, masterchain_create_fee,
|
||||
basechain_create_fee, wc, now);
|
||||
}
|
||||
|
||||
td::Status FetchConfigParams::fetch_config_params(
|
||||
const block::Config& config, td::Ref<vm::Tuple> prev_blocks_info, Ref<vm::Cell>* old_mparams,
|
||||
std::vector<block::StoragePrices>* storage_prices, StoragePhaseConfig* storage_phase_cfg,
|
||||
td::BitArray<256>* rand_seed, ComputePhaseConfig* compute_phase_cfg, ActionPhaseConfig* action_phase_cfg,
|
||||
td::RefInt256* masterchain_create_fee, td::RefInt256* basechain_create_fee, ton::WorkchainId wc,
|
||||
ton::UnixTime now) {
|
||||
*old_mparams = config.get_config_param(9);
|
||||
{
|
||||
auto res = config.get_storage_prices();
|
||||
|
@ -2588,9 +2755,14 @@ td::Status FetchConfigParams::fetch_config_params(const block::Config& config,
|
|||
storage_phase_cfg->delete_due_limit)) {
|
||||
return td::Status::Error(-668, "cannot unpack current gas prices and limits from masterchain configuration");
|
||||
}
|
||||
storage_phase_cfg->enable_due_payment = config.get_global_version() >= 4;
|
||||
compute_phase_cfg->block_rand_seed = *rand_seed;
|
||||
compute_phase_cfg->max_vm_data_depth = size_limits.max_vm_data_depth;
|
||||
compute_phase_cfg->global_config = config.get_root_cell();
|
||||
compute_phase_cfg->global_version = config.get_global_version();
|
||||
if (compute_phase_cfg->global_version >= 4) {
|
||||
compute_phase_cfg->prev_blocks_info = std::move(prev_blocks_info);
|
||||
}
|
||||
compute_phase_cfg->suspended_addresses = config.get_suspended_addresses(now);
|
||||
}
|
||||
{
|
||||
|
@ -2613,6 +2785,9 @@ td::Status FetchConfigParams::fetch_config_params(const block::Config& config,
|
|||
action_phase_cfg->workchains = &config.get_workchain_list();
|
||||
action_phase_cfg->bounce_msg_body = (config.has_capability(ton::capBounceMsgBody) ? 256 : 0);
|
||||
action_phase_cfg->size_limits = size_limits;
|
||||
action_phase_cfg->action_fine_enabled = config.get_global_version() >= 4;
|
||||
action_phase_cfg->bounce_on_fail_enabled = config.get_global_version() >= 4;
|
||||
action_phase_cfg->mc_blackhole_addr = config.get_burning_config().blackhole_addr;
|
||||
}
|
||||
{
|
||||
// fetch block_grams_created
|
||||
|
|
|
@ -80,6 +80,7 @@ struct StoragePhaseConfig {
|
|||
const std::vector<block::StoragePrices>* pricing{nullptr};
|
||||
td::RefInt256 freeze_due_limit;
|
||||
td::RefInt256 delete_due_limit;
|
||||
bool enable_due_payment{false};
|
||||
StoragePhaseConfig() = default;
|
||||
StoragePhaseConfig(const std::vector<block::StoragePrices>* _pricing, td::RefInt256 freeze_limit = {},
|
||||
td::RefInt256 delete_limit = {})
|
||||
|
@ -112,8 +113,11 @@ struct ComputePhaseConfig {
|
|||
bool ignore_chksig{false};
|
||||
bool with_vm_log{false};
|
||||
td::uint16 max_vm_data_depth = 512;
|
||||
int global_version = 0;
|
||||
Ref<vm::Tuple> prev_blocks_info;
|
||||
std::unique_ptr<vm::Dictionary> suspended_addresses;
|
||||
int vm_log_verbosity = 0;
|
||||
|
||||
ComputePhaseConfig(td::uint64 _gas_price = 0, td::uint64 _gas_limit = 0, td::uint64 _gas_credit = 0)
|
||||
: gas_price(_gas_price), gas_limit(_gas_limit), special_gas_limit(_gas_limit), gas_credit(_gas_credit) {
|
||||
compute_threshold();
|
||||
|
@ -153,6 +157,9 @@ struct ActionPhaseConfig {
|
|||
MsgPrices fwd_mc; // from/to masterchain
|
||||
SizeLimitsConfig size_limits;
|
||||
const WorkchainSet* workchains{nullptr};
|
||||
bool action_fine_enabled{false};
|
||||
bool bounce_on_fail_enabled{false};
|
||||
td::optional<td::Bits256> mc_blackhole_addr;
|
||||
const MsgPrices& fetch_msg_prices(bool is_masterchain) const {
|
||||
return is_masterchain ? fwd_mc : fwd_std;
|
||||
}
|
||||
|
@ -209,6 +216,9 @@ struct ActionPhase {
|
|||
std::vector<Ref<vm::Cell>> out_msgs;
|
||||
ton::LogicalTime end_lt;
|
||||
unsigned long long tot_msg_bits{0}, tot_msg_cells{0};
|
||||
td::RefInt256 action_fine;
|
||||
bool need_bounce_on_fail = false;
|
||||
bool bounce = false;
|
||||
};
|
||||
|
||||
struct BouncePhase {
|
||||
|
@ -332,6 +342,7 @@ struct Transaction {
|
|||
td::RefInt256 due_payment;
|
||||
td::RefInt256 in_fwd_fee, msg_fwd_fees;
|
||||
block::CurrencyCollection total_fees{0};
|
||||
block::CurrencyCollection blackhole_burned{0};
|
||||
ton::UnixTime last_paid;
|
||||
Ref<vm::Cell> root;
|
||||
Ref<vm::Cell> new_total_state;
|
||||
|
@ -400,17 +411,18 @@ struct Transaction {
|
|||
} // namespace transaction
|
||||
|
||||
struct FetchConfigParams {
|
||||
static td::Status fetch_config_params(const block::Config& config,
|
||||
Ref<vm::Cell>* old_mparams,
|
||||
std::vector<block::StoragePrices>* storage_prices,
|
||||
StoragePhaseConfig* storage_phase_cfg,
|
||||
td::BitArray<256>* rand_seed,
|
||||
ComputePhaseConfig* compute_phase_cfg,
|
||||
ActionPhaseConfig* action_phase_cfg,
|
||||
td::RefInt256* masterchain_create_fee,
|
||||
td::RefInt256* basechain_create_fee,
|
||||
ton::WorkchainId wc,
|
||||
ton::UnixTime now);
|
||||
static td::Status fetch_config_params(const block::ConfigInfo& config, Ref<vm::Cell>* old_mparams,
|
||||
std::vector<block::StoragePrices>* storage_prices,
|
||||
StoragePhaseConfig* storage_phase_cfg, td::BitArray<256>* rand_seed,
|
||||
ComputePhaseConfig* compute_phase_cfg, ActionPhaseConfig* action_phase_cfg,
|
||||
td::RefInt256* masterchain_create_fee, td::RefInt256* basechain_create_fee,
|
||||
ton::WorkchainId wc, ton::UnixTime now);
|
||||
static td::Status fetch_config_params(const block::Config& config, Ref<vm::Tuple> prev_blocks_info,
|
||||
Ref<vm::Cell>* old_mparams, std::vector<block::StoragePrices>* storage_prices,
|
||||
StoragePhaseConfig* storage_phase_cfg, td::BitArray<256>* rand_seed,
|
||||
ComputePhaseConfig* compute_phase_cfg, ActionPhaseConfig* action_phase_cfg,
|
||||
td::RefInt256* masterchain_create_fee, td::RefInt256* basechain_create_fee,
|
||||
ton::WorkchainId wc, ton::UnixTime now);
|
||||
};
|
||||
|
||||
} // namespace block
|
||||
|
|
91
crypto/ellcurve/p256.cpp
Normal file
91
crypto/ellcurve/p256.cpp
Normal file
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "p256.h"
|
||||
#include "td/utils/check.h"
|
||||
#include "td/utils/misc.h"
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/ec.h>
|
||||
#include <iostream>
|
||||
|
||||
namespace td {
|
||||
|
||||
td::Status p256_check_signature(td::Slice data, td::Slice public_key, td::Slice signature) {
|
||||
CHECK(public_key.size() == 33);
|
||||
CHECK(signature.size() == 64);
|
||||
|
||||
EVP_PKEY_CTX* pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, nullptr);
|
||||
if (pctx == nullptr) {
|
||||
return td::Status::Error("Can't create EVP_PKEY_CTX");
|
||||
}
|
||||
SCOPE_EXIT {
|
||||
EVP_PKEY_CTX_free(pctx);
|
||||
};
|
||||
if (EVP_PKEY_paramgen_init(pctx) <= 0) {
|
||||
return td::Status::Error("EVP_PKEY_paramgen_init failed");
|
||||
}
|
||||
if (EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, NID_X9_62_prime256v1) <= 0) {
|
||||
return td::Status::Error("EVP_PKEY_CTX_set_ec_paramgen_curve_nid failed");
|
||||
}
|
||||
EVP_PKEY* pkey = nullptr;
|
||||
if (EVP_PKEY_paramgen(pctx, &pkey) <= 0) {
|
||||
return td::Status::Error("EVP_PKEY_paramgen failed");
|
||||
}
|
||||
SCOPE_EXIT {
|
||||
EVP_PKEY_free(pkey);
|
||||
};
|
||||
if (EVP_PKEY_set1_tls_encodedpoint(pkey, public_key.ubegin(), public_key.size()) <= 0) {
|
||||
return td::Status::Error("Failed to import public key");
|
||||
}
|
||||
EVP_MD_CTX* md_ctx = EVP_MD_CTX_new();
|
||||
if (md_ctx == nullptr) {
|
||||
return td::Status::Error("Can't create EVP_MD_CTX");
|
||||
}
|
||||
SCOPE_EXIT {
|
||||
EVP_MD_CTX_free(md_ctx);
|
||||
};
|
||||
if (EVP_DigestVerifyInit(md_ctx, nullptr, nullptr, nullptr, pkey) <= 0) {
|
||||
return td::Status::Error("Can't init DigestVerify");
|
||||
}
|
||||
ECDSA_SIG* sig = ECDSA_SIG_new();
|
||||
SCOPE_EXIT {
|
||||
ECDSA_SIG_free(sig);
|
||||
};
|
||||
unsigned char buf[33];
|
||||
buf[0] = 0;
|
||||
std::copy(signature.ubegin(), signature.ubegin() + 32, buf + 1);
|
||||
BIGNUM* r = BN_bin2bn(buf, 33, nullptr);
|
||||
std::copy(signature.ubegin() + 32, signature.ubegin() + 64, buf + 1);
|
||||
BIGNUM* s = BN_bin2bn(buf, 33, nullptr);
|
||||
if (ECDSA_SIG_set0(sig, r, s) != 1) {
|
||||
return td::Status::Error("Invalid signature");
|
||||
}
|
||||
unsigned char* signature_encoded = nullptr;
|
||||
int signature_len = i2d_ECDSA_SIG(sig, &signature_encoded);
|
||||
if (signature_len <= 0) {
|
||||
return td::Status::Error("Invalid signature");
|
||||
}
|
||||
SCOPE_EXIT {
|
||||
OPENSSL_free(signature_encoded);
|
||||
};
|
||||
if (EVP_DigestVerify(md_ctx, signature_encoded, signature_len, data.ubegin(), data.size()) == 1) {
|
||||
return td::Status::OK();
|
||||
}
|
||||
return td::Status::Error("Wrong signature");
|
||||
}
|
||||
|
||||
} // namespace td
|
26
crypto/ellcurve/p256.h
Normal file
26
crypto/ellcurve/p256.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "td/utils/Slice.h"
|
||||
#include "td/utils/Status.h"
|
||||
|
||||
namespace td {
|
||||
|
||||
td::Status p256_check_signature(td::Slice data, td::Slice public_key, td::Slice signature);
|
||||
|
||||
}
|
42
crypto/ellcurve/secp256k1.cpp
Normal file
42
crypto/ellcurve/secp256k1.cpp
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "secp256k1.h"
|
||||
#include "td/utils/check.h"
|
||||
#include <secp256k1_recovery.h>
|
||||
#include <cstring>
|
||||
|
||||
namespace td {
|
||||
|
||||
bool ecrecover(const unsigned char* hash, const unsigned char* signature, unsigned char* public_key) {
|
||||
static secp256k1_context* ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY);
|
||||
secp256k1_ecdsa_recoverable_signature ecdsa_signature;
|
||||
if (signature[64] > 3 ||
|
||||
!secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &ecdsa_signature, signature, signature[64])) {
|
||||
return false;
|
||||
}
|
||||
secp256k1_pubkey pubkey;
|
||||
if (!secp256k1_ecdsa_recover(ctx, &pubkey, &ecdsa_signature, hash)) {
|
||||
return false;
|
||||
}
|
||||
size_t len = 65;
|
||||
secp256k1_ec_pubkey_serialize(ctx, public_key, &len, &pubkey, SECP256K1_EC_UNCOMPRESSED);
|
||||
CHECK(len == 65);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
23
crypto/ellcurve/secp256k1.h
Normal file
23
crypto/ellcurve/secp256k1.h
Normal file
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
namespace td {
|
||||
|
||||
bool ecrecover(const unsigned char* hash, const unsigned char* signature, unsigned char* public_key);
|
||||
|
||||
}
|
|
@ -2,7 +2,7 @@ library TVM_Asm
|
|||
// simple TVM Assembler
|
||||
namespace Asm
|
||||
Asm definitions
|
||||
"0.4.3" constant asm-fif-version
|
||||
"0.4.4" constant asm-fif-version
|
||||
|
||||
variable @atend
|
||||
variable @was-split
|
||||
|
@ -32,6 +32,7 @@ false @was-split !
|
|||
{ 1 { <b swap s, swap 8 i, @addopb } does create } : @Defop(8i)
|
||||
{ 1 { <b swap s, swap 1- 8 u, @addopb } does create } : @Defop(8u+1)
|
||||
{ 1 { <b swap s, swap 4 u, @addopb } does create } : @Defop(4u)
|
||||
{ 1 { <b swap s, swap 12 u, @addopb } does create } : @Defop(12u)
|
||||
{ 1 { <b swap s, rot 4 u, swap 4 u, @addopb } does create } : @Defop(4u,4u)
|
||||
{ 1 { <b swap s, swap ref, @addopb } does create } : @Defop(ref)
|
||||
{ 1 { <b swap s, rot ref, swap ref, @addopb } does create } : @Defop(ref*2)
|
||||
|
@ -266,7 +267,7 @@ x{89} @Defop(ref) PUSHREFSLICE
|
|||
x{8A} @Defop(ref) PUSHREFCONT
|
||||
{ 1- dup 0< over 8 >= or abort"invalid slice padding"
|
||||
swap 1 1 u, 0 rot u, } : @scomplete
|
||||
{ tuck sbitrefs swap 17 + swap @havebitrefs not
|
||||
{ tuck sbitrefs swap 26 + swap @havebitrefs not
|
||||
{ <b rot s, b> PUSHREFSLICE }
|
||||
{ over sbitrefs 2dup 123 0 2x<=
|
||||
{ drop tuck 4 + 3 >> swap x{8B} s, over 4 u, 3 roll s,
|
||||
|
@ -338,6 +339,9 @@ x{A90A} @Defop MODC
|
|||
x{A90C} @Defop DIVMOD
|
||||
x{A90D} @Defop DIVMODR
|
||||
x{A90E} @Defop DIVMODC
|
||||
x{A900} @Defop ADDDIVMOD
|
||||
x{A901} @Defop ADDDIVMODR
|
||||
x{A902} @Defop ADDDIVMODC
|
||||
|
||||
x{A925} @Defop RSHIFTR
|
||||
x{A926} @Defop RSHIFTC
|
||||
|
@ -347,6 +351,9 @@ x{A92A} @Defop MODPOW2C
|
|||
x{A92C} @Defop RSHIFTMOD
|
||||
x{A92D} @Defop RSHIFTMODR
|
||||
x{A92E} @Defop RSHIFTMODC
|
||||
x{A920} @Defop ADDRSHIFTMOD
|
||||
x{A921} @Defop ADDRSHIFTMODR
|
||||
x{A922} @Defop ADDRSHIFTMODC
|
||||
|
||||
x{A935} @Defop(8u+1) RSHIFTR#
|
||||
x{A936} @Defop(8u+1) RSHIFTC#
|
||||
|
@ -356,6 +363,9 @@ x{A93A} @Defop(8u+1) MODPOW2C#
|
|||
x{A93C} @Defop(8u+1) RSHIFT#MOD
|
||||
x{A93D} @Defop(8u+1) RSHIFTR#MOD
|
||||
x{A93E} @Defop(8u+1) RSHIFTC#MOD
|
||||
x{A930} @Defop(8u+1) ADDRSHIFT#MOD
|
||||
x{A931} @Defop(8u+1) ADDRSHIFTR#MOD
|
||||
x{A932} @Defop(8u+1) ADDRSHIFTC#MOD
|
||||
|
||||
x{A984} @Defop MULDIV
|
||||
x{A985} @Defop MULDIVR
|
||||
|
@ -366,6 +376,9 @@ x{A98A} @Defop MULMODC
|
|||
x{A98C} @Defop MULDIVMOD
|
||||
x{A98D} @Defop MULDIVMODR
|
||||
x{A98E} @Defop MULDIVMODC
|
||||
x{A980} @Defop MULADDDIVMOD
|
||||
x{A981} @Defop MULADDDIVMODR
|
||||
x{A982} @Defop MULADDDIVMODC
|
||||
|
||||
x{A9A4} @Defop MULRSHIFT
|
||||
x{A9A5} @Defop MULRSHIFTR
|
||||
|
@ -376,6 +389,9 @@ x{A9AA} @Defop MULMODPOW2C
|
|||
x{A9AC} @Defop MULRSHIFTMOD
|
||||
x{A9AD} @Defop MULRSHIFTRMOD
|
||||
x{A9AE} @Defop MULRSHIFTCMOD
|
||||
x{A9A0} @Defop MULADDRSHIFTMOD
|
||||
x{A9A1} @Defop MULADDRSHIFTRMOD
|
||||
x{A9A2} @Defop MULADDRSHIFTCMOD
|
||||
|
||||
x{A9B4} @Defop(8u+1) MULRSHIFT#
|
||||
x{A9B5} @Defop(8u+1) MULRSHIFTR#
|
||||
|
@ -386,6 +402,9 @@ x{A9BA} @Defop(8u+1) MULMODPOW2C#
|
|||
x{A9BC} @Defop(8u+1) MULRSHIFT#MOD
|
||||
x{A9BD} @Defop(8u+1) MULRSHIFTR#MOD
|
||||
x{A9BE} @Defop(8u+1) MULRSHIFTC#MOD
|
||||
x{A9B0} @Defop(8u+1) MULADDRSHIFT#MOD
|
||||
x{A9B1} @Defop(8u+1) MULADDRSHIFTR#MOD
|
||||
x{A9B2} @Defop(8u+1) MULADDRSHIFTC#MOD
|
||||
|
||||
x{A9C4} @Defop LSHIFTDIV
|
||||
x{A9C5} @Defop LSHIFTDIVR
|
||||
|
@ -396,6 +415,9 @@ x{A9CA} @Defop LSHIFTMODC
|
|||
x{A9CC} @Defop LSHIFTDIVMOD
|
||||
x{A9CD} @Defop LSHIFTDIVMODR
|
||||
x{A9CE} @Defop LSHIFTDIVMODC
|
||||
x{A9C0} @Defop LSHIFTADDDIVMOD
|
||||
x{A9C1} @Defop LSHIFTADDDIVMODR
|
||||
x{A9C2} @Defop LSHIFTADDDIVMODC
|
||||
|
||||
x{A9D4} @Defop(8u+1) LSHIFT#DIV
|
||||
x{A9D5} @Defop(8u+1) LSHIFT#DIVR
|
||||
|
@ -406,6 +428,9 @@ x{A9DA} @Defop(8u+1) LSHIFT#MODC
|
|||
x{A9DC} @Defop(8u+1) LSHIFT#DIVMOD
|
||||
x{A9DD} @Defop(8u+1) LSHIFT#DIVMODR
|
||||
x{A9DE} @Defop(8u+1) LSHIFT#DIVMODC
|
||||
x{A9D0} @Defop(8u+1) LSHIFT#ADDDIVMOD
|
||||
x{A9D1} @Defop(8u+1) LSHIFT#ADDDIVMODR
|
||||
x{A9D2} @Defop(8u+1) LSHIFT#ADDDIVMODC
|
||||
|
||||
x{AA} @Defop(8u+1) LSHIFT#
|
||||
x{AB} @Defop(8u+1) RSHIFT#
|
||||
|
@ -443,8 +468,12 @@ x{B7A908} @Defop QMOD
|
|||
x{B7A90C} @Defop QDIVMOD
|
||||
x{B7A90D} @Defop QDIVMODR
|
||||
x{B7A90E} @Defop QDIVMODC
|
||||
x{B7A900} @Defop QADDDIVMOD
|
||||
x{B7A901} @Defop QADDDIVMODR
|
||||
x{B7A902} @Defop QADDDIVMODC
|
||||
x{B7A985} @Defop QMULDIVR
|
||||
x{B7A98C} @Defop QMULDIVMOD
|
||||
x{B7A980} @Defop QADDMULDIVMOD
|
||||
x{B7AC} @Defop QLSHIFT
|
||||
x{B7AD} @Defop QRSHIFT
|
||||
x{B7AE} @Defop QPOW2
|
||||
|
@ -578,7 +607,7 @@ x{CF3F} @Defop BCHKBITREFSQ
|
|||
x{CF40} @Defop STZEROES
|
||||
x{CF41} @Defop STONES
|
||||
x{CF42} @Defop STSAME
|
||||
{ tuck sbitrefs swap 15 + swap @havebitrefs not
|
||||
{ tuck sbitrefs swap 22 + swap @havebitrefs not
|
||||
{ swap PUSHSLICE STSLICER }
|
||||
{ over sbitrefs 2dup 57 3 2x<=
|
||||
{ rot x{CFC_} s, swap 2 u, over 6 + 3 >> tuck 3 u, 3 roll s,
|
||||
|
@ -721,6 +750,8 @@ x{DB3C} @Defop(ref) CALLREF
|
|||
x{DB3D} @Defop(ref) JMPREF
|
||||
x{DB3E} @Defop(ref) JMPREFDATA
|
||||
x{DB3F} @Defop RETDATA
|
||||
x{DB4} @Defop(12u) RUNVM
|
||||
x{DB50} @Defop RUNVMX
|
||||
// conditional and iterated execution primitives
|
||||
x{DC} @Defop IFRET
|
||||
x{DD} @Defop IFNOTRET
|
||||
|
@ -1154,6 +1185,7 @@ x{F4BF} @Defop DICTUGETEXECZ
|
|||
|
||||
x{F800} @Defop ACCEPT
|
||||
x{F801} @Defop SETGASLIMIT
|
||||
x{F802} @Defop GASCONSUMED
|
||||
x{F80F} @Defop COMMIT
|
||||
|
||||
x{F810} @Defop RANDU256
|
||||
|
@ -1169,9 +1201,16 @@ x{F826} @Defop RANDSEED
|
|||
x{F827} @Defop BALANCE
|
||||
x{F828} @Defop MYADDR
|
||||
x{F829} @Defop CONFIGROOT
|
||||
x{F82A} @Defop MYCODE
|
||||
x{F82B} @Defop INCOMINGVALUE
|
||||
x{F82C} @Defop STORAGEFEES
|
||||
x{F82D} @Defop PREVBLOCKSINFOTUPLE
|
||||
x{F830} @Defop CONFIGDICT
|
||||
x{F832} @Defop CONFIGPARAM
|
||||
x{F833} @Defop CONFIGOPTPARAM
|
||||
x{F83400} @Defop PREVMCBLOCKS
|
||||
x{F83401} @Defop PREVKEYBLOCK
|
||||
x{F835} @Defop GLOBALID
|
||||
|
||||
x{F840} @Defop GETGLOBVAR
|
||||
{ dup 1 31 @rangechk <b x{F85_} s, swap 5 u, @addopb } : GETGLOB
|
||||
|
@ -1181,8 +1220,79 @@ x{F860} @Defop SETGLOBVAR
|
|||
x{F900} @Defop HASHCU
|
||||
x{F901} @Defop HASHSU
|
||||
x{F902} @Defop SHA256U
|
||||
|
||||
x{F904} @Defop(8u) HASHEXT
|
||||
x{F90400} @Defop HASHEXT_SHA256
|
||||
x{F90401} @Defop HASHEXT_SHA512
|
||||
x{F90402} @Defop HASHEXT_BLAKE2B
|
||||
x{F90403} @Defop HASHEXT_KECCAK256
|
||||
x{F90404} @Defop HASHEXT_KECCAK512
|
||||
x{F905} @Defop(8u) HASHEXTR
|
||||
x{F90500} @Defop HASHEXTR_SHA256
|
||||
x{F90501} @Defop HASHEXTR_SHA512
|
||||
x{F90502} @Defop HASHEXTR_BLAKE2B
|
||||
x{F90503} @Defop HASHEXTR_KECCAK256
|
||||
x{F90504} @Defop HASHEXTR_KECCAK512
|
||||
x{F906} @Defop(8u) HASHEXTA
|
||||
x{F90600} @Defop HASHEXTA_SHA256
|
||||
x{F90601} @Defop HASHEXTA_SHA512
|
||||
x{F90602} @Defop HASHEXTA_BLAKE2B
|
||||
x{F90603} @Defop HASHEXTA_KECCAK256
|
||||
x{F90604} @Defop HASHEXTA_KECCAK512
|
||||
x{F907} @Defop(8u) HASHEXTAR
|
||||
x{F90700} @Defop HASHEXTAR_SHA256
|
||||
x{F90701} @Defop HASHEXTAR_SHA512
|
||||
x{F90702} @Defop HASHEXTAR_BLAKE2B
|
||||
x{F90703} @Defop HASHEXTAR_KECCAK256
|
||||
x{F90704} @Defop HASHEXTAR_KECCAK512
|
||||
|
||||
x{F910} @Defop CHKSIGNU
|
||||
x{F911} @Defop CHKSIGNS
|
||||
x{F912} @Defop ECRECOVER
|
||||
x{F914} @Defop P256_CHKSIGNU
|
||||
x{F915} @Defop P256_CHKSIGNS
|
||||
|
||||
x{F920} @Defop RIST255_FROMHASH
|
||||
x{F921} @Defop RIST255_VALIDATE
|
||||
x{F922} @Defop RIST255_ADD
|
||||
x{F923} @Defop RIST255_SUB
|
||||
x{F924} @Defop RIST255_MUL
|
||||
x{F925} @Defop RIST255_MULBASE
|
||||
x{F926} @Defop RIST255_PUSHL
|
||||
|
||||
x{B7F921} @Defop RIST255_QVALIDATE
|
||||
x{B7F922} @Defop RIST255_QADD
|
||||
x{B7F923} @Defop RIST255_QSUB
|
||||
x{B7F924} @Defop RIST255_QMUL
|
||||
x{B7F925} @Defop RIST255_QMULBASE
|
||||
|
||||
x{F93000} @Defop BLS_VERIFY
|
||||
x{F93001} @Defop BLS_AGGREGATE
|
||||
x{F93002} @Defop BLS_FASTAGGREGATEVERIFY
|
||||
x{F93003} @Defop BLS_AGGREGATEVERIFY
|
||||
|
||||
x{F93010} @Defop BLS_G1_ADD
|
||||
x{F93011} @Defop BLS_G1_SUB
|
||||
x{F93012} @Defop BLS_G1_NEG
|
||||
x{F93013} @Defop BLS_G1_MUL
|
||||
x{F93014} @Defop BLS_G1_MULTIEXP
|
||||
x{F93015} @Defop BLS_G1_ZERO
|
||||
x{F93016} @Defop BLS_MAP_TO_G1
|
||||
x{F93017} @Defop BLS_G1_INGROUP
|
||||
x{F93018} @Defop BLS_G1_ISZERO
|
||||
|
||||
x{F93020} @Defop BLS_G2_ADD
|
||||
x{F93021} @Defop BLS_G2_SUB
|
||||
x{F93022} @Defop BLS_G2_NEG
|
||||
x{F93023} @Defop BLS_G2_MUL
|
||||
x{F93024} @Defop BLS_G2_MULTIEXP
|
||||
x{F93025} @Defop BLS_G2_ZERO
|
||||
x{F93026} @Defop BLS_MAP_TO_G2
|
||||
x{F93027} @Defop BLS_G2_INGROUP
|
||||
x{F93028} @Defop BLS_G2_ISZERO
|
||||
|
||||
x{F93030} @Defop BLS_PAIRING
|
||||
x{F93031} @Defop BLS_PUSHR
|
||||
|
||||
x{F940} @Defop CDATASIZEQ
|
||||
x{F941} @Defop CDATASIZE
|
||||
|
@ -1194,6 +1304,11 @@ x{FA01} @Defop LDVARINT16
|
|||
x{FA02} dup @Defop STGRAMS @Defop STVARUINT16
|
||||
x{FA03} @Defop STVARINT16
|
||||
|
||||
x{FA04} @Defop LDVARUINT32 // (s -- x s')
|
||||
x{FA05} @Defop LDVARINT32 // (s -- x s')
|
||||
x{FA06} @Defop STVARUINT32 // (b x -- b')
|
||||
x{FA07} @Defop STVARINT32 // (b x -- b')
|
||||
|
||||
x{FA40} @Defop LDMSGADDR
|
||||
x{FA41} @Defop LDMSGADDRQ
|
||||
x{FA42} @Defop PARSEMSGADDR
|
||||
|
@ -1209,6 +1324,7 @@ x{FB03} @Defop RAWRESERVEX
|
|||
x{FB04} @Defop SETCODE
|
||||
x{FB06} @Defop SETLIBCODE
|
||||
x{FB07} @Defop CHANGELIB
|
||||
x{FB08} @Defop SENDMSG
|
||||
|
||||
//
|
||||
// debug primitives
|
||||
|
@ -1392,7 +1508,7 @@ forget @proclist forget @proccnt
|
|||
{ dup "." $pos dup -1 =
|
||||
{ drop 0 }
|
||||
{ $| 1 $| nip swap (number) 1- abort"invalid version"
|
||||
dup dup 0 < swap 999 > or abort"invalid version"
|
||||
dup dup 0 < swap 999 > or abort"invalid version"
|
||||
}
|
||||
cond
|
||||
} : parse-version-level
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
#include "vm/db/TonDb.h" // only for interpret_db_run_vm{,_parallel}
|
||||
|
||||
#include "block/block.h"
|
||||
#include "common/global-version.h"
|
||||
|
||||
#include "td/utils/filesystem.h"
|
||||
#include "td/utils/misc.h"
|
||||
|
@ -235,7 +236,7 @@ void interpret_cmp(vm::Stack& stack, const char opt[3]) {
|
|||
}
|
||||
|
||||
void interpret_sgn(vm::Stack& stack, const char opt[3]) {
|
||||
auto x = stack.pop_int();
|
||||
auto x = stack.pop_int_finite();
|
||||
int r = x->sgn();
|
||||
assert((unsigned)(r + 1) <= 2);
|
||||
stack.push_smallint(((const signed char*)opt)[r + 1]);
|
||||
|
@ -2658,13 +2659,15 @@ std::vector<Ref<vm::Cell>> get_vm_libraries() {
|
|||
// +128 = pop hard gas limit (enabled by ACCEPT) from stack as well
|
||||
// +256 = enable stack trace
|
||||
// +512 = enable debug instructions
|
||||
// +1024 = load global_version from stack
|
||||
void interpret_run_vm(IntCtx& ctx, int mode) {
|
||||
if (mode < 0) {
|
||||
mode = ctx.stack.pop_smallint_range(0x3ff);
|
||||
mode = ctx.stack.pop_smallint_range(0x7ff);
|
||||
}
|
||||
bool with_data = mode & 4;
|
||||
Ref<vm::Tuple> c7;
|
||||
Ref<vm::Cell> data, actions;
|
||||
int global_version = (mode & 1024) ? ctx.stack.pop_smallint_range(ton::SUPPORTED_VERSION) : ton::SUPPORTED_VERSION;
|
||||
long long gas_max = (mode & 128) ? ctx.stack.pop_long_range(vm::GasLimits::infty) : vm::GasLimits::infty;
|
||||
long long gas_limit = (mode & 8) ? ctx.stack.pop_long_range(vm::GasLimits::infty) : vm::GasLimits::infty;
|
||||
if (!(mode & 128)) {
|
||||
|
@ -2683,7 +2686,7 @@ void interpret_run_vm(IntCtx& ctx, int mode) {
|
|||
auto log = create_vm_log((mode & 64) && ctx.error_stream ? &ostream_logger : nullptr);
|
||||
vm::GasLimits gas{gas_limit, gas_max};
|
||||
int res = vm::run_vm_code(cs, ctx.stack, (mode & 3) | ((mode & 0x300) >> 6), &data, log, nullptr, &gas,
|
||||
get_vm_libraries(), std::move(c7), &actions);
|
||||
get_vm_libraries(), std::move(c7), &actions, global_version);
|
||||
ctx.stack.push_smallint(res);
|
||||
if (with_data) {
|
||||
ctx.stack.push_cell(std::move(data));
|
||||
|
|
|
@ -38,6 +38,9 @@ TmpVar::TmpVar(var_idx_t _idx, int _cls, TypeExpr* _type, SymDef* sym, const Src
|
|||
if (!_type) {
|
||||
v_type = TypeExpr::new_hole();
|
||||
}
|
||||
if (cls == _Named) {
|
||||
undefined = true;
|
||||
}
|
||||
}
|
||||
|
||||
void TmpVar::set_location(const SrcLocation& loc) {
|
||||
|
@ -179,7 +182,7 @@ void VarDescr::set_const_nan() {
|
|||
|
||||
void VarDescr::operator|=(const VarDescr& y) {
|
||||
val &= y.val;
|
||||
if (is_int_const() && cmp(int_const, y.int_const) != 0) {
|
||||
if (is_int_const() && y.is_int_const() && cmp(int_const, y.int_const) != 0) {
|
||||
val &= ~_Const;
|
||||
}
|
||||
if (!(val & _Const)) {
|
||||
|
|
|
@ -42,14 +42,14 @@ int CodeBlob::split_vars(bool strict) {
|
|||
}
|
||||
std::vector<TypeExpr*> comp_types;
|
||||
int k = var.v_type->extract_components(comp_types);
|
||||
assert(k <= 254 && n <= 0x7fff00);
|
||||
assert((unsigned)k == comp_types.size());
|
||||
func_assert(k <= 254 && n <= 0x7fff00);
|
||||
func_assert((unsigned)k == comp_types.size());
|
||||
if (k != 1) {
|
||||
var.coord = ~((n << 8) + k);
|
||||
for (int i = 0; i < k; i++) {
|
||||
auto v = create_var(vars[j].cls, comp_types[i], 0, vars[j].where.get());
|
||||
assert(v == n + i);
|
||||
assert(vars[v].idx == v);
|
||||
func_assert(v == n + i);
|
||||
func_assert(vars[v].idx == v);
|
||||
vars[v].name = vars[j].name;
|
||||
vars[v].coord = ((int)j << 8) + i + 1;
|
||||
}
|
||||
|
@ -75,9 +75,9 @@ bool CodeBlob::compute_used_code_vars() {
|
|||
}
|
||||
|
||||
bool CodeBlob::compute_used_code_vars(std::unique_ptr<Op>& ops_ptr, const VarDescrList& var_info, bool edit) const {
|
||||
assert(ops_ptr);
|
||||
func_assert(ops_ptr);
|
||||
if (!ops_ptr->next) {
|
||||
assert(ops_ptr->cl == Op::_Nop);
|
||||
func_assert(ops_ptr->cl == Op::_Nop);
|
||||
return ops_ptr->set_var_info(var_info);
|
||||
}
|
||||
return compute_used_code_vars(ops_ptr->next, var_info, edit) | ops_ptr->compute_used_vars(*this, edit);
|
||||
|
@ -346,7 +346,7 @@ bool Op::std_compute_used_vars(bool disabled) {
|
|||
}
|
||||
|
||||
bool Op::compute_used_vars(const CodeBlob& code, bool edit) {
|
||||
assert(next);
|
||||
func_assert(next);
|
||||
const VarDescrList& next_var_info = next->var_info;
|
||||
if (cl == _Nop) {
|
||||
return set_var_info_except(next_var_info, left);
|
||||
|
@ -379,7 +379,7 @@ bool Op::compute_used_vars(const CodeBlob& code, bool edit) {
|
|||
case _Let: {
|
||||
// left = right
|
||||
std::size_t cnt = next_var_info.count_used(left);
|
||||
assert(left.size() == right.size());
|
||||
func_assert(left.size() == right.size());
|
||||
auto l_it = left.cbegin(), r_it = right.cbegin();
|
||||
VarDescrList new_var_info{next_var_info};
|
||||
new_var_info -= left;
|
||||
|
@ -388,7 +388,7 @@ bool Op::compute_used_vars(const CodeBlob& code, bool edit) {
|
|||
for (; l_it < left.cend(); ++l_it, ++r_it) {
|
||||
if (std::find(l_it + 1, left.cend(), *l_it) == left.cend()) {
|
||||
auto p = next_var_info[*l_it];
|
||||
new_var_info.add_var(*r_it, !p || p->is_unused());
|
||||
new_var_info.add_var(*r_it, edit && (!p || p->is_unused()));
|
||||
new_left.push_back(*l_it);
|
||||
new_right.push_back(*r_it);
|
||||
}
|
||||
|
@ -500,7 +500,12 @@ bool Op::compute_used_vars(const CodeBlob& code, bool edit) {
|
|||
}
|
||||
changes = (new_var_info.size() == n);
|
||||
} while (changes <= edit);
|
||||
func_assert(left.size() == 1);
|
||||
bool last = new_var_info.count_used(left) == 0;
|
||||
new_var_info += left;
|
||||
if (last) {
|
||||
new_var_info[left[0]]->flags |= VarDescr::_Last;
|
||||
}
|
||||
return set_var_info(std::move(new_var_info));
|
||||
}
|
||||
case _Again: {
|
||||
|
@ -650,7 +655,7 @@ bool prune_unreachable(std::unique_ptr<Op>& ops) {
|
|||
ops = std::move(op.block0);
|
||||
return false;
|
||||
}
|
||||
reach = true;
|
||||
reach = (op.cl != Op::_Again);
|
||||
break;
|
||||
}
|
||||
case Op::_TryCatch: {
|
||||
|
@ -679,7 +684,7 @@ void CodeBlob::prune_unreachable_code() {
|
|||
|
||||
void CodeBlob::fwd_analyze() {
|
||||
VarDescrList values;
|
||||
assert(ops && ops->cl == Op::_Import);
|
||||
func_assert(ops && ops->cl == Op::_Import);
|
||||
for (var_idx_t i : ops->left) {
|
||||
values += i;
|
||||
if (vars[i].v_type->is_int()) {
|
||||
|
@ -760,7 +765,7 @@ VarDescrList Op::fwd_analyze(VarDescrList values) {
|
|||
break;
|
||||
case _Let: {
|
||||
std::vector<VarDescr> old_val;
|
||||
assert(left.size() == right.size());
|
||||
func_assert(left.size() == right.size());
|
||||
for (std::size_t i = 0; i < right.size(); i++) {
|
||||
const VarDescr* ov = values[right[i]];
|
||||
if (!ov && verbosity >= 5) {
|
||||
|
@ -775,7 +780,7 @@ VarDescrList Op::fwd_analyze(VarDescrList values) {
|
|||
}
|
||||
std::cerr << std::endl;
|
||||
}
|
||||
// assert(ov);
|
||||
// func_assert(ov);
|
||||
if (ov) {
|
||||
old_val.push_back(*ov);
|
||||
} else {
|
||||
|
@ -889,7 +894,7 @@ bool Op::mark_noreturn() {
|
|||
return set_noreturn((block0->mark_noreturn() & (block1 && block1->mark_noreturn())) | next->mark_noreturn());
|
||||
case _Again:
|
||||
block0->mark_noreturn();
|
||||
return set_noreturn(false);
|
||||
return set_noreturn(true);
|
||||
case _Until:
|
||||
return set_noreturn(block0->mark_noreturn() | next->mark_noreturn());
|
||||
case _While:
|
||||
|
|
|
@ -166,7 +166,7 @@ AsmOp AsmOp::UnTuple(int a) {
|
|||
|
||||
AsmOp AsmOp::IntConst(td::RefInt256 x) {
|
||||
if (x->signed_fits_bits(8)) {
|
||||
return AsmOp::Const(dec_string(std::move(x)) + " PUSHINT", x);
|
||||
return AsmOp::Const(dec_string(x) + " PUSHINT", x);
|
||||
}
|
||||
if (!x->is_valid()) {
|
||||
return AsmOp::Const("PUSHNAN", x);
|
||||
|
@ -184,9 +184,9 @@ AsmOp AsmOp::IntConst(td::RefInt256 x) {
|
|||
return AsmOp::Const(k, "PUSHNEGPOW2", x);
|
||||
}
|
||||
if (!x->mod_pow2_short(23)) {
|
||||
return AsmOp::Const(dec_string(std::move(x)) + " PUSHINTX", x);
|
||||
return AsmOp::Const(dec_string(x) + " PUSHINTX", x);
|
||||
}
|
||||
return AsmOp::Const(dec_string(std::move(x)) + " PUSHINT", x);
|
||||
return AsmOp::Const(dec_string(x) + " PUSHINT", x);
|
||||
}
|
||||
|
||||
AsmOp AsmOp::BoolConst(bool f) {
|
||||
|
|
27
crypto/func/auto-tests/legacy_tester.js
Normal file
27
crypto/func/auto-tests/legacy_tester.js
Normal file
|
@ -0,0 +1,27 @@
|
|||
const fs = require('fs/promises');
|
||||
const { compileWasm, compileFile } = require('./wasm_tests_common');
|
||||
|
||||
async function main() {
|
||||
const tests = JSON.parse((await fs.readFile('../legacy_tests.json')).toString('utf-8'))
|
||||
|
||||
for (const [filename, hashstr] of tests) {
|
||||
if (filename.includes('storage-provider')) continue;
|
||||
|
||||
const mod = await compileWasm()
|
||||
|
||||
const response = await compileFile(mod, filename);
|
||||
|
||||
if (response.status !== 'ok') {
|
||||
console.error(response);
|
||||
throw new Error('Could not compile ' + filename);
|
||||
}
|
||||
|
||||
if (BigInt('0x' + response.codeHashHex) !== BigInt(hashstr)) {
|
||||
throw new Error('Compilation result is different for ' + filename);
|
||||
}
|
||||
|
||||
console.log(filename, 'ok');
|
||||
}
|
||||
}
|
||||
|
||||
main()
|
1
crypto/func/auto-tests/legacy_tests.json
Normal file
1
crypto/func/auto-tests/legacy_tests.json
Normal file
|
@ -0,0 +1 @@
|
|||
[["elector/elector-code.fc", "115226404411715505328583639896096915745686314074575650766750648324043316883483"], ["config/config-code.fc", "10913070768607625342121305745084703121685937915388357634624451844356456145601"], ["eth-bridge-multisig/multisig-code.fc", "101509909129354488841890823627011033360100627957439967918234053299675481277954"], ["bsc-bridge-collector/votes-collector.fc", "62190447221288642706570413295807615918589884489514159926097051017036969900417"], ["uni-lock-wallet/uni-lockup-wallet.fc", "61959738324779104851267145467044677651344601417998258530238254441977103654381"], ["nft-collection/nft-collection-editable.fc", "45561997735512210616567774035540357815786262097548276229169737015839077731274"], ["dns-collection/nft-collection.fc", "107999822699841936063083742021519765435859194241091312445235370766165379261859"], ["tele-nft-item/nft-item.fc", "69777543125381987786450436977742010705076866061362104025338034583422166453344"], ["storage/storage-contract.fc", "91377830060355733016937375216020277778264560226873154627574229667513068328151"], ["storage/storage-provider.fc", "13618336676213331164384407184540461509022654507176709588621016553953760588122"], ["nominator-pool/pool.fc", "69767057279163099864792356875696330339149706521019810113334238732928422055375"], ["jetton-minter/jetton-minter.fc", "9028309926287301331466371999814928201427184114165428257502393474125007156494"], ["gg-marketplace/nft-marketplace-v2.fc", "92199806964112524639740773542356508485601908152150843819273107618799016205930"], ["jetton-wallet/jetton-wallet.fc", "86251125787443633057458168028617933212663498001665054651523310772884328206542"], ["whales-nominators/nominators.fc", "8941364499854379927692172316865293429893094891593442801401542636695127885153"], ["tact-examples/treasure_Treasure.code.fc", "13962538639825790677138656603323869918938565499584297120566680287245364723897"], ["tact-examples/jetton_SampleJetton.code.fc", "94076762218493729104783735200107713211245710256802265203823917715299139499110"], ["tact-examples/jetton_JettonDefaultWallet.code.fc", "29421313492520031238091587108198906058157443241743283101866538036369069620563"], ["tact-examples/maps_MapTestContract.code.fc", "22556550222249123835909180266811414538971143565993192846012583552876721649744"]]
|
77
crypto/func/auto-tests/run_tests.js
Normal file
77
crypto/func/auto-tests/run_tests.js
Normal file
|
@ -0,0 +1,77 @@
|
|||
const fs = require('fs/promises');
|
||||
const os = require('os');
|
||||
const path = require('path');
|
||||
const { compileWasm, compileFile } = require('./wasm_tests_common');
|
||||
const { execSync } = require('child_process');
|
||||
|
||||
async function main() {
|
||||
const compiledPath = path.join(os.tmpdir(), 'compiled.fif');
|
||||
const runnerPath = path.join(os.tmpdir(), 'runner.fif');
|
||||
|
||||
const tests = (await fs.readdir('.')).filter(f => f.endsWith('.fc')).sort();
|
||||
|
||||
const mathChars = '0x123456789()+-*/<>'.split('')
|
||||
|
||||
for (const testFile of tests) {
|
||||
const mod = await compileWasm()
|
||||
|
||||
const result = await compileFile(mod, testFile)
|
||||
|
||||
if (result.status !== 'ok') {
|
||||
console.error(result);
|
||||
throw new Error('Could not compile ' + filename);
|
||||
}
|
||||
|
||||
const fileLines = (await fs.readFile(testFile)).toString('utf-8').split('\n');
|
||||
|
||||
const testCases = [];
|
||||
|
||||
for (const line of fileLines) {
|
||||
const parts = line.split('|').map(c => c.trim());
|
||||
|
||||
if (parts.length !== 4 || parts[0] !== 'TESTCASE') continue;
|
||||
|
||||
const processedInputs = [];
|
||||
|
||||
for (const input of parts[2].split(' ')) {
|
||||
if (input.includes('x{')) {
|
||||
processedInputs.push(input);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (input.length === 0) {
|
||||
continue
|
||||
}
|
||||
|
||||
const replacedInput = input.split('').filter(c => mathChars.includes(c)).join('').replace('//', '/').replace(/([0-9a-f])($|[^0-9a-fx])/gmi, '$1n$2')
|
||||
|
||||
processedInputs.push(eval(replacedInput).toString());
|
||||
}
|
||||
|
||||
testCases.push([parts[1], processedInputs.join(' '), parts[3]]);
|
||||
}
|
||||
|
||||
await fs.writeFile(compiledPath, '"Asm.fif" include\n' + JSON.parse('"' + result.fiftCode + '"'));
|
||||
await fs.writeFile(runnerPath, `"${compiledPath}" include <s constant code\n${testCases.map(t => `${t[1]} ${t[0]} code 1 runvmx abort"exitcode is not 0" .s cr { drop } depth 1- times`).join('\n')}`)
|
||||
|
||||
const fiftResult = execSync(`${process.env.FIFT_EXECUTABLE || 'fift'} -I ${process.env.FIFT_LIBS} /tmp/runner.fif`, {
|
||||
stdio: ['pipe', 'pipe', 'ignore']
|
||||
}).toString('utf-8')
|
||||
|
||||
const testResults = fiftResult.split('\n').map(s => s.trim()).filter(s => s.length > 0)
|
||||
|
||||
if (testResults.length !== testCases.length) {
|
||||
throw new Error(`Got ${testResults.length} results but there are ${testCases.length} cases`)
|
||||
}
|
||||
|
||||
for (let i = 0; i < testResults.length; i++) {
|
||||
if (testResults[i] !== testCases[i][2]) {
|
||||
throw new Error(`Unequal result ${testResults[i]} and case ${testCases[i][2]}`)
|
||||
}
|
||||
}
|
||||
|
||||
console.log(testFile, 'ok')
|
||||
}
|
||||
}
|
||||
|
||||
main()
|
109
crypto/func/auto-tests/tests/try-func.fc
Normal file
109
crypto/func/auto-tests/tests/try-func.fc
Normal file
|
@ -0,0 +1,109 @@
|
|||
int foo(int x) method_id(11) {
|
||||
try {
|
||||
if (x == 7) {
|
||||
throw(44);
|
||||
}
|
||||
return x;
|
||||
} catch (_, _) {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
int foo_inline(int x) inline method_id(12) {
|
||||
try {
|
||||
if (x == 7) {
|
||||
throw(44);
|
||||
}
|
||||
return x;
|
||||
} catch (_, _) {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
int foo_inlineref(int x) inline_ref method_id(13) {
|
||||
try {
|
||||
if (x == 7) {
|
||||
throw(44);
|
||||
}
|
||||
return x;
|
||||
} catch (_, _) {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
int test(int x, int y, int z) method_id(1) {
|
||||
y = foo(y);
|
||||
return x * 100 + y * 10 + z;
|
||||
}
|
||||
|
||||
int test_inline(int x, int y, int z) method_id(2) {
|
||||
y = foo_inline(y);
|
||||
return x * 100 + y * 10 + z;
|
||||
}
|
||||
|
||||
int test_inlineref(int x, int y, int z) method_id(3) {
|
||||
y = foo_inlineref(y);
|
||||
return x * 100 + y * 10 + z;
|
||||
}
|
||||
|
||||
int foo_inline_big(
|
||||
int x1, int x2, int x3, int x4, int x5, int x6, int x7, int x8, int x9, int x10,
|
||||
int x11, int x12, int x13, int x14, int x15, int x16, int x17, int x18, int x19, int x20
|
||||
) inline method_id(14) {
|
||||
try {
|
||||
if (x1 == 7) {
|
||||
throw(44);
|
||||
}
|
||||
return x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + x9 + x10 + x11 + x12 + x13 + x14 + x15 + x16 + x17 + x18 + x19 + x20;
|
||||
} catch (_, _) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
int test_inline_big(int x, int y, int z) method_id(4) {
|
||||
y = foo_inline_big(
|
||||
y, y + 1, y + 2, y + 3, y + 4, y + 5, y + 6, y + 7, y + 8, y + 9,
|
||||
y + 10, y + 11, y + 12, y + 13, y + 14, y + 15, y + 16, y + 17, y + 18, y + 19);
|
||||
return x * 1000000 + y * 1000 + z;
|
||||
}
|
||||
|
||||
int foo_big(
|
||||
int x1, int x2, int x3, int x4, int x5, int x6, int x7, int x8, int x9, int x10,
|
||||
int x11, int x12, int x13, int x14, int x15, int x16, int x17, int x18, int x19, int x20
|
||||
) method_id(15) {
|
||||
try {
|
||||
if (x1 == 7) {
|
||||
throw(44);
|
||||
}
|
||||
return x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + x9 + x10 + x11 + x12 + x13 + x14 + x15 + x16 + x17 + x18 + x19 + x20;
|
||||
} catch (_, _) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
int test_big(int x, int y, int z) method_id(5) {
|
||||
y = foo_big(
|
||||
y, y + 1, y + 2, y + 3, y + 4, y + 5, y + 6, y + 7, y + 8, y + 9,
|
||||
y + 10, y + 11, y + 12, y + 13, y + 14, y + 15, y + 16, y + 17, y + 18, y + 19);
|
||||
return x * 1000000 + y * 1000 + z;
|
||||
}
|
||||
|
||||
() main() {
|
||||
}
|
||||
|
||||
{-
|
||||
method_id | in | out
|
||||
TESTCASE | 1 | 1 2 3 | 123
|
||||
TESTCASE | 1 | 3 8 9 | 389
|
||||
TESTCASE | 1 | 3 7 9 | 329
|
||||
TESTCASE | 2 | 1 2 3 | 123
|
||||
TESTCASE | 2 | 3 8 9 | 389
|
||||
TESTCASE | 2 | 3 7 9 | 329
|
||||
TESTCASE | 3 | 1 2 3 | 123
|
||||
TESTCASE | 3 | 3 8 9 | 389
|
||||
TESTCASE | 3 | 3 7 9 | 329
|
||||
TESTCASE | 4 | 4 8 9 | 4350009
|
||||
TESTCASE | 4 | 4 7 9 | 4001009
|
||||
TESTCASE | 5 | 4 8 9 | 4350009
|
||||
TESTCASE | 5 | 4 7 9 | 4001009
|
||||
-}
|
63
crypto/func/auto-tests/wasm_tests_common.js
Normal file
63
crypto/func/auto-tests/wasm_tests_common.js
Normal file
|
@ -0,0 +1,63 @@
|
|||
const fsSync = require('fs');
|
||||
|
||||
const copyToCString = (mod, str) => {
|
||||
const len = mod.lengthBytesUTF8(str) + 1;
|
||||
const ptr = mod._malloc(len);
|
||||
mod.stringToUTF8(str, ptr, len);
|
||||
return ptr;
|
||||
};
|
||||
|
||||
const copyToCStringPtr = (mod, str, ptr) => {
|
||||
const allocated = copyToCString(mod, str);
|
||||
mod.setValue(ptr, allocated, '*');
|
||||
return allocated;
|
||||
};
|
||||
|
||||
const copyFromCString = (mod, ptr) => {
|
||||
return mod.UTF8ToString(ptr);
|
||||
};
|
||||
|
||||
async function compileFile(mod, filename) {
|
||||
const callbackPtr = mod.addFunction((_kind, _data, contents, error) => {
|
||||
const kind = copyFromCString(mod, _kind);
|
||||
const data = copyFromCString(mod, _data);
|
||||
if (kind === 'realpath') {
|
||||
copyToCStringPtr(mod, fsSync.realpathSync(data), contents);
|
||||
} else if (kind === 'source') {
|
||||
const path = fsSync.realpathSync(data);
|
||||
try {
|
||||
copyToCStringPtr(mod, fsSync.readFileSync(path).toString('utf-8'), contents);
|
||||
} catch (err) {
|
||||
copyToCStringPtr(mod, e.message, error);
|
||||
}
|
||||
} else {
|
||||
copyToCStringPtr(mod, 'Unknown callback kind ' + kind, error);
|
||||
}
|
||||
}, 'viiii');
|
||||
|
||||
const config = {
|
||||
optLevel: 2,
|
||||
sources: [filename]
|
||||
};
|
||||
|
||||
const configPtr = copyToCString(mod, JSON.stringify(config));
|
||||
|
||||
const responsePtr = mod._func_compile(configPtr, callbackPtr);
|
||||
|
||||
return JSON.parse(copyFromCString(mod, responsePtr));
|
||||
}
|
||||
|
||||
const wasmModule = require(process.env.FUNCFIFTLIB_MODULE)
|
||||
|
||||
const wasmBinary = new Uint8Array(fsSync.readFileSync(process.env.FUNCFIFTLIB_WASM))
|
||||
|
||||
async function compileWasm() {
|
||||
const mod = await wasmModule({ wasmBinary })
|
||||
|
||||
return mod
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
compileFile,
|
||||
compileWasm
|
||||
}
|
|
@ -29,8 +29,12 @@ using namespace std::literals::string_literals;
|
|||
|
||||
int glob_func_cnt, undef_func_cnt, glob_var_cnt, const_cnt;
|
||||
std::vector<SymDef*> glob_func, glob_vars;
|
||||
std::set<std::string> prohibited_var_names;
|
||||
|
||||
SymDef* predefine_builtin_func(std::string name, TypeExpr* func_type) {
|
||||
if (name.back() == '_') {
|
||||
prohibited_var_names.insert(name);
|
||||
}
|
||||
sym_idx_t name_idx = sym::symbols.lookup(name, 1);
|
||||
if (sym::symbols.is_keyword(name_idx)) {
|
||||
std::cerr << "fatal: global function `" << name << "` already defined as a keyword" << std::endl;
|
||||
|
@ -425,7 +429,7 @@ AsmOp push_const(td::RefInt256 x) {
|
|||
}
|
||||
|
||||
AsmOp compile_add(std::vector<VarDescr>& res, std::vector<VarDescr>& args, const SrcLocation& where) {
|
||||
assert(res.size() == 1 && args.size() == 2);
|
||||
func_assert(res.size() == 1 && args.size() == 2);
|
||||
VarDescr &r = res[0], &x = args[0], &y = args[1];
|
||||
if (x.is_int_const() && y.is_int_const()) {
|
||||
r.set_const(x.int_const + y.int_const);
|
||||
|
@ -467,7 +471,7 @@ AsmOp compile_add(std::vector<VarDescr>& res, std::vector<VarDescr>& args, const
|
|||
}
|
||||
|
||||
AsmOp compile_sub(std::vector<VarDescr>& res, std::vector<VarDescr>& args, const SrcLocation& where) {
|
||||
assert(res.size() == 1 && args.size() == 2);
|
||||
func_assert(res.size() == 1 && args.size() == 2);
|
||||
VarDescr &r = res[0], &x = args[0], &y = args[1];
|
||||
if (x.is_int_const() && y.is_int_const()) {
|
||||
r.set_const(x.int_const - y.int_const);
|
||||
|
@ -500,7 +504,7 @@ AsmOp compile_sub(std::vector<VarDescr>& res, std::vector<VarDescr>& args, const
|
|||
}
|
||||
|
||||
AsmOp compile_negate(std::vector<VarDescr>& res, std::vector<VarDescr>& args, const SrcLocation& where) {
|
||||
assert(res.size() == 1 && args.size() == 1);
|
||||
func_assert(res.size() == 1 && args.size() == 1);
|
||||
VarDescr &r = res[0], &x = args[0];
|
||||
if (x.is_int_const()) {
|
||||
r.set_const(-x.int_const);
|
||||
|
@ -515,7 +519,7 @@ AsmOp compile_negate(std::vector<VarDescr>& res, std::vector<VarDescr>& args, co
|
|||
}
|
||||
|
||||
AsmOp compile_and(std::vector<VarDescr>& res, std::vector<VarDescr>& args, const SrcLocation& where) {
|
||||
assert(res.size() == 1 && args.size() == 2);
|
||||
func_assert(res.size() == 1 && args.size() == 2);
|
||||
VarDescr &r = res[0], &x = args[0], &y = args[1];
|
||||
if (x.is_int_const() && y.is_int_const()) {
|
||||
r.set_const(x.int_const & y.int_const);
|
||||
|
@ -528,7 +532,7 @@ AsmOp compile_and(std::vector<VarDescr>& res, std::vector<VarDescr>& args, const
|
|||
}
|
||||
|
||||
AsmOp compile_or(std::vector<VarDescr>& res, std::vector<VarDescr>& args, const SrcLocation& where) {
|
||||
assert(res.size() == 1 && args.size() == 2);
|
||||
func_assert(res.size() == 1 && args.size() == 2);
|
||||
VarDescr &r = res[0], &x = args[0], &y = args[1];
|
||||
if (x.is_int_const() && y.is_int_const()) {
|
||||
r.set_const(x.int_const | y.int_const);
|
||||
|
@ -541,7 +545,7 @@ AsmOp compile_or(std::vector<VarDescr>& res, std::vector<VarDescr>& args, const
|
|||
}
|
||||
|
||||
AsmOp compile_xor(std::vector<VarDescr>& res, std::vector<VarDescr>& args, const SrcLocation& where) {
|
||||
assert(res.size() == 1 && args.size() == 2);
|
||||
func_assert(res.size() == 1 && args.size() == 2);
|
||||
VarDescr &r = res[0], &x = args[0], &y = args[1];
|
||||
if (x.is_int_const() && y.is_int_const()) {
|
||||
r.set_const(x.int_const ^ y.int_const);
|
||||
|
@ -554,7 +558,7 @@ AsmOp compile_xor(std::vector<VarDescr>& res, std::vector<VarDescr>& args, const
|
|||
}
|
||||
|
||||
AsmOp compile_not(std::vector<VarDescr>& res, std::vector<VarDescr>& args, const SrcLocation& where) {
|
||||
assert(res.size() == 1 && args.size() == 1);
|
||||
func_assert(res.size() == 1 && args.size() == 1);
|
||||
VarDescr &r = res[0], &x = args[0];
|
||||
if (x.is_int_const()) {
|
||||
r.set_const(~x.int_const);
|
||||
|
@ -634,12 +638,12 @@ AsmOp compile_mul_internal(VarDescr& r, VarDescr& x, VarDescr& y, const SrcLocat
|
|||
}
|
||||
|
||||
AsmOp compile_mul(std::vector<VarDescr>& res, std::vector<VarDescr>& args, const SrcLocation& where) {
|
||||
assert(res.size() == 1 && args.size() == 2);
|
||||
func_assert(res.size() == 1 && args.size() == 2);
|
||||
return compile_mul_internal(res[0], args[0], args[1], where);
|
||||
}
|
||||
|
||||
AsmOp compile_lshift(std::vector<VarDescr>& res, std::vector<VarDescr>& args, const SrcLocation& where) {
|
||||
assert(res.size() == 1 && args.size() == 2);
|
||||
func_assert(res.size() == 1 && args.size() == 2);
|
||||
VarDescr &r = res[0], &x = args[0], &y = args[1];
|
||||
if (y.is_int_const()) {
|
||||
auto yv = y.int_const->to_long();
|
||||
|
@ -682,7 +686,7 @@ AsmOp compile_lshift(std::vector<VarDescr>& res, std::vector<VarDescr>& args, co
|
|||
|
||||
AsmOp compile_rshift(std::vector<VarDescr>& res, std::vector<VarDescr>& args, const SrcLocation& where,
|
||||
int round_mode) {
|
||||
assert(res.size() == 1 && args.size() == 2);
|
||||
func_assert(res.size() == 1 && args.size() == 2);
|
||||
VarDescr &r = res[0], &x = args[0], &y = args[1];
|
||||
if (y.is_int_const()) {
|
||||
auto yv = y.int_const->to_long();
|
||||
|
@ -751,13 +755,13 @@ AsmOp compile_div_internal(VarDescr& r, VarDescr& x, VarDescr& y, const SrcLocat
|
|||
}
|
||||
|
||||
AsmOp compile_div(std::vector<VarDescr>& res, std::vector<VarDescr>& args, const SrcLocation& where, int round_mode) {
|
||||
assert(res.size() == 1 && args.size() == 2);
|
||||
func_assert(res.size() == 1 && args.size() == 2);
|
||||
return compile_div_internal(res[0], args[0], args[1], where, round_mode);
|
||||
}
|
||||
|
||||
AsmOp compile_mod(std::vector<VarDescr>& res, std::vector<VarDescr>& args, const src::SrcLocation& where,
|
||||
int round_mode) {
|
||||
assert(res.size() == 1 && args.size() == 2);
|
||||
func_assert(res.size() == 1 && args.size() == 2);
|
||||
VarDescr &r = res[0], &x = args[0], &y = args[1];
|
||||
if (x.is_int_const() && y.is_int_const()) {
|
||||
r.set_const(mod(x.int_const, y.int_const, round_mode));
|
||||
|
@ -798,7 +802,7 @@ AsmOp compile_mod(std::vector<VarDescr>& res, std::vector<VarDescr>& args, const
|
|||
|
||||
AsmOp compile_muldiv(std::vector<VarDescr>& res, std::vector<VarDescr>& args, const SrcLocation& where,
|
||||
int round_mode) {
|
||||
assert(res.size() == 1 && args.size() == 3);
|
||||
func_assert(res.size() == 1 && args.size() == 3);
|
||||
VarDescr &r = res[0], &x = args[0], &y = args[1], &z = args[2];
|
||||
if (x.is_int_const() && y.is_int_const() && z.is_int_const()) {
|
||||
r.set_const(muldiv(x.int_const, y.int_const, z.int_const, round_mode));
|
||||
|
@ -919,8 +923,8 @@ int compute_compare(const VarDescr& x, const VarDescr& y, int mode) {
|
|||
}
|
||||
|
||||
AsmOp compile_cmp_int(std::vector<VarDescr>& res, std::vector<VarDescr>& args, int mode) {
|
||||
assert(mode >= 1 && mode <= 7);
|
||||
assert(res.size() == 1 && args.size() == 2);
|
||||
func_assert(mode >= 1 && mode <= 7);
|
||||
func_assert(res.size() == 1 && args.size() == 2);
|
||||
VarDescr &r = res[0], &x = args[0], &y = args[1];
|
||||
if (x.is_int_const() && y.is_int_const()) {
|
||||
int v = compute_compare(x.int_const, y.int_const, mode);
|
||||
|
@ -931,7 +935,7 @@ AsmOp compile_cmp_int(std::vector<VarDescr>& res, std::vector<VarDescr>& args, i
|
|||
}
|
||||
int v = compute_compare(x, y, mode);
|
||||
// std::cerr << "compute_compare(" << x << ", " << y << ", " << mode << ") = " << v << std::endl;
|
||||
assert(v);
|
||||
func_assert(v);
|
||||
if (!(v & (v - 1))) {
|
||||
r.set_const(v - (v >> 2) - 2);
|
||||
x.unused();
|
||||
|
@ -967,7 +971,7 @@ AsmOp compile_cmp_int(std::vector<VarDescr>& res, std::vector<VarDescr>& args, i
|
|||
}
|
||||
|
||||
AsmOp compile_throw(std::vector<VarDescr>& res, std::vector<VarDescr>& args, const SrcLocation&) {
|
||||
assert(res.empty() && args.size() == 1);
|
||||
func_assert(res.empty() && args.size() == 1);
|
||||
VarDescr& x = args[0];
|
||||
if (x.is_int_const() && x.int_const->unsigned_fits_bits(11)) {
|
||||
x.unused();
|
||||
|
@ -978,7 +982,7 @@ AsmOp compile_throw(std::vector<VarDescr>& res, std::vector<VarDescr>& args, con
|
|||
}
|
||||
|
||||
AsmOp compile_cond_throw(std::vector<VarDescr>& res, std::vector<VarDescr>& args, bool mode) {
|
||||
assert(res.empty() && args.size() == 2);
|
||||
func_assert(res.empty() && args.size() == 2);
|
||||
VarDescr &x = args[0], &y = args[1];
|
||||
std::string suff = (mode ? "IF" : "IFNOT");
|
||||
bool skip_cond = false;
|
||||
|
@ -999,7 +1003,7 @@ AsmOp compile_cond_throw(std::vector<VarDescr>& res, std::vector<VarDescr>& args
|
|||
}
|
||||
|
||||
AsmOp compile_throw_arg(std::vector<VarDescr>& res, std::vector<VarDescr>& args, const SrcLocation&) {
|
||||
assert(res.empty() && args.size() == 2);
|
||||
func_assert(res.empty() && args.size() == 2);
|
||||
VarDescr &x = args[1];
|
||||
if (x.is_int_const() && x.int_const->unsigned_fits_bits(11)) {
|
||||
x.unused();
|
||||
|
@ -1010,7 +1014,7 @@ AsmOp compile_throw_arg(std::vector<VarDescr>& res, std::vector<VarDescr>& args,
|
|||
}
|
||||
|
||||
AsmOp compile_cond_throw_arg(std::vector<VarDescr>& res, std::vector<VarDescr>& args, bool mode) {
|
||||
assert(res.empty() && args.size() == 3);
|
||||
func_assert(res.empty() && args.size() == 3);
|
||||
VarDescr &x = args[1], &y = args[2];
|
||||
std::string suff = (mode ? "IF" : "IFNOT");
|
||||
bool skip_cond = false;
|
||||
|
@ -1031,7 +1035,7 @@ AsmOp compile_cond_throw_arg(std::vector<VarDescr>& res, std::vector<VarDescr>&
|
|||
}
|
||||
|
||||
AsmOp compile_bool_const(std::vector<VarDescr>& res, std::vector<VarDescr>& args, bool val) {
|
||||
assert(res.size() == 1 && args.empty());
|
||||
func_assert(res.size() == 1 && args.empty());
|
||||
VarDescr& r = res[0];
|
||||
r.set_const(val ? -1 : 0);
|
||||
return AsmOp::Const(val ? "TRUE" : "FALSE");
|
||||
|
@ -1042,7 +1046,7 @@ AsmOp compile_bool_const(std::vector<VarDescr>& res, std::vector<VarDescr>& args
|
|||
// int preload_int(slice s, int len) asm "PLDIX";
|
||||
// int preload_uint(slice s, int len) asm "PLDUX";
|
||||
AsmOp compile_fetch_int(std::vector<VarDescr>& res, std::vector<VarDescr>& args, bool fetch, bool sgnd) {
|
||||
assert(args.size() == 2 && res.size() == 1 + (unsigned)fetch);
|
||||
func_assert(args.size() == 2 && res.size() == 1 + (unsigned)fetch);
|
||||
auto &y = args[1], &r = res.back();
|
||||
r.val = (sgnd ? VarDescr::FiniteInt : VarDescr::FiniteUInt);
|
||||
int v = -1;
|
||||
|
@ -1065,7 +1069,7 @@ AsmOp compile_fetch_int(std::vector<VarDescr>& res, std::vector<VarDescr>& args,
|
|||
// builder store_uint(builder b, int x, int len) asm(x b len) "STUX";
|
||||
// builder store_int(builder b, int x, int len) asm(x b len) "STIX";
|
||||
AsmOp compile_store_int(std::vector<VarDescr>& res, std::vector<VarDescr>& args, bool sgnd) {
|
||||
assert(args.size() == 3 && res.size() == 1);
|
||||
func_assert(args.size() == 3 && res.size() == 1);
|
||||
auto& z = args[2];
|
||||
if (z.is_int_const() && z.int_const > 0 && z.int_const <= 256) {
|
||||
z.unused();
|
||||
|
@ -1075,7 +1079,7 @@ AsmOp compile_store_int(std::vector<VarDescr>& res, std::vector<VarDescr>& args,
|
|||
}
|
||||
|
||||
AsmOp compile_fetch_slice(std::vector<VarDescr>& res, std::vector<VarDescr>& args, bool fetch) {
|
||||
assert(args.size() == 2 && res.size() == 1 + (unsigned)fetch);
|
||||
func_assert(args.size() == 2 && res.size() == 1 + (unsigned)fetch);
|
||||
auto& y = args[1];
|
||||
int v = -1;
|
||||
if (y.is_int_const() && y.int_const > 0 && y.int_const <= 256) {
|
||||
|
@ -1090,7 +1094,7 @@ AsmOp compile_fetch_slice(std::vector<VarDescr>& res, std::vector<VarDescr>& arg
|
|||
|
||||
// <type> <type>_at(tuple t, int index) asm "INDEXVAR";
|
||||
AsmOp compile_tuple_at(std::vector<VarDescr>& res, std::vector<VarDescr>& args, const SrcLocation&) {
|
||||
assert(args.size() == 2 && res.size() == 1);
|
||||
func_assert(args.size() == 2 && res.size() == 1);
|
||||
auto& y = args[1];
|
||||
if (y.is_int_const() && y.int_const >= 0 && y.int_const < 16) {
|
||||
y.unused();
|
||||
|
@ -1101,7 +1105,7 @@ AsmOp compile_tuple_at(std::vector<VarDescr>& res, std::vector<VarDescr>& args,
|
|||
|
||||
// int null?(X arg)
|
||||
AsmOp compile_is_null(std::vector<VarDescr>& res, std::vector<VarDescr>& args, const SrcLocation&) {
|
||||
assert(args.size() == 1 && res.size() == 1);
|
||||
func_assert(args.size() == 1 && res.size() == 1);
|
||||
auto &x = args[0], &r = res[0];
|
||||
if (x.always_null() || x.always_not_null()) {
|
||||
x.unused();
|
||||
|
@ -1114,7 +1118,7 @@ AsmOp compile_is_null(std::vector<VarDescr>& res, std::vector<VarDescr>& args, c
|
|||
|
||||
bool compile_run_method(AsmOpList& code, std::vector<VarDescr>& res, std::vector<VarDescr>& args, int n,
|
||||
bool has_value) {
|
||||
assert(args.size() == (unsigned)n + 1 && res.size() == (unsigned)has_value);
|
||||
func_assert(args.size() == (unsigned)n + 1 && res.size() == (unsigned)has_value);
|
||||
auto& x = args[0];
|
||||
if (x.is_int_const() && x.int_const->unsigned_fits_bits(14)) {
|
||||
x.unused();
|
||||
|
|
|
@ -165,7 +165,7 @@ void Stack::push_new_const(var_idx_t idx, const_idx_t cidx) {
|
|||
|
||||
void Stack::assign_var(var_idx_t new_idx, var_idx_t old_idx) {
|
||||
int i = find(old_idx);
|
||||
assert(i >= 0 && "variable not found in stack");
|
||||
func_assert(i >= 0 && "variable not found in stack");
|
||||
if (new_idx != old_idx) {
|
||||
at(i).first = new_idx;
|
||||
modified();
|
||||
|
@ -174,10 +174,10 @@ void Stack::assign_var(var_idx_t new_idx, var_idx_t old_idx) {
|
|||
|
||||
void Stack::do_copy_var(var_idx_t new_idx, var_idx_t old_idx) {
|
||||
int i = find(old_idx);
|
||||
assert(i >= 0 && "variable not found in stack");
|
||||
func_assert(i >= 0 && "variable not found in stack");
|
||||
if (find(old_idx, i + 1) < 0) {
|
||||
issue_push(i);
|
||||
assert(at(0).first == old_idx);
|
||||
func_assert(at(0).first == old_idx);
|
||||
}
|
||||
assign_var(new_idx, old_idx);
|
||||
}
|
||||
|
@ -199,21 +199,21 @@ void Stack::enforce_state(const StackLayout& req_stack) {
|
|||
j = 0;
|
||||
}
|
||||
issue_xchg(j, depth() - i - 1);
|
||||
assert(s[i].first == x);
|
||||
func_assert(s[i].first == x);
|
||||
}
|
||||
while (depth() > k) {
|
||||
issue_pop(0);
|
||||
}
|
||||
assert(depth() == k);
|
||||
func_assert(depth() == k);
|
||||
for (int i = 0; i < k; i++) {
|
||||
assert(s[i].first == req_stack[i]);
|
||||
func_assert(s[i].first == req_stack[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void Stack::merge_const(const Stack& req_stack) {
|
||||
assert(s.size() == req_stack.s.size());
|
||||
func_assert(s.size() == req_stack.s.size());
|
||||
for (std::size_t i = 0; i < s.size(); i++) {
|
||||
assert(s[i].first == req_stack.s[i].first);
|
||||
func_assert(s[i].first == req_stack.s[i].first);
|
||||
if (s[i].second != req_stack.s[i].second) {
|
||||
s[i].second = not_const;
|
||||
}
|
||||
|
@ -251,15 +251,15 @@ void Stack::rearrange_top(const StackLayout& top, std::vector<bool> last) {
|
|||
if (last[i]) {
|
||||
// rearrange x to be at s(ss-1)
|
||||
issue_xchg(--ss, j);
|
||||
assert(get(ss).first == x);
|
||||
func_assert(get(ss).first == x);
|
||||
} else {
|
||||
// create a new copy of x
|
||||
issue_push(j);
|
||||
issue_xchg(0, ss);
|
||||
assert(get(ss).first == x);
|
||||
func_assert(get(ss).first == x);
|
||||
}
|
||||
}
|
||||
assert(!ss);
|
||||
func_assert(!ss);
|
||||
}
|
||||
|
||||
void Stack::rearrange_top(var_idx_t top, bool last) {
|
||||
|
@ -269,7 +269,7 @@ void Stack::rearrange_top(var_idx_t top, bool last) {
|
|||
} else {
|
||||
issue_push(i);
|
||||
}
|
||||
assert(get(0).first == top);
|
||||
func_assert(get(0).first == top);
|
||||
}
|
||||
|
||||
bool Op::generate_code_step(Stack& stack) {
|
||||
|
@ -300,7 +300,7 @@ bool Op::generate_code_step(Stack& stack) {
|
|||
stack.o << push_const(int_const);
|
||||
stack.push_new_const(left[0], cidx);
|
||||
} else {
|
||||
assert(stack.at(i).second == cidx);
|
||||
func_assert(stack.at(i).second == cidx);
|
||||
stack.do_copy_var(left[0], stack[i]);
|
||||
}
|
||||
return true;
|
||||
|
@ -329,7 +329,7 @@ bool Op::generate_code_step(Stack& stack) {
|
|||
std::string name = sym::symbols.get_name(fun_ref->sym_idx);
|
||||
stack.o << AsmOp::Custom(name + " GETGLOB", 0, 1);
|
||||
if (left.size() != 1) {
|
||||
assert(left.size() <= 15);
|
||||
func_assert(left.size() <= 15);
|
||||
stack.o << AsmOp::UnTuple((int)left.size());
|
||||
}
|
||||
for (auto i : left) {
|
||||
|
@ -337,7 +337,7 @@ bool Op::generate_code_step(Stack& stack) {
|
|||
}
|
||||
return true;
|
||||
} else {
|
||||
assert(left.size() == 1);
|
||||
func_assert(left.size() == 1);
|
||||
auto p = next->var_info[left[0]];
|
||||
if (!p || p->is_unused() || disabled()) {
|
||||
return true;
|
||||
|
@ -349,10 +349,10 @@ bool Op::generate_code_step(Stack& stack) {
|
|||
// TODO: create and compile a true lambda instead of this (so that arg_order and ret_order would work correctly)
|
||||
std::vector<VarDescr> args0, res;
|
||||
TypeExpr::remove_indirect(func->sym_type);
|
||||
assert(func->get_type()->is_map());
|
||||
func_assert(func->get_type()->is_map());
|
||||
auto wr = func->get_type()->args.at(0)->get_width();
|
||||
auto wl = func->get_type()->args.at(1)->get_width();
|
||||
assert(wl >= 0 && wr >= 0);
|
||||
func_assert(wl >= 0 && wr >= 0);
|
||||
for (int i = 0; i < wl; i++) {
|
||||
res.emplace_back(0);
|
||||
}
|
||||
|
@ -370,7 +370,7 @@ bool Op::generate_code_step(Stack& stack) {
|
|||
return true;
|
||||
}
|
||||
case _Let: {
|
||||
assert(left.size() == right.size());
|
||||
func_assert(left.size() == right.size());
|
||||
int i = 0;
|
||||
std::vector<bool> active;
|
||||
active.reserve(left.size());
|
||||
|
@ -420,13 +420,13 @@ bool Op::generate_code_step(Stack& stack) {
|
|||
stack.rearrange_top(right, std::move(last));
|
||||
stack.opt_show();
|
||||
int k = (int)stack.depth() - (int)right.size();
|
||||
assert(k >= 0);
|
||||
func_assert(k >= 0);
|
||||
if (cl == _Tuple) {
|
||||
stack.o << AsmOp::Tuple((int)right.size());
|
||||
assert(left.size() == 1);
|
||||
func_assert(left.size() == 1);
|
||||
} else {
|
||||
stack.o << AsmOp::UnTuple((int)left.size());
|
||||
assert(right.size() == 1);
|
||||
func_assert(right.size() == 1);
|
||||
}
|
||||
stack.s.resize(k);
|
||||
for (int i = 0; i < (int)left.size(); i++) {
|
||||
|
@ -442,16 +442,16 @@ bool Op::generate_code_step(Stack& stack) {
|
|||
SymValFunc* func = (fun_ref ? dynamic_cast<SymValFunc*>(fun_ref->value) : nullptr);
|
||||
auto arg_order = (func ? func->get_arg_order() : nullptr);
|
||||
auto ret_order = (func ? func->get_ret_order() : nullptr);
|
||||
assert(!arg_order || arg_order->size() == right.size());
|
||||
assert(!ret_order || ret_order->size() == left.size());
|
||||
func_assert(!arg_order || arg_order->size() == right.size());
|
||||
func_assert(!ret_order || ret_order->size() == left.size());
|
||||
std::vector<var_idx_t> right1;
|
||||
if (args.size()) {
|
||||
assert(args.size() == right.size());
|
||||
func_assert(args.size() == right.size());
|
||||
for (int i = 0; i < (int)right.size(); i++) {
|
||||
int j = arg_order ? arg_order->at(i) : i;
|
||||
const VarDescr& arg = args.at(j);
|
||||
if (!arg.is_unused()) {
|
||||
assert(var_info[arg.idx] && !var_info[arg.idx]->is_unused());
|
||||
func_assert(var_info[arg.idx] && !var_info[arg.idx]->is_unused());
|
||||
right1.push_back(arg.idx);
|
||||
}
|
||||
}
|
||||
|
@ -469,17 +469,25 @@ bool Op::generate_code_step(Stack& stack) {
|
|||
stack.rearrange_top(right1, std::move(last));
|
||||
stack.opt_show();
|
||||
int k = (int)stack.depth() - (int)right1.size();
|
||||
assert(k >= 0);
|
||||
func_assert(k >= 0);
|
||||
for (int i = 0; i < (int)right1.size(); i++) {
|
||||
if (stack.s[k + i].first != right1[i]) {
|
||||
std::cerr << stack.o;
|
||||
}
|
||||
assert(stack.s[k + i].first == right1[i]);
|
||||
func_assert(stack.s[k + i].first == right1[i]);
|
||||
}
|
||||
auto exec_callxargs = [&](int args, int ret) {
|
||||
if (args <= 15 && ret <= 15) {
|
||||
stack.o << exec_arg2_op("CALLXARGS", args, ret, args + 1, ret);
|
||||
} else {
|
||||
func_assert(args <= 254 && ret <= 254);
|
||||
stack.o << AsmOp::Const(PSTRING() << args << " PUSHINT");
|
||||
stack.o << AsmOp::Const(PSTRING() << ret << " PUSHINT");
|
||||
stack.o << AsmOp::Custom("CALLXVARARGS", args + 3, ret);
|
||||
}
|
||||
};
|
||||
if (cl == _CallInd) {
|
||||
// TODO: replace with exec_arg2_op()
|
||||
stack.o << exec_arg2_op("CALLXARGS", (int)right.size() - 1, (int)left.size(), (int)right.size(),
|
||||
(int)left.size());
|
||||
exec_callxargs((int)right.size() - 1, (int)left.size());
|
||||
} else {
|
||||
auto func = dynamic_cast<const SymValAsmFunc*>(fun_ref->value);
|
||||
if (func) {
|
||||
|
@ -493,8 +501,14 @@ bool Op::generate_code_step(Stack& stack) {
|
|||
auto fv = dynamic_cast<const SymValCodeFunc*>(fun_ref->value);
|
||||
std::string name = sym::symbols.get_name(fun_ref->sym_idx);
|
||||
bool is_inline = (fv && (fv->flags & 3));
|
||||
stack.o << AsmOp::Custom(name + (is_inline ? " INLINECALLDICT" : " CALLDICT"), (int)right.size(),
|
||||
(int)left.size());
|
||||
if (is_inline) {
|
||||
stack.o << AsmOp::Custom(name + " INLINECALLDICT", (int)right.size(), (int)left.size());
|
||||
} else if (fv && fv->code && fv->code->require_callxargs) {
|
||||
stack.o << AsmOp::Custom(name + (" PREPAREDICT"), 0, 2);
|
||||
exec_callxargs((int)right.size() + 1, (int)left.size());
|
||||
} else {
|
||||
stack.o << AsmOp::Custom(name + " CALLDICT", (int)right.size(), (int)left.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
stack.s.resize(k);
|
||||
|
@ -505,7 +519,7 @@ bool Op::generate_code_step(Stack& stack) {
|
|||
return true;
|
||||
}
|
||||
case _SetGlob: {
|
||||
assert(fun_ref && dynamic_cast<const SymValGlobVar*>(fun_ref->value));
|
||||
func_assert(fun_ref && dynamic_cast<const SymValGlobVar*>(fun_ref->value));
|
||||
std::vector<bool> last;
|
||||
for (var_idx_t x : right) {
|
||||
last.push_back(var_info[x] && var_info[x]->is_last());
|
||||
|
@ -513,12 +527,12 @@ bool Op::generate_code_step(Stack& stack) {
|
|||
stack.rearrange_top(right, std::move(last));
|
||||
stack.opt_show();
|
||||
int k = (int)stack.depth() - (int)right.size();
|
||||
assert(k >= 0);
|
||||
func_assert(k >= 0);
|
||||
for (int i = 0; i < (int)right.size(); i++) {
|
||||
if (stack.s[k + i].first != right[i]) {
|
||||
std::cerr << stack.o;
|
||||
}
|
||||
assert(stack.s[k + i].first == right[i]);
|
||||
func_assert(stack.s[k + i].first == right[i]);
|
||||
}
|
||||
if (right.size() > 1) {
|
||||
stack.o << AsmOp::Tuple((int)right.size());
|
||||
|
@ -539,7 +553,7 @@ bool Op::generate_code_step(Stack& stack) {
|
|||
}
|
||||
var_idx_t x = left[0];
|
||||
stack.rearrange_top(x, var_info[x] && var_info[x]->is_last());
|
||||
assert(stack[0] == x);
|
||||
func_assert(stack[0] == x);
|
||||
stack.opt_show();
|
||||
stack.s.pop_back();
|
||||
stack.modified();
|
||||
|
@ -651,7 +665,7 @@ bool Op::generate_code_step(Stack& stack) {
|
|||
var_idx_t x = left[0];
|
||||
//stack.drop_vars_except(block0->var_info, x);
|
||||
stack.rearrange_top(x, var_info[x] && var_info[x]->is_last());
|
||||
assert(stack[0] == x);
|
||||
func_assert(stack[0] == x);
|
||||
stack.opt_show();
|
||||
stack.s.pop_back();
|
||||
stack.modified();
|
||||
|
@ -877,12 +891,13 @@ void Op::generate_code_all(Stack& stack) {
|
|||
|
||||
void CodeBlob::generate_code(AsmOpList& out, int mode) {
|
||||
Stack stack{out, mode};
|
||||
assert(ops && ops->cl == Op::_Import);
|
||||
func_assert(ops && ops->cl == Op::_Import);
|
||||
auto args = (int)ops->left.size();
|
||||
for (var_idx_t x : ops->left) {
|
||||
stack.push_new_var(x);
|
||||
}
|
||||
ops->generate_code_all(stack);
|
||||
stack.apply_wrappers();
|
||||
stack.apply_wrappers(require_callxargs && (mode & Stack::_InlineAny) ? args : -1);
|
||||
if (!(mode & Stack::_DisableOpt)) {
|
||||
optimize_code(out);
|
||||
}
|
||||
|
|
|
@ -72,7 +72,7 @@ td::Result<std::string> fs_read_callback(ReadCallback::Kind kind, const char* qu
|
|||
|
||||
void generate_output_func(SymDef* func_sym, std::ostream &outs, std::ostream &errs) {
|
||||
SymValCodeFunc* func_val = dynamic_cast<SymValCodeFunc*>(func_sym->value);
|
||||
assert(func_val);
|
||||
func_assert(func_val);
|
||||
std::string name = sym::symbols.get_name(func_sym->sym_idx);
|
||||
if (verbosity >= 2) {
|
||||
errs << "\n\n=========================\nfunction " << name << " : " << func_val->get_type() << std::endl;
|
||||
|
@ -145,6 +145,9 @@ void generate_output_func(SymDef* func_sym, std::ostream &outs, std::ostream &er
|
|||
if (fv && (fv->flags & 1) && code.ops->noreturn()) {
|
||||
mode |= Stack::_InlineFunc;
|
||||
}
|
||||
if (fv && (fv->flags & 3)) {
|
||||
mode |= Stack::_InlineAny;
|
||||
}
|
||||
code.generate_code(outs, mode, indent + 1);
|
||||
outs << std::string(indent * 2, ' ') << "}>\n";
|
||||
if (verbosity >= 2) {
|
||||
|
@ -163,7 +166,7 @@ int generate_output(std::ostream &outs, std::ostream &errs) {
|
|||
}
|
||||
for (SymDef* func_sym : glob_func) {
|
||||
SymValCodeFunc* func_val = dynamic_cast<SymValCodeFunc*>(func_sym->value);
|
||||
assert(func_val);
|
||||
func_assert(func_val);
|
||||
std::string name = sym::symbols.get_name(func_sym->sym_idx);
|
||||
outs << std::string(indent * 2, ' ');
|
||||
if (func_val->method_id.is_null()) {
|
||||
|
@ -173,7 +176,7 @@ int generate_output(std::ostream &outs, std::ostream &errs) {
|
|||
}
|
||||
}
|
||||
for (SymDef* gvar_sym : glob_vars) {
|
||||
assert(dynamic_cast<SymValGlobVar*>(gvar_sym->value));
|
||||
func_assert(dynamic_cast<SymValGlobVar*>(gvar_sym->value));
|
||||
std::string name = sym::symbols.get_name(gvar_sym->sym_idx);
|
||||
outs << std::string(indent * 2, ' ') << "DECLGLOBVAR " << name << "\n";
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#pragma once
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <set>
|
||||
#include <stack>
|
||||
#include <utility>
|
||||
#include <algorithm>
|
||||
|
@ -32,6 +33,10 @@
|
|||
#include "parser/symtable.h"
|
||||
#include "td/utils/Status.h"
|
||||
|
||||
#define func_assert(expr) \
|
||||
(bool(expr) ? void(0) \
|
||||
: throw src::Fatal(PSTRING() << "Assertion failed at " << __FILE__ << ":" << __LINE__ << ": " << #expr))
|
||||
|
||||
namespace funC {
|
||||
|
||||
extern int verbosity;
|
||||
|
@ -40,7 +45,7 @@ extern std::string generated_from;
|
|||
|
||||
constexpr int optimize_depth = 20;
|
||||
|
||||
const std::string func_version{"0.4.2"};
|
||||
const std::string func_version{"0.4.4"};
|
||||
|
||||
enum Keyword {
|
||||
_Eof = -1,
|
||||
|
@ -158,6 +163,7 @@ struct TypeExpr {
|
|||
int minw, maxw;
|
||||
static constexpr int w_inf = 1023;
|
||||
std::vector<TypeExpr*> args;
|
||||
bool was_forall_var = false;
|
||||
TypeExpr(te_type _constr, int _val = 0) : constr(_constr), value(_val), minw(0), maxw(w_inf) {
|
||||
}
|
||||
TypeExpr(te_type _constr, int _val, int width) : constr(_constr), value(_val), minw(width), maxw(width) {
|
||||
|
@ -264,7 +270,7 @@ struct TypeExpr {
|
|||
return new TypeExpr{te_ForAll, body, std::move(list)};
|
||||
}
|
||||
static bool remove_indirect(TypeExpr*& te, TypeExpr* forbidden = nullptr);
|
||||
static bool remove_forall(TypeExpr*& te);
|
||||
static std::vector<TypeExpr*> remove_forall(TypeExpr*& te);
|
||||
static bool remove_forall_in(TypeExpr*& te, TypeExpr* te2, const std::vector<TypeExpr*>& new_vars);
|
||||
};
|
||||
|
||||
|
@ -308,6 +314,7 @@ struct TmpVar {
|
|||
int coord;
|
||||
std::unique_ptr<SrcLocation> where;
|
||||
std::vector<std::function<void(const SrcLocation &)>> on_modification;
|
||||
bool undefined = false;
|
||||
TmpVar(var_idx_t _idx, int _cls, TypeExpr* _type = 0, SymDef* sym = 0, const SrcLocation* loc = 0);
|
||||
void show(std::ostream& os, int omit_idx = 0) const;
|
||||
void dump(std::ostream& os) const;
|
||||
|
@ -692,6 +699,7 @@ struct CodeBlob {
|
|||
std::unique_ptr<Op>* cur_ops;
|
||||
std::stack<std::unique_ptr<Op>*> cur_ops_stack;
|
||||
int flags = 0;
|
||||
bool require_callxargs = false;
|
||||
CodeBlob(TypeExpr* ret = nullptr) : var_cnt(0), in_var_cnt(0), op_cnt(0), ret_type(ret), cur_ops(&ops) {
|
||||
}
|
||||
template <typename... Args>
|
||||
|
@ -839,6 +847,7 @@ struct SymValConst : sym::SymValBase {
|
|||
|
||||
extern int glob_func_cnt, undef_func_cnt, glob_var_cnt;
|
||||
extern std::vector<SymDef*> glob_func, glob_vars;
|
||||
extern std::set<std::string> prohibited_var_names;
|
||||
|
||||
/*
|
||||
*
|
||||
|
@ -1174,7 +1183,7 @@ struct AsmOpList {
|
|||
}
|
||||
template <typename... Args>
|
||||
AsmOpList& add(Args&&... args) {
|
||||
list_.emplace_back(std::forward<Args>(args)...);
|
||||
append(AsmOp(std::forward<Args>(args)...));
|
||||
adjust_last();
|
||||
return *this;
|
||||
}
|
||||
|
@ -1561,8 +1570,8 @@ struct Stack {
|
|||
AsmOpList& o;
|
||||
enum {
|
||||
_StkCmt = 1, _CptStkCmt = 2, _DisableOpt = 4, _DisableOut = 128, _Shown = 256,
|
||||
_InlineFunc = 512, _NeedRetAlt = 1024,
|
||||
_ModeSave = _InlineFunc | _NeedRetAlt,
|
||||
_InlineFunc = 512, _NeedRetAlt = 1024, _InlineAny = 2048,
|
||||
_ModeSave = _InlineFunc | _NeedRetAlt | _InlineAny,
|
||||
_Garbage = -0x10000
|
||||
};
|
||||
int mode;
|
||||
|
@ -1609,7 +1618,7 @@ struct Stack {
|
|||
if (i > 255) {
|
||||
throw src::Fatal{"Too deep stack"};
|
||||
}
|
||||
assert(i >= 0 && i < depth() && "invalid stack reference");
|
||||
func_assert(i >= 0 && i < depth() && "invalid stack reference");
|
||||
}
|
||||
void modified() {
|
||||
mode &= ~_Shown;
|
||||
|
@ -1640,14 +1649,24 @@ struct Stack {
|
|||
bool operator==(const Stack& y) const & {
|
||||
return s == y.s;
|
||||
}
|
||||
void apply_wrappers() {
|
||||
void apply_wrappers(int callxargs_count) {
|
||||
bool is_inline = mode & _InlineFunc;
|
||||
if (o.retalt_) {
|
||||
o.insert(0, "SAMEALTSAVE");
|
||||
o.insert(0, "c2 SAVE");
|
||||
if (mode & _InlineFunc) {
|
||||
o.indent_all();
|
||||
o.insert(0, "CONT:<{");
|
||||
o << "}>";
|
||||
}
|
||||
if (callxargs_count != -1 || (is_inline && o.retalt_)) {
|
||||
o.indent_all();
|
||||
o.insert(0, "CONT:<{");
|
||||
o << "}>";
|
||||
if (callxargs_count != -1) {
|
||||
if (callxargs_count <= 15) {
|
||||
o << AsmOp::Custom(PSTRING() << callxargs_count << " -1 CALLXARGS");
|
||||
} else {
|
||||
func_assert(callxargs_count <= 254);
|
||||
o << AsmOp::Custom(PSTRING() << callxargs_count << " PUSHINT -1 PUSHINT CALLXVARARGS");
|
||||
}
|
||||
} else {
|
||||
o << "EXECUTE";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -92,7 +92,7 @@ bool Expr::deduce_type(const Lexem& lem) {
|
|||
return true;
|
||||
}
|
||||
case _VarApply: {
|
||||
assert(args.size() == 2);
|
||||
func_assert(args.size() == 2);
|
||||
TypeExpr* fun_type = TypeExpr::new_map(args[1]->e_type, TypeExpr::new_hole());
|
||||
try {
|
||||
unify(fun_type, args[0]->e_type);
|
||||
|
@ -107,7 +107,7 @@ bool Expr::deduce_type(const Lexem& lem) {
|
|||
return true;
|
||||
}
|
||||
case _Letop: {
|
||||
assert(args.size() == 2);
|
||||
func_assert(args.size() == 2);
|
||||
try {
|
||||
// std::cerr << "in assignment: " << args[0]->e_type << " from " << args[1]->e_type << std::endl;
|
||||
unify(args[0]->e_type, args[1]->e_type);
|
||||
|
@ -122,7 +122,7 @@ bool Expr::deduce_type(const Lexem& lem) {
|
|||
return true;
|
||||
}
|
||||
case _LetFirst: {
|
||||
assert(args.size() == 2);
|
||||
func_assert(args.size() == 2);
|
||||
TypeExpr* rhs_type = TypeExpr::new_tensor({args[0]->e_type, TypeExpr::new_hole()});
|
||||
try {
|
||||
// std::cerr << "in implicit assignment of a modifying method: " << rhs_type << " and " << args[1]->e_type << std::endl;
|
||||
|
@ -140,7 +140,7 @@ bool Expr::deduce_type(const Lexem& lem) {
|
|||
return true;
|
||||
}
|
||||
case _CondExpr: {
|
||||
assert(args.size() == 3);
|
||||
func_assert(args.size() == 3);
|
||||
auto flag_type = TypeExpr::new_atomic(_Int);
|
||||
try {
|
||||
unify(args[0]->e_type, flag_type);
|
||||
|
@ -204,7 +204,11 @@ int Expr::predefine_vars() {
|
|||
}
|
||||
case _Var:
|
||||
if (!sym) {
|
||||
assert(val < 0 && here.defined());
|
||||
func_assert(val < 0 && here.defined());
|
||||
if (prohibited_var_names.count(sym::symbols.get_name(~val))) {
|
||||
throw src::ParseError{
|
||||
here, PSTRING() << "symbol `" << sym::symbols.get_name(~val) << "` cannot be redefined as a variable"};
|
||||
}
|
||||
sym = sym::define_symbol(~val, false, here);
|
||||
// std::cerr << "predefining variable " << sym::symbols.get_name(~val) << std::endl;
|
||||
if (!sym) {
|
||||
|
@ -270,7 +274,7 @@ std::vector<var_idx_t> pre_compile_tensor(const std::vector<Expr *> args, CodeBl
|
|||
arg_order.resize(args.size());
|
||||
std::iota(arg_order.begin(), arg_order.end(), 0);
|
||||
}
|
||||
assert(args.size() == arg_order.size());
|
||||
func_assert(args.size() == arg_order.size());
|
||||
std::vector<std::vector<var_idx_t>> res_lists(args.size());
|
||||
|
||||
struct ModifiedVar {
|
||||
|
@ -306,7 +310,7 @@ std::vector<var_idx_t> pre_compile_tensor(const std::vector<Expr *> args, CodeBl
|
|||
}
|
||||
for (const auto& list : res_lists) {
|
||||
for (var_idx_t v : list) {
|
||||
assert(!code.vars.at(v).on_modification.empty());
|
||||
func_assert(!code.vars.at(v).on_modification.empty());
|
||||
code.vars.at(v).on_modification.pop_back();
|
||||
}
|
||||
}
|
||||
|
@ -335,7 +339,7 @@ std::vector<var_idx_t> Expr::pre_compile(CodeBlob& code, std::vector<std::pair<S
|
|||
return pre_compile_tensor(args, code, lval_globs, {});
|
||||
}
|
||||
case _Apply: {
|
||||
assert(sym);
|
||||
func_assert(sym);
|
||||
auto func = dynamic_cast<SymValFunc*>(sym->value);
|
||||
std::vector<var_idx_t> res;
|
||||
if (func && func->arg_order.size() == args.size() && !(code.flags & CodeBlob::_ComputeAsmLtr)) {
|
||||
|
@ -422,7 +426,7 @@ std::vector<var_idx_t> Expr::pre_compile(CodeBlob& code, std::vector<std::pair<S
|
|||
}
|
||||
case _CondExpr: {
|
||||
auto cond = args[0]->pre_compile(code);
|
||||
assert(cond.size() == 1);
|
||||
func_assert(cond.size() == 1);
|
||||
auto rvect = new_tmp_vect(code);
|
||||
Op& if_op = code.emplace_back(here, Op::_If, cond);
|
||||
code.push_set_cur(if_op.block0);
|
||||
|
|
|
@ -61,9 +61,9 @@ void Optimizer::apply() {
|
|||
if (!p_ && !q_) {
|
||||
return;
|
||||
}
|
||||
assert(p_ > 0 && p_ <= l_ && q_ >= 0 && q_ <= n && l_ <= n);
|
||||
func_assert(p_ > 0 && p_ <= l_ && q_ >= 0 && q_ <= n && l_ <= n);
|
||||
for (int i = p_; i < l_; i++) {
|
||||
assert(op_[i]);
|
||||
func_assert(op_[i]);
|
||||
op_cons_[i]->car = std::move(op_[i]);
|
||||
op_cons_[i] = nullptr;
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ void Optimizer::apply() {
|
|||
code_ = std::move(code_->cdr);
|
||||
}
|
||||
for (int j = q_ - 1; j >= 0; j--) {
|
||||
assert(oq_[j]);
|
||||
func_assert(oq_[j]);
|
||||
oq_[j]->indent = indent_;
|
||||
code_ = AsmOpCons::cons(std::move(oq_[j]), std::move(code_));
|
||||
}
|
||||
|
@ -246,7 +246,7 @@ bool Optimizer::rewrite_const_push_xchgs() {
|
|||
}
|
||||
show_left();
|
||||
auto c_op = std::move(op_[0]);
|
||||
assert(c_op->is_gconst());
|
||||
func_assert(c_op->is_gconst());
|
||||
StackTransform t;
|
||||
q_ = 0;
|
||||
int pos = 0;
|
||||
|
@ -265,31 +265,31 @@ bool Optimizer::rewrite_const_push_xchgs() {
|
|||
if (b > pos) {
|
||||
oq_[q_]->b = b - 1;
|
||||
}
|
||||
assert(apply_op(t, *oq_[q_]));
|
||||
func_assert(apply_op(t, *oq_[q_]));
|
||||
++q_;
|
||||
}
|
||||
} else {
|
||||
assert(op_[i]->is_push(&a));
|
||||
assert(a != pos);
|
||||
func_assert(op_[i]->is_push(&a));
|
||||
func_assert(a != pos);
|
||||
oq_[q_] = std::move(op_[i]);
|
||||
if (a > pos) {
|
||||
oq_[q_]->a = a - 1;
|
||||
}
|
||||
assert(apply_op(t, *oq_[q_]));
|
||||
func_assert(apply_op(t, *oq_[q_]));
|
||||
++q_;
|
||||
++pos;
|
||||
}
|
||||
}
|
||||
assert(!pos);
|
||||
func_assert(!pos);
|
||||
t.apply_push_newconst();
|
||||
assert(t <= tr_[p_ - 1]);
|
||||
func_assert(t <= tr_[p_ - 1]);
|
||||
oq_[q_++] = std::move(c_op);
|
||||
show_right();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Optimizer::rewrite(int p, AsmOp&& new_op) {
|
||||
assert(p > 0 && p <= l_);
|
||||
func_assert(p > 0 && p <= l_);
|
||||
p_ = p;
|
||||
q_ = 1;
|
||||
show_left();
|
||||
|
@ -300,7 +300,7 @@ bool Optimizer::rewrite(int p, AsmOp&& new_op) {
|
|||
}
|
||||
|
||||
bool Optimizer::rewrite(int p, AsmOp&& new_op1, AsmOp&& new_op2) {
|
||||
assert(p > 1 && p <= l_);
|
||||
func_assert(p > 1 && p <= l_);
|
||||
p_ = p;
|
||||
q_ = 2;
|
||||
show_left();
|
||||
|
@ -313,7 +313,7 @@ bool Optimizer::rewrite(int p, AsmOp&& new_op1, AsmOp&& new_op2) {
|
|||
}
|
||||
|
||||
bool Optimizer::rewrite(int p, AsmOp&& new_op1, AsmOp&& new_op2, AsmOp&& new_op3) {
|
||||
assert(p > 2 && p <= l_);
|
||||
func_assert(p > 2 && p <= l_);
|
||||
p_ = p;
|
||||
q_ = 3;
|
||||
show_left();
|
||||
|
@ -328,7 +328,7 @@ bool Optimizer::rewrite(int p, AsmOp&& new_op1, AsmOp&& new_op2, AsmOp&& new_op3
|
|||
}
|
||||
|
||||
bool Optimizer::rewrite_nop() {
|
||||
assert(p_ > 0 && p_ <= l_);
|
||||
func_assert(p_ > 0 && p_ <= l_);
|
||||
q_ = 0;
|
||||
show_left();
|
||||
show_right();
|
||||
|
|
|
@ -172,6 +172,10 @@ FormalArg parse_formal_arg(Lexer& lex, int fa_idx) {
|
|||
lex.expect(_Ident, "formal parameter name");
|
||||
}
|
||||
loc = lex.cur().loc;
|
||||
if (prohibited_var_names.count(sym::symbols.get_name(lex.cur().val))) {
|
||||
throw src::ParseError{
|
||||
loc, PSTRING() << "symbol `" << sym::symbols.get_name(lex.cur().val) << "` cannot be redefined as a variable"};
|
||||
}
|
||||
SymDef* new_sym_def = sym::define_symbol(lex.cur().val, true, loc);
|
||||
if (!new_sym_def) {
|
||||
lex.cur().error_at("cannot define symbol `", "`");
|
||||
|
@ -395,9 +399,9 @@ bool check_global_func(const Lexem& cur, sym_idx_t func_name = 0) {
|
|||
cur.loc.show_error(std::string{"undefined function `"} + symbols.get_name(func_name) +
|
||||
"`, defining a global function of unknown type");
|
||||
def = sym::define_global_symbol(func_name, 0, cur.loc);
|
||||
assert(def && "cannot define global function");
|
||||
func_assert(def && "cannot define global function");
|
||||
++undef_func_cnt;
|
||||
make_new_glob_func(def, TypeExpr::new_hole()); // was: ... ::new_func()
|
||||
make_new_glob_func(def, TypeExpr::new_func()); // was: ... ::new_func()
|
||||
return true;
|
||||
}
|
||||
SymVal* val = dynamic_cast<SymVal*>(def->value);
|
||||
|
@ -1107,6 +1111,7 @@ blk_fl::val parse_do_stmt(Lexer& lex, CodeBlob& code) {
|
|||
}
|
||||
|
||||
blk_fl::val parse_try_catch_stmt(Lexer& lex, CodeBlob& code) {
|
||||
code.require_callxargs = true;
|
||||
lex.expect(_Try);
|
||||
Op& try_catch_op = code.emplace_back(lex.cur().loc, Op::_TryCatch);
|
||||
code.push_set_cur(try_catch_op.block0);
|
||||
|
@ -1128,7 +1133,7 @@ blk_fl::val parse_try_catch_stmt(Lexer& lex, CodeBlob& code) {
|
|||
expr->predefine_vars();
|
||||
expr->define_new_vars(code);
|
||||
try_catch_op.left = expr->pre_compile(code);
|
||||
assert(try_catch_op.left.size() == 2);
|
||||
func_assert(try_catch_op.left.size() == 2 || try_catch_op.left.size() == 1);
|
||||
blk_fl::val res1 = parse_block_stmt(lex, code);
|
||||
sym::close_scope(lex);
|
||||
code.close_pop_cur(lex.cur().loc);
|
||||
|
@ -1291,7 +1296,7 @@ SymValAsmFunc* parse_asm_func_body(Lexer& lex, TypeExpr* func_type, const Formal
|
|||
}
|
||||
lex.next();
|
||||
}
|
||||
assert(arg_order.size() == (unsigned)tot_width);
|
||||
func_assert(arg_order.size() == (unsigned)tot_width);
|
||||
}
|
||||
if (lex.tp() == _Mapsto) {
|
||||
lex.expect(_Mapsto);
|
||||
|
@ -1369,6 +1374,10 @@ std::vector<TypeExpr*> parse_type_var_list(Lexer& lex) {
|
|||
throw src::ParseError{lex.cur().loc, "free type identifier expected"};
|
||||
}
|
||||
auto loc = lex.cur().loc;
|
||||
if (prohibited_var_names.count(sym::symbols.get_name(lex.cur().val))) {
|
||||
throw src::ParseError{loc, PSTRING() << "symbol `" << sym::symbols.get_name(lex.cur().val)
|
||||
<< "` cannot be redefined as a variable"};
|
||||
}
|
||||
SymDef* new_sym_def = sym::define_symbol(lex.cur().val, true, loc);
|
||||
if (!new_sym_def || new_sym_def->value) {
|
||||
lex.cur().error_at("redefined type variable `", "`");
|
||||
|
@ -1479,7 +1488,7 @@ void parse_func_def(Lexer& lex) {
|
|||
std::cerr << "function " << func_name.str << " : " << func_type << std::endl;
|
||||
}
|
||||
SymDef* func_sym = sym::define_global_symbol(func_name.val, 0, loc);
|
||||
assert(func_sym);
|
||||
func_assert(func_sym);
|
||||
SymValFunc* func_sym_val = dynamic_cast<SymValFunc*>(func_sym->value);
|
||||
if (func_sym->value) {
|
||||
if (func_sym->value->type != SymVal::_Func || !func_sym_val) {
|
||||
|
|
|
@ -183,7 +183,7 @@ bool StackTransform::is_permutation() const {
|
|||
if (!is_valid() || d) {
|
||||
return false;
|
||||
}
|
||||
assert(n <= max_n);
|
||||
func_assert(n <= max_n);
|
||||
std::array<int, max_n> X, Y;
|
||||
for (int i = 0; i < n; i++) {
|
||||
X[i] = A[i].first;
|
||||
|
|
|
@ -132,7 +132,7 @@ void TypeExpr::replace_with(TypeExpr* te2) {
|
|||
}
|
||||
|
||||
bool TypeExpr::remove_indirect(TypeExpr*& te, TypeExpr* forbidden) {
|
||||
assert(te);
|
||||
func_assert(te);
|
||||
while (te->constr == te_Indirect) {
|
||||
te = te->args[0];
|
||||
}
|
||||
|
@ -146,12 +146,9 @@ bool TypeExpr::remove_indirect(TypeExpr*& te, TypeExpr* forbidden) {
|
|||
return res;
|
||||
}
|
||||
|
||||
bool TypeExpr::remove_forall(TypeExpr*& te) {
|
||||
assert(te);
|
||||
if (te->constr != te_ForAll) {
|
||||
return false;
|
||||
}
|
||||
assert(te->args.size() >= 1);
|
||||
std::vector<TypeExpr*> TypeExpr::remove_forall(TypeExpr*& te) {
|
||||
func_assert(te && te->constr == te_ForAll);
|
||||
func_assert(te->args.size() >= 1);
|
||||
std::vector<TypeExpr*> new_vars;
|
||||
for (std::size_t i = 1; i < te->args.size(); i++) {
|
||||
new_vars.push_back(new_hole(1));
|
||||
|
@ -161,12 +158,12 @@ bool TypeExpr::remove_forall(TypeExpr*& te) {
|
|||
te = te->args[0];
|
||||
remove_forall_in(te, te2, new_vars);
|
||||
// std::cerr << "-> " << te << std::endl;
|
||||
return true;
|
||||
return new_vars;
|
||||
}
|
||||
|
||||
bool TypeExpr::remove_forall_in(TypeExpr*& te, TypeExpr* te2, const std::vector<TypeExpr*>& new_vars) {
|
||||
assert(te);
|
||||
assert(te2 && te2->constr == te_ForAll);
|
||||
func_assert(te);
|
||||
func_assert(te2 && te2->constr == te_ForAll);
|
||||
if (te->constr == te_Var) {
|
||||
for (std::size_t i = 0; i < new_vars.size(); i++) {
|
||||
if (te == te2->args[i + 1]) {
|
||||
|
@ -280,7 +277,7 @@ std::ostream& TypeExpr::print(std::ostream& os, int lex_level) {
|
|||
return os << "]";
|
||||
}
|
||||
case te_Map: {
|
||||
assert(args.size() == 2);
|
||||
func_assert(args.size() == 2);
|
||||
if (lex_level > 0) {
|
||||
os << "(";
|
||||
}
|
||||
|
@ -293,7 +290,7 @@ std::ostream& TypeExpr::print(std::ostream& os, int lex_level) {
|
|||
return os;
|
||||
}
|
||||
case te_ForAll: {
|
||||
assert(args.size() >= 1);
|
||||
func_assert(args.size() >= 1);
|
||||
if (lex_level > 0) {
|
||||
os << '(';
|
||||
}
|
||||
|
@ -346,11 +343,11 @@ void check_update_widths(TypeExpr* te1, TypeExpr* te2) {
|
|||
check_width_compat(te1, te2);
|
||||
te1->minw = te2->minw = std::max(te1->minw, te2->minw);
|
||||
te1->maxw = te2->maxw = std::min(te1->maxw, te2->maxw);
|
||||
assert(te1->minw <= te1->maxw);
|
||||
func_assert(te1->minw <= te1->maxw);
|
||||
}
|
||||
|
||||
void unify(TypeExpr*& te1, TypeExpr*& te2) {
|
||||
assert(te1 && te2);
|
||||
func_assert(te1 && te2);
|
||||
// std::cerr << "unify( " << te1 << " , " << te2 << " )\n";
|
||||
while (te1->constr == TypeExpr::te_Indirect) {
|
||||
te1 = te1->args[0];
|
||||
|
@ -363,23 +360,37 @@ void unify(TypeExpr*& te1, TypeExpr*& te2) {
|
|||
}
|
||||
if (te1->constr == TypeExpr::te_ForAll) {
|
||||
TypeExpr* te = te1;
|
||||
if (!TypeExpr::remove_forall(te)) {
|
||||
throw UnifyError{te1, te2, "cannot remove universal type quantifier while performing type unification"};
|
||||
std::vector<TypeExpr*> new_vars = TypeExpr::remove_forall(te);
|
||||
for (TypeExpr* t : new_vars) {
|
||||
t->was_forall_var = true;
|
||||
}
|
||||
unify(te, te2);
|
||||
for (TypeExpr* t : new_vars) {
|
||||
t->was_forall_var = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (te2->constr == TypeExpr::te_ForAll) {
|
||||
TypeExpr* te = te2;
|
||||
if (!TypeExpr::remove_forall(te)) {
|
||||
throw UnifyError{te2, te1, "cannot remove universal type quantifier while performing type unification"};
|
||||
std::vector<TypeExpr*> new_vars = TypeExpr::remove_forall(te);
|
||||
for (TypeExpr* t : new_vars) {
|
||||
t->was_forall_var = true;
|
||||
}
|
||||
unify(te1, te);
|
||||
for (TypeExpr* t : new_vars) {
|
||||
t->was_forall_var = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (te1->was_forall_var && te2->constr == TypeExpr::te_Tensor) {
|
||||
throw UnifyError{te1, te2, "cannot unify generic type and tensor"};
|
||||
}
|
||||
if (te2->was_forall_var && te1->constr == TypeExpr::te_Tensor) {
|
||||
throw UnifyError{te2, te1, "cannot unify generic type and tensor"};
|
||||
}
|
||||
if (te1->constr == TypeExpr::te_Unknown) {
|
||||
if (te2->constr == TypeExpr::te_Unknown) {
|
||||
assert(te1->value != te2->value);
|
||||
func_assert(te1->value != te2->value);
|
||||
}
|
||||
if (!TypeExpr::remove_indirect(te2, te1)) {
|
||||
throw UnifyError{te1, te2, "type unification results in an infinite cyclic type"};
|
||||
|
|
|
@ -92,6 +92,7 @@ td::Result<std::string> compile_internal(char *config_json) {
|
|||
result_obj("status", "ok");
|
||||
result_obj("codeBoc", td::base64_encode(boc));
|
||||
result_obj("fiftCode", escape_json(outs.str()));
|
||||
result_obj("codeHashHex", code_cell->get_hash().to_hex());
|
||||
result_obj.leave();
|
||||
|
||||
outs.clear();
|
||||
|
|
473
crypto/keccak/keccak.cpp
Normal file
473
crypto/keccak/keccak.cpp
Normal file
|
@ -0,0 +1,473 @@
|
|||
/*
|
||||
* An implementation of the SHA3 (Keccak) hash function family.
|
||||
*
|
||||
* Algorithm specifications: http://keccak.noekeon.org/
|
||||
* NIST Announcement:
|
||||
* http://csrc.nist.gov/groups/ST/hash/sha-3/winner_sha-3.html
|
||||
*
|
||||
* Written in 2013 by Fabrizio Tarizzo <fabrizio@fabriziotarizzo.org>
|
||||
*
|
||||
* ===================================================================
|
||||
* The contents of this file are dedicated to the public domain. To
|
||||
* the extent that dedication to the public domain is not available,
|
||||
* everyone is granted a worldwide, perpetual, royalty-free,
|
||||
* non-exclusive license to exercise all rights associated with the
|
||||
* contents of this file for any purpose whatsoever.
|
||||
* No rights are reserved.
|
||||
*
|
||||
* 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.
|
||||
* ===================================================================
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define KECCAK_F1600_STATE 200
|
||||
#define MIN(x, y) ((x) < (y) ? (x) : (y))
|
||||
#define MAX(x, y) ((x) < (y) ? (x) : (y))
|
||||
|
||||
/** Standard errors common to all ciphers **/
|
||||
#define ERR_NULL 1
|
||||
#define ERR_MEMORY 2
|
||||
#define ERR_NOT_ENOUGH_DATA 3
|
||||
#define ERR_ENCRYPT 4
|
||||
#define ERR_DECRYPT 5
|
||||
#define ERR_KEY_SIZE 6
|
||||
#define ERR_NONCE_SIZE 7
|
||||
#define ERR_NR_ROUNDS 8
|
||||
#define ERR_DIGEST_SIZE 9
|
||||
#define ERR_MAX_DATA 10
|
||||
#define ERR_MAX_OFFSET 11
|
||||
#define ERR_BLOCK_SIZE 12
|
||||
#define ERR_TAG_SIZE 13
|
||||
#define ERR_VALUE 14
|
||||
#define ERR_EC_POINT 15
|
||||
#define ERR_EC_CURVE 16
|
||||
#define ERR_MODULUS 17
|
||||
#define ERR_UNKNOWN 32
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint64_t state[25];
|
||||
|
||||
/* The buffer is as long as the state,
|
||||
* but only 'rate' bytes will be used.
|
||||
*/
|
||||
uint8_t buf[KECCAK_F1600_STATE];
|
||||
|
||||
/* When absorbing, this is the number of bytes in buf that
|
||||
* are coming from the message and outstanding.
|
||||
* When squeezing, this is the remaining number of bytes
|
||||
* that can be used as digest.
|
||||
*/
|
||||
unsigned valid_bytes;
|
||||
|
||||
/* All values in bytes */
|
||||
unsigned capacity;
|
||||
unsigned rate;
|
||||
|
||||
uint8_t squeezing;
|
||||
uint8_t rounds;
|
||||
} keccak_state;
|
||||
|
||||
#undef ROL64
|
||||
#define ROL64(x,y) ((((x) << (y)) | (x) >> (64-(y))) & 0xFFFFFFFFFFFFFFFFULL)
|
||||
|
||||
static void keccak_function (uint64_t *state, unsigned rounds);
|
||||
|
||||
int keccak_reset(keccak_state *state)
|
||||
{
|
||||
if (NULL == state)
|
||||
return ERR_NULL;
|
||||
|
||||
memset(state->state, 0, sizeof(state->state));
|
||||
memset(state->buf, 0, sizeof(state->buf));
|
||||
state->valid_bytes = 0;
|
||||
state->squeezing = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void keccak_absorb_internal (keccak_state *self)
|
||||
{
|
||||
unsigned i,j;
|
||||
uint64_t d;
|
||||
|
||||
for (i=j=0; j < self->rate; ++i, j += 8) {
|
||||
d = *(const uint64_t*)(self->buf + j);
|
||||
self->state[i] ^= d;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
keccak_squeeze_internal (keccak_state *self)
|
||||
{
|
||||
unsigned i, j;
|
||||
|
||||
for (i=j=0; j < self->rate; ++i, j += 8) {
|
||||
*(uint64_t*)(self->buf+j) = self->state[i];
|
||||
}
|
||||
}
|
||||
|
||||
int keccak_init (keccak_state **state,
|
||||
size_t capacity_bytes,
|
||||
uint8_t rounds)
|
||||
{
|
||||
keccak_state *ks;
|
||||
|
||||
if (NULL == state) {
|
||||
return ERR_NULL;
|
||||
}
|
||||
|
||||
*state = ks = (keccak_state*) calloc(1, sizeof(keccak_state));
|
||||
if (NULL == ks)
|
||||
return ERR_MEMORY;
|
||||
|
||||
if (capacity_bytes >= KECCAK_F1600_STATE)
|
||||
return ERR_DIGEST_SIZE;
|
||||
|
||||
if ((rounds != 12) && (rounds != 24))
|
||||
return ERR_NR_ROUNDS;
|
||||
|
||||
ks->capacity = (unsigned)capacity_bytes;
|
||||
|
||||
ks->rate = KECCAK_F1600_STATE - ks->capacity;
|
||||
|
||||
ks->squeezing = 0;
|
||||
ks->rounds = rounds;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int keccak_destroy(keccak_state *state)
|
||||
{
|
||||
free(state);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int keccak_absorb (keccak_state *self,
|
||||
const uint8_t *in,
|
||||
size_t length)
|
||||
{
|
||||
if (NULL==self || NULL==in)
|
||||
return ERR_NULL;
|
||||
|
||||
if (self->squeezing != 0)
|
||||
return ERR_UNKNOWN;
|
||||
|
||||
while (length > 0) {
|
||||
unsigned tc;
|
||||
unsigned left;
|
||||
|
||||
left = self->rate - self->valid_bytes;
|
||||
tc = (unsigned) MIN(length, left);
|
||||
memcpy(self->buf + self->valid_bytes, in, tc);
|
||||
|
||||
self->valid_bytes += tc;
|
||||
in += tc;
|
||||
length -= tc;
|
||||
|
||||
if (self->valid_bytes == self->rate) {
|
||||
keccak_absorb_internal (self);
|
||||
keccak_function(self->state, self->rounds);
|
||||
self->valid_bytes = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void keccak_finish (keccak_state *self, uint8_t padding)
|
||||
{
|
||||
assert(self->squeezing == 0);
|
||||
assert(self->valid_bytes < self->rate);
|
||||
|
||||
/* Padding */
|
||||
memset(self->buf + self->valid_bytes, 0, self->rate - self->valid_bytes);
|
||||
self->buf[self->valid_bytes] = padding;
|
||||
self->buf[self->rate-1] |= 0x80;
|
||||
|
||||
/* Final absorb */
|
||||
keccak_absorb_internal (self);
|
||||
keccak_function (self->state, self->rounds);
|
||||
|
||||
/* First squeeze */
|
||||
self->squeezing = 1;
|
||||
keccak_squeeze_internal (self);
|
||||
self->valid_bytes = self->rate;
|
||||
}
|
||||
|
||||
int keccak_squeeze (keccak_state *self, uint8_t *out, size_t length, uint8_t padding)
|
||||
{
|
||||
if ((NULL == self) || (NULL == out))
|
||||
return ERR_NULL;
|
||||
|
||||
if (self->squeezing == 0) {
|
||||
keccak_finish (self, padding);
|
||||
}
|
||||
|
||||
assert(self->squeezing == 1);
|
||||
assert(self->valid_bytes > 0);
|
||||
assert(self->valid_bytes <= self->rate);
|
||||
|
||||
while (length > 0) {
|
||||
unsigned tc;
|
||||
|
||||
tc = (unsigned)MIN(self->valid_bytes, length);
|
||||
memcpy(out, self->buf + (self->rate - self->valid_bytes), tc);
|
||||
|
||||
self->valid_bytes -= tc;
|
||||
out += tc;
|
||||
length -= tc;
|
||||
|
||||
if (self->valid_bytes == 0) {
|
||||
keccak_function (self->state, self->rounds);
|
||||
keccak_squeeze_internal (self);
|
||||
self->valid_bytes = self->rate;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int keccak_digest(keccak_state *state, uint8_t *digest, size_t len, uint8_t padding)
|
||||
{
|
||||
keccak_state tmp;
|
||||
|
||||
if ((NULL==state) || (NULL==digest))
|
||||
return ERR_NULL;
|
||||
|
||||
if (2*len != state->capacity)
|
||||
return ERR_UNKNOWN;
|
||||
|
||||
tmp = *state;
|
||||
return keccak_squeeze(&tmp, digest, len, padding);
|
||||
}
|
||||
|
||||
int keccak_copy(const keccak_state *src, keccak_state *dst)
|
||||
{
|
||||
if (NULL == src || NULL == dst) {
|
||||
return ERR_NULL;
|
||||
}
|
||||
|
||||
*dst = *src;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Keccak core function */
|
||||
|
||||
#define KECCAK_ROUNDS 24
|
||||
|
||||
#define ROT_01 36
|
||||
#define ROT_02 3
|
||||
#define ROT_03 41
|
||||
#define ROT_04 18
|
||||
#define ROT_05 1
|
||||
#define ROT_06 44
|
||||
#define ROT_07 10
|
||||
#define ROT_08 45
|
||||
#define ROT_09 2
|
||||
#define ROT_10 62
|
||||
#define ROT_11 6
|
||||
#define ROT_12 43
|
||||
#define ROT_13 15
|
||||
#define ROT_14 61
|
||||
#define ROT_15 28
|
||||
#define ROT_16 55
|
||||
#define ROT_17 25
|
||||
#define ROT_18 21
|
||||
#define ROT_19 56
|
||||
#define ROT_20 27
|
||||
#define ROT_21 20
|
||||
#define ROT_22 39
|
||||
#define ROT_23 8
|
||||
#define ROT_24 14
|
||||
|
||||
static const uint64_t roundconstants[KECCAK_ROUNDS] = {
|
||||
0x0000000000000001ULL,
|
||||
0x0000000000008082ULL,
|
||||
0x800000000000808aULL,
|
||||
0x8000000080008000ULL,
|
||||
0x000000000000808bULL,
|
||||
0x0000000080000001ULL,
|
||||
0x8000000080008081ULL,
|
||||
0x8000000000008009ULL,
|
||||
0x000000000000008aULL,
|
||||
0x0000000000000088ULL,
|
||||
0x0000000080008009ULL,
|
||||
0x000000008000000aULL,
|
||||
0x000000008000808bULL,
|
||||
0x800000000000008bULL,
|
||||
0x8000000000008089ULL,
|
||||
0x8000000000008003ULL,
|
||||
0x8000000000008002ULL,
|
||||
0x8000000000000080ULL,
|
||||
0x000000000000800aULL,
|
||||
0x800000008000000aULL,
|
||||
0x8000000080008081ULL,
|
||||
0x8000000000008080ULL,
|
||||
0x0000000080000001ULL,
|
||||
0x8000000080008008ULL
|
||||
};
|
||||
|
||||
static void keccak_function (uint64_t *state, unsigned rounds)
|
||||
{
|
||||
unsigned i;
|
||||
unsigned start_round;
|
||||
|
||||
/* Temporary variables to avoid indexing overhead */
|
||||
uint64_t a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12;
|
||||
uint64_t a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24;
|
||||
|
||||
uint64_t b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12;
|
||||
uint64_t b13, b14, b15, b16, b17, b18, b19, b20, b21, b22, b23, b24;
|
||||
|
||||
uint64_t c0, c1, c2, c3, c4, d;
|
||||
|
||||
a0 = state[0];
|
||||
a1 = state[1];
|
||||
a2 = state[2];
|
||||
a3 = state[3];
|
||||
a4 = state[4];
|
||||
a5 = state[5];
|
||||
a6 = state[6];
|
||||
a7 = state[7];
|
||||
a8 = state[8];
|
||||
a9 = state[9];
|
||||
a10 = state[10];
|
||||
a11 = state[11];
|
||||
a12 = state[12];
|
||||
a13 = state[13];
|
||||
a14 = state[14];
|
||||
a15 = state[15];
|
||||
a16 = state[16];
|
||||
a17 = state[17];
|
||||
a18 = state[18];
|
||||
a19 = state[19];
|
||||
a20 = state[20];
|
||||
a21 = state[21];
|
||||
a22 = state[22];
|
||||
a23 = state[23];
|
||||
a24 = state[24];
|
||||
|
||||
if (rounds == 24)
|
||||
start_round = 0;
|
||||
else /* rounds == 12 */
|
||||
start_round = 12;
|
||||
|
||||
for (i = start_round; i < KECCAK_ROUNDS; ++i) {
|
||||
/*
|
||||
Uses temporary variables and loop unrolling to
|
||||
avoid array indexing and inner loops overhead
|
||||
*/
|
||||
|
||||
/* Prepare column parity for Theta step */
|
||||
c0 = a0 ^ a5 ^ a10 ^ a15 ^ a20;
|
||||
c1 = a1 ^ a6 ^ a11 ^ a16 ^ a21;
|
||||
c2 = a2 ^ a7 ^ a12 ^ a17 ^ a22;
|
||||
c3 = a3 ^ a8 ^ a13 ^ a18 ^ a23;
|
||||
c4 = a4 ^ a9 ^ a14 ^ a19 ^ a24;
|
||||
|
||||
/* Theta + Rho + Pi steps */
|
||||
d = c4 ^ ROL64(c1, 1);
|
||||
b0 = d ^ a0;
|
||||
b16 = ROL64(d ^ a5, ROT_01);
|
||||
b7 = ROL64(d ^ a10, ROT_02);
|
||||
b23 = ROL64(d ^ a15, ROT_03);
|
||||
b14 = ROL64(d ^ a20, ROT_04);
|
||||
|
||||
d = c0 ^ ROL64(c2, 1);
|
||||
b10 = ROL64(d ^ a1, ROT_05);
|
||||
b1 = ROL64(d ^ a6, ROT_06);
|
||||
b17 = ROL64(d ^ a11, ROT_07);
|
||||
b8 = ROL64(d ^ a16, ROT_08);
|
||||
b24 = ROL64(d ^ a21, ROT_09);
|
||||
|
||||
d = c1 ^ ROL64(c3, 1);
|
||||
b20 = ROL64(d ^ a2, ROT_10);
|
||||
b11 = ROL64(d ^ a7, ROT_11);
|
||||
b2 = ROL64(d ^ a12, ROT_12);
|
||||
b18 = ROL64(d ^ a17, ROT_13);
|
||||
b9 = ROL64(d ^ a22, ROT_14);
|
||||
|
||||
d = c2 ^ ROL64(c4, 1);
|
||||
b5 = ROL64(d ^ a3, ROT_15);
|
||||
b21 = ROL64(d ^ a8, ROT_16);
|
||||
b12 = ROL64(d ^ a13, ROT_17);
|
||||
b3 = ROL64(d ^ a18, ROT_18);
|
||||
b19 = ROL64(d ^ a23, ROT_19);
|
||||
|
||||
d = c3 ^ ROL64(c0, 1);
|
||||
b15 = ROL64(d ^ a4, ROT_20);
|
||||
b6 = ROL64(d ^ a9, ROT_21);
|
||||
b22 = ROL64(d ^ a14, ROT_22);
|
||||
b13 = ROL64(d ^ a19, ROT_23);
|
||||
b4 = ROL64(d ^ a24, ROT_24);
|
||||
|
||||
/* Chi + Iota steps */
|
||||
a0 = b0 ^ (~b1 & b2) ^ roundconstants[i];
|
||||
a1 = b1 ^ (~b2 & b3);
|
||||
a2 = b2 ^ (~b3 & b4);
|
||||
a3 = b3 ^ (~b4 & b0);
|
||||
a4 = b4 ^ (~b0 & b1);
|
||||
|
||||
a5 = b5 ^ (~b6 & b7);
|
||||
a6 = b6 ^ (~b7 & b8);
|
||||
a7 = b7 ^ (~b8 & b9);
|
||||
a8 = b8 ^ (~b9 & b5);
|
||||
a9 = b9 ^ (~b5 & b6);
|
||||
|
||||
a10 = b10 ^ (~b11 & b12);
|
||||
a11 = b11 ^ (~b12 & b13);
|
||||
a12 = b12 ^ (~b13 & b14);
|
||||
a13 = b13 ^ (~b14 & b10);
|
||||
a14 = b14 ^ (~b10 & b11);
|
||||
|
||||
a15 = b15 ^ (~b16 & b17);
|
||||
a16 = b16 ^ (~b17 & b18);
|
||||
a17 = b17 ^ (~b18 & b19);
|
||||
a18 = b18 ^ (~b19 & b15);
|
||||
a19 = b19 ^ (~b15 & b16);
|
||||
|
||||
a20 = b20 ^ (~b21 & b22);
|
||||
a21 = b21 ^ (~b22 & b23);
|
||||
a22 = b22 ^ (~b23 & b24);
|
||||
a23 = b23 ^ (~b24 & b20);
|
||||
a24 = b24 ^ (~b20 & b21);
|
||||
}
|
||||
|
||||
state[0] = a0;
|
||||
state[1] = a1;
|
||||
state[2] = a2;
|
||||
state[3] = a3;
|
||||
state[4] = a4;
|
||||
state[5] = a5;
|
||||
state[6] = a6;
|
||||
state[7] = a7;
|
||||
state[8] = a8;
|
||||
state[9] = a9;
|
||||
state[10] = a10;
|
||||
state[11] = a11;
|
||||
state[12] = a12;
|
||||
state[13] = a13;
|
||||
state[14] = a14;
|
||||
state[15] = a15;
|
||||
state[16] = a16;
|
||||
state[17] = a17;
|
||||
state[18] = a18;
|
||||
state[19] = a19;
|
||||
state[20] = a20;
|
||||
state[21] = a21;
|
||||
state[22] = a22;
|
||||
state[23] = a23;
|
||||
state[24] = a24;
|
||||
}
|
41
crypto/keccak/keccak.h
Normal file
41
crypto/keccak/keccak.h
Normal file
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* An implementation of the SHA3 (Keccak) hash function family.
|
||||
*
|
||||
* Algorithm specifications: http://keccak.noekeon.org/
|
||||
* NIST Announcement:
|
||||
* http://csrc.nist.gov/groups/ST/hash/sha-3/winner_sha-3.html
|
||||
*
|
||||
* Written in 2013 by Fabrizio Tarizzo <fabrizio@fabriziotarizzo.org>
|
||||
*
|
||||
* ===================================================================
|
||||
* The contents of this file are dedicated to the public domain. To
|
||||
* the extent that dedication to the public domain is not available,
|
||||
* everyone is granted a worldwide, perpetual, royalty-free,
|
||||
* non-exclusive license to exercise all rights associated with the
|
||||
* contents of this file for any purpose whatsoever.
|
||||
* No rights are reserved.
|
||||
*
|
||||
* 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.
|
||||
* ===================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <cstring>
|
||||
#include <cstdint>
|
||||
|
||||
struct keccak_state;
|
||||
|
||||
int keccak_reset(keccak_state *state);
|
||||
int keccak_init(keccak_state **state, size_t capacity_bytes, uint8_t rounds);
|
||||
int keccak_destroy(keccak_state *state);
|
||||
int keccak_absorb(keccak_state *self, const uint8_t *in, size_t length);
|
||||
int keccak_squeeze(keccak_state *self, uint8_t *out, size_t length, uint8_t padding);
|
||||
int keccak_digest(keccak_state *state, uint8_t *digest, size_t len, uint8_t padding);
|
||||
int keccak_copy(const keccak_state *src, keccak_state *dst);
|
|
@ -32,8 +32,8 @@ int scope_level;
|
|||
|
||||
SymTable<100003> symbols;
|
||||
|
||||
SymDef* sym_def[symbols.hprime];
|
||||
SymDef* global_sym_def[symbols.hprime];
|
||||
SymDef* sym_def[symbols.hprime + 1];
|
||||
SymDef* global_sym_def[symbols.hprime + 1];
|
||||
std::vector<std::pair<int, SymDef>> symbol_stack;
|
||||
std::vector<src::SrcLocation> scope_opened_at;
|
||||
|
||||
|
|
|
@ -161,8 +161,8 @@ struct SymDef {
|
|||
}
|
||||
};
|
||||
|
||||
extern SymDef* sym_def[symbols.hprime];
|
||||
extern SymDef* global_sym_def[symbols.hprime];
|
||||
extern SymDef* sym_def[symbols.hprime + 1];
|
||||
extern SymDef* global_sym_def[symbols.hprime + 1];
|
||||
extern std::vector<std::pair<int, SymDef>> symbol_stack;
|
||||
extern std::vector<src::SrcLocation> scope_opened_at;
|
||||
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
;; Simple configuration smart contract
|
||||
;; Currently deployed config-contract in mainnet can be found
|
||||
;; on https://verifier.ton.org/Ef9VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVbxn
|
||||
|
||||
() set_conf_param(int index, cell value) impure {
|
||||
var cs = get_data().begin_parse();
|
||||
|
@ -397,6 +399,7 @@ int register_voting_proposal(slice cs, int msg_value) impure inline_ref {
|
|||
hash = -0xcd506e6c; ;; cannot set mandatory parameter to null
|
||||
}
|
||||
}
|
||||
;; Note, in config contract currently deployed in mainnet, this limit is 256
|
||||
if (param_val.cell_depth() >= 128) {
|
||||
hash = -0xc2616456; ;; bad value
|
||||
}
|
||||
|
@ -601,7 +604,7 @@ _ unpack_proposal(slice pstatus) inline_ref {
|
|||
voters_list = cons(voter_id, voters_list);
|
||||
}
|
||||
} until (~ f);
|
||||
;; Note there is a bug in config contract currently deployed in testnet2:
|
||||
;; Note there is a bug in config contract currently deployed in mainnet:
|
||||
;; wins and losses are messed up
|
||||
var (rounds_remaining, wins, losses) = (rest~load_uint(8), rest~load_uint(8), rest~load_uint(8));
|
||||
rest.end_parse();
|
||||
|
|
|
@ -120,7 +120,7 @@ td::Ref<vm::Stack> prepare_vm_stack(td::RefInt256 amount, td::Ref<vm::CellSlice>
|
|||
return stack_ref;
|
||||
}
|
||||
|
||||
td::Ref<vm::Tuple> prepare_vm_c7(SmartContract::Args args) {
|
||||
td::Ref<vm::Tuple> prepare_vm_c7(SmartContract::Args args, td::Ref<vm::Cell> code) {
|
||||
td::BitArray<256> rand_seed;
|
||||
if (args.rand_seed) {
|
||||
rand_seed = args.rand_seed.unwrap();
|
||||
|
@ -139,10 +139,7 @@ td::Ref<vm::Tuple> prepare_vm_c7(SmartContract::Args args) {
|
|||
if (args.address) {
|
||||
td::BigInt256 dest_addr;
|
||||
dest_addr.import_bits((*args.address).addr.as_bitslice());
|
||||
cb.store_ones(1)
|
||||
.store_zeroes(2)
|
||||
.store_long((*args.address).workchain, 8)
|
||||
.store_int256(dest_addr, 256);
|
||||
cb.store_ones(1).store_zeroes(2).store_long((*args.address).workchain, 8).store_int256(dest_addr, 256);
|
||||
}
|
||||
auto address = cb.finalize();
|
||||
auto config = td::Ref<vm::Cell>();
|
||||
|
@ -151,26 +148,40 @@ td::Ref<vm::Tuple> prepare_vm_c7(SmartContract::Args args) {
|
|||
config = (*args.config)->get_root_cell();
|
||||
}
|
||||
|
||||
auto tuple = vm::make_tuple_ref(
|
||||
td::make_refint(0x076ef1ea), // [ magic:0x076ef1ea
|
||||
td::make_refint(0), // actions:Integer
|
||||
td::make_refint(0), // msgs_sent:Integer
|
||||
td::make_refint(now), // unixtime:Integer
|
||||
td::make_refint(0), //TODO: // block_lt:Integer
|
||||
td::make_refint(0), //TODO: // trans_lt:Integer
|
||||
std::move(rand_seed_int), // rand_seed:Integer
|
||||
block::CurrencyCollection(args.balance).as_vm_tuple(), // balance_remaining:[Integer (Maybe Cell)]
|
||||
vm::load_cell_slice_ref(address), // myself:MsgAddressInt
|
||||
vm::StackEntry::maybe(config) //vm::StackEntry::maybe(td::Ref<vm::Cell>())
|
||||
); // global_config:(Maybe Cell) ] = SmartContractInfo;
|
||||
std::vector<vm::StackEntry> tuple = {
|
||||
td::make_refint(0x076ef1ea), // [ magic:0x076ef1ea
|
||||
td::make_refint(0), // actions:Integer
|
||||
td::make_refint(0), // msgs_sent:Integer
|
||||
td::make_refint(now), // unixtime:Integer
|
||||
td::make_refint(0), //TODO: // block_lt:Integer
|
||||
td::make_refint(0), //TODO: // trans_lt:Integer
|
||||
std::move(rand_seed_int), // rand_seed:Integer
|
||||
block::CurrencyCollection(args.balance).as_vm_tuple(), // balance_remaining:[Integer (Maybe Cell)]
|
||||
vm::load_cell_slice_ref(address), // myself:MsgAddressInt
|
||||
vm::StackEntry::maybe(config) //vm::StackEntry::maybe(td::Ref<vm::Cell>())
|
||||
};
|
||||
if (args.config && args.config.value()->get_global_version() >= 4) {
|
||||
tuple.push_back(code.not_null() ? code : vm::StackEntry{}); // code:Cell
|
||||
tuple.push_back(block::CurrencyCollection::zero().as_vm_tuple()); // in_msg_value:[Integer (Maybe Cell)]
|
||||
tuple.push_back(td::zero_refint()); // storage_fees:Integer
|
||||
|
||||
// See crypto/block/mc-config.cpp#2115 (get_prev_blocks_info)
|
||||
// [ wc:Integer shard:Integer seqno:Integer root_hash:Integer file_hash:Integer] = BlockId;
|
||||
// [ last_mc_blocks:[BlockId...]
|
||||
// prev_key_block:BlockId ] : PrevBlocksInfo
|
||||
tuple.push_back(args.prev_blocks_info ? args.prev_blocks_info.value() : vm::StackEntry{}); // prev_block_info
|
||||
}
|
||||
auto tuple_ref = td::make_cnt_ref<std::vector<vm::StackEntry>>(std::move(tuple));
|
||||
//LOG(DEBUG) << "SmartContractInfo initialized with " << vm::StackEntry(tuple).to_string();
|
||||
return vm::make_tuple_ref(std::move(tuple));
|
||||
return vm::make_tuple_ref(std::move(tuple_ref));
|
||||
}
|
||||
|
||||
SmartContract::Answer run_smartcont(SmartContract::State state, td::Ref<vm::Stack> stack, td::Ref<vm::Tuple> c7,
|
||||
vm::GasLimits gas, bool ignore_chksig, td::Ref<vm::Cell> libraries, int vm_log_verbosity) {
|
||||
vm::GasLimits gas, bool ignore_chksig, td::Ref<vm::Cell> libraries,
|
||||
int vm_log_verbosity, bool debug_enabled,
|
||||
std::shared_ptr<const block::Config> config) {
|
||||
auto gas_credit = gas.gas_credit;
|
||||
vm::init_op_cp0();
|
||||
vm::init_op_cp0(debug_enabled);
|
||||
vm::DictionaryBase::get_empty_dictionary();
|
||||
|
||||
class Logger : public td::LogInterface {
|
||||
|
@ -185,7 +196,13 @@ SmartContract::Answer run_smartcont(SmartContract::State state, td::Ref<vm::Stac
|
|||
if (vm_log_verbosity > 1) {
|
||||
log.log_mask |= vm::VmLog::ExecLocation;
|
||||
if (vm_log_verbosity > 2) {
|
||||
log.log_mask |= vm::VmLog::DumpStack | vm::VmLog::GasRemaining;
|
||||
log.log_mask |= vm::VmLog::GasRemaining;
|
||||
if (vm_log_verbosity > 3) {
|
||||
log.log_mask |= vm::VmLog::DumpStack;
|
||||
if (vm_log_verbosity > 4) {
|
||||
log.log_mask |= vm::VmLog::DumpStackVerbose;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -201,6 +218,13 @@ SmartContract::Answer run_smartcont(SmartContract::State state, td::Ref<vm::Stac
|
|||
if (!libraries.is_null()) {
|
||||
vm.register_library_collection(libraries);
|
||||
}
|
||||
if (config) {
|
||||
vm.set_global_version(config->get_global_version());
|
||||
auto r_limits = config->get_size_limits_config();
|
||||
if (r_limits.is_ok()) {
|
||||
vm.set_max_data_depth(r_limits.ok().max_vm_data_depth);
|
||||
}
|
||||
}
|
||||
try {
|
||||
res.code = ~vm.run();
|
||||
} catch (...) {
|
||||
|
@ -276,7 +300,7 @@ td::Ref<vm::Cell> SmartContract::get_init_state() const {
|
|||
|
||||
SmartContract::Answer SmartContract::run_method(Args args) {
|
||||
if (!args.c7) {
|
||||
args.c7 = prepare_vm_c7(args);
|
||||
args.c7 = prepare_vm_c7(args, state_.code);
|
||||
}
|
||||
if (!args.limits) {
|
||||
bool is_internal = args.get_method_id().ok() == 0;
|
||||
|
@ -289,14 +313,15 @@ SmartContract::Answer SmartContract::run_method(Args args) {
|
|||
args.stack.value().write().push_smallint(args.method_id.unwrap());
|
||||
auto res =
|
||||
run_smartcont(get_state(), args.stack.unwrap(), args.c7.unwrap(), args.limits.unwrap(), args.ignore_chksig,
|
||||
args.libraries ? args.libraries.unwrap().get_root_cell() : td::Ref<vm::Cell>{}, args.vm_log_verbosity_level);
|
||||
args.libraries ? args.libraries.unwrap().get_root_cell() : td::Ref<vm::Cell>{},
|
||||
args.vm_log_verbosity_level, args.debug_enabled, args.config ? args.config.value() : nullptr);
|
||||
state_ = res.new_state;
|
||||
return res;
|
||||
}
|
||||
|
||||
SmartContract::Answer SmartContract::run_get_method(Args args) const {
|
||||
if (!args.c7) {
|
||||
args.c7 = prepare_vm_c7(args);
|
||||
args.c7 = prepare_vm_c7(args, state_.code);
|
||||
}
|
||||
if (!args.limits) {
|
||||
args.limits = vm::GasLimits{1000000, 1000000};
|
||||
|
@ -307,7 +332,8 @@ SmartContract::Answer SmartContract::run_get_method(Args args) const {
|
|||
CHECK(args.method_id);
|
||||
args.stack.value().write().push_smallint(args.method_id.unwrap());
|
||||
return run_smartcont(get_state(), args.stack.unwrap(), args.c7.unwrap(), args.limits.unwrap(), args.ignore_chksig,
|
||||
args.libraries ? args.libraries.unwrap().get_root_cell() : td::Ref<vm::Cell>{}, args.vm_log_verbosity_level);
|
||||
args.libraries ? args.libraries.unwrap().get_root_cell() : td::Ref<vm::Cell>{},
|
||||
args.vm_log_verbosity_level, args.debug_enabled, args.config ? args.config.value() : nullptr);
|
||||
}
|
||||
|
||||
SmartContract::Answer SmartContract::run_get_method(td::Slice method, Args args) const {
|
||||
|
|
|
@ -65,10 +65,12 @@ class SmartContract : public td::CntObject {
|
|||
td::uint64 amount{0};
|
||||
td::uint64 balance{0};
|
||||
int vm_log_verbosity_level{0};
|
||||
bool debug_enabled{false};
|
||||
|
||||
td::optional<block::StdAddress> address;
|
||||
td::optional<std::shared_ptr<const block::Config>> config;
|
||||
td::optional<vm::Dictionary> libraries;
|
||||
td::optional<td::Ref<vm::Tuple>> prev_blocks_info;
|
||||
|
||||
Args() {
|
||||
}
|
||||
|
@ -123,7 +125,7 @@ class SmartContract : public td::CntObject {
|
|||
this->address = address;
|
||||
return std::move(*this);
|
||||
}
|
||||
Args&& set_config(std::shared_ptr<const block::Config>& config) {
|
||||
Args&& set_config(const std::shared_ptr<const block::Config>& config) {
|
||||
this->config = config;
|
||||
return std::move(*this);
|
||||
}
|
||||
|
@ -131,10 +133,22 @@ class SmartContract : public td::CntObject {
|
|||
this->libraries = libraries;
|
||||
return std::move(*this);
|
||||
}
|
||||
Args&& set_prev_blocks_info(td::Ref<vm::Tuple> tuple) {
|
||||
if (tuple.is_null()) {
|
||||
this->prev_blocks_info = {};
|
||||
} else {
|
||||
this->prev_blocks_info = std::move(tuple);
|
||||
}
|
||||
return std::move(*this);
|
||||
}
|
||||
Args&& set_vm_verbosity_level(int vm_log_verbosity_level) {
|
||||
this->vm_log_verbosity_level = vm_log_verbosity_level;
|
||||
return std::move(*this);
|
||||
}
|
||||
Args&& set_debug_enabled(bool debug_enabled) {
|
||||
this->debug_enabled = debug_enabled;
|
||||
return std::move(*this);
|
||||
}
|
||||
|
||||
td::Result<td::int32> get_method_id() const {
|
||||
if (!method_id) {
|
||||
|
|
|
@ -33,9 +33,14 @@ std::string load_test(std::string name) {
|
|||
return td::read_file_str(current_dir() + "fift/" + name).move_as_ok();
|
||||
}
|
||||
|
||||
td::Status run_fift(std::string name, bool preload_fift = true) {
|
||||
TRY_RESULT(res, fift::mem_run_fift(load_test(name)));
|
||||
REGRESSION_VERIFY(res.output);
|
||||
td::Status run_fift(std::string name, bool expect_error = false, bool preload_fift = true) {
|
||||
auto res = fift::mem_run_fift(load_test(name));
|
||||
if (expect_error) {
|
||||
res.ensure_error();
|
||||
return td::Status::OK();
|
||||
}
|
||||
res.ensure();
|
||||
REGRESSION_VERIFY(res.ok().output);
|
||||
return td::Status::OK();
|
||||
}
|
||||
|
||||
|
@ -79,7 +84,7 @@ TEST(Fift, testvmprog) {
|
|||
run_fift("testvmprog.fif");
|
||||
}
|
||||
TEST(Fift, bug) {
|
||||
run_fift("bug.fif");
|
||||
run_fift("bug.fif", true);
|
||||
}
|
||||
TEST(Fift, contfrac) {
|
||||
run_fift("contfrac.fif");
|
||||
|
@ -130,3 +135,31 @@ TEST(Fift, test_namespaces) {
|
|||
TEST(Fift, test_asm_nested_program) {
|
||||
run_fift("asm-nested-program.fif");
|
||||
}
|
||||
|
||||
TEST(Fift, test_adddiv) {
|
||||
run_fift("adddiv.fif");
|
||||
}
|
||||
|
||||
TEST(Fift, test_tvm_runvm) {
|
||||
run_fift("tvm_runvm.fif");
|
||||
}
|
||||
|
||||
TEST(Fift, test_hash_ext) {
|
||||
run_fift("hash_ext.fif");
|
||||
}
|
||||
|
||||
TEST(Fift, test_deep_stack_ops) {
|
||||
run_fift("deep_stack_ops.fif");
|
||||
}
|
||||
|
||||
TEST(Fift, test_rist255) {
|
||||
run_fift("rist255.fif");
|
||||
}
|
||||
|
||||
TEST(Fift, test_bls) {
|
||||
run_fift("bls.fif");
|
||||
}
|
||||
|
||||
TEST(Fift, test_bls_ops) {
|
||||
run_fift("bls_ops.fif");
|
||||
}
|
||||
|
|
144
crypto/test/fift/adddiv.fif
Normal file
144
crypto/test/fift/adddiv.fif
Normal file
|
@ -0,0 +1,144 @@
|
|||
{
|
||||
=: ans-r =: ans-q =: mode
|
||||
=: z =: w =: y =: x
|
||||
."MULADDDIVMOD " @' x . @' y . @' w . @' z . @' mode . ."= " @' ans-q . @' ans-r . cr
|
||||
@' x @' y @' w @' z
|
||||
<b x{A9} s, b{100000} s, @' mode 2 u, b> <s 0 runvmx
|
||||
.s
|
||||
abort"Exitcode != 0"
|
||||
@' ans-r <> abort"Incorrect r"
|
||||
@' ans-q <> abort"Incorrect q"
|
||||
} : test-muladddivmod
|
||||
|
||||
{
|
||||
=: ans-r =: ans-q =: mode
|
||||
=: y =: w =: x
|
||||
."ADDDIVMOD " @' x . @' w . @' y . @' mode . ."= " @' ans-q . @' ans-r . cr
|
||||
@' x @' w @' y
|
||||
<b x{A9} s, b{000000} s, @' mode 2 u, b> <s 0 runvmx
|
||||
.s
|
||||
abort"Exitcode != 0"
|
||||
@' ans-r <> abort"Incorrect r"
|
||||
@' ans-q <> abort"Incorrect q"
|
||||
} : test-adddivmod
|
||||
|
||||
{
|
||||
=: ans-r =: ans-q =: mode
|
||||
=: z =: w =: y =: x
|
||||
."SHLADDDIVMOD " @' x . @' y . @' w . @' z . @' mode . ."= " @' ans-q . @' ans-r . cr
|
||||
@' x @' w @' z @' y
|
||||
<b x{A9} s, b{110000} s, @' mode 2 u, b> <s 0 runvmx
|
||||
.s
|
||||
abort"Exitcode != 0"
|
||||
@' ans-r <> abort"Incorrect r"
|
||||
@' ans-q <> abort"Incorrect q"
|
||||
} : test-shladddivmod
|
||||
|
||||
{
|
||||
=: ans-r =: ans-q =: mode
|
||||
=: z =: w =: y =: x
|
||||
."MULADDSHRMOD " @' x . @' y . @' w . @' z . @' mode . ."= " @' ans-q . @' ans-r . cr
|
||||
@' x @' y @' w @' z
|
||||
<b x{A9} s, b{101000} s, @' mode 2 u, b> <s 0 runvmx
|
||||
.s
|
||||
abort"Exitcode != 0"
|
||||
@' ans-r <> abort"Incorrect r"
|
||||
@' ans-q <> abort"Incorrect q"
|
||||
} : test-muladdshrmod
|
||||
|
||||
729 -212 552 0 0 517 test-adddivmod
|
||||
823 -139 -918 1 -1 -234 test-adddivmod
|
||||
-470 977 47 2 11 -10 test-adddivmod
|
||||
-5 -171 880 0 -1 704 test-adddivmod
|
||||
605 699 -379 1 -3 167 test-adddivmod
|
||||
982 -24 -267 2 -3 157 test-adddivmod
|
||||
194 826 859 0 1 161 test-adddivmod
|
||||
-553 33 -715 1 1 195 test-adddivmod
|
||||
-423 -714 547 2 -2 -43 test-adddivmod
|
||||
-806 266 637 0 -1 97 test-adddivmod
|
||||
-487 863 90 1 4 16 test-adddivmod
|
||||
444 659 232 2 5 -57 test-adddivmod
|
||||
847 -700 -365 -798 0 743 -351 test-muladddivmod
|
||||
494 -849 840 741 1 -565 99 test-muladddivmod
|
||||
400 -324 -34 146 2 -887 -132 test-muladddivmod
|
||||
-794 -276 -111 -353 0 -621 -180 test-muladddivmod
|
||||
251 311 869 -582 1 -136 -222 test-muladddivmod
|
||||
979 131 -24 -94 2 -1364 9 test-muladddivmod
|
||||
772 67 -467 -873 0 -59 -250 test-muladddivmod
|
||||
648 881 123 875 1 653 -364 test-muladddivmod
|
||||
-972 -809 473 720 2 1093 -139 test-muladddivmod
|
||||
-184 454 689 607 0 -137 312 test-muladddivmod
|
||||
368 280 -998 253 1 403 83 test-muladddivmod
|
||||
10 695 776 -318 2 -24 94 test-muladddivmod
|
||||
-501 5 441 782 0 -20 49 test-shladddivmod
|
||||
-872 3 878 162 1 -38 58 test-shladddivmod
|
||||
-546 3 645 981 2 -3 -780 test-shladddivmod
|
||||
-709 8 -83 -814 0 223 -65 test-shladddivmod
|
||||
-836 5 792 40 1 -649 0 test-shladddivmod
|
||||
910 7 -777 -383 2 -302 37 test-shladddivmod
|
||||
128 4 447 -745 0 -4 -485 test-shladddivmod
|
||||
121 5 668 888 1 5 100 test-shladddivmod
|
||||
106 3 973 637 2 3 -90 test-shladddivmod
|
||||
235 8 203 -411 0 -147 -54 test-shladddivmod
|
||||
-89 1 221 634 1 0 43 test-shladddivmod
|
||||
-212 5 178 -505 2 14 464 test-shladddivmod
|
||||
-406 -624 -613 2 0 63182 3 test-muladdshrmod
|
||||
-933 254 344 4 1 -14790 2 test-muladdshrmod
|
||||
-25 -859 -817 10 2 21 -846 test-muladdshrmod
|
||||
551 -734 795 2 0 -100910 1 test-muladdshrmod
|
||||
891 -921 725 1 1 -409943 0 test-muladdshrmod
|
||||
839 432 890 8 2 1420 -182 test-muladdshrmod
|
||||
399 -199 715 8 0 -308 162 test-muladdshrmod
|
||||
-436 68 662 3 1 -3623 -2 test-muladdshrmod
|
||||
739 -560 833 10 2 -403 -335 test-muladdshrmod
|
||||
207 690 945 6 0 2246 31 test-muladdshrmod
|
||||
187 -437 -78 7 1 -639 -5 test-muladdshrmod
|
||||
352 313 434 5 2 3457 -14 test-muladdshrmod
|
||||
25527586395537789869570741399081402682256851060036756777914400562788085574414 -25113160904436633803354228324572450480033217030010944063278205598870671865288 -2256017777568044393040721989849804550406163786581604155567013427587080747425 0 -1 -1841592286466888326824208915340852348182529756555791440930818463669667038299 test-adddivmod
|
||||
-32640246231411323106115073889225624429888478001529402430751550293198007894765 -37905632746827282747258884343685092209247121139851002852469398603088743361022 18753000550171967665955942657615296985943924316121913951069685581208211144632 1 -4 4466123222449264810449812397550471304640098123107250521057793428546093322741 test-adddivmod
|
||||
-95549375212741069607980980863332591640631650412403896229315709698307081396373 106240530356563762252550465652293166037855203388135409179201250774369290711413 63027891874179850739525204890840444316414650119364284762072976150516424705738 2 1 -52336736730357158094955720101879869919191097143632771812187435074454215390698 test-adddivmod
|
||||
51890526097631236478215460328003213527162540175278758108042092328342498521783 19183851048961131310064308531261717471288729454763519442604661504489273629484 37741726035775552009535280639145255965240492091225040562231509956705484553131 0 1 33332651110816815778744488220119675033210777538817236988415243876126287598136 test-adddivmod
|
||||
94071222795948162024492074951491627130123473883831806178173544936543536671735 -79181277644495598779765208777007083667700785694819686730856530041854640922750 101162201634522410327363362416275476419529310370084833033537453927088908146625 1 0 14889945151452563244726866174484543462422688189012119447317014894688895748985 test-adddivmod
|
||||
106849434942283600005926697698751951080751408318517871682753577855332568068854 -24045207490958235002714107597178464324559754040415520751984110097220649552695 74679027778960833059271215597415768445807741415021004423546293120031915119911 2 2 -66553828106596301115329841093258050135423828551939657916323118481951911723663 test-adddivmod
|
||||
-111083603622141356205460042548478779196244111142279948844255415507465496179136 75885719295648796212066209648237285368659643103523469813991536525258102456646 17487288729375302809394363552184340106515810164188804948959885094558256876961 0 -3 17263981861633348434789257756311526491962962453809935816615776301467376908393 test-adddivmod
|
||||
33525382765608498977714984645580937896464574678957613892455278004374765395791 -31203451453013366071092485074296252911543265223612191519873428434459391093162 8205361318951100784724737477089194897616580930791932431609075219761273143789 1 0 2321931312595132906622499571284684984921309455345422372581849569915374302629 test-adddivmod
|
||||
-75999952514508567055051892339604431790575024284443576993806836353012574839934 60096525995012658905135417908615298741753181036991250015243181812480959008245 25156241733999421479698222967097698882671132665627779117308277826680836574301 2 0 -15903426519495908149916474430989133048821843247452326978563654540531615831689 test-adddivmod
|
||||
-25810038415830521876908334245348683093953748145428320530928049623042163542952 13768870762468614895982523795103333718119339794093637483718383357794846902545 -23455630873759864343226329762160671724884569294252944494055101268304334927469 0 0 -12041167653361906980925810450245349375834408351334683047209666265247316640407 test-adddivmod
|
||||
65295636229319469142829758722387755590067603179313024098599396192036031682932 -14508864012052681942310481748034005897814022127985455644382059031122725256639 101258243423658080118042170583591218535452530372858366205652259477702813508611 1 1 -50471471206391292917522893609237468843198949321530797751434922316789507082318 test-adddivmod
|
||||
-9782778804673764937901196234199348720011483228792837975519798751976472498576 97723276666278794523978327321824380269179391405498018632142147588187660001006 -49342195947431856333198825767811410708861002865285674269877261690183407963360 2 -1 38598301914173173252878305319813620840306905311419506386745087146027779539070 test-adddivmod
|
||||
69314796062889467182180663903322273169679119368960545268948720263471816924632 93795938161576335898249305761803240528541213785951419531969609595386829401314 -110346049538998400484346689828188917177083570083289016450597131164930681126587 81149113889296322255375738811288869158926250513403232273765830197055460701260 0 80117280566567035416625919712742621817262121093084845174084285957987697395276 42036691045037437094861959671408390901385540330966807308270651575596167392101 test-muladddivmod
|
||||
-21971450167728355573106502799062118429867408154846289128369107182511643511483 45393555019045493054213057422940072801743824102220594624535868754509418047929 60641652588698494073802822494164156953515858330346793601084497228687965671868 65539824510463171124453489789915597533293103308691110446148835625201340366598 1 -15217651854984270515658273738098718647212153016787679186857576358263739302058 -29371413441460037863394670149687230435838766165616129771684695789862414338155 test-muladddivmod
|
||||
73634008615213489758113683559933051942050608504790565710917645985405082665491 -80155625965090770138821073870266428949137773405175831429923552413761952441361 -38999294453130493506999209141746004309873017414282530140731810289885759492802 -107314816556101242244916895079818037889329087681097150645968648449136338086659 2 54998743344874712983373052080844956119323047070936199528619384334263523872368 13082689556615721830015990667012489975468766353417550442844496303849124272459 test-muladddivmod
|
||||
68441985454806782074858763992903374541757416422223520705458179994903492447753 -61267036145362164840470993649039311748277914273628051012777836672446118682406 88886725386626308975645991554561163959863903429407091061340939714760192334434 -55192455525382179382269200386360902483303866088141254649003462525396159498006 0 75974833096374772090455746107157391488128832802648627140447901963962285642644 -35281244576421605907379124849976697589234314365299818483123805214351816431420 test-muladddivmod
|
||||
13991345100229597325861930387540671073560101799369013558248988792137436010794 32261366615236683296917985913895811707233003589900325435836147185374329094359 -35081305217709330815376010427375742966580511272499524644418734096933080609103 34617350357576952655827361801899194862477556493235499468927833026852355915741 1 13039123706936329824826187692520278079826111394035475962656812793878481550617 15501972367754182150585081456806290271752173495030969288120604381172009339746 test-muladddivmod
|
||||
54599312873997957959553141264956574941720752239162126863069720527738322459321 743784849758283770307843473486531088082399957077059004634332280604041992918 -82452755014987554458459818028526388807440160648566275282022897198718871469325 38291925157759929750140152840087355208836284729075633154257868030142639468974 2 1060540611514863450709563259060420401132951143137987621813620016383521959845 -25576601802989288764264589884413515994814497538433618559906725414501597729677 test-muladddivmod
|
||||
-33715442018098691670021742265266162391174212035380017502572244718418822715623 104887034421874269674272525533704680767916752281317133765280341780898862714955 40882837978738774675184345709913504579827188391303805465905655071457659357026 56761521466376613401789060160037629513193949115508135629309104361041554577464 0 -62301232175317956930653590924038385722281926697603233811485244969539670459488 12675521639977150682490928392886170001456429479565150104484728889568554893493 test-muladddivmod
|
||||
-109706830967107194245468623157302140481713559442721649770259230494532080435232 91091244832469326414116901981654442590329304825709696121493056753007506269108 25586919878947735367325917367337541421822321271842417480093738776553133015696 92030412800134708014057990497075561862656985932946512327644864855223778050176 1 -108587275612051383813143325045450855254642049763863834262763340362417287376196 14236417728543624555544633487823994857557292455110879135165049494799852613136 test-muladddivmod
|
||||
-55349740795363582739414701155082958898639391946026926848599395086577482106561 5153084015148055450516513461735201914781593572521892141092888805185704024388 -65052157988798026904166625513790079385321361518951356077015576483034859919945 -102114306233907646655227677599549837347948442788318424043410967802211179284463 2 2793162633665004752332533372431053166813934025727573730237936408503456830715 70263858264069476764017250048942592796103230166090146586104085945931001951432 test-muladddivmod
|
||||
-39413219476407785933419341321985162122574957075787517059529471719124009278433 -11397560582871643424486223364245599528148517163558642929375020427946855266926 72776685568498650781344357948907544676236244067805626443550533574512635929751 58457602475162312341105487265860863804074002837155658624106642883511552164475 0 7684450571493046035065075993797738633610800975055222799851151005079197271998 25447845742266018765952184307141986304437190746678223193451015171399298065659 test-muladddivmod
|
||||
28902743859707224532426872535592986589584185136999529704427764834614586536146 30118285526375438691436500554083725474584606124188443987423181314058619658259 -112947693515558587819874917596387701093051538659457576158697245759111287251112 -20731780512952622217494754630018335482763668682808767673633845662171371751908 1 -41988727958917592867685340883133510770733630298849576855386410060863664014757 6354934151364300917311007564393521634968794138377927567288802927545928772346 test-muladddivmod
|
||||
25071799008788838242365403068059094326298333378650328613993357620568407227394 -27895932377486960662691379394722126815225783254727720878708826335618109428175 -34783759350459778495483474263506062490621190762057336926096642777973708891199 -46562500545170684944465306233470472124382229989733955650634447552911654749066 2 15020696945874349483297599474537626462120625640258473403957682700588115661859 6123529058588613987393724235023234231421775050193606259696039938834907756545 test-muladddivmod
|
||||
4637334961015630956409530377119128659169399268652032534941609159910059786532 174 -12797497544848087213503981396389428116533825336325463794725594822879690679136 93018556588730187003792638630891717650672350374200759319903911998812002342061 0 1193763005785115313715849486131901382204829468191839 86009298512437248420661887032254663876544001080814196765583913598468234097773 test-shladddivmod
|
||||
63737576485202419511398757422488387344373087691300709744039454443359600742212 17 4434935617055335860270673726237887676208015615002198868506400573861444556411 2395017004775767547761160570739886212190100215618999647636254869255450984262 1 3488166 -825476601398469938219841341785340947550825081895127156723070705988041475817 test-shladddivmod
|
||||
-21264162232365890547240808872203618534857207092355857230053229357857057625546 79 83558436280879393517752968647441646810997015153366115449062116401734553793990 -19667935035506461778339921177556508690003173951785474262950610395510252887673 2 653520430812207296424074 11997579569142787892139960093229284888868038054542931791709721193377458047744 test-shladddivmod
|
||||
50327589756875372367121062573124726147569135695110368165104387616199145495643 159 -56582804136162261915738821952650758787670281453734279574878610404888378091325 41794171917267054297819695791653745099726306264896745093211576006595621865899 0 879953489426631344181134857312933722690648995542 7479251035838043422275284357505479089411783830647758441772426265279908213201 test-shladddivmod
|
||||
-6790346796221361248085433832482913268295667476610056123099942839800062619360 99 -30655005682505720678929136056715874580886440550632733046480550204329894400037 107280989788626394506897862107199815360330755655673306259970134464147378777352 1 -40117951973353319220033820651 15419963034230519057842831193590832882628829971176441336761525930488437456435 test-shladddivmod
|
||||
19046177038646178344769825269053799430308794840550024608332777213474587282651 33 3489319764096497921939317127917520109408688444737580375038679679318170964558 32230702261963164880326384192551720153568540700317784363615498612027586166919 2 5076073543 -31149228513135397726284948367312236333921327766221169520773046236565040396067 test-shladddivmod
|
||||
-110976730374012300153801377038320854184737548404302035494280064993634691387718 177 62599745911697906087525399889373248851994389233059198427444302208529620264342 2939901734097150061182352721440114362417026502565316012346244994332394908737 0 -7231166201303287776306953132498157445481985675557698778 861631401006029279966827198914714166628754059441816200263218068486981128432 test-shladddivmod
|
||||
31852390609689123349381354058350609996064615917952716537339963695989162024629 72 -96928192014181974842953135946922776102933173463512906699090906721752057028243 92656901870085089608820151790239083253300815942245860126341275046871599043017 1 1623394035183378246274 -40717467475217300542569194922405492138512784779596821986363220696851482878117 test-shladddivmod
|
||||
108325270025037161417115474167849009240382377052459846115851642255437288685912 79 -47995506721499545563379889382854078032364619862028413664240909132079634758006 -6166659869789359796343211847537623762770094929722294841335533066616771405539 2 -10618164339787666672859802 2975209691732235673066443530343246725711182217991112340969803628522007294972 test-shladddivmod
|
||||
-102030576317847732070693755030275793160072651528715762716678938494538431797856 162 92259248995288252713115460931891173987977282785918620735892298001910599707421 93069691103831234597581468228357432179178680731051507965844021657079407259554 0 -6408868561946334361312419431284710070541388837754 30090871674656727061174631170248864679275378922263881716308993939778213471313 test-shladddivmod
|
||||
109919709354382523017092140618288318375226272062645130510340454988137017880658 32 11403889262848182921779993946145880893942415285082669079885795084154364295755 -35203479084324376157414643218816253627488669490337878341936871887579427112193 1 -13410650571 -9079152369425295070217928786983170793628233088577531145426537161436231255680 test-shladddivmod
|
||||
32604320264365535336905506430047200856461747148561589244458238442999859570507 87 53600018835628474925583604580250089573381703851509998750334950185805444447855 -13714304553912094478086374486990066534941196173664347737943079140839510240 2 -367884070882655630785891877843 6730574288892465511219887918570728429135366732586091870751580223301793231 test-shladddivmod
|
||||
-6528863440223970638249234714151581865561638514865295384371332680662061970029 -36913540142944821177073496030226577063991271774591429797367434456256316959902 24604605953723174243828240349210337384146509969508816161702610762299708087414 252 0 33301544418230523796798136129325191903276669555089137976430642606666380785097 1111119448521463468919386205636226935698167866010067725789944817681239062460 test-muladdshrmod
|
||||
-84914121307006819861534520354024886732959304976576667909765018675779753895095 -33734797430686302202051663614563177864696792935288850099657207932669766616337 -102660654939881416004941779328139233368526378948134839417440263136258000263276 254 1 98955315519894417210680117251614014274294848178227094975298724352068617948436 11185753669896509258573194177216136324346588911755615485008785003988287318715 test-muladdshrmod
|
||||
-4756805439354914657157062146720760601779363897648559488036119230046473414258 -25205069919224711211607424233708613506619570034044466450241534811277675992336 65841615838405859557610720340525261800430556950418299394523533586361728325556 253 2 8283509830821873572245889567787981786085701113981069889850529960221182899414 -8998763596547876718672658010959335659555767305449508909489610444294401222444 test-muladdshrmod
|
||||
783982375644419567722751049236700086045042736024464491262223120876229442273 5175287637281731481295785519248883235846260036385254885568602894849814368811 -55298781556612762404255558682268367199188235546843731267393108383385576323488 255 0 70079645738212902632136650950755273036821422652512833810215828489102796342 57092783249763565645949150057908892679575599568561392603234275558727880866859 test-muladdshrmod
|
||||
4070111884734287416608979312653292787122202104172152519474989991166732734990 34257747897608142079436828950758942168797726684869935923750014522979867949066 -61460807674782162344337010795962912420813084141671620888972984019328919535019 255 1 2408331480685488199417578349126812242697171581435356157803139449785540375610 -22381063802952741956988549732332921247382434293458568395759850191487471696159 test-muladdshrmod
|
||||
46624156993487206784214341981008205045812193232799951047364876541247557155655 -63729769095463769066210525784474878773448422698647046890735133366216202823024 87326180659880540224448931705993651721770461620305276267209594753354088752298 254 2 -102644205801514086102164756532696646475956724447744150113359070359995022772818 -1428092989561848018204511966860198528552911262896258786227284617693530033510 test-muladdshrmod
|
||||
39272829609755756484322638781158254787641099751271808569134728682168699365109 -11052442053174551837010800294891429615750956891563661801761360982769602119895 -283548082261175812447439483712866143310217576711284967538745642449188994625 253 0 -29988969117668461072095834210490978680262152778767346814972545689246419413980 2174529687955394421606608137904112203633356592266557030912275482323503849980 test-muladdshrmod
|
||||
-6634646688578172858373436607694752472569893432402323211016655704885763912303 -50615746987061510852137844454230120888792101396398105566610972957006661885326 39885934214260485879330356646246293765018634098614146427190880259955614376279 255 1 5800354762566883489975672198380697469946049260633808174115670550957411425502 -28109144677804577765510965536534358513109159026887377398047363431999553081879 test-muladdshrmod
|
||||
36957305118458084509865949238755863689212814576372103672502961803454095738285 -17426859900126562814159340928393951526114707618474312299911007064028697482925 61889497203091392721847485067819343116261217894188379032096092268147391639006 252 2 -88993959131783882197769064733391828196442843554551869076190294411733289296212 -933414186558473122333257942263787394321322401897335201713504555165014099467 test-muladdshrmod
|
||||
72799360004808200591693183601526367934146450159257557514619233204077568035423 -43259113456489928181943264810324365449524922073847088046666461901052175252848 -20928308093701346202205365707157304905304946151034389446852806842785919722024 255 0 -54394661928130271541114188703398383016925401302362215366329066394036243394378 29938721175889548572374867166785136077053268439086595306734647725317227983176 test-muladdshrmod
|
||||
92302382053431541957491748846080777012291600699830575887072283670295321137177 69013668157296288202299005784733240169135155398176346313070175201757132886117 89824190356716673951870631561712249743053597592009107233443818823508120467661 255 1 110026963104671419264446752630572096381373731021551359794924308423043643793015 -23908158790588303139174012402649398780932740824917520006353845804429534584150 test-muladdshrmod
|
||||
19094862392572944474897897922146461521059803020953497046241755599584285859217 -9623105143646767554719516123478862168481718581670270810378662760058752527692 34811921737822512587681133088401450937187249507755006187477956368554274579224 255 2 -3173824217483389220453883003236448477412384215802980550708734379368313500289 -51434014928851488423168753814799098916141626164449965549730115348405330387188 test-muladdshrmod
|
954
crypto/test/fift/bls.fif
Normal file
954
crypto/test/fift/bls.fif
Normal file
|
@ -0,0 +1,954 @@
|
|||
// Based on https://github.com/ethereum/bls12-381-tests
|
||||
"Asm.fif" include
|
||||
"FiftExt.fif" include
|
||||
|
||||
{ shash swap shash B= } : slices-eq?
|
||||
|
||||
{
|
||||
=: expected-result
|
||||
// ."Args: " .s
|
||||
[[ <{ BLS_VERIFY }>s ]] 0 runvmx
|
||||
abort"exitcode != 0"
|
||||
."Result: " dup . cr
|
||||
."Expected: " @' expected-result dup . cr cr
|
||||
<> abort"wrong answer"
|
||||
} : test-verify // pub msg signature exprected-result
|
||||
|
||||
{
|
||||
=: expected-result
|
||||
// ."Args: " .s
|
||||
[[ <{ BLS_AGGREGATE }>s ]] 0 runvmx
|
||||
{ drop x{} } if
|
||||
."Result: " dup csr.
|
||||
."Expected: " @' expected-result dup csr. cr
|
||||
slices-eq? not abort"wrong answer"
|
||||
} : test-aggregate // sig[1] ... sig[n] n expected-result
|
||||
|
||||
{
|
||||
=: expected-result
|
||||
// ."Args: " .s
|
||||
[[ <{ BLS_FASTAGGREGATEVERIFY }>s ]] 0 runvmx
|
||||
abort"exitcode != 0"
|
||||
."Result: " dup . cr
|
||||
."Expected: " @' expected-result dup . cr cr
|
||||
<> abort"wrong answer"
|
||||
} : test-fast-aggregate-verify // pub[1] ... pub[n] n msg signature exprected-result
|
||||
|
||||
{
|
||||
=: expected-result
|
||||
// ."Args: " .s
|
||||
[[ <{ BLS_AGGREGATEVERIFY }>s ]] 0 runvmx
|
||||
abort"exitcode != 0"
|
||||
."Result: " dup . cr
|
||||
."Expected: " @' expected-result dup . cr cr
|
||||
<> abort"wrong answer"
|
||||
} : test-aggregate-verify // pub[1] msg[1] ... pub[n] msg[n] n signature exprected-result
|
||||
|
||||
."Test verifycase_one_privkey_47117849458281be" cr
|
||||
x{97f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb}
|
||||
x{1212121212121212121212121212121212121212121212121212121212121212}
|
||||
x{a42ae16f1c2a5fa69c04cb5998d2add790764ce8dd45bf25b29b4700829232052b52352dcff1cf255b3a7810ad7269601810f03b2bc8b68cf289cf295b206770605a190b6842583e47c3d1c0f73c54907bfb2a602157d46a4353a20283018763}
|
||||
-1
|
||||
test-verify
|
||||
|
||||
."Test verify_infinity_pubkey_and_infinity_signature" cr
|
||||
x{c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000}
|
||||
x{1212121212121212121212121212121212121212121212121212121212121212}
|
||||
x{c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000}
|
||||
0
|
||||
test-verify
|
||||
|
||||
."Test verify_tampered_signature_case_195246ee3bd3b6ec" cr
|
||||
x{b53d21a4cfd562c469cc81514d4ce5a6b577d8403d32a394dc265dd190b47fa9f829fdd7963afdf972e5e77854051f6f}
|
||||
x{abababababababababababababababababababababababababababababababab}
|
||||
x{ae82747ddeefe4fd64cf9cedb9b04ae3e8a43420cd255e3c7cd06a8d88b7c7f8638543719981c5d16fa3527c468c25f0026704a6951bde891360c7e8d12ddee0559004ccdbe6046b55bae1b257ee97f7cdb955773d7cf29adf3ccbb9ffffffff}
|
||||
0
|
||||
test-verify
|
||||
|
||||
."Test verify_tampered_signature_case_2ea479adf8c40300" cr
|
||||
x{a491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79a}
|
||||
x{5656565656565656565656565656565656565656565656565656565656565656}
|
||||
x{882730e5d03f6b42c3abc26d3372625034e1d871b65a8a6b900a56dae22da98abbe1b68f85e49fe7652a55ec3d0591c20767677e33e5cbb1207315c41a9ac03be39c2e7668edc043d6cb1d9fd93033caa8a1c5b0e84bedaeb6c64972ffffffff}
|
||||
0
|
||||
test-verify
|
||||
|
||||
."Test verify_tampered_signature_case_2f09d443ab8a3ac2" cr
|
||||
x{b301803f8b5ac4a1133581fc676dfedc60d891dd5fa99028805e5ea5b08d3491af75d0707adab3b70c6a6a580217bf81}
|
||||
x{0000000000000000000000000000000000000000000000000000000000000000}
|
||||
x{b23c46be3a001c63ca711f87a005c200cc550b9429d5f4eb38d74322144f1b63926da3388979e5321012fb1a0526bcd100b5ef5fe72628ce4cd5e904aeaa3279527843fae5ca9ca675f4f51ed8f83bbf7155da9ecc9663100a885d5dffffffff}
|
||||
0
|
||||
test-verify
|
||||
|
||||
."Test verify_tampered_signature_case_3208262581c8fc09" cr
|
||||
x{b301803f8b5ac4a1133581fc676dfedc60d891dd5fa99028805e5ea5b08d3491af75d0707adab3b70c6a6a580217bf81}
|
||||
x{5656565656565656565656565656565656565656565656565656565656565656}
|
||||
x{af1390c3c47acdb37131a51216da683c509fce0e954328a59f93aebda7e4ff974ba208d9a4a2a2389f892a9d418d618418dd7f7a6bc7aa0da999a9d3a5b815bc085e14fd001f6a1948768a3f4afefc8b8240dda329f984cb345c6363ffffffff}
|
||||
0
|
||||
test-verify
|
||||
|
||||
."Test verify_tampered_signature_case_6b3b17f6962a490c" cr
|
||||
x{b53d21a4cfd562c469cc81514d4ce5a6b577d8403d32a394dc265dd190b47fa9f829fdd7963afdf972e5e77854051f6f}
|
||||
x{5656565656565656565656565656565656565656565656565656565656565656}
|
||||
x{a4efa926610b8bd1c8330c918b7a5e9bf374e53435ef8b7ec186abf62e1b1f65aeaaeb365677ac1d1172a1f5b44b4e6d022c252c58486c0a759fbdc7de15a756acc4d343064035667a594b4c2a6f0b0b421975977f297dba63ee2f63ffffffff}
|
||||
0
|
||||
test-verify
|
||||
|
||||
."Test verify_tampered_signature_case_6eeb7c52dfd9baf0" cr
|
||||
x{b301803f8b5ac4a1133581fc676dfedc60d891dd5fa99028805e5ea5b08d3491af75d0707adab3b70c6a6a580217bf81}
|
||||
x{abababababababababababababababababababababababababababababababab}
|
||||
x{9674e2228034527f4c083206032b020310face156d4a4685e2fcaec2f6f3665aa635d90347b6ce124eb879266b1e801d185de36a0a289b85e9039662634f2eea1e02e670bc7ab849d006a70b2f93b84597558a05b879c8d445f387a5ffffffff}
|
||||
0
|
||||
test-verify
|
||||
|
||||
."Test verify_tampered_signature_case_8761a0b7e920c323" cr
|
||||
x{a491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79a}
|
||||
x{abababababababababababababababababababababababababababababababab}
|
||||
x{91347bccf740d859038fcdcaf233eeceb2a436bcaaee9b2aa3bfb70efe29dfb2677562ccbea1c8e061fb9971b0753c240622fab78489ce96768259fc01360346da5b9f579e5da0d941e4c6ba18a0e64906082375394f337fa1af2b71ffffffff}
|
||||
0
|
||||
test-verify
|
||||
|
||||
."Test verify_tampered_signature_case_d34885d766d5f705" cr
|
||||
x{b53d21a4cfd562c469cc81514d4ce5a6b577d8403d32a394dc265dd190b47fa9f829fdd7963afdf972e5e77854051f6f}
|
||||
x{0000000000000000000000000000000000000000000000000000000000000000}
|
||||
x{948a7cb99f76d616c2c564ce9bf4a519f1bea6b0a624a02276443c245854219fabb8d4ce061d255af5330b078d5380681751aa7053da2c98bae898edc218c75f07e24d8802a17cd1f6833b71e58f5eb5b94208b4d0bb3848cecb075effffffff}
|
||||
0
|
||||
test-verify
|
||||
|
||||
."Test verify_tampered_signature_case_e8a50c445c855360" cr
|
||||
x{a491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79a}
|
||||
x{0000000000000000000000000000000000000000000000000000000000000000}
|
||||
x{b6ed936746e01f8ecf281f020953fbf1f01debd5657c4a383940b020b26507f6076334f91e2366c96e9ab279fb5158090352ea1c5b0c9274504f4f0e7053af24802e51e4568d164fe986834f41e55c8e850ce1f98458c0cfc9ab380bffffffff}
|
||||
0
|
||||
test-verify
|
||||
|
||||
."Test verify_valid_case_195246ee3bd3b6ec" cr
|
||||
x{b53d21a4cfd562c469cc81514d4ce5a6b577d8403d32a394dc265dd190b47fa9f829fdd7963afdf972e5e77854051f6f}
|
||||
x{abababababababababababababababababababababababababababababababab}
|
||||
x{ae82747ddeefe4fd64cf9cedb9b04ae3e8a43420cd255e3c7cd06a8d88b7c7f8638543719981c5d16fa3527c468c25f0026704a6951bde891360c7e8d12ddee0559004ccdbe6046b55bae1b257ee97f7cdb955773d7cf29adf3ccbb9975e4eb9}
|
||||
-1
|
||||
test-verify
|
||||
|
||||
."Test verify_valid_case_2ea479adf8c40300" cr
|
||||
x{a491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79a}
|
||||
x{5656565656565656565656565656565656565656565656565656565656565656}
|
||||
x{882730e5d03f6b42c3abc26d3372625034e1d871b65a8a6b900a56dae22da98abbe1b68f85e49fe7652a55ec3d0591c20767677e33e5cbb1207315c41a9ac03be39c2e7668edc043d6cb1d9fd93033caa8a1c5b0e84bedaeb6c64972503a43eb}
|
||||
-1
|
||||
test-verify
|
||||
|
||||
."Test verify_valid_case_2f09d443ab8a3ac2" cr
|
||||
x{b301803f8b5ac4a1133581fc676dfedc60d891dd5fa99028805e5ea5b08d3491af75d0707adab3b70c6a6a580217bf81}
|
||||
x{0000000000000000000000000000000000000000000000000000000000000000}
|
||||
x{b23c46be3a001c63ca711f87a005c200cc550b9429d5f4eb38d74322144f1b63926da3388979e5321012fb1a0526bcd100b5ef5fe72628ce4cd5e904aeaa3279527843fae5ca9ca675f4f51ed8f83bbf7155da9ecc9663100a885d5dc6df96d9}
|
||||
-1
|
||||
test-verify
|
||||
|
||||
."Test verify_valid_case_3208262581c8fc09" cr
|
||||
x{b301803f8b5ac4a1133581fc676dfedc60d891dd5fa99028805e5ea5b08d3491af75d0707adab3b70c6a6a580217bf81}
|
||||
x{5656565656565656565656565656565656565656565656565656565656565656}
|
||||
x{af1390c3c47acdb37131a51216da683c509fce0e954328a59f93aebda7e4ff974ba208d9a4a2a2389f892a9d418d618418dd7f7a6bc7aa0da999a9d3a5b815bc085e14fd001f6a1948768a3f4afefc8b8240dda329f984cb345c6363272ba4fe}
|
||||
-1
|
||||
test-verify
|
||||
|
||||
."Test verify_valid_case_6b3b17f6962a490c" cr
|
||||
x{b53d21a4cfd562c469cc81514d4ce5a6b577d8403d32a394dc265dd190b47fa9f829fdd7963afdf972e5e77854051f6f}
|
||||
x{5656565656565656565656565656565656565656565656565656565656565656}
|
||||
x{a4efa926610b8bd1c8330c918b7a5e9bf374e53435ef8b7ec186abf62e1b1f65aeaaeb365677ac1d1172a1f5b44b4e6d022c252c58486c0a759fbdc7de15a756acc4d343064035667a594b4c2a6f0b0b421975977f297dba63ee2f63ffe47bb6}
|
||||
-1
|
||||
test-verify
|
||||
|
||||
."Test verify_valid_case_6eeb7c52dfd9baf0" cr
|
||||
x{b301803f8b5ac4a1133581fc676dfedc60d891dd5fa99028805e5ea5b08d3491af75d0707adab3b70c6a6a580217bf81}
|
||||
x{abababababababababababababababababababababababababababababababab}
|
||||
x{9674e2228034527f4c083206032b020310face156d4a4685e2fcaec2f6f3665aa635d90347b6ce124eb879266b1e801d185de36a0a289b85e9039662634f2eea1e02e670bc7ab849d006a70b2f93b84597558a05b879c8d445f387a5d5b653df}
|
||||
-1
|
||||
test-verify
|
||||
|
||||
."Test verify_valid_case_8761a0b7e920c323" cr
|
||||
x{a491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79a}
|
||||
x{abababababababababababababababababababababababababababababababab}
|
||||
x{91347bccf740d859038fcdcaf233eeceb2a436bcaaee9b2aa3bfb70efe29dfb2677562ccbea1c8e061fb9971b0753c240622fab78489ce96768259fc01360346da5b9f579e5da0d941e4c6ba18a0e64906082375394f337fa1af2b7127b0d121}
|
||||
-1
|
||||
test-verify
|
||||
|
||||
."Test verify_valid_case_d34885d766d5f705" cr
|
||||
x{b53d21a4cfd562c469cc81514d4ce5a6b577d8403d32a394dc265dd190b47fa9f829fdd7963afdf972e5e77854051f6f}
|
||||
x{0000000000000000000000000000000000000000000000000000000000000000}
|
||||
x{948a7cb99f76d616c2c564ce9bf4a519f1bea6b0a624a02276443c245854219fabb8d4ce061d255af5330b078d5380681751aa7053da2c98bae898edc218c75f07e24d8802a17cd1f6833b71e58f5eb5b94208b4d0bb3848cecb075ea21be115}
|
||||
-1
|
||||
test-verify
|
||||
|
||||
."Test verify_valid_case_e8a50c445c855360" cr
|
||||
x{a491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79a}
|
||||
x{0000000000000000000000000000000000000000000000000000000000000000}
|
||||
x{b6ed936746e01f8ecf281f020953fbf1f01debd5657c4a383940b020b26507f6076334f91e2366c96e9ab279fb5158090352ea1c5b0c9274504f4f0e7053af24802e51e4568d164fe986834f41e55c8e850ce1f98458c0cfc9ab380b55285a55}
|
||||
-1
|
||||
test-verify
|
||||
|
||||
."Test verify_wrong_pubkey_case_195246ee3bd3b6ec" cr
|
||||
x{b53d21a4cfd562c469cc81514d4ce5a6b577d8403d32a394dc265dd190b47fa9f829fdd7963afdf972e5e77854051f6f}
|
||||
x{abababababababababababababababababababababababababababababababab}
|
||||
x{9674e2228034527f4c083206032b020310face156d4a4685e2fcaec2f6f3665aa635d90347b6ce124eb879266b1e801d185de36a0a289b85e9039662634f2eea1e02e670bc7ab849d006a70b2f93b84597558a05b879c8d445f387a5d5b653df}
|
||||
0
|
||||
test-verify
|
||||
|
||||
."Test verify_wrong_pubkey_case_2ea479adf8c40300" cr
|
||||
x{a491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79a}
|
||||
x{5656565656565656565656565656565656565656565656565656565656565656}
|
||||
x{a4efa926610b8bd1c8330c918b7a5e9bf374e53435ef8b7ec186abf62e1b1f65aeaaeb365677ac1d1172a1f5b44b4e6d022c252c58486c0a759fbdc7de15a756acc4d343064035667a594b4c2a6f0b0b421975977f297dba63ee2f63ffe47bb6}
|
||||
0
|
||||
test-verify
|
||||
|
||||
."Test verify_wrong_pubkey_case_2f09d443ab8a3ac2" cr
|
||||
x{b301803f8b5ac4a1133581fc676dfedc60d891dd5fa99028805e5ea5b08d3491af75d0707adab3b70c6a6a580217bf81}
|
||||
x{0000000000000000000000000000000000000000000000000000000000000000}
|
||||
x{b6ed936746e01f8ecf281f020953fbf1f01debd5657c4a383940b020b26507f6076334f91e2366c96e9ab279fb5158090352ea1c5b0c9274504f4f0e7053af24802e51e4568d164fe986834f41e55c8e850ce1f98458c0cfc9ab380b55285a55}
|
||||
0
|
||||
test-verify
|
||||
|
||||
."Test verify_wrong_pubkey_case_3208262581c8fc09" cr
|
||||
x{b301803f8b5ac4a1133581fc676dfedc60d891dd5fa99028805e5ea5b08d3491af75d0707adab3b70c6a6a580217bf81}
|
||||
x{5656565656565656565656565656565656565656565656565656565656565656}
|
||||
x{882730e5d03f6b42c3abc26d3372625034e1d871b65a8a6b900a56dae22da98abbe1b68f85e49fe7652a55ec3d0591c20767677e33e5cbb1207315c41a9ac03be39c2e7668edc043d6cb1d9fd93033caa8a1c5b0e84bedaeb6c64972503a43eb}
|
||||
0
|
||||
test-verify
|
||||
|
||||
."Test verify_wrong_pubkey_case_6b3b17f6962a490c" cr
|
||||
x{b53d21a4cfd562c469cc81514d4ce5a6b577d8403d32a394dc265dd190b47fa9f829fdd7963afdf972e5e77854051f6f}
|
||||
x{5656565656565656565656565656565656565656565656565656565656565656}
|
||||
x{af1390c3c47acdb37131a51216da683c509fce0e954328a59f93aebda7e4ff974ba208d9a4a2a2389f892a9d418d618418dd7f7a6bc7aa0da999a9d3a5b815bc085e14fd001f6a1948768a3f4afefc8b8240dda329f984cb345c6363272ba4fe}
|
||||
0
|
||||
test-verify
|
||||
|
||||
."Test verify_wrong_pubkey_case_6eeb7c52dfd9baf0" cr
|
||||
x{b301803f8b5ac4a1133581fc676dfedc60d891dd5fa99028805e5ea5b08d3491af75d0707adab3b70c6a6a580217bf81}
|
||||
x{abababababababababababababababababababababababababababababababab}
|
||||
x{91347bccf740d859038fcdcaf233eeceb2a436bcaaee9b2aa3bfb70efe29dfb2677562ccbea1c8e061fb9971b0753c240622fab78489ce96768259fc01360346da5b9f579e5da0d941e4c6ba18a0e64906082375394f337fa1af2b7127b0d121}
|
||||
0
|
||||
test-verify
|
||||
|
||||
."Test verify_wrong_pubkey_case_8761a0b7e920c323" cr
|
||||
x{a491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79a}
|
||||
x{abababababababababababababababababababababababababababababababab}
|
||||
x{ae82747ddeefe4fd64cf9cedb9b04ae3e8a43420cd255e3c7cd06a8d88b7c7f8638543719981c5d16fa3527c468c25f0026704a6951bde891360c7e8d12ddee0559004ccdbe6046b55bae1b257ee97f7cdb955773d7cf29adf3ccbb9975e4eb9}
|
||||
0
|
||||
test-verify
|
||||
|
||||
."Test verify_wrong_pubkey_case_d34885d766d5f705" cr
|
||||
x{b53d21a4cfd562c469cc81514d4ce5a6b577d8403d32a394dc265dd190b47fa9f829fdd7963afdf972e5e77854051f6f}
|
||||
x{0000000000000000000000000000000000000000000000000000000000000000}
|
||||
x{b23c46be3a001c63ca711f87a005c200cc550b9429d5f4eb38d74322144f1b63926da3388979e5321012fb1a0526bcd100b5ef5fe72628ce4cd5e904aeaa3279527843fae5ca9ca675f4f51ed8f83bbf7155da9ecc9663100a885d5dc6df96d9}
|
||||
0
|
||||
test-verify
|
||||
|
||||
."Test verify_wrong_pubkey_case_e8a50c445c855360" cr
|
||||
x{a491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79a}
|
||||
x{0000000000000000000000000000000000000000000000000000000000000000}
|
||||
x{948a7cb99f76d616c2c564ce9bf4a519f1bea6b0a624a02276443c245854219fabb8d4ce061d255af5330b078d5380681751aa7053da2c98bae898edc218c75f07e24d8802a17cd1f6833b71e58f5eb5b94208b4d0bb3848cecb075ea21be115}
|
||||
0
|
||||
test-verify
|
||||
|
||||
|
||||
."Test aggregate_0x0000000000000000000000000000000000000000000000000000000000000000" cr
|
||||
x{b6ed936746e01f8ecf281f020953fbf1f01debd5657c4a383940b020b26507f6076334f91e2366c96e9ab279fb5158090352ea1c5b0c9274504f4f0e7053af24802e51e4568d164fe986834f41e55c8e850ce1f98458c0cfc9ab380b55285a55}
|
||||
x{b23c46be3a001c63ca711f87a005c200cc550b9429d5f4eb38d74322144f1b63926da3388979e5321012fb1a0526bcd100b5ef5fe72628ce4cd5e904aeaa3279527843fae5ca9ca675f4f51ed8f83bbf7155da9ecc9663100a885d5dc6df96d9}
|
||||
x{948a7cb99f76d616c2c564ce9bf4a519f1bea6b0a624a02276443c245854219fabb8d4ce061d255af5330b078d5380681751aa7053da2c98bae898edc218c75f07e24d8802a17cd1f6833b71e58f5eb5b94208b4d0bb3848cecb075ea21be115}
|
||||
3
|
||||
x{9683b3e6701f9a4b706709577963110043af78a5b41991b998475a3d3fd62abf35ce03b33908418efc95a058494a8ae504354b9f626231f6b3f3c849dfdeaf5017c4780e2aee1850ceaf4b4d9ce70971a3d2cfcd97b7e5ecf6759f8da5f76d31}
|
||||
test-aggregate
|
||||
|
||||
."Test aggregate_0x5656565656565656565656565656565656565656565656565656565656565656" cr
|
||||
x{882730e5d03f6b42c3abc26d3372625034e1d871b65a8a6b900a56dae22da98abbe1b68f85e49fe7652a55ec3d0591c20767677e33e5cbb1207315c41a9ac03be39c2e7668edc043d6cb1d9fd93033caa8a1c5b0e84bedaeb6c64972503a43eb}
|
||||
x{af1390c3c47acdb37131a51216da683c509fce0e954328a59f93aebda7e4ff974ba208d9a4a2a2389f892a9d418d618418dd7f7a6bc7aa0da999a9d3a5b815bc085e14fd001f6a1948768a3f4afefc8b8240dda329f984cb345c6363272ba4fe}
|
||||
x{a4efa926610b8bd1c8330c918b7a5e9bf374e53435ef8b7ec186abf62e1b1f65aeaaeb365677ac1d1172a1f5b44b4e6d022c252c58486c0a759fbdc7de15a756acc4d343064035667a594b4c2a6f0b0b421975977f297dba63ee2f63ffe47bb6}
|
||||
3
|
||||
x{ad38fc73846583b08d110d16ab1d026c6ea77ac2071e8ae832f56ac0cbcdeb9f5678ba5ce42bd8dce334cc47b5abcba40a58f7f1f80ab304193eb98836cc14d8183ec14cc77de0f80c4ffd49e168927a968b5cdaa4cf46b9805be84ad7efa77b}
|
||||
test-aggregate
|
||||
|
||||
."Test aggregate_0xabababababababababababababababababababababababababababababababab" cr
|
||||
x{91347bccf740d859038fcdcaf233eeceb2a436bcaaee9b2aa3bfb70efe29dfb2677562ccbea1c8e061fb9971b0753c240622fab78489ce96768259fc01360346da5b9f579e5da0d941e4c6ba18a0e64906082375394f337fa1af2b7127b0d121}
|
||||
x{9674e2228034527f4c083206032b020310face156d4a4685e2fcaec2f6f3665aa635d90347b6ce124eb879266b1e801d185de36a0a289b85e9039662634f2eea1e02e670bc7ab849d006a70b2f93b84597558a05b879c8d445f387a5d5b653df}
|
||||
x{ae82747ddeefe4fd64cf9cedb9b04ae3e8a43420cd255e3c7cd06a8d88b7c7f8638543719981c5d16fa3527c468c25f0026704a6951bde891360c7e8d12ddee0559004ccdbe6046b55bae1b257ee97f7cdb955773d7cf29adf3ccbb9975e4eb9}
|
||||
3
|
||||
x{9712c3edd73a209c742b8250759db12549b3eaf43b5ca61376d9f30e2747dbcf842d8b2ac0901d2a093713e20284a7670fcf6954e9ab93de991bb9b313e664785a075fc285806fa5224c82bde146561b446ccfc706a64b8579513cfc4ff1d930}
|
||||
test-aggregate
|
||||
|
||||
."Test aggregate_infinity_signature" cr
|
||||
x{c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000}
|
||||
1
|
||||
x{c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000}
|
||||
test-aggregate
|
||||
|
||||
."Test aggregate_na_signatures" cr
|
||||
0
|
||||
x{}
|
||||
test-aggregate
|
||||
|
||||
."Test aggregate_single_signature" cr
|
||||
x{b6ed936746e01f8ecf281f020953fbf1f01debd5657c4a383940b020b26507f6076334f91e2366c96e9ab279fb5158090352ea1c5b0c9274504f4f0e7053af24802e51e4568d164fe986834f41e55c8e850ce1f98458c0cfc9ab380b55285a55}
|
||||
1
|
||||
x{b6ed936746e01f8ecf281f020953fbf1f01debd5657c4a383940b020b26507f6076334f91e2366c96e9ab279fb5158090352ea1c5b0c9274504f4f0e7053af24802e51e4568d164fe986834f41e55c8e850ce1f98458c0cfc9ab380b55285a55}
|
||||
test-aggregate
|
||||
|
||||
."Test fast_aggregate_verify_extra_pubkey_4f079f946446fabf" cr
|
||||
x{a491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79a}
|
||||
x{b301803f8b5ac4a1133581fc676dfedc60d891dd5fa99028805e5ea5b08d3491af75d0707adab3b70c6a6a580217bf81}
|
||||
x{b53d21a4cfd562c469cc81514d4ce5a6b577d8403d32a394dc265dd190b47fa9f829fdd7963afdf972e5e77854051f6f}
|
||||
3
|
||||
x{5656565656565656565656565656565656565656565656565656565656565656}
|
||||
x{912c3615f69575407db9392eb21fee18fff797eeb2fbe1816366ca2a08ae574d8824dbfafb4c9eaa1cf61b63c6f9b69911f269b664c42947dd1b53ef1081926c1e82bb2a465f927124b08391a5249036146d6f3f1e17ff5f162f779746d830d1}
|
||||
0
|
||||
test-fast-aggregate-verify
|
||||
|
||||
."Test fast_aggregate_verify_extra_pubkey_5a38e6b4017fe4dd" cr
|
||||
x{a491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79a}
|
||||
x{b301803f8b5ac4a1133581fc676dfedc60d891dd5fa99028805e5ea5b08d3491af75d0707adab3b70c6a6a580217bf81}
|
||||
x{b53d21a4cfd562c469cc81514d4ce5a6b577d8403d32a394dc265dd190b47fa9f829fdd7963afdf972e5e77854051f6f}
|
||||
x{b53d21a4cfd562c469cc81514d4ce5a6b577d8403d32a394dc265dd190b47fa9f829fdd7963afdf972e5e77854051f6f}
|
||||
4
|
||||
x{abababababababababababababababababababababababababababababababab}
|
||||
x{9712c3edd73a209c742b8250759db12549b3eaf43b5ca61376d9f30e2747dbcf842d8b2ac0901d2a093713e20284a7670fcf6954e9ab93de991bb9b313e664785a075fc285806fa5224c82bde146561b446ccfc706a64b8579513cfc4ff1d930}
|
||||
0
|
||||
test-fast-aggregate-verify
|
||||
|
||||
."Test fast_aggregate_verify_extra_pubkey_a698ea45b109f303" cr
|
||||
x{a491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79a}
|
||||
x{b53d21a4cfd562c469cc81514d4ce5a6b577d8403d32a394dc265dd190b47fa9f829fdd7963afdf972e5e77854051f6f}
|
||||
2
|
||||
x{0000000000000000000000000000000000000000000000000000000000000000}
|
||||
x{b6ed936746e01f8ecf281f020953fbf1f01debd5657c4a383940b020b26507f6076334f91e2366c96e9ab279fb5158090352ea1c5b0c9274504f4f0e7053af24802e51e4568d164fe986834f41e55c8e850ce1f98458c0cfc9ab380b55285a55}
|
||||
0
|
||||
test-fast-aggregate-verify
|
||||
|
||||
."Test fast_aggregate_verify_infinity_pubkey" cr
|
||||
x{a491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79a}
|
||||
x{b301803f8b5ac4a1133581fc676dfedc60d891dd5fa99028805e5ea5b08d3491af75d0707adab3b70c6a6a580217bf81}
|
||||
x{b53d21a4cfd562c469cc81514d4ce5a6b577d8403d32a394dc265dd190b47fa9f829fdd7963afdf972e5e77854051f6f}
|
||||
x{c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000}
|
||||
4
|
||||
x{1212121212121212121212121212121212121212121212121212121212121212}
|
||||
x{afcb4d980f079265caa61aee3e26bf48bebc5dc3e7f2d7346834d76cbc812f636c937b6b44a9323d8bc4b1cdf71d6811035ddc2634017faab2845308f568f2b9a0356140727356eae9eded8b87fd8cb8024b440c57aee06076128bb32921f584}
|
||||
0
|
||||
test-fast-aggregate-verify
|
||||
|
||||
."Test fast_aggregate_verify_na_pubkeys_and_infinity_signature" cr
|
||||
0
|
||||
x{abababababababababababababababababababababababababababababababab}
|
||||
x{c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000}
|
||||
0
|
||||
test-fast-aggregate-verify
|
||||
|
||||
."Test fast_aggregate_verify_na_pubkeys_and_na_signature" cr
|
||||
0
|
||||
x{abababababababababababababababababababababababababababababababab}
|
||||
x{000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000}
|
||||
0
|
||||
test-fast-aggregate-verify
|
||||
|
||||
."Test fast_aggregate_verify_tampered_signature_3d7576f3c0e3570a" cr
|
||||
x{a491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79a}
|
||||
x{b301803f8b5ac4a1133581fc676dfedc60d891dd5fa99028805e5ea5b08d3491af75d0707adab3b70c6a6a580217bf81}
|
||||
x{b53d21a4cfd562c469cc81514d4ce5a6b577d8403d32a394dc265dd190b47fa9f829fdd7963afdf972e5e77854051f6f}
|
||||
3
|
||||
x{abababababababababababababababababababababababababababababababab}
|
||||
x{9712c3edd73a209c742b8250759db12549b3eaf43b5ca61376d9f30e2747dbcf842d8b2ac0901d2a093713e20284a7670fcf6954e9ab93de991bb9b313e664785a075fc285806fa5224c82bde146561b446ccfc706a64b8579513cfcffffffff}
|
||||
0
|
||||
test-fast-aggregate-verify
|
||||
|
||||
."Test fast_aggregate_verify_tampered_signature_5e745ad0c6199a6c" cr
|
||||
x{a491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79a}
|
||||
1
|
||||
x{0000000000000000000000000000000000000000000000000000000000000000}
|
||||
x{b6ed936746e01f8ecf281f020953fbf1f01debd5657c4a383940b020b26507f6076334f91e2366c96e9ab279fb5158090352ea1c5b0c9274504f4f0e7053af24802e51e4568d164fe986834f41e55c8e850ce1f98458c0cfc9ab380bffffffff}
|
||||
0
|
||||
test-fast-aggregate-verify
|
||||
|
||||
."Test fast_aggregate_verify_tampered_signature_652ce62f09290811" cr
|
||||
x{a491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79a}
|
||||
x{b301803f8b5ac4a1133581fc676dfedc60d891dd5fa99028805e5ea5b08d3491af75d0707adab3b70c6a6a580217bf81}
|
||||
2
|
||||
x{5656565656565656565656565656565656565656565656565656565656565656}
|
||||
x{912c3615f69575407db9392eb21fee18fff797eeb2fbe1816366ca2a08ae574d8824dbfafb4c9eaa1cf61b63c6f9b69911f269b664c42947dd1b53ef1081926c1e82bb2a465f927124b08391a5249036146d6f3f1e17ff5f162f7797ffffffff}
|
||||
0
|
||||
test-fast-aggregate-verify
|
||||
|
||||
."Test fast_aggregate_verify_valid_3d7576f3c0e3570a" cr
|
||||
x{a491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79a}
|
||||
x{b301803f8b5ac4a1133581fc676dfedc60d891dd5fa99028805e5ea5b08d3491af75d0707adab3b70c6a6a580217bf81}
|
||||
x{b53d21a4cfd562c469cc81514d4ce5a6b577d8403d32a394dc265dd190b47fa9f829fdd7963afdf972e5e77854051f6f}
|
||||
3
|
||||
x{abababababababababababababababababababababababababababababababab}
|
||||
x{9712c3edd73a209c742b8250759db12549b3eaf43b5ca61376d9f30e2747dbcf842d8b2ac0901d2a093713e20284a7670fcf6954e9ab93de991bb9b313e664785a075fc285806fa5224c82bde146561b446ccfc706a64b8579513cfc4ff1d930}
|
||||
-1
|
||||
test-fast-aggregate-verify
|
||||
|
||||
."Test fast_aggregate_verify_valid_5e745ad0c6199a6c" cr
|
||||
x{a491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79a}
|
||||
1
|
||||
x{0000000000000000000000000000000000000000000000000000000000000000}
|
||||
x{b6ed936746e01f8ecf281f020953fbf1f01debd5657c4a383940b020b26507f6076334f91e2366c96e9ab279fb5158090352ea1c5b0c9274504f4f0e7053af24802e51e4568d164fe986834f41e55c8e850ce1f98458c0cfc9ab380b55285a55}
|
||||
-1
|
||||
test-fast-aggregate-verify
|
||||
|
||||
."Test fast_aggregate_verify_valid_652ce62f09290811" cr
|
||||
x{a491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79a}
|
||||
x{b301803f8b5ac4a1133581fc676dfedc60d891dd5fa99028805e5ea5b08d3491af75d0707adab3b70c6a6a580217bf81}
|
||||
2
|
||||
x{5656565656565656565656565656565656565656565656565656565656565656}
|
||||
x{912c3615f69575407db9392eb21fee18fff797eeb2fbe1816366ca2a08ae574d8824dbfafb4c9eaa1cf61b63c6f9b69911f269b664c42947dd1b53ef1081926c1e82bb2a465f927124b08391a5249036146d6f3f1e17ff5f162f779746d830d1}
|
||||
-1
|
||||
test-fast-aggregate-verify
|
||||
|
||||
."Test aggregate_verify_infinity_pubkey" cr
|
||||
x{a491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79a}
|
||||
x{0000000000000000000000000000000000000000000000000000000000000000}
|
||||
x{b301803f8b5ac4a1133581fc676dfedc60d891dd5fa99028805e5ea5b08d3491af75d0707adab3b70c6a6a580217bf81}
|
||||
x{5656565656565656565656565656565656565656565656565656565656565656}
|
||||
x{b53d21a4cfd562c469cc81514d4ce5a6b577d8403d32a394dc265dd190b47fa9f829fdd7963afdf972e5e77854051f6f}
|
||||
x{abababababababababababababababababababababababababababababababab}
|
||||
x{c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000}
|
||||
x{1212121212121212121212121212121212121212121212121212121212121212}
|
||||
4
|
||||
x{9104e74b9dfd3ad502f25d6a5ef57db0ed7d9a0e00f3500586d8ce44231212542fcfaf87840539b398bf07626705cf1105d246ca1062c6c2e1a53029a0f790ed5e3cb1f52f8234dc5144c45fc847c0cd37a92d68e7c5ba7c648a8a339f171244}
|
||||
0
|
||||
test-aggregate-verify
|
||||
|
||||
."Test aggregate_verify_na_pubkeys_and_infinity_signature" cr
|
||||
0
|
||||
x{c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000}
|
||||
0
|
||||
test-aggregate-verify
|
||||
|
||||
."Test aggregate_verify_na_pubkeys_and_na_signature" cr
|
||||
0
|
||||
x{000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000}
|
||||
0
|
||||
test-aggregate-verify
|
||||
|
||||
."Test aggregate_verify_tampered_signature" cr
|
||||
// Test is modified to make all signatures 96 bytes
|
||||
x{a491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79a}
|
||||
x{0000000000000000000000000000000000000000000000000000000000000000}
|
||||
x{b301803f8b5ac4a1133581fc676dfedc60d891dd5fa99028805e5ea5b08d3491af75d0707adab3b70c6a6a580217bf81}
|
||||
x{5656565656565656565656565656565656565656565656565656565656565656}
|
||||
x{b53d21a4cfd562c469cc81514d4ce5a6b577d8403d32a394dc265dd190b47fa9f829fdd7963afdf972e5e77854051f6f}
|
||||
x{abababababababababababababababababababababababababababababababab}
|
||||
3
|
||||
x{9104e74bffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff}
|
||||
0
|
||||
test-aggregate-verify
|
||||
|
||||
."Test aggregate_verify_valid" cr
|
||||
x{a491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79a}
|
||||
x{0000000000000000000000000000000000000000000000000000000000000000}
|
||||
x{b301803f8b5ac4a1133581fc676dfedc60d891dd5fa99028805e5ea5b08d3491af75d0707adab3b70c6a6a580217bf81}
|
||||
x{5656565656565656565656565656565656565656565656565656565656565656}
|
||||
x{b53d21a4cfd562c469cc81514d4ce5a6b577d8403d32a394dc265dd190b47fa9f829fdd7963afdf972e5e77854051f6f}
|
||||
x{abababababababababababababababababababababababababababababababab}
|
||||
3
|
||||
x{9104e74b9dfd3ad502f25d6a5ef57db0ed7d9a0e00f3500586d8ce44231212542fcfaf87840539b398bf07626705cf1105d246ca1062c6c2e1a53029a0f790ed5e3cb1f52f8234dc5144c45fc847c0cd37a92d68e7c5ba7c648a8a339f171244}
|
||||
-1
|
||||
test-aggregate-verify
|
||||
|
||||
."Test fast_aggregate_verify with actual Ethereum signatures" cr
|
||||
x{abd15ed19f6b6f4a199b6c90637e70222a8aadcb34ffdef3c6cc57a824a7410852d209835c91680875794ba287ce7de3}
|
||||
x{832451ba329e4fe2e81056ae224feea873ed8d6ffc86840437976a421a352282faca08b93e9e3a8068a9e3979e6056b5}
|
||||
x{b09e63a9a8b80928532e1fe0d4624be4990bbdf4c11293cd72ac635f56262fea853aef1348c26a8263f83d0c3144bdda}
|
||||
x{98e38f383949a34bc925a381b3e922fafc200201f743001fff15171bdab7a82a3731c54522c98297840ca687e47057bf}
|
||||
x{af2d7140be9332b536222680c690a54de4eea2644b3b3a84e45b3e425d4a37f07c98eff13e123da39b22c536be230f94}
|
||||
x{8277ce097d82f3810e28936bb0f200c47be681db6b22a34bae6b39a0616a1dc5eb542dbc0f68adccbf5e9517a03c0736}
|
||||
x{9663cda398d72bf5bdd4bbc49651bdefb88f5dfb32e305a7f70a968cbd1e6f4ae7cd50e675393e04ec56f7566bbc153c}
|
||||
x{a9c0360b88f09c0528a0cca8173061eeef7e8cc84064dd3bd894808e1da3536093f9acf7552e3485d037cf5b10a9c036}
|
||||
x{8259ce226809ebf580488ad7c8d054732eedd21552d8ab4d8652b62524f3858eb10b055f40f7d1752b200bee9a94b8c0}
|
||||
x{a605c777fb1ce8b67450e0d243305f5a906074dbeaa514d93cb43eae638794c2ef38c60b478f7aabdae5f4e1461d2d69}
|
||||
x{9376c20d92aae571465aba7286ada5c50733fd5c417fc8a4cc7cf2af8298f35ec6f43b6d9fe1bf8c950abe3499b4dd62}
|
||||
x{a4ca29cca82a9bbc250556c459d0ac48c90652b7ecaf77aabc14a64e15a6e686e48efced318ba848303908036fd44f86}
|
||||
x{aa50e833ee57e0b71b52a5f826cb7f131720fb35c828701d0703eeb417613a8f10be0be445b35ad5b9fa7a6da3c3a836}
|
||||
x{825f98ebe875b1b6ad876153d3969a0fbb088f3fdffecdfda40bdad451fb336a05296f325ed85bbc271eab8dd9d541d1}
|
||||
x{9895f1615cec63b3a28be707874dc4273168f91c0c5bf687893680f5e4d88964620b2fc91dc0e663c1d9968c25a95a01}
|
||||
x{a4255953e52e4bf80a8c2c52cd24fbf869bc43c7fc815239d54d841b86b660a3b2841191f9716fc4aad465432b8415c0}
|
||||
x{b663d3f303a2dcc660f274c6b051e4c2a16271840315148748ba0585f47e02e99827527d365acae65094c39a09c1b065}
|
||||
x{86753154725dedbc2f0425723b551f4fccb2f69087354ac0c0c0bbbc23e10d07325b87989623c54e58b7b2241c97efbb}
|
||||
x{b1de760c0271e5ad1422d8b58ddf954fb104ec7b8a74927ddad612833d189fdf6bb776249cde1b48786ad69e015a7b0d}
|
||||
x{976cd11d84723509780656ca3b92f12eeaa7413b78d9c74824bbfb0269d7ffb63499be7340ca75ede7cfac28024785a8}
|
||||
x{b2318f9647bc8ce79734177a85877d63f486ce98ab2a247672c54cc4093dabd013ea2d95157a1c5c5d7cbe00e4c33b11}
|
||||
x{97ec1840d0795bd66dfb2a3ef954f93ac93e05755c2b3d61b714be2d732d37291e5a95a69a02ab6af4ae1441e45e9323}
|
||||
x{a3fc6160fb647a1d43d94d639704d6d17528b18361e3acbfce051fe10d7b9608e717f6d73f51b784e69b59789c121f2f}
|
||||
x{82406906b3a6e0baa89d93fb2e1c1f87537e6920f4c1390a1526fb5f490f65dc35432ac6d265418167d7a68c5cd70c74}
|
||||
x{999a313756535ae0d6816b99c69db91c3792648d45cad753c8f6cea0d9997f2006c508cdb39c3d286e24a607598a8c8a}
|
||||
x{87dffdc02f4797901553cc7de4a8ffdae4df2b5728a0418923d1d4c01da14a482b21a13332b7227f49b4396f88e776ac}
|
||||
x{82c9236f69038abc40acbf1b730b3c1d3962ff9567f823c83eb3e984339e77c4f9373f679d30c4ffd0e2aad1d002f4ba}
|
||||
x{81b989f4a65fce31ba9c63a80ff53d28e75606f5ec563a6aef5f2d76d13f591ad60b974f97fd08155325148df95cfcc1}
|
||||
x{8f3470b02f8e0a5af092625b3f3812d44d76b86cd1c7af64f1c350f6931eacc38490f10cb9888f1b6cdf68fac06ef9f7}
|
||||
x{ad77903be9a9c4611d9c152ba31faf49d936be3ca7ace051ee0d8862a3869d61194d990b5b4c86bdcf5219e0ea2c25f9}
|
||||
x{b6654b4984b1f41517fb3d1f8471f2b3a389329fe304cf315d0c087b7a29f58c8fe61cacd99620ad337fb73e773836a6}
|
||||
x{819cc51962fafcbe99160959e9bbe66e43bf06b5cae2300fe7cb9aca5739f31c4e8a4c695e77f6b06a881eb6322f4399}
|
||||
x{a9aadc9694fc9c214875b66f00472ab3bdb9fec2cf07a46845050506c077a029ee75f88a24ea2a1b9c2c0b50810e6254}
|
||||
x{ab5c69e503a2a7becebb24f17c921e9ec2f4d18f7b1565b0c2a1468271348aee861ee0e9e091a786fbdad10743a7c449}
|
||||
x{8a1d4d071d08a340f3a3df825d748da28b9dcbc52482d34ce05e6272ebaf93858c8460831ded3c81d2d19352414c7fec}
|
||||
x{8fe4c6f6aa8951d3f092132c645f4ccf9a50a1c200fa96f27306968b4baab7b5bb09e1f6b8d7bb91dc82a408576d6894}
|
||||
x{958fa0b9e4a095c7c270d7c3d9a603533e5d91b6e1624ff6dc235d5e96ba7cf3df71b202d96667b4add69c10af948fa3}
|
||||
x{aa9fbae1a28af5400c5fcee35a6b968422c3015f018d06793d21bd4fbf492c484b15d8a7558d0081ce174d1b648bb057}
|
||||
x{819a691281ccb2aef76c9523a9e0329e1abf6fa1917227fcc9c3996662de6d4d3623ba2298845b2f82c893b5f3b7f638}
|
||||
x{b59bc108d9780d1322e318765f0064e93a475f4ef76519a05c76b52b9a640b3d6add5635ff4477b8124e42ada3b95a85}
|
||||
x{b040da098f2f81cb66270ad142035080da510bbb7c7835d12432ab0f689665052aa226e818a2f16c60e38e2e9dae1ce7}
|
||||
x{834a7bc5d9eea4c10508dbbf366e1c0c1d4ae87a0832b7d9cc6b635da6b37b70a0ee57215e7ed2eaadc58587792a7341}
|
||||
x{97c3281b2f7d1893dab3802b620d72e7061af12ad57847ce00af912dbd8c3ab62f8c548764aee8da5ca57d527e41655c}
|
||||
x{af4241e7dff52b4912d0b6b06f6d59562c77858538f0838f652d91cf13afbafbbb7f16aaa2c53c6159cb1aa8e4c672fe}
|
||||
x{92a78d4bc61c4cb7783a57e3f423e83402659de44efc167a943604a89cc7afe3c6db64dbc05cac81503f17bef2f3bfcc}
|
||||
x{907fdbf2864372dfd420acb19dd045f090c088a858bb58e2de82ac6aef9a5efe423c6fcbd1f1810d6bec89f9eab8cea1}
|
||||
x{96ccd37a8c0755f54d66d380ba56e5520a8adfcb70271d223aa9b42bd6cbbe3a7d186012b49dff85f0d7df3f366b41e3}
|
||||
x{89e738b1b69710038089a990a7278b2a54d30075998fb1d4540c6e264e57def74fbed1b35cf0f3f236f12887e4df1949}
|
||||
x{910a6f5d7a02bc8641e179000faf86f92445d63174999b55d6671d05a2253f1b5890f02d2b679a0b3f500faa89f160d2}
|
||||
x{a6d921cc92c139a4345b7aab309318c1067e5169f179f82a9bc735c08ff61232a63d88ea59157ea354476a9d2b40db49}
|
||||
x{b3ed37713ef72ce168beee0aa38f89ed3cf76337a198ccc1b30b58d808aea839af97f5c2fe95ffc61ba875f095058cc6}
|
||||
x{81104459d2f669aa6bd481fead334fb0dd709e6029e7374d61d9cb1a9589255efde16ca1e6ce1c5dbc510dbef512ad4f}
|
||||
x{9684fa7e1f44fd4e326104ede6348bbb978e68a944448dc311a634cda46bb52086cac4b435eef009dcdcfe04f3413ed0}
|
||||
x{b93fe3dbbdf63678e0cb0e4e299015e6a4187d5a6039ac6eb0d96ca4baecfe1a0d3672ed716d2b129fbe7b8373750cf4}
|
||||
x{ac97c56a24b9dbdf87337a87f27a90b1d936c20e68a39e2f8bbc2ae5a9e1ae9490477cbe03e03f180ff42637246b9541}
|
||||
x{8032d15ee910491ac3e5d228e00ef8ae41e50c0ca2692fbe7f006f3d8b360e556a1e0ad0c67d18a231f2d71ae83914f5}
|
||||
x{8ad43c8688a00ea88ddacbf8d2aa99997dd425a35bd7294be0fac420af95bc1723919d2d03862dbee6e3564331d26033}
|
||||
x{ab2aecb129638db624254e7001a725260d2739fd50b374418a1155569eff3581dcd6f25cb0d0b85ae20aa176c30c99e7}
|
||||
x{a9a420966d5d57d11a2d881fb462c7ed53dabba8e51b78bb852acc08c4f5c86791828e8cc59631c3fb1351e0960f4347}
|
||||
x{b974b7427651578b63669ef47ec8cde65c9d134e18e9f2e2761b3250fb472a578424fff31614404d0bc23c0cd75d26e2}
|
||||
x{a2ebd309811f0c33ae45b709bf55e1c0cc0a09cb18a47855d42d5012e6d2e340105dcd85347060c64852a9da589c26fa}
|
||||
x{af6c39210b9c6d153e141fb34d7739fc7a9fbf5656b30744e9a8440e6049d84863c2f208f14e03ab5fb5fb47a19dc277}
|
||||
x{a19820316b4136e5b937c0b60812983f7fbf7a53b1758ad8dc0e249cd49dafbfda4c25d9c798a15a9693bc565a11383f}
|
||||
x{851cf2adc1d7ad56a0ea3a7abff62570b9b4b25ad84e847e278edd8b11b2a6d2ce901bb45604e51ae5d3aa3c13ed4a07}
|
||||
x{b9fd9b663fa540237e214c7b1e3b6b74a4381120f82e9691d3d9243d871eed4672926059973ade7badbb88961868e5ef}
|
||||
x{b943affd10c2735dd5ef10376763e44ad0a848796e28fd215cf5c56d124d191f11fe22fd419ead954a4610b0990fcaa4}
|
||||
x{a579968409343bda51ec7ba8a4870d8bd560c43a313db0564c5e6df8381d7ff818ffb4676c9a06469ab14d00dd26b00b}
|
||||
x{b0fb5a7cf2df5834f822e44e6efe63211db7a747b196c6bc2d1605933dc1d24f75d8373d219da0210ebb4228d98cc4e9}
|
||||
x{967512e3287fa5c4c0093dadf799a4a4053bf95574c18688f9ec9896c74978862517d118058590511a332ca303f42efb}
|
||||
x{80532dfc08ee2b181e9c591d23c8aa53ad6b4dab54b87d57c1530cccfef26bc53a69e6edcdd74a0e072612f9967bc99f}
|
||||
x{a03974bf0c0cd74db34d19a4a417bc5a4bff8a2a7566728a8b411317b2ae1c85d02eb17e955264a7439153876b41208a}
|
||||
x{903f9407477a39f67d5bbd9b6d9a353470019d1f3508fe803a13ba69b01fee8713f468db4846b01d4d4e9f955b87f55b}
|
||||
x{a7a6df5ba7ca5697aa90ee6a4806346d3e2a6b9aac371ac1aa2dc48616c4c24d236a8e8b4900f9382bec9b21907133f6}
|
||||
x{b98f676715d14957248d0738e81e5d5f5359391181e0f573580539751f3d2311264aa8649eea66bc7016413e69ca7d01}
|
||||
x{ac77a4b3a57b754a63d7ae75bc916e0750fdbaa01115f038c7c60f621dc6b0fc30d7e5eea1f0d0a533c90615bbe4429d}
|
||||
x{9561be8f41acdee26b2d35c8812f2265a7e96f2964d90d1c4c26b057381d4f5406891c45c86c27ba1313e2d0938dcefe}
|
||||
x{a61cf69326c454b9f25b54d47f5f7209649992124966b2decdb201e4fd469200a91ac95c8d606e856b02cc01553d806a}
|
||||
x{8f9fb79917775751341b7c96d5325df771b9450b9e1a82d05a3674586f8a374fc4eeb7e2f176b96f18144f8ce6104723}
|
||||
x{8830d4880c14d6ec69305f09d0b7f5d138efc37a1f8fe3d916f51c96feb6c4d6ef51e1a4d574d6f06b0a5c41ddc8b364}
|
||||
x{ab109b1ae29d1687ebdd2d1d2c59d3196ea2afe222466b31ad4242f94a040c81e06e2175ab6f4f75f4738f8d7083e551}
|
||||
x{92b58f175d394c5e5ef3bca7c1f63b53e6f5443572194b7122b6484db96605141c0fc8ca0a670f553c61f58af0f58ae3}
|
||||
x{a3ae85c74796adfa4efdecdd39e014bfa26e69c9f14f69e0383313c7fa99768788037d64bb34b13826ab5a969c43b334}
|
||||
x{b49f0e0bc429eb0016d2d203fb470016cfdcfddc30fb7c7c4bd6f10b77731f8bb2b91a5dfad9200b96a1201ed0b4754b}
|
||||
x{a82a80e0e24d94c5cd6c66d0a8a937aa6f447678b2015f56d8123397f0165456e7000ba51501595a34203a9cbdd88077}
|
||||
x{a52cd7f09adb8f5bf2fe6a3d206f795dd3d2fbf8c50ca54203c5cc04e9af5c78ea72cf0b2f5cc9f40e1ca9e995ade465}
|
||||
x{b271b9a754c2cab8cadb0c2084c525ae4321d4a4200110152189b6fe9537156cbed646816c5a3b8458c8f879bdc2a2e3}
|
||||
x{b09b2fa0f1f5ba3857c8be27197eb3349486c6a9b9e878e2cb6036e79ff8c7463983d73d28d8e9b0f119e7a3fb494e73}
|
||||
x{b9adba35b8a1a01f5f6f6daa26e3bfbe9793b8402eb5e3e2aeccfcbdb597c0636ef8d4bf2c8713f5cdaa1f6432e5dc2b}
|
||||
x{8de96521d0ec24ec97e69da3996389c60c782461a894a67b09562bd0fe2416e1d3b83c241dff07fba400d0def39dfe0a}
|
||||
x{991ac0813bdd9a59ce2322a90da2511d511a12855b09df44555cf43b48296fa9869ef9df66f359179c706ea2e2a1977c}
|
||||
x{978eaadba569a36fa8f5cc0532803b76432d51b26bfb2f3eb1841db325ffbf4f1f72be2d478dead2b79677cffe1331d4}
|
||||
x{b4e52c231a548b29f496e4589afd554dba83b5db9565091eea0c4c79a10163181be836e15070b88c11ce306e8da2b356}
|
||||
x{b928dd2f764ff18bd663ee455af3ed5518088a780fd3486535eaffbf5f55979ac115ba2f745fff6438be6623366c5663}
|
||||
x{ae48e5fb169ac93073b1b36eb20a93fdf5d48f6ad8364a441b3dcbdf5761b5caf84176017e879bd2cc6e0efbe0dece21}
|
||||
x{a4f81f4f3a77a94d3c24ac297d376418a114ea16771ba1b9abac90d6a048c3ce4ba67a724dbd9fc84d941838ec946aa2}
|
||||
x{aad763ee3c5bb1272c24449f6458554039e3370234542b7131dc44c0b1f0f9dd18890b7048e690cd208ad5e066544833}
|
||||
x{b05ef4dd1a820b49d0594240e906bca9e716cd4bf6d45a51d5d571ed205e39b6501930782cd8573d51963d5a0401ea5b}
|
||||
x{a027e8dc718735f9acb9b2f06fc74052bdfd1f2b7ccbf181de1ebf7080e7bd35b7b8fffc825e7f6fe7aa75a814697d3e}
|
||||
x{b07c797102e4f17ac8c33dd40081cd2a502ee2e4bce02bcf4eccd073c51d7db0ef4cccf83de1b7adb864cd38f92e8903}
|
||||
x{98d211310a79d0da3594e88835e5b8cf944c61b1c4199b56af9d703451a21e55c38ba60e9cf566d677437c65d8fb026b}
|
||||
x{92e5e8bbe9ffaf880adc98a42d3e41249b789c94551ffb380620da4cea22b163ea9ba8cbdb393e7dbbbc9553b85f4445}
|
||||
x{a89604f3c9920aaaab0a40a059e621e42fec8902fb15f7e3fc24bad435386eaffcda79e94f52daf9b37058d7eb6af895}
|
||||
x{9372aa0f3f96d683d81ce18233c326ddebca93e6f29a9fce651b1cae20410c1e93e54990af18bb55cc0b97dd3d4ae26d}
|
||||
x{a9c4b9b1ff3b74ea6de69a396be9511a715c8ff87a9b33e0e74f99cea0d823eb907cd127ec06cdfdada16105cd973163}
|
||||
x{a10c5483b6877478a90de5cb4fd2f23da77fca45cb6b53a8c2559b4e310116ff4feea80f308bb296d3e8aa5b00f1c40d}
|
||||
x{8148b79dc931b103ac4a15ba1d613e8ff3b54941708c78bfdb7d8748c6cef01949e09d6a67488f7c12801f0c02b713ed}
|
||||
x{a2e4657128e1bee011fee679b7fe7515335766ab7f635bea59b820de972a24dd3eb3829c875884143f223c03cd18c8d9}
|
||||
x{88e8f1442b2f54fb6e882b71168dbfcfae30f73b422215d7cfac80e87ca87da2a235c71f0965d5428c3654a7cfb79235}
|
||||
x{af992a54c30f72966ff2b5fabb01219812b189d501ad7d5f6e1d89b167f6500b1908b995bb1d96ed27ed74fed800b150}
|
||||
x{99fd4146e659a523b7f3be89e6225849a51377ea49d8fe12b39b39ab926ba59f8176c6fbb121a6aaf4b47a4f4a9df89c}
|
||||
x{8561e48d685afd45b2d0f6e7944c9cb87f3d3f7759cf2d40a9a67fa202db25dffe1380ff9028c6692c14b05fca52bd65}
|
||||
x{93467762e27dd2647b83360aeb0b53b27ad1a49262191a83143e109519414f6e783109362d1f6f6c062f633c4311e2e7}
|
||||
x{b2e9357b2a7e6dbc0168b7f5035e9c3c5f49f47702dddd3e6b08e235086780119a04006909aba277c54fa33768be7585}
|
||||
x{b9820304d2fb65fa993e9316d434c21d4660e3b47db4bdcb4bc6e24dc11b1cd6e4c79d5ee66cf12aa9477d9d903434b2}
|
||||
x{849cde94b4bc6c895ed590db92577a454577fcb2492aec26ca4df48a650b6252a69e7f43ed82ca920a81703e9f2f40a4}
|
||||
x{8f2139e3eda2efbf6466768d5e16679e9cde6607fb15cdb1b91f437f232d830717cffd60da4062c3b5eb382de8330fd1}
|
||||
x{abe47bb7af31ec2bb434ac94bdf514e21c8620eed7943545b30f4c1fe851f9413464550f301ca93ceeff925869cbb18a}
|
||||
x{8130ffad0227ccdf49b6fc98d818baed9032168ad55b2f888af636a7cad52a0411bd8d699c78f63ee3288140759547af}
|
||||
x{aa1760f885bea6903efa5d557a9d5c9f4cb54ff34129ead9e9faa07c0a41d066b667244229627ba5797feb984537f8df}
|
||||
x{98403382601e7766acff837ada3342b15b744a8623ba6e5a55cf8df199ba0c2cd5cc5fd1aa319dff980b11bc6a199d6e}
|
||||
x{b8af58fb6b4f548ff6918c42dd69608b9136a8909edd73fcd2cb994a45a627c6dc26793b7c69262f3e8892d3bf2eefff}
|
||||
x{b2e385e6ee0bcd709dde65cf095f2d9c36f315ff06e83d9597df934a1d7eea5fcad77de858f3ab094772800d491e3819}
|
||||
x{8c10a30693b4b1b752ae0aaca5c6dc656c871085701a8cf68c5c7958dbb896e8798b616fa0fbbeb7a2932adbe0f308d4}
|
||||
x{91b0e15e00aa788d83be05ead90be662bfd17cf16cd5da705d81b3acaa7d478a3bd349552c1429652a64e3967833ae62}
|
||||
x{8ddfe0d8e41c12332f7c5e4310899d9b1be138c80ccfdeadccaf5e74077e13aad63f4bd508290ded0e2c40c6628ec035}
|
||||
x{94c43da38a8ed19392a8662d5ef7c8358eadcdd4a566a61f6a4fdc57cc3aac58d8ad2c4e61f283fef9ab5aea324c080c}
|
||||
x{815fbf4029d334d63bd8f667a6684004714415fee64ca97c60b850b188ea3360d17299d9ff6a332f89ec561c179167e8}
|
||||
x{89873aedf223606eb09afb13c34b1b0ba65532aa4e9864cb588601fa42d69250546214b2498e5047a6fed4e09a0e36a4}
|
||||
x{82a2bb33c62a75abd2ed172d14abc0ef5637b14331c41b6f49b42c2297feb277566975a8f2c720b04474c221648dd95b}
|
||||
x{a46d8964d9854114e82f0d98562e7f3b0b0f38037f9050a47645cece99f75d9cdafb304a8bf7dcc1049ead05a6086eee}
|
||||
x{aece4f7f8c68a959f88128502115201de816f748f8f4f83d406f73806821aa43d204d2d02b487c44266f1559e7eddc69}
|
||||
x{a999ffbea55a6ce252fc4661c337adc2b5675f999351071e6198570d5a7e7e5855ce0312685d691427cc4a230e1aa031}
|
||||
x{b57e85d1390f113c620a772075d6edebf2f2379c7a3bcd469358c128b888f73c947d00f4054df5c2b220082eafd02ae1}
|
||||
x{994df161084d1ac510ae0996121c74ff8c16cf5bebaecbf21aa1da07eed0f602654adaba025636f0bd338e9bc218d942}
|
||||
x{9018e9e6318c824de62f2a3278ef214863b0c98e895e9ffbaefefdf56386c3e5c20f6d5236d4ff7709fd015e6abc3e96}
|
||||
x{a6f41705254ddf479c3d19d60b7800b091561bc7790aedd2d33fa0f41a8d5147c81ebc347f4f012aaf363b3187bff990}
|
||||
x{8fc374c056f5e726063f59e84f97b066af2e07e599d6e2e2593d8e31bf5665afdf3034be6a529ffc434e2b365b94fb01}
|
||||
x{b05b312f4dad2ffba9b50d651607cdd19c22f2eba0cc5384d2743faf74f0f081533a50f7230756bd5638a8570fe73d56}
|
||||
x{a96f25869f617c81188dda1b4d9422dc2a8ded653de0e1879f3e5534b582fd332cdeb13f6d887d9b28f653ab6ac09f88}
|
||||
x{8f6c0bbc567c089a3b22a381d3e5f5915421f27563b7ac51318b9612515ce0d3224d40b3388983afe2c92d2da3844db3}
|
||||
x{b2779d398c462262fb1b5ecb4ebc50d00c44337e6ed20210ada4b8b6321b99ef262455e50647a61452aa2678e64def15}
|
||||
x{85ba9c1a72a420f960a443e7724835e08023581226ee4912a6a1876f40944c7262f92e3bbe66796dcf9c706986917671}
|
||||
x{af01794226c596db4f502475eca86f399df28b1344af6a54b1faba31158702d56c57f1b35a9909f2458734f58c04ffd4}
|
||||
x{8918c724fd6a5530e76d3518e5ab73a7144685769b1553861e0441cba0b0c307a68429923cb7c3cdc577e3dd9e0f11de}
|
||||
x{b6bd93d8442d05d514a5cecd64efd5bc5571221769c1a76177376e2e0d6504c7c8196e300bdbdd38ab8514e0423c1dec}
|
||||
x{b7a6125a2ec2dfe7fe6731bdb7d4d604c473a9f74abe11866f7cb20ca4fe11157d379ed3577b35d96839e95eff110fbe}
|
||||
x{85960eb8968b9a267f65f4f7b2ee1e9ed676e5815615aa4b29abb6bccc669c0232401e529a1597b67b0cfd310e6ca5db}
|
||||
x{a02101be2ec64317b52358933f7b68f0d49df19404f6dc035176d3313eaa5253584d023c43eee1e8e2e627b253fb5634}
|
||||
x{8baede2de9d880a5e9e4f3c35c181a1fdc68867fb432ffb53b530a29daf52d844389cbe3d7ae2557ee00feba9ee2d7e3}
|
||||
x{8f1eee175b515d5c4e8784a03c7192efcf93588d476eacbee95d01f3c7cba46be8279ba65e74eb7e8983383908b07cd7}
|
||||
x{a24b3d111b7ec72a3281402e9d1be91b51f8e71d80d27ae62e6c75e5c8bd3a860f45de65e9bee657d400b78e7a2c5e16}
|
||||
x{85d13e876e384ba0c55f72bf391ccf65248736d0a707e143d65146d439e945abd0133812319626c9e8092f5fefd54c45}
|
||||
x{a0deed3a9b3cbd8ea5ea6497ecd3afd02616b953e33cbe8b117a4add6cf8cc4398268eec7e9e0bd91899472410a452ef}
|
||||
x{a149ae720e47fbcbddde029074ef65969e587d09a8d6cd3aedeb63a46b54bab17b84216feabdd3bb81341c6a83a243c7}
|
||||
x{85913becf48a087fc75613d24b332ccfda08abb67c0b8bd9bcbf5f0a8ab1bf6285c68d89fa80f6ec18c666316f19088b}
|
||||
x{85685bbb5bb114db0d337bfe51089039749e7afcb7099b6d04e668e10e52d29256e950532b4684333dda9a094c6fc7e8}
|
||||
x{a7327cb5024ea8438403f2836ba21bc84460ec2f267d399e0e0fd07ff9344baf689744ecfcb90ca9dfd95b157ffdf29d}
|
||||
x{a3740c34b3dc44df50ac1fe8916a592e8cc86fea02ae29ef53632671b69bd9ee3c6d8b9aed87d4b1bbcb9457486bbfaa}
|
||||
x{8d2c4c61467fde9a45d1adbe02a8c7d2e925e8f6f126be1b91fae1d8578311740678ae9e280c79620d08fcd879159ccf}
|
||||
x{903f21545ef331d5c312801b78b8675fbf093ce8d3e4684da155f80f2153bde840f60436ea506e1d07bf5cf8cbb566b2}
|
||||
x{a2ab1ea627cf7b2b3e3f4a358719d5696e9917b76898beb0b0519962cc34cf222b200367ecff032052023b0d5326e5a4}
|
||||
x{b79fb683f4aa467dd1859468efbf53214cc9301f38958daf8c6f313274cc70a532a167cf24d7d023eb66cfeacd6b553d}
|
||||
x{b202b37b8f801d67896cb60227a72138918488a46034556c90d00cccdc46b86e4d77adf3991e222f4d383f0e0cfec46d}
|
||||
x{a721aab3a83aa009cc22fde90c0a5f1fcb42712a062a68628ee402399a81c4c3bec1a58ab4d1a37a4d4befbc275848af}
|
||||
x{8fb335baabc4d561e133b874c98bbeb8b1787bd7b44fafc9dbd02c85d98db6bc03f439d285c7fe17c2c751268e651255}
|
||||
x{aabc892d3f6b3dbf04b8f1f38215bd58f23f117e6643c47ccff6803fde56f0c950a5885d7e2ce97fdaf01a1ef32ffd9d}
|
||||
x{87a0549679757add0f06d239aa760274c57ccfbf30e722d8a6b33c76ff5576d354f7a54a53073cc3babce0b0465eef3a}
|
||||
x{99e84647be315371ee2714fd2524370daedf5e64c343a31cf35d05f0737f73ca97ac1645d17780916c73317cfb7ecce3}
|
||||
x{ae30f745530dbc0096e0dbdf8b7547499eab8f68c5ffefa05ebf6b735b3f94df7161c09360165459d939f562961a7af0}
|
||||
x{b3ddcfb849a79096763ba2abe2c51b4b0666d548d2c19be8042da0c02956a5b13fd4166ef3002aaf63e16f18ca27e777}
|
||||
x{b7cd98db331a01c52012560297ea9b6a208bf7734164c35777db809aa1e987b5c1ae20bf62e68a6f8160f6606db25bb7}
|
||||
x{a72480094bb69733ed322482458f26732449ec5520b28c70543bfb0e291aa6b2c454b9a67321af82a5aa614f3110a8d8}
|
||||
x{a52162089b34711d405613a42e715e1f06f410f9e1824d91c10db392db200fae8771480ea75b65e43752f5c38f9325cc}
|
||||
x{93869a5603e08ed1431cc308a64a094c2bd24f28bf1e8ebdb667e4da4af58488aaae3cb078b0d1e3ea92e1cecd902f93}
|
||||
x{a6e3a7e4aa049bad205ea2d84f10e1ff096796e82242cbb06b8657bee144d8daa2d5ae23713df4616221a016fd269578}
|
||||
x{8ef617adab8dda4770b870d42d3f3ce503665cbb55ab603f38e9cec0cad1e2f7f322d60a42dd2416a21c783a280a0e4f}
|
||||
x{83f5fe871d91c771d8ad09d26ee4617220721cb4f2324d8b24ef21bc9f5f059949a94d2cb15d3011b86178a4eb52e88d}
|
||||
x{8d528528af05691c4f5085aa3747fde2ba2716e5a79e050765e83c8e52927f32033b994a45b5de5ae310e055dee1dafb}
|
||||
x{a6ddede616eb02303bbc8569d569082872967c7bc0c97462ebd871cca264cba03f114780e1436674022f11da754ec23f}
|
||||
x{aae1a58b985833f827df87146e157900943c16c89d15451f464e17c480b8949228f9ee9117768f92042dfca3bc2e2290}
|
||||
x{b74e17e474fee881d4a2aa803cb0018e5eb94d0d751ec04f2f5235a85c46445c94f21f314fdd6f6b6b862c8387976faa}
|
||||
x{91d1bc79e3abe5156a7fcef084136622198a8bc4fc5fcb4d384a3c3089bae93ed80349e0220f168ede6df2992674b4ec}
|
||||
x{95c1d6d602a03b1fe2eb36308cb939f7093bb9065a1441dcfe6cbdb6fd0051f1a58906829334dc4675c96a9835b23ba8}
|
||||
x{ae07d4db6f10df60bb09d3c187c75953bdd4e7a492b3be74f753074d330b52bfb2f3118ba2f2561d90850afec527306c}
|
||||
x{af93966afc0ba0acd2b91a254222e672dcf204fae9bf405de574f8c1ead72577016ecc5d45ddd1a5c67fa1bcf0e6f765}
|
||||
x{a51adfff1f07ec1b2ba7e7352d262f54bc553510e4b6066b683aafc2748958d4b7a2016902ea8482889975ed61d5c85a}
|
||||
x{a20433f93219eb9976803b7bbae5247c641bcd11821d5eaa7ae3a088faeaf8356f05c9116f28c78ef11cde111f1c1be1}
|
||||
x{b6e6a8bbcba88ce35a38be0d6bacfa32cda83937cd68d504afb087cf02ebb8882ecc1db14a5a903d1abc3db589963d12}
|
||||
x{b8adc04ea1f6ab4bacebbe38e5674d3cdee56f097455b0e94e02ca08f667af82379f8798c5f026b8c5e361c9926a3c3b}
|
||||
x{84be6bbd912f3eb274c9fd12a15dfaa0a908eaef9a849b2aed2a620af2f11ccbf880d419a89e8f67bb81efce710afca0}
|
||||
x{ac4e4d3ec168e14985f73c7b30469473a6e0c89db0f6649435aaff4267fc1ad1989de930ae843521253909d1032fb6be}
|
||||
x{a6cb5e28f19b8a235f9d3e2097528650fb629fab591f2a5d32793fe0ca0b26803a4a284aa132478272ce4c393938ddb4}
|
||||
x{acef262359340b6fc7104d2ad0f67b420f66cb1f8b51956257942a2a5b515db3c5b03a09c09bec9284af2ca4a73507b4}
|
||||
x{ac3f31a5c3ad602dceb6fe7a1a64e167b268bb8493ede809938e2213b3b1608e679918b37a069499f95596ee1735778c}
|
||||
x{8b774778623dcc4d48a049d75c9d42ca7b4a66f79583377fa5ae59c2a3719a97911f55c1768ed655fbbbd16540ea6095}
|
||||
x{a8ad6c5a569b856997ef600b1b1728e4ad9ab8606d90619e2fbc336d4562b9d38498f69556e651b3cba7d61a69e48eb5}
|
||||
x{abd6f511bf89d9c18e7fa0cf6c8aa0f028c31ff78b5d980136e1c528d593d259f1d26ae4c79576a47af8996396b76094}
|
||||
x{a4479f00869f56b0b389d79ab9e23ec2cae1460593f6847b3f2bf5415929db91a0b94aefdf093c99870b1f66c6a0ae64}
|
||||
x{a03f2529e611683bfa7977b08f27c9f5b1eb962acdaaa8c72933ba22376cf461a6fde95e4102a25908ce056f14ddf525}
|
||||
x{a1b6f7748d7c2f7e767773316c7f4d489bd5b793cb30fd750f2a33a02b6db34f64c7a4180a05ac6fef049392cf87e70e}
|
||||
x{93528f173f2dafe0114d688d33c4eb6b33753fb53c54f50c3c7b5990d873593dd6faa65906f1df7c7eb1bc1f6ddc21f7}
|
||||
x{ad8996fb3c231514562b9926628906edf4dc6fdc714d35a8dece3a235c3f49637534166d1ab0715fd7bfc22ec5d17e26}
|
||||
x{b6e5ed2b40848c59db54850ca64971759de81d0601a56d552060f1a6d98305ee97667cefacead2c3dccbcc58b75b1c87}
|
||||
x{83fb0b6260971d174b14377e999617ab4d2621982a3d26555c27520ff8439e2b3585d12a61f34e1bbaf93779b89c2907}
|
||||
x{8b6cdaaf5946847b1e7b7c6d2d5fa8ea1e6c2fc9dd21641b936fbf1b32121fb3bbf65dcba0df83b822e370c9c35a9a5f}
|
||||
x{872eed4104bddf37251a144cf766ba3bc01bd27904b320e42b6122831087a7da0c5a5cf8dc6c00a4c8631f7a91dd3fa4}
|
||||
x{919532809f2e0c285fbb90a52dc9e3d5004eacdc71622bcf8144376c0a63b995a2531ca0d18a6e0ca4df50044626f00c}
|
||||
x{8f1d94624744ba2b92ef07663324c7784081e22911de67b1dd1780942c9bde1dd9667914e749829d76e87a1e86170485}
|
||||
x{94a257f057123beaab8baacf6d3fbbd932ab05c84540273f3ea69633fa9cefe0cebf778da45661d9dd2f617dce9fb960}
|
||||
x{8a33dbe5e72280da6e8d781246af15e92ebcdaa0add650bc0c13535537efe9ca4d51a1a083c952427d77f70954a9430c}
|
||||
x{8d78bcf42dec8ef23bd0fdc515115cef37a89d3d2f5ac0723374c4076a3718600b8505eae1faaf854728ca398dfb1649}
|
||||
x{952601b96441c611dbccaa960cd3657de437e4ef6a0458e4078c4ca45c90a0c90eab2189c6512691bb615ede1a0d835d}
|
||||
x{b5e65e21d0b97ee6fbf858e270bc51d3cf2a95e6364b94eba8d9b5a5817dd345aca03b631b9d30c3fa018c482184303d}
|
||||
x{938af819a7f9662a49dd1353191b43f7c3ed87ccc2b4472dba0f73fd9117177891d6fdd754605a0a98fc9d93b3132d5c}
|
||||
x{a83a552c4b56d70f98d95c68c022959b1f0688df8d13631ba960fc0052b7db74a58a5e56e7389b41c05e0bc7d2ac9ba9}
|
||||
x{ab68cb8be7456a2086cd3695e1bda4135da91894d2f9b49560c39a9ae07f7d91ac2d453c4be9497a7b8631ba83aa9cc6}
|
||||
x{a5e60edcf107dff7d57e51c250862b3eb8c106e40d452a95246f2be08d163a333d626c377d1945cbd514733b5421bfed}
|
||||
x{a72f4482408250365ca1648b6c9a1a6e0adde5bfc1e47933bb93bb72b4418e7782a13abfa550287aaa9137d44ca1d17e}
|
||||
x{a3e0045f65097ab4951747733730d233df35935a08b8934148846c4aa57559c0cbd74de20dad1ebfc6fee1b26b94b868}
|
||||
x{a611d5c5c00db0c6c98c41c74f5f4a6be5523e39a2ec3b172e4b6f142100f5cd700d7eb21d432c4cf3b8dea3fb981cdc}
|
||||
x{8ed47f35a890e5238ae1445fb519646c17a17187370c10c267723cb3c95613da9bc4c9d3fa5dcd0de052716b2f3773a9}
|
||||
x{86b93b4cdc3b3186d8ffcf7c75472b41176fccf3845d83c5e0172bcf6d04443ec644f8916c39d07e6a3f3e947212fe7d}
|
||||
x{8290d28317930e75ce905397d9b203afd6bdb8daac8f654317c7fde3b61f36e67e517ffb43db58cb09fc67f571270119}
|
||||
x{b34fbdd89c0fe771088ce52e16e1a166cabd4643e8848560f376c56f8265e478998c5dc236fd693509bf1615bff5495d}
|
||||
x{b7c3cf81dbec8f4b430a6ce91006b90b8e90d04f5c299161e2db4caadede926ca3a082224342d37120ef42254eabb3b3}
|
||||
x{a072b63854a4c2c6d003d79fd959ff4e6d2fa22d90bd87de6a08b568714caa6b9ee1a43766fb813e01882a9a48086758}
|
||||
x{b319caf57dd380fbdc537ae09f5f59f9d30f3607d9ef7410b2c2d8d88ff8e64e66154c363299c67a8526b5f07d507e2e}
|
||||
x{878fb941a76dce335d77daba3bc41cd9d1b145c4df980e5be9868b37d3c60421e3509d46ed0ff3ea01e8f6b717996774}
|
||||
x{8d2262fa7cfa4fb5c1b5cb6daeadabb220f10171e4c041de13ad9b5aba30599ba9e7f0bf2eb19a446a3a6b0fe6720fcd}
|
||||
x{b249b90858c33e11fa84aa6f412986a886743f7a8a3b81d59c752baec291ad58d9d592aeeb26a00103b8bac4f882eac8}
|
||||
x{b02aa595959b64b09da7de5ffedd316a98fa7e913d442e4bcdc08a584302ebef651c22a5c06dfb891504c53ceb15e5ec}
|
||||
x{9077c6fa2e76347814dbb1c3e9291b4536a5d23441db87ebfcf453b2a07cecdd7a8aed655a71c28112c826ef146a5b85}
|
||||
x{8368584e6e9fd52e8dd9bfdb58087e380b99e9e8cbc551dd40d6d6e4e5207d9384ed6295e03704c00a874ec280b6cf6f}
|
||||
x{b34d3cc4d5cd507fbcbabd2c808c068ef41d3b8efaf7e5302ead08301b4f79324f028968dca7e0a56d628718ff164c83}
|
||||
x{ab9ae1b9172c4d067445552f7da039141ef72ad4fdd82462182d7daad8f6fd3789d2d40c8174dda3fe196f8665c48f64}
|
||||
x{b95ec7ef32d3b0ec97b28073cfc2eacdad7c4a063d5f31c791169bbff0ec4496822624b67264002b1a2eba048c4fbd38}
|
||||
x{b2ed832b474cc84c4d9296bcef944a26a5eacbfbb411cf9834010d3e67127c36759a92f667b46078ffb9482fe5ba37bc}
|
||||
x{95004b20bceeaf744a40289440c1145b4e8d4f7f40460b38cfe272d49b2abcf99880573ea0dd9defd4991a0620d9e528}
|
||||
x{90a921f83766c423cfd9ef04cc3faf208dad5d52b77af9678842b8db2894c33d2d8962edfe2c6e8b477dd6a89223fb61}
|
||||
x{986217666c2fe4711465a2da8daa7d6ee44e4cf32b63a09aba26204b371f296b086f31701e114a3233799b8d2052d7f8}
|
||||
x{88a94b40813d23933c86e6ebbaf36531c7de89fbc345d7593a62c355aedb2ac504ed1a58aa735c2fabf82e73bba87679}
|
||||
x{8441f6b6db07ceeb3cda0d8649b557e082fdfd610a9760a811d0302bc9da6c3107d8a22a0c752fa20ef82054017c20e1}
|
||||
x{854ad0cfac2b94faac229ec7792123fc54377e0d285570ef1435aec0e72d072da978c00d453975415550ab52e8284501}
|
||||
x{b0ad4b51e7c698f77828d3c034fd9b177a877510d7552025fd3cd1c68e405dba23a7a72d921c4798a6cc237887baf967}
|
||||
x{a59e691f1ae2265788523bb6ac5cae309420caaa54d4feaffa6882c1542fdaba817f497c5a8e30bfeaea3bc3a6ba4b42}
|
||||
x{841fdbbdfa848144fc7b29520199a00c3398ef3d78ac67491a9c0f933eee22059f9a0446fa599df627336b1fb84b0145}
|
||||
x{89a8c1e13030ff719ca22c939f4c84b1bdcf0ed11b6d0ff0deb1c3bf9c62640f80c96362e4e88362f7f7d69de831f523}
|
||||
x{88b306b8323a1ccd933782e31e94ec070117a02a8f8349b445da66b33d1dca77e23256644904416751136bed9adc0d45}
|
||||
x{a77b375d16d85257c5f4b996f5514ffa8a5ca31454129d2a25b4bfcf4309f27c97a71e6c33ec7fb9cc57914b3b7baca9}
|
||||
x{a8098c4186848d9d9ba4a4b1af79decdafacdfea7b5cbfd3536aee6ed67653c6129557836252b22421f61b66c84b2e9d}
|
||||
x{912569e76a70ee20160774d2956b70965689d19c8d64941313fcb0d61f35b10648860f85be7a81e90ef6975730f2f636}
|
||||
x{b144b4047dd0ece9b3619bc04e7c971aa608d9143608a49c46a293df2bf2c30facfe4d39675fe23f5b7fc274d07f1b17}
|
||||
x{89489bc8c8ef1224ed29d5f82370c6c3fef80ea23809673414309a1f4b2941acb049a0648c34cf0740f682624a660c3b}
|
||||
x{b72f1a424b0c3609531bb9f5299ee2120066dd5561e42a3beb526f8dd32e89cfc51937fcc668834414b7c16a1516510d}
|
||||
x{8a462a5dfe9b78315fb9945fb6717a27849785d98744d3bf798697823e1f8e6acad5581ed337d4d9e212f9dd96d94ae7}
|
||||
x{a4d046c2d04306fba6c56bf0c9f546ef1a0b5c5762484c5de70e42d1b6a30d39cc80b22f66933bf3534b1d26fb6cb7eb}
|
||||
x{ad8903641d07eb96663b0a2fbac3115127b24945a138ea6617e14545cec689dfd162422818cc4050a23a8df42cb08ce9}
|
||||
x{b50cb2de4074397cc88600126c50da4bb2acbb02ef90bb3b370e1828c39fd78c17902818556e1689e5a7bca50237aafb}
|
||||
x{8f5fb00cd6e476bed5b5562e934383cfc2f1a2b799e9c1f3dc2e0b0ccacee4734a31ff2d9a986e7c0251778e41bb99df}
|
||||
x{aae8828201155e602880a4a9137d3d44c01d32b2374e4223576e8fa4ec56411aded934c2f3121526fe2d834e37c713d4}
|
||||
x{8a074eb84f1ae6d049947cd6dc6bbbbada2aa4209ffc167fad467b44ba3926f3b6ddacae7186c9e155e233226c7fd3e0}
|
||||
x{a85635c3cb2397e961c821cad4a9945bbbbf53c20721f9f1dba9a8c616b2819625767884e22757c29507f0ed73304c43}
|
||||
x{809ac8f6102f411e5ace89bafee2b73c8a2f5340d7677c0877eb9de7b7d522d77b79499bb27bcdec06a2434ade31d40a}
|
||||
x{82134713d5873008449747fb04026b02790c89d9656f2d2b3c22fcdb4e9bf1b328e4051200afd86bf2c7ceda424dc447}
|
||||
x{96a195a8bc8e61dd270c9e1e2b2ac60ffcce8156b11cb2ec45229fa3151a6f8c1a796a752312ecebd5c5bafa2ab4991e}
|
||||
x{89192f77e8caa08c0a976650701206da423fd3e4adf4c11c0b12cf693966e2d32a06bec27de11ef76cb57b1abee47a12}
|
||||
x{89e7e76e55b1b3bde410d10c8c32d0f10c63e1284d4636f5ba73a285abcc9def139c3e419ddce83ea07a9f825b441523}
|
||||
x{97d8551ed66159c461b1679ae0ae0bdc34f306f4cad6cb39b77999f85ad976f2ee2218f777e4e1368133ab31604df540}
|
||||
x{941b0de89934fde7ad4dd6ee46bb1ac0d1228649469969fa9e016a51fe63f3a687b536f53eb70e867e11b306b66954f9}
|
||||
x{8ad57d3d490a57d2cbada20ec81812c429daf3ae6ed372276c1c527dce09737ef4ba3bec464c44165594c8e552b95f55}
|
||||
x{a6cd2543e60f86f7c976df845ca30debc686413418d559162597bf34e44952243906f249939d06d878e1d942500a7c4d}
|
||||
x{b2e066f07c6cfd5e045f94f39f1e040ca09cae4b1b8e9cae55a57ca85301787e772f51b15000fbbfca19b1d28341eeab}
|
||||
x{88242a0a598559686228cca4b72b47d503276c6d3f9270d943e43f6652ac600d91a6245ae3ce365b20d8121ffcd2c7eb}
|
||||
x{b47776fda2429344019841061308ae5cc3e39e55355b4fa2bab80a79be35250cf38127be2d3f93eca196ef8bfa3049f4}
|
||||
x{929c6bc299a6b479b7a5ea1a2c73cf7575161f184fa1fa536fed71fce16cc0127df765c9c3d02d5df15442b50e4d7c81}
|
||||
x{87fd7e06cbdc2e1ffc1a0cf328870fa73cc1df6d4562508efbdd0d71d97866d8890f085e02a8845c8be69840e73c0698}
|
||||
x{855a53160cd2baff4f69b01af39a8e6486aef4c8fba5b23fa958f8c4ae9a4779e3a171c35ba28a23b63d5a746e0def27}
|
||||
x{b4e1464b63413c94f636d648ec6e9dabd357c23d7a37c9fcc3bedbbde7a94249c6dec2192702ced872856c92cc829da2}
|
||||
x{aaaaa6549f519e43b3935cc1d9edcac6a32209ec8f9e9eb8598e7ad1448a4504d204175eda00d2a8bbeb736171389f2a}
|
||||
x{8a6205892d6986bcdc1c3f8deb7f7301cb9be41a131c7c046bd2515e3b36f3253fdfc8609c80478dcc51a7b66b279a45}
|
||||
x{b20d4402ef47455ba7d8f4f9bcf9a7c0d402396e6aaa14d3b1a6f1f5d0ef6705ba9dca6538d0e9fdacde8a5e252c786c}
|
||||
x{a30880c55a04b15d14381001ec06340bf8d60f6c952ec50dcdd8222bb393f88f635dc85d99384a597eebde0693424d47}
|
||||
x{b729dce9e0bf10d615d74931773c3dd81ec38050f597f7d6005def587526d4c587d7767b30f4108d83342dfff313c74f}
|
||||
x{a1cced77186993b4215c66ddcb187e397e10a8ee9666986c6ef2f41398bedfed12c087430d81f4a608da46d275b9bc04}
|
||||
x{862144b431ab9de9c4ceaa784858a2c6788b3758866a228b8e2671433bc56ebe9918a08a3be11d05a7ff9fc64ca882e7}
|
||||
x{b4205cbe870360c5452b2efe87efe9b4aacb4f7edbb88ff2e414931a8613d686608b583fa9bc053ce96bb9930d4a4e8d}
|
||||
x{8063a97bae4b2025eef8522d73a5e3932140a1afff478765dc1279b2bb8133d4bfeb256861afb213f2ace1d885b514cb}
|
||||
x{a4f78536213b3cfdf5ce14fc845cb0a06726f80726740319c812c938417ce6346ca2cc055e2735eeae9b8cd1aafdbe9e}
|
||||
x{a82edc8ff174d91a5c195a778aa265f35a4b7adb596caeddb566d86b15b4ad446ebc4a7c34889d0f69e6b820ae5ee2d1}
|
||||
x{85ff418bd6582cd00828c5cc5fabbe68927d8cff526f435bdac63071707dc2f6cf0d4f916f2e52f8a341ad8e3725cf67}
|
||||
x{ace11bad2e6d2ad1cf84b01c3f194c23d5b8e96840e76444f42a063ef357a3f5376e3ddd3b2031c99400c2f82afdaedb}
|
||||
x{88eb0d46e735ddbdccc6d3763db910420a2c864895f03f3537dfe49aff54784b181d2d02ff37165b29eea18b529d8f82}
|
||||
x{b904f873c0cb532c4633dace5b389ecca9513ec84562ea714d52e1d359c97c567c0267c4c747f060e5f6e3e2fa0f2c13}
|
||||
x{b63791ae81e8abf907f7a6a1091d72e37b655cf1830a6a0bc634049c6f9f4afb597c4389b9636c7fe5e8db52867b26fa}
|
||||
x{b3294d1fc9c45bb0f080db57cb628faf8e2684876c853390a548ee78878697030c932b9e5b5f77ba54cdc4162b439400}
|
||||
x{a38e9faa508b2feb73b4040a0d79acf3bf39bc5a62ef30bbe43c8073a98f12ff9e286ff1490c8c9aed3faac16957b7aa}
|
||||
x{ada99e8309ed1d1fa2621693c8c9e5d618218dde92888a3aeaa0692754e7dd94a4268afbb75550c2dfeaf5764adfc0c9}
|
||||
x{9232ab744f72c5ae7fc674890d07027dc5541eaaf8dc1edc8d8fb4d5c763053a53697d9e5100ad9afa1e9fc888cf1197}
|
||||
x{8b87270d542706c9d0db167db7302c5e3fa81642f8bc707eae2bbbbf731b3948dad68cf0dd1c1d69f61a911d1f8e87bb}
|
||||
x{a9664311d8ac973f6ce364f7033c0d710a98df5ac6d7c3d1df70f78a33701bc0a9a3b2da1113e1667b89aad41c7d1b4e}
|
||||
x{a6d02f30da6b850da8377c718d2d8ca90d2f1d352edc0abc5c0af2435dd180be4d0e1cade63382c990b8ca930dccb1be}
|
||||
x{824c864ee1af1691d009e4c7d1d201da8a691e93b62523e22aca2e4b8a5d9502b6ff941851f8f46a203589e093539bab}
|
||||
x{9873aa35cbb7235aba6dfb17cf8e046b84824b4598acb8cf63a20d26cb242087db54aa6d44270e948fa6a4bb3b1a4aa5}
|
||||
x{929f1a544585afaa2df9f393129bdf3a0ad4e981146e9c9fd2ed89b1ca61e865c88e7347b07121684229e778b10be160}
|
||||
x{97952ed5cb54d0451e8cf08cfc29a423a33a1ad84f7e02b00cc5de88a27b23f77428e4c3a49a022617229952dd27ba6f}
|
||||
x{a49a6e47098ce9ed5d432aeed22a981c05dccda0eaeb25ddb2452d2c5c39f53f781b0840a894cf70804ed300e90c95b0}
|
||||
x{ac3d8d959683d6db8298d6437aa22378375c5b3a4fdb416925b71646e6f7b0087d0c6e65d4f9beb0ae72358e99c1f5fa}
|
||||
x{aaeae464badaba7da40bc59ac873e1f07fceedbcac915f33a94daaa72688c3c49e5717300abe2571446b010416b2dcd5}
|
||||
x{a2f6caa19c0a43d3d6a3d1af5e8bc33a0bb3a54b8f5f6d434bd9b3328cd3b6b148168e554a0af10f47d43943dfc6566b}
|
||||
x{85b48b545c089325b055d2b34666d091a07411272aa6ea074b550f9c9bffe118b1f2f9d4cb903e9caa39fe0cf1ffcfac}
|
||||
x{8db60a483dbadfd71f08f6460027f9dc608df180ccded4a2677e88aba24e72a80d55b783ce84aa787049dc1ca9a53512}
|
||||
x{b0888ba78b37c36f1c61064284aae6021722ae38ae8f64e6da2c3e13daa9396eb5520b910433d0ee25f36162a5d69ad6}
|
||||
x{8e6777565dd463b41aba4c7a63df9d1ae5b6b5b1d7d336f67e86fca8280bfc90c1d7e95ace60c34e6b3bf55d28bb5d2c}
|
||||
x{99275fbc4baac72896a20267af060f21ee65293b7cf8b27d6495d559886ca71a9572f6699e58b63ff2433d760ef2e31f}
|
||||
x{85b16af1b7c62f0beb9c801fd36731dde735c9ef6bcf97bd29dfddf2ec438cd5cb568d914c7701080a7434841ccb0f1e}
|
||||
x{a87a5cf9d7c130418cceb93f2b26747d3f70d8a6eb8ff0cec28ab969bc92addb4fc5dbcf5d18dbe21e150ec78a755e07}
|
||||
x{abcc8ccb7854b76b80a0e6e4d390df544ed8d09daff0818a71e8adc7f4b6f2267769017db965a404665032c46766040c}
|
||||
x{b90e7b9ca3237916f211c02cc1575d8b8df43313f54feae4c78944bca535ee95e37b63729910f9fc4dabb907f3e73acf}
|
||||
x{aa968ee64eedc74b51ef13248e6ad4ed8fb96eb5e499602889b971c17fdb126335f59f98952de0e5243a0b486e2d4e62}
|
||||
x{ac49aeaf558fcf8086def396c8db61cb80ad416a94af50a1b583c5814bc7d54bcaa72feae09a2e162ecb1d342608db10}
|
||||
x{87ef03700a561ad0299e32ae473c1d724a391e3523636e64c75d8676eb2856ce8189a9e0279922fdd7a9365c2a483e7f}
|
||||
x{b949a74107e0c6b93cfbbad5dd0a47f64364e5c7ecc55cca0fad5f85c4bbbac48555144b7f676603a5292fc1712c1bc0}
|
||||
x{869029064f1a86ed00ea442bbc5d330c7a0ae4a06b5595c9a5b57934f6876f3bb96d9dfaef1e926428d14e450624be57}
|
||||
x{8379963a7f188739e953a4e9799ab37d5c49e4b8f49dc9bcb686371219a04dfb6c55c441c59b2ad89d7145ab3dc08631}
|
||||
x{8460a57fed7db8691ed1cc69c66116e1544e164478613ade64eea6b3926c99011d2cf386e0d8bb1681ef9a5d556f3c88}
|
||||
x{8c9cb7d59ef8fe907074382c959b661665dfe9fe4fa328fc93752cc2cf80d431b8799868eaec777013e67966b37ee0f3}
|
||||
x{85e7cba0dc3614869ccccee0ccd782554ec3821a8d6056daf10285973bbf548f7c7120627d1f0edab7bb29cccd4fd35a}
|
||||
x{a2ed49318a58eaf3d2211f3c3573a522605481278c5d5aa06ae610928845f030b3455f8cff3cbe3afe08e8bcb5839b31}
|
||||
x{898c2de6094e5d40e725faa69caae6ae499f2ce0d13ae0fac39291869852d5f9711d447de374942fe7281030cf6a4cab}
|
||||
x{b59b4d2f3da26779b0c3c33493fd23d78d956e688eec9df7260e622e2228b6cf30b111088e6f1aec6e690a4ed80f086c}
|
||||
x{af9916b2d4c305532662819fdafb544f4d4f74a3bf5738cc31cbfc0018310f0848ff749be71d797fa287a7b5e2774e88}
|
||||
x{a6eb7c89dbc44ea9c7439d0ff2a7b302a5182020743d0e54d84048ea668a012c0a808aab9c7809ed9920f75bc1df04e3}
|
||||
x{8da5e1e8173da17fb2527d049c746f216013a0cd3034be30fab97314d67f90638efeb394a504052f84dd3314f5a6e1fa}
|
||||
x{a0a9dfea9829381a8a8be0dd6ae9df703da93546d93e5a8e2a0895d0149894fc424c5735b32517305a575936e6d0bd41}
|
||||
x{afc39ec1ce487612179154f7e36e485626cdcde18593fabcf3a4fe5743abe57d6de0938d1e5b1f45e3861cbe9cff2107}
|
||||
x{8182fbea440a49e1f1deda5b1973eb1a6555d8bef74271ea56489508ae847db9f2a2e0064c8f25c6acad4893ea3556a7}
|
||||
x{b3af977dad139de108294d0fab8dcc817abff1948f6ed746e7f6aae1ca15ff628c4d9ef871481b8a05f3e4eb060f1569}
|
||||
x{b5b23529ae9ecdad0030248957d7135bb0f2212654f8b06b921f4f2e9f3374cf8314ed08a2020a2b81307db91bd31325}
|
||||
x{a05aee8260d4e96ffdfc3764c6aeefee513255daf8abe5df1e455ad9dc1ff826d0e57eb59352d6f3ca805f854ced20f9}
|
||||
x{b3d57b48afdd734921b826b6e165fc7ede42a6298d795cc3df87a659f2920e21f6dcac0fb1ec28e145e415cf1f75f15c}
|
||||
x{b9f8e0bb3f230f87496e6ba4ac104106426c87e1e6732863c28f4ab8b6d752c00d3d935f5e33669045c38a61adc09b5f}
|
||||
x{974e00079eec61f2c2dd74a02da965d367ac1f4cc1e128af147fcfd4c6940d2e0cc3babcbf5514b2beae2882e1ee3e14}
|
||||
x{9539571783ff73f8b5172728c3c5af82a1f36562e06e4e79fa8aff690eb5e4e6cb53f0fdc2a1fc2161e638313d379b59}
|
||||
x{af64b9701e9073ef4cf2b5345190791b0704dbd28b3f626042e1a0c4fa215fda937e996dfbaa07c65d9ca5f96b8f61fa}
|
||||
x{a10eeb3b9cfc1761bf9a22bfdeac39fa830cf2c52e2b70b82d99c005467243948821eafec82310ff761171ca4a5eccc4}
|
||||
x{86a5d807681cb61dead165e7b6dc51fbc4d87a3e1ba203d0850a88fa6abc8c443f6e59d0367375e04166319bbbd70653}
|
||||
x{b68306c1ee04db2c41a5599e8c65b36f27e2ef2dbf74153f50f3ef5a8566a8522268b7131ed8f6244a8e9285b8cc1363}
|
||||
x{b168681033750e64fab4b54121fbf6dc64bb214eb9bacc00d199745354517e3e1b110ad882264862a91990400eb0d832}
|
||||
x{a5a41fa143084456fc9240f4a0b0959c6ab2e4c77a8d0fbacbaebaa7762d19cf25e2bc9bf642c3dc4bd52ef9a125d9b6}
|
||||
x{aa1044716ac0ce361fe3d7cf79cda8ac7bfd5d75c4c9a6385e54c0f058dc37bba7a98066419340119ea957835e3f5062}
|
||||
x{8316f76c23a66cac4d13966c641a8b1fddec4a8a1da95e418d3c29a318123dcf62680b3d7d7fe989200f087da31f2d47}
|
||||
x{b3520e472e5206768de36f16c59537ba7a5f548f1e606ef341be57c61c69b36dd3e9b6fe7fe8a36269e9f6b3b6860612}
|
||||
x{8e58d534f013ab17fe6602ee4a477187367ef4c48dbabedbf81433243dd5138aad25aa483a34cc96665f6fc2b0c43ce1}
|
||||
x{a53b58680e5397ace528cc8b2fe5e9bb72c40eb450c3fc5ca787cb95b1da733b6ba759b2df4e9e2b774e0423b57aa0c3}
|
||||
x{9124081b9f24d896cb79f75a667e58bd97e7150bf245f9f50d3556e1108c47c73bdd153e65d75641b324ca75ef2ac4b8}
|
||||
x{a6f86b395f56ea59ddb0f2329aaf2fb7ad7779b83e9284f9303dee3b29dfb318196f836f8abddcb8368a8e7c2cdaa462}
|
||||
x{993bf4eaf832dcbff2f8c1e8009f779189ad123bcb12ea9c46e0db23dc0772fb0cbb89796d9dff8cc3c96a35efe33b6e}
|
||||
x{b3fc6d1fbf08661dd9912d9f6badde61cfd6ad5a8be87024d9b25724f51d0fdf746b1c7ef08fdccb7453563c32d3b753}
|
||||
x{875284793bc53f9b3483e59ee05094e45c9aaf49d7a94d9d541e1426fd02a0271f6619c1d5dd2ef2ffbcb1429ac65ffd}
|
||||
x{87b53aec91540ea4bc0d89fb7f863a095e4fe9644b433810e75316c0015663cd0087b5044bcd6483b6de46052439ec61}
|
||||
x{926d4637eea543e4d3a97963c9644632bcbce065cabffe5af044c73f43294446dff6f502b0d43978121f8783e789b784}
|
||||
x{83709d410068ec4da081a18cb1000401741e652d2db38fecfc33c2b124cfbc2497ad490fae22c460905066eea5a0295f}
|
||||
x{805b9aef8db25a170b664495fe825c92c737c2c2d42c982a0a87161d3e7ded0a75603946fb68e2dc05525a2617c950da}
|
||||
x{844f8360c42e3472b8e1f0515be2b17c57263569f40e931e96ec456338f89f75f41998eae7d78a32d97f532dedd93ef0}
|
||||
x{8f8a897dcd7a5a3c7bd68c3e9d7a742c116273337c15c7518264dd403467a26647573837ddf08644165fe87dccc8a263}
|
||||
x{8b83e1982cf15c9910075224a8009c3363f2c1c914f2d74dc88f2d1acdb17bac75a838a56d123f8a6746b611b1105b18}
|
||||
x{b27d8d49ee63ecf6f4ced8bd515c4fa27478e8a70344ce098e9cd3e6dc4712f3d24e47f93d23242571444cc726511865}
|
||||
x{a3252f0ad64cfcdfe330f8939f8c9ffa477ff17cd45929f7fa62ba25a9cb5af0f83a070d141f315cc6e82f4564ec4f64}
|
||||
x{a6bb5240fd5ab570f4b5bf8836c34241933973f0fcb537a124dff7ec545c1c55d13cc6c23ba1b7452b9aabb2b66dcb37}
|
||||
x{af83b1ffb771e0698f9b2a7ffef6df235b18e89aa90a5358abe82a2d9b077e08dc1ee11869a53b95519072adff5d26c2}
|
||||
x{a990df005e123fc73bc97c79ecf34dc029265a66b530687192230689aa6a96d4fd8d71d5d6292566d195b968184cc3b9}
|
||||
x{b6db2b4d155a26adc7667e84a98ee9e2f57ba6eaa1a0b1d966502890a060ef5acb1b9ac0e0cd488b0d70f356d4ab1575}
|
||||
x{ad23f7a128230b69b92156de6d12f3d7adca4f17e4fa95ad1e4aba93afeeffa1aec73cfa543b2e9387823c95db18eecc}
|
||||
x{b021626d7882e973d1dc142833d7b78b6ea7ce6d7c5abc4e5c4232d61d9b8d540a01d0c3726f253702335a80d4873e3d}
|
||||
x{97d37b022828ccbf20450561fcba5febcbf2627e2e0e61f0259d9aae32b63efd795e83b247da7828ab3a52f40b055c8d}
|
||||
x{972829ba8a181be19333088f332b80506d5519853ae22d50a1be9fde4eb181f1a00b3e695da8872381d8c663e53ea752}
|
||||
x{a97af7a23e81bc3b56d245bdfe656ddfbb30b00dd05b358b29c442c6d440c84c46a87b9df9bc7706ad6eb004091783a6}
|
||||
x{b062a29f4441bd839232e2dde99e329f7e6c043f7f315ee156852fd557987b04ee911ad8130cca4c49cc8e09ceec6e81}
|
||||
x{a8239d71d680131c1d3857e13d53f11858d81a92217b37aeeb19b634a02441082d966f0b66e7d3f330402f8436ff8424}
|
||||
x{a1ffe6c1a89d5368bdd0366d4f780288d7856fa6085e85945c382d40931d2748b2db1cd443f574847649376487bdfebc}
|
||||
x{aeb35f89d305071d9aff9cce962a0320f84e206dbd927a5a9554d5b4e18e65734b1e7c81d02e245b120c1f7566d9fefd}
|
||||
x{9935f67ac4d2ee6a4c513e46220d67d5bd6bce78e73fc3acd7e4b4ea895f7c99d44c3ca6400b07c925e7c43c97805301}
|
||||
x{b606626eee2ca8f22eafcc063b961b78ad58e67295f9e81ebebd07834d5fb7b094476d4cf4ba977fdbcee58b8ff91ec2}
|
||||
x{aa4f50a49daa01f4e2b92fd58f30029c0692fd529cb2db3aa3a6ea0f990df5020ba8c09992cced29d50e88e77b9eef1f}
|
||||
x{90cb4f0932eafe48081aaeaed46c608fc0d5aaf7cac29a0f28e7a1826882983136f5e91f3d47b147b1f1d252a68cdfa4}
|
||||
x{8610084a4b1884b49f1a4785c8a485cda8d0719510e0013b31810db813dfd115b31eb1c3e29ac17233e903e102f2f858}
|
||||
x{84c5434f9c4554d0d5ac44dc84142ff00c3fd20ddcf207c1b899399d71fd2104d408fced0b58d3673bccc56123e7a62b}
|
||||
x{a186868726ea2fe22049b1dfaa62abdb42ec46ae860d2f60546ece07db5402383b6bf3c7d26781c393a611512c250b38}
|
||||
x{b2fb64b19612176bc0961538c8ef5d5d167c98f3d43747d95fe2f030449efb61a962fb0562bf4c42e7bca96cca4bcd17}
|
||||
x{907261678b16023479eac3a3d921374a6a42ea163a09e7a975627b23043011711f7729efa8a39eaa8b97f9d19a336b4c}
|
||||
x{872246987efe00f8f6a24bd2eeeb6b431204c01f3dcd4ece3b680f2bc164fb65f671551c9611d892a313ffae8ad35bfa}
|
||||
x{8a35e8cf02a79ebeece284cd83d4499b10e8f3bc31f0bb058dab05fed30c7ec1d790a1dcf22685189853d3c8de81fdba}
|
||||
x{8c4251af4d9e27118bd59aaaaf2fedbc6a8d5dde289f66345ac64bd566d094e961a6860238f669e2b4170a85022619f1}
|
||||
x{9798f348d7bdabbbdfb6d2345083ff74ac58db16a6f3d68cd972d8c58380f3f455e589a91beb866d6ee379b8801ca20f}
|
||||
x{932552f80b6a1a93dfddde98362f1f6f2b753f3fa05d6a21feeb47caa44548c8052143e3f71a21189e22bede3b700fbe}
|
||||
x{82a0a28b240899e36db8f0ea641a01225c0e148dda443929f1f4dcc7020dc64a56532c0e0c754f458a78292e67b01098}
|
||||
x{8d131e2eaf0f6ed5b293f22a8523d3c99f7456a5ad866100ad11141148e4825bd041d6870af2db4b6068841ec306181e}
|
||||
x{a7281362b96c621f04e4f9dad0f09f2fd880171649efb46381ac5846a18376018cc43734971f977d18d1751cfb05c709}
|
||||
x{a5d0207289aa93655aff791bdd430ea25ab93076d4295a256529411b4a55aa25ed8b3433086512dedd0255ded3ff9a63}
|
||||
x{8703dcb528278c5c65b410dad0047bf2257f988bac6a11f1fe55e9d9794fc2515ced5f9863262d13daebc487ba4d4cc7}
|
||||
x{b080c720c764ee177c35cbd1e29096e54feb2c29c68c7b5279916fc32177eae21bdf8328c7477e7a7feab59182f79c8d}
|
||||
x{a98842b26ac4212e620a9a09018ce4573c02bb64a37c4e6ba91f972744e73b37a5c2d3f84c6cb59bc00ee25915e8a918}
|
||||
x{aaaff1c584152dbec4fb2b50b91abd0703853a8051cbd3bc536e90aa3b65637ce77ab3dad4e9d6e8f3def0ffc920f9ea}
|
||||
x{8069968e491d68b934b27e91a355249b2b1999cfa2534b7cafb7adb7a333af7920ec7b628cc5725630c39462b967cb7b}
|
||||
x{b4da9f8378e711b30c3dbdaea9dd95e0d43420f7498f12181fb5bd3743392d5b5c0f12c1121bc2dd6f325a3d4c268bf4}
|
||||
x{ad234661b80488143b93ee2efc1ab8eacc50a137aec333ea8141b426e5fd4070c968618d1a875947e08c8428e68c88e5}
|
||||
x{823f71e9139e4982ce3b5dc7242a61876fbff25b3e9c1b532b82895e8624942f5e57af2c7819a80d716e06e04b921250}
|
||||
x{b8f32a192438bf2dd454d0d9b831630c54b65a79a79611ab00386dfd99a80e58101df5455084d91a9a9939e108670214}
|
||||
x{a5f68bd025fe3fb4921de2a081381870d41c85999f1754ff66d270a74794c7ad50d2fc01cf01ae1ef63247528e02aab4}
|
||||
x{b7bb0c34c3e5da34302e937ca40a53c980de5f43fab50299f98b6d44fde2603355845030a29c1593cf342f85a8955450}
|
||||
x{83077ae296c08c8aae4bcfc79b2828403433cb6ac48bb5c48eb85d4ce09f61d916947354e49183fe675c0d7f5905fc4f}
|
||||
x{ade42daf027ed0939428a379dee1d6f52d4d69bd8854a5a5b166b8b1715a5f51b3d7281a0a2a4fa86524775c694deca3}
|
||||
x{a327e8017149cbc021a583348c07edf1699b26bca4e07b6f79b1bc9dc030b77512f2968ceb47c8f72c81a55dbc293a58}
|
||||
x{8dfec6255438a25f4076480b80786a58eb3e5d63d76e30f95e39e590a39d82c405b33bae71001ce647a1e3b3822aa2d3}
|
||||
x{b744e6c66ac37ad90bbdaa8daef65b66a41d6f7c7662e86db742a7d0e52e8b3e6de185c99b53d1d75bd120763d260e1e}
|
||||
x{9954e4646ef602352b8316de9b9186ebfada10718712d0d7ce646dec72a4840e288f6029aa0c2a0a4cd1749a3fc49760}
|
||||
x{aeab8fcafa3f35b2b6585c7b573ab001cb1b1eca62839430010d69bd626bd522a1f64eba0a72d7e35e6081f8f24f9ecf}
|
||||
x{a92ec41af6d290cd87c272d30a9c6afbde28daead0266987cbc24ebb3d68793b3e3030ef1c0fd6162e5d6067189e5b0f}
|
||||
x{870da719fb854d4e97bce5f84994ca582a7973f85abd172682083bf974e07ab0217c56dbc8668d978510ea6d49ebf0e8}
|
||||
x{971389abf73b0b18a85a9bf1a5b78ae54af0e9dab2810ff2a235b106ec2093f31c6144b6267e143b79ffcd4c79ee4902}
|
||||
x{94f929a1834d477597f4d1047d09298676948e7136cd7554de2a5bb89d947c476fb3a9391adb0d804f0304bdefb2c074}
|
||||
x{b250f0c4310487e162a6e8a8b2362a6fc643772838b4fd0b330502f913b04ea55c88212e83ec5a8103408511905807f1}
|
||||
x{a3b0ac5a206ed5a9032ed5cd213751fcee66c7d629fe473f09457b9da9142c957ed39c0090c7eef24397669b0d361f72}
|
||||
x{a151ed4066eafd3ea7eb646def1ffb5d14258a603045e37cf2c8cd7248700e7e1ac3e7f852e2fe7ad5691eccce99252c}
|
||||
x{9711657a493af933761b8b848b5f09fc872d4ec85e3567c40bb48cb4f922627c0088d173d835b115811aa095dd8e5d82}
|
||||
x{a5e7f4a06080b860d376871ce0798aa7677e7a4b117a5bd0909f15fee02f28a62388496982c133fef1eba087d8a06005}
|
||||
x{a821c289f883e5a9bc76076a7cf6f6ee4dcac14d064c76d4a98756f6bfff85cc1fd45f5031b0c491d393869dbf37ab58}
|
||||
x{b5716cb955ab67df3f9035325e00ddf29855f010fdff09c708726aa08196807ba946cfb70a710dea25ee8209af5cd38e}
|
||||
x{b370f1a22a538bce3680d8094eed26372201563713ded3308c2fb4998a4b30f92f57616f2d859ef0806dd6da776fb12c}
|
||||
x{b144c4ec1624abdb6b0b006091ef941f4f785751d114d6bc39269da9431da9991fa23e2b0f333efeb38770a25523e820}
|
||||
x{919a189511a5d7590ecf34fbe5f36d1f92244db0c06aeaf6fb56569abf30ffb71cfc7c42913a6483a57a39a0ccc90b9b}
|
||||
x{b9f830b001c45c07a83d1ef9dfab49a9c76fa9c13d62a0678e4336c6031bda6e07223b87a7302decf09e72364121ebeb}
|
||||
x{af014b3be9c6b92fe8ca07cdcc900c86611e35e32a758ec468c1afc13ce640a7375482d51b8681903372f9c5ecca7687}
|
||||
x{90293185a10067becf6f10dd5bbcdad97e189504d6a1df630a1028103613c80c15b29e0fb4109337b611c66e09ffb050}
|
||||
x{b23acf81c4f787dd63e3f8c31ba9dde38b44a455a18b04f7325e09bbd439e5ee2a75b67d3673aea6d2476998bb2adb0c}
|
||||
x{916efb4510ac05f36693e543384a54c875c5ce811f3bce476a294d00e4d64f27b5ab4d4c4ac7ca9a2c46a2c317326f72}
|
||||
x{b76b06907a9876f8538e3f58758aa95d23d449dad3caab1e9708ebf51b09b9edc29d04d60ca3d6fda0e2823a4437b0d8}
|
||||
x{83c0ccbf5f94afa5a7f5e7b3fcf7eb2afd2e656ff327f357f1a4b36f630fa2856ad1f07e51b38ee3a6e92d8075f85fbf}
|
||||
x{9527d6a088468097aee5e3f0c7cd469aa666f096f054432d2a34df504217dcc5f70b45c7a4923b84b8cc9ca9f4a4b23a}
|
||||
x{aea834fd07048eb22116cee9cdcc04c0ca900b5ae15e297091ce64c5631cae870ca13323241cad96c81d1ffdee43495e}
|
||||
x{a9973ccb82ca88c7862fb684abd6814420b5f763416527a4020ed15adb1d5280b71d21e2ef280bfeb3f64104fd0410df}
|
||||
x{a85b5024a160e7ed3467930b62c1346166e3bc35be18c9a891f19c5f343d2ee3c2702e987a4a1b7c9980dc4e099a7494}
|
||||
x{a279c5583f81d1b1c1c7f6652bef822f0ccd3364de4dd56132a70fc4dbde3e006c17bbaeba9ca3dff6ea0e0d7dc0bede}
|
||||
x{929713e325fbc3b9012896497213781dcd7edcf1122ac2e71bf0eeedd4b72090f9b61780f159f89066aeeb29d1b0bbb1}
|
||||
x{8da3be746b47660268d2f6d74236047f5cc5291b68799ac8bf1bf34e1d035e4c203ecc415e71381a11b3b5884c0f263f}
|
||||
x{98742a51f3d4581ae8f22b8c8e195d4e87017f502c54862d7b76039958d90bff3c02c07cde47d3e0d6877b4937648bef}
|
||||
x{aada0601bff5813cec1b849893e2e6db5fff6a1beb605517c77e4dd2722aaa41510e528ccd072a76c10f12744d2ae172}
|
||||
x{84ea9203ef391535d61ba30fa3a2104acbc59318c2da90d5e6f5df40ae8e234eeee714af1b4715200c471b00682ec3c1}
|
||||
x{899047e4fb2a2824bf3c612a1040fb6c71c1f7ef0654177144d236455b198ddef003b64bb7c9d3f0da78c32800956e2a}
|
||||
x{a10af4ddc28d1794167cef4b751022d8f57860a2618ce05a8b5d87c95584f1c6ee2774df7de60768ff81db4f432a3211}
|
||||
x{93614feda46e422eefb30a724bb519c7c2ca3f743546806d4ba6ed59bf8862fcbc1f3fdae9f17c127255eb6968780b17}
|
||||
x{a1f5e841c97a4ff52b2fdd00164fb77d6960cba1ddb3477d6b522a05521aac0796dee38c7a43e10d9c1681b38d8892ff}
|
||||
x{92d976efe2f26ed00fe867c789407dbdeec51921e718b1a18461f795460d3bbe7cd74ea817d1bdea149423f0ad8393b2}
|
||||
x{a2a3e37af6c9bed27e8f5d7dce5eeb9cfcadd2a942e7e9f84c9d95fed6b1dc7ad7d079f3f5bafe2d44dbbc67d99b0a5f}
|
||||
x{81ffe874b2efce3625b5cd61e0d276d4f460597907a7f862a0a17a8bdd6778f7884e6a9d80e4c5cda224b2701655c96e}
|
||||
x{8d2a05160ae509264ae64e056518a0f3ae2c197c2450d14d7f30a85db58bc7c562b5d450fef287d7355e63cbe558f44b}
|
||||
x{aa3284d0d6e875fdca38b4009f57d7185dd3d8fe58aeda254de4e7df3932d446b80706f754c6d36ac230877a14da2160}
|
||||
x{85a98b4ee6889d0fcec0fb23025e62a0bd6acc92df9cc2ab0cce430d7b096dc3de22f79a22ed727a5d15ab9257216469}
|
||||
x{874bf95557e0094df23d3f1cd41155862b755482d3ef1a2707f341a1c66cf5f3a9edf52df5b167940eb1c1bfc565fc67}
|
||||
x{a8324649bb016038ab07cd91879772df95a952973a19c34cae6af7e4fefbc545a94d12b23a2159e48bd049f57f5e93fb}
|
||||
x{83b8c1dfeb31c8b61d8ffebf44d54a36af52f75aaa0531322020a6b04df9adb53d9a8099c521844f4e88d6e6aa36ab3c}
|
||||
x{abbd6ff3a89fb9e14ad17978f088eb4b60af37b02835eb8d3fb7e7ef59342b68ca6ed1fce928446806015951caabcd6b}
|
||||
x{8e9e5baad181d47ace0c6b5e9d639a2dac88cf667c0a90610267046563afe28b7be6ccd887940b5261579f7dbe6f920d}
|
||||
x{b3f0b8cf0b5a7c6ebcf0c46c1be6d3c1d0a5a8ff5639188b3854206f2912f384e9f4d13fe1de35da1ec0ff4cc0917c56}
|
||||
x{88132b949584e6d96043228bd589ca6438c594fdf91b6640f65932f379cc94a02e294e9d27be40e3d889b63d33c388cd}
|
||||
x{b449cff96f2dfe5bfa879b713b081d48898aebbcae376c5cb32ab1f2bf3a8eb329f3aafcf6c251b55c3622b6a5036a10}
|
||||
x{b705ff85c991b76587c7ddf9dfa144b25d985aa85b0b79e3c21d2229542388d9e66bfe8aadd511229e64c3c14e06bcc3}
|
||||
x{a1f5ecdb881f30fab751b45c17326d04aeb3b67db946b37c3ec9ca8c5608d949437612e0d08e96c393d5b8110d9fb619}
|
||||
x{b53734cdc0454bb8e02789f20b414e3461a73a347aeed2c331ec625f35cf07b44e676d568cdfb1fda7e3bb46fec2a179}
|
||||
x{a496d69daf6ffeb228106883ddc885a7df0290527b4d9ff902b446df6b220842c0040f9be9fd08d8e2c17731d9d6355f}
|
||||
x{89532cb6bdaf72d8e430e8baf25a94ea475328edf876659039e71b1804b407964ec043508a81fc23659ac5d225f81752}
|
||||
x{aadb20736b040c633d4790e0d30748ae047e86efcb5008b586f1bf2dceb99ff4659711b2933f50096ff2af89d9bc187c}
|
||||
x{b1d65445dad3417235c059d084f23fa5407c2de501f3501729bfe9952e7a03c2699f7115130bf3cd7f3878be3bae963e}
|
||||
x{89cbb614041988d7f15e4a2cd7552b4c54afa224839dbe5076ddaf4ef8c30e661af4080f64245588fa4ff71314a1ddb2}
|
||||
x{8dec221ff90b27567f53bea9638293624c5fc64572a32ad93651fa2172b37132195b3d4de8b89df6809d312ddec8e554}
|
||||
x{89700f819dcd49c6c2c6586333773f3a67043bbc780c9ca4f05dd1a48035138c47560dac51c7e0e58cf238b910bb8001}
|
||||
x{96abae0439028d53d35dd4c0ec26dc8a4ba1545726e25620f0a5ce3901ac7b185c9315ef46c0a29e10d8f0a0c7c0fac3}
|
||||
x{9799c21074cd36b98d1e37f66dc05741c13f463b893ed5bce9fd2db604fe95c65f23d07015eb53e2ed9fcece39a2145a}
|
||||
x{9119782077a9ae2564124374d877b0835e79d9de524c6cea6b1f3be2e1f33417040bf62bf064200c74c086d9dde10084}
|
||||
x{8075657d35885a8a3bf5ba8087a5cd5b089f894da72ba7150302a0e6adcdac186eac45cb79385445e3785278711f2091}
|
||||
x{8e2f9aa48d8a3693c73995113ef3d2bb8c2c37f8b528b2e8a9e52104940b1fe3bb6df234eeee099d445c59dab9eefdd4}
|
||||
x{99107a6ba9b0717141c9c36c8a2f99a293e0909da65f20c44594b7bfa519de73c2c93e3ae651f94ee7e7787d16e39ccb}
|
||||
x{8239a6c06392fa5854bdb4a3703b7a38a6ee44df66d498e0c3afc7381a61f335012835bef8a0b558630f1e1863a11731}
|
||||
x{8fdf5c3d7bd9d5d46a0714ba236ebe0f9f8f04db756bcb30f49e87f758a28f7833aef65dfb1bac9963ec945c9ae69314}
|
||||
x{911419794a5b85e78452a8e156eef297d5f10a0b5488b215e8f7d9a757f88eb7f2febcbc4f2b135181f9a0ec5c8943a7}
|
||||
x{acfcbcea8262c87fa851c4d6601cbe9cca7a597425f9aa4f002b518153fe6e9a84da7185a67bfef2be7d07de638617ad}
|
||||
x{b89acb00a4d16e56460ea0bab3f3f5754eb79220d60fa8ea6d5588f20d21a4d16f38107994b2e350d52d5565924c88c5}
|
||||
x{b0bc0f14093c805453040cabb3a58530b5c7d75dd8ed2499c3c089ae6eaff8cb90fee7f4fb4a9a18ab43567eb06b8bdc}
|
||||
x{ad3d2da3b07f0d9688fddc6e19ba30dfcebbd3a5af3a3f791e056d89650bf98d931ebabeda4338d8196e86856b3d109a}
|
||||
x{b501ede6b849057031006a356607df1690206fbd337cd6ef1db764aa257ab09818af900587a751bbfa7d384c0d542c35}
|
||||
x{abc8caaffa2225d3df4aa9020e517f57561efce8bf1628d1a75ad7e5c1efb4469ef56e2fb44427c740aba293e1896992}
|
||||
x{a166cccc21273eca781e33dce0769633296101a1e43515a120f027d06e110e5eb7ff1f6a1a324b9c9315bd89e12819e3}
|
||||
x{81c29db55f0957d889ea8db8e2a15c2d7020d50f1f9f60ccbe74d4a58a9aa5579955d4a73065614d556e443551f1ec51}
|
||||
x{89024f719d34cc220acc52d4075eb1d69a7d3624d6eeca3c0e6ceea66975c94947f6001189b21f72980f883a9f73eb2d}
|
||||
x{b53fddc5ad0059ee152c0d096efef63293999e54a66c867432de3dce6043f7811dc58111480e184a99e4c7f360a3de70}
|
||||
x{a21b66e7db725312ef2929a65d18cf60ad3f595d8d3a76cbbe419430e4e6a83b489343edd714f774ef69b07771ed57cb}
|
||||
x{b177aede11e8288c8d2c7e274cf1b5d9cd17f0b965455d42d014bc4645b93572467c96f47c8d6a0c98c12730f323170a}
|
||||
497
|
||||
x{30cfebbd980ea1c8f157a34abed82f3a34ecc2594e626265063e565230ae9193}
|
||||
x{91cdca080f9cd6ae0bd15b427455053e12025843c2f602e0af70fa0e5d18dceb0bc46aa1a7652b54cfd8ea97c7210c5808d7cc72b82be7a2feb57f69d3511e4590a665e45e0e0f9bb43b05d8a0167fe2a91f4aa54c0a095c864be6e2b1e43081}
|
||||
-1
|
||||
test-fast-aggregate-verify
|
215
crypto/test/fift/bls_ops.fif
Normal file
215
crypto/test/fift/bls_ops.fif
Normal file
|
@ -0,0 +1,215 @@
|
|||
"Asm.fif" include
|
||||
"FiftExt.fif" include
|
||||
|
||||
{ { drop } depth 1- times } : clear-stack
|
||||
|
||||
// Map to g1
|
||||
."G1 Points:" cr
|
||||
x{7abd13983c76661a98659da83066c71bd6581baf20c82c825b007bf8057a258dc53f7a6d44fb6fdecb63d9586e845d92}
|
||||
<{ BLS_MAP_TO_G1 }>s 0 runvmx abort"Exitcode != 0" dup ."a1 = " csr. constant a1
|
||||
x{7a6990b38d5a7bfc47b38c5adeec60680637e8a5030dddd796e7befbec3585c54c378472daadd7756ce7a52adbea507c}
|
||||
<{ BLS_MAP_TO_G1 }>s 0 runvmx abort"Exitcode != 0" dup ."a2 = " csr. constant a2
|
||||
x{4e51f1317a8d7981f7bb061488b6e6528978209226ded49b02fd45fcb9b5ff8d33c360cd6db9661143a77edb34aac125}
|
||||
<{ BLS_MAP_TO_G1 }>s 0 runvmx abort"Exitcode != 0" dup ."a3 = " csr. constant a3
|
||||
x{0ca4a2a9a055367caa8c41facaae4c1f28360e2bfc70182904ff966011de9c02e6744bad6b0096e7ef3f21bd972386af}
|
||||
<{ BLS_MAP_TO_G1 }>s 0 runvmx abort"Exitcode != 0" dup ."a4 = " csr. constant a4
|
||||
x{1473aa897a1a166ce6c1b1d11e2401ad719b9c03f3a86d8dd63158d389667d66917d3845414a23c69ccef01762ec78d4}
|
||||
<{ BLS_MAP_TO_G1 }>s 0 runvmx abort"Exitcode != 0" dup ."a5 = " csr. constant a5
|
||||
|
||||
// Validate points
|
||||
a1 a2 a3 a4 a5
|
||||
<{ { BLS_G1_INGROUP 33 THROWIFNOT } 5 times }>s 0 runvmx abort"Exitcode != 0"
|
||||
|
||||
// Invalid point
|
||||
x{1d549908b5eb3c16f91174abe436c1a91442a57f922da813cb3dbc55de9e62bd63eac19a664eb8c3ea34b5a5c176d844}
|
||||
<{ BLS_G1_INGROUP }>s 0 runvmx abort"Exitcode != 0" abort"0 expected"
|
||||
|
||||
// Zero
|
||||
."Zero:" cr
|
||||
a1 a2 a3 a4 a5
|
||||
<{ { BLS_G1_ISZERO 33 THROWIF } 5 times }>s 0 runvmx abort"Exitcode != 0"
|
||||
<{ BLS_G1_ZERO }>s 0 runvmx abort"Exitcode != 0" dup csr. constant zero
|
||||
zero <{ BLS_G1_INGROUP }>s 0 runvmx abort"Exitcode != 0" not abort"-1 expected"
|
||||
zero <{ BLS_G1_ISZERO }>s 0 runvmx abort"Exitcode != 0" not abort"-1 expected"
|
||||
|
||||
// Addition
|
||||
."a1 + a2 + a3:" cr
|
||||
a1 a2 a3 <{ { BLS_G1_ADD } 2 times }>s 0 runvmx abort"Exitcode != 0" csr.
|
||||
a3 a2 a1 <{ { BLS_G1_ADD } 2 times }>s 0 runvmx abort"Exitcode != 0" csr.
|
||||
a2 a3 a1 <{ { BLS_G1_ADD } 2 times }>s 0 runvmx abort"Exitcode != 0" csr.
|
||||
a1 zero a2 a3 zero <{ { BLS_G1_ADD } 4 times }>s 0 runvmx abort"Exitcode != 0" csr.
|
||||
|
||||
// Subtraction
|
||||
."a1 - a2:" cr
|
||||
a1 a2 <{ BLS_G1_SUB }>s 0 runvmx abort"Exitcode != 0" csr.
|
||||
a1 zero a2 <{ BLS_G1_SUB BLS_G1_ADD }>s 0 runvmx abort"Exitcode != 0" csr.
|
||||
|
||||
// Negation
|
||||
."-a1:" cr
|
||||
a1 <{ BLS_G1_NEG }>s 0 runvmx abort"Exitcode != 0" csr.
|
||||
zero a1 <{ BLS_G1_SUB }>s 0 runvmx abort"Exitcode != 0" csr.
|
||||
."0:" cr
|
||||
a1 a1 <{ BLS_G1_NEG BLS_G1_ADD }>s 0 runvmx abort"Exitcode != 0" csr.
|
||||
a1 a1 <{ BLS_G1_SUB }>s 0 runvmx abort"Exitcode != 0" csr.
|
||||
|
||||
// Multiplication:
|
||||
."a1 * 1:" cr
|
||||
a1 csr.
|
||||
a1 1 <{ BLS_G1_MUL }>s 0 runvmx abort"Exitcode != 0" csr.
|
||||
."a1 * 0:" cr
|
||||
zero csr.
|
||||
a1 0 <{ BLS_G1_MUL }>s 0 runvmx abort"Exitcode != 0" csr.
|
||||
."a1 * (-1):" cr
|
||||
a1 -1 <{ BLS_G1_MUL }>s 0 runvmx abort"Exitcode != 0" csr.
|
||||
a1 <{ BLS_G1_NEG }>s 0 runvmx abort"Exitcode != 0" csr.
|
||||
."a1 * 3:" cr
|
||||
a1 3 <{ BLS_G1_MUL }>s 0 runvmx abort"Exitcode != 0" csr.
|
||||
a1 a1 a1 <{ { BLS_G1_ADD } 2 times }>s 0 runvmx abort"Exitcode != 0" csr.
|
||||
."a1 * 123:" cr
|
||||
a1 123 <{ BLS_G1_MUL }>s 0 runvmx abort"Exitcode != 0" csr.
|
||||
<{ a1 SLICE 100 INT BLS_G1_MUL a1 SLICE 23 INT BLS_G1_MUL BLS_G1_ADD }>s 0 runvmx abort"Exitcode != 0" csr.
|
||||
a1 -123 <{ BLS_G1_MUL BLS_G1_NEG }>s 0 runvmx abort"Exitcode != 0" csr.
|
||||
|
||||
// Multiexp
|
||||
."a1*111 + a2*222 + a3*(-333) + a4*0 + a5*1:" cr
|
||||
a1 111 a2 222 a3 -333 a4 0 a5 1 5 <{ BLS_G1_MULTIEXP }>s 0 runvmx abort"Exitcode != 0" csr.
|
||||
a1 111 a2 222 a3 -333 a5 1 4 <{ BLS_G1_MULTIEXP }>s 0 runvmx abort"Exitcode != 0" csr.
|
||||
<{
|
||||
a1 SLICE 111 INT BLS_G1_MUL
|
||||
a2 SLICE 222 INT BLS_G1_MUL
|
||||
a3 SLICE -333 INT BLS_G1_MUL
|
||||
a5 SLICE
|
||||
{ BLS_G1_ADD } 3 times
|
||||
}>s 0 runvmx abort"Exitcode != 0" csr.
|
||||
."0:" cr
|
||||
zero csr.
|
||||
0 <{ BLS_G1_MULTIEXP }>s 0 runvmx abort"Exitcode != 0" csr.
|
||||
a1 0 1 <{ BLS_G1_MULTIEXP }>s 0 runvmx abort"Exitcode != 0" csr.
|
||||
|
||||
// Map to g2
|
||||
."G2 Points:" cr
|
||||
x{cce34c6322b8f3b455617a975aff8b6eaedf04fbae74a8890db6bc3fab0475b94cd8fbde0e1182ce6993afd56ed6e71919cae59c891923b4014ed9e42d9f0e1a779d9a7edb64f5e2fd600012805fc773b5092af5d2f0c6c0946ee9ad8394bf19}
|
||||
<{ BLS_MAP_TO_G2 }>s 0 runvmx abort"Exitcode != 0" dup ."b1 = " csr. constant b1
|
||||
x{2faa65f3431da8f04b8d029f7699b6426eb31feb06b3429b13b99fde35d5c0ab17e67943802313a96b2252a69dfdcc6e56f5671d905984940f4b9ce3b410042457dff7ae5fd4be6a0b73cad5d0390ed379d658cb24e11973d80f98bd7ff64f19}
|
||||
<{ BLS_MAP_TO_G2 }>s 0 runvmx abort"Exitcode != 0" dup ."b2 = " csr. constant b2
|
||||
x{28619564e5cbb27c9e709d80b654f2eb1fd2c3ab435d7b97b4bd80638dbfe5b47e52df0e5be0b2c328357c5ddd8018acc6e739c4d132cc6f2b9797c210051acef9513ae54bb66de2a9ea8d02cbca7e96ce8193be1557d3128906e12f37913887}
|
||||
<{ BLS_MAP_TO_G2 }>s 0 runvmx abort"Exitcode != 0" dup ."b3 = " csr. constant b3
|
||||
x{66f14fc1bb199ece07fde0a7af3cb3d2719acd4bb5186ab4ddda7de6a9f96557df44f3d14264eb0fed79f53d972ddc4517e362a001c5e7c7217169a05d9e3cd82b521236737f5d564f5860139d027018d3b33605d51e48c77b51554bf1d5b24a}
|
||||
<{ BLS_MAP_TO_G2 }>s 0 runvmx abort"Exitcode != 0" dup ."b4 = " csr. constant b4
|
||||
x{a9e68db711778adb0bcee53ae4fd2d31605c1eff02ae38279eebfb45fc319964d33cb45ee32bbcb13663fe2131f79120af2d8ce26400ece9a7fb57ef9666c5b1b6f1856cb121b1c618b2dcfb359ffa63a08989c1f457b355958f589e7314610a}
|
||||
<{ BLS_MAP_TO_G2 }>s 0 runvmx abort"Exitcode != 0" dup ."b5 = " csr. constant b5
|
||||
|
||||
// Validate points
|
||||
b1 b2 b3 b4 b5
|
||||
<{ { BLS_G2_INGROUP 33 THROWIFNOT } 5 times }>s 0 runvmx abort"Exitcode != 0"
|
||||
|
||||
// Invalid point
|
||||
x{090069862cb1b1ac4241c4b1ed5f98edb95413db77f534bba7e85d9cb54d953c61416c0eeb5c65c6f0b494e9f59b2c9dfe8b4a9af75e1114b45ec60f6b5d2327cc05a6d9d6e76d7a9efd947302966d4f357bd48e5c3f950101c88c65b13bd5c7}
|
||||
<{ BLS_G2_INGROUP }>s 0 runvmx abort"Exitcode != 0" abort"0 expected"
|
||||
|
||||
// Zero
|
||||
."Zero:" cr
|
||||
b1 b2 b3 b4 b5
|
||||
<{ { BLS_G2_ISZERO 33 THROWIF } 5 times }>s 0 runvmx abort"Exitcode != 0"
|
||||
<{ BLS_G2_ZERO }>s 0 runvmx abort"Exitcode != 0" dup csr. constant zero
|
||||
zero <{ BLS_G2_INGROUP }>s 0 runvmx abort"Exitcode != 0" not abort"-1 expected"
|
||||
zero <{ BLS_G2_ISZERO }>s 0 runvmx abort"Exitcode != 0" not abort"-1 expected"
|
||||
|
||||
// Addition
|
||||
."b1 + b2 + b3:" cr
|
||||
b1 b2 b3 <{ { BLS_G2_ADD } 2 times }>s 0 runvmx abort"Exitcode != 0" csr.
|
||||
b3 b2 b1 <{ { BLS_G2_ADD } 2 times }>s 0 runvmx abort"Exitcode != 0" csr.
|
||||
b2 b3 b1 <{ { BLS_G2_ADD } 2 times }>s 0 runvmx abort"Exitcode != 0" csr.
|
||||
b1 zero b2 b3 zero <{ { BLS_G2_ADD } 4 times }>s 0 runvmx abort"Exitcode != 0" csr.
|
||||
|
||||
// Subtraction
|
||||
."b1 - b2:" cr
|
||||
b1 b2 <{ BLS_G2_SUB }>s 0 runvmx abort"Exitcode != 0" csr.
|
||||
b1 zero b2 <{ BLS_G2_SUB BLS_G2_ADD }>s 0 runvmx abort"Exitcode != 0" csr.
|
||||
|
||||
// Negation
|
||||
."-b1:" cr
|
||||
b1 <{ BLS_G2_NEG }>s 0 runvmx abort"Exitcode != 0" csr.
|
||||
zero b1 <{ BLS_G2_SUB }>s 0 runvmx abort"Exitcode != 0" csr.
|
||||
."0:" cr
|
||||
b1 b1 <{ BLS_G2_NEG BLS_G2_ADD }>s 0 runvmx abort"Exitcode != 0" csr.
|
||||
b1 b1 <{ BLS_G2_SUB }>s 0 runvmx abort"Exitcode != 0" csr.
|
||||
|
||||
// Multiplication:
|
||||
."b1 * 1:" cr
|
||||
b1 csr.
|
||||
b1 1 <{ BLS_G2_MUL }>s 0 runvmx abort"Exitcode != 0" csr.
|
||||
."b1 * 0:" cr
|
||||
zero csr.
|
||||
b1 0 <{ BLS_G2_MUL }>s 0 runvmx abort"Exitcode != 0" csr.
|
||||
."b1 * (-1):" cr
|
||||
b1 -1 <{ BLS_G2_MUL }>s 0 runvmx abort"Exitcode != 0" csr.
|
||||
b1 <{ BLS_G2_NEG }>s 0 runvmx abort"Exitcode != 0" csr.
|
||||
."b1 * 3:" cr
|
||||
b1 3 <{ BLS_G2_MUL }>s 0 runvmx abort"Exitcode != 0" csr.
|
||||
b1 b1 b1 <{ { BLS_G2_ADD } 2 times }>s 0 runvmx abort"Exitcode != 0" csr.
|
||||
."b1 * 123:" cr
|
||||
b1 123 <{ BLS_G2_MUL }>s 0 runvmx abort"Exitcode != 0" csr.
|
||||
<{ b1 SLICE 100 INT BLS_G2_MUL b1 SLICE 23 INT BLS_G2_MUL BLS_G2_ADD }>s 0 runvmx abort"Exitcode != 0" csr.
|
||||
b1 -123 <{ BLS_G2_MUL BLS_G2_NEG }>s 0 runvmx abort"Exitcode != 0" csr.
|
||||
|
||||
// Multiexp
|
||||
."b1*111 + b2*222 + b3*(-333) + b4*0 + b5*1:" cr
|
||||
b1 111 b2 222 b3 -333 b4 0 b5 1 5 <{ BLS_G2_MULTIEXP }>s 0 runvmx abort"Exitcode != 0" csr.
|
||||
b1 111 b2 222 b3 -333 b5 1 4 <{ BLS_G2_MULTIEXP }>s 0 runvmx abort"Exitcode != 0" csr.
|
||||
<{
|
||||
b1 SLICE 111 INT BLS_G2_MUL
|
||||
b2 SLICE 222 INT BLS_G2_MUL
|
||||
b3 SLICE -333 INT BLS_G2_MUL
|
||||
b5 SLICE
|
||||
{ BLS_G2_ADD } 3 times
|
||||
}>s 0 runvmx abort"Exitcode != 0" csr.
|
||||
."0:" cr
|
||||
zero csr.
|
||||
0 <{ BLS_G2_MULTIEXP }>s 0 runvmx abort"Exitcode != 0" csr.
|
||||
b1 0 1 <{ BLS_G2_MULTIEXP }>s 0 runvmx abort"Exitcode != 0" csr.
|
||||
|
||||
// r
|
||||
<{ BLS_PUSHR }>s 0 runvmx abort"Exitcode != 0" cr ."r = " . cr
|
||||
b1 <{ BLS_PUSHR BLS_G2_MUL }>s 0 runvmx abort"Exitcode != 0" csr.
|
||||
zero csr.
|
||||
b1 <{ BLS_PUSHR INC BLS_G2_MUL }>s 0 runvmx abort"Exitcode != 0" csr.
|
||||
b1 csr.
|
||||
|
||||
// Pairings
|
||||
{ [[ <{ BLS_G1_MUL }>s ]] 0 runvmx abort"Exitcode != -1" } : bls_g1_mul
|
||||
{ [[ <{ BLS_G2_MUL }>s ]] 0 runvmx abort"Exitcode != -1" } : bls_g2_mul
|
||||
75634785643785634785634876232423354534 constant x
|
||||
."a1*x,b1 a1,b1*(-x) : "
|
||||
a1 x bls_g1_mul b1
|
||||
a1 b1 x negate bls_g2_mul
|
||||
2 <{ BLS_PAIRING }>s 0 runvmx abort"Exitcode != 0" .s not abort"-1 expected"
|
||||
."a1*x,b1 a1,b1*(-x-1) : "
|
||||
a1 x bls_g1_mul b1
|
||||
a1 b1 x negate 1 - bls_g2_mul
|
||||
2 <{ BLS_PAIRING }>s 0 runvmx abort"Exitcode != 0" .s abort"0 expected"
|
||||
|
||||
08036758068232723862526737758751120353935980577994643429668638941492109432519 constant x1
|
||||
76720311667788346189068792441910584335982488547394926476426087533015880449318 constant x2
|
||||
73698677644295053147826041647629389417255852559045739853199261775689421644183 constant x3
|
||||
00651749128863148819911470689106677724299434569675211711456038250594316760143 constant x4
|
||||
."a1*x1,b1 a2*x2,b2 a3*x3,b3 a4*x4,b4 a1,b1*(-x1) a2,b2*(-x2) a3,b3*(-x3) a4,b4*(-x4) : "
|
||||
a1 x1 bls_g1_mul b1
|
||||
a2 x2 bls_g1_mul b2
|
||||
a3 x3 bls_g1_mul b3
|
||||
a4 x4 bls_g1_mul b4
|
||||
a1 b1 x1 negate bls_g2_mul
|
||||
a2 b2 x2 negate bls_g2_mul
|
||||
a3 b3 x3 negate bls_g2_mul
|
||||
a4 b4 x4 negate bls_g2_mul
|
||||
8 <{ BLS_PAIRING }>s 0 runvmx abort"Exitcode != 0" .s not abort"-1 expected"
|
||||
."a1*x1,b1 a2*x2,b2 a3*x3,b3 a4*x4,b4 a1,b1*(-x1) a2,b2*(-x2) a3,b3*(-x4) a4,b4*(-x3) : "
|
||||
a1 x1 bls_g1_mul b1
|
||||
a2 x2 bls_g1_mul b2
|
||||
a3 x3 bls_g1_mul b3
|
||||
a4 x4 bls_g1_mul b4
|
||||
a1 b1 x1 negate bls_g2_mul
|
||||
a2 b2 x2 negate bls_g2_mul
|
||||
a3 b3 x4 negate bls_g2_mul
|
||||
a4 b4 x3 negate bls_g2_mul
|
||||
8 <{ BLS_PAIRING }>s 0 runvmx abort"Exitcode != 0" .s abort"0 expected"
|
27
crypto/test/fift/deep_stack_ops.fif
Normal file
27
crypto/test/fift/deep_stack_ops.fif
Normal file
|
@ -0,0 +1,27 @@
|
|||
"Asm.fif" include
|
||||
|
||||
{ { drop } depth 1- times } : clear-stack
|
||||
|
||||
0 { dup 1+ } 500 times
|
||||
<{ 400 INT XCHGX 300 INT PICK 450 INT CHKDEPTH }>s 1000000 64 8 + runvmx .s clear-stack
|
||||
|
||||
0 { dup 1+ } 500 times
|
||||
<{ 400 INT ROLLX }>s 1000000 64 8 + runvmx .s clear-stack
|
||||
|
||||
0 { dup 1+ } 500 times
|
||||
<{ 400 INT -ROLLX }>s 1000000 64 8 + runvmx .s clear-stack
|
||||
|
||||
0 { dup 1+ } 700 times
|
||||
<{ 350 INT 300 INT BLKSWX }>s 1000000 64 8 + runvmx .s clear-stack
|
||||
|
||||
0 { dup 1+ } 500 times
|
||||
<{ 400 INT 5 INT REVX }>s 1000000 64 8 + runvmx .s clear-stack
|
||||
|
||||
0 { dup 1+ } 500 times
|
||||
<{ 400 INT DROPX }>s 1000000 64 8 + runvmx .s clear-stack
|
||||
|
||||
0 { dup 1+ } 500 times
|
||||
<{ 400 INT ONLYTOPX }>s 1000000 64 8 + runvmx .s clear-stack
|
||||
|
||||
0 { dup 1+ } 500 times
|
||||
<{ 400 INT ONLYX }>s 1000000 64 8 + runvmx .s clear-stack
|
98
crypto/test/fift/hash_ext.fif
Normal file
98
crypto/test/fift/hash_ext.fif
Normal file
|
@ -0,0 +1,98 @@
|
|||
"Asm.fif" include
|
||||
|
||||
{ { drop } depth 1- times } : clear-stack
|
||||
|
||||
// Compare HASHEXT_SHA256 with SHA256U
|
||||
<{
|
||||
x{0123456789abcdef} PUSHSLICE SHA256U
|
||||
|
||||
x{0123456789abcdef} PUSHSLICE 1 PUSHINT HASHEXT_SHA256
|
||||
|
||||
x{01} PUSHSLICE
|
||||
x{2} PUSHSLICE
|
||||
b{001101} PUSHSLICE NEWC STSLICE
|
||||
b{0} PUSHSLICE
|
||||
b{00101} PUSHSLICE NEWC STSLICE
|
||||
x{6789a} PUSHSLICE
|
||||
b{1} PUSHSLICE
|
||||
b{0111100} PUSHSLICE
|
||||
x{def} PUSHSLICE
|
||||
9 PUSHINT HASHEXT_SHA256
|
||||
|
||||
x{01} PUSHSLICE
|
||||
x{2} PUSHSLICE
|
||||
b{001101} PUSHSLICE NEWC STSLICE
|
||||
b{0} PUSHSLICE
|
||||
b{00101} PUSHSLICE NEWC STSLICE
|
||||
x{6789a} PUSHSLICE
|
||||
b{1} PUSHSLICE
|
||||
b{0111100} PUSHSLICE
|
||||
x{def} PUSHSLICE
|
||||
9 0 REVERSE
|
||||
9 PUSHINT HASHEXTR_SHA256
|
||||
}>s
|
||||
0 runvmx abort"runvmx finished with exitcode != 0"
|
||||
. cr . cr . cr . cr .s
|
||||
|
||||
// HASHEXTA
|
||||
<{
|
||||
NEWC x{ff} PUSHSLICE STSLICER x{01234567} PUSHSLICE SHA256U 256 STUR ENDC CTOS
|
||||
NEWC x{ff} PUSHSLICE STSLICER x{0123} PUSHSLICE x{4567} PUSHSLICE 2 PUSHINT HASHEXTA_SHA256 ENDC CTOS
|
||||
NEWC x{ff} PUSHSLICE STSLICER x{4567} PUSHSLICE x{0123} PUSHSLICE 2 PUSHINT HASHEXTAR_SHA256 ENDC CTOS
|
||||
}>s
|
||||
0 runvmx abort"runvmx finished with exitcode != 0"
|
||||
csr. csr. csr. .s
|
||||
|
||||
// Exceptions on errors
|
||||
<{ x{001122334455667} PUSHSLICE 1 PUSHINT HASHEXT_SHA256 }>s 0 runvmx .s 9 <> abort"exitcode != 9" clear-stack
|
||||
<{ x{00} PUSHSLICE x{11} PUSHSLICE 3 PUSHINT HASHEXT_SHA256 }>s 0 runvmx .s 5 <> abort"exitcode != 5" clear-stack
|
||||
<{ x{00} PUSHSLICE 1 PUSHINT 2 PUSHINT HASHEXT_SHA256 }>s 0 runvmx .s 7 <> abort"exitcode != 7" clear-stack
|
||||
<{ x{1234} PUSHSLICE 1 PUSHINT 100 HASHEXT }>s 0 runvmx .s 5 <> abort"exitcode != 5" clear-stack
|
||||
|
||||
// Other hash functions
|
||||
<b "lorem ipsum" $, b> <s constant str
|
||||
<{
|
||||
0 PUSHINT 0 HASHEXT
|
||||
0 PUSHINT 1 HASHEXT
|
||||
0 PUSHINT 2 HASHEXT
|
||||
0 PUSHINT 3 HASHEXT
|
||||
0 PUSHINT 4 HASHEXT
|
||||
}>s 0 runvmx .s abort"runvmx finished with exitcode != 0" clear-stack
|
||||
<{
|
||||
str PUSHSLICE 1 PUSHINT 0 HASHEXT
|
||||
str PUSHSLICE 1 PUSHINT 1 HASHEXT
|
||||
str PUSHSLICE 1 PUSHINT 2 HASHEXT
|
||||
str PUSHSLICE 1 PUSHINT 3 HASHEXT
|
||||
str PUSHSLICE 1 PUSHINT 4 HASHEXT
|
||||
}>s 0 runvmx .s abort"runvmx finished with exitcode != 0" clear-stack
|
||||
<{
|
||||
NEWC str PUSHSLICE 1 PUSHINT 4 HASHEXTA ENDC CTOS
|
||||
NEWC str PUSHSLICE 1 PUSHINT 3 HASHEXTA ENDC CTOS
|
||||
NEWC str PUSHSLICE 1 PUSHINT 2 HASHEXTA ENDC CTOS
|
||||
NEWC str PUSHSLICE 1 PUSHINT 1 HASHEXTA ENDC CTOS
|
||||
NEWC str PUSHSLICE 1 PUSHINT 0 HASHEXTA ENDC CTOS
|
||||
}>s 0 runvmx abort"runvmx finished with exitcode != 0"
|
||||
{ csr. } 5 times .s
|
||||
|
||||
// Long string
|
||||
0 {
|
||||
=: hash-idx
|
||||
0 {
|
||||
dup =: len
|
||||
<b
|
||||
@' len
|
||||
{ dup } {
|
||||
dup 64 min =: c @' c -
|
||||
swap
|
||||
@' len dup * 1+ dup * 1+ dup * 1 @' c << mod
|
||||
@' c u,
|
||||
swap
|
||||
}
|
||||
while
|
||||
drop
|
||||
swap
|
||||
1+
|
||||
} 1024 times
|
||||
<b x{F904} s, @' hash-idx 8 u, b> <s 0 runvmx .s abort"runvmx finished with exitcode != 0" clear-stack
|
||||
@' hash-idx 1+
|
||||
} 5 times
|
89
crypto/test/fift/rist255.fif
Normal file
89
crypto/test/fift/rist255.fif
Normal file
|
@ -0,0 +1,89 @@
|
|||
// Test data: https://ristretto.group/test_vectors/ristretto255.html
|
||||
"Asm.fif" include
|
||||
"FiftExt.fif" include
|
||||
|
||||
."Basepoint multiples:" cr
|
||||
{
|
||||
=: ans =: n
|
||||
@' n
|
||||
[[ <{ RIST255_MULBASE DUP RIST255_VALIDATE }>s ]] 0 runvmx abort"Exitcode != 0"
|
||||
@' n . dup (x.) type cr
|
||||
@' ans <> abort"Invalid result"
|
||||
} : test-basepoint
|
||||
|
||||
0 0x0000000000000000000000000000000000000000000000000000000000000000 test-basepoint
|
||||
1 0xe2f2ae0a6abc4e71a884a961c500515f58e30b6aa582dd8db6a65945e08d2d76 test-basepoint
|
||||
2 0x6a493210f7499cd17fecb510ae0cea23a110e8d5b901f8acadd3095c73a3b919 test-basepoint
|
||||
3 0x94741f5d5d52755ece4f23f044ee27d5d1ea1e2bd196b462166b16152a9d0259 test-basepoint
|
||||
4 0xda80862773358b466ffadfe0b3293ab3d9fd53c5ea6c955358f568322daf6a57 test-basepoint
|
||||
5 0xe882b131016b52c1d3337080187cf768423efccbb517bb495ab812c4160ff44e test-basepoint
|
||||
6 0xf64746d3c92b13050ed8d80236a7f0007c3b3f962f5ba793d19a601ebb1df403 test-basepoint
|
||||
7 0x44f53520926ec81fbd5a387845beb7df85a96a24ece18738bdcfa6a7822a176d test-basepoint
|
||||
8 0x903293d8f2287ebe10e2374dc1a53e0bc887e592699f02d077d5263cdd55601c test-basepoint
|
||||
9 0x02622ace8f7303a31cafc63f8fc48fdc16e1c8c8d234b2f0d6685282a9076031 test-basepoint
|
||||
10 0x20706fd788b2720a1ed2a5dad4952b01f413bcf0e7564de8cdc816689e2db95f test-basepoint
|
||||
11 0xbce83f8ba5dd2fa572864c24ba1810f9522bc6004afe95877ac73241cafdab42 test-basepoint
|
||||
12 0xe4549ee16b9aa03099ca208c67adafcafa4c3f3e4e5303de6026e3ca8ff84460 test-basepoint
|
||||
13 0xaa52e000df2e16f55fb1032fc33bc42742dad6bd5a8fc0be0167436c5948501f test-basepoint
|
||||
14 0x46376b80f409b29dc2b5f6f0c52591990896e5716f41477cd30085ab7f10301e test-basepoint
|
||||
15 0xe0c418f7c8d9c4cdd7395b93ea124f3ad99021bb681dfc3302a9d99a2e53e64e test-basepoint
|
||||
|
||||
cr ."Invalid points:" cr
|
||||
{
|
||||
=: x
|
||||
@' x (x.) type cr
|
||||
@' x
|
||||
[[ <{ RIST255_QVALIDATE }>s ]] 0 runvmx abort"Exitcode != 0"
|
||||
abort"Invalid result"
|
||||
} : test-invalid
|
||||
// These are all bad because they're non-canonical field encodings.
|
||||
0x00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff test-invalid
|
||||
0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f test-invalid
|
||||
0xf3ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f test-invalid
|
||||
0xedffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f test-invalid
|
||||
// These are all bad because they're negative field elements.
|
||||
0x0100000000000000000000000000000000000000000000000000000000000000 test-invalid
|
||||
0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f test-invalid
|
||||
0xed57ffd8c914fb201471d1c3d245ce3c746fcbe63a3679d51b6a516ebebe0e20 test-invalid
|
||||
0xc34c4e1826e5d403b78e246e88aa051c36ccf0aafebffe137d148a2bf9104562 test-invalid
|
||||
0xc940e5a4404157cfb1628b108db051a8d439e1a421394ec4ebccb9ec92a8ac78 test-invalid
|
||||
0x47cfc5497c53dc8e61c91d17fd626ffb1c49e2bca94eed052281b510b1117a24 test-invalid
|
||||
0xf1c6165d33367351b0da8f6e4511010c68174a03b6581212c71c0e1d026c3c72 test-invalid
|
||||
0x87260f7a2f12495118360f02c26a470f450dadf34a413d21042b43b9d93e1309 test-invalid
|
||||
// These are all bad because they give a nonsquare x^2.
|
||||
0x26948d35ca62e643e26a83177332e6b6afeb9d08e4268b650f1f5bbd8d81d371 test-invalid
|
||||
0x4eac077a713c57b4f4397629a4145982c661f48044dd3f96427d40b147d9742f test-invalid
|
||||
0xde6a7b00deadc788eb6b6c8d20c0ae96c2f2019078fa604fee5b87d6e989ad7b test-invalid
|
||||
0xbcab477be20861e01e4a0e295284146a510150d9817763caf1a6f4b422d67042 test-invalid
|
||||
0x2a292df7e32cababbd9de088d1d1abec9fc0440f637ed2fba145094dc14bea08 test-invalid
|
||||
0xf4a9e534fc0d216c44b218fa0c42d99635a0127ee2e53c712f70609649fdff22 test-invalid
|
||||
0x8268436f8c4126196cf64b3c7ddbda90746a378625f9813dd9b8457077256731 test-invalid
|
||||
0x2810e5cbc2cc4d4eece54f61c6f69758e289aa7ab440b3cbeaa21995c2f4232b test-invalid
|
||||
// These are all bad because they give a negative xy value.
|
||||
0x3eb858e78f5a7254d8c9731174a94f76755fd3941c0ac93735c07ba14579630e test-invalid
|
||||
0xa45fdc55c76448c049a1ab33f17023edfb2be3581e9c7aade8a6125215e04220 test-invalid
|
||||
0xd483fe813c6ba647ebbfd3ec41adca1c6130c2beeee9d9bf065c8d151c5f396e test-invalid
|
||||
0x8a2e1d30050198c65a54483123960ccc38aef6848e1ec8f5f780e8523769ba32 test-invalid
|
||||
0x32888462f8b486c68ad7dd9610be5192bbeaf3b443951ac1a8118419d9fa097b test-invalid
|
||||
0x227142501b9d4355ccba290404bde41575b037693cef1f438c47f8fbf35d1165 test-invalid
|
||||
0x5c37cc491da847cfeb9281d407efc41e15144c876e0170b499a96a22ed31e01e test-invalid
|
||||
0x445425117cb8c90edcbc7c1cc0e74f747f2c1efa5630a967c64f287792a48a4b test-invalid
|
||||
// This is s = -1, which causes y = 0.
|
||||
0xecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f test-invalid
|
||||
|
||||
cr ."Hash to point:" cr
|
||||
{
|
||||
=: text =: ans
|
||||
@' text $>s
|
||||
[[ <{ 1 INT HASHEXT_SHA512 2 UNTUPLE RIST255_FROMHASH }>s ]] 0 runvmx abort"Exitcode != 0"
|
||||
@' ans <> abort"Invalid result"
|
||||
@' ans (x.) type ." " @' text type cr
|
||||
} : test-hash
|
||||
|
||||
0x3066f82a1a747d45120d1740f14358531a8f04bbffe6a819f86dfe50f44a0a46 "Ristretto is traditionally a short shot of espresso coffee" test-hash
|
||||
0xf26e5b6f7d362d2d2a94c5d0e7602cb4773c95a2e5c31a64f133189fa76ed61b "made with the normal amount of ground coffee but extracted with" test-hash
|
||||
0x006ccd2a9e6867e6a2c5cea83d3302cc9de128dd2a9a57dd8ee7b9d7ffe02826 "about half the amount of water in the same amount of time" test-hash
|
||||
0xf8f0c87cf237953c5890aec3998169005dae3eca1fbb04548c635953c817f92a "by using a finer grind." test-hash
|
||||
0xae81e7dedf20a497e10c304a765c1767a42d6e06029758d2d7e8ef7cc4c41179 "This produces a concentrated shot of coffee per volume." test-hash
|
||||
0xe2705652ff9f5e44d3e841bf1c251cf7dddb77d140870d1ab2ed64f1a9ce8628 "Just pulling a normal shot short will produce a weaker shot" test-hash
|
||||
0x80bd07262511cdde4863f8a7434cef696750681cb9510eea557088f76d9e5065 "and is not a Ristretto as some believe." test-hash
|
228
crypto/test/fift/tvm_runvm.fif
Normal file
228
crypto/test/fift/tvm_runvm.fif
Normal file
|
@ -0,0 +1,228 @@
|
|||
"Asm.fif" include
|
||||
|
||||
// Just run
|
||||
111 10 20 2
|
||||
<{
|
||||
ADD // Ensure that stack was passed to runvmx
|
||||
DEPTH // Ensure that only 2 stack entries were passed
|
||||
c4 PUSH CTOS SBITREFS // Ensure that c4 is empty
|
||||
c5 PUSH CTOS SBITREFS // Ensure that c5 is empty
|
||||
c7 PUSH // Ensure that c7 is empty
|
||||
<b x{99991111} s, b> PUSHREF c4 POP // Ensure that it does not affect c4, c5, c7 in parent vm
|
||||
<b x{aaaabbbb} s, b> PUSHREF c5 POP
|
||||
NIL 100 PUSHINT TPUSH 200 PUSHINT TPUSH c7 POP
|
||||
123 PUSHINT
|
||||
}>s
|
||||
<{
|
||||
<b x{1234} s, b> PUSHREF c4 POP
|
||||
<b x{5678} s, b> PUSHREF c5 POP
|
||||
NIL 5 PUSHINT TPUSH 6 PUSHINT TPUSH c7 POP
|
||||
0 RUNVM
|
||||
c4 PUSH CTOS c5 PUSH CTOS c7 PUSH // Ensure that c4, c5, c7 are unchanged
|
||||
}>s 1000000 8 runvmx // Show gas usage
|
||||
.s { drop } depth 1- times // 111 30 1 0 0 0 0 [] 123 0 x{1234} x{5678} [ 5 6 ] 0 1197
|
||||
|
||||
// Exception
|
||||
111 10 20 2
|
||||
<{ 22 PUSHINT 55 PUSHINT 66 THROWARG }>s
|
||||
<{ 0 RUNVM }>s 0 runvmx
|
||||
.s { drop } depth 1- times // 111 55 66 0
|
||||
|
||||
// Mode +1 - set c3 to code
|
||||
PROGRAM{
|
||||
22 DECLMETHOD foo
|
||||
DECLPROC main
|
||||
foo PROC:<{
|
||||
MUL
|
||||
}>
|
||||
main PROC:<{
|
||||
DUP
|
||||
foo CALLDICT
|
||||
INC
|
||||
}>
|
||||
}END>s constant prog
|
||||
<{
|
||||
10 PUSHINT 0 PUSHINT 2 PUSHINT prog PUSHSLICE 1 RUNVM
|
||||
10 PUSHINT 0 PUSHINT 2 PUSHINT prog PUSHSLICE 0 RUNVM
|
||||
}>s 0 runvmx
|
||||
.s { drop } depth 1- times // 101 0 10 10 22 11 0
|
||||
|
||||
// Mode +2 - push 0
|
||||
<{ 10 PUSHINT 1 PUSHINT prog PUSHSLICE 3 RUNVM }>s 0 runvmx
|
||||
.s { drop } depth 1- times // 101 0 0
|
||||
|
||||
// Mode +4 - load and return c4
|
||||
0
|
||||
<{
|
||||
c4 PUSHCTR CTOS // Ensure that this is x{5678}
|
||||
<b x{abcd} s, b> PUSHREF c4 POPCTR // This should be returned from RUNVM
|
||||
1000 PUSHINT
|
||||
}>s
|
||||
<b x{5678} s, b>
|
||||
<{
|
||||
<b x{1234} s, b> PUSHREF c4 POP // Ensure that this does not change
|
||||
4 RUNVM
|
||||
CTOS
|
||||
c4 PUSH CTOS // x{1234}
|
||||
}>s 0 runvmx
|
||||
.s { drop } depth 1- times // x{5678} 1000 0 x{abcd} x{1234} 0
|
||||
|
||||
// Mode +16 - load c7
|
||||
0
|
||||
<{
|
||||
c7 PUSH // Ensure that this is [ 10 15 20 ]
|
||||
NIL 111 PUSHINT TPUSH 222 PUSHINT TPUSH 3333 PUSHINT TPUSH c7 POP
|
||||
1000 PUSHINT
|
||||
}>s
|
||||
10 15 20 3 tuple
|
||||
<{
|
||||
NIL 1 PUSHINT TPUSH 2 PUSHINT TPUSH 3 PUSHINT TPUSH c7 POP // Ensure that this does not change
|
||||
16 RUNVM
|
||||
c7 PUSH // [ 1 2 3 ]
|
||||
}>s 0 runvmx
|
||||
.s { drop } depth 1- times // [ 10 15 20 ] 1000 0 [ 1 2 3 ] 0
|
||||
|
||||
// Mode +32 - return c5
|
||||
0
|
||||
<{
|
||||
c5 PUSH CTOS SBITREFS // Ensure that this is empty
|
||||
<b x{5678} s, b> PUSHREF c5 POP // Ensure that this is returned from RUNVM
|
||||
1000 PUSHINT
|
||||
}>s
|
||||
<{
|
||||
<b x{1234} s, b> PUSHREF c5 POP // Ensure that this does not change
|
||||
32 RUNVM
|
||||
CTOS
|
||||
c5 PUSH CTOS // x{1234}
|
||||
}>s 0 runvmx
|
||||
.s { drop } depth 1- times // 0 0 1000 0 x{5678} x{1234} 0
|
||||
|
||||
// c4, c5 with exception
|
||||
0
|
||||
<{
|
||||
<b x{abcdaaaa} s, b> PUSHREF c4 POP
|
||||
<b x{abcdbbbb} s, b> PUSHREF c5 POP
|
||||
55 THROW
|
||||
}>s
|
||||
<b x{5678} s, b> // c4 for RUNVM
|
||||
<{
|
||||
<b x{1234aaaa} s, b> PUSHREF c4 POP // Ensure that this does not change
|
||||
<b x{1234bbbb} s, b> PUSHREF c5 POP // Ensure that this does not change
|
||||
32 4 + RUNVM
|
||||
c4 PUSH CTOS // x{1234aaaa}
|
||||
c5 PUSH CTOS // x{1234bbbb}
|
||||
}>s 0 runvmx
|
||||
.s { drop } depth 1- times // 0 55 null null x{1234aaaa} x{1234bbbb} 0
|
||||
|
||||
// c4, c5 with exception and commit
|
||||
0
|
||||
<{
|
||||
<b x{abcdaaaa} s, b> PUSHREF c4 POP
|
||||
<b x{abcdbbbb} s, b> PUSHREF c5 POP
|
||||
COMMIT
|
||||
<b x{} s, b> PUSHREF c4 POP
|
||||
<b x{} s, b> PUSHREF c5 POP
|
||||
55 THROW
|
||||
}>s
|
||||
<b x{5678} s, b> // c4 for RUNVM
|
||||
<{
|
||||
<b x{1234aaaa} s, b> PUSHREF c4 POP // Ensure that this does not change
|
||||
<b x{1234bbbb} s, b> PUSHREF c5 POP // Ensure that this does not change
|
||||
32 4 + RUNVM
|
||||
CTOS SWAP CTOS SWAP
|
||||
c4 PUSH CTOS // x{1234aaaa}
|
||||
c5 PUSH CTOS // x{1234bbbb}
|
||||
}>s 0 runvmx
|
||||
.s { drop } depth 1- times // 0 55 x{abcdaaaa} x{abcdbbbb} x{1234aaaa} x{1234bbbb} 0
|
||||
|
||||
// Mode +8 - gas limit
|
||||
0
|
||||
<{ AGAIN:<{ NOP }> }>s
|
||||
200
|
||||
<{ 8 RUNVM 1234 PUSHINT }>s 0 runvmx
|
||||
.s { drop } depth 1- times // 215 -14 215 1234 0
|
||||
|
||||
// Gas limit of parent vm is too low
|
||||
0
|
||||
<{ AGAIN:<{ NOP }> }>s
|
||||
1000000
|
||||
<{ 8 RUNVM 1234 PUSHINT }>s 300 8 runvmx
|
||||
.s { drop } depth 1- times // 301 -14 301
|
||||
|
||||
// Mode +64 - hard gas limit
|
||||
0 <{ AGAIN:<{ NOP }> }>s 200 500
|
||||
<{ 8 64 + RUNVM 1234 PUSHINT }>s 0 runvmx
|
||||
.s { drop } depth 1- times // 215 -14 215 1234 0
|
||||
0 <{ ACCEPT AGAIN:<{ NOP }> }>s 200 500
|
||||
<{ 8 64 + RUNVM 1234 PUSHINT }>s 0 runvmx
|
||||
.s { drop } depth 1- times // 517 -14 517 1234 0
|
||||
|
||||
// 10000 nested VMs (recursively calculating 1+...+10000)
|
||||
<{
|
||||
DUP
|
||||
0 EQINT
|
||||
IFJMP:<{
|
||||
DROP DROP
|
||||
0 PUSHINT
|
||||
}>
|
||||
OVER OVER DEC
|
||||
2 PUSHINT
|
||||
s2 PUSH
|
||||
0 RUNVM
|
||||
11 THROWIF
|
||||
ADD
|
||||
NIP
|
||||
}>s constant code1
|
||||
<{ code1 PUSHSLICE 10000 PUSHINT 2 PUSHINT code1 PUSHSLICE 0 RUNVM }>s 10000000 8 runvmx // Show gas
|
||||
.s { drop } depth 1- times // 50005000 0 0 2710286
|
||||
|
||||
// Same thing, but out of gas
|
||||
<{ code1 PUSHSLICE 10000 PUSHINT 2 PUSHINT code1 PUSHSLICE 0 RUNVM }>s 100000 8 runvmx // Show gas
|
||||
.s { drop } depth 1- times // 100001 -14 100001
|
||||
|
||||
// RUNVMX
|
||||
0
|
||||
<{ AGAIN:<{ NOP }> }>s
|
||||
200
|
||||
<{ 8 PUSHINT RUNVMX 1234 PUSHINT }>s 0 runvmx
|
||||
.s { drop } depth 1- times // 215 -14 215 1234 0
|
||||
|
||||
// +128 - separate loaded_cells
|
||||
<b x{12345678} s, b> <b x{87654321} s, b>
|
||||
<{ DUP CTOS DROP 2 INT <{ CTOS DROP CTOS DROP }>s SLICE 10000 INT 8 RUNVM }>s 1000000 8 runvmx
|
||||
.s { drop } depth 1- times // 0 202 0 509
|
||||
<b x{12345678} s, b> <b x{87654321} s, b>
|
||||
<{ DUP CTOS DROP 2 INT <{ CTOS DROP CTOS DROP }>s SLICE 10000 INT 8 128 + RUNVM }>s 1000000 8 runvmx
|
||||
.s { drop } depth 1- times // 0 277 0 584
|
||||
|
||||
// +256 - fixed number of return values
|
||||
11 22 33 3
|
||||
<{ 1 INT 2 INT 3 INT 4 INT 5 INT }>s
|
||||
3
|
||||
<{ 256 RUNVM }>s 0 runvmx
|
||||
.s { drop } depth 1- times // 3 4 5 0 0
|
||||
|
||||
11 22 33 3
|
||||
<{ 1 INT 2 INT 3 INT 4 INT 5 INT }>s
|
||||
0
|
||||
<{ 256 RUNVM }>s 0 runvmx
|
||||
.s { drop } depth 1- times // 0 0
|
||||
|
||||
11 22 33 3
|
||||
<{ 1 INT 2 INT 3 INT 4 INT 5 INT 77 THROW }>s
|
||||
3
|
||||
<{ 256 RUNVM }>s 0 runvmx
|
||||
.s { drop } depth 1- times // 0 77 0
|
||||
|
||||
11 22 33 3
|
||||
<{ 1 INT 2 INT 3 INT 4 INT 5 INT }>s
|
||||
20
|
||||
<{ 256 RUNVM }>s 0 runvmx
|
||||
.s { drop } depth 1- times // 0 -3 0
|
||||
|
||||
// GASCONSUMED
|
||||
<{ 10 INT 20 INT ADD DROP GASCONSUMED }>s 0 runvmx
|
||||
.s { drop } depth 1- times // 106 0
|
||||
0 <{ 10 INT 20 INT ADD DROP GASCONSUMED }>s
|
||||
<{ 100 INT 200 INT 300 INT MUL DIV DROP 0 RUNVM GASCONSUMED }>s 0 runvmx
|
||||
.s { drop } depth 1- times // 106 0 367 0
|
|
@ -1998,7 +1998,7 @@ TypeExpr* parse_anonymous_constructor(Lexer& lex, Constructor& cs) {
|
|||
if (types[i].parent_type_idx >= 0) {
|
||||
types[i].parent_type_idx = -2;
|
||||
}
|
||||
delete cs2;
|
||||
cs2->~Constructor();
|
||||
return TypeExpr::mk_apply_empty(lex.cur().loc, 0, &types[i]);
|
||||
}
|
||||
}
|
||||
|
|
148
crypto/vm/Hasher.cpp
Normal file
148
crypto/vm/Hasher.cpp
Normal file
|
@ -0,0 +1,148 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "vm/Hasher.h"
|
||||
#include "vm/excno.hpp"
|
||||
#include "vm/vm.h"
|
||||
#include <iostream>
|
||||
#include <openssl/evp.h>
|
||||
#include "keccak/keccak.h"
|
||||
|
||||
namespace vm {
|
||||
|
||||
using td::Ref;
|
||||
|
||||
class HasherImplEVP : public Hasher::HasherImpl {
|
||||
public:
|
||||
explicit HasherImplEVP(EVP_MD_CTX* ctx) : ctx_(ctx) {
|
||||
}
|
||||
|
||||
~HasherImplEVP() override {
|
||||
EVP_MD_CTX_free(ctx_);
|
||||
}
|
||||
|
||||
void append(const unsigned char *data, size_t size) override {
|
||||
CHECK(EVP_DigestUpdate(ctx_, data, size));
|
||||
}
|
||||
|
||||
td::BufferSlice finish() override {
|
||||
td::BufferSlice hash(EVP_MD_CTX_size(ctx_));
|
||||
unsigned size;
|
||||
CHECK(EVP_DigestFinal_ex(ctx_, (unsigned char *)hash.data(), &size) || size != hash.size());
|
||||
return hash;
|
||||
}
|
||||
|
||||
std::unique_ptr<HasherImpl> make_copy() const override {
|
||||
EVP_MD_CTX *new_ctx = nullptr;
|
||||
new_ctx = EVP_MD_CTX_new();
|
||||
CHECK(new_ctx != nullptr);
|
||||
CHECK(EVP_MD_CTX_copy_ex(new_ctx, ctx_));
|
||||
return std::make_unique<HasherImplEVP>(new_ctx);
|
||||
}
|
||||
|
||||
private:
|
||||
EVP_MD_CTX *ctx_;
|
||||
};
|
||||
|
||||
class HasherImplKeccak : public Hasher::HasherImpl {
|
||||
public:
|
||||
explicit HasherImplKeccak(size_t hash_size) : hash_size_(hash_size) {
|
||||
CHECK(keccak_init(&state_, hash_size * 2, 24) == 0);
|
||||
CHECK(state_ != nullptr);
|
||||
}
|
||||
|
||||
~HasherImplKeccak() override {
|
||||
CHECK(keccak_destroy(state_) == 0);
|
||||
}
|
||||
|
||||
void append(const unsigned char *data, size_t size) override {
|
||||
CHECK(keccak_absorb(state_, data, size) == 0);
|
||||
}
|
||||
|
||||
td::BufferSlice finish() override {
|
||||
td::BufferSlice hash(hash_size_);
|
||||
CHECK(keccak_digest(state_, (unsigned char*)hash.data(), hash_size_, 1) == 0);
|
||||
return hash;
|
||||
}
|
||||
|
||||
std::unique_ptr<HasherImpl> make_copy() const override {
|
||||
auto copy = std::make_unique<HasherImplKeccak>(hash_size_);
|
||||
CHECK(keccak_copy(state_, copy->state_) == 0);
|
||||
return copy;
|
||||
}
|
||||
|
||||
private:
|
||||
size_t hash_size_;
|
||||
keccak_state *state_ = nullptr;
|
||||
};
|
||||
|
||||
Hasher::Hasher(int hash_id) : id_(hash_id) {
|
||||
if (hash_id == KECCAK256 || hash_id == KECCAK512) {
|
||||
impl_ = std::make_unique<HasherImplKeccak>(hash_id == KECCAK256 ? 32 : 64);
|
||||
return;
|
||||
}
|
||||
|
||||
EVP_MD_CTX *ctx = EVP_MD_CTX_new();
|
||||
CHECK(ctx != nullptr);
|
||||
const EVP_MD *evp;
|
||||
switch (hash_id) {
|
||||
case SHA256: evp = EVP_sha256(); break;
|
||||
case SHA512: evp = EVP_sha512(); break;
|
||||
case BLAKE2B: evp = EVP_blake2b512(); break;
|
||||
default:
|
||||
throw VmError{Excno::range_chk, "invalid hash id"};
|
||||
}
|
||||
CHECK(evp != nullptr && EVP_DigestInit_ex(ctx, evp, nullptr));
|
||||
impl_ = std::make_unique<HasherImplEVP>(ctx);
|
||||
}
|
||||
|
||||
void Hasher::append(td::ConstBitPtr data, unsigned size) {
|
||||
if (!impl_) {
|
||||
throw VmError{Excno::unknown, "can't use finished hasher"};
|
||||
}
|
||||
while (size > 0) {
|
||||
unsigned cur_size = std::min(size, BUF_SIZE * 8 - buf_ptr_);
|
||||
td::BitPtr{buf_, (int)buf_ptr_}.copy_from(data, cur_size);
|
||||
buf_ptr_ += cur_size;
|
||||
if (buf_ptr_ == BUF_SIZE * 8) {
|
||||
impl_->append(buf_, BUF_SIZE);
|
||||
buf_ptr_ = 0;
|
||||
}
|
||||
size -= cur_size;
|
||||
data += cur_size;
|
||||
}
|
||||
}
|
||||
|
||||
td::BufferSlice Hasher::finish() {
|
||||
if (!impl_) {
|
||||
throw VmError{Excno::unknown, "can't use finished hasher"};
|
||||
}
|
||||
if (buf_ptr_ % 8 != 0) {
|
||||
throw VmError{Excno::cell_und, "data does not consist of an integer number of bytes"};
|
||||
}
|
||||
impl_->append(buf_, buf_ptr_ / 8);
|
||||
td::BufferSlice hash = impl_->finish();
|
||||
impl_ = nullptr;
|
||||
return hash;
|
||||
}
|
||||
|
||||
static const size_t BYTES_PER_GAS_UNIT[5] = {33, 16, 19, 11, 6};
|
||||
|
||||
size_t Hasher::bytes_per_gas_unit() const {
|
||||
return BYTES_PER_GAS_UNIT[id_];
|
||||
}
|
||||
|
||||
}
|
58
crypto/vm/Hasher.h
Normal file
58
crypto/vm/Hasher.h
Normal file
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include "common/refcnt.hpp"
|
||||
#include "td/utils/buffer.h"
|
||||
#include "common/bitstring.h"
|
||||
#include "vm/cells/Cell.h"
|
||||
#include <memory>
|
||||
|
||||
namespace vm {
|
||||
|
||||
using td::Ref;
|
||||
|
||||
class Hasher {
|
||||
public:
|
||||
explicit Hasher(int id);
|
||||
Hasher(const Hasher&) = delete;
|
||||
void append(td::ConstBitPtr data, unsigned size);
|
||||
td::BufferSlice finish();
|
||||
size_t bytes_per_gas_unit() const;
|
||||
|
||||
static const int SHA256 = 0;
|
||||
static const int SHA512 = 1;
|
||||
static const int BLAKE2B = 2;
|
||||
static const int KECCAK256 = 3;
|
||||
static const int KECCAK512 = 4;
|
||||
|
||||
class HasherImpl {
|
||||
public:
|
||||
virtual ~HasherImpl() = default;
|
||||
virtual void append(const unsigned char* data, size_t size) = 0;
|
||||
virtual td::BufferSlice finish() = 0;
|
||||
virtual std::unique_ptr<HasherImpl> make_copy() const = 0;
|
||||
};
|
||||
|
||||
private:
|
||||
int id_ = 0;
|
||||
static const unsigned BUF_SIZE = 256;
|
||||
unsigned char buf_[BUF_SIZE];
|
||||
unsigned buf_ptr_ = 0;
|
||||
std::unique_ptr<HasherImpl> impl_;
|
||||
};
|
||||
|
||||
}
|
|
@ -265,26 +265,42 @@ void register_add_mul_ops(OpcodeTable& cp0) {
|
|||
|
||||
int exec_divmod(VmState* st, unsigned args, int quiet) {
|
||||
int round_mode = (int)(args & 3) - 1;
|
||||
if (!(args & 12) || round_mode == 2) {
|
||||
unsigned d = (args >> 2) & 3;
|
||||
bool add = false;
|
||||
if (d == 0 && st->get_global_version() >= 4) {
|
||||
d = 3;
|
||||
add = true;
|
||||
}
|
||||
if (d == 0 || round_mode == 2) {
|
||||
throw VmError{Excno::inv_opcode};
|
||||
}
|
||||
Stack& stack = st->get_stack();
|
||||
VM_LOG(st) << "execute DIV/MOD " << (args & 15);
|
||||
stack.check_underflow(2);
|
||||
stack.check_underflow(add ? 3 : 2);
|
||||
auto y = stack.pop_int();
|
||||
auto w = add ? stack.pop_int() : td::RefInt256{};
|
||||
auto x = stack.pop_int();
|
||||
switch ((args >> 2) & 3) {
|
||||
case 1:
|
||||
stack.push_int_quiet(td::div(std::move(x), std::move(y), round_mode), quiet);
|
||||
break;
|
||||
case 2:
|
||||
stack.push_int_quiet(td::mod(std::move(x), std::move(y), round_mode), quiet);
|
||||
break;
|
||||
case 3: {
|
||||
auto dm = td::divmod(std::move(x), std::move(y), round_mode);
|
||||
stack.push_int_quiet(std::move(dm.first), quiet);
|
||||
stack.push_int_quiet(std::move(dm.second), quiet);
|
||||
break;
|
||||
if (add) {
|
||||
CHECK(d == 3);
|
||||
typename td::BigInt256::DoubleInt tmp{*x}, quot;
|
||||
tmp += *w;
|
||||
tmp.mod_div(*y, quot, round_mode);
|
||||
stack.push_int_quiet(td::make_refint(quot), quiet);
|
||||
stack.push_int_quiet(td::make_refint(tmp), quiet);
|
||||
} else {
|
||||
switch (d) {
|
||||
case 1:
|
||||
stack.push_int_quiet(td::div(std::move(x), std::move(y), round_mode), quiet);
|
||||
break;
|
||||
case 2:
|
||||
stack.push_int_quiet(td::mod(std::move(x), std::move(y), round_mode), quiet);
|
||||
break;
|
||||
case 3: {
|
||||
auto dm = td::divmod(std::move(x), std::move(y), round_mode);
|
||||
stack.push_int_quiet(std::move(dm.first), quiet);
|
||||
stack.push_int_quiet(std::move(dm.second), quiet);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
@ -292,11 +308,20 @@ int exec_divmod(VmState* st, unsigned args, int quiet) {
|
|||
|
||||
std::string dump_divmod(CellSlice&, unsigned args, bool quiet) {
|
||||
int round_mode = (int)(args & 3);
|
||||
if (!(args & 12) || round_mode == 3) {
|
||||
unsigned d = (args >> 2) & 3;
|
||||
bool add = false;
|
||||
if (d == 0) {
|
||||
d = 3;
|
||||
add = true;
|
||||
}
|
||||
if (round_mode == 3) {
|
||||
return "";
|
||||
}
|
||||
std::string s = (args & 4) ? "DIV" : "";
|
||||
if (args & 8) {
|
||||
std::string s = add ? "ADD" : "";
|
||||
if (d & 1) {
|
||||
s += "DIV";
|
||||
}
|
||||
if (d & 2) {
|
||||
s += "MOD";
|
||||
}
|
||||
if (quiet) {
|
||||
|
@ -312,32 +337,50 @@ int exec_shrmod(VmState* st, unsigned args, int mode) {
|
|||
args >>= 8;
|
||||
}
|
||||
int round_mode = (int)(args & 3) - 1;
|
||||
if (!(args & 12) || round_mode == 2) {
|
||||
unsigned d = (args >> 2) & 3;
|
||||
bool add = false;
|
||||
if (d == 0 && st->get_global_version() >= 4) {
|
||||
d = 3;
|
||||
add = true;
|
||||
}
|
||||
if (d == 0 || round_mode == 2) {
|
||||
throw VmError{Excno::inv_opcode};
|
||||
}
|
||||
Stack& stack = st->get_stack();
|
||||
VM_LOG(st) << "execute SHR/MOD " << (args & 15) << ',' << y;
|
||||
if (!(mode & 2)) {
|
||||
stack.check_underflow(2);
|
||||
stack.check_underflow(add ? 3 : 2);
|
||||
y = stack.pop_smallint_range(256);
|
||||
} else {
|
||||
stack.check_underflow(1);
|
||||
stack.check_underflow(add ? 2 : 1);
|
||||
}
|
||||
if (!y) {
|
||||
round_mode = -1;
|
||||
}
|
||||
auto w = add ? stack.pop_int() : td::RefInt256{};
|
||||
auto x = stack.pop_int();
|
||||
switch ((args >> 2) & 3) {
|
||||
case 1:
|
||||
stack.push_int_quiet(td::rshift(std::move(x), y, round_mode), mode & 1);
|
||||
break;
|
||||
case 3:
|
||||
stack.push_int_quiet(td::rshift(x, y, round_mode), mode & 1);
|
||||
// fallthrough
|
||||
case 2:
|
||||
x.write().mod_pow2(y, round_mode).normalize();
|
||||
stack.push_int_quiet(std::move(x), mode & 1);
|
||||
break;
|
||||
if (add) {
|
||||
CHECK(d == 3);
|
||||
typename td::BigInt256::DoubleInt tmp{*x}, quot;
|
||||
tmp += *w;
|
||||
typename td::BigInt256::DoubleInt tmp2{tmp};
|
||||
tmp2.rshift(y, round_mode).normalize();
|
||||
stack.push_int_quiet(td::make_refint(tmp2), mode & 1);
|
||||
tmp.normalize().mod_pow2(y, round_mode).normalize();
|
||||
stack.push_int_quiet(td::make_refint(tmp), mode & 1);
|
||||
} else {
|
||||
switch (d) {
|
||||
case 1:
|
||||
stack.push_int_quiet(td::rshift(std::move(x), y, round_mode), mode & 1);
|
||||
break;
|
||||
case 3:
|
||||
stack.push_int_quiet(td::rshift(x, y, round_mode), mode & 1);
|
||||
// fallthrough
|
||||
case 2:
|
||||
x.write().mod_pow2(y, round_mode).normalize();
|
||||
stack.push_int_quiet(std::move(x), mode & 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -349,7 +392,7 @@ std::string dump_shrmod(CellSlice&, unsigned args, int mode) {
|
|||
args >>= 8;
|
||||
}
|
||||
int round_mode = (int)(args & 3);
|
||||
if (!(args & 12) || round_mode == 3) {
|
||||
if (round_mode == 3) {
|
||||
return "";
|
||||
}
|
||||
std::ostringstream os;
|
||||
|
@ -366,6 +409,9 @@ std::string dump_shrmod(CellSlice&, unsigned args, int mode) {
|
|||
case 12:
|
||||
os << "RSHIFTMOD";
|
||||
break;
|
||||
case 0:
|
||||
os << "ADDRSHIFTMOD";
|
||||
break;
|
||||
}
|
||||
if (round_mode) {
|
||||
os << "FRC"[round_mode];
|
||||
|
@ -378,20 +424,30 @@ std::string dump_shrmod(CellSlice&, unsigned args, int mode) {
|
|||
|
||||
int exec_muldivmod(VmState* st, unsigned args, int quiet) {
|
||||
int round_mode = (int)(args & 3) - 1;
|
||||
if (!(args & 12) || round_mode == 2) {
|
||||
unsigned d = (args >> 2) & 3;
|
||||
bool add = false;
|
||||
if (d == 0 && st->get_global_version() >= 4) {
|
||||
d = 3;
|
||||
add = true;
|
||||
}
|
||||
if (d == 0 || round_mode == 2) {
|
||||
throw VmError{Excno::inv_opcode};
|
||||
}
|
||||
Stack& stack = st->get_stack();
|
||||
VM_LOG(st) << "execute MULDIV/MOD " << (args & 15);
|
||||
stack.check_underflow(3);
|
||||
stack.check_underflow(add ? 4 : 3);
|
||||
auto z = stack.pop_int();
|
||||
auto w = add ? stack.pop_int() : td::RefInt256{};
|
||||
auto y = stack.pop_int();
|
||||
auto x = stack.pop_int();
|
||||
typename td::BigInt256::DoubleInt tmp{0}, quot;
|
||||
if (add) {
|
||||
tmp = *w;
|
||||
}
|
||||
tmp.add_mul(*x, *y);
|
||||
auto q = td::make_refint();
|
||||
tmp.mod_div(*z, quot, round_mode);
|
||||
switch ((args >> 2) & 3) {
|
||||
switch (d) {
|
||||
case 1:
|
||||
stack.push_int_quiet(td::make_refint(quot.normalize()), quiet);
|
||||
break;
|
||||
|
@ -407,11 +463,20 @@ int exec_muldivmod(VmState* st, unsigned args, int quiet) {
|
|||
|
||||
std::string dump_muldivmod(CellSlice&, unsigned args, bool quiet) {
|
||||
int round_mode = (int)(args & 3);
|
||||
if (!(args & 12) || round_mode == 3) {
|
||||
unsigned d = (args >> 2) & 3;
|
||||
bool add = false;
|
||||
if (d == 0) {
|
||||
d = 3;
|
||||
add = true;
|
||||
}
|
||||
if (round_mode == 3) {
|
||||
return "";
|
||||
}
|
||||
std::string s = (args & 4) ? "MULDIV" : "MUL";
|
||||
if (args & 8) {
|
||||
std::string s = add ? "MULADD" : "MUL";
|
||||
if (d & 1) {
|
||||
s += "DIV";
|
||||
}
|
||||
if (d & 2) {
|
||||
s += "MOD";
|
||||
}
|
||||
if (quiet) {
|
||||
|
@ -427,25 +492,35 @@ int exec_mulshrmod(VmState* st, unsigned args, int mode) {
|
|||
args >>= 8;
|
||||
}
|
||||
int round_mode = (int)(args & 3) - 1;
|
||||
if (!(args & 12) || round_mode == 2) {
|
||||
unsigned d = (args >> 2) & 3;
|
||||
bool add = false;
|
||||
if (d == 0 && st->get_global_version() >= 4) {
|
||||
d = 3;
|
||||
add = true;
|
||||
}
|
||||
if (d == 0 || round_mode == 2) {
|
||||
throw VmError{Excno::inv_opcode};
|
||||
}
|
||||
Stack& stack = st->get_stack();
|
||||
VM_LOG(st) << "execute MULSHR/MOD " << (args & 15) << ',' << z;
|
||||
if (!(mode & 2)) {
|
||||
stack.check_underflow(3);
|
||||
stack.check_underflow(add ? 4 : 3);
|
||||
z = stack.pop_smallint_range(256);
|
||||
} else {
|
||||
stack.check_underflow(2);
|
||||
stack.check_underflow(add ? 3 : 2);
|
||||
}
|
||||
if (!z) {
|
||||
round_mode = -1;
|
||||
}
|
||||
auto w = add ? stack.pop_int() : td::RefInt256{};
|
||||
auto y = stack.pop_int();
|
||||
auto x = stack.pop_int();
|
||||
typename td::BigInt256::DoubleInt tmp{0};
|
||||
if (add) {
|
||||
tmp = *w;
|
||||
}
|
||||
tmp.add_mul(*x, *y);
|
||||
switch ((args >> 2) & 3) {
|
||||
switch (d) {
|
||||
case 1:
|
||||
tmp.rshift(z, round_mode).normalize();
|
||||
stack.push_int_quiet(td::make_refint(tmp), mode & 1);
|
||||
|
@ -471,7 +546,7 @@ std::string dump_mulshrmod(CellSlice&, unsigned args, int mode) {
|
|||
args >>= 8;
|
||||
}
|
||||
int round_mode = (int)(args & 3);
|
||||
if (!(args & 12) || round_mode == 3) {
|
||||
if (round_mode == 3) {
|
||||
return "";
|
||||
}
|
||||
std::ostringstream os;
|
||||
|
@ -488,6 +563,9 @@ std::string dump_mulshrmod(CellSlice&, unsigned args, int mode) {
|
|||
case 12:
|
||||
os << "MULRSHIFTMOD";
|
||||
break;
|
||||
case 0:
|
||||
os << "MULADDRSHIFTMOD";
|
||||
break;
|
||||
}
|
||||
if (round_mode) {
|
||||
os << "FRC"[round_mode];
|
||||
|
@ -505,22 +583,32 @@ int exec_shldivmod(VmState* st, unsigned args, int mode) {
|
|||
args >>= 8;
|
||||
}
|
||||
int round_mode = (int)(args & 3) - 1;
|
||||
if (!(args & 12) || round_mode == 2) {
|
||||
unsigned d = (args >> 2) & 3;
|
||||
bool add = false;
|
||||
if (d == 0 && st->get_global_version() >= 4) {
|
||||
d = 3;
|
||||
add = true;
|
||||
}
|
||||
if (d == 0 || round_mode == 2) {
|
||||
throw VmError{Excno::inv_opcode};
|
||||
}
|
||||
Stack& stack = st->get_stack();
|
||||
VM_LOG(st) << "execute SHLDIV/MOD " << (args & 15) << ',' << y;
|
||||
if (!(mode & 2)) {
|
||||
stack.check_underflow(3);
|
||||
stack.check_underflow(add ? 4 : 3);
|
||||
y = stack.pop_smallint_range(256);
|
||||
} else {
|
||||
stack.check_underflow(2);
|
||||
stack.check_underflow(add ? 3 : 2);
|
||||
}
|
||||
auto z = stack.pop_int();
|
||||
auto w = add ? stack.pop_int() : td::RefInt256{};
|
||||
auto x = stack.pop_int();
|
||||
typename td::BigInt256::DoubleInt tmp{*x}, quot;
|
||||
tmp <<= y;
|
||||
switch ((args >> 2) & 3) {
|
||||
if (add) {
|
||||
tmp += *w;
|
||||
}
|
||||
switch (d) {
|
||||
case 1: {
|
||||
tmp.mod_div(*z, quot, round_mode);
|
||||
stack.push_int_quiet(td::make_refint(quot.normalize()), mode & 1);
|
||||
|
@ -549,11 +637,27 @@ std::string dump_shldivmod(CellSlice&, unsigned args, int mode) {
|
|||
args >>= 8;
|
||||
}
|
||||
int round_mode = (int)(args & 3);
|
||||
if (!(args & 12) || round_mode == 3) {
|
||||
if (round_mode == 3) {
|
||||
return "";
|
||||
}
|
||||
std::ostringstream os;
|
||||
os << (mode & 1 ? "Q" : "") << (args & 4 ? "LSHIFTDIV" : "LSHIFT") << (args & 8 ? "MOD" : "");
|
||||
if (mode & 1) {
|
||||
os << "Q";
|
||||
}
|
||||
switch (args & 12) {
|
||||
case 4:
|
||||
os << "LSHIFTDIV";
|
||||
break;
|
||||
case 8:
|
||||
os << "LSHIFTMOD";
|
||||
break;
|
||||
case 12:
|
||||
os << "LSHIFTDIVMOD";
|
||||
break;
|
||||
case 0:
|
||||
os << "LSHIFTADDDIVMOD";
|
||||
break;
|
||||
}
|
||||
if (round_mode) {
|
||||
os << "FRC"[round_mode];
|
||||
}
|
||||
|
@ -855,7 +959,9 @@ int exec_cmp(VmState* st, int mode, bool quiet, const char* name) {
|
|||
auto y = stack.pop_int();
|
||||
auto x = stack.pop_int();
|
||||
if (!x->is_valid() || !y->is_valid()) {
|
||||
stack.push_int_quiet(std::move(x), quiet);
|
||||
td::RefInt256 r{true};
|
||||
r.unique_write().invalidate();
|
||||
stack.push_int_quiet(std::move(r), quiet);
|
||||
} else {
|
||||
int z = td::cmp(std::move(x), std::move(y));
|
||||
stack.push_smallint(((mode >> (4 + z * 4)) & 15) - 8);
|
||||
|
|
334
crypto/vm/bls.cpp
Normal file
334
crypto/vm/bls.cpp
Normal file
|
@ -0,0 +1,334 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "bls.h"
|
||||
#include "blst.h"
|
||||
#include "blst.hpp"
|
||||
#include "excno.hpp"
|
||||
|
||||
namespace vm {
|
||||
namespace bls {
|
||||
|
||||
static const std::string DST = "BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_";
|
||||
|
||||
bool verify(const P1 &pub, td::Slice msg, const P2 &sig) {
|
||||
try {
|
||||
blst::P1_Affine p1(pub.data(), P1_SIZE);
|
||||
if (p1.is_inf()) {
|
||||
return false;
|
||||
}
|
||||
blst::P2_Affine p2(sig.data(), P2_SIZE);
|
||||
// core_verify checks for p1.in_group() and p2.in_group()
|
||||
return p2.core_verify(p1, true, (const byte *)msg.data(), msg.size(), DST) == BLST_SUCCESS;
|
||||
} catch (BLST_ERROR) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
P2 aggregate(const std::vector<P2> &sig) {
|
||||
try {
|
||||
if (sig.empty()) {
|
||||
throw VmError{Excno::unknown, "no signatures"};
|
||||
}
|
||||
blst::P2 aggregated;
|
||||
for (size_t i = 0; i < sig.size(); ++i) {
|
||||
blst::P2_Affine p2(sig[i].data(), P2_SIZE);
|
||||
if (i == 0) {
|
||||
aggregated = p2.to_jacobian();
|
||||
} else {
|
||||
aggregated.aggregate(p2);
|
||||
}
|
||||
}
|
||||
P2 result;
|
||||
aggregated.compress(result.data());
|
||||
return result;
|
||||
} catch (BLST_ERROR e) {
|
||||
throw VmError{Excno::unknown, PSTRING() << "blst error " << e};
|
||||
}
|
||||
}
|
||||
|
||||
bool fast_aggregate_verify(const std::vector<P1> &pubs, td::Slice msg, const P2 &sig) {
|
||||
try {
|
||||
if (pubs.empty()) {
|
||||
return false;
|
||||
}
|
||||
blst::P1 p1_aggregated;
|
||||
for (size_t i = 0; i < pubs.size(); ++i) {
|
||||
blst::P1_Affine p1(pubs[i].data(), P1_SIZE);
|
||||
if (p1.is_inf()) {
|
||||
return false;
|
||||
}
|
||||
if (i == 0) {
|
||||
p1_aggregated = p1.to_jacobian();
|
||||
} else {
|
||||
p1_aggregated.aggregate(p1);
|
||||
}
|
||||
}
|
||||
blst::P2_Affine p2(sig.data(), P2_SIZE);
|
||||
blst::P1_Affine p1 = p1_aggregated.to_affine();
|
||||
// core_verify checks for p1.in_group() and p2.in_group()
|
||||
return p2.core_verify(p1, true, (const byte *)msg.data(), msg.size(), DST) == BLST_SUCCESS;
|
||||
} catch (BLST_ERROR) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool aggregate_verify(const std::vector<std::pair<P1, td::BufferSlice>> &pubs_msgs, const P2 &sig) {
|
||||
try {
|
||||
if (pubs_msgs.empty()) {
|
||||
return false;
|
||||
}
|
||||
std::unique_ptr<blst::Pairing> pairing = std::make_unique<blst::Pairing>(true, DST);
|
||||
for (const auto &p : pubs_msgs) {
|
||||
blst::P1_Affine p1(p.first.data(), P1_SIZE);
|
||||
if (!p1.in_group() || p1.is_inf()) {
|
||||
return false;
|
||||
}
|
||||
pairing->aggregate(&p1, nullptr, (const td::uint8 *)p.second.data(), p.second.size());
|
||||
}
|
||||
pairing->commit();
|
||||
blst::P2_Affine p2(sig.data(), P2_SIZE);
|
||||
if (!p2.in_group()) {
|
||||
return false;
|
||||
}
|
||||
blst::PT pt(p2);
|
||||
return pairing->finalverify(&pt);
|
||||
} catch (BLST_ERROR) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename P, typename blst_P, typename blst_P_Affine>
|
||||
static P generic_add(const P &a, const P &b) {
|
||||
try {
|
||||
blst_P point(a.data(), a.size() / 8);
|
||||
point.aggregate(blst_P_Affine(b.data(), b.size() / 8));
|
||||
P result;
|
||||
point.compress(result.data());
|
||||
return result;
|
||||
} catch (BLST_ERROR e) {
|
||||
throw VmError{Excno::unknown, PSTRING() << "blst error " << e};
|
||||
}
|
||||
}
|
||||
|
||||
template <typename P, typename blst_P, typename blst_P_Affine>
|
||||
static P generic_sub(const P &a, const P &b) {
|
||||
try {
|
||||
blst_P point(b.data(), b.size() / 8);
|
||||
point.neg();
|
||||
point.aggregate(blst_P_Affine(a.data(), a.size() / 8));
|
||||
P result;
|
||||
point.compress(result.data());
|
||||
return result;
|
||||
} catch (BLST_ERROR e) {
|
||||
throw VmError{Excno::unknown, PSTRING() << "blst error " << e};
|
||||
}
|
||||
}
|
||||
|
||||
template <typename P, typename blst_P>
|
||||
static P generic_neg(const P &a) {
|
||||
try {
|
||||
blst_P point(a.data(), a.size() / 8);
|
||||
point.neg();
|
||||
P result;
|
||||
point.compress(result.data());
|
||||
return result;
|
||||
} catch (BLST_ERROR e) {
|
||||
throw VmError{Excno::unknown, PSTRING() << "blst error " << e};
|
||||
}
|
||||
}
|
||||
|
||||
template <typename P, typename blst_P>
|
||||
static P generic_zero() {
|
||||
static P zero = []() -> P {
|
||||
blst_P point = blst_P();
|
||||
P result;
|
||||
point.compress(result.data());
|
||||
return result;
|
||||
}();
|
||||
return zero;
|
||||
}
|
||||
|
||||
template <typename P, typename blst_P>
|
||||
static P generic_mul(const P &p, const td::RefInt256 &x) {
|
||||
CHECK(x.not_null() && x->is_valid());
|
||||
if (x->sgn() == 0) {
|
||||
return generic_zero<P, blst_P>();
|
||||
}
|
||||
td::uint8 x_bytes[32];
|
||||
CHECK((x % get_r())->export_bytes(x_bytes, 32, false));
|
||||
try {
|
||||
blst_P point(p.data(), p.size() / 8);
|
||||
blst::Scalar scalar;
|
||||
scalar.from_bendian(x_bytes, 32);
|
||||
point.mult(scalar);
|
||||
P result;
|
||||
point.compress(result.data());
|
||||
return result;
|
||||
} catch (BLST_ERROR e) {
|
||||
throw VmError{Excno::unknown, PSTRING() << "blst error " << e};
|
||||
}
|
||||
}
|
||||
|
||||
template <typename P, typename blst_P, typename blst_P_Affine, typename blst_P_Affines>
|
||||
static P generic_multiexp(const std::vector<std::pair<P, td::RefInt256>> &ps) {
|
||||
if (ps.size() == 1) {
|
||||
return generic_mul<P, blst_P>(ps[0].first, ps[0].second);
|
||||
}
|
||||
try {
|
||||
std::vector<blst_P_Affine> points(ps.size());
|
||||
std::vector<td::Bits256> scalars(ps.size());
|
||||
std::vector<const byte *> scalar_ptrs(ps.size());
|
||||
for (size_t i = 0; i < ps.size(); ++i) {
|
||||
points[i] = blst_P_Affine(ps[i].first.data(), ps[i].first.size() / 8);
|
||||
CHECK(ps[i].second.not_null() && ps[i].second->is_valid());
|
||||
CHECK((ps[i].second % get_r())->export_bytes_lsb(scalars[i].data(), 32));
|
||||
scalar_ptrs[i] = (const byte *)&scalars[i];
|
||||
}
|
||||
blst_P point =
|
||||
ps.empty() ? blst_P() : blst_P_Affines::mult_pippenger(points.data(), points.size(), scalar_ptrs.data(), 256);
|
||||
P result;
|
||||
point.compress(result.data());
|
||||
return result;
|
||||
} catch (BLST_ERROR e) {
|
||||
throw VmError{Excno::unknown, PSTRING() << "blst error " << e};
|
||||
}
|
||||
}
|
||||
|
||||
template <typename P, typename blst_P>
|
||||
static bool generic_in_group(const P &a) {
|
||||
try {
|
||||
blst_P point = blst_P(a.data(), a.size() / 8);
|
||||
return point.in_group();
|
||||
} catch (BLST_ERROR e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename P, typename blst_P>
|
||||
static bool generic_is_zero(const P &a) {
|
||||
return a == generic_zero<P, blst_P>();
|
||||
}
|
||||
|
||||
P1 g1_add(const P1 &a, const P1 &b) {
|
||||
return generic_add<P1, blst::P1, blst::P1_Affine>(a, b);
|
||||
}
|
||||
|
||||
P1 g1_sub(const P1 &a, const P1 &b) {
|
||||
return generic_sub<P1, blst::P1, blst::P1_Affine>(a, b);
|
||||
}
|
||||
|
||||
P1 g1_neg(const P1 &a) {
|
||||
return generic_neg<P1, blst::P1>(a);
|
||||
}
|
||||
|
||||
P1 g1_mul(const P1 &p, const td::RefInt256 &x) {
|
||||
return generic_mul<P1, blst::P1>(p, x);
|
||||
}
|
||||
|
||||
P1 g1_multiexp(const std::vector<std::pair<P1, td::RefInt256>> &ps) {
|
||||
return generic_multiexp<P1, blst::P1, blst::P1_Affine, blst::P1_Affines>(ps);
|
||||
}
|
||||
|
||||
P1 g1_zero() {
|
||||
return generic_zero<P1, blst::P1>();
|
||||
}
|
||||
|
||||
P1 map_to_g1(const FP &a) {
|
||||
blst_fp fp;
|
||||
blst_fp_from_bendian(&fp, a.data());
|
||||
blst_p1 point;
|
||||
blst_map_to_g1(&point, &fp, nullptr);
|
||||
P1 result;
|
||||
blst_p1_compress(result.data(), &point);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool g1_in_group(const P1 &a) {
|
||||
return generic_in_group<P1, blst::P1>(a);
|
||||
}
|
||||
|
||||
bool g1_is_zero(const P1 &a) {
|
||||
return generic_is_zero<P1, blst::P1>(a);
|
||||
}
|
||||
|
||||
P2 g2_add(const P2 &a, const P2 &b) {
|
||||
return generic_add<P2, blst::P2, blst::P2_Affine>(a, b);
|
||||
}
|
||||
|
||||
P2 g2_sub(const P2 &a, const P2 &b) {
|
||||
return generic_sub<P2, blst::P2, blst::P2_Affine>(a, b);
|
||||
}
|
||||
|
||||
P2 g2_neg(const P2 &a) {
|
||||
return generic_neg<P2, blst::P2>(a);
|
||||
}
|
||||
|
||||
P2 g2_mul(const P2 &p, const td::RefInt256 &x) {
|
||||
return generic_mul<P2, blst::P2>(p, x);
|
||||
}
|
||||
|
||||
P2 g2_multiexp(const std::vector<std::pair<P2, td::RefInt256>> &ps) {
|
||||
return generic_multiexp<P2, blst::P2, blst::P2_Affine, blst::P2_Affines>(ps);
|
||||
}
|
||||
|
||||
P2 g2_zero() {
|
||||
return generic_zero<P2, blst::P2>();
|
||||
}
|
||||
|
||||
P2 map_to_g2(const FP2 &a) {
|
||||
blst_fp2 fp2;
|
||||
blst_fp_from_bendian(&fp2.fp[0], a.data());
|
||||
blst_fp_from_bendian(&fp2.fp[1], a.data() + FP_SIZE);
|
||||
blst_p2 point;
|
||||
blst_map_to_g2(&point, &fp2, nullptr);
|
||||
P2 result;
|
||||
blst_p2_compress(result.data(), &point);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool g2_in_group(const P2 &a) {
|
||||
return generic_in_group<P2, blst::P2>(a);
|
||||
}
|
||||
|
||||
bool g2_is_zero(const P2 &a) {
|
||||
return generic_is_zero<P2, blst::P2>(a);
|
||||
}
|
||||
|
||||
bool pairing(const std::vector<std::pair<P1, P2>> &ps) {
|
||||
try {
|
||||
std::unique_ptr<blst::Pairing> pairing = std::make_unique<blst::Pairing>(true, DST);
|
||||
for (const auto &p : ps) {
|
||||
blst::P1_Affine point1(p.first.data(), P1_SIZE);
|
||||
blst::P2_Affine point2(p.second.data(), P2_SIZE);
|
||||
pairing->raw_aggregate(&point2, &point1);
|
||||
}
|
||||
pairing->commit();
|
||||
return pairing->finalverify();
|
||||
} catch (BLST_ERROR e) {
|
||||
throw VmError{Excno::unknown, PSTRING() << "blst error " << e};
|
||||
}
|
||||
}
|
||||
|
||||
td::RefInt256 get_r() {
|
||||
static td::RefInt256 r = td::dec_string_to_int256(
|
||||
td::Slice{"52435875175126190479447740508185965837690552500527637822603658699938581184513"});
|
||||
return r;
|
||||
}
|
||||
|
||||
} // namespace bls
|
||||
} // namespace vm
|
65
crypto/vm/bls.h
Normal file
65
crypto/vm/bls.h
Normal file
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <vector>
|
||||
#include "td/utils/buffer.h"
|
||||
#include "common/bitstring.h"
|
||||
#include "common/refint.h"
|
||||
|
||||
namespace vm {
|
||||
namespace bls {
|
||||
|
||||
const size_t P1_SIZE = 48;
|
||||
const size_t P2_SIZE = 96;
|
||||
const size_t FP_SIZE = 48;
|
||||
|
||||
using P1 = td::BitArray<P1_SIZE * 8>;
|
||||
using P2 = td::BitArray<P2_SIZE * 8>;
|
||||
using FP = td::BitArray<FP_SIZE * 8>;
|
||||
using FP2 = td::BitArray<FP_SIZE * 2 * 8>;
|
||||
|
||||
bool verify(const P1 &pub, td::Slice msg, const P2 &sig);
|
||||
P2 aggregate(const std::vector<P2> &sig);
|
||||
bool fast_aggregate_verify(const std::vector<P1> &pubs, td::Slice msg, const P2 &sig);
|
||||
bool aggregate_verify(const std::vector<std::pair<P1, td::BufferSlice>> &pubs_msgs, const P2 &sig);
|
||||
|
||||
P1 g1_add(const P1 &a, const P1 &b);
|
||||
P1 g1_sub(const P1 &a, const P1 &b);
|
||||
P1 g1_neg(const P1 &a);
|
||||
P1 g1_mul(const P1 &p, const td::RefInt256 &x);
|
||||
P1 g1_multiexp(const std::vector<std::pair<P1, td::RefInt256>> &ps);
|
||||
P1 g1_zero();
|
||||
P1 map_to_g1(const FP &a);
|
||||
bool g1_in_group(const P1 &a);
|
||||
bool g1_is_zero(const P1 &a);
|
||||
|
||||
P2 g2_add(const P2 &a, const P2 &b);
|
||||
P2 g2_sub(const P2 &a, const P2 &b);
|
||||
P2 g2_neg(const P2 &a);
|
||||
P2 g2_mul(const P2 &p, const td::RefInt256 &x);
|
||||
P2 g2_multiexp(const std::vector<std::pair<P2, td::RefInt256>> &ps);
|
||||
P2 g2_zero();
|
||||
P2 map_to_g2(const FP2 &a);
|
||||
bool g2_in_group(const P2 &a);
|
||||
bool g2_is_zero(const P2 &a);
|
||||
|
||||
bool pairing(const std::vector<std::pair<P1, P2>> &ps);
|
||||
|
||||
td::RefInt256 get_r();
|
||||
|
||||
} // namespace bls
|
||||
} // namespace vm
|
|
@ -115,6 +115,9 @@ struct CellStorageStat {
|
|||
std::map<vm::Cell::Hash, CellInfo> seen;
|
||||
CellStorageStat() : cells(0), bits(0), public_cells(0) {
|
||||
}
|
||||
explicit CellStorageStat(unsigned long long limit_cells)
|
||||
: cells(0), bits(0), public_cells(0), limit_cells(limit_cells) {
|
||||
}
|
||||
void clear_seen() {
|
||||
seen.clear();
|
||||
}
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
#include "vm/log.h"
|
||||
#include "vm/vm.h"
|
||||
#include "vm/vmstate.h"
|
||||
#include "vm/boc.h"
|
||||
#include "td/utils/misc.h"
|
||||
|
||||
namespace vm {
|
||||
|
||||
|
@ -254,6 +256,17 @@ bool Continuation::deserialize_to(Ref<Cell> cell, Ref<Continuation>& cont, int m
|
|||
return deserialize_to(cs, cont, mode & ~0x1000) && cs.empty_ext();
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const Continuation& cont) {
|
||||
CellBuilder cb;
|
||||
if (cont.serialize(cb)) {
|
||||
auto boc = vm::std_boc_serialize(cb.finalize());
|
||||
if (boc.is_ok()) {
|
||||
os << td::buffer_to_hex(boc.move_as_ok().as_slice());
|
||||
}
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
bool QuitCont::serialize(CellBuilder& cb) const {
|
||||
// vmc_quit$1000 exit_code:int32 = VmCont;
|
||||
return cb.store_long_bool(8, 4) && cb.store_long_bool(exit_code, 32);
|
||||
|
@ -269,6 +282,10 @@ Ref<QuitCont> QuitCont::deserialize(CellSlice& cs, int mode) {
|
|||
}
|
||||
}
|
||||
|
||||
std::string QuitCont::type() const {
|
||||
return "vmc_quit";
|
||||
}
|
||||
|
||||
int ExcQuitCont::jump(VmState* st) const & {
|
||||
int n = 0;
|
||||
try {
|
||||
|
@ -280,6 +297,10 @@ int ExcQuitCont::jump(VmState* st) const & {
|
|||
return ~n;
|
||||
}
|
||||
|
||||
std::string ExcQuitCont::type() const {
|
||||
return "vmc_quit_exc";
|
||||
}
|
||||
|
||||
bool ExcQuitCont::serialize(CellBuilder& cb) const {
|
||||
// vmc_quit_exc$1001 = VmCont;
|
||||
return cb.store_long_bool(9, 4);
|
||||
|
@ -302,6 +323,10 @@ int PushIntCont::jump_w(VmState* st) & {
|
|||
return st->jump(std::move(next));
|
||||
}
|
||||
|
||||
std::string PushIntCont::type() const {
|
||||
return "vmc_pushint";
|
||||
}
|
||||
|
||||
bool PushIntCont::serialize(CellBuilder& cb) const {
|
||||
// vmc_pushint$1111 value:int32 next:^VmCont = VmCont;
|
||||
return cb.store_long_bool(15, 4) && cb.store_long_bool(push_val, 32) && next->serialize_ref(cb);
|
||||
|
@ -353,6 +378,10 @@ Ref<ArgContExt> ArgContExt::deserialize(CellSlice& cs, int mode) {
|
|||
: Ref<ArgContExt>{};
|
||||
}
|
||||
|
||||
std::string ArgContExt::type() const {
|
||||
return "vmc_envelope";
|
||||
}
|
||||
|
||||
int RepeatCont::jump(VmState* st) const & {
|
||||
VM_LOG(st) << "repeat " << count << " more times (slow)\n";
|
||||
if (count <= 0) {
|
||||
|
@ -401,6 +430,10 @@ Ref<RepeatCont> RepeatCont::deserialize(CellSlice& cs, int mode) {
|
|||
}
|
||||
}
|
||||
|
||||
std::string RepeatCont::type() const {
|
||||
return "vmc_repeat";
|
||||
}
|
||||
|
||||
int VmState::repeat(Ref<Continuation> body, Ref<Continuation> after, long long count) {
|
||||
if (count <= 0) {
|
||||
body.clear();
|
||||
|
@ -444,6 +477,10 @@ Ref<AgainCont> AgainCont::deserialize(CellSlice& cs, int mode) {
|
|||
}
|
||||
}
|
||||
|
||||
std::string AgainCont::type() const {
|
||||
return "vmc_again";
|
||||
}
|
||||
|
||||
int VmState::again(Ref<Continuation> body) {
|
||||
return jump(Ref<AgainCont>{true, std::move(body)});
|
||||
}
|
||||
|
@ -493,6 +530,10 @@ Ref<UntilCont> UntilCont::deserialize(CellSlice& cs, int mode) {
|
|||
}
|
||||
}
|
||||
|
||||
std::string UntilCont::type() const {
|
||||
return "vmc_until";
|
||||
}
|
||||
|
||||
int VmState::until(Ref<Continuation> body, Ref<Continuation> after) {
|
||||
if (!body->has_c0()) {
|
||||
set_c0(Ref<UntilCont>{true, body, std::move(after)});
|
||||
|
@ -575,6 +616,10 @@ Ref<WhileCont> WhileCont::deserialize(CellSlice& cs, int mode) {
|
|||
}
|
||||
}
|
||||
|
||||
std::string WhileCont::type() const {
|
||||
return chkcond ? "vmc_while_cond" : "vmc_while_body";
|
||||
}
|
||||
|
||||
int VmState::loop_while(Ref<Continuation> cond, Ref<Continuation> body, Ref<Continuation> after) {
|
||||
if (!cond->has_c0()) {
|
||||
set_c0(Ref<WhileCont>{true, cond, std::move(body), std::move(after), true});
|
||||
|
@ -610,4 +655,8 @@ Ref<OrdCont> OrdCont::deserialize(CellSlice& cs, int mode) {
|
|||
: Ref<OrdCont>{};
|
||||
}
|
||||
|
||||
std::string OrdCont::type() const {
|
||||
return "vmc_std";
|
||||
}
|
||||
|
||||
} // namespace vm
|
||||
|
|
|
@ -191,8 +191,11 @@ class Continuation : public td::CntObject {
|
|||
return (cont = deserialize(cs, mode)).not_null();
|
||||
}
|
||||
static bool deserialize_to(Ref<Cell> cell, Ref<Continuation>& cont, int mode = 0);
|
||||
virtual std::string type() const = 0;
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const Continuation& cont);
|
||||
|
||||
class QuitCont : public Continuation {
|
||||
int exit_code;
|
||||
|
||||
|
@ -205,6 +208,7 @@ class QuitCont : public Continuation {
|
|||
}
|
||||
bool serialize(CellBuilder& cb) const override;
|
||||
static Ref<QuitCont> deserialize(CellSlice& cs, int mode = 0);
|
||||
std::string type() const override;
|
||||
};
|
||||
|
||||
class ExcQuitCont : public Continuation {
|
||||
|
@ -214,6 +218,7 @@ class ExcQuitCont : public Continuation {
|
|||
int jump(VmState* st) const & override;
|
||||
bool serialize(CellBuilder& cb) const override;
|
||||
static Ref<ExcQuitCont> deserialize(CellSlice& cs, int mode = 0);
|
||||
std::string type() const override;
|
||||
};
|
||||
|
||||
class PushIntCont : public Continuation {
|
||||
|
@ -228,6 +233,7 @@ class PushIntCont : public Continuation {
|
|||
int jump_w(VmState* st) & override;
|
||||
bool serialize(CellBuilder& cb) const override;
|
||||
static Ref<PushIntCont> deserialize(CellSlice& cs, int mode = 0);
|
||||
std::string type() const override;
|
||||
};
|
||||
|
||||
class RepeatCont : public Continuation {
|
||||
|
@ -243,6 +249,7 @@ class RepeatCont : public Continuation {
|
|||
int jump_w(VmState* st) & override;
|
||||
bool serialize(CellBuilder& cb) const override;
|
||||
static Ref<RepeatCont> deserialize(CellSlice& cs, int mode = 0);
|
||||
std::string type() const override;
|
||||
};
|
||||
|
||||
class AgainCont : public Continuation {
|
||||
|
@ -256,6 +263,7 @@ class AgainCont : public Continuation {
|
|||
int jump_w(VmState* st) & override;
|
||||
bool serialize(CellBuilder& cb) const override;
|
||||
static Ref<AgainCont> deserialize(CellSlice& cs, int mode = 0);
|
||||
std::string type() const override;
|
||||
};
|
||||
|
||||
class UntilCont : public Continuation {
|
||||
|
@ -269,6 +277,7 @@ class UntilCont : public Continuation {
|
|||
int jump_w(VmState* st) & override;
|
||||
bool serialize(CellBuilder& cb) const override;
|
||||
static Ref<UntilCont> deserialize(CellSlice& cs, int mode = 0);
|
||||
std::string type() const override;
|
||||
};
|
||||
|
||||
class WhileCont : public Continuation {
|
||||
|
@ -284,6 +293,7 @@ class WhileCont : public Continuation {
|
|||
int jump_w(VmState* st) & override;
|
||||
bool serialize(CellBuilder& cb) const override;
|
||||
static Ref<WhileCont> deserialize(CellSlice& cs, int mode = 0);
|
||||
std::string type() const override;
|
||||
};
|
||||
|
||||
class ArgContExt : public Continuation {
|
||||
|
@ -315,6 +325,7 @@ class ArgContExt : public Continuation {
|
|||
}
|
||||
bool serialize(CellBuilder& cb) const override;
|
||||
static Ref<ArgContExt> deserialize(CellSlice& cs, int mode = 0);
|
||||
std::string type() const override;
|
||||
};
|
||||
|
||||
class OrdCont : public Continuation {
|
||||
|
@ -369,6 +380,7 @@ class OrdCont : public Continuation {
|
|||
}
|
||||
bool serialize(CellBuilder& cb) const override;
|
||||
static Ref<OrdCont> deserialize(CellSlice& cs, int mode = 0);
|
||||
std::string type() const override;
|
||||
};
|
||||
|
||||
ControlData* force_cdata(Ref<Continuation>& cont);
|
||||
|
|
|
@ -212,6 +212,77 @@ int exec_ret_data(VmState* st) {
|
|||
return st->ret();
|
||||
}
|
||||
|
||||
// Mode:
|
||||
// +1 = same_c3 (set c3 to code)
|
||||
// +2 = push_0 (push an implicit 0 before running the code)
|
||||
// +4 = load c4 (persistent data) from stack and return its final value
|
||||
// +8 = load gas limit from stack and return consumed gas
|
||||
// +16 = load c7 (smart-contract context)
|
||||
// +32 = return c5 (actions)
|
||||
// +64 = pop hard gas limit (enabled by ACCEPT) from stack as well
|
||||
// +128 = isolated gas consumption (separate set of visited cells, reset chksgn counter)
|
||||
// +256 = pop number N, return exactly N values from stack (only if res=0 or 1; if not enough then res=stk_und)
|
||||
int exec_runvm_common(VmState* st, unsigned mode) {
|
||||
if (mode >= 512) {
|
||||
throw VmError{Excno::range_chk, "invalid flags"};
|
||||
}
|
||||
st->consume_gas(VmState::runvm_gas_price);
|
||||
Stack& stack = st->get_stack();
|
||||
bool with_data = mode & 4;
|
||||
Ref<vm::Tuple> c7;
|
||||
Ref<vm::Cell> data, actions;
|
||||
long long gas_max = (mode & 64) ? stack.pop_long_range(vm::GasLimits::infty) : vm::GasLimits::infty;
|
||||
long long gas_limit = (mode & 8) ? stack.pop_long_range(vm::GasLimits::infty) : vm::GasLimits::infty;
|
||||
if (!(mode & 64)) {
|
||||
gas_max = gas_limit;
|
||||
} else {
|
||||
gas_max = std::max(gas_max, gas_limit);
|
||||
}
|
||||
if (mode & 16) {
|
||||
c7 = stack.pop_tuple();
|
||||
}
|
||||
if (with_data) {
|
||||
data = stack.pop_cell();
|
||||
}
|
||||
int ret_vals = -1;
|
||||
if (mode & 256) {
|
||||
ret_vals = stack.pop_smallint_range(1 << 30);
|
||||
}
|
||||
auto code = stack.pop_cellslice();
|
||||
int stack_size = stack.pop_smallint_range(stack.depth() - 1);
|
||||
std::vector<StackEntry> new_stack_entries(stack_size);
|
||||
for (int i = 0; i < stack_size; ++i) {
|
||||
new_stack_entries[stack_size - 1 - i] = stack.pop();
|
||||
}
|
||||
td::Ref<Stack> new_stack{true, std::move(new_stack_entries)};
|
||||
st->consume_stack_gas(new_stack);
|
||||
gas_max = std::min(gas_max, st->get_gas_limits().gas_remaining);
|
||||
gas_limit = std::min(gas_limit, st->get_gas_limits().gas_remaining);
|
||||
vm::GasLimits gas{gas_limit, gas_max};
|
||||
|
||||
VmStateInterface::Guard guard{nullptr}; // Don't consume gas for creating/loading cells during VM init
|
||||
VmState new_state{std::move(code), std::move(new_stack), gas, (int)mode & 3, std::move(data),
|
||||
VmLog{}, std::vector<Ref<Cell>>{}, std::move(c7)};
|
||||
new_state.set_chksig_always_succeed(st->get_chksig_always_succeed());
|
||||
new_state.set_global_version(st->get_global_version());
|
||||
st->run_child_vm(std::move(new_state), with_data, mode & 32, mode & 8, mode & 128, ret_vals);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int exec_runvm(VmState* st, unsigned args) {
|
||||
VM_LOG(st) << "execute RUNVM " << (args & 4095) << "\n";
|
||||
return exec_runvm_common(st, args & 4095);
|
||||
}
|
||||
|
||||
int exec_runvmx(VmState* st) {
|
||||
VM_LOG(st) << "execute RUNVMX\n";
|
||||
return exec_runvm_common(st, st->get_stack().pop_smallint_range(4095));
|
||||
}
|
||||
|
||||
std::string dump_runvm(CellSlice&, unsigned args) {
|
||||
return PSTRING() << "RUNVM " << (args & 4095);
|
||||
}
|
||||
|
||||
void register_continuation_jump_ops(OpcodeTable& cp0) {
|
||||
using namespace std::placeholders;
|
||||
cp0.insert(OpcodeInstr::mksimple(0xd8, 8, "EXECUTE", exec_execute))
|
||||
|
@ -246,7 +317,9 @@ void register_continuation_jump_ops(OpcodeTable& cp0) {
|
|||
},
|
||||
"JMPREFDATA"),
|
||||
compute_len_push_ref))
|
||||
.insert(OpcodeInstr::mksimple(0xdb3f, 16, "RETDATA", exec_ret_data));
|
||||
.insert(OpcodeInstr::mksimple(0xdb3f, 16, "RETDATA", exec_ret_data))
|
||||
.insert(OpcodeInstr::mkfixed(0xdb4, 12, 12, dump_runvm, exec_runvm)->require_version(4))
|
||||
.insert(OpcodeInstr::mksimple(0xdb50, 16, "RUNVMX ", exec_runvmx)->require_version(4));
|
||||
}
|
||||
|
||||
int exec_if(VmState* st) {
|
||||
|
|
|
@ -31,7 +31,7 @@ namespace vm {
|
|||
struct VmLog {
|
||||
td::LogInterface *log_interface{td::log_interface};
|
||||
td::LogOptions log_options{td::log_options};
|
||||
enum { DumpStack = 2, ExecLocation = 4, GasRemaining = 8 };
|
||||
enum { DumpStack = 2, ExecLocation = 4, GasRemaining = 8, DumpStackVerbose = 16 };
|
||||
int log_mask{1};
|
||||
static VmLog Null() {
|
||||
VmLog res;
|
||||
|
|
|
@ -447,4 +447,24 @@ dump_arg_instr_func_t dump_2c_add(unsigned add, std::string prefix, std::string
|
|||
|
||||
} // namespace instr
|
||||
|
||||
OpcodeInstr* OpcodeInstr::require_version(int required_version) {
|
||||
return new OpcodeInstrWithVersion(this, required_version);
|
||||
}
|
||||
|
||||
int OpcodeInstrWithVersion::dispatch(VmState* st, CellSlice& cs, unsigned opcode, unsigned bits) const {
|
||||
if (st->get_global_version() < required_version) {
|
||||
st->consume_gas(gas_per_instr);
|
||||
throw VmError{Excno::inv_opcode, "invalid opcode", opcode};
|
||||
}
|
||||
return instr->dispatch(st, cs, opcode, bits);
|
||||
}
|
||||
|
||||
std::string OpcodeInstrWithVersion::dump(CellSlice& cs, unsigned opcode, unsigned bits) const {
|
||||
return instr->dump(cs, opcode, bits);
|
||||
}
|
||||
|
||||
int OpcodeInstrWithVersion::instr_len(const CellSlice& cs, unsigned opcode, unsigned bits) const {
|
||||
return instr->instr_len(cs, opcode, bits);
|
||||
}
|
||||
|
||||
} // namespace vm
|
||||
|
|
|
@ -57,6 +57,9 @@ class OpcodeInstr {
|
|||
std::pair<unsigned, unsigned> get_opcode_range() const {
|
||||
return {min_opcode, max_opcode};
|
||||
}
|
||||
|
||||
OpcodeInstr* require_version(int required_version);
|
||||
|
||||
//static OpcodeInstr* mksimple(unsigned opcode, unsigned opc_bits, std::string _name, exec_instr_func_t exec);
|
||||
static OpcodeInstr* mksimple(unsigned opcode, unsigned opc_bits, std::string _name, exec_simple_instr_func_t exec);
|
||||
static OpcodeInstr* mkfixed(unsigned opcode, unsigned opc_bits, unsigned arg_bits, dump_arg_instr_func_t dump,
|
||||
|
@ -188,4 +191,19 @@ class OpcodeInstrExt : public OpcodeInstr {
|
|||
int instr_len(const CellSlice& cs, unsigned opcode, unsigned bits) const override;
|
||||
};
|
||||
|
||||
class OpcodeInstrWithVersion : public OpcodeInstr {
|
||||
public:
|
||||
OpcodeInstrWithVersion() = delete;
|
||||
OpcodeInstrWithVersion(OpcodeInstr* instr, int required_version) :
|
||||
OpcodeInstr(instr->get_opcode_min(), instr->get_opcode_max()), instr(instr), required_version(required_version) {
|
||||
}
|
||||
~OpcodeInstrWithVersion() override = default;
|
||||
int dispatch(VmState* st, CellSlice& cs, unsigned opcode, unsigned bits) const override;
|
||||
std::string dump(CellSlice& cs, unsigned opcode, unsigned bits) const override;
|
||||
int instr_len(const CellSlice& cs, unsigned opcode, unsigned bits) const override;
|
||||
private:
|
||||
OpcodeInstr* instr;
|
||||
int required_version;
|
||||
};
|
||||
|
||||
} // namespace vm
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
#include "vm/box.hpp"
|
||||
#include "vm/atom.h"
|
||||
#include "vm/vmstate.h"
|
||||
#include "vm/boc.h"
|
||||
#include "td/utils/misc.h"
|
||||
|
||||
namespace td {
|
||||
template class td::Cnt<std::string>;
|
||||
|
@ -81,7 +83,7 @@ std::string StackEntry::to_lisp_string() const {
|
|||
return std::move(os).str();
|
||||
}
|
||||
|
||||
void StackEntry::dump(std::ostream& os) const {
|
||||
void StackEntry::dump(std::ostream& os, bool verbose) const {
|
||||
switch (tp) {
|
||||
case t_null:
|
||||
os << "(null)";
|
||||
|
@ -91,14 +93,23 @@ void StackEntry::dump(std::ostream& os) const {
|
|||
break;
|
||||
case t_cell:
|
||||
if (ref.not_null()) {
|
||||
os << "C{" << static_cast<Ref<Cell>>(ref)->get_hash().to_hex() << "}";
|
||||
if (verbose) {
|
||||
std::string serialized = "???";
|
||||
auto boc = vm::std_boc_serialize(as_cell());
|
||||
if (boc.is_ok()) {
|
||||
serialized = td::buffer_to_hex(boc.move_as_ok().as_slice());
|
||||
}
|
||||
os << "C{" << serialized << "}";
|
||||
} else {
|
||||
os << "C{" << *as_cell() << "}";
|
||||
}
|
||||
} else {
|
||||
os << "C{null}";
|
||||
}
|
||||
break;
|
||||
case t_builder:
|
||||
if (ref.not_null()) {
|
||||
os << "BC{" << static_cast<Ref<CellBuilder>>(ref)->to_hex() << "}";
|
||||
os << "BC{" << *as_builder() << "}";
|
||||
} else {
|
||||
os << "BC{null}";
|
||||
}
|
||||
|
@ -149,12 +160,24 @@ void StackEntry::dump(std::ostream& os) const {
|
|||
os << "Object{" << (const void*)&*ref << "}";
|
||||
break;
|
||||
}
|
||||
case t_vmcont: {
|
||||
if (ref.not_null()) {
|
||||
if (verbose) {
|
||||
os << "Cont{" << *as_cont() << "}";
|
||||
} else {
|
||||
os << "Cont{" << as_cont()->type() << "}";
|
||||
}
|
||||
} else {
|
||||
os << "Cont{null}";
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
os << "???";
|
||||
}
|
||||
}
|
||||
|
||||
void StackEntry::print_list(std::ostream& os) const {
|
||||
void StackEntry::print_list(std::ostream& os, bool verbose) const {
|
||||
switch (tp) {
|
||||
case t_null:
|
||||
os << "()";
|
||||
|
@ -163,7 +186,7 @@ void StackEntry::print_list(std::ostream& os) const {
|
|||
const auto& tuple = *static_cast<Ref<Tuple>>(ref);
|
||||
if (is_list()) {
|
||||
os << '(';
|
||||
tuple[0].print_list(os);
|
||||
tuple[0].print_list(os, verbose);
|
||||
print_list_tail(os, &tuple[1]);
|
||||
break;
|
||||
}
|
||||
|
@ -172,7 +195,7 @@ void StackEntry::print_list(std::ostream& os) const {
|
|||
os << "[]";
|
||||
} else if (n == 1) {
|
||||
os << "[";
|
||||
tuple[0].print_list(os);
|
||||
tuple[0].print_list(os, verbose);
|
||||
os << "]";
|
||||
} else {
|
||||
os << "[";
|
||||
|
@ -181,14 +204,14 @@ void StackEntry::print_list(std::ostream& os) const {
|
|||
if (c++) {
|
||||
os << " ";
|
||||
}
|
||||
entry.print_list(os);
|
||||
entry.print_list(os, verbose);
|
||||
}
|
||||
os << ']';
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
dump(os);
|
||||
dump(os, verbose);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -326,7 +349,7 @@ void StackEntry::for_each_scalar(const std::function<void(const StackEntry&)>& f
|
|||
}
|
||||
}
|
||||
|
||||
const StackEntry& tuple_index(const Tuple& tup, unsigned idx) {
|
||||
const StackEntry& tuple_index(const Ref<Tuple>& tup, unsigned idx) {
|
||||
if (idx >= tup->size()) {
|
||||
throw VmError{Excno::range_chk, "tuple index out of range"};
|
||||
}
|
||||
|
@ -687,12 +710,12 @@ void Stack::dump(std::ostream& os, int mode) const {
|
|||
os << " [ ";
|
||||
if (mode & 2) {
|
||||
for (const auto& x : stack) {
|
||||
x.print_list(os);
|
||||
x.print_list(os, mode & 4);
|
||||
os << ' ';
|
||||
}
|
||||
} else {
|
||||
for (const auto& x : stack) {
|
||||
x.dump(os);
|
||||
x.dump(os, mode & 4);
|
||||
os << ' ';
|
||||
}
|
||||
}
|
||||
|
@ -908,23 +931,29 @@ bool Stack::serialize(vm::CellBuilder& cb, int mode) const {
|
|||
if (vsi && !vsi->register_op()) {
|
||||
return false;
|
||||
}
|
||||
// vm_stack#_ depth:(## 24) stack:(VmStackList depth) = VmStack;
|
||||
unsigned n = depth();
|
||||
if (!cb.store_ulong_rchk_bool(n, 24)) { // vm_stack#_ depth:(## 24)
|
||||
return false;
|
||||
}
|
||||
if (!n) {
|
||||
return true;
|
||||
}
|
||||
vm::CellBuilder cb2;
|
||||
Ref<vm::Cell> rest = cb2.finalize(); // vm_stk_nil#_ = VmStackList 0;
|
||||
for (unsigned i = 0; i < n - 1; i++) {
|
||||
// vm_stk_cons#_ {n:#} rest:^(VmStackList n) tos:VmStackValue = VmStackList (n + 1);
|
||||
if (!(cb2.store_ref_bool(std::move(rest)) && stack[i].serialize(cb2, mode) && cb2.finalize_to(rest))) {
|
||||
try {
|
||||
// vm_stack#_ depth:(## 24) stack:(VmStackList depth) = VmStack;
|
||||
unsigned n = depth();
|
||||
if (!cb.store_ulong_rchk_bool(n, 24)) { // vm_stack#_ depth:(## 24)
|
||||
return false;
|
||||
}
|
||||
if (!n) {
|
||||
return true;
|
||||
}
|
||||
vm::CellBuilder cb2;
|
||||
Ref<vm::Cell> rest = cb2.finalize(); // vm_stk_nil#_ = VmStackList 0;
|
||||
for (unsigned i = 0; i < n - 1; i++) {
|
||||
// vm_stk_cons#_ {n:#} rest:^(VmStackList n) tos:VmStackValue = VmStackList (n + 1);
|
||||
if (!(cb2.store_ref_bool(std::move(rest)) && stack[i].serialize(cb2, mode) && cb2.finalize_to(rest))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return cb.store_ref_bool(std::move(rest)) && stack[n - 1].serialize(cb, mode);
|
||||
} catch (CellBuilder::CellCreateError) {
|
||||
return false;
|
||||
} catch (CellBuilder::CellWriteError) {
|
||||
return false;
|
||||
}
|
||||
return cb.store_ref_bool(std::move(rest)) && stack[n - 1].serialize(cb, mode);
|
||||
}
|
||||
|
||||
bool Stack::deserialize(vm::CellSlice& cs, int mode) {
|
||||
|
|
|
@ -292,8 +292,8 @@ class StackEntry {
|
|||
}
|
||||
bool for_each_scalar(const std::function<bool(const StackEntry&)>& func) const;
|
||||
void for_each_scalar(const std::function<void(const StackEntry&)>& func) const;
|
||||
void dump(std::ostream& os) const;
|
||||
void print_list(std::ostream& os) const;
|
||||
void dump(std::ostream& os, bool verbose = false) const;
|
||||
void print_list(std::ostream& os, bool verbose = false) const;
|
||||
std::string to_string() const;
|
||||
std::string to_lisp_string() const;
|
||||
|
||||
|
@ -305,7 +305,7 @@ inline void swap(StackEntry& se1, StackEntry& se2) {
|
|||
se1.swap(se2);
|
||||
}
|
||||
|
||||
const StackEntry& tuple_index(const Tuple& tup, unsigned idx);
|
||||
const StackEntry& tuple_index(const Ref<Tuple>& tup, unsigned idx);
|
||||
StackEntry tuple_extend_index(const Ref<Tuple>& tup, unsigned idx);
|
||||
unsigned tuple_extend_set_index(Ref<Tuple>& tup, unsigned idx, StackEntry&& value, bool force = false);
|
||||
|
||||
|
@ -558,7 +558,7 @@ class Stack : public td::CntObject {
|
|||
}
|
||||
bool for_each_scalar(const std::function<bool(const StackEntry&)>& func) const;
|
||||
void for_each_scalar(const std::function<void(const StackEntry&)>& func) const;
|
||||
// mode: +1 = add eoln, +2 = Lisp-style lists
|
||||
// mode: +1 = add eoln, +2 = Lisp-style lists, +4 = serialized bocs
|
||||
void dump(std::ostream& os, int mode = 1) const;
|
||||
bool serialize(vm::CellBuilder& cb, int mode = 0) const;
|
||||
bool deserialize(vm::CellSlice& cs, int mode = 0);
|
||||
|
|
|
@ -301,9 +301,7 @@ int exec_blkswap(VmState* st, unsigned args) {
|
|||
Stack& stack = st->get_stack();
|
||||
VM_LOG(st) << "execute BLKSWAP " << x << ',' << y;
|
||||
stack.check_underflow(x + y);
|
||||
std::reverse(stack.from_top(x + y), stack.from_top(y));
|
||||
std::reverse(stack.from_top(y), stack.top());
|
||||
std::reverse(stack.from_top(x + y), stack.top());
|
||||
std::rotate(stack.from_top(x + y), stack.from_top(y), stack.top());
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -403,7 +401,7 @@ int exec_pick(VmState* st) {
|
|||
Stack& stack = st->get_stack();
|
||||
VM_LOG(st) << "execute PICK\n";
|
||||
stack.check_underflow(1);
|
||||
int x = stack.pop_smallint_range(255);
|
||||
int x = stack.pop_smallint_range(st->get_global_version() >= 4 ? (1 << 30) - 1 : 255);
|
||||
stack.check_underflow_p(x);
|
||||
stack.push(stack.fetch(x));
|
||||
return 0;
|
||||
|
@ -413,8 +411,9 @@ int exec_roll(VmState* st) {
|
|||
Stack& stack = st->get_stack();
|
||||
VM_LOG(st) << "execute ROLL\n";
|
||||
stack.check_underflow(1);
|
||||
int x = stack.pop_smallint_range(255);
|
||||
int x = stack.pop_smallint_range(st->get_global_version() >= 4 ? (1 << 30) - 1 : 255);
|
||||
stack.check_underflow_p(x);
|
||||
st->consume_gas(std::max(x - 255, 0));
|
||||
while (--x >= 0) {
|
||||
swap(stack[x], stack[x + 1]);
|
||||
}
|
||||
|
@ -425,8 +424,9 @@ int exec_rollrev(VmState* st) {
|
|||
Stack& stack = st->get_stack();
|
||||
VM_LOG(st) << "execute ROLLREV\n";
|
||||
stack.check_underflow(1);
|
||||
int x = stack.pop_smallint_range(255);
|
||||
int x = stack.pop_smallint_range(st->get_global_version() >= 4 ? (1 << 30) - 1 : 255);
|
||||
stack.check_underflow_p(x);
|
||||
st->consume_gas(std::max(x - 255, 0));
|
||||
for (int i = 0; i < x; i++) {
|
||||
swap(stack[i], stack[i + 1]);
|
||||
}
|
||||
|
@ -437,13 +437,14 @@ int exec_blkswap_x(VmState* st) {
|
|||
Stack& stack = st->get_stack();
|
||||
VM_LOG(st) << "execute BLKSWX\n";
|
||||
stack.check_underflow(2);
|
||||
int y = stack.pop_smallint_range(255);
|
||||
int x = stack.pop_smallint_range(255);
|
||||
int y = stack.pop_smallint_range(st->get_global_version() >= 4 ? (1 << 30) - 1 : 255);
|
||||
int x = stack.pop_smallint_range(st->get_global_version() >= 4 ? (1 << 30) - 1 : 255);
|
||||
stack.check_underflow(x + y);
|
||||
if (x > 0 && y > 0) {
|
||||
std::reverse(stack.from_top(x + y), stack.from_top(y));
|
||||
std::reverse(stack.from_top(y), stack.top());
|
||||
std::reverse(stack.from_top(x + y), stack.top());
|
||||
if (st->get_global_version() >= 4) {
|
||||
st->consume_gas(std::max(x + y - 255, 0));
|
||||
}
|
||||
std::rotate(stack.from_top(x + y), stack.from_top(y), stack.top());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -452,9 +453,10 @@ int exec_reverse_x(VmState* st) {
|
|||
Stack& stack = st->get_stack();
|
||||
VM_LOG(st) << "execute REVX\n";
|
||||
stack.check_underflow(2);
|
||||
int y = stack.pop_smallint_range(255);
|
||||
int x = stack.pop_smallint_range(255);
|
||||
int y = stack.pop_smallint_range(st->get_global_version() >= 4 ? (1 << 30) - 1 : 255);
|
||||
int x = stack.pop_smallint_range(st->get_global_version() >= 4 ? (1 << 30) - 1 : 255);
|
||||
stack.check_underflow(x + y);
|
||||
st->consume_gas(std::max(x - 255, 0));
|
||||
std::reverse(stack.from_top(x + y), stack.from_top(y));
|
||||
return 0;
|
||||
}
|
||||
|
@ -463,7 +465,7 @@ int exec_drop_x(VmState* st) {
|
|||
Stack& stack = st->get_stack();
|
||||
VM_LOG(st) << "execute DROPX\n";
|
||||
stack.check_underflow(1);
|
||||
int x = stack.pop_smallint_range(255);
|
||||
int x = stack.pop_smallint_range(st->get_global_version() >= 4 ? (1 << 30) - 1 : 255);
|
||||
stack.check_underflow(x);
|
||||
stack.pop_many(x);
|
||||
return 0;
|
||||
|
@ -482,7 +484,7 @@ int exec_xchg_x(VmState* st) {
|
|||
Stack& stack = st->get_stack();
|
||||
VM_LOG(st) << "execute XCHGX\n";
|
||||
stack.check_underflow(1);
|
||||
int x = stack.pop_smallint_range(255);
|
||||
int x = stack.pop_smallint_range(st->get_global_version() >= 4 ? (1 << 30) - 1 : 255);
|
||||
stack.check_underflow_p(x);
|
||||
swap(stack[0], stack[x]);
|
||||
return 0;
|
||||
|
@ -499,7 +501,7 @@ int exec_chkdepth(VmState* st) {
|
|||
Stack& stack = st->get_stack();
|
||||
VM_LOG(st) << "execute CHKDEPTH\n";
|
||||
stack.check_underflow(1);
|
||||
int x = stack.pop_smallint_range(255);
|
||||
int x = stack.pop_smallint_range(st->get_global_version() >= 4 ? (1 << 30) - 1 : 255);
|
||||
stack.check_underflow(x);
|
||||
return 0;
|
||||
}
|
||||
|
@ -508,10 +510,11 @@ int exec_onlytop_x(VmState* st) {
|
|||
Stack& stack = st->get_stack();
|
||||
VM_LOG(st) << "execute ONLYTOPX\n";
|
||||
stack.check_underflow(1);
|
||||
int x = stack.pop_smallint_range(255);
|
||||
int x = stack.pop_smallint_range(st->get_global_version() >= 4 ? (1 << 30) - 1 : 255);
|
||||
stack.check_underflow(x);
|
||||
int n = stack.depth(), d = n - x;
|
||||
if (d > 0) {
|
||||
st->consume_gas(std::max(x - 255, 0));
|
||||
for (int i = n - 1; i >= d; i--) {
|
||||
stack[i] = std::move(stack[i - d]);
|
||||
}
|
||||
|
@ -524,7 +527,7 @@ int exec_only_x(VmState* st) {
|
|||
Stack& stack = st->get_stack();
|
||||
VM_LOG(st) << "execute ONLYX\n";
|
||||
stack.check_underflow(1);
|
||||
int x = stack.pop_smallint_range(255);
|
||||
int x = stack.pop_smallint_range(st->get_global_version() >= 4 ? (1 << 30) - 1 : 255);
|
||||
stack.check_underflow(x);
|
||||
stack.pop_many(stack.depth() - x);
|
||||
return 0;
|
||||
|
|
1012
crypto/vm/tonops.cpp
1012
crypto/vm/tonops.cpp
File diff suppressed because it is too large
Load diff
|
@ -99,7 +99,7 @@ int exec_mktuple_var(VmState* st) {
|
|||
|
||||
int exec_tuple_index_common(Stack& stack, unsigned n) {
|
||||
auto tuple = stack.pop_tuple_range(255);
|
||||
stack.push(tuple_index(*tuple, n));
|
||||
stack.push(tuple_index(tuple, n));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -322,11 +322,11 @@ int exec_tuple_index2(VmState* st, unsigned args) {
|
|||
VM_LOG(st) << "execute INDEX2 " << i << "," << j;
|
||||
Stack& stack = st->get_stack();
|
||||
auto tuple = stack.pop_tuple_range(255);
|
||||
auto t1 = tuple_index(*tuple, i).as_tuple_range(255);
|
||||
auto t1 = tuple_index(tuple, i).as_tuple_range(255);
|
||||
if (t1.is_null()) {
|
||||
throw VmError{Excno::type_chk, "intermediate value is not a tuple"};
|
||||
}
|
||||
stack.push(tuple_index(*t1, j));
|
||||
stack.push(tuple_index(t1, j));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -342,15 +342,15 @@ int exec_tuple_index3(VmState* st, unsigned args) {
|
|||
VM_LOG(st) << "execute INDEX3 " << i << "," << j << "," << k;
|
||||
Stack& stack = st->get_stack();
|
||||
auto tuple = stack.pop_tuple_range(255);
|
||||
auto t1 = tuple_index(*tuple, i).as_tuple_range(255);
|
||||
auto t1 = tuple_index(tuple, i).as_tuple_range(255);
|
||||
if (t1.is_null()) {
|
||||
throw VmError{Excno::type_chk, "intermediate value is not a tuple"};
|
||||
}
|
||||
auto t2 = tuple_index(*t1, j).as_tuple_range(255);
|
||||
auto t2 = tuple_index(t1, j).as_tuple_range(255);
|
||||
if (t2.is_null()) {
|
||||
throw VmError{Excno::type_chk, "intermediate value is not a tuple"};
|
||||
}
|
||||
stack.push(tuple_index(*t2, k));
|
||||
stack.push(tuple_index(t2, k));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
181
crypto/vm/vm.cpp
181
crypto/vm/vm.cpp
|
@ -389,7 +389,7 @@ int VmState::throw_exception(int excno) {
|
|||
stack_ref.push_smallint(0);
|
||||
stack_ref.push_smallint(excno);
|
||||
code.clear();
|
||||
gas.consume_chk(exception_gas_price);
|
||||
consume_gas_chk(exception_gas_price);
|
||||
return jump(get_c2());
|
||||
}
|
||||
|
||||
|
@ -399,7 +399,7 @@ int VmState::throw_exception(int excno, StackEntry&& arg) {
|
|||
stack_ref.push(std::move(arg));
|
||||
stack_ref.push_smallint(excno);
|
||||
code.clear();
|
||||
gas.consume_chk(exception_gas_price);
|
||||
consume_gas_chk(exception_gas_price);
|
||||
return jump(get_c2());
|
||||
}
|
||||
|
||||
|
@ -435,7 +435,11 @@ int VmState::step() {
|
|||
CHECK(code.not_null() && stack.not_null());
|
||||
if (log.log_mask & vm::VmLog::DumpStack) {
|
||||
std::stringstream ss;
|
||||
stack->dump(ss, 3);
|
||||
int mode = 3;
|
||||
if (log.log_mask & vm::VmLog::DumpStackVerbose) {
|
||||
mode += 4;
|
||||
}
|
||||
stack->dump(ss, mode);
|
||||
VM_LOG(this) << "stack:" << ss.str();
|
||||
}
|
||||
if (stack_trace) {
|
||||
|
@ -449,54 +453,41 @@ int VmState::step() {
|
|||
VM_LOG(this) << "execute implicit JMPREF";
|
||||
auto ref_cell = code->prefetch_ref();
|
||||
VM_LOG_MASK(this, vm::VmLog::ExecLocation) << "code cell hash: " << ref_cell->get_hash().to_hex() << " offset: 0";
|
||||
gas.consume_chk(implicit_jmpref_gas_price);
|
||||
consume_gas_chk(implicit_jmpref_gas_price);
|
||||
Ref<Continuation> cont = Ref<OrdCont>{true, load_cell_slice_ref(std::move(ref_cell)), get_cp()};
|
||||
return jump(std::move(cont));
|
||||
} else {
|
||||
VM_LOG(this) << "execute implicit RET";
|
||||
gas.consume_chk(implicit_ret_gas_price);
|
||||
consume_gas_chk(implicit_ret_gas_price);
|
||||
return ret();
|
||||
}
|
||||
}
|
||||
|
||||
int VmState::run() {
|
||||
if (code.is_null() || stack.is_null()) {
|
||||
// throw VmError{Excno::fatal, "cannot run an uninitialized VM"};
|
||||
return (int)Excno::fatal; // no ~ for unhandled exceptions
|
||||
}
|
||||
int VmState::run_inner() {
|
||||
int res;
|
||||
Guard guard(this);
|
||||
do {
|
||||
try {
|
||||
try {
|
||||
try {
|
||||
res = step();
|
||||
VM_LOG_MASK(this, vm::VmLog::GasRemaining) << "gas remaining: " << gas.gas_remaining;
|
||||
gas.check();
|
||||
} catch (vm::CellBuilder::CellWriteError) {
|
||||
throw VmError{Excno::cell_ov};
|
||||
} catch (vm::CellBuilder::CellCreateError) {
|
||||
throw VmError{Excno::cell_ov};
|
||||
} catch (vm::CellSlice::CellReadError) {
|
||||
throw VmError{Excno::cell_und};
|
||||
}
|
||||
} catch (const VmError& vme) {
|
||||
VM_LOG(this) << "handling exception code " << vme.get_errno() << ": " << vme.get_msg();
|
||||
try {
|
||||
++steps;
|
||||
res = throw_exception(vme.get_errno());
|
||||
} catch (const VmError& vme2) {
|
||||
VM_LOG(this) << "exception " << vme2.get_errno() << " while handling exception: " << vme.get_msg();
|
||||
return ~vme2.get_errno();
|
||||
}
|
||||
res = step();
|
||||
VM_LOG_MASK(this, vm::VmLog::GasRemaining) << "gas remaining: " << gas.gas_remaining;
|
||||
gas.check();
|
||||
} catch (vm::CellBuilder::CellWriteError) {
|
||||
throw VmError{Excno::cell_ov};
|
||||
} catch (vm::CellBuilder::CellCreateError) {
|
||||
throw VmError{Excno::cell_ov};
|
||||
} catch (vm::CellSlice::CellReadError) {
|
||||
throw VmError{Excno::cell_und};
|
||||
}
|
||||
} catch (const VmError& vme) {
|
||||
VM_LOG(this) << "handling exception code " << vme.get_errno() << ": " << vme.get_msg();
|
||||
try {
|
||||
++steps;
|
||||
res = throw_exception(vme.get_errno());
|
||||
} catch (const VmError& vme2) {
|
||||
VM_LOG(this) << "exception " << vme2.get_errno() << " while handling exception: " << vme.get_msg();
|
||||
return ~vme2.get_errno();
|
||||
}
|
||||
} catch (VmNoGas vmoog) {
|
||||
++steps;
|
||||
VM_LOG(this) << "unhandled out-of-gas exception: gas consumed=" << gas.gas_consumed()
|
||||
<< ", limit=" << gas.gas_limit;
|
||||
get_stack().clear();
|
||||
get_stack().push_smallint(gas.gas_consumed());
|
||||
return vmoog.get_errno(); // no ~ for unhandled exceptions (to make their faking impossible)
|
||||
}
|
||||
} while (!res);
|
||||
if ((res | 1) == -1 && !try_commit()) {
|
||||
|
@ -508,6 +499,34 @@ int VmState::run() {
|
|||
return res;
|
||||
}
|
||||
|
||||
int VmState::run() {
|
||||
if (code.is_null() || stack.is_null()) {
|
||||
// throw VmError{Excno::fatal, "cannot run an uninitialized VM"};
|
||||
return (int)Excno::fatal; // no ~ for unhandled exceptions
|
||||
}
|
||||
int res = 0;
|
||||
bool restore_parent = false;
|
||||
while (true) {
|
||||
try {
|
||||
if (restore_parent) {
|
||||
restore_parent_vm(~res);
|
||||
}
|
||||
res = run_inner();
|
||||
} catch (VmNoGas &vmoog) {
|
||||
++steps;
|
||||
VM_LOG(this) << "unhandled out-of-gas exception: gas consumed=" << gas.gas_consumed()
|
||||
<< ", limit=" << gas.gas_limit;
|
||||
get_stack().clear();
|
||||
get_stack().push_smallint(gas.gas_consumed());
|
||||
res = vmoog.get_errno(); // no ~ for unhandled exceptions (to make their faking impossible)
|
||||
}
|
||||
if (!parent) {
|
||||
return res;
|
||||
}
|
||||
restore_parent = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool VmState::try_commit() {
|
||||
if (cr.d[0].not_null() && cr.d[1].not_null() && cr.d[0]->get_depth() <= max_data_depth &&
|
||||
cr.d[1]->get_depth() <= max_data_depth && cr.d[0]->get_level() == 0 && cr.d[1]->get_level() == 0) {
|
||||
|
@ -540,7 +559,8 @@ ControlRegs* force_cregs(Ref<Continuation>& cont) {
|
|||
}
|
||||
|
||||
int run_vm_code(Ref<CellSlice> code, Ref<Stack>& stack, int flags, Ref<Cell>* data_ptr, VmLog log, long long* steps,
|
||||
GasLimits* gas_limits, std::vector<Ref<Cell>> libraries, Ref<Tuple> init_c7, Ref<Cell>* actions_ptr) {
|
||||
GasLimits* gas_limits, std::vector<Ref<Cell>> libraries, Ref<Tuple> init_c7, Ref<Cell>* actions_ptr,
|
||||
int global_version) {
|
||||
VmState vm{code,
|
||||
std::move(stack),
|
||||
gas_limits ? *gas_limits : GasLimits{},
|
||||
|
@ -549,6 +569,7 @@ int run_vm_code(Ref<CellSlice> code, Ref<Stack>& stack, int flags, Ref<Cell>* da
|
|||
log,
|
||||
std::move(libraries),
|
||||
std::move(init_c7)};
|
||||
vm.set_global_version(global_version);
|
||||
int res = vm.run();
|
||||
stack = vm.get_stack_ref();
|
||||
if (vm.committed() && data_ptr) {
|
||||
|
@ -578,12 +599,13 @@ int run_vm_code(Ref<CellSlice> code, Ref<Stack>& stack, int flags, Ref<Cell>* da
|
|||
}
|
||||
|
||||
int run_vm_code(Ref<CellSlice> code, Stack& stack, int flags, Ref<Cell>* data_ptr, VmLog log, long long* steps,
|
||||
GasLimits* gas_limits, std::vector<Ref<Cell>> libraries, Ref<Tuple> init_c7, Ref<Cell>* actions_ptr) {
|
||||
GasLimits* gas_limits, std::vector<Ref<Cell>> libraries, Ref<Tuple> init_c7, Ref<Cell>* actions_ptr,
|
||||
int global_version) {
|
||||
Ref<Stack> stk{true};
|
||||
stk.unique_write().set_contents(std::move(stack));
|
||||
stack.clear();
|
||||
int res = run_vm_code(code, stk, flags, data_ptr, log, steps, gas_limits, std::move(libraries), std::move(init_c7),
|
||||
actions_ptr);
|
||||
actions_ptr, global_version);
|
||||
CHECK(stack.is_unique());
|
||||
if (stk.is_null()) {
|
||||
stack.clear();
|
||||
|
@ -604,7 +626,7 @@ int run_vm_code(Ref<CellSlice> code, Stack& stack, int flags, Ref<Cell>* data_pt
|
|||
Ref<Cell> VmState::load_library(td::ConstBitPtr hash) {
|
||||
std::unique_ptr<VmStateInterface> tmp_ctx;
|
||||
// install temporary dummy vm state interface to prevent charging for cell load operations during library lookup
|
||||
VmStateInterface::Guard(tmp_ctx.get());
|
||||
VmStateInterface::Guard guard{global_version >= 4 ? tmp_ctx.get() : VmStateInterface::get()};
|
||||
for (const auto& lib_collection : libraries) {
|
||||
auto lib = lookup_library_in(hash, lib_collection);
|
||||
if (lib.not_null()) {
|
||||
|
@ -628,9 +650,6 @@ void VmState::register_cell_load(const CellHash& cell_hash) {
|
|||
consume_gas(cell_load_gas_price);
|
||||
} else {
|
||||
auto ok = loaded_cells.insert(cell_hash); // check whether this is the first time this cell is loaded
|
||||
if (ok.second) {
|
||||
loaded_cells_count++;
|
||||
}
|
||||
consume_gas(ok.second ? cell_load_gas_price : cell_reload_gas_price);
|
||||
}
|
||||
}
|
||||
|
@ -677,4 +696,78 @@ Ref<vm::Cell> lookup_library_in(td::ConstBitPtr key, Ref<vm::Cell> lib_root) {
|
|||
return lookup_library_in(key, dict);
|
||||
}
|
||||
|
||||
void VmState::run_child_vm(VmState&& new_state, bool return_data, bool return_actions, bool return_gas,
|
||||
bool isolate_gas, int ret_vals) {
|
||||
new_state.log = std::move(log);
|
||||
new_state.libraries = std::move(libraries);
|
||||
new_state.stack_trace = stack_trace;
|
||||
new_state.max_data_depth = max_data_depth;
|
||||
if (!isolate_gas) {
|
||||
new_state.loaded_cells = std::move(loaded_cells);
|
||||
} else {
|
||||
consume_gas(std::min<long long>(chksgn_counter, chksgn_free_count) * chksgn_gas_price);
|
||||
chksgn_counter = 0;
|
||||
}
|
||||
new_state.chksgn_counter = chksgn_counter;
|
||||
|
||||
auto new_parent = std::make_unique<ParentVmState>();
|
||||
new_parent->return_data = return_data;
|
||||
new_parent->return_actions = return_actions;
|
||||
new_parent->return_gas = return_gas;
|
||||
new_parent->isolate_gas = isolate_gas;
|
||||
new_parent->ret_vals = ret_vals;
|
||||
new_parent->state = std::move(*this);
|
||||
new_state.parent = std::move(new_parent);
|
||||
*this = std::move(new_state);
|
||||
}
|
||||
|
||||
void VmState::restore_parent_vm(int res) {
|
||||
auto parent = std::move(this->parent);
|
||||
CHECK(parent);
|
||||
VmState child_state = std::move(*this);
|
||||
*this = std::move(parent->state);
|
||||
log = std::move(child_state.log);
|
||||
libraries = std::move(child_state.libraries);
|
||||
steps += child_state.steps;
|
||||
if (!parent->isolate_gas) {
|
||||
loaded_cells = std::move(child_state.loaded_cells);
|
||||
}
|
||||
chksgn_counter = child_state.chksgn_counter;
|
||||
VM_LOG(this) << "Child VM finished. res: " << res << ", steps: " << child_state.steps
|
||||
<< ", gas: " << child_state.gas_consumed();
|
||||
|
||||
consume_gas(std::min(child_state.gas_consumed(), child_state.gas.gas_limit + 1));
|
||||
Stack& cur_stack = get_stack();
|
||||
int ret_cnt;
|
||||
if (res == 0 || res == 1) {
|
||||
if (parent->ret_vals >= 0) {
|
||||
if (child_state.stack->depth() >= parent->ret_vals) {
|
||||
ret_cnt = parent->ret_vals;
|
||||
} else {
|
||||
ret_cnt = 0;
|
||||
res = ~(int)Excno::stk_und;
|
||||
cur_stack.push(td::zero_refint());
|
||||
}
|
||||
} else {
|
||||
ret_cnt = child_state.stack->depth();
|
||||
}
|
||||
} else {
|
||||
ret_cnt = std::min(child_state.stack->depth(), 1);
|
||||
}
|
||||
consume_stack_gas(ret_cnt);
|
||||
for (int i = ret_cnt - 1; i >= 0; --i) {
|
||||
cur_stack.push(std::move(child_state.stack->at(i)));
|
||||
}
|
||||
cur_stack.push_smallint(res);
|
||||
if (parent->return_data) {
|
||||
cur_stack.push_cell(child_state.get_committed_state().c4);
|
||||
}
|
||||
if (parent->return_actions) {
|
||||
cur_stack.push_cell(child_state.get_committed_state().c5);
|
||||
}
|
||||
if (parent->return_gas) {
|
||||
cur_stack.push_smallint(child_state.gas.gas_consumed());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace vm
|
||||
|
|
|
@ -80,6 +80,8 @@ struct CommittedState {
|
|||
bool committed{false};
|
||||
};
|
||||
|
||||
struct ParentVmState;
|
||||
|
||||
class VmState final : public VmStateInterface {
|
||||
Ref<CellSlice> code;
|
||||
Ref<Stack> stack;
|
||||
|
@ -93,11 +95,13 @@ class VmState final : public VmStateInterface {
|
|||
GasLimits gas;
|
||||
std::vector<Ref<Cell>> libraries;
|
||||
td::HashSet<CellHash> loaded_cells;
|
||||
td::int64 loaded_cells_count{0};
|
||||
int stack_trace{0}, debug_off{0};
|
||||
bool chksig_always_succeed{false};
|
||||
td::ConstBitPtr missing_library{0};
|
||||
td::uint16 max_data_depth = 512; // Default value
|
||||
int global_version{0};
|
||||
size_t chksgn_counter = 0;
|
||||
std::unique_ptr<ParentVmState> parent = nullptr;
|
||||
|
||||
public:
|
||||
enum {
|
||||
|
@ -109,7 +113,51 @@ class VmState final : public VmStateInterface {
|
|||
implicit_jmpref_gas_price = 10,
|
||||
implicit_ret_gas_price = 5,
|
||||
free_stack_depth = 32,
|
||||
stack_entry_gas_price = 1
|
||||
stack_entry_gas_price = 1,
|
||||
runvm_gas_price = 40,
|
||||
hash_ext_entry_gas_price = 1,
|
||||
|
||||
rist255_mul_gas_price = 2000,
|
||||
rist255_mulbase_gas_price = 750,
|
||||
rist255_add_gas_price = 600,
|
||||
rist255_fromhash_gas_price = 600,
|
||||
rist255_validate_gas_price = 200,
|
||||
|
||||
ecrecover_gas_price = 1500,
|
||||
chksgn_free_count = 10,
|
||||
chksgn_gas_price = 4000,
|
||||
p256_chksgn_gas_price = 3500,
|
||||
|
||||
bls_verify_gas_price = 61300,
|
||||
bls_aggregate_base_gas_price = -2645,
|
||||
bls_aggregate_element_gas_price = 4355,
|
||||
bls_fast_aggregate_verify_base_gas_price = 58400,
|
||||
bls_fast_aggregate_verify_element_gas_price = 2990,
|
||||
bls_aggregate_verify_base_gas_price = 37275,
|
||||
bls_aggregate_verify_element_gas_price = 22290,
|
||||
|
||||
bls_g1_add_sub_gas_price = 3925,
|
||||
bls_g1_neg_gas_price = 765,
|
||||
bls_g1_mul_gas_price = 5180,
|
||||
bls_map_to_g1_gas_price = 2330,
|
||||
bls_g1_in_group_gas_price = 2930,
|
||||
|
||||
bls_g2_add_sub_gas_price = 6100,
|
||||
bls_g2_neg_gas_price = 1550,
|
||||
bls_g2_mul_gas_price = 10530,
|
||||
bls_map_to_g2_gas_price = 7970,
|
||||
bls_g2_in_group_gas_price = 4255,
|
||||
|
||||
// multiexp gas = base + n * coef1 + n/floor(max(log2(n), 4)) * coef2
|
||||
bls_g1_multiexp_base_gas_price = 11375,
|
||||
bls_g1_multiexp_coef1_gas_price = 630,
|
||||
bls_g1_multiexp_coef2_gas_price = 8820,
|
||||
bls_g2_multiexp_base_gas_price = 30388,
|
||||
bls_g2_multiexp_coef1_gas_price = 1280,
|
||||
bls_g2_multiexp_coef2_gas_price = 22840,
|
||||
|
||||
bls_pairing_base_gas_price = 20000,
|
||||
bls_pairing_element_gas_price = 11770
|
||||
};
|
||||
VmState();
|
||||
VmState(Ref<CellSlice> _code);
|
||||
|
@ -122,9 +170,9 @@ class VmState final : public VmStateInterface {
|
|||
: VmState(convert_code_cell(std::move(code_cell)), std::forward<Args>(args)...) {
|
||||
}
|
||||
VmState(const VmState&) = delete;
|
||||
VmState(VmState&&) = delete;
|
||||
VmState(VmState&&) = default;
|
||||
VmState& operator=(const VmState&) = delete;
|
||||
VmState& operator=(VmState&&) = delete;
|
||||
VmState& operator=(VmState&&) = default;
|
||||
bool set_gas_limits(long long _max, long long _limit, long long _credit = 0);
|
||||
bool final_gas_ok() const {
|
||||
return gas.final_ok();
|
||||
|
@ -138,8 +186,15 @@ class VmState final : public VmStateInterface {
|
|||
const CommittedState& get_committed_state() const {
|
||||
return cstate;
|
||||
}
|
||||
void consume_gas_chk(long long amount) {
|
||||
gas.consume_chk(amount);
|
||||
}
|
||||
void consume_gas(long long amount) {
|
||||
gas.consume(amount);
|
||||
if (global_version >= 4) {
|
||||
gas.consume_chk(amount);
|
||||
} else {
|
||||
gas.consume(amount);
|
||||
}
|
||||
}
|
||||
void consume_tuple_gas(unsigned tuple_len) {
|
||||
consume_gas(tuple_len * tuple_entry_gas_price);
|
||||
|
@ -283,6 +338,12 @@ class VmState final : public VmStateInterface {
|
|||
void preclear_cr(const ControlRegs& save) {
|
||||
cr &= save;
|
||||
}
|
||||
int get_global_version() const {
|
||||
return global_version;
|
||||
}
|
||||
void set_global_version(int version) {
|
||||
global_version = version;
|
||||
}
|
||||
int call(Ref<Continuation> cont);
|
||||
int call(Ref<Continuation> cont, int pass_args, int ret_args = -1);
|
||||
int jump(Ref<Continuation> cont);
|
||||
|
@ -328,17 +389,36 @@ class VmState final : public VmStateInterface {
|
|||
void set_max_data_depth(td::uint16 depth) {
|
||||
max_data_depth = depth;
|
||||
}
|
||||
void run_child_vm(VmState&& new_state, bool return_data, bool return_actions, bool return_gas, bool isolate_gas,
|
||||
int ret_vals);
|
||||
void restore_parent_vm(int res);
|
||||
|
||||
void register_chksgn_call() {
|
||||
if (global_version >= 4) {
|
||||
++chksgn_counter;
|
||||
if (chksgn_counter > chksgn_free_count) {
|
||||
consume_gas(chksgn_gas_price);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void init_cregs(bool same_c3 = false, bool push_0 = true);
|
||||
int run_inner();
|
||||
};
|
||||
|
||||
struct ParentVmState {
|
||||
VmState state;
|
||||
bool return_data, return_actions, return_gas, isolate_gas;
|
||||
int ret_vals;
|
||||
};
|
||||
|
||||
int run_vm_code(Ref<CellSlice> _code, Ref<Stack>& _stack, int flags = 0, Ref<Cell>* data_ptr = nullptr, VmLog log = {},
|
||||
long long* steps = nullptr, GasLimits* gas_limits = nullptr, std::vector<Ref<Cell>> libraries = {},
|
||||
Ref<Tuple> init_c7 = {}, Ref<Cell>* actions_ptr = nullptr);
|
||||
Ref<Tuple> init_c7 = {}, Ref<Cell>* actions_ptr = nullptr, int global_version = 0);
|
||||
int run_vm_code(Ref<CellSlice> _code, Stack& _stack, int flags = 0, Ref<Cell>* data_ptr = nullptr, VmLog log = {},
|
||||
long long* steps = nullptr, GasLimits* gas_limits = nullptr, std::vector<Ref<Cell>> libraries = {},
|
||||
Ref<Tuple> init_c7 = {}, Ref<Cell>* actions_ptr = nullptr);
|
||||
Ref<Tuple> init_c7 = {}, Ref<Cell>* actions_ptr = nullptr, int global_version = 0);
|
||||
|
||||
Ref<vm::Cell> lookup_library_in(td::ConstBitPtr key, Ref<vm::Cell> lib_root);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue