Skip to content

Commit

Permalink
Refactor peg-in witness construction to it's own function
Browse files Browse the repository at this point in the history
Also changes to Use CVectorWriter instead of casting for peg-in value serialization
  • Loading branch information
achow101 committed Oct 14, 2019
1 parent 5af17a4 commit a90d152
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 26 deletions.
42 changes: 42 additions & 0 deletions src/pegins.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -496,3 +496,45 @@ std::vector<std::pair<CScript, CScript>> GetValidFedpegScripts(const CBlockIndex
fedpegscripts.resize(std::min(fedpegscripts.size(), params.total_valid_epochs));
return fedpegscripts;
}

template<typename T_tx_ref, typename T_merkle_block>
CScriptWitness CreatePeginWitnessInner(const CAmount& value, const CAsset& asset, const uint256& genesis_hash, const CScript& claim_script, const T_tx_ref& tx_ref, const T_merkle_block& merkle_block)
{
std::vector<unsigned char> value_bytes;
CVectorWriter ss_val(0, 0, value_bytes, 0);
try {
ss_val << value;
} catch (...) {
throw std::ios_base::failure("Amount serialization is invalid.");
}

// Strip witness data for proof inclusion since only TXID-covered fields matters
CDataStream ss_tx(SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS);
ss_tx << tx_ref;
std::vector<unsigned char> tx_data_stripped(ss_tx.begin(), ss_tx.end());

// Serialize merkle block
CDataStream ss_txout_proof(SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS);
ss_txout_proof << merkle_block;
std::vector<unsigned char> txout_proof_bytes(ss_txout_proof.begin(), ss_txout_proof.end());

// Construct pegin proof
CScriptWitness pegin_witness;
std::vector<std::vector<unsigned char> >& stack = pegin_witness.stack;
stack.push_back(value_bytes);
stack.push_back(std::vector<unsigned char>(asset.begin(), asset.end()));
stack.push_back(std::vector<unsigned char>(genesis_hash.begin(), genesis_hash.end()));
stack.push_back(std::vector<unsigned char>(claim_script.begin(), claim_script.end()));
stack.push_back(tx_data_stripped);
stack.push_back(txout_proof_bytes);
return pegin_witness;
}

CScriptWitness CreatePeginWitness(const CAmount& value, const CAsset& asset, const uint256& genesis_hash, const CScript& claim_script, const CTransactionRef& tx_ref, const CMerkleBlock& merkle_block)
{
return CreatePeginWitnessInner(value, asset, genesis_hash, claim_script, tx_ref, merkle_block);
}
CScriptWitness CreatePeginWitness(const CAmount& value, const CAsset& asset, const uint256& genesis_hash, const CScript& claim_script, const Sidechain::Bitcoin::CTransactionRef& tx_ref, const Sidechain::Bitcoin::CMerkleBlock& merkle_block)
{
return CreatePeginWitnessInner(value, asset, genesis_hash, claim_script, tx_ref, merkle_block);
}
7 changes: 7 additions & 0 deletions src/pegins.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@

#include <amount.h>
#include <consensus/params.h>
#include <merkleblock.h>
#include <primitives/bitcoin/transaction.h>
#include <primitives/bitcoin/merkleblock.h>
#include <primitives/transaction.h>
#include <script/script.h>
#include <chain.h>
Expand Down Expand Up @@ -38,4 +40,9 @@ bool MatchLiquidWatchman(const CScript& script);
* scriptPubKey for the script, the second is the witnessScript. */
std::vector<std::pair<CScript, CScript>> GetValidFedpegScripts(const CBlockIndex* pblockindex, const Consensus::Params& params, bool nextblock_validation);

/** Create the peg-in witness stack */
CScriptWitness CreatePeginWitness(const CAmount& value, const CAsset& asset, const uint256& genesis_hash, const CScript& claim_script, const CTransactionRef& tx_ref, const CMerkleBlock& merkle_block);
CScriptWitness CreatePeginWitness(const CAmount& value, const CAsset& asset, const uint256& genesis_hash, const CScript& claim_script, const Sidechain::Bitcoin::CTransactionRef& tx_ref, const Sidechain::Bitcoin::CMerkleBlock& merkle_block);


#endif // BITCOIN_PEGINS_H
27 changes: 1 addition & 26 deletions src/wallet/rpcwallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5530,19 +5530,6 @@ static UniValue createrawpegin(const JSONRPCRequest& request, T_tx_ref& txBTCRef
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Amounts to pegin must be explicit and asset must be %s", Params().GetConsensus().parent_pegged_asset.GetHex()));
}

CDataStream stream(0, 0);
try {
stream << value;
} catch (...) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Amount serialization is invalid.");
}
// Need to reinterpret bytes as unsigned chars before adding to witness
char* buf = stream.data();
unsigned char* membuf = reinterpret_cast<unsigned char*>(buf);
std::vector<unsigned char> value_bytes(membuf, membuf + stream.size());

uint256 genesisBlockHash = Params().ParentGenesisBlockHash();

// Manually construct peg-in transaction, sign it, and send it off.
// Decrement the output value as much as needed given the total vsize to
// pay the fees.
Expand All @@ -5566,20 +5553,8 @@ static UniValue createrawpegin(const JSONRPCRequest& request, T_tx_ref& txBTCRef
mtx.vout.push_back(CTxOut(Params().GetConsensus().pegged_asset, value, GetScriptForDestination(wpkhash)));
mtx.vout.push_back(CTxOut(Params().GetConsensus().pegged_asset, 0, CScript()));

// Strip witness data for proof inclusion since only TXID-covered fields matters
CDataStream ssTxBack(SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS);
ssTxBack << txBTC;
std::vector<unsigned char> tx_data_stripped(ssTxBack.begin(), ssTxBack.end());

// Construct pegin proof
CScriptWitness pegin_witness;
std::vector<std::vector<unsigned char> >& stack = pegin_witness.stack;
stack.push_back(value_bytes);
stack.push_back(std::vector<unsigned char>(Params().GetConsensus().pegged_asset.begin(), Params().GetConsensus().pegged_asset.end()));
stack.push_back(std::vector<unsigned char>(genesisBlockHash.begin(), genesisBlockHash.end()));
stack.push_back(std::vector<unsigned char>(witness_script.begin(), witness_script.end()));
stack.push_back(tx_data_stripped);
stack.push_back(txOutProofData);
CScriptWitness pegin_witness = CreatePeginWitness(value, Params().GetConsensus().pegged_asset, Params().ParentGenesisBlockHash(), witness_script, txBTCRef, merkleBlock);

// Peg-in witness isn't valid, even though the block header is(without depth check)
// We re-check depth before returning with more descriptive result
Expand Down

0 comments on commit a90d152

Please sign in to comment.