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:
parent
d41ce55305
commit
acf16718e6
45 changed files with 1360 additions and 185 deletions
|
@ -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());
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue