Withdrawal object creation

This commit is contained in:
serkixenos 2021-04-26 13:05:27 +02:00
parent 7536f1a2d7
commit 09f23dade8
11 changed files with 1085 additions and 18 deletions

View file

@ -16,6 +16,7 @@ add_library( peerplays_sidechain
bitcoin/sign_bitcoin_transaction.cpp bitcoin/sign_bitcoin_transaction.cpp
common/rpc_client.cpp common/rpc_client.cpp
common/utils.cpp common/utils.cpp
hive/asset.cpp
hive/operations.cpp hive/operations.cpp
hive/transaction.cpp hive/transaction.cpp
hive/types.cpp hive/types.cpp

View file

@ -0,0 +1,263 @@
#include <graphene/peerplays_sidechain/hive/asset.hpp>
#include <fc/io/json.hpp>
#include <boost/multiprecision/cpp_int.hpp>
#include <boost/rational.hpp>
#define ASSET_AMOUNT_KEY "amount"
#define ASSET_PRECISION_KEY "precision"
#define ASSET_NAI_KEY "nai"
namespace graphene { namespace peerplays_sidechain { namespace hive {
std::string asset_symbol_type::to_string() const {
return fc::json::to_string(fc::variant(*this, 5));
}
asset_symbol_type asset_symbol_type::from_string(const std::string &str) {
return fc::json::from_string(str).as<hive::asset_symbol_type>(5);
}
void asset_symbol_type::to_nai_string(char *buf) const {
static_assert(HIVE_ASSET_SYMBOL_NAI_STRING_LENGTH >= 12, "This code will overflow a short buffer");
uint32_t x = to_nai();
buf[11] = '\0';
buf[10] = ((x % 10) + '0');
x /= 10;
buf[9] = ((x % 10) + '0');
x /= 10;
buf[8] = ((x % 10) + '0');
x /= 10;
buf[7] = ((x % 10) + '0');
x /= 10;
buf[6] = ((x % 10) + '0');
x /= 10;
buf[5] = ((x % 10) + '0');
x /= 10;
buf[4] = ((x % 10) + '0');
x /= 10;
buf[3] = ((x % 10) + '0');
x /= 10;
buf[2] = ((x) + '0');
buf[1] = '@';
buf[0] = '@';
}
asset_symbol_type asset_symbol_type::from_nai_string(const char *p, uint8_t decimal_places) {
try {
FC_ASSERT(p != nullptr, "NAI string cannot be a null");
FC_ASSERT(std::strlen(p) == HIVE_ASSET_SYMBOL_NAI_STRING_LENGTH - 1, "Incorrect NAI string length");
FC_ASSERT(p[0] == '@' && p[1] == '@', "Invalid NAI string prefix");
uint32_t nai = boost::lexical_cast<uint32_t>(p + 2);
return asset_symbol_type::from_nai(nai, decimal_places);
}
FC_CAPTURE_AND_RETHROW();
}
// Highly optimized implementation of Damm algorithm
// https://en.wikipedia.org/wiki/Damm_algorithm
uint8_t asset_symbol_type::damm_checksum_8digit(uint32_t value) {
FC_ASSERT(value < 100000000);
const uint8_t t[] = {
0, 30, 10, 70, 50, 90, 80, 60, 40, 20,
70, 0, 90, 20, 10, 50, 40, 80, 60, 30,
40, 20, 0, 60, 80, 70, 10, 30, 50, 90,
10, 70, 50, 0, 90, 80, 30, 40, 20, 60,
60, 10, 20, 30, 0, 40, 50, 90, 70, 80,
30, 60, 70, 40, 20, 0, 90, 50, 80, 10,
50, 80, 60, 90, 70, 20, 0, 10, 30, 40,
80, 90, 40, 50, 30, 60, 20, 0, 10, 70,
90, 40, 30, 80, 60, 10, 70, 20, 0, 50,
20, 50, 80, 10, 40, 30, 60, 70, 90, 0};
uint32_t q0 = value / 10;
uint32_t d0 = value % 10;
uint32_t q1 = q0 / 10;
uint32_t d1 = q0 % 10;
uint32_t q2 = q1 / 10;
uint32_t d2 = q1 % 10;
uint32_t q3 = q2 / 10;
uint32_t d3 = q2 % 10;
uint32_t q4 = q3 / 10;
uint32_t d4 = q3 % 10;
uint32_t q5 = q4 / 10;
uint32_t d5 = q4 % 10;
uint32_t d6 = q5 % 10;
uint32_t d7 = q5 / 10;
uint8_t x = t[d7];
x = t[x + d6];
x = t[x + d5];
x = t[x + d4];
x = t[x + d3];
x = t[x + d2];
x = t[x + d1];
x = t[x + d0];
return x / 10;
}
uint32_t asset_symbol_type::asset_num_from_nai(uint32_t nai, uint8_t decimal_places) {
// Can be replaced with some clever bitshifting
uint32_t nai_check_digit = nai % 10;
uint32_t nai_data_digits = nai / 10;
FC_ASSERT((nai_data_digits >= SMT_MIN_NAI) & (nai_data_digits <= SMT_MAX_NAI), "NAI out of range");
FC_ASSERT(nai_check_digit == damm_checksum_8digit(nai_data_digits), "Invalid check digit");
switch (nai_data_digits) {
case HIVE_NAI_HIVE:
FC_ASSERT(decimal_places == HIVE_PRECISION_HIVE);
return HIVE_ASSET_NUM_HIVE;
case HIVE_NAI_HBD:
FC_ASSERT(decimal_places == HIVE_PRECISION_HBD);
return HIVE_ASSET_NUM_HBD;
case HIVE_NAI_VESTS:
FC_ASSERT(decimal_places == HIVE_PRECISION_VESTS);
return HIVE_ASSET_NUM_VESTS;
default:
FC_ASSERT(decimal_places <= HIVE_ASSET_MAX_DECIMALS, "Invalid decimal_places");
return (nai_data_digits << HIVE_NAI_SHIFT) | SMT_ASSET_NUM_CONTROL_MASK | decimal_places;
}
}
uint32_t asset_symbol_type::to_nai() const {
uint32_t nai_data_digits = 0;
// Can be replaced with some clever bitshifting
switch (asset_num) {
case HIVE_ASSET_NUM_HIVE:
nai_data_digits = HIVE_NAI_HIVE;
break;
case HIVE_ASSET_NUM_HBD:
nai_data_digits = HIVE_NAI_HBD;
break;
case HIVE_ASSET_NUM_VESTS:
nai_data_digits = HIVE_NAI_VESTS;
break;
default:
FC_ASSERT(space() == smt_nai_space);
nai_data_digits = (asset_num >> HIVE_NAI_SHIFT);
}
uint32_t nai_check_digit = damm_checksum_8digit(nai_data_digits);
return nai_data_digits * 10 + nai_check_digit;
}
bool asset_symbol_type::is_vesting() const {
switch (space()) {
case legacy_space: {
switch (asset_num) {
case HIVE_ASSET_NUM_HIVE:
return false;
case HIVE_ASSET_NUM_HBD:
// HBD is certainly liquid.
return false;
case HIVE_ASSET_NUM_VESTS:
return true;
default:
FC_ASSERT(false, "Unknown asset symbol");
}
}
case smt_nai_space:
// 6th bit of asset_num is used as vesting/liquid variant indicator.
return asset_num & SMT_ASSET_NUM_VESTING_MASK;
default:
FC_ASSERT(false, "Unknown asset symbol");
}
}
asset_symbol_type asset_symbol_type::get_paired_symbol() const {
switch (space()) {
case legacy_space: {
switch (asset_num) {
case HIVE_ASSET_NUM_HIVE:
return from_asset_num(HIVE_ASSET_NUM_VESTS);
case HIVE_ASSET_NUM_HBD:
return *this;
case HIVE_ASSET_NUM_VESTS:
return from_asset_num(HIVE_ASSET_NUM_HIVE);
default:
FC_ASSERT(false, "Unknown asset symbol");
}
}
case smt_nai_space: {
// Toggle 6th bit of this asset_num.
auto paired_asset_num = asset_num ^ (SMT_ASSET_NUM_VESTING_MASK);
return from_asset_num(paired_asset_num);
}
default:
FC_ASSERT(false, "Unknown asset symbol");
}
}
asset_symbol_type::asset_symbol_space asset_symbol_type::space() const {
asset_symbol_type::asset_symbol_space s = legacy_space;
switch (asset_num) {
case HIVE_ASSET_NUM_HIVE:
case HIVE_ASSET_NUM_HBD:
case HIVE_ASSET_NUM_VESTS:
s = legacy_space;
break;
default:
s = smt_nai_space;
}
return s;
}
void asset_symbol_type::validate() const {
switch (asset_num) {
case HIVE_ASSET_NUM_HIVE:
case HIVE_ASSET_NUM_HBD:
case HIVE_ASSET_NUM_VESTS:
break;
default: {
uint32_t nai_data_digits = (asset_num >> HIVE_NAI_SHIFT);
uint32_t nai_1bit = (asset_num & SMT_ASSET_NUM_CONTROL_MASK);
uint32_t nai_decimal_places = (asset_num & SMT_ASSET_NUM_PRECISION_MASK);
FC_ASSERT((nai_data_digits >= SMT_MIN_NAI) &
(nai_data_digits <= SMT_MAX_NAI) &
(nai_1bit == SMT_ASSET_NUM_CONTROL_MASK) &
(nai_decimal_places <= HIVE_ASSET_MAX_DECIMALS),
"Cannot determine space for asset ${n}", ("n", asset_num));
}
}
// this assert is duplicated by above code in all cases
// FC_ASSERT( decimals() <= HIVE_ASSET_MAX_DECIMALS );
}
}}} // namespace graphene::peerplays_sidechain::hive
namespace fc {
void to_variant(const graphene::peerplays_sidechain::hive::asset &var, fc::variant &vo, uint32_t max_depth) {
try {
variant v = mutable_variant_object(ASSET_AMOUNT_KEY, boost::lexical_cast<std::string>(var.amount.value))(ASSET_PRECISION_KEY, uint64_t(var.symbol.decimals()))(ASSET_NAI_KEY, var.symbol.to_nai_string());
vo = v;
}
FC_CAPTURE_AND_RETHROW()
}
void from_variant(const fc::variant &var, graphene::peerplays_sidechain::hive::asset &vo, uint32_t max_depth) {
try {
FC_ASSERT(var.is_object(), "Asset has to be treated as object.");
const auto &v_object = var.get_object();
FC_ASSERT(v_object.contains(ASSET_AMOUNT_KEY), "Amount field doesn't exist.");
FC_ASSERT(v_object[ASSET_AMOUNT_KEY].is_string(), "Expected a string type for value '${key}'.", ("key", ASSET_AMOUNT_KEY));
vo.amount = boost::lexical_cast<int64_t>(v_object[ASSET_AMOUNT_KEY].as<std::string>(max_depth));
FC_ASSERT(vo.amount >= 0, "Asset amount cannot be negative");
FC_ASSERT(v_object.contains(ASSET_PRECISION_KEY), "Precision field doesn't exist.");
FC_ASSERT(v_object[ASSET_PRECISION_KEY].is_uint64(), "Expected an unsigned integer type for value '${key}'.", ("key", ASSET_PRECISION_KEY));
FC_ASSERT(v_object.contains(ASSET_NAI_KEY), "NAI field doesn't exist.");
FC_ASSERT(v_object[ASSET_NAI_KEY].is_string(), "Expected a string type for value '${key}'.", ("key", ASSET_NAI_KEY));
vo.symbol = graphene::peerplays_sidechain::hive::asset_symbol_type::from_nai_string(v_object[ASSET_NAI_KEY].as<std::string>(max_depth).c_str(), v_object[ASSET_PRECISION_KEY].as<uint8_t>(max_depth));
}
FC_CAPTURE_AND_RETHROW()
}
} // namespace fc

View file

@ -0,0 +1,300 @@
//#include <graphene/peerplays_sidechain/hive/asset_symbol.hpp>
//
//#include <fc/io/json.hpp>
//
//namespace graphene { namespace peerplays_sidechain { namespace hive {
//
//std::string asset_symbol_type::to_string() const {
// return fc::json::to_string(fc::variant(*this, 5));
//}
//
//asset_symbol_type asset_symbol_type::from_string(const std::string &str) {
// return fc::json::from_string(str).as<hive::asset_symbol_type>(5);
//}
//
//void asset_symbol_type::to_nai_string(char *buf) const {
// static_assert(HIVE_ASSET_SYMBOL_NAI_STRING_LENGTH >= 12, "This code will overflow a short buffer");
// uint32_t x = to_nai();
// buf[11] = '\0';
// buf[10] = ((x % 10) + '0');
// x /= 10;
// buf[9] = ((x % 10) + '0');
// x /= 10;
// buf[8] = ((x % 10) + '0');
// x /= 10;
// buf[7] = ((x % 10) + '0');
// x /= 10;
// buf[6] = ((x % 10) + '0');
// x /= 10;
// buf[5] = ((x % 10) + '0');
// x /= 10;
// buf[4] = ((x % 10) + '0');
// x /= 10;
// buf[3] = ((x % 10) + '0');
// x /= 10;
// buf[2] = ((x) + '0');
// buf[1] = '@';
// buf[0] = '@';
//}
//
//asset_symbol_type asset_symbol_type::from_nai_string(const char *p, uint8_t decimal_places) {
// try {
// FC_ASSERT(p != nullptr, "NAI string cannot be a null");
// FC_ASSERT(std::strlen(p) == HIVE_ASSET_SYMBOL_NAI_STRING_LENGTH - 1, "Incorrect NAI string length");
// FC_ASSERT(p[0] == '@' && p[1] == '@', "Invalid NAI string prefix");
// uint32_t nai = boost::lexical_cast<uint32_t>(p + 2);
// return asset_symbol_type::from_nai(nai, decimal_places);
// }
// FC_CAPTURE_AND_RETHROW();
//}
//
//// Highly optimized implementation of Damm algorithm
//// https://en.wikipedia.org/wiki/Damm_algorithm
//uint8_t asset_symbol_type::damm_checksum_8digit(uint32_t value) {
// FC_ASSERT(value < 100000000);
//
// const uint8_t t[] = {
// 0, 30, 10, 70, 50, 90, 80, 60, 40, 20,
// 70, 0, 90, 20, 10, 50, 40, 80, 60, 30,
// 40, 20, 0, 60, 80, 70, 10, 30, 50, 90,
// 10, 70, 50, 0, 90, 80, 30, 40, 20, 60,
// 60, 10, 20, 30, 0, 40, 50, 90, 70, 80,
// 30, 60, 70, 40, 20, 0, 90, 50, 80, 10,
// 50, 80, 60, 90, 70, 20, 0, 10, 30, 40,
// 80, 90, 40, 50, 30, 60, 20, 0, 10, 70,
// 90, 40, 30, 80, 60, 10, 70, 20, 0, 50,
// 20, 50, 80, 10, 40, 30, 60, 70, 90, 0};
//
// uint32_t q0 = value / 10;
// uint32_t d0 = value % 10;
// uint32_t q1 = q0 / 10;
// uint32_t d1 = q0 % 10;
// uint32_t q2 = q1 / 10;
// uint32_t d2 = q1 % 10;
// uint32_t q3 = q2 / 10;
// uint32_t d3 = q2 % 10;
// uint32_t q4 = q3 / 10;
// uint32_t d4 = q3 % 10;
// uint32_t q5 = q4 / 10;
// uint32_t d5 = q4 % 10;
// uint32_t d6 = q5 % 10;
// uint32_t d7 = q5 / 10;
//
// uint8_t x = t[d7];
// x = t[x + d6];
// x = t[x + d5];
// x = t[x + d4];
// x = t[x + d3];
// x = t[x + d2];
// x = t[x + d1];
// x = t[x + d0];
// return x / 10;
//}
//
//uint32_t asset_symbol_type::asset_num_from_nai(uint32_t nai, uint8_t decimal_places) {
// // Can be replaced with some clever bitshifting
// uint32_t nai_check_digit = nai % 10;
// uint32_t nai_data_digits = nai / 10;
//
// FC_ASSERT((nai_data_digits >= SMT_MIN_NAI) & (nai_data_digits <= SMT_MAX_NAI), "NAI out of range");
// FC_ASSERT(nai_check_digit == damm_checksum_8digit(nai_data_digits), "Invalid check digit");
//
// switch (nai_data_digits) {
// case HIVE_NAI_HIVE:
// FC_ASSERT(decimal_places == HIVE_PRECISION_HIVE);
// return HIVE_ASSET_NUM_HIVE;
// case HIVE_NAI_HBD:
// FC_ASSERT(decimal_places == HIVE_PRECISION_HBD);
// return HIVE_ASSET_NUM_HBD;
// case HIVE_NAI_VESTS:
// FC_ASSERT(decimal_places == HIVE_PRECISION_VESTS);
// return HIVE_ASSET_NUM_VESTS;
// default:
// FC_ASSERT(decimal_places <= HIVE_ASSET_MAX_DECIMALS, "Invalid decimal_places");
// return (nai_data_digits << HIVE_NAI_SHIFT) | SMT_ASSET_NUM_CONTROL_MASK | decimal_places;
// }
//}
//
//uint32_t asset_symbol_type::to_nai() const {
// uint32_t nai_data_digits = 0;
//
// // Can be replaced with some clever bitshifting
// switch (asset_num) {
// case HIVE_ASSET_NUM_HIVE:
// nai_data_digits = HIVE_NAI_HIVE;
// break;
// case HIVE_ASSET_NUM_HBD:
// nai_data_digits = HIVE_NAI_HBD;
// break;
// case HIVE_ASSET_NUM_VESTS:
// nai_data_digits = HIVE_NAI_VESTS;
// break;
// default:
// FC_ASSERT(space() == smt_nai_space);
// nai_data_digits = (asset_num >> HIVE_NAI_SHIFT);
// }
//
// uint32_t nai_check_digit = damm_checksum_8digit(nai_data_digits);
// return nai_data_digits * 10 + nai_check_digit;
//}
//
//bool asset_symbol_type::is_vesting() const {
// switch (space()) {
// case legacy_space: {
// switch (asset_num) {
// case HIVE_ASSET_NUM_HIVE:
// return false;
// case HIVE_ASSET_NUM_HBD:
// // HBD is certainly liquid.
// return false;
// case HIVE_ASSET_NUM_VESTS:
// return true;
// default:
// FC_ASSERT(false, "Unknown asset symbol");
// }
// }
// case smt_nai_space:
// // 6th bit of asset_num is used as vesting/liquid variant indicator.
// return asset_num & SMT_ASSET_NUM_VESTING_MASK;
// default:
// FC_ASSERT(false, "Unknown asset symbol");
// }
//}
//
//asset_symbol_type asset_symbol_type::get_paired_symbol() const {
// switch (space()) {
// case legacy_space: {
// switch (asset_num) {
// case HIVE_ASSET_NUM_HIVE:
// return from_asset_num(HIVE_ASSET_NUM_VESTS);
// case HIVE_ASSET_NUM_HBD:
// return *this;
// case HIVE_ASSET_NUM_VESTS:
// return from_asset_num(HIVE_ASSET_NUM_HIVE);
// default:
// FC_ASSERT(false, "Unknown asset symbol");
// }
// }
// case smt_nai_space: {
// // Toggle 6th bit of this asset_num.
// auto paired_asset_num = asset_num ^ (SMT_ASSET_NUM_VESTING_MASK);
// return from_asset_num(paired_asset_num);
// }
// default:
// FC_ASSERT(false, "Unknown asset symbol");
// }
//}
//
//asset_symbol_type::asset_symbol_space asset_symbol_type::space() const {
// asset_symbol_type::asset_symbol_space s = legacy_space;
// switch (asset_num) {
// case HIVE_ASSET_NUM_HIVE:
// case HIVE_ASSET_NUM_HBD:
// case HIVE_ASSET_NUM_VESTS:
// s = legacy_space;
// break;
// default:
// s = smt_nai_space;
// }
// return s;
//}
//
//void asset_symbol_type::validate() const {
// switch (asset_num) {
// case HIVE_ASSET_NUM_HIVE:
// case HIVE_ASSET_NUM_HBD:
// case HIVE_ASSET_NUM_VESTS:
// break;
// default: {
// uint32_t nai_data_digits = (asset_num >> HIVE_NAI_SHIFT);
// uint32_t nai_1bit = (asset_num & SMT_ASSET_NUM_CONTROL_MASK);
// uint32_t nai_decimal_places = (asset_num & SMT_ASSET_NUM_PRECISION_MASK);
// FC_ASSERT((nai_data_digits >= SMT_MIN_NAI) &
// (nai_data_digits <= SMT_MAX_NAI) &
// (nai_1bit == SMT_ASSET_NUM_CONTROL_MASK) &
// (nai_decimal_places <= HIVE_ASSET_MAX_DECIMALS),
// "Cannot determine space for asset ${n}", ("n", asset_num));
// }
// }
// // this assert is duplicated by above code in all cases
// // FC_ASSERT( decimals() <= HIVE_ASSET_MAX_DECIMALS );
//}
//
//}}} // namespace graphene::peerplays_sidechain::hive
//
//namespace fc {
//
//namespace raw {
//
//// Legacy serialization of assets
//// 0000pppp aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff 00000000
//// Symbol = abcdef
////
//// NAI serialization of assets
//// aaa1pppp bbbbbbbb cccccccc dddddddd
//// NAI = (MSB to LSB) dddddddd cccccccc bbbbbbbb aaa
////
//// NAI internal storage of legacy assets
//
////template <typename Stream>
////void unpack(Stream &s, graphene::peerplays_sidechain::hive::asset_symbol_type &sym, uint32_t, uint32_t max_depth) {
//// uint64_t ser = 0;
//// s.read((char *)&ser, 4);
////
//// switch (ser) {
//// case OBSOLETE_SYMBOL_SER & 0xFFFFFFFF:
//// s.read(((char *)&ser) + 4, 4);
//// FC_ASSERT(ser == OBSOLETE_SYMBOL_SER, "invalid asset bits");
//// sym.asset_num = HIVE_ASSET_NUM_HIVE;
//// break;
//// case OBD_SYMBOL_SER & 0xFFFFFFFF:
//// s.read(((char *)&ser) + 4, 4);
//// FC_ASSERT(ser == OBD_SYMBOL_SER, "invalid asset bits");
//// sym.asset_num = HIVE_ASSET_NUM_HBD;
//// break;
//// case VESTS_SYMBOL_SER & 0xFFFFFFFF:
//// s.read(((char *)&ser) + 4, 4);
//// FC_ASSERT(ser == VESTS_SYMBOL_SER, "invalid asset bits");
//// sym.asset_num = HIVE_ASSET_NUM_VESTS;
//// break;
//// default:
//// sym.asset_num = uint32_t(ser);
//// }
//// sym.validate();
////}
//
//} // namespace raw
////
////void to_variant(const graphene::peerplays_sidechain::hive::asset_symbol_type &sym, fc::variant &var, uint32_t max_depth) {
//// try {
//// mutable_variant_object o;
//// o(ASSET_SYMBOL_NAI_KEY, sym.to_nai_string())(ASSET_SYMBOL_DECIMALS_KEY, sym.decimals());
//// var = std::move(o);
//// }
//// FC_CAPTURE_AND_RETHROW()
////}
////
////void from_variant(const fc::variant &var, graphene::peerplays_sidechain::hive::asset_symbol_type &sym, uint32_t max_depth) {
//// using graphene::peerplays_sidechain::hive::asset_symbol_type;
////
//// try {
//// FC_ASSERT(var.is_object(), "Asset symbol is expected to be an object.");
////
//// auto &o = var.get_object();
////
//// auto nai = o.find(ASSET_SYMBOL_NAI_KEY);
//// FC_ASSERT(nai != o.end(), "Expected key '${key}'.", ("key", ASSET_SYMBOL_NAI_KEY));
//// FC_ASSERT(nai->value().is_string(), "Expected a string type for value '${key}'.", ("key", ASSET_SYMBOL_NAI_KEY));
////
//// auto decimals = o.find(ASSET_SYMBOL_DECIMALS_KEY);
//// FC_ASSERT(decimals != o.end(), "Expected key '${key}'.", ("key", ASSET_SYMBOL_DECIMALS_KEY));
//// FC_ASSERT(decimals->value().is_uint64(), "Expected an unsigned integer type for value '${key}'.", ("key", ASSET_SYMBOL_DECIMALS_KEY));
//// FC_ASSERT(decimals->value().as_uint64() <= HIVE_ASSET_MAX_DECIMALS,
//// "Expected decimals to be less than or equal to ${num}", ("num", HIVE_ASSET_MAX_DECIMALS));
////
//// sym = asset_symbol_type::from_nai_string(nai->value().as_string().c_str(), decimals->value().as<uint8_t>(max_depth));
//// }
//// FC_CAPTURE_AND_RETHROW()
////}
//
//} // namespace fc

View file

@ -67,7 +67,15 @@ signature_type signed_transaction::sign(const hive::private_key_type &key, const
digest_type::encoder enc; digest_type::encoder enc;
fc::raw::pack(enc, chain_id); fc::raw::pack(enc, chain_id);
fc::raw::pack(enc, *this); fc::raw::pack(enc, *this);
return key.sign_compact(enc.result(), true); auto sig = key.sign_compact(enc.result(), true);
ilog("Signing2: chain_id = ${chain_id}", ("chain_id", chain_id));
ilog("Signing2: key = ${key}", ("key", key));
ilog("Signing2: this = ${this}", ("this", *this));
ilog("Signing2: h = ${h}", ("h", enc.result()));
ilog("Signing2: signature = ${sig}", ("sig", sig));
return sig;
} }
}}} // namespace graphene::peerplays_sidechain::hive }}} // namespace graphene::peerplays_sidechain::hive

