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

updated tonlib, block routing

- upated tonlib
- fixed bug in message routing
This commit is contained in:
ton 2019-09-28 11:44:38 +04:00
parent ac3eb1a7b8
commit fd7a8de970
33 changed files with 1002 additions and 381 deletions

View file

@ -552,7 +552,9 @@ bool MsgProcessedUpto::already_processed(const EnqueuedMsgDescr& msg) const {
if (msg.lt_ == last_inmsg_lt && last_inmsg_hash < msg.hash_) {
return false;
}
if (ton::shard_contains(shard, msg.cur_prefix_.account_id_prefix)) {
if (msg.same_workchain() && ton::shard_contains(shard, msg.cur_prefix_.account_id_prefix)) {
// this branch is needed only for messages generated in the same shard
// (such messages could have been processed without a reference from the masterchain)
// ? enable this branch only if an extra boolean parameter is set ?
return true;
}

View file

@ -145,6 +145,9 @@ struct EnqueuedMsgDescr {
return false;
}
bool unpack(vm::CellSlice& cs);
bool same_workchain() const {
return cur_prefix_.workchain == next_prefix_.workchain;
}
};
using compute_shard_end_lt_func_t = std::function<ton::LogicalTime(ton::AccountIdPrefixFull)>;

View file

@ -32,7 +32,7 @@ namespace block {
using namespace std::literals::string_literals;
td::Status check_block_header_proof(td::Ref<vm::Cell> root, ton::BlockIdExt blkid, ton::Bits256* store_shard_hash_to,
bool check_state_hash) {
bool check_state_hash, td::uint32* save_utime) {
ton::RootHash vhash{root->get_hash().bits()};
if (vhash != blkid.root_hash) {
return td::Status::Error(PSTRING() << " block header for block " << blkid.to_str() << " has incorrect root hash "
@ -47,6 +47,9 @@ td::Status check_block_header_proof(td::Ref<vm::Cell> root, ton::BlockIdExt blki
if (!(tlb::unpack_cell(root, blk) && tlb::unpack_cell(blk.info, info))) {
return td::Status::Error(std::string{"cannot unpack header for block "} + blkid.to_str());
}
if (save_utime) {
*save_utime = info.gen_utime;
}
if (store_shard_hash_to) {
vm::CellSlice upd_cs{vm::NoVmSpec(), blk.state_update};
if (!(upd_cs.is_special() && upd_cs.prefetch_long(8) == 4 // merkle update
@ -153,7 +156,8 @@ td::Status check_shard_proof(ton::BlockIdExt blk, ton::BlockIdExt shard_blk, td:
}
td::Status check_account_proof(td::Slice proof, ton::BlockIdExt shard_blk, const block::StdAddress& addr,
td::Ref<vm::Cell> root, ton::LogicalTime* last_trans_lt, ton::Bits256* last_trans_hash) {
td::Ref<vm::Cell> root, ton::LogicalTime* last_trans_lt, ton::Bits256* last_trans_hash,
td::uint32* save_utime) {
TRY_RESULT_PREFIX(Q_roots, vm::std_boc_deserialize_multi(std::move(proof)), "cannot deserialize account proof");
if (Q_roots.size() != 2) {
return td::Status::Error(PSLICE() << "account state proof must have exactly two roots");
@ -169,9 +173,9 @@ td::Status check_account_proof(td::Slice proof, ton::BlockIdExt shard_blk, const
return td::Status::Error("account state proof is invalid");
}
ton::Bits256 state_hash = state_root->get_hash().bits();
TRY_STATUS_PREFIX(
check_block_header_proof(vm::MerkleProof::virtualize(std::move(Q_roots[0]), 1), shard_blk, &state_hash, true),
"error in account shard block header proof : ");
TRY_STATUS_PREFIX(check_block_header_proof(vm::MerkleProof::virtualize(std::move(Q_roots[0]), 1), shard_blk,
&state_hash, true, save_utime),
"error in account shard block header proof : ");
block::gen::ShardStateUnsplit::Record sstate;
if (!(tlb::unpack_cell(std::move(state_root), sstate))) {
return td::Status::Error("cannot unpack state header");
@ -233,8 +237,8 @@ td::Result<AccountState::Info> AccountState::validate(ton::BlockIdExt ref_blk, b
TRY_STATUS(block::check_shard_proof(blk, shard_blk, shard_proof.as_slice()));
Info res;
TRY_STATUS(
block::check_account_proof(proof.as_slice(), shard_blk, addr, root, &res.last_trans_lt, &res.last_trans_hash));
TRY_STATUS(block::check_account_proof(proof.as_slice(), shard_blk, addr, root, &res.last_trans_lt,
&res.last_trans_hash, &res.gen_utime));
res.root = std::move(root);
return res;

View file

@ -25,11 +25,12 @@ namespace block {
using td::Ref;
td::Status check_block_header_proof(td::Ref<vm::Cell> root, ton::BlockIdExt blkid,
ton::Bits256* store_shard_hash_to = nullptr, bool check_state_hash = false);
ton::Bits256* store_shard_hash_to = nullptr, bool check_state_hash = false,
td::uint32* save_utime = nullptr);
td::Status check_shard_proof(ton::BlockIdExt blk, ton::BlockIdExt shard_blk, td::Slice shard_proof);
td::Status check_account_proof(td::Slice proof, ton::BlockIdExt shard_blk, const block::StdAddress& addr,
td::Ref<vm::Cell> root, ton::LogicalTime* last_trans_lt = nullptr,
ton::Bits256* last_trans_hash = nullptr);
ton::Bits256* last_trans_hash = nullptr, td::uint32* save_utime = nullptr);
td::Result<td::Bits256> check_state_proof(ton::BlockIdExt blkid, td::Slice proof);
td::Result<Ref<vm::Cell>> check_extract_state_proof(ton::BlockIdExt blkid, td::Slice proof, td::Slice data);
@ -47,6 +48,7 @@ struct AccountState {
td::Ref<vm::Cell> root;
ton::LogicalTime last_trans_lt = 0;
ton::Bits256 last_trans_hash;
td::uint32 gen_utime{0};
};
td::Result<Info> validate(ton::BlockIdExt ref_blk, block::StdAddress addr) const;

View file

@ -1027,6 +1027,12 @@ bool Transaction::prepare_action_phase(const ActionPhaseConfig& cfg) {
break;
case block::gen::OutAction::action_send_msg:
err_code = try_action_send_msg(cs, ap, cfg);
if (err_code == -2) {
err_code = try_action_send_msg(cs, ap, cfg, 1);
if (err_code == -2) {
err_code = try_action_send_msg(cs, ap, cfg, 2);
}
}
break;
case block::gen::OutAction::action_reserve_currency:
err_code = try_action_reserve_currency(cs, ap, cfg);
@ -1240,22 +1246,60 @@ bool Transaction::check_rewrite_dest_addr(Ref<vm::CellSlice>& dest_addr, const A
return true;
}
int Transaction::try_action_send_msg(vm::CellSlice& cs, ActionPhase& ap, const ActionPhaseConfig& cfg) {
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, +1 = pay message fees, +2 = skip if message cannot be sent
vm::CellSlice cs{cs0};
if (!tlb::unpack_exact(cs, act_rec) || (act_rec.mode & ~0xc3) || (act_rec.mode & 0xc0) == 0xc0) {
return -1;
}
bool skip_invalid = (act_rec.mode & 2);
auto cs2 = vm::load_cell_slice(act_rec.out_msg);
// try to parse suggested message in cs2
// try to parse suggested message in act_rec.out_msg
td::RefInt256 fwd_fee, ihr_fee;
bool ext_msg = cs2.prefetch_ulong(1);
block::gen::MessageRelaxed::Record msg;
if (!tlb::type_unpack_cell(act_rec.out_msg, block::gen::t_MessageRelaxed_Any, msg)) {
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";
// init:(Maybe (Either StateInit ^StateInit))
// transform (just (left z:StateInit)) into (just (right z:^StateInit))
CHECK(msg.init.write().fetch_ulong(2) == 2);
vm::CellBuilder cb;
Ref<vm::Cell> cell;
CHECK(cb.append_cellslice_bool(std::move(msg.init)) // StateInit
&& cb.finalize_to(cell) // -> ^StateInit
&& 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));
} else {
redoing = 2;
}
}
if (redoing >= 2 && msg.body->size_ext() > 1 && msg.body->prefetch_ulong(1) == 0) {
LOG(DEBUG) << "moving the body of a suggested outbound message into a separate cell";
// body:(Either X ^X)
// transform (left x:X) into (right x:^X)
CHECK(msg.body.write().fetch_ulong(1) == 0);
vm::CellBuilder cb;
Ref<vm::Cell> cell;
CHECK(cb.append_cellslice_bool(std::move(msg.body)) // X
&& cb.finalize_to(cell) // -> ^X
&& 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));
}
block::gen::CommonMsgInfoRelaxed::Record_int_msg_info info;
bool ext_msg = msg.info->prefetch_ulong(1);
if (ext_msg) {
// ext_out_msg_info$11 constructor of CommonMsgInfoRelaxed
block::gen::CommonMsgInfoRelaxed::Record_ext_out_msg_info erec;
if (!tlb::unpack(cs2, erec)) {
if (!tlb::csr_unpack(msg.info, erec)) {
return -1;
}
info.src = std::move(erec.src);
@ -1267,7 +1311,7 @@ int Transaction::try_action_send_msg(vm::CellSlice& cs, ActionPhase& ap, const A
fwd_fee = ihr_fee = td::RefInt256{true, 0};
} else {
// int_msg_info$0 constructor
if (!tlb::unpack(cs2, info) || !block::tlb::t_CurrencyCollection.validate_csr(info.value)) {
if (!tlb::csr_unpack(msg.info, info) || !block::tlb::t_CurrencyCollection.validate_csr(info.value)) {
return -1;
}
fwd_fee = block::tlb::t_Grams.as_integer(info.fwd_fee);
@ -1295,12 +1339,11 @@ int Transaction::try_action_send_msg(vm::CellSlice& cs, ActionPhase& ap, const A
// compute size of message
vm::CellStorageStat sstat; // for message size
// preliminary storage estimation of the resulting message
sstat.compute_used_storage(cs2); // message body
sstat.add_used_storage(msg.init, true, 3); // message init
sstat.add_used_storage(msg.body, true, 3); // message body (the root cell itself is not counted)
if (!ext_msg) {
sstat.add_used_storage(info.value->prefetch_ref());
}
sstat.bits -= cs2.size(); // bits in the root cells are free
sstat.cells--; // the root cell itself is not counted as a cell
LOG(DEBUG) << "storage paid for a message: " << sstat.cells << " cells, " << sstat.bits << " bits";
if (sstat.bits > max_msg_bits || sstat.cells > max_msg_cells) {
LOG(DEBUG) << "message too large, invalid";
@ -1397,17 +1440,15 @@ int Transaction::try_action_send_msg(vm::CellSlice& cs, ActionPhase& ap, const A
// re-pack message value
CHECK(req.pack_to(info.value));
vm::CellBuilder cb;
CHECK(block::tlb::t_Grams.store_integer_ref(cb, fwd_fee_remain) &&
(info.fwd_fee = load_cell_slice_ref(cb.finalize())).not_null());
CHECK(block::tlb::t_Grams.store_integer_ref(cb, ihr_fee) &&
(info.ihr_fee = load_cell_slice_ref(cb.finalize())).not_null());
CHECK(block::tlb::t_Grams.pack_integer(info.fwd_fee, fwd_fee_remain));
CHECK(block::tlb::t_Grams.pack_integer(info.ihr_fee, ihr_fee));
// serialize message
CHECK(tlb::pack(cb, info));
if (!cb.append_cellslice_bool(cs2)) {
CHECK(tlb::csr_pack(msg.info, info));
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 39;
return redoing < 2 ? -2 : (skip_invalid ? 0 : 39);
}
new_msg_bits = cb.size();
@ -1438,11 +1479,11 @@ int Transaction::try_action_send_msg(vm::CellSlice& cs, ActionPhase& ap, const A
erec.dest = info.dest;
erec.created_at = info.created_at;
erec.created_lt = info.created_lt;
CHECK(tlb::csr_pack(msg.info, erec));
vm::CellBuilder cb;
CHECK(tlb::pack(cb, erec));
if (!cb.append_cellslice_bool(cs2)) {
if (!tlb::type_pack(cb, block::gen::t_MessageRelaxed_Any, msg)) {
LOG(DEBUG) << "outbound message does not fit into a cell after rewriting";
return 39;
return redoing < 2 ? -2 : (skip_invalid ? 0 : 39);
}
new_msg_bits = cb.size();
@ -1461,6 +1502,8 @@ int Transaction::try_action_send_msg(vm::CellSlice& cs, ActionPhase& ap, const A
}
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);
return -1;
}
if (verbosity > 2) {

View file

@ -390,7 +390,7 @@ struct Transaction {
Ref<vm::Tuple> prepare_vm_c7(const ComputePhaseConfig& cfg) const;
bool prepare_rand_seed(td::BitArray<256>& rand_seed, const ComputePhaseConfig& cfg) const;
int try_action_set_code(vm::CellSlice& cs, ActionPhase& ap, const ActionPhaseConfig& cfg);
int try_action_send_msg(vm::CellSlice& cs, ActionPhase& ap, const ActionPhaseConfig& cfg);
int try_action_send_msg(const vm::CellSlice& cs, ActionPhase& ap, const ActionPhaseConfig& cfg, int redoing = 0);
int try_action_reserve_currency(vm::CellSlice& cs, ActionPhase& ap, const ActionPhaseConfig& cfg);
bool check_replace_src_addr(Ref<vm::CellSlice>& src_addr) const;
bool check_rewrite_dest_addr(Ref<vm::CellSlice>& dest_addr, const ActionPhaseConfig& cfg,