From 8b9791fa0e58db49e8864379f8652437d596853a Mon Sep 17 00:00:00 2001 From: Steven Roose Date: Fri, 7 May 2021 14:56:22 +0200 Subject: [PATCH] Support supplying contract hash to issueasset RPC --- src/wallet/rpcwallet.cpp | 15 +++++++++++---- src/wallet/wallet.cpp | 4 ++-- src/wallet/wallet.h | 4 ++++ test/functional/feature_issuance.py | 6 ++++-- 4 files changed, 21 insertions(+), 8 deletions(-) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 0044533073..da86d0bf11 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -6133,16 +6133,16 @@ UniValue issueasset(const JSONRPCRequest& request) return NullUniValue; } - if (request.fHelp || request.params.size() < 2 || request.params.size() > 3) + if (request.fHelp || request.params.size() < 2 || request.params.size() > 4) throw std::runtime_error( RPCHelpMan{"issueasset", "\nCreate an asset. Must have funds in wallet to do so. Returns asset hex id.\n" - "For more fine-grained control such as non-empty contract-hashes to commit\n" - "to an issuance policy, see `rawissueasset` RPC call.\n", + "For more fine-grained control such as multiple issuances, see `rawissueasset` RPC call.\n", { {"assetamount", RPCArg::Type::AMOUNT, RPCArg::Optional::NO, "Amount of asset to generate. Note that the amount is BTC-like, with 8 decimal places."}, {"tokenamount", RPCArg::Type::AMOUNT, RPCArg::Optional::NO, "Amount of reissuance tokens to generate. Note that the amount is BTC-like, with 8 decimal places. These will allow you to reissue the asset if in wallet using `reissueasset`. These tokens are not consumed during reissuance."}, {"blind", RPCArg::Type::BOOL , /* default */ "true", "Whether to blind the issuances."}, + {"contract_hash", RPCArg::Type::STR_HEX, /* default */ "0000...0000", "Contract hash that is put into issuance definition. Must be 32 bytes worth in hex string form. This will affect the asset id."}, }, RPCResult{ "{ (json object)\n" @@ -6174,6 +6174,12 @@ UniValue issueasset(const JSONRPCRequest& request) bool blind_issuances = request.params.size() < 3 || request.params[2].get_bool(); + // Check for optional contract to hash into definition + uint256 contract_hash; + if (request.params.size() >= 4) { + contract_hash = ParseHashV(request.params[3], "contract_hash"); + } + if (!pwallet->IsLocked()) pwallet->TopUpKeyPool(); @@ -6205,13 +6211,14 @@ UniValue issueasset(const JSONRPCRequest& request) CAsset dummyasset; IssuanceDetails issuance_details; issuance_details.blind_issuance = blind_issuances; + issuance_details.contract_hash = contract_hash; CTransactionRef tx_ref = SendGenerationTransaction(GetScriptForDestination(asset_dest), asset_dest_blindpub, GetScriptForDestination(token_dest), token_dest_blindpub, nAmount, nTokens, &issuance_details, *locked_chain, pwallet); // Calculate asset type, assumes first vin is used for issuance CAsset asset; CAsset token; assert(!tx_ref->vin.empty()); - GenerateAssetEntropy(issuance_details.entropy, tx_ref->vin[0].prevout, uint256()); + GenerateAssetEntropy(issuance_details.entropy, tx_ref->vin[0].prevout, issuance_details.contract_hash); CalculateAsset(asset, issuance_details.entropy); CalculateReissuanceToken(token, issuance_details.entropy, blind_issuances); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index c1352dca33..12964e2c99 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -3448,12 +3448,12 @@ bool CWallet::CreateTransaction(interfaces::Chain::Lock& locked_chain, const std uint256 entropy; CAsset asset; CAsset token; - //TODO take optional contract hash // Initial issuance always uses vin[0] - GenerateAssetEntropy(entropy, txNew.vin[0].prevout, uint256()); + GenerateAssetEntropy(entropy, txNew.vin[0].prevout, issuance_details->contract_hash); CalculateAsset(asset, entropy); CalculateReissuanceToken(token, entropy, issuance_details->blind_issuance); CScript blindingScript(CScript() << OP_RETURN << std::vector(txNew.vin[0].prevout.hash.begin(), txNew.vin[0].prevout.hash.end()) << txNew.vin[0].prevout.n); + txNew.vin[0].assetIssuance.assetEntropy = issuance_details->contract_hash; // We're making asset outputs, fill out asset type and issuance input if (asset_index != -1) { txNew.vin[0].assetIssuance.nAmount = txNew.vout[asset_index].nValue; diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 6e01a00178..10c956155e 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -693,7 +693,11 @@ struct CoinSelectionParams struct IssuanceDetails { bool issuing = false; + // Indicated fields. bool blind_issuance = true; + uint256 contract_hash; + + // Calculated fields. CAsset reissuance_asset; CAsset reissuance_token; uint256 entropy; diff --git a/test/functional/feature_issuance.py b/test/functional/feature_issuance.py index 81c08266f8..b0f252a688 100755 --- a/test/functional/feature_issuance.py +++ b/test/functional/feature_issuance.py @@ -109,7 +109,8 @@ class IssuanceTest(BitcoinTestFramework): assert_equal(len(self.nodes[0].listissuances()), 0) # Unblinded issuance of asset - issued = self.nodes[0].issueasset(1, 1, False) + contract_hash = "deadbeef"*8 + issued = self.nodes[0].issueasset(1, 1, False, contract_hash) balance = self.nodes[0].getwalletinfo()["balance"] assert_equal(balance[issued["asset"]], 1) assert_equal(balance[issued["token"]], 1) @@ -119,7 +120,8 @@ class IssuanceTest(BitcoinTestFramework): self.nodes[0].generate(1) self.sync_all() - issued2 = self.nodes[0].issueasset(2, 1) + contract_hash = "deadbeee"*8 + issued2 = self.nodes[0].issueasset(2, 1, True, contract_hash) test_asset = issued2["asset"] assert_equal(self.nodes[0].getwalletinfo()['balance'][test_asset], Decimal(2)) node1balance = self.nodes[1].getwalletinfo()['balance']