View file

@ -0,0 +1,20 @@
#pragma once
#include <graphene/peerplays_sidechain/hive/asset_symbol.hpp>
#include <graphene/peerplays_sidechain/hive/types.hpp>
namespace graphene { namespace peerplays_sidechain { namespace hive {
struct asset {
share_type amount;
asset_symbol_type symbol;
};
}}} // namespace graphene::peerplays_sidechain::hive
namespace fc {
void to_variant(const graphene::peerplays_sidechain::hive::asset &var, fc::variant &vo, uint32_t max_depth);
void from_variant(const fc::variant &var, graphene::peerplays_sidechain::hive::asset &vo, uint32_t max_depth);
} // namespace fc
FC_REFLECT(graphene::peerplays_sidechain::hive::asset, (amount)(symbol))

View file

@ -0,0 +1,245 @@
#pragma once
#include <cstdint>
#include <iostream>
#include <string>
#include <fc/exception/exception.hpp>
#include <fc/io/raw.hpp>
#include <fc/reflect/reflect.hpp>
#include <fc/variant.hpp>
#include <graphene/peerplays_sidechain/hive/types_fwd.hpp>
#define HIVE_ASSET_SYMBOL_PRECISION_BITS 4
#define HIVE_ASSET_CONTROL_BITS 1
#define HIVE_NAI_SHIFT (HIVE_ASSET_SYMBOL_PRECISION_BITS + HIVE_ASSET_CONTROL_BITS)
#define SMT_MAX_NAI 99999999
#define SMT_MIN_NAI 1
#define SMT_MIN_NON_RESERVED_NAI 10000000
#define HIVE_ASSET_SYMBOL_NAI_LENGTH 10
#define HIVE_ASSET_SYMBOL_NAI_STRING_LENGTH (HIVE_ASSET_SYMBOL_NAI_LENGTH + 2)
#define SMT_MAX_NAI_POOL_COUNT 10
#define SMT_MAX_NAI_GENERATION_TRIES 100
#define HIVE_PRECISION_HBD (3)
#define HIVE_PRECISION_HIVE (3)
#define HIVE_PRECISION_VESTS (6)
// One's place is used for check digit, which means NAI 0-9 all have NAI data of 0 which is invalid
// This space is safe to use because it would alwasys result in failure to convert from NAI
#define HIVE_NAI_HBD (1)
#define HIVE_NAI_HIVE (2)
#define HIVE_NAI_VESTS (3)
#define HIVE_ASSET_NUM_HBD (uint32_t(((SMT_MAX_NAI + HIVE_NAI_HBD) << HIVE_NAI_SHIFT) | HIVE_PRECISION_HBD))
#define HIVE_ASSET_NUM_HIVE (uint32_t(((SMT_MAX_NAI + HIVE_NAI_HIVE) << HIVE_NAI_SHIFT) | HIVE_PRECISION_HIVE))
#define HIVE_ASSET_NUM_VESTS (uint32_t(((SMT_MAX_NAI + HIVE_NAI_VESTS) << HIVE_NAI_SHIFT) | HIVE_PRECISION_VESTS))
#ifdef IS_TEST_NET
#define VESTS_SYMBOL_U64 (uint64_t('V') | (uint64_t('E') << 8) | (uint64_t('S') << 16) | (uint64_t('T') << 24) | (uint64_t('S') << 32))
my #define HIVE_SYMBOL_U64 OBSOLETE_SYMBOL_U64
#define OBD_SYMBOL_U64 (uint64_t('T') | (uint64_t('B') << 8) | (uint64_t('D') << 16))
#define HBD_SYMBOL_U64 OBD_SYMBOL_U64
#else
#define VESTS_SYMBOL_U64 (uint64_t('V') | (uint64_t('E') << 8) | (uint64_t('S') << 16) | (uint64_t('T') << 24) | (uint64_t('S') << 32))
#define OBSOLETE_SYMBOL_U64 (uint64_t('S') | (uint64_t('T') << 8) | (uint64_t('E') << 16) | (uint64_t('E') << 24) | (uint64_t('M') << 32))
#define HIVE_SYMBOL_U64 (uint64_t('H') | (uint64_t('I') << 8) | (uint64_t('V') << 16) | (uint64_t('E') << 24))
#define OBD_SYMBOL_U64 (uint64_t('S') | (uint64_t('B') << 8) | (uint64_t('D') << 16))
#define HBD_SYMBOL_U64 (uint64_t('H') | (uint64_t('B') << 8) | (uint64_t('D') << 16))
#endif
#define VESTS_SYMBOL_SER (uint64_t(6) | (VESTS_SYMBOL_U64 << 8)) ///< VESTS|VESTS with 6 digits of precision
#define OBSOLETE_SYMBOL_SER (uint64_t(3) | (OBSOLETE_SYMBOL_U64 << 8)) ///< STEEM|TESTS with 3 digits of precision
#define OBD_SYMBOL_SER (uint64_t(3) | (OBD_SYMBOL_U64 << 8)) ///< SBD|TBD with 3 digits of precision
#define HIVE_ASSET_MAX_DECIMALS 12
#define SMT_ASSET_NUM_PRECISION_MASK 0xF
#define SMT_ASSET_NUM_CONTROL_MASK 0x10
#define SMT_ASSET_NUM_VESTING_MASK 0x20
#define ASSET_SYMBOL_NAI_KEY "nai"
#define ASSET_SYMBOL_DECIMALS_KEY "decimals"
namespace graphene {
namespace peerplays_sidechain { namespace hive {
class asset_symbol_type {
public:
enum asset_symbol_space {
legacy_space = 1,
smt_nai_space = 2
};
explicit operator uint32_t() {
return to_nai();
}
static asset_symbol_type from_string(const std::string &str);
// buf must have space for HIVE_ASSET_SYMBOL_NAI_STRING_LENGTH
static asset_symbol_type from_nai_string(const char *buf, uint8_t decimal_places);
static asset_symbol_type from_asset_num(uint32_t asset_num) {
asset_symbol_type result;
result.asset_num = asset_num;
return result;
}
static uint32_t asset_num_from_nai(uint32_t nai, uint8_t decimal_places);
static asset_symbol_type from_nai(uint32_t nai, uint8_t decimal_places) {
return from_asset_num(asset_num_from_nai(nai, decimal_places));
}
static uint8_t damm_checksum_8digit(uint32_t value);
std::string to_string() const;
void to_nai_string(char *buf) const;
std::string to_nai_string() const {
char buf[HIVE_ASSET_SYMBOL_NAI_STRING_LENGTH];
to_nai_string(buf);
return std::string(buf);
}
uint32_t to_nai() const;
/**Returns true when symbol represents vesting variant of the token,
* false for liquid one.
*/
bool is_vesting() const;
/**Returns vesting symbol when called from liquid one
* and liquid symbol when called from vesting one.
* Returns back the HBD symbol if represents HBD.
*/
asset_symbol_type get_paired_symbol() const;
/**Returns asset_num stripped of precision holding bits.
* \warning checking that it's SMT symbol is caller responsibility.
*/
uint32_t get_stripped_precision_smt_num() const {
return asset_num & ~(SMT_ASSET_NUM_PRECISION_MASK);
}
asset_symbol_space space() const;
uint8_t decimals() const {
return uint8_t(asset_num & SMT_ASSET_NUM_PRECISION_MASK);
}
void validate() const;
uint32_t asset_num = 0;
uint64_t ser = OBSOLETE_SYMBOL_SER;
};
}} // namespace peerplays_sidechain::hive
} // namespace graphene
FC_REFLECT(graphene::peerplays_sidechain::hive::asset_symbol_type, (asset_num))
namespace fc {
namespace raw {
// Legacy serialization of assets
// 0000pppp aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff 00000000
// Symbol = abcdef
//
// NAI serialization of assets
// aaa1pppp bbbbbbbb cccccccc dddddddd
// NAI = (MSB to LSB) dddddddd cccccccc bbbbbbbb aaa
//
// NAI internal storage of legacy assets
template <typename Stream>
void pack(Stream &s, const graphene::peerplays_sidechain::hive::asset_symbol_type &sym) {
std::cout << "##### PACK ###" << std::endl;
switch (sym.space()) {
case graphene::peerplays_sidechain::hive::asset_symbol_type::legacy_space: {
uint64_t ser = 0;
switch (sym.asset_num) {
case HIVE_ASSET_NUM_HIVE:
ser = OBSOLETE_SYMBOL_SER;
break;
case HIVE_ASSET_NUM_HBD:
ser = OBD_SYMBOL_SER;
break;
case HIVE_ASSET_NUM_VESTS:
ser = VESTS_SYMBOL_SER;
break;
default:
FC_ASSERT(false, "Cannot serialize unknown asset symbol");
}
pack(s, ser);
break;
}
case graphene::peerplays_sidechain::hive::asset_symbol_type::smt_nai_space:
pack(s, sym.asset_num);
break;
default:
FC_ASSERT(false, "Cannot serialize unknown asset symbol");
}
}
template <typename Stream>
void unpack(Stream &s, graphene::peerplays_sidechain::hive::asset_symbol_type &sym) {
std::cout << "##### UNPACK ###" << std::endl;
uint64_t ser = 0;
s.read((char *)&ser, 4);
switch (ser) {
case OBSOLETE_SYMBOL_SER & 0xFFFFFFFF:
s.read(((char *)&ser) + 4, 4);
FC_ASSERT(ser == OBSOLETE_SYMBOL_SER, "invalid asset bits");
sym.asset_num = HIVE_ASSET_NUM_HIVE;
break;
case OBD_SYMBOL_SER & 0xFFFFFFFF:
s.read(((char *)&ser) + 4, 4);
FC_ASSERT(ser == OBD_SYMBOL_SER, "invalid asset bits");
sym.asset_num = HIVE_ASSET_NUM_HBD;
break;
case VESTS_SYMBOL_SER & 0xFFFFFFFF:
s.read(((char *)&ser) + 4, 4);
FC_ASSERT(ser == VESTS_SYMBOL_SER, "invalid asset bits");
sym.asset_num = HIVE_ASSET_NUM_VESTS;
break;
default:
sym.asset_num = uint32_t(ser);
}
sym.validate();
}
} // namespace raw
inline void to_variant(const graphene::peerplays_sidechain::hive::asset_symbol_type &sym, fc::variant &var, uint32_t max_depth) {
try {
mutable_variant_object o;
o(ASSET_SYMBOL_NAI_KEY, sym.to_nai_string())(ASSET_SYMBOL_DECIMALS_KEY, sym.decimals());
var = std::move(o);
}
FC_CAPTURE_AND_RETHROW()
}
inline void from_variant(const fc::variant &var, graphene::peerplays_sidechain::hive::asset_symbol_type &sym, uint32_t max_depth) {
using graphene::peerplays_sidechain::hive::asset_symbol_type;
try {
FC_ASSERT(var.is_object(), "Asset symbol is expected to be an object.");
auto &o = var.get_object();
auto nai = o.find(ASSET_SYMBOL_NAI_KEY);
FC_ASSERT(nai != o.end(), "Expected key '${key}'.", ("key", ASSET_SYMBOL_NAI_KEY));
FC_ASSERT(nai->value().is_string(), "Expected a string type for value '${key}'.", ("key", ASSET_SYMBOL_NAI_KEY));
auto decimals = o.find(ASSET_SYMBOL_DECIMALS_KEY);
FC_ASSERT(decimals != o.end(), "Expected key '${key}'.", ("key", ASSET_SYMBOL_DECIMALS_KEY));
FC_ASSERT(decimals->value().is_uint64(), "Expected an unsigned integer type for value '${key}'.", ("key", ASSET_SYMBOL_DECIMALS_KEY));
FC_ASSERT(decimals->value().as_uint64() <= HIVE_ASSET_MAX_DECIMALS,
"Expected decimals to be less than or equal to ${num}", ("num", HIVE_ASSET_MAX_DECIMALS));
sym = asset_symbol_type::from_nai_string(nai->value().as_string().c_str(), decimals->value().as<uint8_t>(max_depth));
}
FC_CAPTURE_AND_RETHROW()
}
} // namespace fc

