mirror of
https://github.com/ton-blockchain/ton
synced 2025-02-13 03:32:22 +00:00
vm bugfixes
This commit is contained in:
parent
e27fb1e09c
commit
dd4ac0f440
9 changed files with 107 additions and 30 deletions
|
@ -500,8 +500,8 @@ bool HashmapE::add_values(vm::CellBuilder& cb, vm::CellSlice& cs1, vm::CellSlice
|
||||||
int n = root_type.n;
|
int n = root_type.n;
|
||||||
vm::Dictionary dict1{vm::DictAdvance(), cs1, n}, dict2{vm::DictAdvance(), cs2, n};
|
vm::Dictionary dict1{vm::DictAdvance(), cs1, n}, dict2{vm::DictAdvance(), cs2, n};
|
||||||
const TLB& vt = root_type.value_type;
|
const TLB& vt = root_type.value_type;
|
||||||
vm::Dictionary::simple_combine_func_t combine = [vt](vm::CellBuilder& cb, Ref<vm::CellSlice> cs1_ref,
|
vm::Dictionary::simple_combine_func_t combine = [&vt](vm::CellBuilder& cb, Ref<vm::CellSlice> cs1_ref,
|
||||||
Ref<vm::CellSlice> cs2_ref) -> bool {
|
Ref<vm::CellSlice> cs2_ref) -> bool {
|
||||||
if (!vt.add_values(cb, cs1_ref.write(), cs2_ref.write())) {
|
if (!vt.add_values(cb, cs1_ref.write(), cs2_ref.write())) {
|
||||||
throw CombineError{};
|
throw CombineError{};
|
||||||
}
|
}
|
||||||
|
@ -514,8 +514,8 @@ bool HashmapE::add_values_ref(Ref<vm::Cell>& res, Ref<vm::Cell> arg1, Ref<vm::Ce
|
||||||
int n = root_type.n;
|
int n = root_type.n;
|
||||||
vm::Dictionary dict1{std::move(arg1), n}, dict2{std::move(arg2), n};
|
vm::Dictionary dict1{std::move(arg1), n}, dict2{std::move(arg2), n};
|
||||||
const TLB& vt = root_type.value_type;
|
const TLB& vt = root_type.value_type;
|
||||||
vm::Dictionary::simple_combine_func_t combine = [vt](vm::CellBuilder& cb, Ref<vm::CellSlice> cs1_ref,
|
vm::Dictionary::simple_combine_func_t combine = [&vt](vm::CellBuilder& cb, Ref<vm::CellSlice> cs1_ref,
|
||||||
Ref<vm::CellSlice> cs2_ref) -> bool {
|
Ref<vm::CellSlice> cs2_ref) -> bool {
|
||||||
if (!vt.add_values(cb, cs1_ref.write(), cs2_ref.write())) {
|
if (!vt.add_values(cb, cs1_ref.write(), cs2_ref.write())) {
|
||||||
throw CombineError{};
|
throw CombineError{};
|
||||||
}
|
}
|
||||||
|
@ -535,8 +535,8 @@ int HashmapE::sub_values(vm::CellBuilder& cb, vm::CellSlice& cs1, vm::CellSlice&
|
||||||
int n = root_type.n;
|
int n = root_type.n;
|
||||||
vm::Dictionary dict1{vm::DictAdvance(), cs1, n}, dict2{vm::DictAdvance(), cs2, n};
|
vm::Dictionary dict1{vm::DictAdvance(), cs1, n}, dict2{vm::DictAdvance(), cs2, n};
|
||||||
const TLB& vt = root_type.value_type;
|
const TLB& vt = root_type.value_type;
|
||||||
vm::Dictionary::simple_combine_func_t combine = [vt](vm::CellBuilder& cb, Ref<vm::CellSlice> cs1_ref,
|
vm::Dictionary::simple_combine_func_t combine = [&vt](vm::CellBuilder& cb, Ref<vm::CellSlice> cs1_ref,
|
||||||
Ref<vm::CellSlice> cs2_ref) -> bool {
|
Ref<vm::CellSlice> cs2_ref) -> bool {
|
||||||
int r = vt.sub_values(cb, cs1_ref.write(), cs2_ref.write());
|
int r = vt.sub_values(cb, cs1_ref.write(), cs2_ref.write());
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
throw CombineError{};
|
throw CombineError{};
|
||||||
|
@ -555,8 +555,8 @@ int HashmapE::sub_values_ref(Ref<vm::Cell>& res, Ref<vm::Cell> arg1, Ref<vm::Cel
|
||||||
int n = root_type.n;
|
int n = root_type.n;
|
||||||
vm::Dictionary dict1{std::move(arg1), n}, dict2{std::move(arg2), n};
|
vm::Dictionary dict1{std::move(arg1), n}, dict2{std::move(arg2), n};
|
||||||
const TLB& vt = root_type.value_type;
|
const TLB& vt = root_type.value_type;
|
||||||
vm::Dictionary::simple_combine_func_t combine = [vt](vm::CellBuilder& cb, Ref<vm::CellSlice> cs1_ref,
|
vm::Dictionary::simple_combine_func_t combine = [&vt](vm::CellBuilder& cb, Ref<vm::CellSlice> cs1_ref,
|
||||||
Ref<vm::CellSlice> cs2_ref) -> bool {
|
Ref<vm::CellSlice> cs2_ref) -> bool {
|
||||||
int r = vt.sub_values(cb, cs1_ref.write(), cs2_ref.write());
|
int r = vt.sub_values(cb, cs1_ref.write(), cs2_ref.write());
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
throw CombineError{};
|
throw CombineError{};
|
||||||
|
|
|
@ -68,6 +68,9 @@ struct VarUInteger final : TLB_Complex {
|
||||||
bool store_integer_value(vm::CellBuilder& cb, const td::BigInt256& value) const override;
|
bool store_integer_value(vm::CellBuilder& cb, const td::BigInt256& value) const override;
|
||||||
unsigned precompute_integer_size(const td::BigInt256& value) const;
|
unsigned precompute_integer_size(const td::BigInt256& value) const;
|
||||||
unsigned precompute_integer_size(td::RefInt256 value) const;
|
unsigned precompute_integer_size(td::RefInt256 value) const;
|
||||||
|
std::ostream& print_type(std::ostream& os) const override {
|
||||||
|
return os << "(VarUInteger " << n << ")";
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
extern const VarUInteger t_VarUInteger_3, t_VarUInteger_7, t_VarUInteger_16, t_VarUInteger_32;
|
extern const VarUInteger t_VarUInteger_3, t_VarUInteger_7, t_VarUInteger_16, t_VarUInteger_32;
|
||||||
|
@ -82,6 +85,9 @@ struct VarUIntegerPos final : TLB_Complex {
|
||||||
td::RefInt256 as_integer_skip(vm::CellSlice& cs) const override;
|
td::RefInt256 as_integer_skip(vm::CellSlice& cs) const override;
|
||||||
unsigned long long as_uint(const vm::CellSlice& cs) const override;
|
unsigned long long as_uint(const vm::CellSlice& cs) const override;
|
||||||
bool store_integer_value(vm::CellBuilder& cb, const td::BigInt256& value) const override;
|
bool store_integer_value(vm::CellBuilder& cb, const td::BigInt256& value) const override;
|
||||||
|
std::ostream& print_type(std::ostream& os) const override {
|
||||||
|
return os << "(VarUIntegerPos " << n << ")";
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
extern const VarUIntegerPos t_VarUIntegerPos_16, t_VarUIntegerPos_32;
|
extern const VarUIntegerPos t_VarUIntegerPos_16, t_VarUIntegerPos_32;
|
||||||
|
@ -99,6 +105,9 @@ struct VarInteger final : TLB_Complex {
|
||||||
return cb.store_zeroes_bool(ln);
|
return cb.store_zeroes_bool(ln);
|
||||||
}
|
}
|
||||||
bool store_integer_value(vm::CellBuilder& cb, const td::BigInt256& value) const override;
|
bool store_integer_value(vm::CellBuilder& cb, const td::BigInt256& value) const override;
|
||||||
|
std::ostream& print_type(std::ostream& os) const override {
|
||||||
|
return os << "(VarInteger " << n << ")";
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct VarIntegerNz final : TLB_Complex {
|
struct VarIntegerNz final : TLB_Complex {
|
||||||
|
@ -111,6 +120,9 @@ struct VarIntegerNz final : TLB_Complex {
|
||||||
td::RefInt256 as_integer_skip(vm::CellSlice& cs) const override;
|
td::RefInt256 as_integer_skip(vm::CellSlice& cs) const override;
|
||||||
long long as_int(const vm::CellSlice& cs) const override;
|
long long as_int(const vm::CellSlice& cs) const override;
|
||||||
bool store_integer_value(vm::CellBuilder& cb, const td::BigInt256& value) const override;
|
bool store_integer_value(vm::CellBuilder& cb, const td::BigInt256& value) const override;
|
||||||
|
std::ostream& print_type(std::ostream& os) const override {
|
||||||
|
return os << "(VarIntegerNz " << n << ")";
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Unary final : TLB {
|
struct Unary final : TLB {
|
||||||
|
@ -312,8 +324,8 @@ struct MsgAddress final : TLB_Complex {
|
||||||
extern const MsgAddress t_MsgAddress;
|
extern const MsgAddress t_MsgAddress;
|
||||||
|
|
||||||
struct ExtraCurrencyCollection final : TLB {
|
struct ExtraCurrencyCollection final : TLB {
|
||||||
HashmapE dict_type;
|
HashmapE dict_type, dict_type2;
|
||||||
ExtraCurrencyCollection() : dict_type(32, t_VarUIntegerPos_32) {
|
ExtraCurrencyCollection() : dict_type(32, t_VarUIntegerPos_32), dict_type2(32, t_VarUInteger_32) {
|
||||||
}
|
}
|
||||||
int get_size(const vm::CellSlice& cs) const override {
|
int get_size(const vm::CellSlice& cs) const override {
|
||||||
return dict_type.get_size(cs);
|
return dict_type.get_size(cs);
|
||||||
|
@ -328,13 +340,13 @@ struct ExtraCurrencyCollection final : TLB {
|
||||||
return dict_type.add_values(cb, cs1, cs2);
|
return dict_type.add_values(cb, cs1, cs2);
|
||||||
}
|
}
|
||||||
int sub_values(vm::CellBuilder& cb, vm::CellSlice& cs1, vm::CellSlice& cs2) const override {
|
int sub_values(vm::CellBuilder& cb, vm::CellSlice& cs1, vm::CellSlice& cs2) const override {
|
||||||
return dict_type.sub_values(cb, cs1, cs2);
|
return dict_type2.sub_values(cb, cs1, cs2);
|
||||||
}
|
}
|
||||||
bool add_values_ref(Ref<vm::Cell>& res, Ref<vm::Cell> arg1, Ref<vm::Cell> arg2) const {
|
bool add_values_ref(Ref<vm::Cell>& res, Ref<vm::Cell> arg1, Ref<vm::Cell> arg2) const {
|
||||||
return dict_type.add_values_ref(res, std::move(arg1), std::move(arg2));
|
return dict_type.add_values_ref(res, std::move(arg1), std::move(arg2));
|
||||||
}
|
}
|
||||||
int sub_values_ref(Ref<vm::Cell>& res, Ref<vm::Cell> arg1, Ref<vm::Cell> arg2) const {
|
int sub_values_ref(Ref<vm::Cell>& res, Ref<vm::Cell> arg1, Ref<vm::Cell> arg2) const {
|
||||||
return dict_type.sub_values_ref(res, std::move(arg1), std::move(arg2));
|
return dict_type2.sub_values_ref(res, std::move(arg1), std::move(arg2));
|
||||||
}
|
}
|
||||||
bool store_ref(vm::CellBuilder& cb, Ref<vm::Cell> arg) const {
|
bool store_ref(vm::CellBuilder& cb, Ref<vm::Cell> arg) const {
|
||||||
return dict_type.store_ref(cb, std::move(arg));
|
return dict_type.store_ref(cb, std::move(arg));
|
||||||
|
|
|
@ -1651,7 +1651,7 @@ bool sub_extra_currency(Ref<vm::Cell> extra1, Ref<vm::Cell> extra2, Ref<vm::Cell
|
||||||
res.clear();
|
res.clear();
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
return block::tlb::t_ExtraCurrencyCollection.sub_values_ref(res, std::move(extra1), std::move(extra2));
|
return block::tlb::t_ExtraCurrencyCollection.sub_values_ref(res, std::move(extra1), std::move(extra2)) >= 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -616,6 +616,24 @@ void interpret_is_workchain_descr(vm::Stack& stack) {
|
||||||
stack.push_bool(block::gen::t_WorkchainDescr.validate_ref(std::move(cell)));
|
stack.push_bool(block::gen::t_WorkchainDescr.validate_ref(std::move(cell)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void interpret_add_extra_currencies(vm::Stack& stack) {
|
||||||
|
Ref<vm::Cell> y = stack.pop_maybe_cell(), x = stack.pop_maybe_cell(), res;
|
||||||
|
bool ok = block::add_extra_currency(std::move(x), std::move(y), res);
|
||||||
|
if (ok) {
|
||||||
|
stack.push_maybe_cell(std::move(res));
|
||||||
|
}
|
||||||
|
stack.push_bool(ok);
|
||||||
|
}
|
||||||
|
|
||||||
|
void interpret_sub_extra_currencies(vm::Stack& stack) {
|
||||||
|
Ref<vm::Cell> y = stack.pop_maybe_cell(), x = stack.pop_maybe_cell(), res;
|
||||||
|
bool ok = block::sub_extra_currency(std::move(x), std::move(y), res);
|
||||||
|
if (ok) {
|
||||||
|
stack.push_maybe_cell(std::move(res));
|
||||||
|
}
|
||||||
|
stack.push_bool(ok);
|
||||||
|
}
|
||||||
|
|
||||||
void init_words_custom(fift::Dictionary& d) {
|
void init_words_custom(fift::Dictionary& d) {
|
||||||
d.def_stack_word("verb@ ", interpret_get_verbosity);
|
d.def_stack_word("verb@ ", interpret_get_verbosity);
|
||||||
d.def_stack_word("verb! ", interpret_set_verbosity);
|
d.def_stack_word("verb! ", interpret_set_verbosity);
|
||||||
|
@ -631,6 +649,8 @@ void init_words_custom(fift::Dictionary& d) {
|
||||||
d.def_stack_word("create_state ", interpret_create_state);
|
d.def_stack_word("create_state ", interpret_create_state);
|
||||||
d.def_stack_word("isShardState? ", interpret_is_shard_state);
|
d.def_stack_word("isShardState? ", interpret_is_shard_state);
|
||||||
d.def_stack_word("isWorkchainDescr? ", interpret_is_workchain_descr);
|
d.def_stack_word("isWorkchainDescr? ", interpret_is_workchain_descr);
|
||||||
|
d.def_stack_word("CC+? ", interpret_add_extra_currencies);
|
||||||
|
d.def_stack_word("CC-? ", interpret_sub_extra_currencies);
|
||||||
}
|
}
|
||||||
|
|
||||||
tlb::TypenameLookup tlb_dict;
|
tlb::TypenameLookup tlb_dict;
|
||||||
|
|
|
@ -1555,9 +1555,17 @@ int Transaction::try_action_send_msg(const vm::CellSlice& cs0, ActionPhase& ap,
|
||||||
Ref<vm::Cell> new_extra;
|
Ref<vm::Cell> new_extra;
|
||||||
|
|
||||||
if (!block::sub_extra_currency(ap.remaining_balance.extra, req.extra, new_extra)) {
|
if (!block::sub_extra_currency(ap.remaining_balance.extra, req.extra, new_extra)) {
|
||||||
LOG(DEBUG) << "not enough extra currency to send with the message";
|
LOG(DEBUG) << "not enough extra currency to send with the message: "
|
||||||
|
<< block::CurrencyCollection{0, req.extra}.to_str() << " required, only "
|
||||||
|
<< block::CurrencyCollection{0, ap.remaining_balance.extra}.to_str() << " available";
|
||||||
return skip_invalid ? 0 : 38; // not enough (extra) funds
|
return skip_invalid ? 0 : 38; // not enough (extra) funds
|
||||||
}
|
}
|
||||||
|
if (ap.remaining_balance.extra.not_null() || req.extra.not_null()) {
|
||||||
|
LOG(WARNING) << "subtracting extra currencies: "
|
||||||
|
<< block::CurrencyCollection{0, ap.remaining_balance.extra}.to_str() << " minus "
|
||||||
|
<< block::CurrencyCollection{0, req.extra}.to_str() << " equals "
|
||||||
|
<< block::CurrencyCollection{0, new_extra}.to_str();
|
||||||
|
}
|
||||||
|
|
||||||
auto fwd_fee_mine = msg_prices.get_first_part(fwd_fee);
|
auto fwd_fee_mine = msg_prices.get_first_part(fwd_fee);
|
||||||
auto fwd_fee_remain = fwd_fee - fwd_fee_mine;
|
auto fwd_fee_remain = fwd_fee - fwd_fee_mine;
|
||||||
|
@ -1691,7 +1699,9 @@ int Transaction::try_action_reserve_currency(vm::CellSlice& cs, ActionPhase& ap,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!block::sub_extra_currency(ap.remaining_balance.extra, reserve.extra, newc.extra)) {
|
if (!block::sub_extra_currency(ap.remaining_balance.extra, reserve.extra, newc.extra)) {
|
||||||
LOG(DEBUG) << "not enough extra currency to reserve";
|
LOG(DEBUG) << "not enough extra currency to reserve: " << block::CurrencyCollection{0, reserve.extra}.to_str()
|
||||||
|
<< " required, only " << block::CurrencyCollection{0, ap.remaining_balance.extra}.to_str()
|
||||||
|
<< " available";
|
||||||
if (mode & 2) {
|
if (mode & 2) {
|
||||||
// TODO: process (mode & 2) correctly by setting res_extra := inf (reserve.extra, ap.remaining_balance.extra)
|
// TODO: process (mode & 2) correctly by setting res_extra := inf (reserve.extra, ap.remaining_balance.extra)
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,7 +85,8 @@ library TonUtil // TON Blockchain Fift Library
|
||||||
// ( nanograms -- S )
|
// ( nanograms -- S )
|
||||||
{ dup abs <# ' # 9 times char . hold #s rot sign #>
|
{ dup abs <# ' # 9 times char . hold #s rot sign #>
|
||||||
nip -trailing0 } : (.GR)
|
nip -trailing0 } : (.GR)
|
||||||
{ (.GR) ."GR$" type space } : .GR
|
{ (.GR) ."GR$" type } : .GR_
|
||||||
|
{ .GR_ space } : .GR
|
||||||
|
|
||||||
// b x -- b' ( serializes a Gram amount )
|
// b x -- b' ( serializes a Gram amount )
|
||||||
{ -1 { 1+ 2dup 8 * ufits } until
|
{ -1 { 1+ 2dup 8 * ufits } until
|
||||||
|
@ -105,19 +106,49 @@ nip -trailing0 } : (.GR)
|
||||||
' VarUInt32, : val,
|
' VarUInt32, : val,
|
||||||
' VarUInt32@ : val@
|
' VarUInt32@ : val@
|
||||||
// d k v -- d'
|
// d k v -- d'
|
||||||
{ <b swap val, b> <s swap rot cc-key-bits idict! not abort"cannot add key-value to CurrencyCollection" } : +ccpair
|
{ <b swap val, b> <s swap rot cc-key-bits idict!+ not abort"cannot add key-value to CurrencyCollection"
|
||||||
|
} : +newccpair
|
||||||
|
{ dup { -rot tuck swap cc-key-bits idict@- { val@ 2swap -rot + } { swap rot } cond +newccpair
|
||||||
|
} { 2drop } cond
|
||||||
|
} : +ccpair
|
||||||
dictnew constant cc0 // zero currency collection
|
dictnew constant cc0 // zero currency collection
|
||||||
// ( v k -- d ) Creates currency collection representing v units of currency k
|
// ( v k -- d ) Creates currency collection representing v units of currency k
|
||||||
{ cc0 swap rot +ccpair } : of-cc
|
{ cc0 swap rot +ccpair } : of-cc
|
||||||
{ dictnew { over null? not } { swap uncons -rot unpair +ccpair } while nip } : list>cc
|
{ dictnew { over null? not } { swap uncons -rot unpair +ccpair } while nip } : list>cc
|
||||||
{ dup null? { ."(null) " drop } { val@ . } cond } dup : .maybeVarUInt32 : .val
|
{ dup null? { ."(null)" drop } { val@ ._ } cond } dup : .maybeVarUInt32 : .val
|
||||||
{ cc-key-bits { swap 32 1<< rmod . ."-> " .val ."; " true } dictforeach drop cr } : .cc
|
{ swap cc-key-bits { rot { ."+" } if .val ."*$" ._ true true } idictforeach drop } : (.cc)
|
||||||
|
{ false (.cc) { ."0" } ifnot } : .cc_
|
||||||
|
{ .cc_ space } : .cc
|
||||||
|
{ true (.cc) } : .+cc_
|
||||||
|
{ .+cc_ space } : .+cc
|
||||||
{ cc-key-bits { rot . ."-> " swap .val .val ."; " true } dictdiff drop cr } : show-cc-diff
|
{ cc-key-bits { rot . ."-> " swap .val .val ."; " true } dictdiff drop cr } : show-cc-diff
|
||||||
{ cc-key-bits { val@ swap val@ + val, true } dictmerge } : cc+
|
{ cc-key-bits { val@ swap val@ + val, true } dictmerge } : cc+
|
||||||
{ null swap cc-key-bits { val@ pair swap cons true } dictforeach drop } : cc>list-rev
|
{ null swap cc-key-bits { val@ pair swap cons true } idictforeach drop } : cc>list-rev
|
||||||
{ cc>list-rev list-reverse } : cc>list
|
{ cc>list-rev list-reverse } : cc>list
|
||||||
forget val, forget val@ forget .val
|
forget val, forget val@ forget .val
|
||||||
|
|
||||||
|
// ( S -- x -1 or 0 )
|
||||||
|
{ (number) dup 2 = { -rot 2drop } if 1 = } : int?
|
||||||
|
{ int? dup { drop dup 0< { drop false } { true } cond } if } : pos-int?
|
||||||
|
// ( S -- k v -1 or 0 ) Parses expression <value>*<currency> or <value>*$<currency>
|
||||||
|
{ dup "*" $pos dup 0< { 2drop false } {
|
||||||
|
$| dup $len 2 < { 2drop false } {
|
||||||
|
1 $| nip dup 1 $| swap "$" $= { swap } if drop
|
||||||
|
int? dup { over 32 fits { 2drop false } ifnot } if
|
||||||
|
not { drop false } {
|
||||||
|
swap pos-int? not { drop false } {
|
||||||
|
true
|
||||||
|
} cond } cond } cond } cond
|
||||||
|
} : cc-key-value?
|
||||||
|
// ( S -- D -1 or 0 ) Parses an extra currency collection
|
||||||
|
{ dictnew { // S D
|
||||||
|
swap dup "+" $pos dup 0< { drop null -rot } { $| 1 $| nip -rot } cond
|
||||||
|
cc-key-value? { +ccpair over null? dup { rot drop true } if } { 2drop false true } cond
|
||||||
|
} until
|
||||||
|
} : $>cc?
|
||||||
|
{ $>cc? not abort"invalid extra currency collection" } : $>cc
|
||||||
|
{ char } word dup $len { $>cc } { drop dictnew } cond 1 'nop } ::_ CX{
|
||||||
|
|
||||||
// Libraries
|
// Libraries
|
||||||
// ( -- D ) New empty library collection
|
// ( -- D ) New empty library collection
|
||||||
' dictnew : Libs{
|
' dictnew : Libs{
|
||||||
|
|
|
@ -8,9 +8,10 @@
|
||||||
true =: allow-bounce
|
true =: allow-bounce
|
||||||
false =: force-bounce
|
false =: force-bounce
|
||||||
3 =: send-mode // mode for SENDRAWMSG: +1 - sender pays fees, +2 - ignore errors
|
3 =: send-mode // mode for SENDRAWMSG: +1 - sender pays fees, +2 - ignore errors
|
||||||
|
variable extra-currencies
|
||||||
|
|
||||||
begin-options
|
begin-options
|
||||||
" <filename-base> <dest-addr> <seqno> <amount> [-n|-b] [-B <body-boc>] [-C <comment>] [<savefile>]" +cr +tab
|
" <filename-base> <dest-addr> <seqno> <amount> [-x <extra-amount>*<extra-currency-id>] [-n|-b] [-B <body-boc>] [-C <comment>] [<savefile>]" +cr +tab
|
||||||
+"Creates a request to simple wallet created by new-wallet.fif, with private key loaded from file <filename-base>.pk "
|
+"Creates a request to simple wallet created by new-wallet.fif, with private key loaded from file <filename-base>.pk "
|
||||||
+"and address from <filename-base>.addr, and saves it into <savefile>.boc ('wallet-query.boc' by default)"
|
+"and address from <filename-base>.addr, and saves it into <savefile>.boc ('wallet-query.boc' by default)"
|
||||||
disable-digit-options generic-help-setopt
|
disable-digit-options generic-help-setopt
|
||||||
|
@ -18,6 +19,8 @@ begin-options
|
||||||
"Clears bounce flag" option-help
|
"Clears bounce flag" option-help
|
||||||
"b" "--force-bounce" { true =: force-bounce } short-long-option
|
"b" "--force-bounce" { true =: force-bounce } short-long-option
|
||||||
"Forces bounce flag" option-help
|
"Forces bounce flag" option-help
|
||||||
|
"x" "--extra" { $>cc extra-currencies @ cc+ extra-currencies ! } short-long-option-arg
|
||||||
|
"Indicates the amount of extra currencies to be transfered" option-help
|
||||||
"B" "--body" { =: body-boc-file } short-long-option-arg
|
"B" "--body" { =: body-boc-file } short-long-option-arg
|
||||||
"Sets the payload of the transfer message" option-help
|
"Sets the payload of the transfer message" option-help
|
||||||
"C" "--comment" { =: comment } short-long-option-arg
|
"C" "--comment" { =: comment } short-long-option-arg
|
||||||
|
@ -48,13 +51,13 @@ file-base +".pk" load-keypair nip constant wallet_pk
|
||||||
def? body-boc-file { @' body-boc-file file>B B>boc } { comment simple-transfer-body } cond
|
def? body-boc-file { @' body-boc-file file>B B>boc } { comment simple-transfer-body } cond
|
||||||
constant body-cell
|
constant body-cell
|
||||||
|
|
||||||
."Transferring " amount .GR ."to account "
|
."Transferring " amount .GR_ extra-currencies @ .+cc ."to account "
|
||||||
dest_addr 2dup bounce 7 + .Addr ." = " .addr
|
dest_addr 2dup bounce 7 + .Addr ." = " .addr
|
||||||
."seqno=0x" seqno x. ."bounce=" bounce . cr
|
."seqno=0x" seqno x. ."bounce=" bounce . cr
|
||||||
."Body of transfer message is " body-cell <s csr. cr
|
."Body of transfer message is " body-cell <s csr. cr
|
||||||
|
|
||||||
// create a message
|
// create a message
|
||||||
<b b{01} s, bounce 1 i, b{000} s, dest_addr Addr, amount Gram, 0 9 64 32 + + 1+ u,
|
<b b{01} s, bounce 1 i, b{000} s, dest_addr Addr, amount Gram, extra-currencies @ dict, 0 9 64 32 + + u,
|
||||||
body-cell <s 2dup 1 s-fits-with? not rot over 1 i, -rot { drop body-cell ref, } { s, } cond
|
body-cell <s 2dup 1 s-fits-with? not rot over 1 i, -rot { drop body-cell ref, } { s, } cond
|
||||||
b>
|
b>
|
||||||
<b seqno 32 u, send-mode 8 u, swap ref, b>
|
<b seqno 32 u, send-mode 8 u, swap ref, b>
|
||||||
|
|
|
@ -95,7 +95,8 @@ td::Result<std::pair<std::string, td::BufferSlice>> Package::read(td::uint64 off
|
||||||
return td::Status::Error(ErrorCode::notready, "too short read");
|
return td::Status::Error(ErrorCode::notready, "too short read");
|
||||||
}
|
}
|
||||||
if ((header[0] & 0xffff) != entry_header_magic()) {
|
if ((header[0] & 0xffff) != entry_header_magic()) {
|
||||||
return td::Status::Error(ErrorCode::notready, "bad entry magic");
|
return td::Status::Error(ErrorCode::notready,
|
||||||
|
PSTRING() << "bad entry magic " << (header[0] & 0xffff) << " offset=" << offset);
|
||||||
}
|
}
|
||||||
offset += 8;
|
offset += 8;
|
||||||
auto fname_size = header[0] >> 16;
|
auto fname_size = header[0] >> 16;
|
||||||
|
|
|
@ -1628,7 +1628,7 @@ bool Collator::do_collate() {
|
||||||
return fatal_error("cannot compute the value to be created / minted / recovered");
|
return fatal_error("cannot compute the value to be created / minted / recovered");
|
||||||
}
|
}
|
||||||
// 2. tick transactions
|
// 2. tick transactions
|
||||||
LOG(DEBUG) << "create tick transactions";
|
LOG(INFO) << "create tick transactions";
|
||||||
if (!create_ticktock_transactions(2)) {
|
if (!create_ticktock_transactions(2)) {
|
||||||
return fatal_error("cannot generate tick transactions");
|
return fatal_error("cannot generate tick transactions");
|
||||||
}
|
}
|
||||||
|
@ -1642,18 +1642,18 @@ bool Collator::do_collate() {
|
||||||
// ...
|
// ...
|
||||||
}
|
}
|
||||||
// 4. import inbound internal messages, process or transit
|
// 4. import inbound internal messages, process or transit
|
||||||
LOG(DEBUG) << "process inbound internal messages";
|
LOG(INFO) << "process inbound internal messages";
|
||||||
if (!process_inbound_internal_messages()) {
|
if (!process_inbound_internal_messages()) {
|
||||||
return fatal_error("cannot process inbound internal messages");
|
return fatal_error("cannot process inbound internal messages");
|
||||||
}
|
}
|
||||||
// 5. import inbound external messages (if space&gas left)
|
// 5. import inbound external messages (if space&gas left)
|
||||||
LOG(DEBUG) << "process inbound external messages";
|
LOG(INFO) << "process inbound external messages";
|
||||||
if (!process_inbound_external_messages()) {
|
if (!process_inbound_external_messages()) {
|
||||||
return fatal_error("cannot process inbound external messages");
|
return fatal_error("cannot process inbound external messages");
|
||||||
}
|
}
|
||||||
// 6. process newly-generated messages (if space&gas left)
|
// 6. process newly-generated messages (if space&gas left)
|
||||||
// (if we were unable to process all inbound messages, all new messages must be queued)
|
// (if we were unable to process all inbound messages, all new messages must be queued)
|
||||||
LOG(DEBUG) << "process newly-generated messages";
|
LOG(INFO) << "process newly-generated messages";
|
||||||
if (!process_new_messages(!inbound_queues_empty_)) {
|
if (!process_new_messages(!inbound_queues_empty_)) {
|
||||||
return fatal_error("cannot process newly-generated outbound messages");
|
return fatal_error("cannot process newly-generated outbound messages");
|
||||||
}
|
}
|
||||||
|
@ -1664,12 +1664,12 @@ bool Collator::do_collate() {
|
||||||
// ...
|
// ...
|
||||||
}
|
}
|
||||||
// 8. tock transactions
|
// 8. tock transactions
|
||||||
LOG(DEBUG) << "create tock transactions";
|
LOG(INFO) << "create tock transactions";
|
||||||
if (!create_ticktock_transactions(1)) {
|
if (!create_ticktock_transactions(1)) {
|
||||||
return fatal_error("cannot generate tock transactions");
|
return fatal_error("cannot generate tock transactions");
|
||||||
}
|
}
|
||||||
// 9. process newly-generated messages (only by including them into output queue)
|
// 9. process newly-generated messages (only by including them into output queue)
|
||||||
LOG(DEBUG) << "enqueue newly-generated messages";
|
LOG(INFO) << "enqueue newly-generated messages";
|
||||||
if (!process_new_messages(true)) {
|
if (!process_new_messages(true)) {
|
||||||
return fatal_error("cannot process newly-generated outbound messages");
|
return fatal_error("cannot process newly-generated outbound messages");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue