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

TON Storage utilities (#564)

* Rename chunk to piece in MerkleTree for consistency

* Refactor PeerManager

* Make PeerState thread-safe

* Download torrent by hash

* First version of storage daemon

* Download torrents partially

* Improve storing and loading torrent state in DB

* Rewrite MerkleTree

* "Remove torrent" in storage daemon

* Process errors, fix bugs in storage

* Move TonlibClientWrapper from rldp-http-proxy to tonlib

* Initial version of storage provider

* Move interaction with contracts to smc-util

* Improve TonlibClientWrapper interface

* Various improvements in storage provider

* Fix TorrentCreator.cpp

* Improve interface for partial download

* Client mode in storage-daemon

* Improve interface of storage-daemon-cli

* Fix calculating speed, show peers in storage-daemon

* Use permanent adnl id in storage daemon

* Fix sending large "storage.addUpdate" messages

* Improve printing torrents in cli

* Update tlo

* Fix RldpSender::on_ack

* Update storage provider

* Add "address" parameter to get-provider-params

* Allow client to close storage contract

* Limit torrent description

* Add more logs to storage provider

* smc.forget tonlib method

* Use smc.forget in storage daemon

* Optimize sending messages in smc-util.cpp

* Fix verbosity, remove excessive logs

* Json output in storage-daemon-cli

* Update storage provider contracts

* Fix rldp2 acks

* Change verbosity of logs in rldp2

* Update help and output of commands and in storage-daemon-cli

Co-authored-by: SpyCheese <mikle98@yandex.ru>
This commit is contained in:
EmelyanenkoK 2022-12-22 12:24:13 +03:00 committed by GitHub
parent 434dc487a4
commit 360ef54e6b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
75 changed files with 8872 additions and 1148 deletions

View file

@ -0,0 +1 @@
provider-code.h

View file

@ -0,0 +1,23 @@
# Storage Provider
Simple smart-contract system for conclusion of a storage agreements.
- guarantees that the provider stores the file
- no storage - no payment
- no penalties, if provider doesn't store file client can stop payment at any time
- no control that provider upload the file: client can stop payment at any time if not satisfied
## Storage Agreements Fabric
Storage provider deploy storage agreements fabric. Any client may request fabric to deploy storage agreement contract.
Fabric provides get-method `get_storage_params` which returns
- `accept_new_contracts?` - whether provider accepts new contracts
- `rate_per_mb_day` - price in nanoTON per Megabyte per day
- `max_span` - maximal timespan between proving file storage which will be paid
- `minimal_file_size` - minimal file size accepted by provider
- `maximal_file_size` - maximal file size accepted by provider
## Storage agreement
Agreement contract has client account and accept deposits to this account.
It also knows merkle root and allows provider to withdraw money from client account by providing merkle proof of file storage.
Client can stop agreement at any time.

View file

@ -0,0 +1,4 @@
func -SPA -o storage-contract.fif ../../../crypto/smartcont/stdlib.fc storage-contract.fc && \
(echo "\"storage-contract.fif\" include boc>B \"storage-contract-code.boc\" B>file" | fift) && \
func -SPA -o storage-provider.fif ../../../crypto/smartcont/stdlib.fc storage-provider.fc && \
(echo "\"storage-provider.fif\" include boc>B \"storage-provider-code.boc\" B>file" | fift)

View file

@ -0,0 +1,23 @@
const op::offer_storage_contract = 0x107c49ef;
const op::close_contract = 0x79f937ea;
const op::contract_deployed = 0xbf7bd0c1;
const op::storage_contract_confirmed = 0xd4caedcd;
const op::reward_withdrawal = 0xa91baf56;
const op::storage_contract_terminated = 0xb6236d63;
const op::accept_storage_contract = 0x7a361688;
const op::withdraw = 0x46ed2e94;
const op::proof_storage = 0x419d5d4d;
const op::update_pubkey = 0x53f34cd6;
const op::update_storage_params = 0x54cbf19b;
const error::not_enough_money = 1001;
const error::unauthorized = 401;
const error::wrong_proof = 1002;
const error::contract_not_active = 1003;
const error::file_too_small = 1004;
const error::file_too_big = 1005;
const error::no_new_contracts = 1006;
const error::contract_already_active = 1007;
const error::no_microchunk_hash = 1008;
const error::provider_params_changed = 1009;

View file

@ -0,0 +1,40 @@
#include <fstream>
#include <iostream>
#include <vector>
int main(int argc, char** argv) {
if (argc != 3) {
std::cerr << "Usage: generate-provider-code in.boc out.h\n";
return 1;
}
std::ifstream in(argv[1], std::ios_base::ate | std::ios_base::binary);
size_t size = in.tellg();
in.seekg(0, std::ios::beg);
std::vector<char> buf(size);
if (!in.read(buf.data(), size)) {
std::cerr << "Error: cannot read input\n";
return 1;
}
in.close();
std::ofstream out(argv[2]);
out << "// Auto-generated by embed-provider-code\n";
out << "#pragma once\n";
out << "const unsigned char STORAGE_PROVIDER_CODE[" << size << "] = {\n ";
for (size_t i = 0; i < size; ++i) {
if (i != 0) {
out << ",";
if (i % 32 == 31) {
out << "\n ";
}
}
out << (int)(unsigned char)buf[i];
}
out << "\n};\n";
if (!out) {
std::cerr << "Error: cannot write output\n";
return 1;
}
out.close();
return 0;
}

View file

@ -0,0 +1,266 @@
#include "constants.fc";
const CHUNK_SIZE = 64;
const fee::receipt_value = 20000000;
const fee::storage = 10000000;
{-
storage#_ active:Bool
balance:Coins provider:MsgAddress
merkle_hash:uint256 file_size:uint64 next_proof_byte:uint64
rate_per_mb_day:Coins
max_span:uint32 last_proof_time:uint32
^[client:MsgAddress torrent_hash:uint256] = Storage;
-}
(slice, int) begin_parse_special(cell c) asm "x{D739} s,";
int check_proof(int merkle_hash, int byte_to_proof, int file_size, cell file_dict_proof) {
(slice cs, int special) = file_dict_proof.begin_parse_special();
if (~ special) {
return false;
}
if (cs~load_uint(8) != 3) { ;; Merkle proof
return false;
}
if (cs~load_uint(256) != merkle_hash) {
return false;
}
cell file_dict = cs~load_ref();
int key_len = 0;
while ((CHUNK_SIZE << key_len) < file_size) {
key_len += 1;
}
(slice data, int found?) = file_dict.udict_get?(key_len, byte_to_proof / CHUNK_SIZE);
if(found?) {
return true;
}
return false;
}
() add_to_balance(int amount) impure inline_ref {
var ds = get_data().begin_parse();
var (active, balance, residue) = (ds~load_int(1), ds~load_grams(), ds);
balance += amount;
begin_cell()
.store_int(active, 1)
.store_coins(balance)
.store_slice(residue)
.end_cell().set_data();
}
(slice, int) get_client_data(ds) {
ds = ds.preload_ref().begin_parse();
return (ds~load_msg_addr(), ds~load_uint(256));
}
() recv_internal(int msg_value, cell in_msg_full, slice in_msg_body) impure {
slice cs = in_msg_full.begin_parse();
int flags = cs~load_uint(4);
if (flags & 1) { ;; ignore all bounced messages
return ();
}
slice sender_address = cs~load_msg_addr();
if (in_msg_body.slice_empty?()) {
return add_to_balance(msg_value);
}
int op = in_msg_body~load_uint(32);
if (op == 0) {
return add_to_balance(msg_value);
}
int query_id = in_msg_body~load_uint(64);
if(op == op::offer_storage_contract) {
add_to_balance(msg_value - 2 * fee::receipt_value);
var (client, torrent_hash) = get_client_data(get_data().begin_parse());
var msg = begin_cell()
.store_uint(0x18, 6)
.store_slice(client)
.store_coins(fee::receipt_value)
.store_uint(0, 1 + 4 + 4 + 64 + 32 + 1 + 1)
.store_uint(op::contract_deployed, 32)
.store_uint(query_id, 64)
.store_uint(torrent_hash, 256)
.end_cell();
send_raw_message(msg, 0);
}
if (op == op::accept_storage_contract) {
var ds = get_data().begin_parse();
(int active, int balance, slice provider, slice rest) =
(ds~load_int(1), ds~load_coins(), ds~load_msg_addr(), ds);
throw_unless(error::contract_already_active, ~ active);
throw_unless(error::unauthorized, equal_slice_bits(sender_address, provider));
begin_cell()
.store_int(true, 1)
.store_coins(balance)
.store_slice(provider)
.store_slice(rest)
.end_cell().set_data();
var (client, torrent_hash) = get_client_data(rest);
var msg = begin_cell()
.store_uint(0x18, 6)
.store_slice(client)
.store_coins(fee::receipt_value)
.store_uint(0, 1 + 4 + 4 + 64 + 32 + 1 + 1)
.store_uint(op::storage_contract_confirmed, 32)
.store_uint(cur_lt(), 64)
.store_uint(torrent_hash, 256)
.end_cell();
send_raw_message(msg, 0);
}
if (op == op::close_contract) {
var ds = get_data().begin_parse();
(int active, int balance, slice provider, slice rest) =
(ds~load_int(1), ds~load_coins(), ds~load_msg_addr(), ds);
var (client, torrent_hash) = get_client_data(rest);
throw_unless(error::unauthorized, equal_slice_bits(sender_address, provider) | equal_slice_bits(sender_address, client));
var client_msg = begin_cell()
.store_uint(0x18, 6)
.store_slice(client)
.store_coins(balance)
.store_uint(0, 1 + 4 + 4 + 64 + 32 + 1 + 1)
.store_uint(op::storage_contract_terminated, 32)
.store_uint(cur_lt(), 64)
.store_uint(torrent_hash, 256)
.end_cell();
if(~ active) {
return send_raw_message(client_msg, 128 + 32);
}
send_raw_message(client_msg, 64);
var provider_msg = begin_cell()
.store_uint(0x18, 6)
.store_slice(provider)
.store_coins(0)
.store_uint(0, 1 + 4 + 4 + 64 + 32 + 1 + 1)
.store_uint(op::storage_contract_terminated, 32)
.store_uint(cur_lt(), 64)
.store_uint(torrent_hash, 256)
.end_cell();
return send_raw_message(provider_msg, 128 + 32);
}
if (op == op::withdraw) {
var ds = get_data().begin_parse();
(int active, int balance, slice provider) = (ds~load_int(1), ds~load_coins(), ds~load_msg_addr());
throw_unless(error::contract_not_active, active);
throw_unless(error::unauthorized, equal_slice_bits(sender_address, provider));
if(balance > 0) {
raw_reserve(balance + fee::storage, 2);
}
var msg = begin_cell()
.store_uint(0x18, 6)
.store_slice(provider)
.store_coins(fee::receipt_value)
.store_uint(0, 1 + 4 + 4 + 64 + 32 + 1 + 1)
.store_uint(op::reward_withdrawal, 32)
.store_uint(query_id, 64)
.end_cell();
send_raw_message(msg, 128 + 32);
}
if (op == op::proof_storage) {
cell file_dict_proof = in_msg_body~load_ref();
var ds = get_data().begin_parse();
var (active,
balance,
provider,
merkle_hash,
file_size,
next_proof,
rate_per_mb_day,
max_span,
last_proof_time,
client_data) = (ds~load_int(1),
ds~load_coins(),
ds~load_msg_addr(),
ds~load_uint(256),
ds~load_uint(64),
ds~load_uint(64),
ds~load_coins(),
ds~load_uint(32),
ds~load_uint(32),
ds~load_ref());
throw_unless(error::contract_not_active, active);
throw_unless(error::unauthorized, equal_slice_bits(sender_address, provider));
throw_unless(error::wrong_proof, check_proof(merkle_hash, next_proof, file_size, file_dict_proof));
next_proof = rand(file_size);
int actual_span = min(now() - last_proof_time, max_span);
int bounty = muldiv(file_size * rate_per_mb_day, actual_span, 24 * 60 * 60 * 1024 * 1024);
balance = max(0, balance - bounty);
last_proof_time = now();
begin_cell()
.store_int(true, 1)
.store_coins(balance)
.store_slice(provider)
.store_uint(merkle_hash, 256)
.store_uint(file_size, 64)
.store_uint(next_proof, 64)
.store_coins(rate_per_mb_day)
.store_uint(max_span, 32)
.store_uint(last_proof_time, 32)
.store_ref(client_data)
.end_cell().set_data();
;; Send remaining balance back
cell msg = begin_cell()
.store_uint(0x18, 6)
.store_slice(sender_address)
.store_uint(0, 4 + 1 + 4 + 4 + 64 + 32 + 1 + 1)
.end_cell();
send_raw_message(msg, 64 + 2);
}
}
_ get_storage_contract_data() method_id {
var ds = get_data().begin_parse();
var (active,
balance,
provider,
merkle_hash,
file_size,
next_proof,
rate_per_mb_day,
max_span,
last_proof_time,
rest) = (ds~load_int(1),
ds~load_coins(),
ds~load_msg_addr(),
ds~load_uint(256),
ds~load_uint(64),
ds~load_uint(64),
ds~load_coins(),
ds~load_uint(32),
ds~load_uint(32),
ds);
var (client, torrent_hash) = get_client_data(rest);
return (active, balance, provider, merkle_hash, file_size,
next_proof, rate_per_mb_day, max_span, last_proof_time,
client, torrent_hash);
}
_ get_torrent_hash() method_id {
var (active, balance, provider, merkle_hash, file_size,
next_proof, rate_per_mb_day, max_span, last_proof_time,
client, torrent_hash) = get_storage_contract_data();
return torrent_hash;
}
_ is_active() method_id {
return get_data().begin_parse().preload_int(1);
}
;; next_proof, last_proof_time, max_span
_ get_next_proof_info() method_id {
var (active, balance, provider, merkle_hash, file_size,
next_proof, rate_per_mb_day, max_span, last_proof_time,
client, torrent_hash) = get_storage_contract_data();
return (next_proof, last_proof_time, max_span);
}

View file

@ -0,0 +1,421 @@
"Asm.fif" include
// automatically generated from `../../../crypto/smartcont/stdlib.fc` `storage-contract.fc` incl:`constants.fc`
PROGRAM{
DECLPROC check_proof
DECLPROC add_to_balance
DECLPROC get_client_data
DECLPROC recv_internal
86593 DECLMETHOD get_storage_contract_data
71463 DECLMETHOD get_torrent_hash
122058 DECLMETHOD is_active
81490 DECLMETHOD get_next_proof_info
check_proof PROC:<{
// merkle_hash byte_to_proof file_size file_dict_proof
x{D739} s, // merkle_hash byte_to_proof file_size cs special
NOT // merkle_hash byte_to_proof file_size cs _7
IFJMP:<{ // merkle_hash byte_to_proof file_size cs
4 BLKDROP //
FALSE // _8
}> // merkle_hash byte_to_proof file_size cs
8 LDU // merkle_hash byte_to_proof file_size _9 cs
SWAP // merkle_hash byte_to_proof file_size cs _9
3 NEQINT // merkle_hash byte_to_proof file_size cs _13
IFJMP:<{ // merkle_hash byte_to_proof file_size cs
4 BLKDROP //
FALSE // _14
}> // merkle_hash byte_to_proof file_size cs
256 LDU // merkle_hash byte_to_proof file_size _15 cs
s0 s4 XCHG // cs byte_to_proof file_size _15 merkle_hash
NEQ // cs byte_to_proof file_size _18
IFJMP:<{ // cs byte_to_proof file_size
3 BLKDROP //
FALSE // _19
}> // cs byte_to_proof file_size
s0 s2 XCHG // file_size byte_to_proof cs
LDREF // file_size byte_to_proof _44 _43
DROP // file_size byte_to_proof file_dict
0 PUSHINT // file_size byte_to_proof file_dict key_len=0
WHILE:<{
64 PUSHINT // file_size byte_to_proof file_dict key_len _25=64
OVER // file_size byte_to_proof file_dict key_len _25=64 key_len
LSHIFT // file_size byte_to_proof file_dict key_len _26
s4 PUSH // file_size byte_to_proof file_dict key_len _26 file_size
LESS // file_size byte_to_proof file_dict key_len _27
}>DO<{ // file_size byte_to_proof file_dict key_len
INC // file_size byte_to_proof file_dict key_len
}> // file_size byte_to_proof file_dict key_len
s3 POP // key_len byte_to_proof file_dict
SWAP // key_len file_dict byte_to_proof
6 RSHIFT# // key_len file_dict _33
s0 s2 XCHG // _33 file_dict key_len
DICTUGET
NULLSWAPIFNOT // _45 _46
NIP // found?
IFJMP:<{ //
TRUE // _35
}> //
FALSE // _36
}>
add_to_balance PROCREF:<{
// amount
c4 PUSH // amount _2
CTOS // amount ds
1 LDI // amount _7 ds
LDGRAMS // amount active balance residue
s0 s3 XCHG // residue active balance amount
ADD // residue active balance
SWAP
NEWC // residue balance active _13
1 STI // residue balance _15
SWAP // residue _15 balance
STGRAMS // residue _16
SWAP // _16 residue
STSLICER // _17
ENDC // _18
c4 POP
}>
get_client_data PROC:<{
// ds
PLDREF // _1
CTOS // ds
LDMSGADDR // _3 ds
256 LDU // _3 _11 _10
DROP // _3 _5
}>
recv_internal PROC:<{
// msg_value in_msg_full in_msg_body
SWAP // msg_value in_msg_body in_msg_full
CTOS // msg_value in_msg_body cs
4 LDU // msg_value in_msg_body flags cs
SWAP
1 PUSHINT // msg_value in_msg_body cs flags _9=1
AND // msg_value in_msg_body cs _10
IFJMP:<{ // msg_value in_msg_body cs
3 BLKDROP //
}> // msg_value in_msg_body cs
LDMSGADDR // msg_value in_msg_body _421 _420
DROP // msg_value in_msg_body sender_address
OVER // msg_value in_msg_body sender_address in_msg_body
SEMPTY // msg_value in_msg_body sender_address _14
IFJMP:<{ // msg_value in_msg_body sender_address
2DROP // msg_value
add_to_balance INLINECALLDICT
}> // msg_value in_msg_body sender_address
SWAP // msg_value sender_address in_msg_body
32 LDU // msg_value sender_address op in_msg_body
OVER // msg_value sender_address op in_msg_body op
0 EQINT // msg_value sender_address op in_msg_body _21
IFJMP:<{ // msg_value sender_address op in_msg_body
3 BLKDROP // msg_value
add_to_balance INLINECALLDICT
}> // msg_value sender_address op in_msg_body
64 LDU // msg_value sender_address op query_id in_msg_body
s2 PUSH
276580847 PUSHINT // msg_value sender_address op query_id in_msg_body op _27=276580847
EQUAL // msg_value sender_address op query_id in_msg_body _28
IF:<{ // msg_value sender_address op query_id in_msg_body
s0 s4 XCHG
40000000 PUSHINT // in_msg_body sender_address op query_id msg_value _31
SUB // in_msg_body sender_address op query_id _32
add_to_balance INLINECALLDICT
c4 PUSH // in_msg_body sender_address op query_id _36
CTOS // in_msg_body sender_address op query_id _37
get_client_data CALLDICT // in_msg_body sender_address op query_id client torrent_hash
3212562625 PUSHINT // in_msg_body sender_address op query_id client torrent_hash _40=3212562625
0 PUSHINT // in_msg_body sender_address op query_id client torrent_hash _40=3212562625 _41=0
24 PUSHINT // in_msg_body sender_address op query_id client torrent_hash _40=3212562625 _41=0 _42=24
NEWC // in_msg_body sender_address op query_id client torrent_hash _40=3212562625 _41=0 _42=24 _43
6 STU // in_msg_body sender_address op query_id client torrent_hash _40=3212562625 _41=0 _45
s0 s4 XCHG2 // in_msg_body sender_address op query_id _41=0 torrent_hash _40=3212562625 _45 client
STSLICER // in_msg_body sender_address op query_id _41=0 torrent_hash _40=3212562625 _46
20000000 PUSHINT // in_msg_body sender_address op query_id _41=0 torrent_hash _40=3212562625 _46 _47=20000000
STGRAMS // in_msg_body sender_address op query_id _41=0 torrent_hash _40=3212562625 _48
s1 s3 XCHG // in_msg_body sender_address op query_id _40=3212562625 torrent_hash _41=0 _48
107 STU // in_msg_body sender_address op query_id _40=3212562625 torrent_hash _62
s1 s2 XCHG // in_msg_body sender_address op query_id torrent_hash _40=3212562625 _62
32 STU // in_msg_body sender_address op query_id torrent_hash _64
s2 s(-1) PUXC // in_msg_body sender_address op query_id torrent_hash query_id _64
64 STU // in_msg_body sender_address op query_id torrent_hash _66
256 STU // in_msg_body sender_address op query_id _68
ENDC // in_msg_body sender_address op query_id msg
0 PUSHINT // in_msg_body sender_address op query_id msg _70=0
SENDRAWMSG
}>ELSE<{
s4 POP // in_msg_body sender_address op query_id
}>
OVER
2050365064 PUSHINT // in_msg_body sender_address op query_id op _72=2050365064
EQUAL // in_msg_body sender_address op query_id _73
IF:<{ // in_msg_body sender_address op query_id
c4 PUSH // in_msg_body sender_address op query_id _75
CTOS // in_msg_body sender_address op query_id ds
1 LDI // in_msg_body sender_address op query_id _81 ds
LDGRAMS // in_msg_body sender_address op query_id _81 _84 ds
LDMSGADDR // in_msg_body sender_address op query_id active balance provider rest
s0 s3 XCHG // in_msg_body sender_address op query_id rest balance provider active
NOT // in_msg_body sender_address op query_id rest balance provider _89
1007 THROWIFNOT
s5 s0 PUSH2 // in_msg_body sender_address op query_id rest balance provider sender_address provider
SDEQ // in_msg_body sender_address op query_id rest balance provider _92
401 THROWIFNOT
TRUE // in_msg_body sender_address op query_id rest balance provider _94
NEWC // in_msg_body sender_address op query_id rest balance provider _94 _95
1 STI // in_msg_body sender_address op query_id rest balance provider _97
ROT // in_msg_body sender_address op query_id rest provider _97 balance
STGRAMS // in_msg_body sender_address op query_id rest provider _98
SWAP // in_msg_body sender_address op query_id rest _98 provider
STSLICER // in_msg_body sender_address op query_id rest _99
OVER // in_msg_body sender_address op query_id rest _99 rest
STSLICER // in_msg_body sender_address op query_id rest _100
ENDC // in_msg_body sender_address op query_id rest _101
c4 POP
get_client_data CALLDICT // in_msg_body sender_address op query_id client torrent_hash
LTIME // in_msg_body sender_address op query_id client torrent_hash _107
3570068941 PUSHINT // in_msg_body sender_address op query_id client torrent_hash _107 _108=3570068941
0 PUSHINT // in_msg_body sender_address op query_id client torrent_hash _107 _108=3570068941 _109=0
24 PUSHINT // in_msg_body sender_address op query_id client torrent_hash _107 _108=3570068941 _109=0 _110=24
NEWC // in_msg_body sender_address op query_id client torrent_hash _107 _108=3570068941 _109=0 _110=24 _111
6 STU // in_msg_body sender_address op query_id client torrent_hash _107 _108=3570068941 _109=0 _113
s0 s5 XCHG2 // in_msg_body sender_address op query_id _109=0 torrent_hash _107 _108=3570068941 _113 client
STSLICER // in_msg_body sender_address op query_id _109=0 torrent_hash _107 _108=3570068941 _114
20000000 PUSHINT // in_msg_body sender_address op query_id _109=0 torrent_hash _107 _108=3570068941 _114 _115=20000000
STGRAMS // in_msg_body sender_address op query_id _109=0 torrent_hash _107 _108=3570068941 _116
s1 s4 XCHG // in_msg_body sender_address op query_id _108=3570068941 torrent_hash _107 _109=0 _116
107 STU // in_msg_body sender_address op query_id _108=3570068941 torrent_hash _107 _130
s1 s3 XCHG // in_msg_body sender_address op query_id _107 torrent_hash _108=3570068941 _130
32 STU // in_msg_body sender_address op query_id _107 torrent_hash _132
s1 s2 XCHG // in_msg_body sender_address op query_id torrent_hash _107 _132
64 STU // in_msg_body sender_address op query_id torrent_hash _134
256 STU // in_msg_body sender_address op query_id _136
ENDC // in_msg_body sender_address op query_id msg
0 PUSHINT // in_msg_body sender_address op query_id msg _138=0
SENDRAWMSG
}> // in_msg_body sender_address op query_id
OVER
2046375914 PUSHINT // in_msg_body sender_address op query_id op _140=2046375914
EQUAL // in_msg_body sender_address op query_id _141
IFJMP:<{ // in_msg_body sender_address op query_id
s2 s3 XCHG
3 BLKDROP // sender_address
c4 PUSH // sender_address _143
CTOS // sender_address ds
1 LDI // sender_address _149 ds
LDGRAMS // sender_address _149 _152 ds
LDMSGADDR // sender_address active balance provider rest
get_client_data CALLDICT // sender_address active balance provider client torrent_hash
s5 s2 PUSH2 // sender_address active balance provider client torrent_hash sender_address provider
SDEQ // sender_address active balance provider client torrent_hash _160
s6 s2 XCPU // _160 active balance provider client torrent_hash sender_address client
SDEQ // _160 active balance provider client torrent_hash _161
s1 s6 XCHG // torrent_hash active balance provider client _160 _161
OR // torrent_hash active balance provider client _162
401 THROWIFNOT
LTIME // torrent_hash active balance provider client _165
3055775075 PUSHINT // torrent_hash active balance provider client _165 _166=3055775075
0 PUSHINT // torrent_hash active balance provider client _165 _166=3055775075 _167=0
24 PUSHINT // torrent_hash active balance provider client _165 _166=3055775075 _167=0 _168=24
NEWC // torrent_hash active balance provider client _165 _166=3055775075 _167=0 _168=24 _169
6 STU // torrent_hash active balance provider client _165 _166=3055775075 _167=0 _171
s0 s4 XCHG2 // torrent_hash active balance provider _167=0 _165 _166=3055775075 _171 client
STSLICER // torrent_hash active balance provider _167=0 _165 _166=3055775075 _172
s0 s5 XCHG2 // torrent_hash active _166=3055775075 provider _167=0 _165 _172 balance
STGRAMS // torrent_hash active _166=3055775075 provider _167=0 _165 _173
s1 s2 XCHG // torrent_hash active _166=3055775075 provider _165 _167=0 _173
107 STU // torrent_hash active _166=3055775075 provider _165 _187
s1 s3 XCHG // torrent_hash active _165 provider _166=3055775075 _187
32 STU // torrent_hash active _165 provider _189
s1 s2 XCHG // torrent_hash active provider _165 _189
64 STU // torrent_hash active provider _191
s3 s(-1) PUXC // torrent_hash active provider torrent_hash _191
256 STU // torrent_hash active provider _193
ENDC // torrent_hash active provider client_msg
s0 s2 XCHG // torrent_hash client_msg provider active
NOT // torrent_hash client_msg provider _195
IFJMP:<{ // torrent_hash client_msg provider
DROP
NIP // client_msg
160 PUSHINT // client_msg _198
SENDRAWMSG
}> // torrent_hash client_msg provider
SWAP
64 PUSHINT // torrent_hash provider client_msg _200=64
SENDRAWMSG
LTIME // torrent_hash provider _203
3055775075 PUSHINT // torrent_hash provider _203 _204=3055775075
0 PUSHINT // torrent_hash provider _203 _204=3055775075 _205=0
24 PUSHINT // torrent_hash provider _203 _204=3055775075 _205=0 _206=24
NEWC // torrent_hash provider _203 _204=3055775075 _205=0 _206=24 _207
6 STU // torrent_hash provider _203 _204=3055775075 _205=0 _209
s0 s4 XCHG2 // torrent_hash _205=0 _203 _204=3055775075 _209 provider
STSLICER // torrent_hash _205=0 _203 _204=3055775075 _210
s3 PUSH // torrent_hash _205=0 _203 _204=3055775075 _210 _211=0
STGRAMS // torrent_hash _205=0 _203 _204=3055775075 _212
s1 s3 XCHG // torrent_hash _204=3055775075 _203 _205=0 _212
107 STU // torrent_hash _204=3055775075 _203 _226
s1 s2 XCHG // torrent_hash _203 _204=3055775075 _226
32 STU // torrent_hash _203 _228
64 STU // torrent_hash _230
256 STU // _232
ENDC // provider_msg
160 PUSHINT // provider_msg _236
SENDRAWMSG
}> // in_msg_body sender_address op query_id
OVER
1189949076 PUSHINT // in_msg_body sender_address op query_id op _238=1189949076
EQUAL // in_msg_body sender_address op query_id _239
IF:<{ // in_msg_body sender_address op query_id
c4 PUSH // in_msg_body sender_address op query_id _241
CTOS // in_msg_body sender_address op query_id ds
1 LDI // in_msg_body sender_address op query_id _246 ds
LDGRAMS // in_msg_body sender_address op query_id _246 _249 ds
LDMSGADDR // in_msg_body sender_address op query_id _246 _249 _449 _448
DROP // in_msg_body sender_address op query_id active balance provider
s0 s2 XCHG // in_msg_body sender_address op query_id provider balance active
1003 THROWIFNOT
s4 s1 PUSH2 // in_msg_body sender_address op query_id provider balance sender_address provider
SDEQ // in_msg_body sender_address op query_id provider balance _256
401 THROWIFNOT
DUP // in_msg_body sender_address op query_id provider balance balance
0 GTINT // in_msg_body sender_address op query_id provider balance _259
IF:<{ // in_msg_body sender_address op query_id provider balance
10000000 PUSHINT // in_msg_body sender_address op query_id provider balance _260=10000000
ADD // in_msg_body sender_address op query_id provider _261
2 PUSHINT // in_msg_body sender_address op query_id provider _261 _262=2
RAWRESERVE
}>ELSE<{
DROP // in_msg_body sender_address op query_id provider
}>
2837163862 PUSHINT // in_msg_body sender_address op query_id provider _265=2837163862
0 PUSHINT // in_msg_body sender_address op query_id provider _265=2837163862 _266=0
24 PUSHINT // in_msg_body sender_address op query_id provider _265=2837163862 _266=0 _267=24
NEWC // in_msg_body sender_address op query_id provider _265=2837163862 _266=0 _267=24 _268
6 STU // in_msg_body sender_address op query_id provider _265=2837163862 _266=0 _270
s0 s3 XCHG2 // in_msg_body sender_address op query_id _266=0 _265=2837163862 _270 provider
STSLICER // in_msg_body sender_address op query_id _266=0 _265=2837163862 _271
20000000 PUSHINT // in_msg_body sender_address op query_id _266=0 _265=2837163862 _271 _272=20000000
STGRAMS // in_msg_body sender_address op query_id _266=0 _265=2837163862 _273
s1 s2 XCHG // in_msg_body sender_address op query_id _265=2837163862 _266=0 _273
107 STU // in_msg_body sender_address op query_id _265=2837163862 _287
32 STU // in_msg_body sender_address op query_id _289
64 STU // in_msg_body sender_address op _291
ENDC // in_msg_body sender_address op msg
160 PUSHINT // in_msg_body sender_address op msg _295
SENDRAWMSG
}>ELSE<{
DROP // in_msg_body sender_address op
}>
1100832077 PUSHINT // in_msg_body sender_address op _297=1100832077
EQUAL // in_msg_body sender_address _298
IF:<{ // in_msg_body sender_address
SWAP // sender_address in_msg_body
LDREF // sender_address _451 _450
DROP // sender_address file_dict_proof
c4 PUSH // sender_address file_dict_proof _303
CTOS // sender_address file_dict_proof ds
1 LDI // sender_address file_dict_proof _315 ds
LDGRAMS // sender_address file_dict_proof _315 _318 ds
LDMSGADDR // sender_address file_dict_proof _315 _318 _320 ds
256 LDU // sender_address file_dict_proof _315 _318 _320 _322 ds
64 LDU // sender_address file_dict_proof _315 _318 _320 _322 _325 ds
64 LDU // sender_address file_dict_proof _315 _318 _320 _322 _325 _328 ds
LDGRAMS // sender_address file_dict_proof _315 _318 _320 _322 _325 _328 _331 ds
32 LDU // sender_address file_dict_proof _315 _318 _320 _322 _325 _328 _331 _333 ds
32 LDU // sender_address file_dict_proof _315 _318 _320 _322 _325 _328 _331 _333 _336 ds
LDREF // sender_address file_dict_proof _315 _318 _320 _322 _325 _328 _331 _333 _336 _471 _470
DROP // sender_address file_dict_proof active balance provider merkle_hash file_size next_proof rate_per_mb_day max_span last_proof_time client_data
s0 s9 XCHG // sender_address file_dict_proof client_data balance provider merkle_hash file_size next_proof rate_per_mb_day max_span last_proof_time active
1003 THROWIFNOT
s10 s6 PUSH2 // sender_address file_dict_proof client_data balance provider merkle_hash file_size next_proof rate_per_mb_day max_span last_proof_time sender_address provider
SDEQ // sender_address file_dict_proof client_data balance provider merkle_hash file_size next_proof rate_per_mb_day max_span last_proof_time _344
401 THROWIFNOT
s5 s3 s(-1) PUXC2
s5 s10 PUXC // sender_address max_span client_data balance provider merkle_hash file_size last_proof_time rate_per_mb_day merkle_hash next_proof file_size file_dict_proof
check_proof CALLDICT // sender_address max_span client_data balance provider merkle_hash file_size last_proof_time rate_per_mb_day _347
1002 THROWIFNOT
s2 PUSH // sender_address max_span client_data balance provider merkle_hash file_size last_proof_time rate_per_mb_day file_size
RAND // sender_address max_span client_data balance provider merkle_hash file_size last_proof_time rate_per_mb_day next_proof
NOW // sender_address max_span client_data balance provider merkle_hash file_size last_proof_time rate_per_mb_day next_proof _351
s0 s3 XCHG2 // sender_address max_span client_data balance provider merkle_hash file_size next_proof rate_per_mb_day _351 last_proof_time
SUB // sender_address max_span client_data balance provider merkle_hash file_size next_proof rate_per_mb_day _352
s8 PUSH // sender_address max_span client_data balance provider merkle_hash file_size next_proof rate_per_mb_day _352 max_span
MIN // sender_address max_span client_data balance provider merkle_hash file_size next_proof rate_per_mb_day actual_span
s3 s1 PUSH2 // sender_address max_span client_data balance provider merkle_hash file_size next_proof rate_per_mb_day actual_span file_size rate_per_mb_day
MUL // sender_address max_span client_data balance provider merkle_hash file_size next_proof rate_per_mb_day actual_span _355
SWAP
90596966400 PUSHINTX // sender_address max_span client_data balance provider merkle_hash file_size next_proof rate_per_mb_day _355 actual_span _364
MULDIV // sender_address max_span client_data balance provider merkle_hash file_size next_proof rate_per_mb_day bounty
s0 s6 XCHG
0 PUSHINT
s0 s7 XCHG // sender_address max_span client_data _366=0 provider merkle_hash file_size next_proof rate_per_mb_day balance bounty
SUB // sender_address max_span client_data _366=0 provider merkle_hash file_size next_proof rate_per_mb_day _367
s1 s6 XCHG // sender_address max_span client_data rate_per_mb_day provider merkle_hash file_size next_proof _366=0 _367
MAX // sender_address max_span client_data rate_per_mb_day provider merkle_hash file_size next_proof balance
NOW // sender_address max_span client_data rate_per_mb_day provider merkle_hash file_size next_proof balance last_proof_time
TRUE // sender_address max_span client_data rate_per_mb_day provider merkle_hash file_size next_proof balance last_proof_time _370
NEWC // sender_address max_span client_data rate_per_mb_day provider merkle_hash file_size next_proof balance last_proof_time _370 _371
1 STI // sender_address max_span client_data rate_per_mb_day provider merkle_hash file_size next_proof balance last_proof_time _373
ROT // sender_address max_span client_data rate_per_mb_day provider merkle_hash file_size next_proof last_proof_time _373 balance
STGRAMS // sender_address max_span client_data rate_per_mb_day provider merkle_hash file_size next_proof last_proof_time _374
s0 s5 XCHG2 // sender_address max_span client_data rate_per_mb_day last_proof_time merkle_hash file_size next_proof _374 provider
STSLICER // sender_address max_span client_data rate_per_mb_day last_proof_time merkle_hash file_size next_proof _375
s1 s3 XCHG // sender_address max_span client_data rate_per_mb_day last_proof_time next_proof file_size merkle_hash _375
256 STU // sender_address max_span client_data rate_per_mb_day last_proof_time next_proof file_size _377
64 STU // sender_address max_span client_data rate_per_mb_day last_proof_time next_proof _379
64 STU // sender_address max_span client_data rate_per_mb_day last_proof_time _381
ROT // sender_address max_span client_data last_proof_time _381 rate_per_mb_day
STGRAMS // sender_address max_span client_data last_proof_time _382
s1 s3 XCHG // sender_address last_proof_time client_data max_span _382
32 STU // sender_address last_proof_time client_data _384
s1 s2 XCHG // sender_address client_data last_proof_time _384
32 STU // sender_address client_data _386
STREF // sender_address _387
ENDC // sender_address _388
c4 POP
0 PUSHINT // sender_address _391=0
24 PUSHINT // sender_address _391=0 _392=24
NEWC // sender_address _391=0 _392=24 _393
6 STU // sender_address _391=0 _395
ROT // _391=0 _395 sender_address
STSLICER // _391=0 _396
111 STU // _412
ENDC // msg
66 PUSHINT // msg _416
SENDRAWMSG
}>ELSE<{
2DROP //
}>
}>
get_storage_contract_data PROC:<{
//
c4 PUSH // _1
CTOS // ds
1 LDI // _13 ds
LDGRAMS // _13 _16 ds
LDMSGADDR // _13 _16 _18 ds
256 LDU // _13 _16 _18 _20 ds
64 LDU // _13 _16 _18 _20 _23 ds
64 LDU // _13 _16 _18 _20 _23 _26 ds
LDGRAMS // _13 _16 _18 _20 _23 _26 _29 ds
32 LDU // _13 _16 _18 _20 _23 _26 _29 _31 ds
32 LDU // active balance provider merkle_hash file_size next_proof rate_per_mb_day max_span last_proof_time rest
get_client_data CALLDICT // active balance provider merkle_hash file_size next_proof rate_per_mb_day max_span last_proof_time client torrent_hash
}>
get_torrent_hash PROC:<{
//
get_storage_contract_data CALLDICT // _12 _13 _14 _15 _16 _17 _18 _19 _20 _21 _22
10 1 BLKDROP2 // torrent_hash
}>
is_active PROC:<{
//
c4 PUSH // _0
CTOS // _1
1 PLDI // _3
}>
get_next_proof_info PROC:<{
//
get_storage_contract_data CALLDICT // _12 _13 _14 _15 _16 _17 _18 _19 _20 _21 _22
2DROP
s2 POP
5 3 BLKDROP2 // next_proof last_proof_time max_span
}>
}END>c

View file

@ -0,0 +1,227 @@
;; Storage contract fabric
#include "constants.fc";
const min_deploy_amount = 50000000;
cell storage_contract_code() asm """ "storage-contract-code.boc" file>B B>boc PUSHREF """;
slice calculate_address_by_stateinit(cell state_init) {
return begin_cell().store_uint(4, 3)
.store_int(0, 8)
.store_uint(cell_hash(state_init), 256)
.end_cell()
.begin_parse();
}
cell build_storage_contract_stateinit(int merkle_hash, int file_size, int rate_per_mb_day,
int max_span, slice client, int torrent_hash) {
cell data = begin_cell()
.store_int(0, 1) ;; active
.store_coins(0) ;; client balance
.store_slice(my_address())
.store_uint(merkle_hash, 256)
.store_uint(file_size, 64)
.store_uint(0, 64) ;; next_proof
.store_coins(rate_per_mb_day)
.store_uint(max_span, 32)
.store_uint(now(), 32) ;; last_proof_time
.store_ref(begin_cell()
.store_slice(client)
.store_uint(torrent_hash, 256)
.end_cell())
.end_cell();
cell state_init = begin_cell()
.store_uint(0, 2)
.store_maybe_ref(storage_contract_code())
.store_maybe_ref(data)
.store_uint(0, 1) .end_cell();
return state_init;
}
() deploy_storage_contract (slice client, int query_id, int file_size, int merkle_hash, int torrent_hash,
int expected_rate, int expected_max_span) impure {
var ds = get_data().begin_parse();
var (wallet_data,
accept_new_contracts?,
rate_per_mb_day,
max_span,
minimal_file_size,
maximal_file_size) = (ds~load_bits(32 + 32 + 256),
ds~load_int(1),
ds~load_coins(),
ds~load_uint(32),
ds~load_uint(64),
ds~load_uint(64));
throw_unless(error::no_new_contracts, accept_new_contracts?);
throw_unless(error::file_too_small, file_size >= minimal_file_size);
throw_unless(error::file_too_big, file_size <= maximal_file_size);
throw_unless(error::provider_params_changed, expected_rate == rate_per_mb_day);
throw_unless(error::provider_params_changed, expected_max_span == max_span);
cell state_init = build_storage_contract_stateinit(merkle_hash, file_size, rate_per_mb_day,
max_span, client, torrent_hash);
cell msg = begin_cell()
.store_uint(0x18, 6)
.store_slice(calculate_address_by_stateinit(state_init))
.store_coins(0)
.store_uint(4 + 2, 1 + 4 + 4 + 64 + 32 + 1 + 1 + 1)
.store_ref(state_init)
.store_uint(op::offer_storage_contract, 32)
.store_uint(query_id, 64)
.end_cell();
send_raw_message(msg, 64);
}
() recv_internal(int msg_value, cell in_msg_full, slice in_msg_body) impure {
slice cs = in_msg_full.begin_parse();
int flags = cs~load_uint(4);
if ((flags & 1) | in_msg_body.slice_empty?()) { ;; ignore all bounced and empty messages
return ();
}
slice sender_address = cs~load_msg_addr();
int op = in_msg_body~load_uint(32);
if (op == 0) { ;; transfer with text message
return ();
}
int query_id = in_msg_body~load_uint(64);
if(op == op::offer_storage_contract) {
throw_unless(error::not_enough_money, msg_value >= min_deploy_amount);
;; torrent_info piece_size:uint32 file_size:uint64 root_hash:(## 256) header_size:uint64 header_hash:(## 256)
;; microchunk_hash:(Maybe (## 256)) description:Text = TorrentInfo;
;;
;; new_storage_contract#00000001 query_id:uint64 info:(^ TorrentInfo) microchunk_hash:uint256
;; expected_rate:Coins expected_max_span:uint32 = NewStorageContract;
cell torrent_info = in_msg_body~load_ref();
int torrent_hash = cell_hash(torrent_info);
slice info_cs = torrent_info.begin_parse();
info_cs~skip_bits(32);
int file_size = info_cs~load_uint(64);
int merkle_hash = in_msg_body~load_uint(256);
int expected_rate = in_msg_body~load_coins();
int expected_max_span = in_msg_body~load_uint(32);
deploy_storage_contract(sender_address, query_id, file_size, merkle_hash, torrent_hash,
expected_rate, expected_max_span);
return ();
}
if(op == op::storage_contract_terminated) {
return ();
}
if(op == op::update_pubkey) {
if(~ equal_slice_bits(my_address(), sender_address)) {
return ();
}
var ds = get_data().begin_parse();
var (seqno_subwallet,
_,
non_wallet_data) = (ds~load_bits(32 + 32),
ds~load_uint(256),
ds);
int new_pubkey = in_msg_body~load_uint(256);
set_data(begin_cell()
.store_slice(seqno_subwallet)
.store_uint(new_pubkey, 256)
.store_slice(non_wallet_data)
.end_cell());
}
if(op == op::update_storage_params) {
if(~ equal_slice_bits(my_address(), sender_address)) {
return ();
}
var ds = get_data().begin_parse();
var wallet_data = ds~load_bits(32 + 32 + 256);
var(accept_new_contracts?,
rate_per_mb_day,
max_span,
minimal_file_size,
maximal_file_size) = (in_msg_body~load_int(1),
in_msg_body~load_coins(),
in_msg_body~load_uint(32),
in_msg_body~load_uint(64),
in_msg_body~load_uint(64));
set_data(begin_cell()
.store_slice(wallet_data)
.store_int(accept_new_contracts?, 1)
.store_coins(rate_per_mb_day)
.store_uint(max_span, 32)
.store_uint(minimal_file_size, 64)
.store_uint(maximal_file_size, 64)
.end_cell());
}
}
() recv_external(slice in_msg) impure {
var signature = in_msg~load_bits(512);
var cs = in_msg;
var (subwallet_id, valid_until, msg_seqno) = (cs~load_uint(32), cs~load_uint(32), cs~load_uint(32));
throw_if(35, valid_until <= now());
var ds = get_data().begin_parse();
var (stored_seqno,
stored_subwallet,
public_key,
non_wallet_data) = (ds~load_uint(32),
ds~load_uint(32),
ds~load_uint(256),
ds);
throw_unless(33, msg_seqno == stored_seqno);
throw_unless(34, subwallet_id == stored_subwallet);
throw_unless(35, check_signature(slice_hash(in_msg), signature, public_key));
accept_message();
cs~touch();
while (cs.slice_refs()) {
var mode = cs~load_uint(8);
send_raw_message(cs~load_ref(), mode);
}
set_data(begin_cell()
.store_uint(stored_seqno + 1, 32)
.store_uint(stored_subwallet, 32)
.store_uint(public_key, 256)
.store_slice(non_wallet_data)
.end_cell());
}
;; Get methods
int seqno() method_id {
return get_data().begin_parse().preload_uint(32);
}
int get_public_key() method_id {
var cs = get_data().begin_parse();
cs~load_uint(64);
return cs.preload_uint(256);
}
;; seqno, subwallet, key
_ get_wallet_params() method_id {
var ds = get_data().begin_parse();
var (stored_seqno, stored_subwallet, public_key) = (ds~load_uint(32), ds~load_uint(32), ds~load_uint(256));
return (stored_seqno, stored_subwallet, public_key);
}
_ get_storage_params() method_id {
var ds = get_data().begin_parse();
var (wallet_data,
accept_new_contracts?,
rate_per_mb_day,
max_span,
minimal_file_size,
maximal_file_size) = (ds~load_bits(32 + 32 + 256),
ds~load_int(1),
ds~load_coins(),
ds~load_uint(32),
ds~load_uint(64),
ds~load_uint(64));
return (accept_new_contracts?, rate_per_mb_day, max_span, minimal_file_size, maximal_file_size);
}
slice get_storage_contract_address(int merkle_hash, int file_size, slice client, int torrent_hash) method_id {
var (_, rate_per_mb_day, max_span, _, _) = get_storage_params();
cell state_init = build_storage_contract_stateinit(merkle_hash, file_size, rate_per_mb_day, max_span, client, torrent_hash);
return calculate_address_by_stateinit(state_init);
}

View file

@ -0,0 +1,340 @@
"Asm.fif" include
// automatically generated from `../../../crypto/smartcont/stdlib.fc` `storage-provider.fc` incl:`constants.fc`
PROGRAM{
DECLPROC calculate_address_by_stateinit
DECLPROC build_storage_contract_stateinit
DECLPROC deploy_storage_contract
DECLPROC recv_internal
DECLPROC recv_external
85143 DECLMETHOD seqno
78748 DECLMETHOD get_public_key
130271 DECLMETHOD get_wallet_params
104346 DECLMETHOD get_storage_params
119729 DECLMETHOD get_storage_contract_address
calculate_address_by_stateinit PROC:<{
// state_init
HASHCU // _1
0 PUSHINT // _1 _2=0
4 PUSHINT // _1 _2=0 _3=4
NEWC // _1 _2=0 _3=4 _4
3 STU // _1 _2=0 _6
8 STI // _1 _8
256 STU // _10
ENDC // _11
CTOS // _12
}>
build_storage_contract_stateinit PROC:<{
// merkle_hash file_size rate_per_mb_day max_span client torrent_hash
NEWC
ROT // merkle_hash file_size rate_per_mb_day max_span torrent_hash _7 client
STSLICER // merkle_hash file_size rate_per_mb_day max_span torrent_hash _8
256 STU // merkle_hash file_size rate_per_mb_day max_span _10
ENDC // merkle_hash file_size rate_per_mb_day max_span _11
NOW // merkle_hash file_size rate_per_mb_day max_span _11 _12
0 PUSHINT // merkle_hash file_size rate_per_mb_day max_span _11 _12 _13=0
DUP // merkle_hash file_size rate_per_mb_day max_span _11 _12 _13=0 _14=0
NEWC // merkle_hash file_size rate_per_mb_day max_span _11 _12 _13=0 _14=0 _15
1 STI // merkle_hash file_size rate_per_mb_day max_span _11 _12 _13=0 _17
OVER // merkle_hash file_size rate_per_mb_day max_span _11 _12 _13=0 _17 _18=0
STGRAMS // merkle_hash file_size rate_per_mb_day max_span _11 _12 _13=0 _19
MYADDR // merkle_hash file_size rate_per_mb_day max_span _11 _12 _13=0 _19 _20
STSLICER // merkle_hash file_size rate_per_mb_day max_span _11 _12 _13=0 _21
s1 s7 XCHG // _13=0 file_size rate_per_mb_day max_span _11 _12 merkle_hash _21
256 STU // _13=0 file_size rate_per_mb_day max_span _11 _12 _23
s1 s5 XCHG // _13=0 _12 rate_per_mb_day max_span _11 file_size _23
64 STU // _13=0 _12 rate_per_mb_day max_span _11 _25
s1 s5 XCHG // _11 _12 rate_per_mb_day max_span _13=0 _25
64 STU // _11 _12 rate_per_mb_day max_span _27
ROT // _11 _12 max_span _27 rate_per_mb_day
STGRAMS // _11 _12 max_span _28
32 STU // _11 _12 _30
32 STU // _11 _32
STREF // _33
ENDC // data
0 PUSHINT // data _36=0
"storage-contract-code.boc" file>B B>boc PUSHREF // data _36=0 _37
OVER // data _36=0 _37 _38=0
NEWC // data _36=0 _37 _38=0 _39
2 STU // data _36=0 _37 _41
STOPTREF // data _36=0 _42
s1 s2 XCHG // _36=0 data _42
STOPTREF // _36=0 _43
1 STU // _45
ENDC // state_init
}>
deploy_storage_contract PROC:<{
// client query_id file_size merkle_hash torrent_hash expected_rate expected_max_span
c4 PUSH // client query_id file_size merkle_hash torrent_hash expected_rate expected_max_span _8
CTOS // client query_id file_size merkle_hash torrent_hash expected_rate expected_max_span ds
320 PUSHINT // client query_id file_size merkle_hash torrent_hash expected_rate expected_max_span ds _21
LDSLICEX // client query_id file_size merkle_hash torrent_hash expected_rate expected_max_span _91 _90
NIP // client query_id file_size merkle_hash torrent_hash expected_rate expected_max_span ds
1 LDI // client query_id file_size merkle_hash torrent_hash expected_rate expected_max_span _23 ds
LDGRAMS // client query_id file_size merkle_hash torrent_hash expected_rate expected_max_span _23 _26 ds
32 LDU // client query_id file_size merkle_hash torrent_hash expected_rate expected_max_span _23 _26 _28 ds
64 LDU // client query_id file_size merkle_hash torrent_hash expected_rate expected_max_span _23 _26 _28 _31 ds
64 LDU // client query_id file_size merkle_hash torrent_hash expected_rate expected_max_span _23 _26 _28 _31 _101 _100
DROP // client query_id file_size merkle_hash torrent_hash expected_rate expected_max_span accept_new_contracts? rate_per_mb_day max_span minimal_file_size maximal_file_size
s0 s4 XCHG // client query_id file_size merkle_hash torrent_hash expected_rate expected_max_span maximal_file_size rate_per_mb_day max_span minimal_file_size accept_new_contracts?
1006 THROWIFNOT
s8 s(-1) PUXC // client query_id file_size merkle_hash torrent_hash expected_rate expected_max_span maximal_file_size rate_per_mb_day max_span file_size minimal_file_size
GEQ // client query_id file_size merkle_hash torrent_hash expected_rate expected_max_span maximal_file_size rate_per_mb_day max_span _40
1004 THROWIFNOT
s7 s2 PUXC // client query_id file_size merkle_hash torrent_hash expected_rate expected_max_span max_span rate_per_mb_day file_size maximal_file_size
LEQ // client query_id file_size merkle_hash torrent_hash expected_rate expected_max_span max_span rate_per_mb_day _43
1005 THROWIFNOT
s3 s3 XCPU // client query_id file_size merkle_hash torrent_hash rate_per_mb_day expected_max_span max_span expected_rate rate_per_mb_day
EQUAL // client query_id file_size merkle_hash torrent_hash rate_per_mb_day expected_max_span max_span _46
1009 THROWIFNOT
TUCK // client query_id file_size merkle_hash torrent_hash rate_per_mb_day max_span expected_max_span max_span
EQUAL // client query_id file_size merkle_hash torrent_hash rate_per_mb_day max_span _49
1009 THROWIFNOT
2SWAP
s1 s5 XCHG
s1 s6 XCHG // query_id merkle_hash file_size rate_per_mb_day max_span client torrent_hash
build_storage_contract_stateinit CALLDICT // query_id state_init
276580847 PUSHINT // query_id state_init _54=276580847
6 PUSHINT // query_id state_init _54=276580847 _57
24 PUSHINT // query_id state_init _54=276580847 _57 _58=24
NEWC // query_id state_init _54=276580847 _57 _58=24 _59
6 STU // query_id state_init _54=276580847 _57 _61
s3 PUSH // query_id state_init _54=276580847 _57 _61 state_init
calculate_address_by_stateinit CALLDICT // query_id state_init _54=276580847 _57 _61 _62
STSLICER // query_id state_init _54=276580847 _57 _63
0 PUSHINT // query_id state_init _54=276580847 _57 _63 _64=0
STGRAMS // query_id state_init _54=276580847 _57 _65
108 STU // query_id state_init _54=276580847 _81
s1 s2 XCHG // query_id _54=276580847 state_init _81
STREF // query_id _54=276580847 _82
32 STU // query_id _84
64 STU // _86
ENDC // msg
64 PUSHINT // msg _88=64
SENDRAWMSG
}>
recv_internal PROC:<{
SAMEALTSAVE // msg_value in_msg_full in_msg_body
SWAP // msg_value in_msg_body in_msg_full
CTOS // msg_value in_msg_body cs
4 LDU // msg_value in_msg_body flags cs
SWAP
1 PUSHINT // msg_value in_msg_body cs flags _9=1
AND // msg_value in_msg_body cs _10
s2 PUSH // msg_value in_msg_body cs _10 in_msg_body
SEMPTY // msg_value in_msg_body cs _10 _11
OR // msg_value in_msg_body cs _12
IFJMP:<{ // msg_value in_msg_body cs
3 BLKDROP //
}> // msg_value in_msg_body cs
LDMSGADDR // msg_value in_msg_body _141 _140
DROP // msg_value in_msg_body sender_address
SWAP // msg_value sender_address in_msg_body
32 LDU // msg_value sender_address op in_msg_body
OVER // msg_value sender_address op in_msg_body op
0 EQINT // msg_value sender_address op in_msg_body _21
IFJMP:<{ // msg_value sender_address op in_msg_body
4 BLKDROP //
}> // msg_value sender_address op in_msg_body
64 LDU // msg_value sender_address op query_id in_msg_body
s2 PUSH
276580847 PUSHINT // msg_value sender_address op query_id in_msg_body op _26=276580847
EQUAL // msg_value sender_address op query_id in_msg_body _27
IFJMP:<{ // msg_value sender_address op query_id in_msg_body
s2 POP // msg_value sender_address in_msg_body query_id
s0 s3 XCHG
50000000 PUSHINT // query_id sender_address in_msg_body msg_value _29=50000000
GEQ // query_id sender_address in_msg_body _30
1001 THROWIFNOT
LDREF // query_id sender_address torrent_info in_msg_body
OVER // query_id sender_address torrent_info in_msg_body torrent_info
HASHCU // query_id sender_address torrent_info in_msg_body torrent_hash
s0 s2 XCHG // query_id sender_address torrent_hash in_msg_body torrent_info
CTOS // query_id sender_address torrent_hash in_msg_body info_cs
32 PUSHINT // query_id sender_address torrent_hash in_msg_body info_cs _40=32
SDSKIPFIRST // query_id sender_address torrent_hash in_msg_body info_cs
64 LDU // query_id sender_address torrent_hash in_msg_body _149 _148
DROP // query_id sender_address torrent_hash in_msg_body file_size
SWAP // query_id sender_address torrent_hash file_size in_msg_body
256 LDU // query_id sender_address torrent_hash file_size merkle_hash in_msg_body
LDGRAMS // query_id sender_address torrent_hash file_size merkle_hash expected_rate in_msg_body
32 LDU // query_id sender_address torrent_hash file_size merkle_hash expected_rate _155 _154
DROP // query_id sender_address torrent_hash file_size merkle_hash expected_rate expected_max_span
s5 s6 XCHG
s3 s4 XCHG
s2 s3 XCHG // sender_address query_id file_size merkle_hash torrent_hash expected_rate expected_max_span
deploy_storage_contract CALLDICT
}> // msg_value sender_address op query_id in_msg_body
NIP
s3 POP // in_msg_body sender_address op
DUP
3055775075 PUSHINT // in_msg_body sender_address op op _58=3055775075
EQUAL // in_msg_body sender_address op _59
IFJMP:<{ // in_msg_body sender_address op
3 BLKDROP //
}> // in_msg_body sender_address op
DUP
1408453846 PUSHINT // in_msg_body sender_address op op _60=1408453846
EQUAL // in_msg_body sender_address op _61
IF:<{ // in_msg_body sender_address op
MYADDR // in_msg_body sender_address op _62
s2 PUSH // in_msg_body sender_address op _62 sender_address
SDEQ // in_msg_body sender_address op _63
NOT // in_msg_body sender_address op _64
IFJMP:<{ // in_msg_body sender_address op
3 BLKDROP //
RETALT
}> // in_msg_body sender_address op
c4 PUSH // in_msg_body sender_address op _66
CTOS // in_msg_body sender_address op ds
64 LDSLICE // in_msg_body sender_address op _71 ds
256 LDU // in_msg_body sender_address op _71 _159 _158
NIP // in_msg_body sender_address op seqno_subwallet non_wallet_data
s0 s4 XCHG // non_wallet_data sender_address op seqno_subwallet in_msg_body
256 LDU // non_wallet_data sender_address op seqno_subwallet new_pubkey in_msg_body
NEWC // non_wallet_data sender_address op seqno_subwallet new_pubkey in_msg_body _83
s0 s3 XCHG2 // non_wallet_data sender_address op in_msg_body new_pubkey _83 seqno_subwallet
STSLICER // non_wallet_data sender_address op in_msg_body new_pubkey _84
256 STU // non_wallet_data sender_address op in_msg_body _86
s0 s4 XCHG2 // in_msg_body sender_address op _86 non_wallet_data
STSLICER // in_msg_body sender_address op _87
ENDC // in_msg_body sender_address op _88
c4 POP
}> // in_msg_body sender_address op
1422651803 PUSHINT // in_msg_body sender_address op _90=1422651803
EQUAL // in_msg_body sender_address _91
IF:<{ // in_msg_body sender_address
MYADDR // in_msg_body sender_address _92
SWAP // in_msg_body _92 sender_address
SDEQ // in_msg_body _93
NOT // in_msg_body _94
IFJMP:<{ // in_msg_body
DROP //
RETALT
}> // in_msg_body
c4 PUSH // in_msg_body _96
CTOS // in_msg_body ds
320 PUSHINT // in_msg_body ds _104
LDSLICEX // in_msg_body _163 _162
DROP // in_msg_body wallet_data
SWAP // wallet_data in_msg_body
1 LDI // wallet_data _111 in_msg_body
LDGRAMS // wallet_data _111 _114 in_msg_body
32 LDU // wallet_data _111 _114 _116 in_msg_body
64 LDU // wallet_data _111 _114 _116 _119 in_msg_body
64 LDU // wallet_data _111 _114 _116 _119 _173 _172
DROP // wallet_data accept_new_contracts? rate_per_mb_day max_span minimal_file_size maximal_file_size
NEWC // wallet_data accept_new_contracts? rate_per_mb_day max_span minimal_file_size maximal_file_size _125
s0 s6 XCHG2 // maximal_file_size accept_new_contracts? rate_per_mb_day max_span minimal_file_size _125 wallet_data
STSLICER // maximal_file_size accept_new_contracts? rate_per_mb_day max_span minimal_file_size _126
s1 s4 XCHG // maximal_file_size minimal_file_size rate_per_mb_day max_span accept_new_contracts? _126
1 STI // maximal_file_size minimal_file_size rate_per_mb_day max_span _128
ROT // maximal_file_size minimal_file_size max_span _128 rate_per_mb_day
STGRAMS // maximal_file_size minimal_file_size max_span _129
32 STU // maximal_file_size minimal_file_size _131
64 STU // maximal_file_size _133
64 STU // _135
ENDC // _136
c4 POP
}>ELSE<{
2DROP //
}>
}>
recv_external PROC:<{
// in_msg
9 PUSHPOW2 // in_msg _3=512
LDSLICEX // signature in_msg
DUP // signature in_msg cs
32 LDU // signature in_msg _9 cs
32 LDU // signature in_msg _9 _12 cs
32 LDU // signature in_msg subwallet_id valid_until msg_seqno cs
s0 s2 XCHG
NOW // signature in_msg subwallet_id cs msg_seqno valid_until _19
LEQ // signature in_msg subwallet_id cs msg_seqno _20
35 THROWIF
c4 PUSH // signature in_msg subwallet_id cs msg_seqno _23
CTOS // signature in_msg subwallet_id cs msg_seqno ds
32 LDU // signature in_msg subwallet_id cs msg_seqno _29 ds
32 LDU // signature in_msg subwallet_id cs msg_seqno _29 _32 ds
256 LDU // signature in_msg subwallet_id cs msg_seqno stored_seqno stored_subwallet public_key non_wallet_data
s4 s3 XCPU // signature in_msg subwallet_id cs non_wallet_data stored_seqno stored_subwallet public_key msg_seqno stored_seqno
EQUAL // signature in_msg subwallet_id cs non_wallet_data stored_seqno stored_subwallet public_key _39
33 THROWIFNOT
s5 s1 XCPU // signature in_msg public_key cs non_wallet_data stored_seqno stored_subwallet subwallet_id stored_subwallet
EQUAL // signature in_msg public_key cs non_wallet_data stored_seqno stored_subwallet _42
34 THROWIFNOT
s0 s5 XCHG // signature stored_subwallet public_key cs non_wallet_data stored_seqno in_msg
HASHSU // signature stored_subwallet public_key cs non_wallet_data stored_seqno _45
s0 s6 s4 XC2PU // stored_seqno stored_subwallet public_key cs non_wallet_data _45 signature public_key
CHKSIGNU // stored_seqno stored_subwallet public_key cs non_wallet_data _46
35 THROWIFNOT
ACCEPT
SWAP // stored_seqno stored_subwallet public_key non_wallet_data cs
WHILE:<{
DUP // stored_seqno stored_subwallet public_key non_wallet_data cs cs
SREFS // stored_seqno stored_subwallet public_key non_wallet_data cs _51
}>DO<{ // stored_seqno stored_subwallet public_key non_wallet_data cs
8 LDU // stored_seqno stored_subwallet public_key non_wallet_data mode cs
LDREF // stored_seqno stored_subwallet public_key non_wallet_data mode _56 cs
s0 s2 XCHG // stored_seqno stored_subwallet public_key non_wallet_data cs _56 mode
SENDRAWMSG
}> // stored_seqno stored_subwallet public_key non_wallet_data cs
DROP // stored_seqno stored_subwallet public_key non_wallet_data
s0 s3 XCHG // non_wallet_data stored_subwallet public_key stored_seqno
INC // non_wallet_data stored_subwallet public_key _60
NEWC // non_wallet_data stored_subwallet public_key _60 _61
32 STU // non_wallet_data stored_subwallet public_key _63
s1 s2 XCHG // non_wallet_data public_key stored_subwallet _63
32 STU // non_wallet_data public_key _65
256 STU // non_wallet_data _67
SWAP // _67 non_wallet_data
STSLICER // _68
ENDC // _69
c4 POP
}>
seqno PROC:<{
//
c4 PUSH // _0
CTOS // _1
32 PLDU // _3
}>
get_public_key PROC:<{
//
c4 PUSH // _1
CTOS // cs
64 LDU // _9 _8
NIP // cs
256 PLDU // _7
}>
get_wallet_params PROC:<{
//
c4 PUSH // _1
CTOS // ds
32 LDU // _6 ds
32 LDU // _6 _9 ds
256 LDU // _6 _9 _20 _19
DROP // stored_seqno stored_subwallet public_key
}>
get_storage_params PROC:<{
//
c4 PUSH // _1
CTOS // ds
320 PUSHINT // ds _14
LDSLICEX // _31 _30
NIP // ds
1 LDI // _16 ds
LDGRAMS // _16 _19 ds
32 LDU // _16 _19 _21 ds
64 LDU // _16 _19 _21 _24 ds
64 LDU // _16 _19 _21 _24 _41 _40
DROP // accept_new_contracts? rate_per_mb_day max_span minimal_file_size maximal_file_size
}>
get_storage_contract_address PROC:<{
// merkle_hash file_size client torrent_hash
get_storage_params CALLDICT // merkle_hash file_size client torrent_hash _13 _14 _15 _16 _17
2DROP
s2 POP // merkle_hash file_size client torrent_hash max_span rate_per_mb_day
s1 s3 s3 XCHG3 // merkle_hash file_size rate_per_mb_day max_span client torrent_hash
build_storage_contract_stateinit CALLDICT // state_init
calculate_address_by_stateinit CALLDICT // _12
}>
}END>c