Skip to content

Commit f94d1be

Browse files
authored
Extra currencies (#1122)
* Support extra currencies in tonlib, blockchain-explorer, getAccountPrunned * Fix dict_combine_with with non-zero mode
1 parent 257cd8c commit f94d1be

File tree

12 files changed

+182
-57
lines changed

12 files changed

+182
-57
lines changed

blockchain-explorer/blockchain-explorer-http.cpp

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -122,9 +122,8 @@ HttpAnswer& HttpAnswer::operator<<(MessageCell msg) {
122122
abort("cannot unpack internal message");
123123
return *this;
124124
}
125-
td::RefInt256 value;
126-
td::Ref<vm::Cell> extra;
127-
if (!block::unpack_CurrencyCollection(info.value, value, extra)) {
125+
block::CurrencyCollection currency_collection;
126+
if (!currency_collection.unpack(info.value)) {
128127
abort("cannot unpack message value");
129128
return *this;
130129
}
@@ -133,7 +132,7 @@ HttpAnswer& HttpAnswer::operator<<(MessageCell msg) {
133132
<< "<tr><th>destination</th><td>" << AddressCell{info.dest} << "</td></tr>\n"
134133
<< "<tr><th>lt</th><td>" << info.created_lt << "</td></tr>\n"
135134
<< "<tr><th>time</th><td>" << info.created_at << " (" << time_to_human(info.created_at) << ")</td></tr>\n"
136-
<< "<tr><th>value</th><td>" << value << "</td></tr>\n";
135+
<< "<tr><th>value</th><td>" << currency_collection.to_str()<< "</td></tr>\n";
137136
break;
138137
}
139138
default:
@@ -365,6 +364,7 @@ HttpAnswer& HttpAnswer::operator<<(AccountCell acc_c) {
365364
ton::LogicalTime last_trans_lt = 0;
366365
ton::Bits256 last_trans_hash;
367366
last_trans_hash.set_zero();
367+
block::CurrencyCollection balance = block::CurrencyCollection::zero();
368368
try {
369369
auto state_root = vm::MerkleProof::virtualize(acc_c.q_roots[1], 1);
370370
if (state_root.is_null()) {
@@ -397,6 +397,20 @@ HttpAnswer& HttpAnswer::operator<<(AccountCell acc_c) {
397397
}
398398
last_trans_hash = acc_info.last_trans_hash;
399399
last_trans_lt = acc_info.last_trans_lt;
400+
block::gen::Account::Record_account acc;
401+
block::gen::AccountStorage::Record storage_rec;
402+
if (!tlb::unpack_cell(acc_c.root, acc)) {
403+
abort("cannot unpack Account");
404+
return *this;
405+
}
406+
if (!tlb::csr_unpack(acc.storage, storage_rec)) {
407+
abort("cannot unpack AccountStorage");
408+
return *this;
409+
}
410+
if (!balance.unpack(storage_rec.balance)) {
411+
abort("cannot unpack account balance");
412+
return *this;
413+
}
400414
} else if (acc_c.root.not_null()) {
401415
abort(PSTRING() << "account state proof shows that account state for " << acc_c.addr.workchain << ":"
402416
<< acc_c.addr.addr.to_hex() << " must be empty, but it is not");
@@ -434,6 +448,7 @@ HttpAnswer& HttpAnswer::operator<<(AccountCell acc_c) {
434448
*this << "<tr><th>workchain</th><td>" << acc_c.addr.workchain << "</td></tr>";
435449
*this << "<tr><th>account hex</th><td>" << acc_c.addr.addr.to_hex() << "</td></tr>";
436450
*this << "<tr><th>account</th><td>" << acc_c.addr.rserialize(true) << "</td></tr>";
451+
*this << "<tr><th>balance</th><td>" << balance.to_str() << "</td></tr>";
437452
if (last_trans_lt > 0) {
438453
*this << "<tr><th>last transaction</th><td>"
439454
<< "<a href=\"" << TransactionLink{acc_c.addr, last_trans_lt, last_trans_hash} << "\">lt=" << last_trans_lt

crypto/smc-envelope/GenericAccount.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@ block::StdAddress GenericAccount::get_address(ton::WorkchainId workchain_id,
6161
return block::StdAddress(workchain_id, init_state->get_hash().bits(), true /*bounce*/);
6262
}
6363

64-
void GenericAccount::store_int_message(vm::CellBuilder& cb, const block::StdAddress& dest_address, td::int64 gramms) {
64+
void GenericAccount::store_int_message(vm::CellBuilder& cb, const block::StdAddress& dest_address, td::int64 gramms,
65+
td::Ref<vm::Cell> extra_currencies) {
6566
td::BigInt256 dest_addr;
6667
dest_addr.import_bits(dest_address.addr.as_bitslice());
6768
cb.store_zeroes(1)
@@ -73,7 +74,8 @@ void GenericAccount::store_int_message(vm::CellBuilder& cb, const block::StdAddr
7374
.store_long(dest_address.workchain, 8)
7475
.store_int256(dest_addr, 256);
7576
block::tlb::t_Grams.store_integer_value(cb, td::BigInt256(gramms));
76-
cb.store_zeroes(9 + 64 + 32);
77+
cb.store_maybe_ref(extra_currencies);
78+
cb.store_zeroes(8 + 64 + 32);
7779
}
7880

7981
td::Ref<vm::Cell> GenericAccount::create_ext_message(const block::StdAddress& address, td::Ref<vm::Cell> new_state,

crypto/smc-envelope/GenericAccount.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ class GenericAccount {
3636
static block::StdAddress get_address(ton::WorkchainId workchain_id, const td::Ref<vm::Cell>& init_state) noexcept;
3737
static td::Ref<vm::Cell> create_ext_message(const block::StdAddress& address, td::Ref<vm::Cell> new_state,
3838
td::Ref<vm::Cell> body) noexcept;
39-
static void store_int_message(vm::CellBuilder& cb, const block::StdAddress& dest_address, td::int64 gramms);
39+
static void store_int_message(vm::CellBuilder& cb, const block::StdAddress& dest_address, td::int64 gramms,
40+
td::Ref<vm::Cell> extra_currencies);
4041

4142
static td::Result<td::Ed25519::PublicKey> get_public_key(const SmartContract& sc);
4243
static td::Result<td::uint32> get_seqno(const SmartContract& sc);

crypto/smc-envelope/WalletInterface.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ td::Result<td::Ref<vm::Cell>> WalletInterface::get_init_message(const td::Ed2551
4848

4949
td::Ref<vm::Cell> WalletInterface::create_int_message(const Gift &gift) {
5050
vm::CellBuilder cbi;
51-
GenericAccount::store_int_message(cbi, gift.destination, gift.gramms < 0 ? 0 : gift.gramms);
51+
GenericAccount::store_int_message(cbi, gift.destination, gift.gramms < 0 ? 0 : gift.gramms, gift.extra_currencies);
5252
if (gift.init_state.not_null()) {
5353
cbi.store_ones(2);
5454
cbi.store_ref(gift.init_state);

crypto/smc-envelope/WalletInterface.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ class WalletInterface : public SmartContract {
3737
struct Gift {
3838
block::StdAddress destination;
3939
td::int64 gramms;
40+
td::Ref<vm::Cell> extra_currencies;
4041
td::int32 send_mode{-1};
4142

4243
bool is_encrypted{false};

crypto/vm/dict.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1779,7 +1779,7 @@ Ref<Cell> DictionaryFixed::dict_combine_with(Ref<Cell> dict1, Ref<Cell> dict2, t
17791779
int mode, int skip1, int skip2) const {
17801780
if (dict1.is_null()) {
17811781
assert(!skip2);
1782-
if ((mode & 1) && dict2.is_null()) {
1782+
if ((mode & 1) && dict2.not_null()) {
17831783
throw CombineError{};
17841784
}
17851785
return dict2;
@@ -1854,11 +1854,11 @@ Ref<Cell> DictionaryFixed::dict_combine_with(Ref<Cell> dict1, Ref<Cell> dict2, t
18541854
key_buffer[-1] = 0;
18551855
// combine left subtrees
18561856
auto c1 = dict_combine_with(label1.remainder->prefetch_ref(0), label2.remainder->prefetch_ref(0), key_buffer,
1857-
n - c - 1, total_key_len, combine_func);
1857+
n - c - 1, total_key_len, combine_func, mode);
18581858
key_buffer[-1] = 1;
18591859
// combine right subtrees
18601860
auto c2 = dict_combine_with(label1.remainder->prefetch_ref(1), label2.remainder->prefetch_ref(1), key_buffer,
1861-
n - c - 1, total_key_len, combine_func);
1861+
n - c - 1, total_key_len, combine_func, mode);
18621862
label1.remainder.clear();
18631863
label2.remainder.clear();
18641864
// c1 and c2 are merged left and right children of dict1 and dict2

tl/generate/scheme/tonlib_api.tl

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,10 @@ internal.transactionId lt:int64 hash:bytes = internal.TransactionId;
5050
ton.blockId workchain:int32 shard:int64 seqno:int32 = internal.BlockId;
5151
ton.blockIdExt workchain:int32 shard:int64 seqno:int32 root_hash:bytes file_hash:bytes = ton.BlockIdExt;
5252

53-
raw.fullAccountState balance:int64 code:bytes data:bytes last_transaction_id:internal.transactionId block_id:ton.blockIdExt frozen_hash:bytes sync_utime:int53 = raw.FullAccountState;
54-
raw.message source:accountAddress destination:accountAddress value:int64 fwd_fee:int64 ihr_fee:int64 created_lt:int64 body_hash:bytes msg_data:msg.Data = raw.Message;
53+
extraCurrency id:int32 amount:int64 = ExtraCurrency;
54+
55+
raw.fullAccountState balance:int64 extra_currencies:vector<extraCurrency> code:bytes data:bytes last_transaction_id:internal.transactionId block_id:ton.blockIdExt frozen_hash:bytes sync_utime:int53 = raw.FullAccountState;
56+
raw.message source:accountAddress destination:accountAddress value:int64 extra_currencies:vector<extraCurrency> fwd_fee:int64 ihr_fee:int64 created_lt:int64 body_hash:bytes msg_data:msg.Data = raw.Message;
5557
raw.transaction address:accountAddress utime:int53 data:bytes transaction_id:internal.transactionId fee:int64 storage_fee:int64 other_fee:int64 in_msg:raw.message out_msgs:vector<raw.message> = raw.Transaction;
5658
raw.transactions transactions:vector<raw.transaction> previous_transaction_id:internal.transactionId = raw.Transactions;
5759

@@ -87,7 +89,7 @@ pchan.statePayout A:int64 B:int64 = pchan.State;
8789
pchan.accountState config:pchan.config state:pchan.State description:string = AccountState;
8890
uninited.accountState frozen_hash:bytes = AccountState;
8991

90-
fullAccountState address:accountAddress balance:int64 last_transaction_id:internal.transactionId block_id:ton.blockIdExt sync_utime:int53 account_state:AccountState revision:int32 = FullAccountState;
92+
fullAccountState address:accountAddress balance:int64 extra_currencies:vector<extraCurrency> last_transaction_id:internal.transactionId block_id:ton.blockIdExt sync_utime:int53 account_state:AccountState revision:int32 = FullAccountState;
9193

9294
accountRevisionList revisions:vector<fullAccountState> = AccountRevisionList;
9395
accountList accounts:vector<fullAccountState> = AccountList;
@@ -110,7 +112,7 @@ msg.dataDecrypted proof:bytes data:msg.Data = msg.DataDecrypted;
110112
msg.dataEncryptedArray elements:vector<msg.dataEncrypted> = msg.DataEncryptedArray;
111113
msg.dataDecryptedArray elements:vector<msg.dataDecrypted> = msg.DataDecryptedArray;
112114

113-
msg.message destination:accountAddress public_key:string amount:int64 data:msg.Data send_mode:int32 = msg.Message;
115+
msg.message destination:accountAddress public_key:string amount:int64 extra_currencies:vector<extraCurrency> data:msg.Data send_mode:int32 = msg.Message;
114116

115117
//
116118
// DNS

tl/generate/scheme/tonlib_api.tlo

416 Bytes
Binary file not shown.

tonlib/test/online.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,8 @@ td::Result<QueryId> create_send_grams_query(Client& client, const Wallet& source
264264
data = tonlib_api::make_object<tonlib_api::msg_dataRaw>(message.raw.unwrap(), message.init_state.unwrap());
265265
}
266266
msgs.push_back(tonlib_api::make_object<tonlib_api::msg_message>(
267-
tonlib_api::make_object<tonlib_api::accountAddress>(destination), "", amount, std::move(data), -1));
267+
tonlib_api::make_object<tonlib_api::accountAddress>(destination), "", amount,
268+
std::vector<tonlib_api::object_ptr<tonlib_api::extraCurrency>>{}, std::move(data), -1));
268269

269270
auto r_id =
270271
sync_send(client, tonlib_api::make_object<tonlib_api::createQuery>(
@@ -566,7 +567,7 @@ void test_multisig(Client& client, const Wallet& giver_wallet) {
566567
for (int i = 0; i < 2; i++) {
567568
// Just transfer all (some) money back in one query
568569
vm::CellBuilder icb;
569-
ton::GenericAccount::store_int_message(icb, block::StdAddress::parse(giver_wallet.address).move_as_ok(), 1);
570+
ton::GenericAccount::store_int_message(icb, block::StdAddress::parse(giver_wallet.address).move_as_ok(), 1, {});
570571
icb.store_bytes("\0\0\0\0", 4);
571572
vm::CellString::store(icb, "Greatings from multisig", 35 * 8).ensure();
572573
ton::MultisigWallet::QueryBuilder qb(wallet_id, -1 - i, icb.finalize());

0 commit comments

Comments
 (0)