Use wallet to find compatible pegin sidechain_address by default during claimpegin

This commit is contained in:
Gregory Sanders 2017-05-31 12:14:54 -04:00
parent 098436fcb2
commit dfc6c6483f
2 changed files with 93 additions and 53 deletions

View file

@ -1,6 +1,6 @@
#!/usr/bin/env python2
from test_framework.authproxy import AuthServiceProxy
from test_framework.authproxy import AuthServiceProxy, JSONRPCException
import os
import random
import sys
@ -38,6 +38,7 @@ with open(os.path.join(bitcoin_datadir, "bitcoin.conf"), 'w') as f:
f.write("testnet=0\n")
f.write("txindex=1\n")
f.write("daemon=1\n")
f.write("listen=0\n")
with open(os.path.join(sidechain_datadir, "elements.conf"), 'w') as f:
f.write("regtest=1\n")
@ -56,49 +57,67 @@ with open(os.path.join(sidechain_datadir, "elements.conf"), 'w') as f:
f.write("mainchainrpcpassword="+bitcoin_pass+"\n")
f.write("validatepegin=1\n")
f.write("validatepegout=0\n")
f.write("listen=0\n")
# Start daemons
print("Starting daemons at "+bitcoin_datadir+" and "+sidechain_datadir)
bitcoindstart = sys.argv[1]+"/bitcoind -datadir="+bitcoin_datadir
subprocess.Popen(bitcoindstart.split(), stdout=subprocess.PIPE)
try:
sidechainstart = sys.argv[2]+"/elementsd -datadir="+sidechain_datadir
subprocess.Popen(sidechainstart.split(), stdout=subprocess.PIPE)
# Start daemons
print("Starting daemons at "+bitcoin_datadir+" and "+sidechain_datadir)
bitcoindstart = sys.argv[1]+"/bitcoind -datadir="+bitcoin_datadir
subprocess.Popen(bitcoindstart.split(), stdout=subprocess.PIPE)
print("Daemons started")
time.sleep(2)
sidechainstart = sys.argv[2]+"/elementsd -datadir="+sidechain_datadir
subprocess.Popen(sidechainstart.split(), stdout=subprocess.PIPE)
bitcoin = AuthServiceProxy("http://bitcoinrpc:"+bitcoin_pass+"@127.0.0.1:"+str(bitcoin_port))
sidechain = AuthServiceProxy("http://sidechainrpc:"+sidechain_pass+"@127.0.0.1:"+str(sidechain_port))
print("Daemons started, making blocks to get funds")
print("Daemons started")
time.sleep(2)
bitcoin.generate(101)
sidechain.generate(101)
bitcoin = AuthServiceProxy("http://bitcoinrpc:"+bitcoin_pass+"@127.0.0.1:"+str(bitcoin_port))
sidechain = AuthServiceProxy("http://sidechainrpc:"+sidechain_pass+"@127.0.0.1:"+str(sidechain_port))
print("Daemons started, making blocks to get funds")
addr = bitcoin.getnewaddress()
bitcoin.generate(101)
sidechain.generate(101)
# Lockup some funds to unlock later
sidechain.sendtomainchain(addr, 50)
sidechain.generate(101)
addr = bitcoin.getnewaddress()
addrs = sidechain.getpeginaddress()
txid = bitcoin.sendtoaddress(addrs["mainchain_address"], 49)
bitcoin.generate(10)
proof = bitcoin.gettxoutproof([txid])
raw = bitcoin.getrawtransaction(txid)
# Lockup some funds to unlock later
sidechain.sendtomainchain(addr, 50)
sidechain.generate(101)
print("Attempting peg-in")
pegtxid = sidechain.claimpegin(addrs["sidechain_address"], raw, proof)
sidechain.generate(1)
addrs = sidechain.getpeginaddress()
txid = bitcoin.sendtoaddress(addrs["mainchain_address"], 49)
bitcoin.generate(10)
proof = bitcoin.gettxoutproof([txid])
raw = bitcoin.getrawtransaction(txid)
tx = sidechain.gettransaction(pegtxid)
print("Attempting peg-in")
if "confirmations" in tx and tx["confirmations"] > 0:
print("Peg-in is confirmed: Success!")
else:
print("Peg-in has failed.")
# Should fail due to non-matching address
try:
pegtxid = sidechain.claimpegin(raw, proof, sidechain.getnewaddress())
raise Exception("Peg-in with non-matching address should fail.")
except JSONRPCException:
pass
# Should succeed via wallet lookup for address match
pegtxid = sidechain.claimpegin(raw, proof)
sidechain.generate(1)
tx = sidechain.gettransaction(pegtxid)
if "confirmations" in tx and tx["confirmations"] > 0:
print("Peg-in is confirmed: Success!")
else:
raise Exception("Peg-in confirmation has failed.")
except JSONRPCException as e:
print("Pegging testing failed, aborting:")
print(e.error)
except Exception as e:
print("Pegging testing failed, aborting:")
print(e)
print("Stopping daemons and cleaning up")
bitcoin.stop()

View file

