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

updated smartcontracts

- updated smartcontracts
- updated fullnode database layout
- fixed memory leak in blockchain-explorer
- updated tonlib
This commit is contained in:
ton 2019-10-23 17:43:50 +04:00
parent 9c9248a9ae
commit c860ce3d1e
104 changed files with 7309 additions and 1335 deletions

View file

@ -0,0 +1,64 @@
#include "CellString.h"
#include "td/utils/misc.h"
#include "vm/cells/CellSlice.h"
namespace vm {
td::Status CellString::store(CellBuilder &cb, td::Slice slice, unsigned int top_bits) {
td::uint32 size = td::narrow_cast<td::uint32>(slice.size() * 8);
return store(cb, td::BitSlice(slice.ubegin(), size), top_bits);
}
td::Status CellString::store(CellBuilder &cb, td::BitSlice slice, unsigned int top_bits) {
if (slice.size() > max_bytes * 8) {
return td::Status::Error("String is too long (1)");
}
unsigned int head = td::min(slice.size(), td::min(cb.remaining_bits(), top_bits)) / 8 * 8;
auto max_bits = vm::Cell::max_bits / 8 * 8;
auto depth = 1 + (slice.size() - head + max_bits - 1) / max_bits;
if (depth > max_chain_length) {
return td::Status::Error("String is too long (2)");
}
cb.append_bitslice(slice.subslice(0, head));
slice.advance(head);
if (slice.size() == 0) {
return td::Status::OK();
}
CellBuilder child_cb;
store(child_cb, std::move(slice));
cb.store_ref(child_cb.finalize());
return td::Status::OK();
}
template <class F>
void CellString::for_each(F &&f, CellSlice &cs, unsigned int top_bits) {
unsigned int head = td::min(cs.size(), top_bits);
f(cs.prefetch_bits(head));
if (!cs.have_refs()) {
return;
}
auto ref = cs.prefetch_ref();
while (true) {
auto cs = vm::load_cell_slice(ref);
f(cs.prefetch_bits(cs.size()));
if (!cs.have_refs()) {
return;
}
ref = cs.prefetch_ref();
}
}
td::Result<td::string> CellString::load(CellSlice &cs, unsigned int top_bits) {
unsigned int size = 0;
for_each([&](auto slice) { size += slice.size(); }, cs, top_bits);
if (size % 8 != 0) {
return td::Status::Error("Size is not divisible by 8");
}
std::string res(size / 8, 0);
td::BitPtr to(td::MutableSlice(res).ubegin());
for_each([&](auto slice) { to.concat(slice); }, cs, top_bits);
CHECK(to.offs == (int)size);
return res;
}
} // namespace vm

View file

@ -0,0 +1,22 @@
#pragma once
#include "td/utils/Status.h"
#include "vm/cells/CellBuilder.h"
namespace vm {
class CellString {
public:
static constexpr unsigned int max_bytes = 1024;
static constexpr unsigned int max_chain_length = 16;
static td::Status store(CellBuilder &cb, td::Slice slice, unsigned int top_bits = Cell::max_bits);
static td::Status store(CellBuilder &cb, td::BitSlice slice, unsigned int top_bits = Cell::max_bits);
static td::Result<td::string> load(CellSlice &cs, unsigned int top_bits = Cell::max_bits);
private:
template <class F>
static void for_each(F &&f, CellSlice &cs, unsigned int top_bits = Cell::max_bits);
};
} // namespace vm

View file

@ -744,6 +744,9 @@ int VmState::run() {
}
} while (!res);
// LOG(INFO) << "[EN] data cells: " << DataCell::get_total_data_cells();
if ((res | 1) == -1) {
commit();
}
return res;
}

View file

