void CDeterministicMNState::ToJson(UniValue& obj) const { obj.clear(); obj.setObject(); obj.push_back(Pair("service", addr.ToStringIPPort(false))); obj.push_back(Pair("registeredHeight", nRegisteredHeight)); obj.push_back(Pair("lastPaidHeight", nLastPaidHeight)); obj.push_back(Pair("PoSePenalty", nPoSePenalty)); obj.push_back(Pair("PoSeRevivedHeight", nPoSeRevivedHeight)); obj.push_back(Pair("PoSeBanHeight", nPoSeBanHeight)); obj.push_back(Pair("revocationReason", nRevocationReason)); obj.push_back(Pair("ownerAddress", CBitcoinAddress(keyIDOwner).ToString())); obj.push_back(Pair("votingAddress", CBitcoinAddress(keyIDVoting).ToString())); CTxDestination dest; if (ExtractDestination(scriptPayout, dest)) { CBitcoinAddress payoutAddress(dest); obj.push_back(Pair("payoutAddress", payoutAddress.ToString())); } obj.push_back(Pair("pubKeyOperator", pubKeyOperator.ToString())); if (ExtractDestination(scriptOperatorPayout, dest)) { CBitcoinAddress operatorPayoutAddress(dest); obj.push_back(Pair("operatorPayoutAddress", operatorPayoutAddress.ToString())); } }
void CProUpRevTx::ToJson(UniValue& obj) const { obj.clear(); obj.setObject(); obj.push_back(Pair("version", nVersion)); obj.push_back(Pair("proTxHash", proTxHash.ToString())); obj.push_back(Pair("reason", (int)nReason)); obj.push_back(Pair("inputsHash", inputsHash.ToString())); }
BOOST_FIXTURE_TEST_CASE(importmulti_rescan, TestChain100Setup) { auto chain = interfaces::MakeChain(); // Cap last block file size, and mine new block in a new block file. CBlockIndex* oldTip = chainActive.Tip(); GetBlockFileInfo(oldTip->GetBlockPos().nFile)->nSize = MAX_BLOCKFILE_SIZE; CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())); CBlockIndex* newTip = chainActive.Tip(); auto locked_chain = chain->lock(); // Prune the older block file. PruneOneBlockFile(oldTip->GetBlockPos().nFile); UnlinkPrunedFiles({oldTip->GetBlockPos().nFile}); // Verify importmulti RPC returns failure for a key whose creation time is // before the missing block, and success for a key whose creation time is // after. { std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(*chain, WalletLocation(), WalletDatabase::CreateDummy()); AddWallet(wallet); UniValue keys; keys.setArray(); UniValue key; key.setObject(); key.pushKV("scriptPubKey", HexStr(GetScriptForRawPubKey(coinbaseKey.GetPubKey()))); key.pushKV("timestamp", 0); key.pushKV("internal", UniValue(true)); keys.push_back(key); key.clear(); key.setObject(); CKey futureKey; futureKey.MakeNewKey(true); key.pushKV("scriptPubKey", HexStr(GetScriptForRawPubKey(futureKey.GetPubKey()))); key.pushKV("timestamp", newTip->GetBlockTimeMax() + TIMESTAMP_WINDOW + 1); key.pushKV("internal", UniValue(true)); keys.push_back(key); JSONRPCRequest request; request.params.setArray(); request.params.push_back(keys); UniValue response = importmulti(request); BOOST_CHECK_EQUAL(response.write(), strprintf("[{\"success\":false,\"error\":{\"code\":-1,\"message\":\"Rescan failed for key with creation " "timestamp %d. There was an error reading a block from time %d, which is after or within %d " "seconds of key creation, and could contain transactions pertaining to the key. As a result, " "transactions and coins using this key may not appear in the wallet. This error could be caused " "by pruning or data corruption (see bitcoind log for details) and could be dealt with by " "downloading and rescanning the relevant blocks (see -reindex and -rescan " "options).\"}},{\"success\":true}]", 0, oldTip->GetBlockTimeMax(), TIMESTAMP_WINDOW)); RemoveWallet(wallet); } }
void CProUpServTx::ToJson(UniValue& obj) const { obj.clear(); obj.setObject(); obj.push_back(Pair("version", nVersion)); obj.push_back(Pair("proTxHash", proTxHash.ToString())); obj.push_back(Pair("service", addr.ToString(false))); CTxDestination dest; if (ExtractDestination(scriptOperatorPayout, dest)) { CBitcoinAddress bitcoinAddress(dest); obj.push_back(Pair("operatorPayoutAddress", bitcoinAddress.ToString())); } obj.push_back(Pair("inputsHash", inputsHash.ToString())); }
void CProUpRegTx::ToJson(UniValue& obj) const { obj.clear(); obj.setObject(); obj.push_back(Pair("version", nVersion)); obj.push_back(Pair("proTxHash", proTxHash.ToString())); obj.push_back(Pair("votingAddress", CBitcoinAddress(keyIDVoting).ToString())); CTxDestination dest; if (ExtractDestination(scriptPayout, dest)) { CBitcoinAddress bitcoinAddress(dest); obj.push_back(Pair("payoutAddress", bitcoinAddress.ToString())); } obj.push_back(Pair("pubKeyOperator", pubKeyOperator.ToString())); obj.push_back(Pair("inputsHash", inputsHash.ToString())); }
void CProRegTx::ToJson(UniValue& obj) const { obj.clear(); obj.setObject(); obj.push_back(Pair("version", nVersion)); obj.push_back(Pair("collateralHash", collateralOutpoint.hash.ToString())); obj.push_back(Pair("collateralIndex", (int)collateralOutpoint.n)); obj.push_back(Pair("service", addr.ToString(false))); obj.push_back(Pair("ownerAddress", CBitcoinAddress(keyIDOwner).ToString())); obj.push_back(Pair("votingAddress", CBitcoinAddress(keyIDVoting).ToString())); CTxDestination dest; if (ExtractDestination(scriptPayout, dest)) { CBitcoinAddress bitcoinAddress(dest); obj.push_back(Pair("payoutAddress", bitcoinAddress.ToString())); } obj.push_back(Pair("pubKeyOperator", pubKeyOperator.ToString())); obj.push_back(Pair("operatorReward", (double)nOperatorReward / 100)); obj.push_back(Pair("inputsHash", inputsHash.ToString())); }
void CDeterministicMN::ToJson(UniValue& obj) const { obj.clear(); obj.setObject(); UniValue stateObj; pdmnState->ToJson(stateObj); obj.push_back(Pair("proTxHash", proTxHash.ToString())); obj.push_back(Pair("collateralHash", collateralOutpoint.hash.ToString())); obj.push_back(Pair("collateralIndex", (int)collateralOutpoint.n)); Coin coin; if (GetUTXOCoin(collateralOutpoint, coin)) { CTxDestination dest; if (ExtractDestination(coin.out.scriptPubKey, dest)) { obj.push_back(Pair("collateralAddress", CBitcoinAddress(dest).ToString())); } } obj.push_back(Pair("operatorReward", (double)nOperatorReward / 100)); obj.push_back(Pair("state", stateObj)); }
BOOST_FIXTURE_TEST_CASE(rescan, TestChain100Setup) { LOCK(cs_main); // Cap last block file size, and mine new block in a new block file. CBlockIndex* const nullBlock = nullptr; CBlockIndex* oldTip = chainActive.Tip(); GetBlockFileInfo(oldTip->GetBlockPos().nFile)->nSize = MAX_BLOCKFILE_SIZE; CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())); CBlockIndex* newTip = chainActive.Tip(); // Verify ScanForWalletTransactions picks up transactions in both the old // and new block files. { CWallet wallet; LOCK(wallet.cs_wallet); wallet.AddKeyPubKey(coinbaseKey, coinbaseKey.GetPubKey()); BOOST_CHECK_EQUAL(nullBlock, wallet.ScanForWalletTransactions(oldTip)); BOOST_CHECK_EQUAL(wallet.GetImmatureBalance(), 100 * COIN); } // Prune the older block file. PruneOneBlockFile(oldTip->GetBlockPos().nFile); UnlinkPrunedFiles({oldTip->GetBlockPos().nFile}); // Verify ScanForWalletTransactions only picks transactions in the new block // file. { CWallet wallet; LOCK(wallet.cs_wallet); wallet.AddKeyPubKey(coinbaseKey, coinbaseKey.GetPubKey()); BOOST_CHECK_EQUAL(oldTip, wallet.ScanForWalletTransactions(oldTip)); BOOST_CHECK_EQUAL(wallet.GetImmatureBalance(), 50 * COIN); } // Verify importmulti RPC returns failure for a key whose creation time is // before the missing block, and success for a key whose creation time is // after. { CWallet wallet; vpwallets.insert(vpwallets.begin(), &wallet); UniValue keys; keys.setArray(); UniValue key; key.setObject(); key.pushKV("scriptPubKey", HexStr(GetScriptForRawPubKey(coinbaseKey.GetPubKey()))); key.pushKV("timestamp", 0); key.pushKV("internal", UniValue(true)); keys.push_back(key); key.clear(); key.setObject(); CKey futureKey; futureKey.MakeNewKey(true); key.pushKV("scriptPubKey", HexStr(GetScriptForRawPubKey(futureKey.GetPubKey()))); key.pushKV("timestamp", newTip->GetBlockTimeMax() + TIMESTAMP_WINDOW + 1); key.pushKV("internal", UniValue(true)); keys.push_back(key); JSONRPCRequest request; request.params.setArray(); request.params.push_back(keys); UniValue response = importmulti(request); BOOST_CHECK_EQUAL(response.write(), strprintf("[{\"success\":false,\"error\":{\"code\":-1,\"message\":\"Rescan failed for key with creation " "timestamp %d. There was an error reading a block from time %d, which is after or within %d " "seconds of key creation, and could contain transactions pertaining to the key. As a result, " "transactions and coins using this key may not appear in the wallet. This error could be caused " "by pruning or data corruption (see bitcoind log for details) and could be dealt with by " "downloading and rescanning the relevant blocks (see -reindex and -rescan " "options).\"}},{\"success\":true}]", 0, oldTip->GetBlockTimeMax(), TIMESTAMP_WINDOW)); vpwallets.erase(vpwallets.begin()); } }
/** * Sign and send a raw transaction. * Raw transaction as hex string should be in object field "rawtxn" */ void AsyncRPCOperation_sendmany::sign_send_raw_transaction(UniValue obj) { // Sign the raw transaction UniValue rawtxnValue = find_value(obj, "rawtxn"); if (rawtxnValue.isNull()) { throw JSONRPCError(RPC_WALLET_ERROR, "Missing hex data for raw transaction"); } std::string rawtxn = rawtxnValue.get_str(); UniValue params = UniValue(UniValue::VARR); params.push_back(rawtxn); UniValue signResultValue = signrawtransaction(params, false); UniValue signResultObject = signResultValue.get_obj(); UniValue completeValue = find_value(signResultObject, "complete"); bool complete = completeValue.get_bool(); if (!complete) { // TODO: #1366 Maybe get "errors" and print array vErrors into a string throw JSONRPCError(RPC_WALLET_ENCRYPTION_FAILED, "Failed to sign transaction"); } UniValue hexValue = find_value(signResultObject, "hex"); if (hexValue.isNull()) { throw JSONRPCError(RPC_WALLET_ERROR, "Missing hex data for signed transaction"); } std::string signedtxn = hexValue.get_str(); // Send the signed transaction if (!testmode) { params.clear(); params.setArray(); params.push_back(signedtxn); UniValue sendResultValue = sendrawtransaction(params, false); if (sendResultValue.isNull()) { throw JSONRPCError(RPC_WALLET_ERROR, "Send raw transaction did not return an error or a txid."); } std::string txid = sendResultValue.get_str(); UniValue o(UniValue::VOBJ); o.push_back(Pair("txid", txid)); set_result(o); } else { // Test mode does not send the transaction to the network. CDataStream stream(ParseHex(signedtxn), SER_NETWORK, PROTOCOL_VERSION); CTransaction tx; stream >> tx; UniValue o(UniValue::VOBJ); o.push_back(Pair("test", 1)); o.push_back(Pair("txid", tx.GetHash().ToString())); o.push_back(Pair("hex", signedtxn)); set_result(o); } // Keep the signed transaction so we can hash to the same txid CDataStream stream(ParseHex(signedtxn), SER_NETWORK, PROTOCOL_VERSION); CTransaction tx; stream >> tx; tx_ = tx; }
BOOST_FIXTURE_TEST_CASE(rescan, TestChain100Setup) { LOCK(cs_main); // Cap last block file size, and mine new block in a new block file. CBlockIndex* oldTip = chainActive.Tip(); GetBlockFileInfo(oldTip->GetBlockPos().nFile)->nSize = MAX_BLOCKFILE_SIZE; CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())); CBlockIndex* newTip = chainActive.Tip(); // Verify ScanForWalletTransactions picks up transactions in both the old // and new block files. { CWallet wallet; LOCK(wallet.cs_wallet); wallet.AddKeyPubKey(coinbaseKey, coinbaseKey.GetPubKey()); BOOST_CHECK_EQUAL(oldTip, wallet.ScanForWalletTransactions(oldTip)); BOOST_CHECK_EQUAL(wallet.GetImmatureBalance(), 100 * COIN); } // Prune the older block file. PruneOneBlockFile(oldTip->GetBlockPos().nFile); UnlinkPrunedFiles({oldTip->GetBlockPos().nFile}); // Verify ScanForWalletTransactions only picks transactions in the new block // file. { CWallet wallet; LOCK(wallet.cs_wallet); wallet.AddKeyPubKey(coinbaseKey, coinbaseKey.GetPubKey()); BOOST_CHECK_EQUAL(newTip, wallet.ScanForWalletTransactions(oldTip)); BOOST_CHECK_EQUAL(wallet.GetImmatureBalance(), 50 * COIN); } // Verify importmulti RPC returns failure for a key whose creation time is // before the missing block, and success for a key whose creation time is // after. { CWallet wallet; CWallet *backup = ::pwalletMain; ::pwalletMain = &wallet; UniValue keys; keys.setArray(); UniValue key; key.setObject(); key.pushKV("scriptPubKey", HexStr(GetScriptForRawPubKey(coinbaseKey.GetPubKey()))); key.pushKV("timestamp", 0); key.pushKV("internal", UniValue(true)); keys.push_back(key); key.clear(); key.setObject(); CKey futureKey; futureKey.MakeNewKey(true); key.pushKV("scriptPubKey", HexStr(GetScriptForRawPubKey(futureKey.GetPubKey()))); key.pushKV("timestamp", newTip->GetBlockTimeMax() + TIMESTAMP_WINDOW); key.pushKV("internal", UniValue(true)); keys.push_back(key); JSONRPCRequest request; request.params.setArray(); request.params.push_back(keys); UniValue response = importmulti(request); BOOST_CHECK_EQUAL(response.write(), strprintf("[{\"success\":false,\"error\":{\"code\":-1,\"message\":\"Failed to rescan before time %d, transactions may be missing.\"}},{\"success\":true}]", newTip->GetBlockTimeMax())); ::pwalletMain = backup; } // Verify ScanForWalletTransactions does not return null when the scan is // elided due to the nTimeFirstKey optimization. { CWallet wallet; { LOCK(wallet.cs_wallet); wallet.UpdateTimeFirstKey(newTip->GetBlockTime() + 7200 + 1); } BOOST_CHECK_EQUAL(newTip, wallet.ScanForWalletTransactions(newTip)); } }