@ -3175,19 +3175,32 @@ UniValue sendtomainchain(const UniValue& params, bool fHelp)
extern UniValue sendrawtransaction(const UniValue& params, bool fHelp);
unsigned int GetPeginTxnOutputIndex(const Sidechain::Bitcoin::CTransaction& txn, const CBitcoinAddress& sidechainAddress, unsigned char* fullcontract)
{
unsigned char nonce[16];
memset(nonce, 0, sizeof(nonce));
unsigned int nOut = 0;
//Call contracthashtool
CScript mainchain_script = GetScriptForDestination(calculate_contract(Params().GetConsensus().fedpegScript, sidechainAddress, &nonce[0], fullcontract));
for (; nOut < txn.vout.size(); nOut++)
if (txn.vout[nOut].scriptPubKey == mainchain_script)
break;
return nOut;
}
UniValue claimpegin(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 3)
if (fHelp || params.size() < 2 || params.size() > 3)
throw runtime_error(
"claimpegin sidechainaddress bitcoinTx txoutproof\n"
"claimpegin bitcoinTx txoutproof ( sidechain_address )\n"
"\nClaim coins from the main chain by creating a withdraw transaction with the necessary metadata after the corresponding Bitcoin transaction.\n"
"Note that the transaction will not be mined or relayed unless it is buried at least 10 blocks deep.\n"
"Note that the transaction will not be relayed unless it is buried at least 102 blocks deep.\n"
"If a transaction is not relayed it may require manual addition to a functionary mempool in order for it to be mined.\n"
"\nArguments:\n"
"1. \"sidechain_address\" (string, required) The sidechain_address address generated by getpeginaddress\n"
"2. \"bitcoinTx\" (string, required) The raw bitcoin transaction (in hex) depositing bitcoin to the mainchain_address generated by getpeginaddress\n"
"3. \"txoutproof\" (string, required) A rawtxoutproof (in hex) generated by bitcoind's `gettxoutproof` containing a proof of only bitcoinTx\n"
"1. \"bitcoinTx\" (string, required) The raw bitcoin transaction (in hex) depositing bitcoin to the mainchain_address generated by getpeginaddress\n"
"2. \"txoutproof\" (string, required) A rawtxoutproof (in hex) generated by bitcoind's `gettxoutproof` containing a proof of only bitcoinTx\n"
"3. \"sidechain_address\" (string, optional) The sidechain_address generated by getpeginaddress. Only needed if not in wallet.\n"
"\nResult:\n"
"\"txid\" (string) Txid of the resulting sidechain transaction\n"
"\nExamples:\n"
@ -3200,14 +3213,12 @@ UniValue claimpegin(const UniValue& params, bool fHelp)
throw JSONRPCError(RPC_WALLET_ERROR, "Peg-ins cannot be completed during initial sync or reindexing.");
}
CBitcoinAddress sidechainAddress(params[0].get_str());
if (!sidechainAddress.IsValid())
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid sidechain_address");
if (!IsHex(params[0].get_str()) || !IsHex(params[1].get_str())) {
throw JSONRPCError(RPC_TYPE_ERROR, "the first two arguments must be hex strings");
}
if (!IsHex(params[1].get_str()) || !IsHex(params[2].get_str()))
throw JSONRPCError(RPC_TYPE_ERROR, "the last two arguments must be hex strings");
std::vector<unsigned char> txData = ParseHex(params[1].get_str());
std::vector<unsigned char> txData = ParseHex(params[0].get_str());
CDataStream ssTx(txData, SER_NETWORK, PROTOCOL_VERSION);
Sidechain::Bitcoin::CTransaction txBTC;
try {
@ -3217,7 +3228,7 @@ UniValue claimpegin(const UniValue& params, bool fHelp)
throw JSONRPCError(RPC_TYPE_ERROR, "The included bitcoinTx is malformed. Are you sure that is the whole string?");
}
std::vector<unsigned char> txOutProofData = ParseHex(params[2].get_str());
std::vector<unsigned char> txOutProofData = ParseHex(params[1].get_str());
CDataStream ssTxOutProof(txOutProofData, SER_NETWORK, PROTOCOL_VERSION);
Sidechain::Bitcoin::CMerkleBlock merkleBlock;
try {
@ -3237,16 +3248,26 @@ UniValue claimpegin(const UniValue& params, bool fHelp)
if (txHashes.size() != 1 || txHashes[0] != txBTC.GetHash())
throw JSONRPCError(RPC_INVALID_PARAMETER, "The txoutproof must contain bitcoinTx and only bitcoinTx");
//Call contracthashtool
unsigned char nonce[16];
memset(nonce, 0, sizeof(nonce));
unsigned char fullcontract[40];
CScript mainchain_script = GetScriptForDestination(calculate_contract(Params().GetConsensus().fedpegScript, sidechainAddress, &nonce[0], fullcontract));
unsigned int nOut = 0;
for (; nOut < txBTC.vout.size(); nOut++)
if (txBTC.vout[nOut].scriptPubKey == mainchain_script)
break;
unsigned char fullcontract[40];
CBitcoinAddress sidechainAddress;
if (params.size() > 2) {
sidechainAddress = CBitcoinAddress(params[2].get_str());
if (!sidechainAddress.IsValid()) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Given sidechain_address is invalid.");
}
nOut = GetPeginTxnOutputIndex(txBTC, sidechainAddress, fullcontract);
}
else {
// Look through address book for pegin contract value
for (std::map<CTxDestination, CAddressBookData>::const_iterator iter = pwalletMain->mapAddressBook.begin(); iter != pwalletMain->mapAddressBook.end(); ++iter) {
sidechainAddress = CBitcoinAddress(iter->first);
nOut = GetPeginTxnOutputIndex(txBTC, sidechainAddress, fullcontract);
if (nOut != txBTC.vout.size()) {
break;
}
}
}
if (nOut == txBTC.vout.size())
throw JSONRPCError(RPC_INVALID_PARAMETER, "Failed to find output in bitcoinTx to the mainchain_address from getpeginaddress");
CAmount value = txBTC.vout[nOut].nValue;