View file

@ -6,6 +6,7 @@
#include <fc/optional.hpp> #include <fc/optional.hpp>
#include <graphene/chain/protocol/types.hpp> #include <graphene/chain/protocol/types.hpp>
#include <graphene/peerplays_sidechain/hive/asset.hpp>
#include <graphene/peerplays_sidechain/hive/authority.hpp> #include <graphene/peerplays_sidechain/hive/authority.hpp>
#include <graphene/peerplays_sidechain/hive/types.hpp> #include <graphene/peerplays_sidechain/hive/types.hpp>
@ -15,7 +16,12 @@ struct vote_operation {};
struct comment_operation {}; struct comment_operation {};
struct transfer_operation {}; struct transfer_operation {
hive::account_name_type from;
hive::account_name_type to;
hive::asset amount;
std::string memo;
};
struct transfer_to_vesting_operation {}; struct transfer_to_vesting_operation {};
@ -44,7 +50,8 @@ struct account_update_operation {
FC_REFLECT(graphene::peerplays_sidechain::hive::vote_operation, ) FC_REFLECT(graphene::peerplays_sidechain::hive::vote_operation, )
FC_REFLECT(graphene::peerplays_sidechain::hive::comment_operation, ) FC_REFLECT(graphene::peerplays_sidechain::hive::comment_operation, )
FC_REFLECT(graphene::peerplays_sidechain::hive::transfer_operation, ) FC_REFLECT(graphene::peerplays_sidechain::hive::transfer_operation,
(from)(to)(amount)(memo))
FC_REFLECT(graphene::peerplays_sidechain::hive::transfer_to_vesting_operation, ) FC_REFLECT(graphene::peerplays_sidechain::hive::transfer_to_vesting_operation, )
FC_REFLECT(graphene::peerplays_sidechain::hive::withdraw_vesting_operation, ) FC_REFLECT(graphene::peerplays_sidechain::hive::withdraw_vesting_operation, )
FC_REFLECT(graphene::peerplays_sidechain::hive::limit_order_create_operation, ) FC_REFLECT(graphene::peerplays_sidechain::hive::limit_order_create_operation, )

View file

@ -18,7 +18,7 @@ typedef fc::ripemd160 block_id_type;
typedef fc::ripemd160 transaction_id_type; typedef fc::ripemd160 transaction_id_type;
typedef fc::sha256 digest_type; typedef fc::sha256 digest_type;
typedef fc::ecc::compact_signature signature_type; typedef fc::ecc::compact_signature signature_type;
//typedef safe<int64_t> share_type; typedef fc::safe<int64_t> share_type;
//typedef safe<uint64_t> ushare_type; //typedef safe<uint64_t> ushare_type;
//typedef uint16_t weight_type; //typedef uint16_t weight_type;
//typedef uint32_t contribution_id_type; //typedef uint32_t contribution_id_type;

View file

@ -0,0 +1,90 @@
//#pragma once
//#include <boost/container/flat_set.hpp>
//#include <cstdint>
//#include <fc/uint128.hpp>
//
//#include "asset_symbol.hpp"
//
//namespace fc {
//class variant;
//} // namespace fc
//
//namespace graphene { namespace peerplays_sidechain { namespace hive {
////template< typename Storage = fc::uint128 >
////class fixed_string_impl;
//
//class asset_symbol_type;
////class legacy_hive_asset_symbol_type;
////struct legacy_hive_asset;
//}}} // namespace graphene::peerplays_sidechain::hive
//
////using boost::container::flat_set;
////
////template< class Key >
////class flat_set_ex: public flat_set< Key >
////{
//// public:
////
//// flat_set_ex& operator=( const flat_set< Key >& obj )
//// {
//// flat_set< Key >::operator=( obj );
//// return *this;
//// }
////
//// flat_set_ex& operator=( const flat_set_ex& obj )
//// {
//// flat_set< Key >::operator=( obj );
//// return *this;
//// }
////};
//
//namespace fc {
//namespace raw {
//
////template<typename Stream, typename T>
////void pack( Stream& s, const flat_set_ex<T>& value );
////template<typename Stream, typename T>
////void unpack( Stream& s, flat_set_ex<T>& value, uint32_t depth = 0 );
//
////template< typename Stream, typename Storage >
////inline void pack( Stream& s, const hive::protocol::fixed_string_impl< Storage >& u );
////template< typename Stream, typename Storage >
////inline void unpack( Stream& s, hive::protocol::fixed_string_impl< Storage >& u, uint32_t depth = 0 );
//
//template <typename Stream>
//inline void pack(Stream &s, const graphene::peerplays_sidechain::hive::asset_symbol_type &sym, uint32_t depth = 0);
//template <typename Stream>
//inline void unpack(Stream &s, graphene::peerplays_sidechain::hive::asset_symbol_type &sym, uint32_t depth = 0);
//
////template< typename Stream >
////inline void pack( Stream& s, const hive::protocol::legacy_hive_asset_symbol_type& sym );
////template< typename Stream >
////inline void unpack( Stream& s, hive::protocol::legacy_hive_asset_symbol_type& sym, uint32_t depth = 0 );
//
//} // namespace raw
//
////template<typename T>
////void to_variant( const flat_set_ex<T>& var, variant& vo );
//
////template<typename T>
////void from_variant( const variant& var, flat_set_ex<T>& vo );
//
////template< typename Storage >
////inline void to_variant( const hive::protocol::fixed_string_impl< Storage >& s, fc::variant& v );
////template< typename Storage >
////inline void from_variant( const variant& v, hive::protocol::fixed_string_impl< Storage >& s );
//
//inline void to_variant(const graphene::peerplays_sidechain::hive::asset_symbol_type &sym, fc::variant &v, uint32_t max_depth);
//
////inline void from_variant( const fc::variant& v, hive::protocol::legacy_hive_asset& leg );
////inline void to_variant( const hive::protocol::legacy_hive_asset& leg, fc::variant& v );
//
////template<typename T> struct get_typename<flat_set_ex<T>>
////{
//// static const char* name() {
//// static std::string n = std::string("flat_set<") + get_typename< fc::flat_set<T> >::name() + ">";
//// return n.c_str();
//// }
////};
//
//} // namespace fc

View file

@ -168,10 +168,10 @@ void sidechain_net_handler::sidechain_event_data_received(const sidechain_event_
bool enable_peerplays_asset_deposits = false; bool enable_peerplays_asset_deposits = false;
#ifdef ENABLE_PEERPLAYS_ASSET_DEPOSITS #ifdef ENABLE_PEERPLAYS_ASSET_DEPOSITS
enable_peerplays_asset_deposits = (sed.sidechain == sidechain_type::peerplays) && //enable_peerplays_asset_deposits = (sed.sidechain == sidechain_type::peerplays) &&
(sed.sidechain_currency.compare("BTC") != 0) && // (sed.sidechain_currency.compare("BTC") != 0) &&
(sed.sidechain_currency.compare("HBD") != 0) && // (sed.sidechain_currency.compare("HBD") != 0) &&
(sed.sidechain_currency.compare("HIVE") != 0); // (sed.sidechain_currency.compare("HIVE") != 0);
#endif #endif
bool deposit_condition = (sed.peerplays_to == gpo.parameters.son_account()) && bool deposit_condition = (sed.peerplays_to == gpo.parameters.son_account()) &&
@ -180,10 +180,19 @@ void sidechain_net_handler::sidechain_event_data_received(const sidechain_event_
((sed.sidechain == sidechain_type::hive) && (sed.sidechain_currency.compare("HIVE") == 0)) || ((sed.sidechain == sidechain_type::hive) && (sed.sidechain_currency.compare("HIVE") == 0)) ||
enable_peerplays_asset_deposits); enable_peerplays_asset_deposits);
bool is_tracked_asset = false;
if (sed.sidechain == sidechain_type::peerplays) {
for (const auto &asset_id : tracked_assets) {
std::string asset_id_str = asset_id_to_string(asset_id);
if (sed.sidechain_currency == asset_id_str) {
is_tracked_asset = true;
break;
}
}
}
bool withdraw_condition = (sed.peerplays_to == gpo.parameters.son_account()) && (sed.sidechain == sidechain_type::peerplays) && bool withdraw_condition = (sed.peerplays_to == gpo.parameters.son_account()) && (sed.sidechain == sidechain_type::peerplays) &&
((sed.sidechain_currency.compare("BTC") == 0) || is_tracked_asset;
(sed.sidechain_currency.compare("HBD") == 0) ||
(sed.sidechain_currency.compare("HIVE") == 0));
// Deposit request // Deposit request
if (deposit_condition) { if (deposit_condition) {
@ -223,12 +232,29 @@ void sidechain_net_handler::sidechain_event_data_received(const sidechain_event_
// Withdrawal request // Withdrawal request
if (withdraw_condition) { if (withdraw_condition) {
// BTC Payout only (for now)
const auto &sidechain_addresses_idx = database.get_index_type<sidechain_address_index>().indices().get<by_account_and_sidechain_and_expires>(); const auto &sidechain_addresses_idx = database.get_index_type<sidechain_address_index>().indices().get<by_account_and_sidechain_and_expires>();
const auto &addr_itr = sidechain_addresses_idx.find(std::make_tuple(sed.peerplays_from, sidechain_type::bitcoin, time_point_sec::maximum())); const auto &addr_itr = sidechain_addresses_idx.find(std::make_tuple(sed.peerplays_from, sidechain, time_point_sec::maximum()));
if (addr_itr == sidechain_addresses_idx.end()) if (addr_itr == sidechain_addresses_idx.end())
return; return;
std::string withdraw_currency = "";
price withdraw_currency_price = {};
if (sed.sidechain_currency == asset_id_to_string(gpo.parameters.btc_asset())) {
withdraw_currency = "BTC";
withdraw_currency_price = database.get<asset_object>(database.get_global_properties().parameters.btc_asset()).options.core_exchange_rate;
}
if (sed.sidechain_currency == asset_id_to_string(gpo.parameters.hbd_asset())) {
withdraw_currency = "HBD";
withdraw_currency_price = database.get<asset_object>(database.get_global_properties().parameters.hbd_asset()).options.core_exchange_rate;
}
if (sed.sidechain_currency == asset_id_to_string(gpo.parameters.hive_asset())) {
withdraw_currency = "HIVE";
withdraw_currency_price = database.get<asset_object>(database.get_global_properties().parameters.hive_asset()).options.core_exchange_rate;
}
if (withdraw_currency.empty()) {
return;
}
for (son_id_type son_id : plugin.get_sons()) { for (son_id_type son_id : plugin.get_sons()) {
if (plugin.is_active_son(son_id)) { if (plugin.is_active_son(son_id)) {
@ -242,12 +268,10 @@ void sidechain_net_handler::sidechain_event_data_received(const sidechain_event_
op.peerplays_transaction_id = sed.sidechain_transaction_id; op.peerplays_transaction_id = sed.sidechain_transaction_id;
op.peerplays_from = sed.peerplays_from; op.peerplays_from = sed.peerplays_from;
op.peerplays_asset = sed.peerplays_asset; op.peerplays_asset = sed.peerplays_asset;
// BTC payout only (for now) op.withdraw_sidechain = sidechain;
op.withdraw_sidechain = sidechain_type::bitcoin;
op.withdraw_address = addr_itr->withdraw_address; op.withdraw_address = addr_itr->withdraw_address;
op.withdraw_currency = "BTC"; op.withdraw_currency = withdraw_currency;
price btc_price = database.get<asset_object>(database.get_global_properties().parameters.btc_asset()).options.core_exchange_rate; op.withdraw_amount = sed.peerplays_asset.amount * withdraw_currency_price.quote.amount / withdraw_currency_price.base.amount;
op.withdraw_amount = sed.peerplays_asset.amount * btc_price.quote.amount / btc_price.base.amount;
signed_transaction trx = database.create_signed_transaction(plugin.get_private_key(son_id), op); signed_transaction trx = database.create_signed_transaction(plugin.get_private_key(son_id), op);
try { try {
@ -593,6 +617,7 @@ void sidechain_net_handler::on_applied_block(const signed_block &b) {
operation_index = operation_index + 1; operation_index = operation_index + 1;
if (op.which() == operation::tag<transfer_operation>::value) { if (op.which() == operation::tag<transfer_operation>::value) {
transfer_operation transfer_op = op.get<transfer_operation>(); transfer_operation transfer_op = op.get<transfer_operation>();
if (transfer_op.to != plugin.database().get_global_properties().parameters.son_account()) { if (transfer_op.to != plugin.database().get_global_properties().parameters.son_account()) {
continue; continue;
} }

View file

@ -472,6 +472,78 @@ bool sidechain_net_handler_hive::process_deposit(const son_wallet_deposit_object
} }
bool sidechain_net_handler_hive::process_withdrawal(const son_wallet_withdraw_object &swwo) { bool sidechain_net_handler_hive::process_withdrawal(const son_wallet_withdraw_object &swwo) {
const chain::global_property_object &gpo = database.get_global_properties();
//=====
uint32_t asset_num = 0;
if (swwo.withdraw_currency == "HBD") {
asset_num = HIVE_ASSET_NUM_HBD;
}
if (swwo.withdraw_currency == "HIVE") {
asset_num = HIVE_ASSET_NUM_HIVE;
}
hive::transfer_operation t_op;
t_op.from = "son-account";
t_op.to = swwo.withdraw_address;
t_op.amount.amount = swwo.withdraw_amount;
t_op.amount.symbol = hive::asset_symbol_type::from_asset_num(asset_num);
t_op.memo = "";
std::string block_id_str = node_rpc_client->get_head_block_id();
hive::block_id_type head_block_id(block_id_str);
std::string head_block_time_str = node_rpc_client->get_head_block_time();
time_point head_block_time = fc::time_point_sec::from_iso_string(head_block_time_str);
hive::signed_transaction htrx;
htrx.set_reference_block(head_block_id);
htrx.set_expiration(head_block_time + fc::seconds(90));
htrx.operations.push_back(t_op);
ilog("TRX: ${htrx}", ("htrx", htrx));
std::stringstream ss;
fc::raw::pack(ss, htrx, 1000);
std::string tx_str = boost::algorithm::hex(ss.str());
if (tx_str.empty()) {
return false;
}
//=====
proposal_create_operation proposal_op;
proposal_op.fee_paying_account = plugin.get_current_son_object().son_account;
uint32_t lifetime = (gpo.parameters.block_interval * gpo.active_witnesses.size()) * 3;
proposal_op.expiration_time = time_point_sec(database.head_block_time().sec_since_epoch() + lifetime);
son_wallet_withdraw_process_operation swwp_op;
swwp_op.payer = gpo.parameters.son_account();
swwp_op.son_wallet_withdraw_id = swwo.id;
proposal_op.proposed_ops.emplace_back(swwp_op);
sidechain_transaction_create_operation stc_op;
stc_op.payer = gpo.parameters.son_account();
stc_op.object_id = swwo.id;
stc_op.sidechain = sidechain;
stc_op.transaction = tx_str;
stc_op.signers = gpo.active_sons;
proposal_op.proposed_ops.emplace_back(stc_op);
signed_transaction trx = database.create_signed_transaction(plugin.get_private_key(plugin.get_current_son_id()), proposal_op);
try {
trx.validate();
database.push_transaction(trx, database::validation_steps::skip_block_size_check);
if (plugin.app().p2p_node())
plugin.app().p2p_node()->broadcast(net::trx_message(trx));
return true;
} catch (fc::exception &e) {
elog("Sending proposal for deposit sidechain transaction create operation failed with exception ${e}", ("e", e.what()));
return false;
}
return false; return false;
} }
@ -635,6 +707,42 @@ void sidechain_net_handler_hive::handle_event(const std::string &event_data) {
} }
} }
} }
//==========
{
hive::transfer_operation t_op;
t_op.from = "sonaccount01";
t_op.to = "account05";
t_op.amount.amount = 1000;
t_op.amount.symbol = hive::asset_symbol_type::from_asset_num(HIVE_ASSET_NUM_HIVE);
t_op.memo = "";
std::string block_id_str = node_rpc_client->get_head_block_id();
hive::block_id_type head_block_id(block_id_str);
//hive::block_id_type head_block_id("000087723a5513e7cc0f03a71bf05a5b7b36102f");
std::string head_block_time_str = node_rpc_client->get_head_block_time();
time_point head_block_time = fc::time_point_sec::from_iso_string(head_block_time_str);
//time_point head_block_time = fc::time_point_sec::from_iso_string("2021-04-23T10:38:03");
hive::signed_transaction htrx;
htrx.set_reference_block(head_block_id);
htrx.set_expiration(head_block_time + fc::seconds(30));
htrx.operations.push_back(t_op);
ilog("TRX: ${htrx}", ("htrx", htrx));
std::string chain_id_str = node_rpc_client->get_chain_id();
const hive::chain_id_type chain_id(chain_id_str);
fc::optional<fc::ecc::private_key> privkey = graphene::utilities::wif_to_key(get_private_key("sonaccount01"));
htrx.sign(*privkey, chain_id);
std::string params = fc::json::to_string(htrx);
ilog("HTRX: ${htrx}", ("htrx", params));
node_rpc_client->network_broadcast_api_broadcast_transaction(params);
}
//==========
} }
}} // namespace graphene::peerplays_sidechain }} // namespace graphene::peerplays_sidechain