@ -154,7 +154,7 @@ struct ControlData {
class Continuation : public td::CntObject {
public:
virtual int jump(VmState* st) const & = 0;
virtual int jump(VmState* st) const& = 0;
virtual int jump_w(VmState* st) &;
virtual ControlData* get_cdata() {
return 0;
@ -184,7 +184,7 @@ class QuitCont : public Continuation {
QuitCont(int _code = 0) : exit_code(_code) {
}
~QuitCont() override = default;
int jump(VmState* st) const & override {
int jump(VmState* st) const& override {
return ~exit_code;
}
};
@ -193,7 +193,7 @@ class ExcQuitCont : public Continuation {
public:
ExcQuitCont() = default;
~ExcQuitCont() override = default;
int jump(VmState* st) const & override;
int jump(VmState* st) const& override;
};
class PushIntCont : public Continuation {
@ -204,7 +204,7 @@ class PushIntCont : public Continuation {
PushIntCont(int val, Ref<Continuation> _next) : push_val(val), next(_next) {
}
~PushIntCont() override = default;
int jump(VmState* st) const & override;
int jump(VmState* st) const& override;
int jump_w(VmState* st) & override;
};
@ -217,7 +217,7 @@ class RepeatCont : public Continuation {
: body(std::move(_body)), after(std::move(_after)), count(_count) {
}
~RepeatCont() override = default;
int jump(VmState* st) const & override;
int jump(VmState* st) const& override;
int jump_w(VmState* st) & override;
};
@ -228,7 +228,7 @@ class AgainCont : public Continuation {
AgainCont(Ref<Continuation> _body) : body(std::move(_body)) {
}
~AgainCont() override = default;
int jump(VmState* st) const & override;
int jump(VmState* st) const& override;
int jump_w(VmState* st) & override;
};
@ -239,7 +239,7 @@ class UntilCont : public Continuation {
UntilCont(Ref<Continuation> _body, Ref<Continuation> _after) : body(std::move(_body)), after(std::move(_after)) {
}
~UntilCont() override = default;
int jump(VmState* st) const & override;
int jump(VmState* st) const& override;
int jump_w(VmState* st) & override;
};
@ -252,7 +252,7 @@ class WhileCont : public Continuation {
: cond(std::move(_cond)), body(std::move(_body)), after(std::move(_after)), chkcond(_chk) {
}
~WhileCont() override = default;
int jump(VmState* st) const & override;
int jump(VmState* st) const& override;
int jump_w(VmState* st) & override;
};
@ -268,7 +268,7 @@ class ArgContExt : public Continuation {
ArgContExt(const ArgContExt&) = default;
ArgContExt(ArgContExt&&) = default;
~ArgContExt() override = default;
int jump(VmState* st) const & override;
int jump(VmState* st) const& override;
int jump_w(VmState* st) & override;
ControlData* get_cdata() override {
return &data;
@ -303,7 +303,7 @@ class OrdCont : public Continuation {
td::CntObject* make_copy() const override {
return new OrdCont{*this};
}
int jump(VmState* st) const & override;
int jump(VmState* st) const& override;
int jump_w(VmState* st) & override;
ControlData* get_cdata() override {
@ -321,7 +321,7 @@ class OrdCont : public Continuation {
Ref<Stack> get_stack_ref() const {
return data.stack;
}
Ref<OrdCont> copy_ord() const & {
Ref<OrdCont> copy_ord() const& {
return Ref<OrdCont>{true, *this};
}
Ref<OrdCont> copy_ord() && {
@ -375,10 +375,16 @@ struct GasLimits {
}
};
struct CommittedState {
Ref<vm::Cell> c4, c5;
bool committed{false};
};
class VmState final : public VmStateInterface {
Ref<CellSlice> code;
Ref<Stack> stack;
ControlRegs cr;
CommittedState cstate;
int cp;
long long steps{0};
const DispatchTable* dispatch;
@ -388,6 +394,8 @@ class VmState final : public VmStateInterface {
std::vector<Ref<Cell>> libraries;
int stack_trace{0}, debug_off{0};
bool chksig_always_succeed{false};
public:
static constexpr unsigned cell_load_gas_price = 100, cell_create_gas_price = 500, exception_gas_price = 50,
tuple_entry_gas_price = 1;
@ -401,6 +409,10 @@ class VmState final : public VmStateInterface {
VmState(Ref<Cell> code_cell, Args&&... args)
: VmState(convert_code_cell(std::move(code_cell)), std::forward<Args>(args)...) {
}
VmState(const VmState&) = delete;
VmState(VmState&&) = delete;
VmState& operator=(const VmState&) = delete;
VmState& operator=(VmState&&) = delete;
bool set_gas_limits(long long _max, long long _limit, long long _credit = 0);
bool final_gas_ok() const {
return gas.final_ok();
@ -408,6 +420,12 @@ class VmState final : public VmStateInterface {
long long gas_consumed() const {
return gas.gas_consumed();
}
bool committed() const {
return cstate.committed;
}
const CommittedState& get_committed_state() const {
return cstate;
}
void consume_gas(long long amount) {
gas.consume(amount);
}
@ -567,6 +585,18 @@ class VmState final : public VmStateInterface {
return cont->is_unique() ? cont.unique_write().jump_w(this) : cont->jump(this);
}
static Ref<CellSlice> convert_code_cell(Ref<Cell> code_cell);
void commit() {
cstate.c4 = cr.d[0];
cstate.c5 = cr.d[1];
cstate.committed = true;
}
void set_chksig_always_succeed(bool flag) {
chksig_always_succeed = flag;
}
bool get_chksig_always_succeed() const {
return chksig_always_succeed;
}
private:
void init_cregs(bool same_c3 = false, bool push_0 = true);

View file

@ -18,6 +18,8 @@
*/
#pragma once
#include "td/utils/Status.h"
namespace vm {
enum class Excno : int {
@ -95,4 +97,19 @@ struct VmVirtError {
struct VmFatal {};
template <class F>
auto try_f(F&& f) noexcept -> decltype(f()) {
try {
return f();
} catch (vm::VmError error) {
return td::Status::Error(PSLICE() << "Got a vm exception: " << error.get_msg());
} catch (vm::VmVirtError error) {
return td::Status::Error(PSLICE() << "Got a vm virtualization exception: " << error.get_msg());
} catch (vm::VmNoGas error) {
return td::Status::Error(PSLICE() << "Got a vm no gas exception: " << error.get_msg());
}
}
#define TRY_VM(f) ::vm::try_f([&] { return f; })
} // namespace vm

View file

@ -75,10 +75,17 @@ int exec_set_gas_limit(VmState* st) {
return exec_set_gas_generic(st, gas);
}
int exec_commit(VmState* st) {
VM_LOG(st) << "execute COMMIT";
st->commit();
return 0;
}
void register_basic_gas_ops(OpcodeTable& cp0) {
using namespace std::placeholders;
cp0.insert(OpcodeInstr::mksimple(0xf800, 16, "ACCEPT", exec_accept))
.insert(OpcodeInstr::mksimple(0xf801, 16, "SETGASLIMIT", exec_set_gas_limit));
.insert(OpcodeInstr::mksimple(0xf801, 16, "SETGASLIMIT", exec_set_gas_limit))
.insert(OpcodeInstr::mksimple(0xf80f, 16, "COMMIT", exec_commit));
}
void register_ton_gas_ops(OpcodeTable& cp0) {
@ -268,7 +275,7 @@ int exec_ed25519_check_signature(VmState* st, bool from_slice) {
}
td::Ed25519::PublicKey pub_key{td::SecureString(td::Slice{key, 32})};
auto res = pub_key.verify_signature(td::Slice{data, data_len}, td::Slice{signature, 64});
stack.push_bool(res.is_ok());
stack.push_bool(res.is_ok() || st->get_chksig_always_succeed());
return 0;
}