Skip to content

Commit

Permalink
Merge #475: rawreissuance rpc
Browse files Browse the repository at this point in the history
bc257db f'rawreissueasset functional tests' (Gregory Sanders)
181d099 rawreissueasset functional tests (Gregory Sanders)
21cb8aa rawreissuance rpc (Gregory Sanders)
1251ecd fixup rawissueasset help comment (Gregory Sanders)
23371af add confidential_key explanation in validateaddress help (Gregory Sanders)
c579f4b Correct how wallet blinding logic detects which token id to use based on blinding keys (Gregory Sanders)
fff2dcc blindrawtransaction: Have blind_issuances parse correctly from command line (Gregory Sanders)
756bdc0 issueasset_base: Push 0-value value to issuance field if blinding (Gregory Sanders)
  • Loading branch information
instagibbs committed Dec 17, 2018
2 parents 71c69c3 + bc257db commit 5467be3
Show file tree
Hide file tree
Showing 5 changed files with 261 additions and 12 deletions.
119 changes: 116 additions & 3 deletions qa/rpc-tests/feature_issuance.py
Original file line number Diff line number Diff line change
Expand Up @@ -248,8 +248,8 @@ def run_test(self):
self.nodes[1].generate(1)
raw_tx = self.nodes[0].createrawtransaction([], {nonblind_addr:self.nodes[0].getbalance()['bitcoin']-1})
funded_tx = self.nodes[0].fundrawtransaction(raw_tx)['hex']
issued_tx = self.nodes[2].rawissueasset(funded_tx, [{"asset_amount":1, "asset_address":nonblind_addr}])[0]["hex"]
blind_tx = self.nodes[0].blindrawtransaction(issued_tx)
issued_tx = self.nodes[2].rawissueasset(funded_tx, [{"asset_amount":1, "asset_address":nonblind_addr, "blind":False}])[0]["hex"]
blind_tx = self.nodes[0].blindrawtransaction(issued_tx) # This is a no-op
signed_tx = self.nodes[0].signrawtransaction(blind_tx)
assert_raises_jsonrpc(-26, "", self.nodes[0].sendrawtransaction, signed_tx['hex'])

Expand Down Expand Up @@ -303,13 +303,126 @@ def run_test(self):

# Finally, append an issuance on top of an already-"issued" raw tx
# Same contract, different utxo being spent results in new asset type
issued_tx = self.nodes[2].rawissueasset(issued_tx, [{"asset_amount":1, "asset_address":nonblind_addr, "contract":"deadbeee"*8}])[0]["hex"]
# We also create a reissuance token to test reissuance with contract hash
issued_tx = self.nodes[2].rawissueasset(issued_tx, [{"asset_amount":1, "asset_address":nonblind_addr, "token_address":nonblind_addr, "contract":"deadbeee"*8}])[0]["hex"]
decode_tx = self.nodes[0].decoderawtransaction(issued_tx)
id_set.add(decode_tx["vin"][1]["issuance"]["asset"])
assert_equal(len(id_set), 4)
# This issuance should not have changed
id_set.add(decode_tx["vin"][0]["issuance"]["asset"])
assert_equal(len(id_set), 4)

print("Raw reissuance tests")
issued_asset = self.nodes[0].issueasset(0, 1)
self.nodes[0].generate(1)
utxo_info = None
# Find info about the token output using wallet
for utxo in self.nodes[0].listunspent():
if utxo["asset"] == issued_asset["token"]:
utxo_info = utxo
break
assert(utxo_info is not None)

issued_address = self.nodes[0].getnewaddress()
# Create transaction spending the reissuance token
raw_tx = self.nodes[0].createrawtransaction([], {issued_address:Decimal('0.00000001')}, 0, {issued_address:issued_asset["token"]})
funded_tx = self.nodes[0].fundrawtransaction(raw_tx)['hex']
# Find the reissuance input
reissuance_index = -1
for i, tx_input in enumerate(self.nodes[0].decoderawtransaction(funded_tx)["vin"]):
if tx_input["txid"] == utxo_info["txid"] and tx_input["vout"] == utxo_info["vout"]:
reissuance_index = i
break
assert(reissuance_index != -1)
reissued_tx = self.nodes[0].rawreissueasset(funded_tx, [{"asset_amount":3, "asset_address":self.nodes[0].getnewaddress(), "input_index":reissuance_index, "asset_blinder":utxo_info["assetblinder"], "entropy":issued_asset["entropy"]}])
blind_tx = self.nodes[0].blindrawtransaction(reissued_tx["hex"])
signed_tx = self.nodes[0].signrawtransaction(blind_tx)
tx_id = self.nodes[0].sendrawtransaction(signed_tx["hex"])
self.nodes[0].generate(1)
assert_equal(self.nodes[0].gettransaction(tx_id)["confirmations"], 1)

