Compare commits
2 commits
master
...
SON-215_Si
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
182fa180e3 | ||
|
|
2a2440acf9 |
5 changed files with 91 additions and 10 deletions
|
|
@ -27,6 +27,7 @@ namespace graphene { namespace chain {
|
|||
struct fee_parameters_type { uint64_t fee = 0; };
|
||||
|
||||
asset fee;
|
||||
son_id_type signer;
|
||||
account_id_type payer;
|
||||
|
||||
sidechain_transaction_id_type sidechain_transaction_id;
|
||||
|
|
@ -73,7 +74,7 @@ FC_REFLECT( graphene::chain::sidechain_transaction_create_operation, (fee)(payer
|
|||
(signers) )
|
||||
|
||||
FC_REFLECT( graphene::chain::sidechain_transaction_sign_operation::fee_parameters_type, (fee) )
|
||||
FC_REFLECT( graphene::chain::sidechain_transaction_sign_operation, (fee)(payer)
|
||||
FC_REFLECT( graphene::chain::sidechain_transaction_sign_operation, (fee)(signer)(payer)
|
||||
(sidechain_transaction_id)
|
||||
(signature) )
|
||||
|
||||
|
|
|
|||
|
|
@ -49,13 +49,14 @@ object_id_type sidechain_transaction_create_evaluator::do_apply(const sidechain_
|
|||
void_result sidechain_transaction_sign_evaluator::do_evaluate(const sidechain_transaction_sign_operation &op)
|
||||
{ try {
|
||||
FC_ASSERT(db().head_block_time() >= HARDFORK_SON_TIME, "Not allowed until SON HARDFORK"); // can be removed after HF date pass
|
||||
FC_ASSERT( op.payer == db().get_global_properties().parameters.son_account(), "SON paying account must be set as payer." );
|
||||
|
||||
const auto &sto_idx = db().get_index_type<sidechain_transaction_index>().indices().get<by_id>();
|
||||
const auto &sto_obj = sto_idx.find(op.sidechain_transaction_id);
|
||||
FC_ASSERT(sto_obj != sto_idx.end(), "Sidechain transaction object not found");
|
||||
|
||||
const auto &son_idx = db().get_index_type<son_index>().indices().get<by_account>();
|
||||
const auto &son_obj = son_idx.find(op.payer);
|
||||
const auto &son_idx = db().get_index_type<son_index>().indices().get<by_id>();
|
||||
const auto &son_obj = son_idx.find(op.signer);
|
||||
FC_ASSERT(son_obj != son_idx.end(), "SON object not found");
|
||||
|
||||
bool expected = false;
|
||||
|
|
@ -76,8 +77,8 @@ object_id_type sidechain_transaction_sign_evaluator::do_apply(const sidechain_tr
|
|||
const auto &sto_idx = db().get_index_type<sidechain_transaction_index>().indices().get<by_id>();
|
||||
auto sto_obj = sto_idx.find(op.sidechain_transaction_id);
|
||||
|
||||
const auto &son_idx = db().get_index_type<son_index>().indices().get<by_account>();
|
||||
auto son_obj = son_idx.find(op.payer);
|
||||
const auto &son_idx = db().get_index_type<son_index>().indices().get<by_id>();
|
||||
auto son_obj = son_idx.find(op.signer);
|
||||
|
||||
db().modify(*sto_obj, [&](sidechain_transaction_object &sto) {
|
||||
for (size_t i = 0; i < sto.signatures.size(); i++) {
|
||||
|
|
|
|||
|
|
@ -25,7 +25,8 @@ public:
|
|||
std::vector<std::string> get_sidechain_withdraw_addresses();
|
||||
std::string get_private_key(std::string public_key);
|
||||
|
||||
bool proposal_exists(int32_t operation_tag, const object_id_type &object_id);
|
||||
bool proposal_exists(int32_t operation_tag, const object_id_type &object_id, boost::optional<chain::operation &> proposal_op = boost::none);
|
||||
bool signer_expected(const sidechain_transaction_object &sto, son_id_type signer);
|
||||
bool approve_proposal(const proposal_id_type &proposal_id, const son_id_type &son_id);
|
||||
void sidechain_event_data_received(const sidechain_event_data &sed);
|
||||
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ std::string sidechain_net_handler::get_private_key(std::string public_key) {
|
|||
return std::string();
|
||||
}
|
||||
|
||||
bool sidechain_net_handler::proposal_exists(int32_t operation_tag, const object_id_type &object_id) {
|
||||
bool sidechain_net_handler::proposal_exists(int32_t operation_tag, const object_id_type &object_id, boost::optional<chain::operation &> proposal_op) {
|
||||
|
||||
bool result = false;
|
||||
|
||||
|
|
@ -92,6 +92,16 @@ bool sidechain_net_handler::proposal_exists(int32_t operation_tag, const object_
|
|||
break;
|
||||
}
|
||||
|
||||
case chain::operation::tag<chain::sidechain_transaction_sign_operation>::value: {
|
||||
if (proposal_op) {
|
||||
chain::operation proposal_op_obj_0 = proposal_op.get();
|
||||
result = ((proposal_op_obj_0.get<sidechain_transaction_sign_operation>().sidechain_transaction_id == op_obj_idx_0.get<sidechain_transaction_sign_operation>().sidechain_transaction_id) &&
|
||||
(proposal_op_obj_0.get<sidechain_transaction_sign_operation>().signer == op_obj_idx_0.get<sidechain_transaction_sign_operation>().signer) &&
|
||||
(proposal_op_obj_0.get<sidechain_transaction_sign_operation>().signature == op_obj_idx_0.get<sidechain_transaction_sign_operation>().signature));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
|
@ -104,6 +114,16 @@ bool sidechain_net_handler::proposal_exists(int32_t operation_tag, const object_
|
|||
return result;
|
||||
}
|
||||
|
||||
bool sidechain_net_handler::signer_expected(const sidechain_transaction_object &sto, son_id_type signer) {
|
||||
bool expected = false;
|
||||
for (auto signature : sto.signatures) {
|
||||
if (signature.first == signer) {
|
||||
expected = signature.second.empty();
|
||||
}
|
||||
}
|
||||
return expected;
|
||||
}
|
||||
|
||||
bool sidechain_net_handler::approve_proposal(const proposal_id_type &proposal_id, const son_id_type &son_id) {
|
||||
|
||||
proposal_update_operation op;
|
||||
|
|
@ -296,6 +316,17 @@ void sidechain_net_handler::process_proposals() {
|
|||
break;
|
||||
}
|
||||
|
||||
case chain::operation::tag<chain::sidechain_transaction_sign_operation>::value: {
|
||||
sidechain_transaction_id_type st_id = op_obj_idx_0.get<sidechain_transaction_sign_operation>().sidechain_transaction_id;
|
||||
son_id_type signer = op_obj_idx_0.get<sidechain_transaction_sign_operation>().signer;
|
||||
const auto &idx = database.get_index_type<sidechain_transaction_index>().indices().get<by_id>();
|
||||
const auto sto = idx.find(st_id);
|
||||
if (sto != idx.end()) {
|
||||
should_process = ((sto->sidechain == sidechain) && (sto->status == sidechain_transaction_status::valid) && signer_expected(*sto, signer));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case chain::operation::tag<chain::sidechain_transaction_settle_operation>::value: {
|
||||
sidechain_transaction_id_type st_id = op_obj_idx_0.get<sidechain_transaction_settle_operation>().sidechain_transaction_id;
|
||||
const auto &idx = database.get_index_type<sidechain_transaction_index>().indices().get<by_id>();
|
||||
|
|
@ -381,7 +412,7 @@ void sidechain_net_handler::process_sidechain_transactions() {
|
|||
const auto &idx_range = idx.equal_range(std::make_tuple(sidechain, sidechain_transaction_status::valid));
|
||||
|
||||
std::for_each(idx_range.first, idx_range.second, [&](const sidechain_transaction_object &sto) {
|
||||
if (sto.id == object_id_type(0, 0, 0)) {
|
||||
if ((sto.id == object_id_type(0, 0, 0)) || !signer_expected(sto, plugin.get_current_son_id())) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -394,12 +425,24 @@ void sidechain_net_handler::process_sidechain_transactions() {
|
|||
return;
|
||||
}
|
||||
|
||||
const chain::global_property_object &gpo = database.get_global_properties();
|
||||
sidechain_transaction_sign_operation sts_op;
|
||||
sts_op.payer = plugin.get_current_son_object().son_account;
|
||||
sts_op.signer = plugin.get_current_son_id();
|
||||
sts_op.payer = gpo.parameters.son_account();
|
||||
sts_op.sidechain_transaction_id = sto.id;
|
||||
sts_op.signature = processed_sidechain_tx;
|
||||
|
||||
signed_transaction trx = database.create_signed_transaction(plugin.get_private_key(plugin.get_current_son_id()), sts_op);
|
||||
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);
|
||||
proposal_op.proposed_ops.emplace_back(sts_op);
|
||||
|
||||
if (proposal_exists(chain::operation::tag<chain::sidechain_transaction_sign_operation>::value, sto.id, proposal_op.proposed_ops[0].op)) {
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -1151,6 +1151,41 @@ bool sidechain_net_handler_bitcoin::process_proposal(const proposal_object &po)
|
|||
break;
|
||||
}
|
||||
|
||||
case chain::operation::tag<chain::sidechain_transaction_sign_operation>::value: {
|
||||
using namespace bitcoin;
|
||||
should_approve = true;
|
||||
son_id_type signer = op_obj_idx_0.get<sidechain_transaction_sign_operation>().signer;
|
||||
std::string signature = op_obj_idx_0.get<sidechain_transaction_sign_operation>().signature;
|
||||
sidechain_transaction_id_type sidechain_transaction_id = op_obj_idx_0.get<sidechain_transaction_sign_operation>().sidechain_transaction_id;
|
||||
std::vector<uint64_t> in_amounts;
|
||||
std::string tx_hex;
|
||||
std::string redeem_script;
|
||||
const auto &st_idx = database.get_index_type<sidechain_transaction_index>().indices().get<by_id>();
|
||||
const auto sto = st_idx.find(sidechain_transaction_id);
|
||||
if (sto == st_idx.end()) {
|
||||
should_approve = false;
|
||||
break;
|
||||
}
|
||||
|
||||
const auto &s_idx = database.get_index_type<son_index>().indices().get<by_id>();
|
||||
const auto son = s_idx.find(signer);
|
||||
if (son == s_idx.end()) {
|
||||
should_approve = false;
|
||||
break;
|
||||
}
|
||||
|
||||
read_transaction_data(sto->transaction, tx_hex, in_amounts, redeem_script);
|
||||
bitcoin_transaction tx = unpack(parse_hex(tx_hex));
|
||||
bitcoin::bytes pubkey = parse_hex(son->sidechain_public_keys.at(sidechain_type::bitcoin));
|
||||
vector<bitcoin::bytes> sigs = read_byte_arrays_from_string(signature);
|
||||
for (size_t i = 0; i < tx.vin.size(); i++) {
|
||||
const auto &sighash_str = get_signature_hash(tx, parse_hex(redeem_script), static_cast<int64_t>(in_amounts[i]), i, 1, true).str();
|
||||
const bitcoin::bytes &sighash_hex = parse_hex(sighash_str);
|
||||
should_approve = should_approve && verify_sig(sigs[i], pubkey, sighash_hex, btc_context());
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case chain::operation::tag<chain::sidechain_transaction_settle_operation>::value: {
|
||||
should_approve = true;
|
||||
break;
|
||||
|
|
|
|||
Loading…
Reference in a new issue