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

updated smartcontract code

updated lite-client and configuration smartcontract
updated tonlib code
This commit is contained in:
ton 2019-09-16 12:06:04 +04:00
parent 8e5bd938aa
commit bce33f588a
46 changed files with 677 additions and 299 deletions

View file

@ -24,10 +24,61 @@
#include "common/util.h"
#include "td/utils/crypto.h"
#include "td/utils/tl_storers.h"
#include "td/utils/misc.h"
namespace block {
using namespace std::literals::string_literals;
td::Result<PublicKey> PublicKey::from_bytes(td::Slice key) {
if (key.size() != 32) {
return td::Status::Error("Ed25519 public key must be exactly 32 bytes long");
}
PublicKey res;
res.key = key.str();
return res;
}
td::Result<PublicKey> PublicKey::parse(td::Slice key) {
if (key.size() != 48) {
return td::Status::Error("Serialized Ed25519 public key must be exactly 48 characters long");
}
td::uint8 buf[36];
if (!buff_base64_decode(td::MutableSlice(buf, 36), key, true)) {
return td::Status::Error("Public key is not serialized in base64 encoding");
}
td::uint16 hash = static_cast<td::uint16>((static_cast<unsigned>(buf[34]) << 8) + buf[35]);
if (hash != td::crc16(td::Slice(buf, 34))) {
return td::Status::Error("Public key has incorrect crc16 hash");
}
if (buf[0] != 0x3e) {
return td::Status::Error("Not a public key");
}
if (buf[1] != 0xe6) {
return td::Status::Error("Not an ed25519 public key");
}
return from_bytes(td::Slice(buf + 2, 32));
}
std::string PublicKey::serialize(bool base64_url) {
CHECK(key.size() == 32);
std::string buf(36, 0);
td::MutableSlice bytes(buf);
bytes[0] = static_cast<char>(0x3e);
bytes[1] = static_cast<char>(0xe6);
bytes.substr(2).copy_from(key);
auto hash = td::crc16(bytes.substr(0, 34));
bytes[34] = static_cast<char>(hash >> 8);
bytes[35] = static_cast<char>(hash & 255);
std::string res(48, 0);
buff_base64_encode(res, bytes, base64_url);
return res;
}
bool pack_std_smc_addr_to(char result[48], bool base64_url, ton::WorkchainId wc, const ton::StdSmcAddress& addr,
bool bounceable, bool testnet) {
if (wc < -128 || wc >= 128) {
@ -316,14 +367,14 @@ std::unique_ptr<MsgProcessedUptoCollection> MsgProcessedUptoCollection::unpack(t
return v && v->valid ? std::move(v) : std::unique_ptr<MsgProcessedUptoCollection>{};
}
bool MsgProcessedUpto::contains(const MsgProcessedUpto& other) const & {
bool MsgProcessedUpto::contains(const MsgProcessedUpto& other) const& {
return ton::shard_is_ancestor(shard, other.shard) && mc_seqno >= other.mc_seqno &&
(last_inmsg_lt > other.last_inmsg_lt ||
(last_inmsg_lt == other.last_inmsg_lt && !(last_inmsg_hash < other.last_inmsg_hash)));
}
bool MsgProcessedUpto::contains(ton::ShardId other_shard, ton::LogicalTime other_lt, td::ConstBitPtr other_hash,
ton::BlockSeqno other_mc_seqno) const & {
ton::BlockSeqno other_mc_seqno) const& {
return ton::shard_is_ancestor(shard, other_shard) && mc_seqno >= other_mc_seqno &&
(last_inmsg_lt > other_lt || (last_inmsg_lt == other_lt && !(last_inmsg_hash < other_hash)));
}

View file

@ -33,6 +33,16 @@ namespace block {
using td::Ref;
struct PublicKey {
std::string key;
static td::Result<PublicKey> from_bytes(td::Slice key);
static td::Result<PublicKey> parse(td::Slice key);
std::string serialize(bool base64_url = false);
};
struct StdAddress {
ton::WorkchainId workchain{ton::workchainInvalid};
bool bounceable{true}; // addresses must be bounceable by default
@ -149,12 +159,12 @@ struct MsgProcessedUpto {
MsgProcessedUpto(ton::ShardId _shard, ton::BlockSeqno _mcseqno, ton::LogicalTime _lt, td::ConstBitPtr _hash)
: shard(_shard), mc_seqno(_mcseqno), last_inmsg_lt(_lt), last_inmsg_hash(_hash) {
}
bool operator<(const MsgProcessedUpto& other) const & {
bool operator<(const MsgProcessedUpto& other) const& {
return shard < other.shard || (shard == other.shard && mc_seqno < other.mc_seqno);
}
bool contains(const MsgProcessedUpto& other) const &;
bool contains(const MsgProcessedUpto& other) const&;
bool contains(ton::ShardId other_shard, ton::LogicalTime other_lt, td::ConstBitPtr other_hash,
ton::BlockSeqno other_mc_seqno) const &;
ton::BlockSeqno other_mc_seqno) const&;
// NB: this is for checking whether we have already imported an internal message
bool already_processed(const EnqueuedMsgDescr& msg) const;
};
@ -470,13 +480,14 @@ struct BlockProofLink {
bool incomplete() const {
return dest_proof.is_null();
}
td::Status validate() const;
td::Status validate(td::uint32* save_utime = nullptr) const;
};
struct BlockProofChain {
ton::BlockIdExt from, to;
int mode;
bool complete{false}, has_key_block{false}, valid{false};
td::uint32 last_utime{0};
bool complete{false}, has_key_block{false}, has_utime{false}, valid{false};
ton::BlockIdExt key_blkid;
std::vector<BlockProofLink> links;
std::size_t link_count() const {

View file

@ -599,6 +599,10 @@ 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;
gas_prices_ext#de gas_price:uint64 gas_limit:uint64 special_gas_limit:uint64 gas_credit:uint64
block_gas_limit:uint64 freeze_due_limit:uint64 delete_due_limit:uint64
= GasLimitsPrices;
config_mc_gas_prices#_ GasLimitsPrices = ConfigParam 20;
config_gas_prices#_ GasLimitsPrices = ConfigParam 21;

View file

@ -296,7 +296,10 @@ td::Result<TransactionList::Info> TransactionList::validate() const {
return std::move(res);
}
td::Status BlockProofLink::validate() const {
td::Status BlockProofLink::validate(td::uint32* save_utime) const {
if (save_utime) {
*save_utime = 0;
}
if (!(from.is_masterchain_ext() && to.is_masterchain_ext())) {
return td::Status::Error("BlockProofLink must have both source and destination blocks in the masterchain");
}
@ -346,6 +349,9 @@ td::Status BlockProofLink::validate() const {
return td::Status::Error(PSTRING() << "incorrect is_key_block value " << is_key << " for destination block "
<< to.to_str());
}
if (save_utime) {
*save_utime = info.gen_utime;
}
} else if (!is_key) {
// return td::Status::Error("Zerostate destination block "s + to.to_str() + " does not have is_key_block set");
}
@ -414,6 +420,8 @@ td::Status BlockProofLink::validate() const {
td::Status BlockProofChain::validate() {
valid = false;
has_key_block = false;
has_utime = false;
last_utime = 0;
key_blkid.invalidate();
if (!(from.is_masterchain_ext() && to.is_masterchain_ext())) {
return td::Status::Error("BlockProofChain must have both source and destination blocks in the masterchain");
@ -435,7 +443,7 @@ td::Status BlockProofChain::validate() {
<< link.from.to_str() << " but the previous link ends at different block "
<< cur.to_str());
}
auto err = link.validate();
auto err = link.validate(&last_utime);
if (err.is_error()) {
return td::Status::Error(PSTRING() << "link #" << i << " in BlockProofChain is invalid: " << err.to_string());
}
@ -449,6 +457,7 @@ td::Status BlockProofChain::validate() {
return td::Status::Error("last link of BlockProofChain ends at block "s + cur.to_str() +
" different from declared chain destination block " + to.to_str());
}
has_utime = (last_utime > 0);
valid = true;
return td::Status::OK();
}

View file

@ -695,7 +695,7 @@ td::RefInt256 ComputePhaseConfig::compute_gas_price(td::uint64 gas_used) const {
bool Transaction::compute_gas_limits(ComputePhase& cp, const ComputePhaseConfig& cfg) {
// Compute gas limits
if (account.is_special) {
cp.gas_max = cfg.gas_limit; // TODO: introduce special gas limits?
cp.gas_max = cfg.special_gas_limit;
} else {
cp.gas_max = cfg.gas_bought_for(balance.grams);
}

View file

@ -96,6 +96,7 @@ struct StoragePhase {
struct ComputePhaseConfig {
td::uint64 gas_price;
td::uint64 gas_limit;
td::uint64 special_gas_limit;
td::uint64 gas_credit;
static constexpr td::uint64 gas_infty = (1ULL << 63) - 1;
td::RefInt256 gas_price256;
@ -104,7 +105,11 @@ struct ComputePhaseConfig {
Ref<vm::Cell> global_config;
td::BitArray<256> block_rand_seed;
ComputePhaseConfig(td::uint64 _gas_price = 0, td::uint64 _gas_limit = 0, td::uint64 _gas_credit = 0)
: gas_price(_gas_price), gas_limit(_gas_limit), gas_credit(_gas_credit) {
: gas_price(_gas_price), gas_limit(_gas_limit), special_gas_limit(_gas_limit), gas_credit(_gas_credit) {
compute_threshold();
}
ComputePhaseConfig(td::uint64 _gas_price, td::uint64 _gas_limit, td::uint64 _spec_gas_limit, td::uint64 _gas_credit)
: gas_price(_gas_price), gas_limit(_gas_limit), special_gas_limit(_spec_gas_limit), gas_credit(_gas_credit) {
compute_threshold();
}
void compute_threshold();

View file

@ -50,6 +50,7 @@
#include "td/utils/port/Stat.h"
#include "td/utils/Timer.h"
#include "td/utils/tl_helpers.h"
#include "td/utils/crypto.h"
#include <ctime>
@ -704,6 +705,10 @@ void interpret_int_to_bytes(vm::Stack& stack, bool sgnd, bool lsb) {
stack.push_bytes(std::string{(char*)buffer, sz});
}
void interpret_string_to_bytes(vm::Stack& stack) {
stack.push_bytes(stack.pop_string());
}
void interpret_bytes_hash(vm::Stack& stack) {
std::string str = stack.pop_bytes();
unsigned char buffer[32];
@ -1306,6 +1311,21 @@ void interpret_ed25519_chksign(vm::Stack& stack) {
stack.push_bool(res.is_ok());
}
void interpret_crc16(vm::Stack& stack) {
std::string str = stack.pop_bytes();
stack.push_smallint(td::crc16(td::Slice{str}));
}
void interpret_crc32(vm::Stack& stack) {
std::string str = stack.pop_bytes();
stack.push_smallint(td::crc32(td::Slice{str}));
}
void interpret_crc32c(vm::Stack& stack) {
std::string str = stack.pop_bytes();
stack.push_smallint(td::crc32c(td::Slice{str}));
}
// vm dictionaries
void interpret_dict_new(vm::Stack& stack) {
stack.push({});
@ -2427,6 +2447,7 @@ void init_words_common(Dictionary& d) {
d.def_stack_word("B>Li@ ", std::bind(interpret_bytes_fetch_int, _1, 0x11));
d.def_stack_word("B>Lu@+ ", std::bind(interpret_bytes_fetch_int, _1, 0x12));
d.def_stack_word("B>Li@+ ", std::bind(interpret_bytes_fetch_int, _1, 0x13));
d.def_stack_word("$>B ", interpret_string_to_bytes);
d.def_stack_word("Bhash ", interpret_bytes_hash);
// cell manipulation (create, write and modify cells)
d.def_stack_word("<b ", interpret_empty);
@ -2493,6 +2514,9 @@ void init_words_common(Dictionary& d) {
d.def_stack_word("ed25519_sign ", interpret_ed25519_sign);
d.def_stack_word("ed25519_chksign ", interpret_ed25519_chksign);
d.def_stack_word("ed25519_sign_uint ", interpret_ed25519_sign_uint);
d.def_stack_word("crc16 ", interpret_crc16);
d.def_stack_word("crc32 ", interpret_crc32);
d.def_stack_word("crc32c ", interpret_crc32c);
// vm dictionaries
d.def_stack_word("dictnew ", interpret_dict_new);
d.def_stack_word("dict>s ", interpret_dict_to_slice);

View file

@ -96,8 +96,8 @@ dictnew constant special-dict
1 'nop
} ::_ sg~
// gas_price gas_limit gas_credit block_gas_limit freeze_due_limit delete_due_limit -- c
{ 6 0 reverse <b x{dd} s, swap 64 u, swap 64 u, swap 64 u, swap 64 u, swap 64 u, swap 64 u, b>
// gas_price gas_limit spec_limit gas_credit block_gas_limit freeze_due_limit delete_due_limit -- c
{ 7 0 reverse <b x{de} s, { swap 64 u, } 7 times b>
} : make-gas-prices
{ make-gas-prices 20 config! } : config.mc_gas_prices!
{ make-gas-prices 21 config! } : config.gas_prices!
@ -136,7 +136,6 @@ dictnew constant special-dict
{ <b swap dict, b> 7 config! } : config.to_mint!
1000000000 constant Gram
1000000 constant mGram
1000 constant uGram
@ -149,6 +148,7 @@ dictnew constant special-dict
{ mGram swap */r } : mGram*/
{ uGram swap */r } : uGram*/
{ /r } : nGram*/
// GR$.17 is equivalent to 170000000
{ bl word (number) ?dup 0= abort"not a valid Gram amount"
1- { Gram swap */r } { Gram * } cond
@ -157,8 +157,16 @@ dictnew constant special-dict
{ 10 << } : *Ki
{ 20 << } : *Mi
{ 30 << } : *Gi
{ 10 <</r } : */Ki
{ 20 <</r } : */Mi
{ 30 <</r } : */Gi
{ 1000 * } : *K
{ 1000000 * } : *M
{ 1000000000 * } : *G
{ 1000 swap */r } : */K
{ 1000000 swap */r } : */M
{ 1000000000 swap */r } : */G
0 constant recv_internal
-1 constant recv_external

View file

@ -168,9 +168,9 @@ elector_addr config.elector_smc!
1 500 1000 500000 config.storage_prices!
config.special!
// gas_price gas_limit gas_credit block_gas_limit freeze_due_limit delete_due_limit --
1000 sg* 1000000 10000 10000000 GR$0.1 GR$1.0 config.gas_prices!
10000 sg* 1000000 10000 10000000 GR$0.1 GR$1.0 config.mc_gas_prices!
// gas_price gas_limit special_gas_limit gas_credit block_gas_limit freeze_due_limit delete_due_limit --
1000 sg* 1 *M dup 10000 10 *M GR$0.1 GR$1.0 config.gas_prices!
10000 sg* 1 *M 10 *M 10000 10 *M GR$0.1 GR$1.0 config.mc_gas_prices!
// lump_price bit_price cell_price ihr_factor first_frac next_frac
1000000 1000 sg* 100000 sg* 3/2 sg*/ 1/3 sg*/ 1/3 sg*/ config.fwd_prices!
10000000 10000 sg* 1000000 sg* 3/2 sg*/ 1/3 sg*/ 1/3 sg*/ config.mc_fwd_prices!

View file

@ -1,4 +1,4 @@
#!/usr/bin/fift -s
#!/usr/bin/env fift -s
"TonUtil.fif" include
"Asm.fif" include

View file

@ -1,4 +1,4 @@
#!/usr/bin/fift -s
#!/usr/bin/env fift -s
"TonUtil.fif" include
"Asm.fif" include
@ -6,10 +6,9 @@
."Creates a new wallet in specified workchain, with private key saved to or loaded from <filename-base>.pk" cr
."('new-wallet.pk' by default)" cr 1 halt
} : usage
def? $# { @' $# 1- -2 and ' usage if } if
$# 1- -2 and ' usage if
Basechain constant wc // create a wallet in workchain 0 (basechain)
def? $1 { @' $1 parse-workchain-id =: wc } if // set workchain id from command line argument
$1 parse-workchain-id =: wc // set workchain id from command line argument
def? $2 { @' $2 } { "new-wallet" } cond constant file-base
."Creating new wallet in workchain " wc . cr

View file

@ -1,4 +1,4 @@
#!/usr/bin/fift -s
#!/usr/bin/env fift -s
"TonUtil.fif" include
{ ."usage: " @' $0 type ." [<savefile>]" cr

View file

@ -1,4 +1,4 @@
#!/usr/bin/fift -s
#!/usr/bin/env fift -s
"TonUtil.fif" include
{ ."usage: " @' $0 type ." <filename-base>" cr

View file

@ -1,29 +1,21 @@
#!/usr/bin/fift -s
#!/usr/bin/env fift -s
"TonUtil.fif" include
{ ."usage: " @' $0 type ." <dest-addr> <seqno> <amount> [<savefile>]" cr
."Creates a request to TestGiver and saves it into <savefile>.boc" cr
."('testgiver-query.boc' by default)" cr 1 halt
} : usage
def? $# { @' $# 3 - -2 and ' usage if } if
$# 3 - -2 and ' usage if
// "testgiver.addr" load-address
Masterchain 0x8156775b79325e5d62e742d9b96c30b6515a5cd2f1f64c5da4b193c03f070e0d
2constant giver_addr
."Test giver address = " giver_addr 2dup .addr cr 6 .Addr cr
Basechain 0x60c04141c6a7b96d68615e7a91d265ad0f3a9a922e9ae9c901d4fa83f5d3c0d0
2constant dest_addr
false constant bounce
0 constant seqno
GR$6.666 constant amount
def? $3 {
@' $1 bounce parse-load-address =: bounce 2=: dest_addr
@' $2 parse-int =: seqno
@' $3 $>GR =: amount
} if
$1 true parse-load-address =: bounce 2=: dest_addr
$2 parse-int =: seqno
$3 $>GR =: amount
def? $4 { @' $4 } { "testgiver-query" } cond constant savefile
."Requesting " amount .GR ."to account "

View file

@ -1,4 +1,4 @@
#!/usr/bin/fift -s
#!/usr/bin/env fift -s
"TonUtil.fif" include
{ ."usage: " @' $0 type ." <filename-base> <seqno> [<savefile>]" cr

View file

@ -1,4 +1,4 @@
#!/usr/bin/fift -s
#!/usr/bin/env fift -s
"TonUtil.fif" include
{ ."usage: " @' $0 type ." <filename-base> <seqno> <index> <new-value-boc> [<savefile>]" cr

View file

@ -1,4 +1,4 @@
#!/usr/bin/fift -s
#!/usr/bin/env fift -s
"TonUtil.fif" include
{ ."usage: " @' $0 type ." <filename-base> <seqno> [<savefile>]" cr

View file

@ -1,4 +1,4 @@
#!/usr/bin/fift -s
#!/usr/bin/env fift -s
"TonUtil.fif" include
{ ."usage: " @' $0 type ." <wallet-addr> <elect-utime> <max-factor> <adnl-addr> [<savefile>]" cr

View file

@ -1,4 +1,4 @@
#!/usr/bin/fift -s
#!/usr/bin/env fift -s
"TonUtil.fif" include
{ ."usage: " @' $0 type ." <wallet-addr> <elect-utime> <max-factor> <adnl-addr> <validator-pubkey> <validator-signature> [<savefile>]" cr

View file

@ -1,26 +1,20 @@
#!/usr/bin/fift -s
#!/usr/bin/env fift -s
"TonUtil.fif" include
{ ."usage: " @' $0 type ." <filename-base> <dest-addr> <seqno> <amount> [-B <body-boc>] [<savefile>]" cr
."Creates a request to simple wallet created by new-wallet.fif, with private key loaded from file <filename-base>.pk "
."and address from <filename-base>.addr, and saves it into <savefile>.boc ('wallet-query.boc' by default)" cr 1 halt
} : usage
$# dup 4 < swap 5 > or ' usage if
def? $6 { @' $5 "-B" $= { @' $6 =: body-boc-file [forget] $6 def? $7 { @' $7 =: $5 [forget] $7 } { [forget] $5 } cond
@' $# 2- =: $# } if } if
def? $# { @' $# dup 4 < swap 5 > or ' usage if } if
"new-wallet" constant file-base
Basechain 0x13CB612A00A7C092C7DFD2EA45D603A9B54591BA4C88F71E707E009B879F0FB2 2constant dest_addr
0 constant seqno
GR$.666 constant amount
true constant bounce
def? $4 {
@' $1 =: file-base
@' $2 bounce parse-load-address =: bounce 2=: dest_addr
@' $3 parse-int =: seqno
@' $4 $>GR =: amount
} if
$1 =: file-base
$2 bounce parse-load-address =: bounce 2=: dest_addr
$3 parse-int =: seqno
$4 $>GR =: amount
def? $5 { @' $5 } { "wallet-query" } cond constant savefile
file-base +".addr" load-address