# Now send reissuance token to blinded multisig, then reissue
addrs = []
for i in range(3):
addrs.append(self.nodes[0].validateaddress(self.nodes[0].getnewaddress())["pubkey"])


multisig_addr = self.nodes[0].createmultisig(2,addrs)
blinded_addr = self.nodes[0].getnewaddress()
blinding_pubkey = self.nodes[0].validateaddress(blinded_addr)["confidential_key"]
blinding_privkey = self.nodes[0].dumpblindingkey(blinded_addr)
blinded_multisig = self.nodes[0].createblindedaddress(multisig_addr["address"], blinding_pubkey)
# Import address so we consider the reissuance tokens ours
self.nodes[0].importaddress(blinded_multisig)
# Import blinding key to be able to decrypt values sent to it
self.nodes[0].importblindingkey(blinded_multisig, blinding_privkey)

self.nodes[0].sendtoaddress(blinded_multisig, self.nodes[0].getbalance()[issued_asset["asset"]], "", "", False, issued_asset["asset"])
self.nodes[0].generate(1)

# Get that multisig output
utxo_info = None
# Find info about the token output using wallet
for utxo in self.nodes[0].listunspent():
if utxo["asset"] == issued_asset["token"]:
utxo_info = utxo
break
assert(utxo_info is not None)

# Now make transaction spending that input
raw_tx = self.nodes[0].createrawtransaction([], {issued_address:1}, 0, {issued_address:issued_asset["token"]})
funded_tx = self.nodes[0].fundrawtransaction(raw_tx)["hex"]
# Find the reissuance input
reissuance_index = -1
for i, tx_input in enumerate(self.nodes[0].decoderawtransaction(funded_tx)["vin"]):
if tx_input["txid"] == utxo_info["txid"] and tx_input["vout"] == utxo_info["vout"]:
reissuance_index = i
break
assert(reissuance_index != -1)
reissued_tx = self.nodes[0].rawreissueasset(funded_tx, [{"asset_amount":3, "asset_address":self.nodes[0].getnewaddress(), "input_index":reissuance_index, "asset_blinder":utxo_info["assetblinder"], "entropy":issued_asset["entropy"]}])

blind_tx = self.nodes[0].blindrawtransaction(reissued_tx["hex"])
signed_tx = self.nodes[0].signrawtransaction(blind_tx)
tx_id = self.nodes[0].sendrawtransaction(signed_tx["hex"])
self.nodes[0].generate(1)
assert_equal(self.nodes[0].gettransaction(tx_id)["confirmations"], 1)

# Now make transaction spending a token that had non-null contract_hash
contract_hash = "deadbeee"*8
raw_tx = self.nodes[0].createrawtransaction([], {self.nodes[0].getnewaddress():1})
funded_tx = self.nodes[0].fundrawtransaction(raw_tx)["hex"]
issued_tx = self.nodes[0].rawissueasset(funded_tx, [{"token_amount":1, "token_address":self.nodes[0].getnewaddress(), "contract_hash":contract_hash}])[0]
blinded_tx = self.nodes[0].blindrawtransaction(issued_tx["hex"])
signed_tx = self.nodes[0].signrawtransaction(blinded_tx)
tx_id = self.nodes[0].sendrawtransaction(signed_tx["hex"])
self.nodes[0].generate(1)
assert_equal(self.nodes[0].gettransaction(tx_id)["confirmations"], 1)

utxo_info = None
# Find info about the token output using wallet
for utxo in self.nodes[0].listunspent():
if utxo["asset"] == issued_tx["token"]:
utxo_info = utxo
break
assert(utxo_info is not None)

