Skip to content

Commit

Permalink
Support wallet-v4 in tonlib (#785)
Browse files Browse the repository at this point in the history
  • Loading branch information
SpyCheese authored Oct 25, 2023
1 parent 7f815fc commit 2bfa624
Show file tree
Hide file tree
Showing 10 changed files with 226 additions and 6 deletions.
2 changes: 2 additions & 0 deletions crypto/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@ set(SMC_ENVELOPE_SOURCE
smc-envelope/SmartContractCode.cpp
smc-envelope/WalletInterface.cpp
smc-envelope/WalletV3.cpp
smc-envelope/WalletV4.cpp

smc-envelope/GenericAccount.h
smc-envelope/HighloadWallet.h
Expand All @@ -246,6 +247,7 @@ set(SMC_ENVELOPE_SOURCE
smc-envelope/SmartContractCode.h
smc-envelope/WalletInterface.h
smc-envelope/WalletV3.h
smc-envelope/WalletV4.h
)

set(ED25519_TEST_SOURCE
Expand Down
2 changes: 1 addition & 1 deletion crypto/smc-envelope/GenericAccount.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ td::Result<td::uint32> GenericAccount::get_wallet_id(const SmartContract& sc) {
return TRY_VM([&]() -> td::Result<td::uint32> {
auto answer = sc.run_get_method("wallet_id");
if (!answer.success) {
return td::Status::Error("seqno get method failed");
return td::Status::Error("wallet_id get method failed");
}
return static_cast<td::uint32>(answer.stack.write().pop_long_range(std::numeric_limits<td::uint32>::max()));
}());
Expand Down
23 changes: 21 additions & 2 deletions crypto/smc-envelope/SmartContractCode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ namespace {
// WALLET_REVISION = 2;
// WALLET2_REVISION = 2;
// WALLET3_REVISION = 2;
// WALLET4_REVISION = 2;
// HIGHLOAD_WALLET_REVISION = 2;
// HIGHLOAD_WALLET2_REVISION = 2;
// DNS_REVISION = 1;
Expand Down Expand Up @@ -92,6 +93,20 @@ const auto& get_map() {
"AAXrc52omhpn5jrhf/AABesePaiaGmPmOuFj8ABDbbYHwR7Z5AOAQm1B1tnkA4BTu1E0IEBQNch0x/"
"0BNEC2zz4J28QAoAg9HtvpTGX+gAwoXC2CZEw4g8AOiGOETGA8/gzIG6SMHCU0NcLH+IB3yGSAaGSW3/iAAzTB9QC+wAAHssfFMsfEsv/yx/"
"0AMntVA==");
with_tvm_code(
"wallet-v4-r2",
"te6cckECFAEAAtQAART/APSkE/S88sgLAQIBIAIDAgFIBAUE+PKDCNcYINMf0x/THwL4I7vyZO1E0NMf0x/T//"
"QE0VFDuvKhUVG68qIF+QFUEGT5EPKj+AAkpMjLH1JAyx9SMMv/"
"UhD0AMntVPgPAdMHIcAAn2xRkyDXSpbTB9QC+wDoMOAhwAHjACHAAuMAAcADkTDjDQOkyMsfEssfy/"
"8QERITAubQAdDTAyFxsJJfBOAi10nBIJJfBOAC0x8hghBwbHVnvSKCEGRzdHK9sJJfBeAD+kAwIPpEAcjKB8v/"
"ydDtRNCBAUDXIfQEMFyBAQj0Cm+hMbOSXwfgBdM/"
"yCWCEHBsdWe6kjgw4w0DghBkc3RyupJfBuMNBgcCASAICQB4AfoA9AQw+CdvIjBQCqEhvvLgUIIQcGx1Z4MesXCAGFAEywUmzxZY+"
"gIZ9ADLaRfLH1Jgyz8gyYBA+wAGAIpQBIEBCPRZMO1E0IEBQNcgyAHPFvQAye1UAXKwjiOCEGRzdHKDHrFwgBhQBcsFUAPPFiP6AhPLassfyz/"
"JgED7AJJfA+ICASAKCwBZvSQrb2omhAgKBrkPoCGEcNQICEekk30pkQzmkD6f+YN4EoAbeBAUiYcVnzGEAgFYDA0AEbjJftRNDXCx+"
"AA9sp37UTQgQFA1yH0BDACyMoHy//J0AGBAQj0Cm+hMYAIBIA4PABmtznaiaEAga5Drhf/AABmvHfaiaEAQa5DrhY/AAG7SB/"
"oA1NQi+QAFyMoHFcv/ydB3dIAYyMsFywIizxZQBfoCFMtrEszMyXP7AMhAFIEBCPRR8qcCAHCBAQjXGPoA0z/"
"IVCBHgQEI9FHyp4IQbm90ZXB0gBjIywXLAlAGzxZQBPoCFMtqEssfyz/Jc/sAAgBsgQEI1xj6ANM/"
"MFIkgQEI9Fnyp4IQZHN0cnB0gBjIywXLAlAFzxZQA/oCE8tqyx8Syz/Jc/sAAAr0AMntVGliJeU=");
return map;
}();
return map;
Expand Down Expand Up @@ -137,9 +152,12 @@ td::Span<int> SmartContractCode::get_revisions(Type type) {
static int res[] = {1};
return res;
}
case Type::WalletV4: {
static int res[] = {2};
return res;
}
}
UNREACHABLE();
return {};
}

td::Result<int> SmartContractCode::validate_revision(Type type, int revision) {
Expand Down Expand Up @@ -179,9 +197,10 @@ td::Ref<vm::Cell> SmartContractCode::get_code(Type type, int ext_revision) {
return "payment-channel";
case Type::RestrictedWallet:
return "restricted-wallet3";
case Type::WalletV4:
return "wallet-v4";
}
UNREACHABLE();
return "";
}(type);
if (revision == -1) {
return load(basename).move_as_ok();
Expand Down
11 changes: 10 additions & 1 deletion crypto/smc-envelope/SmartContractCode.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,16 @@ class SmartContractCode {
public:
static td::Result<td::Ref<vm::Cell>> load(td::Slice name);

enum Type { WalletV3 = 4, HighloadWalletV1, HighloadWalletV2, ManualDns, Multisig, PaymentChannel, RestrictedWallet };
enum Type {
WalletV3 = 4,
HighloadWalletV1,
HighloadWalletV2,
ManualDns,
Multisig,
PaymentChannel,
RestrictedWallet,
WalletV4
};
static td::Span<int> get_revisions(Type type);
static td::Result<int> validate_revision(Type type, int revision);
static td::Ref<vm::Cell> get_code(Type type, int revision = 0);
Expand Down
71 changes: 71 additions & 0 deletions crypto/smc-envelope/WalletV4.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
This file is part of TON Blockchain Library.
TON Blockchain Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
TON Blockchain Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "WalletV4.h"
#include "GenericAccount.h"
#include "SmartContractCode.h"

#include "vm/boc.h"
#include "vm/cells/CellString.h"
#include "td/utils/base64.h"

#include <limits>

namespace ton {
td::Result<td::Ref<vm::Cell>> WalletV4::make_a_gift_message(const td::Ed25519::PrivateKey& private_key,
td::uint32 valid_until, td::Span<Gift> gifts) const {
CHECK(gifts.size() <= get_max_gifts_size());
TRY_RESULT(seqno, get_seqno());
TRY_RESULT(wallet_id, get_wallet_id());
vm::CellBuilder cb;
cb.store_long(wallet_id, 32).store_long(valid_until, 32).store_long(seqno, 32);
cb.store_long(0, 8); // The only difference with wallet-v3

for (auto& gift : gifts) {
td::int32 send_mode = 3;
if (gift.gramms == -1) {
send_mode += 128;
}
if (gift.send_mode > -1) {
send_mode = gift.send_mode;
}
cb.store_long(send_mode, 8).store_ref(create_int_message(gift));
}

auto message_outer = cb.finalize();
auto signature = private_key.sign(message_outer->get_hash().as_slice()).move_as_ok();
return vm::CellBuilder().store_bytes(signature).append_cellslice(vm::load_cell_slice(message_outer)).finalize();
}

td::Ref<vm::Cell> WalletV4::get_init_data(const InitData& init_data) noexcept {
return vm::CellBuilder()
.store_long(init_data.seqno, 32)
.store_long(init_data.wallet_id, 32)
.store_bytes(init_data.public_key)
.store_zeroes(1) // plugins dict
.finalize();
}

td::Result<td::uint32> WalletV4::get_wallet_id() const {
return TRY_VM([&]() -> td::Result<td::uint32> {
auto answer = run_get_method("get_subwallet_id");
if (!answer.success) {
return td::Status::Error("get_subwallet_id get method failed");
}
return static_cast<td::uint32>(answer.stack.write().pop_long_range(std::numeric_limits<td::uint32>::max()));
}());
}
} // namespace ton
46 changes: 46 additions & 0 deletions crypto/smc-envelope/WalletV4.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
This file is part of TON Blockchain Library.
TON Blockchain Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
TON Blockchain Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once

#include "smc-envelope/SmartContract.h"
#include "smc-envelope/WalletInterface.h"
#include "vm/cells.h"
#include "Ed25519.h"
#include "block/block.h"
#include "vm/cells/CellString.h"

namespace ton {

struct WalletV4Traits {
using InitData = WalletInterface::DefaultInitData;

static constexpr unsigned max_message_size = vm::CellString::max_bytes;
static constexpr unsigned max_gifts_size = 4;
static constexpr auto code_type = SmartContractCode::WalletV4;
};

class WalletV4 : public WalletBase<WalletV4, WalletV4Traits> {
public:
explicit WalletV4(State state) : WalletBase(std::move(state)) {
}
td::Result<td::Ref<vm::Cell>> make_a_gift_message(const td::Ed25519::PrivateKey& private_key, td::uint32 valid_until,
td::Span<Gift> gifts) const override;
static td::Ref<vm::Cell> get_init_data(const InitData& init_data) noexcept;

td::Result<td::uint32> get_wallet_id() const override;
};
} // namespace ton
2 changes: 2 additions & 0 deletions crypto/test/test-smartcont.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include "smc-envelope/SmartContract.h"
#include "smc-envelope/SmartContractCode.h"
#include "smc-envelope/WalletV3.h"
#include "smc-envelope/WalletV4.h"
#include "smc-envelope/HighloadWallet.h"
#include "smc-envelope/HighloadWalletV2.h"
#include "smc-envelope/PaymentChannel.h"
Expand Down Expand Up @@ -526,6 +527,7 @@ void do_test_wallet() {

TEST(Tonlib, Wallet) {
do_test_wallet<ton::WalletV3>();
do_test_wallet<ton::WalletV4>();
do_test_wallet<ton::HighloadWallet>();
do_test_wallet<ton::HighloadWalletV2>();
do_test_wallet<ton::RestrictedWallet>();
Expand Down
2 changes: 2 additions & 0 deletions tl/generate/scheme/tonlib_api.tl
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ pchan.config alice_public_key:string alice_address:accountAddress bob_public_key

raw.initialAccountState code:bytes data:bytes = InitialAccountState;
wallet.v3.initialAccountState public_key:string wallet_id:int64 = InitialAccountState;
wallet.v4.initialAccountState public_key:string wallet_id:int64 = InitialAccountState;
wallet.highload.v1.initialAccountState public_key:string wallet_id:int64 = InitialAccountState;
wallet.highload.v2.initialAccountState public_key:string wallet_id:int64 = InitialAccountState;

Expand All @@ -73,6 +74,7 @@ pchan.initialAccountState config:pchan.config = InitialAccountState;

raw.accountState code:bytes data:bytes frozen_hash:bytes = AccountState;
wallet.v3.accountState wallet_id:int64 seqno:int32 = AccountState;
wallet.v4.accountState wallet_id:int64 seqno:int32 = AccountState;
wallet.highload.v1.accountState wallet_id:int64 seqno:int32 = AccountState;
wallet.highload.v2.accountState wallet_id:int64 = AccountState;
dns.accountState wallet_id:int64 = AccountState;
Expand Down
Binary file modified tl/generate/scheme/tonlib_api.tlo
Binary file not shown.
Loading

0 comments on commit 2bfa624

Please sign in to comment.