From 2c7392c7a158480b0119754e4e71ed675ae4e806 Mon Sep 17 00:00:00 2001 From: Anthony Fieroni Date: Thu, 31 Oct 2019 18:19:00 +0200 Subject: [PATCH] Working python bindings Signed-off-by: Anthony Fieroni --- src/claimtrie/CMakeLists.txt | 101 ++++++--------------- src/claimtrie/data.cpp | 5 - src/claimtrie/data.h | 13 +-- src/claimtrie/libclaimtrie.i | 57 ++++++++++++ src/claimtrie/libclaimtrie_test.py | 86 ++++++++++++++++++ src/claimtrie/trie.cpp | 4 +- src/claimtrie/trie.h | 30 ++++-- src/claimtrie/txoutpoint.h | 5 + src/claimtrie_serial.h | 14 --- src/init.cpp | 2 +- src/test/claimtriebranching_tests.cpp | 8 +- src/test/claimtrieexpirationfork_tests.cpp | 8 +- src/test/claimtriefixture.h | 2 + 13 files changed, 208 insertions(+), 127 deletions(-) create mode 100644 src/claimtrie/libclaimtrie.i create mode 100644 src/claimtrie/libclaimtrie_test.py diff --git a/src/claimtrie/CMakeLists.txt b/src/claimtrie/CMakeLists.txt index 4563b53df..21e75627e 100644 --- a/src/claimtrie/CMakeLists.txt +++ b/src/claimtrie/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.10) project(claimtrie) -set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD 14) set(CMAKE_POSITION_INDEPENDENT_CODE ON) include(../../contrib/cmake/cmake/CPM.cmake) @@ -12,90 +12,43 @@ set(CLAIMTRIE_SRC forks.cpp hashes.cpp log.cpp - prefixtrie.cpp trie.cpp txoutpoint.cpp uints.cpp + sqlite/sqlite3.c ) +if(BIND) + find_program(SWIG NAMES swig) + string(TOLOWER ${BIND} BIND) + set(INTERFACE_NAME libclaimtrie) + if(${BIND} STREQUAL "python") + find_package(PythonInterp 3.6 REQUIRED) + find_package(PythonLibs 3.6 REQUIRED) + set(BIND_INCLUDE_DIRS ${PYTHON_INCLUDE_DIRS}) + set(SWIG_OPTIONS -python;-py3) + set(CMAKE_SHARED_LIBRARY_PREFIX _lib) + else() + message(FATAL_ERROR "Implement a handler for ${BIND}") + endif() + add_custom_command(OUTPUT ${INTERFACE_NAME}_wrap.cxx + COMMAND ${SWIG} + ARGS -c++ ${SWIG_OPTIONS} -outcurrentdir ${CMAKE_CURRENT_SOURCE_DIR}/${INTERFACE_NAME}.i + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + ) + set(CLAIMTRIE_SRC ${CLAIMTRIE_SRC} + ${INTERFACE_NAME}_wrap.cxx + ) +endif() + add_library(claimtrie SHARED ${CLAIMTRIE_SRC}) target_include_directories(claimtrie PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) -# TODO remove leveldb depends -set(LEVELDB_SRC - ../leveldb/db/builder.cc - ../leveldb/db/c.cc - ../leveldb/db/dbformat.cc - ../leveldb/db/db_impl.cc - ../leveldb/db/db_iter.cc - ../leveldb/db/dumpfile.cc - ../leveldb/db/filename.cc - ../leveldb/db/log_reader.cc - ../leveldb/db/log_writer.cc - ../leveldb/db/memtable.cc - ../leveldb/db/repair.cc - ../leveldb/db/table_cache.cc - ../leveldb/db/version_edit.cc - ../leveldb/db/version_set.cc - ../leveldb/db/write_batch.cc - ../leveldb/table/block_builder.cc - ../leveldb/table/block.cc - ../leveldb/table/filter_block.cc - ../leveldb/table/format.cc - ../leveldb/table/iterator.cc - ../leveldb/table/merger.cc - ../leveldb/table/table_builder.cc - ../leveldb/table/table.cc - ../leveldb/table/two_level_iterator.cc - ../leveldb/util/arena.cc - ../leveldb/util/bloom.cc - ../leveldb/util/cache.cc - ../leveldb/util/coding.cc - ../leveldb/util/comparator.cc - ../leveldb/util/crc32c.cc - ../leveldb/util/env.cc - ../leveldb/util/env_posix.cc - ../leveldb/util/filter_policy.cc - ../leveldb/util/hash.cc - ../leveldb/util/histogram.cc - ../leveldb/util/logging.cc - ../leveldb/util/options.cc - ../leveldb/util/status.cc -) - -if(WIN32) - set(LEVELDB_SRC ${LEVELDB_SRC} - ../leveldb/util/env_win.cc - ../leveldb/port/port_win.cc - ) -else() - set(LEVELDB_SRC ${LEVELDB_SRC} - ../leveldb/port/port_posix.cc - ) +if(BIND_INCLUDE_DIRS) + target_include_directories(claimtrie PRIVATE ${BIND_INCLUDE_DIRS}) endif() -add_library(leveldb STATIC ${LEVELDB_SRC}) - -target_include_directories(leveldb PRIVATE ../leveldb ../leveldb/include) - -if(WIN32) - target_compile_definitions(leveldb PRIVATE -DLEVELDB_PLATFORM_WINDOWS -DWINVER=0x0500 -D__USE_MINGW_ANSI_STDIO=1) -else() - target_compile_definitions(leveldb PRIVATE -DLEVELDB_PLATFORM_POSIX) -endif() - -target_compile_definitions(leveldb PRIVATE -DLEVELDB_ATOMIC_PRESENT -D__STDC_LIMIT_MACROS) - -target_link_libraries(claimtrie PRIVATE leveldb) -# leveldb depends end here - -# TODO remove BITCOIN depends -target_include_directories(claimtrie PRIVATE ../ ../leveldb/include) -# it's needed a configure call to create config files -target_compile_definitions(claimtrie PRIVATE -DHAVE_CONFIG_H) -# bitcoin depends end here - CPMAddPackage( NAME OpenSSL GITHUB_REPOSITORY openssl/openssl diff --git a/src/claimtrie/data.cpp b/src/claimtrie/data.cpp index 77a4ba70e..ecbd86ba4 100644 --- a/src/claimtrie/data.cpp +++ b/src/claimtrie/data.cpp @@ -77,8 +77,3 @@ CNameOutPointHeightType::CNameOutPointHeightType(std::string name, CTxOutPoint o : name(std::move(name)), outPoint(std::move(outPoint)), nValidHeight(nValidHeight) { } - -CClaimIndexElement::CClaimIndexElement(std::string name, CClaimValue claim) - : name(std::move(name)), claim(std::move(claim)) -{ -} diff --git a/src/claimtrie/data.h b/src/claimtrie/data.h index b1801521a..cb41c6be4 100644 --- a/src/claimtrie/data.h +++ b/src/claimtrie/data.h @@ -2,7 +2,7 @@ #ifndef CLAIMTRIE_DATA_H #define CLAIMTRIE_DATA_H -#include +#include #include #include @@ -29,7 +29,7 @@ namespace sqlite } } -#include +#include namespace sqlite { @@ -119,13 +119,4 @@ struct CNameOutPointHeightType CNameOutPointHeightType(std::string name, CTxOutPoint outPoint, int nValidHeight); }; -struct CClaimIndexElement -{ - std::string name; - CClaimValue claim; - - CClaimIndexElement() = default; - CClaimIndexElement(std::string name, CClaimValue claim); -}; - #endif // CLAIMTRIE_DATA_H diff --git a/src/claimtrie/libclaimtrie.i b/src/claimtrie/libclaimtrie.i new file mode 100644 index 000000000..38b268554 --- /dev/null +++ b/src/claimtrie/libclaimtrie.i @@ -0,0 +1,57 @@ + +%module libclaimtrie +%{ +#include "uints.h" +#include "txoutpoint.h" +#include "data.h" +#include "trie.h" +#include "forks.h" +%} + +%feature("directors", 1); +%feature("flatnested", 1); + +%include stl.i +%include stdint.i +%include std_pair.i + +%ignore CBaseBlob(CBaseBlob &&); +%ignore CClaimIndexElement(CClaimIndexElement &&); +%ignore CClaimNsupports(CClaimNsupports &&); +%ignore CClaimTrieProof(CClaimTrieProof &&); +%ignore CClaimTrieProofNode(CClaimTrieProofNode &&); +%ignore CClaimValue(CClaimValue &&); +%ignore CSupportValue(CSupportValue &&); +%ignore CTxOutPoint(CTxOutPoint &&); + +#define SWIG_INTERFACE + +%include "uints.h" +%include "txoutpoint.h" +%include "data.h" +%include "trie.h" +%include "forks.h" + +%template(CUint160) CBaseBlob<160>; +%template(CUint256) CBaseBlob<256>; +%template(uint8vec) std::vector; + +%template(claimEntryType) std::vector; +%template(supportEntryType) std::vector; +%template(claimsNsupports) std::vector; + +%template(proofPair) std::pair; +%template(proofNodePair) std::pair; +%template(claimUndoPair) std::pair; +%template(supportUndoPair) std::pair; +%template(takeoverUndoPair) std::pair>; + +%template(proofNodes) std::vector; +%template(proofPairs) std::vector>; +%template(proofNodeChildren) std::vector>; +%template(claimUndoType) std::vector; +%template(supportUndoType) std::vector; +%template(insertUndoType) std::vector; +%template(takeoverUndoType) std::vector; + +%rename(CClaimTrieCache) CClaimTrieCacheHashFork; diff --git a/src/claimtrie/libclaimtrie_test.py b/src/claimtrie/libclaimtrie_test.py new file mode 100644 index 000000000..558e5707b --- /dev/null +++ b/src/claimtrie/libclaimtrie_test.py @@ -0,0 +1,86 @@ + +from libclaimtrie import * +import unittest + +class TestClaimTrieTypes(unittest.TestCase): + def setUp(self): + self.uint256s = "1234567890987654321012345678909876543210123456789098765432101234" + self.uint160 = CUint160S("1234567890987654321012345678909876543210") + self.uint = CUint256S(self.uint256s) + self.txp = CTxOutPoint(self.uint, 1) + + def assertClaimEqual(self, claim, txo, cid, amount, effe, height, validHeight, msg): + self.assertEqual(claim.outPoint, txo, msg) + self.assertEqual(claim.claimId, cid, msg) + self.assertEqual(claim.nAmount, amount, msg) + self.assertEqual(claim.nEffectiveAmount, effe, msg) + self.assertEqual(claim.nHeight, height, msg) + self.assertEqual(claim.nValidAtHeight, validHeight, msg) + + def assertSupportEqual(self, support, txo, cid, amount, height, validHeight, msg): + self.assertEqual(support.outPoint, txo, msg) + self.assertEqual(support.supportedClaimId, cid, msg) + self.assertEqual(support.nAmount, amount, msg) + self.assertEqual(support.nHeight, height, msg) + self.assertEqual(support.nValidAtHeight, validHeight, msg) + + def test_uint256(self): + uint = self.uint + self.assertFalse(uint.IsNull(), "incorrect CUint256S or CBaseBlob::IsNull") + self.assertEqual(uint.GetHex(), self.uint256s, "incorrect CBaseBlob::GetHex") + self.assertEqual(uint.GetHex(), uint.ToString(), "incorrect CBaseBlob::ToString") + self.assertEqual(uint.size(), 32, "incorrect CBaseBlob::size") + copy = CUint256() + self.assertNotEqual(copy, uint, "incorrect CBaseBlob::operator!=") + self.assertTrue(copy.IsNull(), "incorrect CBaseBlob::IsNull") + copy = CUint256(uint) + self.assertEqual(copy, uint, "incorrect CBaseBlob::operator==") + copy.SetNull() + self.assertTrue(copy.IsNull()), "incorrect CBaseBlob::SetNull" + + def test_txoupoint(self): + txp = self.txp + uint = self.uint + self.assertEqual(txp.hash, uint, "incorrect CTxOutPoint::CTxOutPoint") + self.assertEqual(txp.n, 1, "incorrect CTxOutPoint::CTxOutPoint") + self.assertFalse(txp.IsNull(), "incorrect CTxOutPoint::IsNull") + pcopy = CTxOutPoint() + self.assertTrue(pcopy.IsNull(), "incorrect CTxOutPoint::IsNull") + self.assertEqual(pcopy.hash, CUint256(), "incorrect CTxOutPoint::CTxOutPoint") + self.assertNotEqual(pcopy, txp, "incorrect CTxOutPoint::operator!=") + self.assertIn(uint.ToString()[:10], txp.ToString(), "incorrect CTxOutPoint::ToString") + + def test_claim(self): + txp = self.txp + uint160 = self.uint160 + self.assertEqual(uint160.size(), 20, "incorrect CBaseBlob::size") + claim = CClaimValue(txp, uint160, 20, 1, 10) + self.assertClaimEqual(claim, txp, uint160, 20, 20, 1, 10, "incorrect CClaimValue::CClaimValue") + + def test_support(self): + txp = self.txp + uint160 = self.uint160 + claim = CClaimValue(txp, uint160, 20, 1, 10) + support = CSupportValue(txp, uint160, 20, 1, 10) + self.assertSupportEqual(support, claim.outPoint, claim.claimId, claim.nAmount, claim.nHeight, claim.nValidAtHeight, "incorrect CSupportValue::CSupportValue") + + def test_claimtrie(self): + txp = self.txp + uint160 = self.uint160 + claim = CClaimValue(txp, uint160, 20, 1, 10) + data = CClaimTrieData() + data.insertClaim(claim) + wipe = True; height = 0; data_dir = "." + trie = CClaimTrie(wipe, height, data_dir) + cache = CClaimTrieCacheBase(trie) + self.assertTrue(cache.empty(), "incorrect CClaimtrieCache::empty") + self.assertFalse(cache.haveClaim("test", txp), "incorrect CClaimtrieCache::haveClaim") + self.assertTrue(cache.addClaim("tes", txp, uint160, 20, 0), "incorrect CClaimtrieCache::addClaim") + self.assertEqual(cache.getTotalNamesInTrie(), 1, "incorrect CClaimtrieCache::getTotalNamesInTrie") + self.assertEqual(cache.getTotalClaimsInTrie(), 1, "incorrect CClaimtrieCache::getTotalClaimsInTrie") + claimsToName = cache.getClaimsForName("test") + claims = claimsToName.claimsNsupports + self.assertEqual(claims.size(), 1, "incorrect CClaimTrieCache::getClaimsForName") + self.assertFalse(claims[0].IsNull(), "incorrect CClaimNsupports::IsNull") + +unittest.main() diff --git a/src/claimtrie/trie.cpp b/src/claimtrie/trie.cpp index 9045b7438..d765ca7ba 100644 --- a/src/claimtrie/trie.cpp +++ b/src/claimtrie/trie.cpp @@ -452,7 +452,7 @@ CUint256 CClaimTrieCacheBase::recursiveComputeMerkleHash(const std::string& name std::vector, int>> children; childHashQuery << name >> [&children](std::string name, std::unique_ptr hash, int takeoverHeight) { children.push_back(std::make_tuple(std::move(name), std::move(hash), takeoverHeight)); - } + }; childHashQuery++; for (auto& child: children) { @@ -460,7 +460,7 @@ CUint256 CClaimTrieCacheBase::recursiveComputeMerkleHash(const std::string& name auto& hash = std::get<1>(child); if (!hash) hash = std::make_unique(); if (hash->IsNull()) - hash = recursiveComputeMerkleHash(name, std::get<2>(child), checkOnly); + *hash = recursiveComputeMerkleHash(name, std::get<2>(child), checkOnly); completeHash(*hash, name, pos); vchToHash.push_back(name[pos]); vchToHash.insert(vchToHash.end(), hash->begin(), hash->end()); diff --git a/src/claimtrie/trie.h b/src/claimtrie/trie.h index f4a9fe651..7caf4ff74 100644 --- a/src/claimtrie/trie.h +++ b/src/claimtrie/trie.h @@ -55,17 +55,18 @@ class CClaimTrie friend class CClaimTrieCacheHashFork; friend class CClaimTrieCacheExpirationFork; friend class CClaimTrieCacheNormalizationFork; + public: CClaimTrie() = default; CClaimTrie(CClaimTrie&&) = delete; CClaimTrie(const CClaimTrie&) = delete; CClaimTrie(bool fWipe, int height, const std::string& dataDir, - int nNormalizedNameForkHeight, - int64_t nOriginalClaimExpirationTime, - int64_t nExtendedClaimExpirationTime, - int64_t nExtendedClaimExpirationForkHeight, - int64_t nAllClaimsInMerkleForkHeight, + int nNormalizedNameForkHeight = -1, + int64_t nOriginalClaimExpirationTime = -1, + int64_t nExtendedClaimExpirationTime = -1, + int64_t nExtendedClaimExpirationForkHeight = -1, + int64_t nAllClaimsInMerkleForkHeight = -1, int proportionalDelayFactor = 32); CClaimTrie& operator=(CClaimTrie&&) = delete; @@ -77,7 +78,7 @@ public: protected: int nNextHeight = 0; sqlite::database db; - const int nProportionalDelayFactor = 0; + const int nProportionalDelayFactor = 1; const int nNormalizedNameForkHeight = -1; const int64_t nOriginalClaimExpirationTime = -1; @@ -90,6 +91,7 @@ struct CClaimTrieProofNode { CClaimTrieProofNode(std::vector> children, bool hasValue, CUint256 valHash); + CClaimTrieProofNode() = default; CClaimTrieProofNode(CClaimTrieProofNode&&) = default; CClaimTrieProofNode(const CClaimTrieProofNode&) = default; CClaimTrieProofNode& operator=(CClaimTrieProofNode&&) = default; @@ -118,10 +120,20 @@ struct CClaimTrieProof template using queueEntryType = std::pair; -typedef std::vector> claimUndoType; -typedef std::vector> supportUndoType; +#ifdef SWIG_INTERFACE // swig has a problem with using in typedef +using claimUndoPair = std::pair; +using supportUndoPair = std::pair; +using takeoverUndoPair = std::pair>; +#else +using claimUndoPair = queueEntryType; +using supportUndoPair = queueEntryType; +using takeoverUndoPair = queueEntryType>; +#endif + +typedef std::vector claimUndoType; +typedef std::vector supportUndoType; typedef std::vector insertUndoType; -typedef std::vector>> takeoverUndoType; +typedef std::vector takeoverUndoType; class CClaimTrieCacheBase { diff --git a/src/claimtrie/txoutpoint.h b/src/claimtrie/txoutpoint.h index 3433f4575..3b9426512 100644 --- a/src/claimtrie/txoutpoint.h +++ b/src/claimtrie/txoutpoint.h @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -34,4 +35,8 @@ public: std::string ToString() const; }; +#ifndef SWIG_INTERFACE + + +#endif // SWIG_INTERFACE #endif // CLAIMTRIE_TXOUTPUT_H diff --git a/src/claimtrie_serial.h b/src/claimtrie_serial.h index e78db0244..60599f167 100644 --- a/src/claimtrie_serial.h +++ b/src/claimtrie_serial.h @@ -88,18 +88,4 @@ void Unserialize(Stream& s, CNameOutPointHeightType& u) Unserialize(s, u.nValidHeight); } -template -void Serialize(Stream& s, const CClaimIndexElement& u) -{ - Serialize(s, u.name); - Serialize(s, u.claim); -} - -template -void Unserialize(Stream& s, CClaimIndexElement& u) -{ - Unserialize(s, u.name); - Unserialize(s, u.claim); -} - #endif // CLAIMTRIE_SERIAL_H diff --git a/src/init.cpp b/src/init.cpp index a0c9fd7be..50975c7b0 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1586,7 +1586,7 @@ bool AppInitMain(InitInterfaces& interfaces) } auto tip = chainActive.Tip(); assert(tip); - if (!CClaimTrieCache(pclaimTrie).validateDb(tip->hashClaimTrie)) + if (!CClaimTrieCache(pclaimTrie).validateDb(tip->hashClaimTrie)) { strLoadError = _("Error loading the claim trie from disk"); break; } diff --git a/src/test/claimtriebranching_tests.cpp b/src/test/claimtriebranching_tests.cpp index dd292f657..78de6120b 100644 --- a/src/test/claimtriebranching_tests.cpp +++ b/src/test/claimtriebranching_tests.cpp @@ -440,15 +440,15 @@ BOOST_AUTO_TEST_CASE(claimtrie_update_takeover_test) fixture.getLastTakeoverForName("test", cid2, takeover); CClaimValue value; BOOST_REQUIRE(fixture.getInfoForName("test", value) && value.nAmount == 3); - BOOST_CHECK_EQUAL(cid, cid2); + BOOST_CHECK_EQUAL(cid, uint160(cid2)); BOOST_CHECK_EQUAL(height, takeover); fixture.DecrementBlocks(1); fixture.getLastTakeoverForName("test", cid2, takeover); - BOOST_CHECK_EQUAL(cid, cid2); + BOOST_CHECK_EQUAL(cid, uint160(cid2)); BOOST_CHECK_EQUAL(height, takeover); fixture.DecrementBlocks(1); fixture.getLastTakeoverForName("test", cid2, takeover); - BOOST_CHECK_EQUAL(cid, cid2); + BOOST_CHECK_EQUAL(cid, uint160(cid2)); BOOST_CHECK_EQUAL(height, takeover); } @@ -1924,7 +1924,7 @@ BOOST_AUTO_TEST_CASE(update_on_support2_test) int lastTakeover; BOOST_CHECK(fixture.getLastTakeoverForName(name, claimId, lastTakeover)); BOOST_CHECK_EQUAL(lastTakeover, height + 1); - BOOST_CHECK_EQUAL(ClaimIdHash(tx1.GetHash(), 0), claimId); + BOOST_CHECK_EQUAL(ClaimIdHash(tx1.GetHash(), 0), uint160(claimId)); fixture.Spend(s1); fixture.Spend(s2); diff --git a/src/test/claimtrieexpirationfork_tests.cpp b/src/test/claimtrieexpirationfork_tests.cpp index a7d2837ea..2ad8e5eeb 100644 --- a/src/test/claimtrieexpirationfork_tests.cpp +++ b/src/test/claimtrieexpirationfork_tests.cpp @@ -276,9 +276,6 @@ BOOST_AUTO_TEST_CASE(hardfork_disk_test) BOOST_CHECK_EQUAL(fixture.expirationTime(), 3); fixture.IncrementBlocks(7, true); BOOST_CHECK_EQUAL(fixture.expirationTime(), 6); - auto tip = chainActive.Tip(); - pclaimTrie->ReadFromDisk(tip->nHeight, tip->hashClaimTrie); - BOOST_CHECK_EQUAL(fixture.expirationTime(), 6); // Create a claim and support 1 block before the fork height that will expire after the fork height. // Reset to disk, increment past the fork height and make sure we get @@ -288,8 +285,6 @@ BOOST_AUTO_TEST_CASE(hardfork_disk_test) CMutableTransaction s1 = fixture.MakeSupport(fixture.GetCoinbase(), tx1, "test", 1); fixture.IncrementBlocks(1); - tip = chainActive.Tip(); - pclaimTrie->ReadFromDisk(tip->nHeight, tip->hashClaimTrie); BOOST_CHECK_EQUAL(fixture.expirationTime(), 3); fixture.IncrementBlocks(1); BOOST_CHECK_EQUAL(fixture.expirationTime(), 6); @@ -310,8 +305,7 @@ BOOST_AUTO_TEST_CASE(hardfork_disk_test) CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(),"test2","one",1); CMutableTransaction s2 = fixture.MakeSupport(fixture.GetCoinbase(),tx2,"test2",1); fixture.IncrementBlocks(1); - tip = chainActive.Tip(); - pclaimTrie->ReadFromDisk(tip->nHeight, tip->hashClaimTrie); + CMutableTransaction u2 = fixture.MakeUpdate(tx2, "test2", "two", ClaimIdHash(tx2.GetHash(), 0), 1); // increment to fork fixture.IncrementBlocks(2); diff --git a/src/test/claimtriefixture.h b/src/test/claimtriefixture.h index 7ffd0a158..44d82e334 100644 --- a/src/test/claimtriefixture.h +++ b/src/test/claimtriefixture.h @@ -28,6 +28,8 @@ extern ::CChainState g_chainstate; extern ::ArgsManager gArgs; +extern std::vector random_strings(std::size_t count); + CMutableTransaction BuildTransaction(const uint256& prevhash); CMutableTransaction BuildTransaction(const CTransaction& prev, uint32_t prevout=0, unsigned int numOutputs=1, int locktime=0);