# Now spend the token, and create reissuance
raw_tx = self.nodes[0].createrawtransaction([], {issued_address:1}, 0, {issued_address:issued_tx["token"]})
funded_tx = self.nodes[0].fundrawtransaction(raw_tx)["hex"]
# Find the reissuance input
reissuance_index = -1
for i, tx_input in enumerate(self.nodes[0].decoderawtransaction(funded_tx)["vin"]):
if tx_input["txid"] == utxo_info["txid"] and tx_input["vout"] == utxo_info["vout"]:
reissuance_index = i
break
assert(reissuance_index != -1)
reissued_tx = self.nodes[0].rawreissueasset(funded_tx, [{"asset_amount":3, "asset_address":self.nodes[0].getnewaddress(), "input_index":reissuance_index, "asset_blinder":utxo_info["assetblinder"], "entropy":issued_tx["entropy"]}])

blind_tx = self.nodes[0].blindrawtransaction(reissued_tx["hex"], False)
signed_tx = self.nodes[0].signrawtransaction(blind_tx)
tx_id = self.nodes[0].sendrawtransaction(signed_tx["hex"])
self.nodes[0].generate(1)
assert_equal(self.nodes[0].gettransaction(tx_id)["confirmations"], 1)

if __name__ == '__main__':
IssuanceTest ().main ()
8 changes: 4 additions & 4 deletions src/blind.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -265,10 +265,10 @@ int BlindTransaction(std::vector<uint256 >& input_blinding_factors, const std::v
}
// New Issuance
if (issuance.assetBlindingNonce.IsNull()) {
bool assetToBlind = (vBlindIssuanceAsset.size() > i && vBlindIssuanceAsset[i].IsValid()) ? true : false;
bool blind_issuance = (vBlindIssuanceToken.size() > i && vBlindIssuanceToken[i].IsValid()) ? true : false;
GenerateAssetEntropy(entropy, tx.vin[i].prevout, issuance.assetEntropy);
CalculateAsset(asset, entropy);
CalculateReissuanceToken(token, entropy, assetToBlind);
CalculateReissuanceToken(token, entropy, blind_issuance);
} else {
CalculateAsset(asset, issuance.assetEntropy);
}
Expand Down Expand Up @@ -395,8 +395,8 @@ int BlindTransaction(std::vector<uint256 >& input_blinding_factors, const std::v
if (nPseudo == 0) {
CalculateAsset(asset, entropy);
} else {
bool assetToBlind = (vBlindIssuanceAsset.size() > nIn && vBlindIssuanceAsset[nIn].IsValid()) ? true : false;
CalculateReissuanceToken(asset, entropy, assetToBlind);
bool blind_issuance = (vBlindIssuanceToken.size() > nIn && vBlindIssuanceToken[nIn].IsValid()) ? true : false;
CalculateReissuanceToken(asset, entropy, blind_issuance);
}
} else {
if (nPseudo == 0) {
Expand Down
2 changes: 2 additions & 0 deletions src/rpc/client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "rawblindrawtransaction", 6, "ignoreblindfail" },
{ "blindrawtransaction", 1, "assetcommitments" },
{ "blindrawtransaction", 2, "ignoreblindfail" },
{ "blindrawtransaction", 3, "blind_issuances" },
{ "createrawtransaction", 0, "inputs" },
{ "createrawtransaction", 1, "outputs" },
{ "dumpissuanceblindingkey", 1, "vin" },
Expand Down Expand Up @@ -142,6 +143,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "sendtomainchain", 2, "subtractfeefromamount"},
{ "getnewblockhex", 0, "required_age"},
{ "rawissueasset", 1, "issuances"},
{ "rawreissueasset", 1, "reissuances"},
// Echo with conversion (For testing only)
{ "echojson", 0, "arg0" },
{ "echojson", 1, "arg1" },
Expand Down
1 change: 1 addition & 0 deletions src/rpc/misc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ UniValue validateaddress(const JSONRPCRequest& request)
" \"timestamp\" : timestamp, (number, optional) The creation time of the key if available in seconds since epoch (Jan 1 1970 GMT)\n"
" \"unconfidential\" : \"address\" (string) The address without confidentiality key\n"
" \"confidential\" : \"address\" (string) Confidential version of the address, only if it is yours and unconfidential\n"
" \"confidential_key\" : \"publickeyhex\" (string) The hex value of the raw blinding public key for that address, if any.\n"
" \"hdkeypath\" : \"keypath\" (string, optional) The HD keypath if the key is HD and available\n"
" \"hdmasterkeyid\" : \"<hash160>\" (string, optional) The Hash160 of the HD master pubkey\n"
"}\n"
Expand Down
Loading

0 comments on commit 5467be3

Please sign in to comment.