Skip to content

Commit

Permalink
updated smartcontract code
Browse files Browse the repository at this point in the history
updated lite-client and configuration smartcontract
updated tonlib code
  • Loading branch information
ton committed Sep 16, 2019
1 parent 8e5bd93 commit bce33f5
Show file tree
Hide file tree
Showing 46 changed files with 680 additions and 302 deletions.
55 changes: 53 additions & 2 deletions crypto/block/block.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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)));
}
Expand Down
21 changes: 16 additions & 5 deletions crypto/block/block.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
};
Expand Down Expand Up @@ -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 {
Expand Down
4 changes: 4 additions & 0 deletions crypto/block/block.tlb
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
13 changes: 11 additions & 2 deletions crypto/block/check-proof.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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");
}
Expand Down Expand Up @@ -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");
}
Expand Down Expand Up @@ -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");
Expand All @@ -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());
}
Expand All @@ -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();
}
Expand Down
2 changes: 1 addition & 1 deletion crypto/block/transaction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
7 changes: 6 additions & 1 deletion crypto/block/transaction.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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();
Expand Down
24 changes: 24 additions & 0 deletions crypto/fift/words.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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>

Expand Down Expand Up @@ -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];
Expand Down Expand Up @@ -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({});
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
14 changes: 11 additions & 3 deletions crypto/smartcont/CreateState.fif
Original file line number Diff line number Diff line change
Expand Up @@ -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!
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down
6 changes: 3 additions & 3 deletions crypto/smartcont/gen-zerostate.fif
Original file line number Diff line number Diff line change
Expand Up @@ -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!
Expand Down
2 changes: 1 addition & 1 deletion crypto/smartcont/new-pinger.fif
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/usr/bin/fift -s
#!/usr/bin/env fift -s
"TonUtil.fif" include
"Asm.fif" include

Expand Down
7 changes: 3 additions & 4 deletions crypto/smartcont/new-wallet.fif
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
#!/usr/bin/fift -s
#!/usr/bin/env fift -s
"TonUtil.fif" include
"Asm.fif" include

{ ."usage: " @' $0 type ." <workchain-id> [<filename-base>]" cr
."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
Expand Down
2 changes: 1 addition & 1 deletion crypto/smartcont/recover-stake.fif
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/usr/bin/fift -s
#!/usr/bin/env fift -s
"TonUtil.fif" include

{ ."usage: " @' $0 type ." [<savefile>]" cr
Expand Down
2 changes: 1 addition & 1 deletion crypto/smartcont/show-addr.fif
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/usr/bin/fift -s
#!/usr/bin/env fift -s
"TonUtil.fif" include

{ ."usage: " @' $0 type ." <filename-base>" cr
Expand Down
Loading

0 comments on commit bce33f5

Please sign in to comment.