Skip to content

Commit

Permalink
Extra currencies (ton-blockchain#1122)
Browse files Browse the repository at this point in the history
* Support extra currencies in tonlib, blockchain-explorer, getAccountPrunned

* Fix dict_combine_with with non-zero mode
  • Loading branch information
SpyCheese authored Oct 1, 2024
1 parent 257cd8c commit f94d1be
Show file tree
Hide file tree
Showing 12 changed files with 182 additions and 57 deletions.
23 changes: 19 additions & 4 deletions blockchain-explorer/blockchain-explorer-http.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,9 +122,8 @@ HttpAnswer& HttpAnswer::operator<<(MessageCell msg) {
abort("cannot unpack internal message");
return *this;
}
td::RefInt256 value;
td::Ref<vm::Cell> extra;
if (!block::unpack_CurrencyCollection(info.value, value, extra)) {
block::CurrencyCollection currency_collection;
if (!currency_collection.unpack(info.value)) {
abort("cannot unpack message value");
return *this;
}
Expand All @@ -133,7 +132,7 @@ HttpAnswer& HttpAnswer::operator<<(MessageCell msg) {
<< "<tr><th>destination</th><td>" << AddressCell{info.dest} << "</td></tr>\n"
<< "<tr><th>lt</th><td>" << info.created_lt << "</td></tr>\n"
<< "<tr><th>time</th><td>" << info.created_at << " (" << time_to_human(info.created_at) << ")</td></tr>\n"
<< "<tr><th>value</th><td>" << value << "</td></tr>\n";
<< "<tr><th>value</th><td>" << currency_collection.to_str()<< "</td></tr>\n";
break;
}
default:
Expand Down Expand Up @@ -365,6 +364,7 @@ HttpAnswer& HttpAnswer::operator<<(AccountCell acc_c) {
ton::LogicalTime last_trans_lt = 0;
ton::Bits256 last_trans_hash;
last_trans_hash.set_zero();
block::CurrencyCollection balance = block::CurrencyCollection::zero();
try {
auto state_root = vm::MerkleProof::virtualize(acc_c.q_roots[1], 1);
if (state_root.is_null()) {
Expand Down Expand Up @@ -397,6 +397,20 @@ HttpAnswer& HttpAnswer::operator<<(AccountCell acc_c) {
}
last_trans_hash = acc_info.last_trans_hash;
last_trans_lt = acc_info.last_trans_lt;
block::gen::Account::Record_account acc;
block::gen::AccountStorage::Record storage_rec;
if (!tlb::unpack_cell(acc_c.root, acc)) {
abort("cannot unpack Account");
return *this;
}
if (!tlb::csr_unpack(acc.storage, storage_rec)) {
abort("cannot unpack AccountStorage");
return *this;
}
if (!balance.unpack(storage_rec.balance)) {
abort("cannot unpack account balance");
return *this;
}
} else if (acc_c.root.not_null()) {
abort(PSTRING() << "account state proof shows that account state for " << acc_c.addr.workchain << ":"
<< acc_c.addr.addr.to_hex() << " must be empty, but it is not");
Expand Down Expand Up @@ -434,6 +448,7 @@ HttpAnswer& HttpAnswer::operator<<(AccountCell acc_c) {
*this << "<tr><th>workchain</th><td>" << acc_c.addr.workchain << "</td></tr>";
*this << "<tr><th>account hex</th><td>" << acc_c.addr.addr.to_hex() << "</td></tr>";
*this << "<tr><th>account</th><td>" << acc_c.addr.rserialize(true) << "</td></tr>";
*this << "<tr><th>balance</th><td>" << balance.to_str() << "</td></tr>";
if (last_trans_lt > 0) {
*this << "<tr><th>last transaction</th><td>"
<< "<a href=\"" << TransactionLink{acc_c.addr, last_trans_lt, last_trans_hash} << "\">lt=" << last_trans_lt
Expand Down
6 changes: 4 additions & 2 deletions crypto/smc-envelope/GenericAccount.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ block::StdAddress GenericAccount::get_address(ton::WorkchainId workchain_id,
return block::StdAddress(workchain_id, init_state->get_hash().bits(), true /*bounce*/);
}

void GenericAccount::store_int_message(vm::CellBuilder& cb, const block::StdAddress& dest_address, td::int64 gramms) {
void GenericAccount::store_int_message(vm::CellBuilder& cb, const block::StdAddress& dest_address, td::int64 gramms,
td::Ref<vm::Cell> extra_currencies) {
td::BigInt256 dest_addr;
dest_addr.import_bits(dest_address.addr.as_bitslice());
cb.store_zeroes(1)
Expand All @@ -73,7 +74,8 @@ void GenericAccount::store_int_message(vm::CellBuilder& cb, const block::StdAddr
.store_long(dest_address.workchain, 8)
.store_int256(dest_addr, 256);
block::tlb::t_Grams.store_integer_value(cb, td::BigInt256(gramms));
cb.store_zeroes(9 + 64 + 32);
cb.store_maybe_ref(extra_currencies);
cb.store_zeroes(8 + 64 + 32);
}

td::Ref<vm::Cell> GenericAccount::create_ext_message(const block::StdAddress& address, td::Ref<vm::Cell> new_state,
Expand Down
3 changes: 2 additions & 1 deletion crypto/smc-envelope/GenericAccount.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ class GenericAccount {
static block::StdAddress get_address(ton::WorkchainId workchain_id, const td::Ref<vm::Cell>& init_state) noexcept;
static td::Ref<vm::Cell> create_ext_message(const block::StdAddress& address, td::Ref<vm::Cell> new_state,
td::Ref<vm::Cell> body) noexcept;
static void store_int_message(vm::CellBuilder& cb, const block::StdAddress& dest_address, td::int64 gramms);
static void store_int_message(vm::CellBuilder& cb, const block::StdAddress& dest_address, td::int64 gramms,
td::Ref<vm::Cell> extra_currencies);

static td::Result<td::Ed25519::PublicKey> get_public_key(const SmartContract& sc);
static td::Result<td::uint32> get_seqno(const SmartContract& sc);
Expand Down
2 changes: 1 addition & 1 deletion crypto/smc-envelope/WalletInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ td::Result<td::Ref<vm::Cell>> WalletInterface::get_init_message(const td::Ed2551

td::Ref<vm::Cell> WalletInterface::create_int_message(const Gift &gift) {
vm::CellBuilder cbi;
GenericAccount::store_int_message(cbi, gift.destination, gift.gramms < 0 ? 0 : gift.gramms);
GenericAccount::store_int_message(cbi, gift.destination, gift.gramms < 0 ? 0 : gift.gramms, gift.extra_currencies);
if (gift.init_state.not_null()) {
cbi.store_ones(2);
cbi.store_ref(gift.init_state);
Expand Down
1 change: 1 addition & 0 deletions crypto/smc-envelope/WalletInterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class WalletInterface : public SmartContract {
struct Gift {
block::StdAddress destination;
td::int64 gramms;
td::Ref<vm::Cell> extra_currencies;
td::int32 send_mode{-1};

bool is_encrypted{false};
Expand Down
6 changes: 3 additions & 3 deletions crypto/vm/dict.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1779,7 +1779,7 @@ Ref<Cell> DictionaryFixed::dict_combine_with(Ref<Cell> dict1, Ref<Cell> dict2, t
int mode, int skip1, int skip2) const {
if (dict1.is_null()) {
assert(!skip2);
if ((mode & 1) && dict2.is_null()) {
if ((mode & 1) && dict2.not_null()) {
throw CombineError{};
}
return dict2;
Expand Down Expand Up @@ -1854,11 +1854,11 @@ Ref<Cell> DictionaryFixed::dict_combine_with(Ref<Cell> dict1, Ref<Cell> dict2, t
key_buffer[-1] = 0;
// combine left subtrees
auto c1 = dict_combine_with(label1.remainder->prefetch_ref(0), label2.remainder->prefetch_ref(0), key_buffer,
n - c - 1, total_key_len, combine_func);
n - c - 1, total_key_len, combine_func, mode);
key_buffer[-1] = 1;
// combine right subtrees
auto c2 = dict_combine_with(label1.remainder->prefetch_ref(1), label2.remainder->prefetch_ref(1), key_buffer,
n - c - 1, total_key_len, combine_func);
n - c - 1, total_key_len, combine_func, mode);
label1.remainder.clear();
label2.remainder.clear();
// c1 and c2 are merged left and right children of dict1 and dict2
Expand Down
10 changes: 6 additions & 4 deletions tl/generate/scheme/tonlib_api.tl
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,10 @@ internal.transactionId lt:int64 hash:bytes = internal.TransactionId;
ton.blockId workchain:int32 shard:int64 seqno:int32 = internal.BlockId;
ton.blockIdExt workchain:int32 shard:int64 seqno:int32 root_hash:bytes file_hash:bytes = ton.BlockIdExt;

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;
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;
extraCurrency id:int32 amount:int64 = ExtraCurrency;

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;
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;
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;
raw.transactions transactions:vector<raw.transaction> previous_transaction_id:internal.transactionId = raw.Transactions;

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

fullAccountState address:accountAddress balance:int64 last_transaction_id:internal.transactionId block_id:ton.blockIdExt sync_utime:int53 account_state:AccountState revision:int32 = FullAccountState;
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;

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

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

//
// DNS
Expand Down
Binary file modified tl/generate/scheme/tonlib_api.tlo
Binary file not shown.
5 changes: 3 additions & 2 deletions tonlib/test/online.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,8 @@ td::Result<QueryId> create_send_grams_query(Client& client, const Wallet& source
data = tonlib_api::make_object<tonlib_api::msg_dataRaw>(message.raw.unwrap(), message.init_state.unwrap());
}
msgs.push_back(tonlib_api::make_object<tonlib_api::msg_message>(
tonlib_api::make_object<tonlib_api::accountAddress>(destination), "", amount, std::move(data), -1));
tonlib_api::make_object<tonlib_api::accountAddress>(destination), "", amount,
std::vector<tonlib_api::object_ptr<tonlib_api::extraCurrency>>{}, std::move(data), -1));

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

0 comments on commit f94d1be

Please sign in to comment.