1
0
Fork 0
mirror of https://github.com/ton-blockchain/ton synced 2025-03-09 15:40:10 +00:00

updated func/fift

- updated func/fift
- updated liteclient/liteserver
- bugfixes
This commit is contained in:
ton 2019-12-29 12:14:12 +03:00
parent d41ce55305
commit acf16718e6
45 changed files with 1360 additions and 185 deletions

View file

@ -143,19 +143,80 @@ Ref<Cell> MerkleProof::virtualize(Ref<Cell> cell, int virtualization) {
return virtualize_raw(r_raw.move_as_ok(), {0 /*level*/, static_cast<td::uint8>(virtualization)});
}
class MerkleProofCombineFast {
public:
MerkleProofCombineFast(Ref<Cell> a, Ref<Cell> b) : a_(std::move(a)), b_(std::move(b)) {
}
td::Result<Ref<Cell>> run() {
TRY_RESULT_ASSIGN(a_, unpack_proof(a_));
TRY_RESULT_ASSIGN(b_, unpack_proof(b_));
TRY_RESULT(res, run_raw());
return CellBuilder::create_merkle_proof(std::move(res));
}
td::Result<Ref<Cell>> run_raw() {
if (a_->get_hash(0) != b_->get_hash(0)) {
return td::Status::Error("Can't combine MerkleProofs with different roots");
}
return merge(a_, b_, 0);
}
private:
Ref<Cell> a_;
Ref<Cell> b_;
Ref<Cell> merge(Ref<Cell> a, Ref<Cell> b, td::uint32 merkle_depth) {
if (a->get_hash() == b->get_hash()) {
return a;
}
if (a->get_level() == merkle_depth) {
return a;
}
if (b->get_level() == merkle_depth) {
return b;
}
CellSlice csa(NoVm(), a);
CellSlice csb(NoVm(), b);
if (csa.is_special() && csa.special_type() == vm::Cell::SpecialType::PrunnedBranch) {
return b;
}
if (csb.is_special() && csb.special_type() == vm::Cell::SpecialType::PrunnedBranch) {
return a;
}
CHECK(csa.size_refs() != 0);
auto child_merkle_depth = csa.child_merkle_depth(merkle_depth);
CellBuilder cb;
cb.store_bits(csa.fetch_bits(csa.size()));
for (unsigned i = 0; i < csa.size_refs(); i++) {
cb.store_ref(merge(csa.prefetch_ref(i), csb.prefetch_ref(i), child_merkle_depth));
}
return cb.finalize(csa.is_special());
}
};
class MerkleProofCombine {
public:
MerkleProofCombine(Ref<Cell> a, Ref<Cell> b) : a_(std::move(a)), b_(std::move(b)) {
}
td::Result<Ref<Cell>> run() {
TRY_RESULT(a, unpack_proof(a_));
TRY_RESULT(b, unpack_proof(b_));
if (a->get_hash(0) != b->get_hash(0)) {
TRY_RESULT_ASSIGN(a_, unpack_proof(a_));
TRY_RESULT_ASSIGN(b_, unpack_proof(b_));
TRY_RESULT(res, run_raw());
return CellBuilder::create_merkle_proof(std::move(res));
}
td::Result<Ref<Cell>> run_raw() {
if (a_->get_hash(0) != b_->get_hash(0)) {
return td::Status::Error("Can't combine MerkleProofs with different roots");
}
dfs(a, 0);
dfs(b, 0);
return CellBuilder::create_merkle_proof(create_A(a, 0, 0));
dfs(a_, 0);
dfs(b_, 0);
return create_A(a_, 0, 0);
}
private:
@ -262,6 +323,30 @@ Ref<Cell> MerkleProof::combine(Ref<Cell> a, Ref<Cell> b) {
return res.move_as_ok();
}
Ref<Cell> MerkleProof::combine_fast(Ref<Cell> a, Ref<Cell> b) {
auto res = MerkleProofCombineFast(std::move(a), std::move(b)).run();
if (res.is_error()) {
return {};
}
return res.move_as_ok();
}
Ref<Cell> MerkleProof::combine_raw(Ref<Cell> a, Ref<Cell> b) {
auto res = MerkleProofCombine(std::move(a), std::move(b)).run_raw();
if (res.is_error()) {
return {};
}
return res.move_as_ok();
}
Ref<Cell> MerkleProof::combine_fast_raw(Ref<Cell> a, Ref<Cell> b) {
auto res = MerkleProofCombineFast(std::move(a), std::move(b)).run_raw();
if (res.is_error()) {
return {};
}
return res.move_as_ok();
}
MerkleProofBuilder::MerkleProofBuilder(Ref<Cell> root)
: usage_tree(std::make_shared<CellUsageTree>()), orig_root(std::move(root)) {
usage_root = UsageCell::create(orig_root, usage_tree->root_ptr());

View file

@ -38,12 +38,15 @@ class MerkleProof {
static Ref<Cell> virtualize(Ref<Cell> cell, int virtualization);
static Ref<Cell> combine(Ref<Cell> a, Ref<Cell> b);
static Ref<Cell> combine_fast(Ref<Cell> a, Ref<Cell> b);
// works with upwrapped proofs
// works fine with cell of non-zero level, but this is not supported (yet?) in MerkeProof special cell
static Ref<Cell> generate_raw(Ref<Cell> cell, IsPrunnedFunction is_prunned);
static Ref<Cell> generate_raw(Ref<Cell> cell, CellUsageTree *usage_tree);
static Ref<Cell> virtualize_raw(Ref<Cell> cell, Cell::VirtualizationParameters virt);
static Ref<Cell> combine_raw(Ref<Cell> a, Ref<Cell> b);
static Ref<Cell> combine_fast_raw(Ref<Cell> a, Ref<Cell> b);
};
class MerkleProofBuilder {

View file

@ -268,7 +268,7 @@ class MerkleCombine {
// 1. Create maximum subtrees of X and Z with all cells in A, B, C and D
// Max(V) - such maximum subtree
//
// 2. Max(A) and Max(D) should be merkle update already. But win want to minimize it
// 2. Max(A) and Max(D) should be merkle update already. But we want to minimize it
// So we cut all branches of Max(D) which are in maxA
// When we cut branch q in Max(D) we mark some path to q in Max(A)
// Then we cut all branches of Max(A) which are not marked.

View file

@ -1055,7 +1055,7 @@ 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) {
GasLimits* gas_limits, std::vector<Ref<Cell>> libraries, Ref<Tuple> init_c7, Ref<Cell>* actions_ptr) {
VmState vm{code,
std::move(stack),
gas_limits ? *gas_limits : GasLimits{},
@ -1066,8 +1066,11 @@ int run_vm_code(Ref<CellSlice> code, Ref<Stack>& stack, int flags, Ref<Cell>* da
std::move(init_c7)};
int res = vm.run();
stack = vm.get_stack_ref();
if (res == -1 && data_ptr) {
*data_ptr = vm.get_c4();
if (vm.committed() && data_ptr) {
*data_ptr = vm.get_committed_state().c4;
}
if (vm.committed() && actions_ptr) {
*actions_ptr = vm.get_committed_state().c5;
}
if (steps) {
*steps = vm.get_steps_count();
@ -1090,11 +1093,12 @@ 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) {
GasLimits* gas_limits, std::vector<Ref<Cell>> libraries, Ref<Tuple> init_c7, Ref<Cell>* actions_ptr) {
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));
int res = run_vm_code(code, stk, flags, data_ptr, log, steps, gas_limits, std::move(libraries), std::move(init_c7),
actions_ptr);
CHECK(stack.is_unique());
if (stk.is_null()) {
stack.clear();

View file

@ -644,12 +644,12 @@ class VmState final : public VmStateInterface {
void init_cregs(bool same_c3 = false, bool push_0 = true);
};
int run_vm_code(Ref<CellSlice> _code, Ref<Stack>& _stack, int flags = 0, Ref<Cell>* data_ptr = 0, VmLog log = {},
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 = {});
int run_vm_code(Ref<CellSlice> _code, Stack& _stack, int flags = 0, Ref<Cell>* data_ptr = 0, VmLog log = {},
Ref<Tuple> init_c7 = {}, Ref<Cell>* actions_ptr = nullptr);
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<Tuple> init_c7 = {}, Ref<Cell>* actions_ptr = nullptr);
ControlData* force_cdata(Ref<Continuation>& cont);
ControlRegs* force_cregs(Ref<Continuation>& cont);

View file

@ -481,6 +481,18 @@ class Stack : public td::CntObject {
Ref<Atom> pop_atom();
std::string pop_string();
std::string pop_bytes();
template <typename T>
Ref<T> pop_object() {
return pop_chk().as_object<T>();
}
template <typename T>
Ref<T> pop_object_type_chk() {
auto res = pop_object<T>();
if (!res) {
throw VmError{Excno::type_chk, "not an object of required type"};
}
return res;
}
void push_null();
void push_int(td::RefInt256 val);
void push_int_quiet(td::RefInt256 val, bool quiet = true);