test: Use test_bitcoin setup in bench, Add test utils
This commit is contained in:
parent
666696b673
commit
fa8685d49e
9 changed files with 152 additions and 135 deletions
|
@ -20,6 +20,10 @@
|
||||||
</ProjectConfiguration>
|
</ProjectConfiguration>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ClCompile Include="..\..\src\test\util.h" />
|
||||||
|
<ClCompile Include="..\..\src\test\util.cpp" />
|
||||||
|
<ClCompile Include="..\..\src\test\test_bitcoin.h" />
|
||||||
|
<ClCompile Include="..\..\src\test\test_bitcoin.cpp" />
|
||||||
<ClCompile Include="..\..\src\bench\base58.cpp" />
|
<ClCompile Include="..\..\src\bench\base58.cpp" />
|
||||||
<ClCompile Include="..\..\src\bench\bech32.cpp" />
|
<ClCompile Include="..\..\src\bench\bech32.cpp" />
|
||||||
<ClCompile Include="..\..\src\bench\bench.cpp" />
|
<ClCompile Include="..\..\src\bench\bench.cpp" />
|
||||||
|
|
|
@ -32,7 +32,11 @@ bench_bench_bitcoin_SOURCES = \
|
||||||
bench/bech32.cpp \
|
bench/bech32.cpp \
|
||||||
bench/lockedpool.cpp \
|
bench/lockedpool.cpp \
|
||||||
bench/poly1305.cpp \
|
bench/poly1305.cpp \
|
||||||
bench/prevector.cpp
|
bench/prevector.cpp \
|
||||||
|
test/test_bitcoin.h \
|
||||||
|
test/test_bitcoin.cpp \
|
||||||
|
test/util.h \
|
||||||
|
test/util.cpp
|
||||||
|
|
||||||
nodist_bench_bench_bitcoin_SOURCES = $(GENERATED_BENCH_FILES)
|
nodist_bench_bench_bitcoin_SOURCES = $(GENERATED_BENCH_FILES)
|
||||||
|
|
||||||
|
|
|
@ -4,12 +4,16 @@
|
||||||
|
|
||||||
#include <bench/bench.h>
|
#include <bench/bench.h>
|
||||||
|
|
||||||
#include <assert.h>
|
#include <chainparams.h>
|
||||||
#include <iostream>
|
#include <test/test_bitcoin.h>
|
||||||
#include <iomanip>
|
#include <validation.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <regex>
|
#include <assert.h>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <iostream>
|
||||||
#include <numeric>
|
#include <numeric>
|
||||||
|
#include <regex>
|
||||||
|
|
||||||
void benchmark::ConsolePrinter::header()
|
void benchmark::ConsolePrinter::header()
|
||||||
{
|
{
|
||||||
|
@ -108,6 +112,13 @@ void benchmark::BenchRunner::RunAll(Printer& printer, uint64_t num_evals, double
|
||||||
printer.header();
|
printer.header();
|
||||||
|
|
||||||
for (const auto& p : benchmarks()) {
|
for (const auto& p : benchmarks()) {
|
||||||
|
TestingSetup test{CBaseChainParams::REGTEST};
|
||||||
|
{
|
||||||
|
assert(::chainActive.Height() == 0);
|
||||||
|
const bool witness_enabled{IsWitnessEnabled(::chainActive.Tip(), Params().GetConsensus())};
|
||||||
|
assert(witness_enabled);
|
||||||
|
}
|
||||||
|
|
||||||
if (!std::regex_match(p.first, baseMatch, reFilter)) {
|
if (!std::regex_match(p.first, baseMatch, reFilter)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,14 +6,11 @@
|
||||||
|
|
||||||
#include <crypto/sha256.h>
|
#include <crypto/sha256.h>
|
||||||
#include <key.h>
|
#include <key.h>
|
||||||
#include <util/system.h>
|
|
||||||
#include <util/strencodings.h>
|
#include <util/strencodings.h>
|
||||||
#include <validation.h>
|
#include <util/system.h>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
const std::function<std::string(const char*)> G_TRANSLATION_FUN = nullptr;
|
|
||||||
|
|
||||||
static const int64_t DEFAULT_BENCH_EVALUATIONS = 5;
|
static const int64_t DEFAULT_BENCH_EVALUATIONS = 5;
|
||||||
static const char* DEFAULT_BENCH_FILTER = ".*";
|
static const char* DEFAULT_BENCH_FILTER = ".*";
|
||||||
static const char* DEFAULT_BENCH_SCALING = "1.0";
|
static const char* DEFAULT_BENCH_SCALING = "1.0";
|
||||||
|
@ -36,14 +33,6 @@ static void SetupBenchArgs()
|
||||||
gArgs.AddArg("-plot-height=<x>", strprintf("Plot height in pixel (default: %u)", DEFAULT_PLOT_HEIGHT), false, OptionsCategory::OPTIONS);
|
gArgs.AddArg("-plot-height=<x>", strprintf("Plot height in pixel (default: %u)", DEFAULT_PLOT_HEIGHT), false, OptionsCategory::OPTIONS);
|
||||||
}
|
}
|
||||||
|
|
||||||
static fs::path SetDataDir()
|
|
||||||
{
|
|
||||||
fs::path ret = fs::temp_directory_path() / "bench_bitcoin" / fs::unique_path();
|
|
||||||
fs::create_directories(ret);
|
|
||||||
gArgs.ForceSetArg("-datadir", ret.string());
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
SetupBenchArgs();
|
SetupBenchArgs();
|
||||||
|
@ -59,13 +48,6 @@ int main(int argc, char** argv)
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the datadir after parsing the bench options
|
|
||||||
const fs::path bench_datadir{SetDataDir()};
|
|
||||||
|
|
||||||
SHA256AutoDetect();
|
|
||||||
ECC_Start();
|
|
||||||
SetupEnvironment();
|
|
||||||
|
|
||||||
int64_t evaluations = gArgs.GetArg("-evals", DEFAULT_BENCH_EVALUATIONS);
|
int64_t evaluations = gArgs.GetArg("-evals", DEFAULT_BENCH_EVALUATIONS);
|
||||||
std::string regex_filter = gArgs.GetArg("-filter", DEFAULT_BENCH_FILTER);
|
std::string regex_filter = gArgs.GetArg("-filter", DEFAULT_BENCH_FILTER);
|
||||||
std::string scaling_str = gArgs.GetArg("-scaling", DEFAULT_BENCH_SCALING);
|
std::string scaling_str = gArgs.GetArg("-scaling", DEFAULT_BENCH_SCALING);
|
||||||
|
@ -88,9 +70,5 @@ int main(int argc, char** argv)
|
||||||
|
|
||||||
benchmark::BenchRunner::RunAll(*printer, evaluations, scaling_factor, regex_filter, is_list_only);
|
benchmark::BenchRunner::RunAll(*printer, evaluations, scaling_factor, regex_filter, is_list_only);
|
||||||
|
|
||||||
fs::remove_all(bench_datadir);
|
|
||||||
|
|
||||||
ECC_Stop();
|
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,56 +3,16 @@
|
||||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
#include <bench/bench.h>
|
#include <bench/bench.h>
|
||||||
#include <chainparams.h>
|
|
||||||
#include <coins.h>
|
|
||||||
#include <consensus/merkle.h>
|
|
||||||
#include <consensus/validation.h>
|
#include <consensus/validation.h>
|
||||||
#include <crypto/sha256.h>
|
#include <crypto/sha256.h>
|
||||||
#include <miner.h>
|
#include <test/util.h>
|
||||||
#include <policy/policy.h>
|
|
||||||
#include <pow.h>
|
|
||||||
#include <scheduler.h>
|
|
||||||
#include <txdb.h>
|
|
||||||
#include <txmempool.h>
|
#include <txmempool.h>
|
||||||
#include <util/time.h>
|
|
||||||
#include <validation.h>
|
#include <validation.h>
|
||||||
#include <validationinterface.h>
|
|
||||||
|
|
||||||
#include <boost/thread.hpp>
|
|
||||||
|
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
static std::shared_ptr<CBlock> PrepareBlock(const CScript& coinbase_scriptPubKey)
|
|
||||||
{
|
|
||||||
auto block = std::make_shared<CBlock>(
|
|
||||||
BlockAssembler{Params()}
|
|
||||||
.CreateNewBlock(coinbase_scriptPubKey)
|
|
||||||
->block);
|
|
||||||
|
|
||||||
block->nTime = ::chainActive.Tip()->GetMedianTimePast() + 1;
|
|
||||||
block->hashMerkleRoot = BlockMerkleRoot(*block);
|
|
||||||
|
|
||||||
return block;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static CTxIn MineBlock(const CScript& coinbase_scriptPubKey)
|
|
||||||
{
|
|
||||||
auto block = PrepareBlock(coinbase_scriptPubKey);
|
|
||||||
|
|
||||||
while (!CheckProofOfWork(block->GetHash(), block->nBits, Params().GetConsensus())) {
|
|
||||||
++block->nNonce;
|
|
||||||
assert(block->nNonce);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool processed{ProcessNewBlock(Params(), block, true, nullptr)};
|
|
||||||
assert(processed);
|
|
||||||
|
|
||||||
return CTxIn{block->vtx[0]->GetHash(), 0};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void AssembleBlock(benchmark::State& state)
|
static void AssembleBlock(benchmark::State& state)
|
||||||
{
|
{
|
||||||
const std::vector<unsigned char> op_true{OP_TRUE};
|
const std::vector<unsigned char> op_true{OP_TRUE};
|
||||||
|
@ -64,32 +24,6 @@ static void AssembleBlock(benchmark::State& state)
|
||||||
|
|
||||||
const CScript SCRIPT_PUB{CScript(OP_0) << std::vector<unsigned char>{witness_program.begin(), witness_program.end()}};
|
const CScript SCRIPT_PUB{CScript(OP_0) << std::vector<unsigned char>{witness_program.begin(), witness_program.end()}};
|
||||||
|
|
||||||
// Switch to regtest so we can mine faster
|
|
||||||
// Also segwit is active, so we can include witness transactions
|
|
||||||
SelectParams(CBaseChainParams::REGTEST);
|
|
||||||
|
|
||||||
InitScriptExecutionCache();
|
|
||||||
|
|
||||||
boost::thread_group thread_group;
|
|
||||||
CScheduler scheduler;
|
|
||||||
{
|
|
||||||
LOCK(cs_main);
|
|
||||||
::pblocktree.reset(new CBlockTreeDB(1 << 20, true));
|
|
||||||
::pcoinsdbview.reset(new CCoinsViewDB(1 << 23, true));
|
|
||||||
::pcoinsTip.reset(new CCoinsViewCache(pcoinsdbview.get()));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const CChainParams& chainparams = Params();
|
|
||||||
thread_group.create_thread(std::bind(&CScheduler::serviceQueue, &scheduler));
|
|
||||||
GetMainSignals().RegisterBackgroundSignalScheduler(scheduler);
|
|
||||||
LoadGenesisBlock(chainparams);
|
|
||||||
CValidationState state;
|
|
||||||
ActivateBestChain(state, chainparams);
|
|
||||||
assert(::chainActive.Tip() != nullptr);
|
|
||||||
const bool witness_enabled{IsWitnessEnabled(::chainActive.Tip(), chainparams.GetConsensus())};
|
|
||||||
assert(witness_enabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Collect some loose transactions that spend the coinbases of our mined blocks
|
// Collect some loose transactions that spend the coinbases of our mined blocks
|
||||||
constexpr size_t NUM_BLOCKS{200};
|
constexpr size_t NUM_BLOCKS{200};
|
||||||
std::array<CTransactionRef, NUM_BLOCKS - COINBASE_MATURITY + 1> txs;
|
std::array<CTransactionRef, NUM_BLOCKS - COINBASE_MATURITY + 1> txs;
|
||||||
|
@ -114,11 +48,6 @@ static void AssembleBlock(benchmark::State& state)
|
||||||
while (state.KeepRunning()) {
|
while (state.KeepRunning()) {
|
||||||
PrepareBlock(SCRIPT_PUB);
|
PrepareBlock(SCRIPT_PUB);
|
||||||
}
|
}
|
||||||
|
|
||||||
thread_group.interrupt_all();
|
|
||||||
thread_group.join_all();
|
|
||||||
GetMainSignals().FlushBackgroundCallbacks();
|
|
||||||
GetMainSignals().UnregisterBackgroundSignalScheduler();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BENCHMARK(AssembleBlock, 700);
|
BENCHMARK(AssembleBlock, 700);
|
||||||
|
|
|
@ -10,15 +10,11 @@
|
||||||
#include <miner.h>
|
#include <miner.h>
|
||||||
#include <policy/policy.h>
|
#include <policy/policy.h>
|
||||||
#include <pow.h>
|
#include <pow.h>
|
||||||
#include <scheduler.h>
|
#include <test/util.h>
|
||||||
#include <txdb.h>
|
|
||||||
#include <txmempool.h>
|
#include <txmempool.h>
|
||||||
#include <util/time.h>
|
|
||||||
#include <validation.h>
|
#include <validation.h>
|
||||||
#include <validationinterface.h>
|
#include <validationinterface.h>
|
||||||
|
|
||||||
#include <boost/thread.hpp>
|
|
||||||
|
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
@ -27,31 +23,7 @@ static void DuplicateInputs(benchmark::State& state)
|
||||||
{
|
{
|
||||||
const CScript SCRIPT_PUB{CScript(OP_TRUE)};
|
const CScript SCRIPT_PUB{CScript(OP_TRUE)};
|
||||||
|
|
||||||
// Switch to regtest so we can mine faster
|
|
||||||
// Also segwit is active, so we can include witness transactions
|
|
||||||
SelectParams(CBaseChainParams::REGTEST);
|
|
||||||
|
|
||||||
InitScriptExecutionCache();
|
|
||||||
|
|
||||||
boost::thread_group thread_group;
|
|
||||||
CScheduler scheduler;
|
|
||||||
const CChainParams& chainparams = Params();
|
const CChainParams& chainparams = Params();
|
||||||
{
|
|
||||||
LOCK(cs_main);
|
|
||||||
::pblocktree.reset(new CBlockTreeDB(1 << 20, true));
|
|
||||||
::pcoinsdbview.reset(new CCoinsViewDB(1 << 23, true));
|
|
||||||
::pcoinsTip.reset(new CCoinsViewCache(pcoinsdbview.get()));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
thread_group.create_thread(std::bind(&CScheduler::serviceQueue, &scheduler));
|
|
||||||
GetMainSignals().RegisterBackgroundSignalScheduler(scheduler);
|
|
||||||
LoadGenesisBlock(chainparams);
|
|
||||||
CValidationState cvstate;
|
|
||||||
ActivateBestChain(cvstate, chainparams);
|
|
||||||
assert(::chainActive.Tip() != nullptr);
|
|
||||||
const bool witness_enabled{IsWitnessEnabled(::chainActive.Tip(), chainparams.GetConsensus())};
|
|
||||||
assert(witness_enabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
CBlock block{};
|
CBlock block{};
|
||||||
CMutableTransaction coinbaseTx{};
|
CMutableTransaction coinbaseTx{};
|
||||||
|
@ -92,11 +64,6 @@ static void DuplicateInputs(benchmark::State& state)
|
||||||
assert(!CheckBlock(block, cvstate, chainparams.GetConsensus(), false, false));
|
assert(!CheckBlock(block, cvstate, chainparams.GetConsensus(), false, false));
|
||||||
assert(cvstate.GetRejectReason() == "bad-txns-inputs-duplicate");
|
assert(cvstate.GetRejectReason() == "bad-txns-inputs-duplicate");
|
||||||
}
|
}
|
||||||
|
|
||||||
thread_group.interrupt_all();
|
|
||||||
thread_group.join_all();
|
|
||||||
GetMainSignals().FlushBackgroundCallbacks();
|
|
||||||
GetMainSignals().UnregisterBackgroundSignalScheduler();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BENCHMARK(DuplicateInputs, 10);
|
BENCHMARK(DuplicateInputs, 10);
|
||||||
|
|
|
@ -33,7 +33,7 @@ std::ostream& operator<<(std::ostream& os, const uint256& num)
|
||||||
}
|
}
|
||||||
|
|
||||||
BasicTestingSetup::BasicTestingSetup(const std::string& chainName)
|
BasicTestingSetup::BasicTestingSetup(const std::string& chainName)
|
||||||
: m_path_root(fs::temp_directory_path() / "test_bitcoin" / strprintf("%lu_%i", (unsigned long)GetTime(), (int)(InsecureRandRange(1 << 30))))
|
: m_path_root(fs::temp_directory_path() / "test_common_" PACKAGE_NAME / strprintf("%lu_%i", (unsigned long)GetTime(), (int)(InsecureRandRange(1 << 30))))
|
||||||
{
|
{
|
||||||
SHA256AutoDetect();
|
SHA256AutoDetect();
|
||||||
ECC_Start();
|
ECC_Start();
|
||||||
|
|
90
src/test/util.cpp
Normal file
90
src/test/util.cpp
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
// Copyright (c) 2019 The Bitcoin Core developers
|
||||||
|
// Distributed under the MIT software license, see the accompanying
|
||||||
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
|
#include <test/util.h>
|
||||||
|
|
||||||
|
#include <chainparams.h>
|
||||||
|
#include <consensus/merkle.h>
|
||||||
|
#include <consensus/validation.h>
|
||||||
|
#include <key_io.h>
|
||||||
|
#include <miner.h>
|
||||||
|
#include <outputtype.h>
|
||||||
|
#include <pow.h>
|
||||||
|
#include <scheduler.h>
|
||||||
|
#include <script/standard.h>
|
||||||
|
#include <txdb.h>
|
||||||
|
#include <validation.h>
|
||||||
|
#include <validationinterface.h>
|
||||||
|
#ifdef ENABLE_WALLET
|
||||||
|
#include <wallet/wallet.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <boost/thread.hpp>
|
||||||
|
|
||||||
|
#ifdef ENABLE_WALLET
|
||||||
|
std::string getnewaddress(CWallet& w)
|
||||||
|
{
|
||||||
|
constexpr auto output_type = OutputType::BECH32;
|
||||||
|
|
||||||
|
CPubKey new_key;
|
||||||
|
if (!w.GetKeyFromPool(new_key)) assert(false);
|
||||||
|
|
||||||
|
w.LearnRelatedScripts(new_key, output_type);
|
||||||
|
const auto dest = GetDestinationForKey(new_key, output_type);
|
||||||
|
|
||||||
|
w.SetAddressBook(dest, /* label */ "", "receive");
|
||||||
|
|
||||||
|
return EncodeDestination(dest);
|
||||||
|
}
|
||||||
|
|
||||||
|
void importaddress(CWallet& wallet, const std::string& address)
|
||||||
|
{
|
||||||
|
LOCK(wallet.cs_wallet);
|
||||||
|
const auto dest = DecodeDestination(address);
|
||||||
|
assert(IsValidDestination(dest));
|
||||||
|
const auto script = GetScriptForDestination(dest);
|
||||||
|
wallet.MarkDirty();
|
||||||
|
assert(!wallet.HaveWatchOnly(script));
|
||||||
|
if (!wallet.AddWatchOnly(script, 0 /* nCreateTime */)) assert(false);
|
||||||
|
wallet.SetAddressBook(dest, /* label */ "", "receive");
|
||||||
|
}
|
||||||
|
#endif // ENABLE_WALLET
|
||||||
|
|
||||||
|
CTxIn generatetoaddress(const std::string& address)
|
||||||
|
{
|
||||||
|
const auto dest = DecodeDestination(address);
|
||||||
|
assert(IsValidDestination(dest));
|
||||||
|
const auto coinbase_script = GetScriptForDestination(dest);
|
||||||
|
|
||||||
|
return MineBlock(coinbase_script);
|
||||||
|
}
|
||||||
|
|
||||||
|
CTxIn MineBlock(const CScript& coinbase_scriptPubKey)
|
||||||
|
{
|
||||||
|
auto block = PrepareBlock(coinbase_scriptPubKey);
|
||||||
|
|
||||||
|
while (!CheckProofOfWork(block->GetHash(), block->nBits, Params().GetConsensus())) {
|
||||||
|
++block->nNonce;
|
||||||
|
assert(block->nNonce);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool processed{ProcessNewBlock(Params(), block, true, nullptr)};
|
||||||
|
assert(processed);
|
||||||
|
|
||||||
|
return CTxIn{block->vtx[0]->GetHash(), 0};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::shared_ptr<CBlock> PrepareBlock(const CScript& coinbase_scriptPubKey)
|
||||||
|
{
|
||||||
|
auto block = std::make_shared<CBlock>(
|
||||||
|
BlockAssembler{Params()}
|
||||||
|
.CreateNewBlock(coinbase_scriptPubKey)
|
||||||
|
->block);
|
||||||
|
|
||||||
|
block->nTime = ::chainActive.Tip()->GetMedianTimePast() + 1;
|
||||||
|
block->hashMerkleRoot = BlockMerkleRoot(*block);
|
||||||
|
|
||||||
|
return block;
|
||||||
|
}
|
34
src/test/util.h
Normal file
34
src/test/util.h
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
// Copyright (c) 2019 The Bitcoin Core developers
|
||||||
|
// Distributed under the MIT software license, see the accompanying
|
||||||
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
|
#ifndef BITCOIN_TEST_UTIL_H
|
||||||
|
#define BITCOIN_TEST_UTIL_H
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
class CBlock;
|
||||||
|
class CScript;
|
||||||
|
class CTxIn;
|
||||||
|
class CWallet;
|
||||||
|
|
||||||
|
// Lower-level utils //
|
||||||
|
|
||||||
|
/** Returns the generated coin */
|
||||||
|
CTxIn MineBlock(const CScript& coinbase_scriptPubKey);
|
||||||
|
/** Prepare a block to be mined */
|
||||||
|
std::shared_ptr<CBlock> PrepareBlock(const CScript& coinbase_scriptPubKey);
|
||||||
|
|
||||||
|
|
||||||
|
// RPC-like //
|
||||||
|
|
||||||
|
/** Import the address to the wallet */
|
||||||
|
void importaddress(CWallet& wallet, const std::string& address);
|
||||||
|
/** Returns a new address from the wallet */
|
||||||
|
std::string getnewaddress(CWallet& w);
|
||||||
|
/** Returns the generated coin */
|
||||||
|
CTxIn generatetoaddress(const std::string& address);
|
||||||
|
|
||||||
|
|
||||||
|
#endif // BITCOIN_TEST_UTIL_H
|
Loading…
Reference in a new issue