mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-04-05 05:14:51 +02:00
Merge bitcoin/bitcoin#32520: Remove legacy Parse(U)Int*
faf55fc80bdoc: Remove ParseInt mentions in documentation (MarcoFalke)3333282933refactor: Remove unused Parse(U)Int* (MarcoFalke)fa84e6c36cbitcoin-tx: Reject + sign in MutateTxDel* (MarcoFalke)face2519fabitcoin-tx: Reject + sign in vout parsing (MarcoFalke)fa8acaf0b9bitcoin-tx: Reject + sign in replaceable parsing (MarcoFalke)faff25a558bitcoin-tx: Reject + sign in locktime (MarcoFalke)dddd9e5fe3bitcoin-tx: Reject + sign in nversion parsing (MarcoFalke)fab06ac037rest: Use SAFE_CHARS_URI in SanitizeString error msg (MarcoFalke)8888bb499drest: Reject + sign in /blockhashbyheight/ (MarcoFalke)fafd43c691test: Reject + sign when parsing regtest deployment params (MarcoFalke)fa123afa0eReject + sign when checking -ipcfd (MarcoFalke)fa479857edReject + sign in SplitHostPort (MarcoFalke)fab4c2967dnet: Reject + sign when parsing subnet mask (MarcoFalke)fa89652e68init: Reject + sign in -*port parsing (MarcoFalke)fa9c45577dcli: Reject + sign in -netinfo level parsing (MarcoFalke)fa98041325refactor: Use ToIntegral in CreateFromDump (MarcoFalke)fa23ed7fc2refactor: Use ToIntegral in ParseHDKeypath (MarcoFalke) Pull request description: The legacy int parsing is problematic, because it accepts the `+` sign for unsigned integers. In all cases this is either: * Useless, because the `+` sign was already rejected. * Erroneous and inconsistent, when third party parsers reject it. (C.f. https://github.com/bitcoin/bitcoin/pull/32365) * Confusing, because the `+` sign is neither documented, nor can it be assumed to be present. Fix all issues by removing the legacy int parsing. ACKs for top commit: stickies-v: re-ACKfaf55fc80bbrunoerg: code review ACKfaf55fc80bTree-SHA512: a311ab6a58fe02a37741c1800feb3dcfad92377b4bfb61b433b2393f52ba89ef45d00940972b2767b213a3dd7b59e5e35d5b659c586eacdfe4e565a77b12b19f
This commit is contained in:
@@ -1009,10 +1009,6 @@ Strings and formatting
|
||||
buffer overflows, and surprises with `\0` characters. Also, some C string manipulations
|
||||
tend to act differently depending on platform, or even the user locale.
|
||||
|
||||
- Use `ToIntegral` from [`strencodings.h`](/src/util/strencodings.h) for number parsing. In legacy code you might also find `ParseInt*` family of functions, `ParseDouble` or `LocaleIndependentAtoi`.
|
||||
|
||||
- *Rationale*: These functions do overflow checking and avoid pesky locale issues.
|
||||
|
||||
- For `strprintf`, `LogInfo`, `LogDebug`, etc formatting characters don't need size specifiers.
|
||||
|
||||
- *Rationale*: Bitcoin Core uses tinyformat, which is type safe. Leave them out to avoid confusion.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2022 The Bitcoin Core developers
|
||||
// Copyright (c) 2009-present The Bitcoin Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
@@ -472,7 +472,8 @@ public:
|
||||
{
|
||||
if (!args.empty()) {
|
||||
uint8_t n{0};
|
||||
if (ParseUInt8(args.at(0), &n)) {
|
||||
if (const auto res{ToIntegral<uint8_t>(args.at(0))}) {
|
||||
n = *res;
|
||||
m_details_level = std::min(n, NETINFO_MAX_LEVEL);
|
||||
} else {
|
||||
throw std::runtime_error(strprintf("invalid -netinfo level argument: %s\nFor more information, run: bitcoin-cli -netinfo help", args.at(0)));
|
||||
|
||||
@@ -211,35 +211,33 @@ static CAmount ExtractAndValidateValue(const std::string& strValue)
|
||||
|
||||
static void MutateTxVersion(CMutableTransaction& tx, const std::string& cmdVal)
|
||||
{
|
||||
uint32_t newVersion;
|
||||
if (!ParseUInt32(cmdVal, &newVersion) || newVersion < 1 || newVersion > TX_MAX_STANDARD_VERSION) {
|
||||
const auto ver{ToIntegral<uint32_t>(cmdVal)};
|
||||
if (!ver || *ver < 1 || *ver > TX_MAX_STANDARD_VERSION) {
|
||||
throw std::runtime_error("Invalid TX version requested: '" + cmdVal + "'");
|
||||
}
|
||||
|
||||
tx.version = newVersion;
|
||||
tx.version = *ver;
|
||||
}
|
||||
|
||||
static void MutateTxLocktime(CMutableTransaction& tx, const std::string& cmdVal)
|
||||
{
|
||||
int64_t newLocktime;
|
||||
if (!ParseInt64(cmdVal, &newLocktime) || newLocktime < 0LL || newLocktime > 0xffffffffLL)
|
||||
const auto locktime{ToIntegral<uint32_t>(cmdVal)};
|
||||
if (!locktime) {
|
||||
throw std::runtime_error("Invalid TX locktime requested: '" + cmdVal + "'");
|
||||
|
||||
tx.nLockTime = (unsigned int) newLocktime;
|
||||
}
|
||||
tx.nLockTime = *locktime;
|
||||
}
|
||||
|
||||
static void MutateTxRBFOptIn(CMutableTransaction& tx, const std::string& strInIdx)
|
||||
{
|
||||
// parse requested index
|
||||
int64_t inIdx = -1;
|
||||
if (strInIdx != "" && (!ParseInt64(strInIdx, &inIdx) || inIdx < 0 || inIdx >= static_cast<int64_t>(tx.vin.size()))) {
|
||||
const auto idx{ToIntegral<uint32_t>(strInIdx)};
|
||||
if (strInIdx != "" && (!idx || *idx >= tx.vin.size())) {
|
||||
throw std::runtime_error("Invalid TX input index '" + strInIdx + "'");
|
||||
}
|
||||
|
||||
// set the nSequence to MAX_INT - 2 (= RBF opt in flag)
|
||||
int cnt = 0;
|
||||
uint32_t cnt{0};
|
||||
for (CTxIn& txin : tx.vin) {
|
||||
if (strInIdx == "" || cnt == inIdx) {
|
||||
if (strInIdx == "" || cnt == *idx) {
|
||||
if (txin.nSequence > MAX_BIP125_RBF_SEQUENCE) {
|
||||
txin.nSequence = MAX_BIP125_RBF_SEQUENCE;
|
||||
}
|
||||
@@ -277,9 +275,10 @@ static void MutateTxAddInput(CMutableTransaction& tx, const std::string& strInpu
|
||||
|
||||
// extract and validate vout
|
||||
const std::string& strVout = vStrInputParts[1];
|
||||
int64_t vout;
|
||||
if (!ParseInt64(strVout, &vout) || vout < 0 || vout > static_cast<int64_t>(maxVout))
|
||||
const auto vout{ToIntegral<uint32_t>(strVout)};
|
||||
if (!vout || *vout > maxVout) {
|
||||
throw std::runtime_error("invalid TX input vout '" + strVout + "'");
|
||||
}
|
||||
|
||||
// extract the optional sequence number
|
||||
uint32_t nSequenceIn = CTxIn::SEQUENCE_FINAL;
|
||||
@@ -288,7 +287,7 @@ static void MutateTxAddInput(CMutableTransaction& tx, const std::string& strInpu
|
||||
}
|
||||
|
||||
// append to transaction input list
|
||||
CTxIn txin(*txid, vout, CScript(), nSequenceIn);
|
||||
CTxIn txin{*txid, *vout, CScript{}, nSequenceIn};
|
||||
tx.vin.push_back(txin);
|
||||
}
|
||||
|
||||
@@ -508,26 +507,20 @@ static void MutateTxAddOutScript(CMutableTransaction& tx, const std::string& str
|
||||
|
||||
static void MutateTxDelInput(CMutableTransaction& tx, const std::string& strInIdx)
|
||||
{
|
||||
// parse requested deletion index
|
||||
int64_t inIdx;
|
||||
if (!ParseInt64(strInIdx, &inIdx) || inIdx < 0 || inIdx >= static_cast<int64_t>(tx.vin.size())) {
|
||||
const auto idx{ToIntegral<uint32_t>(strInIdx)};
|
||||
if (!idx || idx >= tx.vin.size()) {
|
||||
throw std::runtime_error("Invalid TX input index '" + strInIdx + "'");
|
||||
}
|
||||
|
||||
// delete input from transaction
|
||||
tx.vin.erase(tx.vin.begin() + inIdx);
|
||||
tx.vin.erase(tx.vin.begin() + *idx);
|
||||
}
|
||||
|
||||
static void MutateTxDelOutput(CMutableTransaction& tx, const std::string& strOutIdx)
|
||||
{
|
||||
// parse requested deletion index
|
||||
int64_t outIdx;
|
||||
if (!ParseInt64(strOutIdx, &outIdx) || outIdx < 0 || outIdx >= static_cast<int64_t>(tx.vout.size())) {
|
||||
const auto idx{ToIntegral<uint32_t>(strOutIdx)};
|
||||
if (!idx || idx >= tx.vout.size()) {
|
||||
throw std::runtime_error("Invalid TX output index '" + strOutIdx + "'");
|
||||
}
|
||||
|
||||
// delete output from transaction
|
||||
tx.vout.erase(tx.vout.begin() + outIdx);
|
||||
tx.vout.erase(tx.vout.begin() + *idx);
|
||||
}
|
||||
|
||||
static const unsigned int N_SIGHASH_OPTS = 7;
|
||||
|
||||
@@ -53,14 +53,14 @@ void ReadRegTestArgs(const ArgsManager& args, CChainParams::RegTestOptions& opti
|
||||
}
|
||||
|
||||
const auto value{arg.substr(found + 1)};
|
||||
int32_t height;
|
||||
if (!ParseInt32(value, &height) || height < 0 || height >= std::numeric_limits<int>::max()) {
|
||||
const auto height{ToIntegral<int32_t>(value)};
|
||||
if (!height || *height < 0 || *height >= std::numeric_limits<int>::max()) {
|
||||
throw std::runtime_error(strprintf("Invalid height value (%s) for -testactivationheight=name@height.", arg));
|
||||
}
|
||||
|
||||
const auto deployment_name{arg.substr(0, found)};
|
||||
if (const auto buried_deployment = GetBuriedDeployment(deployment_name)) {
|
||||
options.activation_heights[*buried_deployment] = height;
|
||||
options.activation_heights[*buried_deployment] = *height;
|
||||
} else {
|
||||
throw std::runtime_error(strprintf("Invalid name (%s) for -testactivationheight=name@height.", arg));
|
||||
}
|
||||
@@ -72,16 +72,22 @@ void ReadRegTestArgs(const ArgsManager& args, CChainParams::RegTestOptions& opti
|
||||
throw std::runtime_error("Version bits parameters malformed, expecting deployment:start:end[:min_activation_height]");
|
||||
}
|
||||
CChainParams::VersionBitsParameters vbparams{};
|
||||
if (!ParseInt64(vDeploymentParams[1], &vbparams.start_time)) {
|
||||
const auto start_time{ToIntegral<int64_t>(vDeploymentParams[1])};
|
||||
if (!start_time) {
|
||||
throw std::runtime_error(strprintf("Invalid nStartTime (%s)", vDeploymentParams[1]));
|
||||
}
|
||||
if (!ParseInt64(vDeploymentParams[2], &vbparams.timeout)) {
|
||||
vbparams.start_time = *start_time;
|
||||
const auto timeout{ToIntegral<int64_t>(vDeploymentParams[2])};
|
||||
if (!timeout) {
|
||||
throw std::runtime_error(strprintf("Invalid nTimeout (%s)", vDeploymentParams[2]));
|
||||
}
|
||||
vbparams.timeout = *timeout;
|
||||
if (vDeploymentParams.size() >= 4) {
|
||||
if (!ParseInt32(vDeploymentParams[3], &vbparams.min_activation_height)) {
|
||||
const auto min_activation_height{ToIntegral<int64_t>(vDeploymentParams[3])};
|
||||
if (!min_activation_height) {
|
||||
throw std::runtime_error(strprintf("Invalid min_activation_height (%s)", vDeploymentParams[3]));
|
||||
}
|
||||
vbparams.min_activation_height = *min_activation_height;
|
||||
} else {
|
||||
vbparams.min_activation_height = 0;
|
||||
}
|
||||
|
||||
@@ -1151,8 +1151,8 @@ bool CheckHostPortOptions(const ArgsManager& args) {
|
||||
"-rpcport",
|
||||
}) {
|
||||
if (const auto port{args.GetArg(port_option)}) {
|
||||
uint16_t n;
|
||||
if (!ParseUInt16(*port, &n) || n == 0) {
|
||||
const auto n{ToIntegral<uint16_t>(*port)};
|
||||
if (!n || *n == 0) {
|
||||
return InitError(InvalidPortErrMsg(port_option, *port));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,9 +55,11 @@ public:
|
||||
// in combination with other arguments because the parent process
|
||||
// should be able to control the child process through the IPC protocol
|
||||
// without passing information out of band.
|
||||
if (!ParseInt32(argv[2], &fd)) {
|
||||
const auto maybe_fd{ToIntegral<int32_t>(argv[2])};
|
||||
if (!maybe_fd) {
|
||||
throw std::runtime_error(strprintf("Invalid -ipcfd number '%s'", argv[2]));
|
||||
}
|
||||
fd = *maybe_fd;
|
||||
return true;
|
||||
}
|
||||
int connect(const fs::path& data_dir,
|
||||
|
||||
@@ -829,10 +829,9 @@ CSubNet LookupSubNet(const std::string& subnet_str)
|
||||
addr = static_cast<CNetAddr>(MaybeFlipIPv6toCJDNS(CService{addr.value(), /*port=*/0}));
|
||||
if (slash_pos != subnet_str.npos) {
|
||||
const std::string netmask_str{subnet_str.substr(slash_pos + 1)};
|
||||
uint8_t netmask;
|
||||
if (ParseUInt8(netmask_str, &netmask)) {
|
||||
if (const auto netmask{ToIntegral<uint8_t>(netmask_str)}) {
|
||||
// Valid number; assume CIDR variable-length subnet masking.
|
||||
subnet = CSubNet{addr.value(), netmask};
|
||||
subnet = CSubNet{addr.value(), *netmask};
|
||||
} else {
|
||||
// Invalid number; try full netmask syntax. Never allow lookup for netmask.
|
||||
const std::optional<CNetAddr> full_netmask{LookupHost(netmask_str, /*fAllowLookup=*/false)};
|
||||
|
||||
10
src/rest.cpp
10
src/rest.cpp
@@ -962,9 +962,9 @@ static bool rest_blockhash_by_height(const std::any& context, HTTPRequest* req,
|
||||
std::string height_str;
|
||||
const RESTResponseFormat rf = ParseDataFormat(height_str, str_uri_part);
|
||||
|
||||
int32_t blockheight = -1; // Initialization done only to prevent valgrind false positive, see https://github.com/bitcoin/bitcoin/pull/18785
|
||||
if (!ParseInt32(height_str, &blockheight) || blockheight < 0) {
|
||||
return RESTERR(req, HTTP_BAD_REQUEST, "Invalid height: " + SanitizeString(height_str));
|
||||
const auto blockheight{ToIntegral<int32_t>(height_str)};
|
||||
if (!blockheight || *blockheight < 0) {
|
||||
return RESTERR(req, HTTP_BAD_REQUEST, "Invalid height: " + SanitizeString(height_str, SAFE_CHARS_URI));
|
||||
}
|
||||
|
||||
CBlockIndex* pblockindex = nullptr;
|
||||
@@ -974,10 +974,10 @@ static bool rest_blockhash_by_height(const std::any& context, HTTPRequest* req,
|
||||
ChainstateManager& chainman = *maybe_chainman;
|
||||
LOCK(cs_main);
|
||||
const CChain& active_chain = chainman.ActiveChain();
|
||||
if (blockheight > active_chain.Height()) {
|
||||
if (*blockheight > active_chain.Height()) {
|
||||
return RESTERR(req, HTTP_NOT_FOUND, "Block height out of range");
|
||||
}
|
||||
pblockindex = active_chain[blockheight];
|
||||
pblockindex = active_chain[*blockheight];
|
||||
}
|
||||
switch (rf) {
|
||||
case RESTResponseFormat::BINARY: {
|
||||
|
||||
@@ -46,16 +46,8 @@ FUZZ_TARGET(locale)
|
||||
assert(c_locale != nullptr);
|
||||
|
||||
const std::string random_string = fuzzed_data_provider.ConsumeRandomLengthString(5);
|
||||
int32_t parseint32_out_without_locale;
|
||||
const bool parseint32_without_locale = ParseInt32(random_string, &parseint32_out_without_locale);
|
||||
int64_t parseint64_out_without_locale;
|
||||
const bool parseint64_without_locale = ParseInt64(random_string, &parseint64_out_without_locale);
|
||||
const int64_t random_int64 = fuzzed_data_provider.ConsumeIntegral<int64_t>();
|
||||
const std::string tostring_without_locale = util::ToString(random_int64);
|
||||
// The variable `random_int32` is no longer used, but the harness still needs to
|
||||
// consume the same data that it did previously to not invalidate existing seeds.
|
||||
const int32_t random_int32 = fuzzed_data_provider.ConsumeIntegral<int32_t>();
|
||||
(void)random_int32;
|
||||
const std::string strprintf_int_without_locale = strprintf("%d", random_int64);
|
||||
const double random_double = fuzzed_data_provider.ConsumeFloatingPoint<double>();
|
||||
const std::string strprintf_double_without_locale = strprintf("%f", random_double);
|
||||
@@ -63,18 +55,6 @@ FUZZ_TARGET(locale)
|
||||
const char* new_locale = std::setlocale(LC_ALL, locale_identifier.c_str());
|
||||
assert(new_locale != nullptr);
|
||||
|
||||
int32_t parseint32_out_with_locale;
|
||||
const bool parseint32_with_locale = ParseInt32(random_string, &parseint32_out_with_locale);
|
||||
assert(parseint32_without_locale == parseint32_with_locale);
|
||||
if (parseint32_without_locale) {
|
||||
assert(parseint32_out_without_locale == parseint32_out_with_locale);
|
||||
}
|
||||
int64_t parseint64_out_with_locale;
|
||||
const bool parseint64_with_locale = ParseInt64(random_string, &parseint64_out_with_locale);
|
||||
assert(parseint64_without_locale == parseint64_with_locale);
|
||||
if (parseint64_without_locale) {
|
||||
assert(parseint64_out_without_locale == parseint64_out_with_locale);
|
||||
}
|
||||
const std::string tostring_with_locale = util::ToString(random_int64);
|
||||
assert(tostring_without_locale == tostring_with_locale);
|
||||
const std::string strprintf_int_with_locale = strprintf("%d", random_int64);
|
||||
|
||||
@@ -5,33 +5,59 @@
|
||||
#include <test/fuzz/fuzz.h>
|
||||
#include <util/moneystr.h>
|
||||
#include <util/strencodings.h>
|
||||
#include <util/string.h>
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
FUZZ_TARGET(parse_numbers)
|
||||
{
|
||||
const std::string random_string(buffer.begin(), buffer.end());
|
||||
{
|
||||
const auto i8{ToIntegral<int8_t>(random_string)};
|
||||
const auto u8{ToIntegral<uint8_t>(random_string)};
|
||||
const auto i16{ToIntegral<int16_t>(random_string)};
|
||||
const auto u16{ToIntegral<uint16_t>(random_string)};
|
||||
const auto i32{ToIntegral<int32_t>(random_string)};
|
||||
const auto u32{ToIntegral<uint32_t>(random_string)};
|
||||
const auto i64{ToIntegral<int64_t>(random_string)};
|
||||
const auto u64{ToIntegral<uint64_t>(random_string)};
|
||||
// Dont check any values, just that each success result must fit into
|
||||
// the one with the largest bit-width.
|
||||
if (i8) {
|
||||
assert(i8 == i64);
|
||||
}
|
||||
if (u8) {
|
||||
assert(u8 == u64);
|
||||
}
|
||||
if (i16) {
|
||||
assert(i16 == i64);
|
||||
}
|
||||
if (u16) {
|
||||
assert(u16 == u64);
|
||||
}
|
||||
if (i32) {
|
||||
assert(i32 == i64);
|
||||
}
|
||||
if (u32) {
|
||||
assert(u32 == u64);
|
||||
}
|
||||
constexpr auto digits{"0123456789"};
|
||||
if (i64) {
|
||||
assert(util::RemovePrefixView(random_string, "-").find_first_not_of(digits) == std::string::npos);
|
||||
}
|
||||
if (u64) {
|
||||
assert(random_string.find_first_not_of(digits) == std::string::npos);
|
||||
}
|
||||
}
|
||||
|
||||
(void)ParseMoney(random_string);
|
||||
|
||||
uint8_t u8;
|
||||
(void)ParseUInt8(random_string, &u8);
|
||||
|
||||
uint16_t u16;
|
||||
(void)ParseUInt16(random_string, &u16);
|
||||
|
||||
int32_t i32;
|
||||
(void)ParseInt32(random_string, &i32);
|
||||
(void)LocaleIndependentAtoi<int>(random_string);
|
||||
|
||||
uint32_t u32;
|
||||
(void)ParseUInt32(random_string, &u32);
|
||||
|
||||
int64_t i64;
|
||||
(void)LocaleIndependentAtoi<int64_t>(random_string);
|
||||
(void)ParseFixedPoint(random_string, 3, &i64);
|
||||
(void)ParseInt64(random_string, &i64);
|
||||
|
||||
uint64_t u64;
|
||||
(void)ParseUInt64(random_string, &u64);
|
||||
}
|
||||
|
||||
@@ -150,7 +150,6 @@ BOOST_AUTO_TEST_CASE(embedded_test)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(subnet_test)
|
||||
{
|
||||
|
||||
BOOST_CHECK(LookupSubNet("1.2.3.0/24") == LookupSubNet("1.2.3.0/255.255.255.0"));
|
||||
BOOST_CHECK(LookupSubNet("1.2.3.0/24") != LookupSubNet("1.2.4.0/255.255.255.0"));
|
||||
BOOST_CHECK(LookupSubNet("1.2.3.0/24").Match(ResolveIP("1.2.3.4")));
|
||||
@@ -185,6 +184,7 @@ BOOST_AUTO_TEST_CASE(subnet_test)
|
||||
// Check valid/invalid
|
||||
BOOST_CHECK(LookupSubNet("1.2.3.0/0").IsValid());
|
||||
BOOST_CHECK(!LookupSubNet("1.2.3.0/-1").IsValid());
|
||||
BOOST_CHECK(!LookupSubNet("1.2.3.0/+24").IsValid());
|
||||
BOOST_CHECK(LookupSubNet("1.2.3.0/32").IsValid());
|
||||
BOOST_CHECK(!LookupSubNet("1.2.3.0/33").IsValid());
|
||||
BOOST_CHECK(!LookupSubNet("1.2.3.0/300").IsValid());
|
||||
|
||||
@@ -648,40 +648,6 @@ BOOST_AUTO_TEST_CASE(util_overflow)
|
||||
TestAddMatrix<signed>();
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_ParseInt32)
|
||||
{
|
||||
int32_t n;
|
||||
// Valid values
|
||||
BOOST_CHECK(ParseInt32("1234", nullptr));
|
||||
BOOST_CHECK(ParseInt32("0", &n) && n == 0);
|
||||
BOOST_CHECK(ParseInt32("1234", &n) && n == 1234);
|
||||
BOOST_CHECK(ParseInt32("01234", &n) && n == 1234); // no octal
|
||||
BOOST_CHECK(ParseInt32("2147483647", &n) && n == 2147483647);
|
||||
BOOST_CHECK(ParseInt32("-2147483648", &n) && n == (-2147483647 - 1)); // (-2147483647 - 1) equals INT_MIN
|
||||
BOOST_CHECK(ParseInt32("-1234", &n) && n == -1234);
|
||||
BOOST_CHECK(ParseInt32("00000000000000001234", &n) && n == 1234);
|
||||
BOOST_CHECK(ParseInt32("-00000000000000001234", &n) && n == -1234);
|
||||
BOOST_CHECK(ParseInt32("00000000000000000000", &n) && n == 0);
|
||||
BOOST_CHECK(ParseInt32("-00000000000000000000", &n) && n == 0);
|
||||
// Invalid values
|
||||
BOOST_CHECK(!ParseInt32("", &n));
|
||||
BOOST_CHECK(!ParseInt32(" 1", &n)); // no padding inside
|
||||
BOOST_CHECK(!ParseInt32("1 ", &n));
|
||||
BOOST_CHECK(!ParseInt32("++1", &n));
|
||||
BOOST_CHECK(!ParseInt32("+-1", &n));
|
||||
BOOST_CHECK(!ParseInt32("-+1", &n));
|
||||
BOOST_CHECK(!ParseInt32("--1", &n));
|
||||
BOOST_CHECK(!ParseInt32("1a", &n));
|
||||
BOOST_CHECK(!ParseInt32("aap", &n));
|
||||
BOOST_CHECK(!ParseInt32("0x1", &n)); // no hex
|
||||
BOOST_CHECK(!ParseInt32(STRING_WITH_EMBEDDED_NULL_CHAR, &n));
|
||||
// Overflow and underflow
|
||||
BOOST_CHECK(!ParseInt32("-2147483649", nullptr));
|
||||
BOOST_CHECK(!ParseInt32("2147483648", nullptr));
|
||||
BOOST_CHECK(!ParseInt32("-32482348723847471234", nullptr));
|
||||
BOOST_CHECK(!ParseInt32("32482348723847471234", nullptr));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static void RunToIntegralTests()
|
||||
{
|
||||
@@ -869,171 +835,6 @@ BOOST_AUTO_TEST_CASE(test_LocaleIndependentAtoi)
|
||||
BOOST_CHECK_EQUAL(LocaleIndependentAtoi<uint8_t>("256"), 255U);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_ParseInt64)
|
||||
{
|
||||
int64_t n;
|
||||
// Valid values
|
||||
BOOST_CHECK(ParseInt64("1234", nullptr));
|
||||
BOOST_CHECK(ParseInt64("0", &n) && n == 0LL);
|
||||
BOOST_CHECK(ParseInt64("1234", &n) && n == 1234LL);
|
||||
BOOST_CHECK(ParseInt64("01234", &n) && n == 1234LL); // no octal
|
||||
BOOST_CHECK(ParseInt64("2147483647", &n) && n == 2147483647LL);
|
||||
BOOST_CHECK(ParseInt64("-2147483648", &n) && n == -2147483648LL);
|
||||
BOOST_CHECK(ParseInt64("9223372036854775807", &n) && n == int64_t{9223372036854775807});
|
||||
BOOST_CHECK(ParseInt64("-9223372036854775808", &n) && n == int64_t{-9223372036854775807-1});
|
||||
BOOST_CHECK(ParseInt64("-1234", &n) && n == -1234LL);
|
||||
// Invalid values
|
||||
BOOST_CHECK(!ParseInt64("", &n));
|
||||
BOOST_CHECK(!ParseInt64(" 1", &n)); // no padding inside
|
||||
BOOST_CHECK(!ParseInt64("1 ", &n));
|
||||
BOOST_CHECK(!ParseInt64("1a", &n));
|
||||
BOOST_CHECK(!ParseInt64("aap", &n));
|
||||
BOOST_CHECK(!ParseInt64("0x1", &n)); // no hex
|
||||
BOOST_CHECK(!ParseInt64(STRING_WITH_EMBEDDED_NULL_CHAR, &n));
|
||||
// Overflow and underflow
|
||||
BOOST_CHECK(!ParseInt64("-9223372036854775809", nullptr));
|
||||
BOOST_CHECK(!ParseInt64("9223372036854775808", nullptr));
|
||||
BOOST_CHECK(!ParseInt64("-32482348723847471234", nullptr));
|
||||
BOOST_CHECK(!ParseInt64("32482348723847471234", nullptr));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_ParseUInt8)
|
||||
{
|
||||
uint8_t n;
|
||||
// Valid values
|
||||
BOOST_CHECK(ParseUInt8("255", nullptr));
|
||||
BOOST_CHECK(ParseUInt8("0", &n) && n == 0);
|
||||
BOOST_CHECK(ParseUInt8("255", &n) && n == 255);
|
||||
BOOST_CHECK(ParseUInt8("0255", &n) && n == 255); // no octal
|
||||
BOOST_CHECK(ParseUInt8("255", &n) && n == static_cast<uint8_t>(255));
|
||||
BOOST_CHECK(ParseUInt8("+255", &n) && n == 255);
|
||||
BOOST_CHECK(ParseUInt8("00000000000000000012", &n) && n == 12);
|
||||
BOOST_CHECK(ParseUInt8("00000000000000000000", &n) && n == 0);
|
||||
// Invalid values
|
||||
BOOST_CHECK(!ParseUInt8("-00000000000000000000", &n));
|
||||
BOOST_CHECK(!ParseUInt8("", &n));
|
||||
BOOST_CHECK(!ParseUInt8(" 1", &n)); // no padding inside
|
||||
BOOST_CHECK(!ParseUInt8(" -1", &n));
|
||||
BOOST_CHECK(!ParseUInt8("++1", &n));
|
||||
BOOST_CHECK(!ParseUInt8("+-1", &n));
|
||||
BOOST_CHECK(!ParseUInt8("-+1", &n));
|
||||
BOOST_CHECK(!ParseUInt8("--1", &n));
|
||||
BOOST_CHECK(!ParseUInt8("-1", &n));
|
||||
BOOST_CHECK(!ParseUInt8("1 ", &n));
|
||||
BOOST_CHECK(!ParseUInt8("1a", &n));
|
||||
BOOST_CHECK(!ParseUInt8("aap", &n));
|
||||
BOOST_CHECK(!ParseUInt8("0x1", &n)); // no hex
|
||||
BOOST_CHECK(!ParseUInt8(STRING_WITH_EMBEDDED_NULL_CHAR, &n));
|
||||
// Overflow and underflow
|
||||
BOOST_CHECK(!ParseUInt8("-255", &n));
|
||||
BOOST_CHECK(!ParseUInt8("256", &n));
|
||||
BOOST_CHECK(!ParseUInt8("-123", &n));
|
||||
BOOST_CHECK(!ParseUInt8("-123", nullptr));
|
||||
BOOST_CHECK(!ParseUInt8("256", nullptr));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_ParseUInt16)
|
||||
{
|
||||
uint16_t n;
|
||||
// Valid values
|
||||
BOOST_CHECK(ParseUInt16("1234", nullptr));
|
||||
BOOST_CHECK(ParseUInt16("0", &n) && n == 0);
|
||||
BOOST_CHECK(ParseUInt16("1234", &n) && n == 1234);
|
||||
BOOST_CHECK(ParseUInt16("01234", &n) && n == 1234); // no octal
|
||||
BOOST_CHECK(ParseUInt16("65535", &n) && n == static_cast<uint16_t>(65535));
|
||||
BOOST_CHECK(ParseUInt16("+65535", &n) && n == 65535);
|
||||
BOOST_CHECK(ParseUInt16("00000000000000000012", &n) && n == 12);
|
||||
BOOST_CHECK(ParseUInt16("00000000000000000000", &n) && n == 0);
|
||||
// Invalid values
|
||||
BOOST_CHECK(!ParseUInt16("-00000000000000000000", &n));
|
||||
BOOST_CHECK(!ParseUInt16("", &n));
|
||||
BOOST_CHECK(!ParseUInt16(" 1", &n)); // no padding inside
|
||||
BOOST_CHECK(!ParseUInt16(" -1", &n));
|
||||
BOOST_CHECK(!ParseUInt16("++1", &n));
|
||||
BOOST_CHECK(!ParseUInt16("+-1", &n));
|
||||
BOOST_CHECK(!ParseUInt16("-+1", &n));
|
||||
BOOST_CHECK(!ParseUInt16("--1", &n));
|
||||
BOOST_CHECK(!ParseUInt16("-1", &n));
|
||||
BOOST_CHECK(!ParseUInt16("1 ", &n));
|
||||
BOOST_CHECK(!ParseUInt16("1a", &n));
|
||||
BOOST_CHECK(!ParseUInt16("aap", &n));
|
||||
BOOST_CHECK(!ParseUInt16("0x1", &n)); // no hex
|
||||
BOOST_CHECK(!ParseUInt16(STRING_WITH_EMBEDDED_NULL_CHAR, &n));
|
||||
// Overflow and underflow
|
||||
BOOST_CHECK(!ParseUInt16("-65535", &n));
|
||||
BOOST_CHECK(!ParseUInt16("65536", &n));
|
||||
BOOST_CHECK(!ParseUInt16("-123", &n));
|
||||
BOOST_CHECK(!ParseUInt16("-123", nullptr));
|
||||
BOOST_CHECK(!ParseUInt16("65536", nullptr));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_ParseUInt32)
|
||||
{
|
||||
uint32_t n;
|
||||
// Valid values
|
||||
BOOST_CHECK(ParseUInt32("1234", nullptr));
|
||||
BOOST_CHECK(ParseUInt32("0", &n) && n == 0);
|
||||
BOOST_CHECK(ParseUInt32("1234", &n) && n == 1234);
|
||||
BOOST_CHECK(ParseUInt32("01234", &n) && n == 1234); // no octal
|
||||
BOOST_CHECK(ParseUInt32("2147483647", &n) && n == 2147483647);
|
||||
BOOST_CHECK(ParseUInt32("2147483648", &n) && n == uint32_t{2147483648});
|
||||
BOOST_CHECK(ParseUInt32("4294967295", &n) && n == uint32_t{4294967295});
|
||||
BOOST_CHECK(ParseUInt32("+1234", &n) && n == 1234);
|
||||
BOOST_CHECK(ParseUInt32("00000000000000001234", &n) && n == 1234);
|
||||
BOOST_CHECK(ParseUInt32("00000000000000000000", &n) && n == 0);
|
||||
// Invalid values
|
||||
BOOST_CHECK(!ParseUInt32("-00000000000000000000", &n));
|
||||
BOOST_CHECK(!ParseUInt32("", &n));
|
||||
BOOST_CHECK(!ParseUInt32(" 1", &n)); // no padding inside
|
||||
BOOST_CHECK(!ParseUInt32(" -1", &n));
|
||||
BOOST_CHECK(!ParseUInt32("++1", &n));
|
||||
BOOST_CHECK(!ParseUInt32("+-1", &n));
|
||||
BOOST_CHECK(!ParseUInt32("-+1", &n));
|
||||
BOOST_CHECK(!ParseUInt32("--1", &n));
|
||||
BOOST_CHECK(!ParseUInt32("-1", &n));
|
||||
BOOST_CHECK(!ParseUInt32("1 ", &n));
|
||||
BOOST_CHECK(!ParseUInt32("1a", &n));
|
||||
BOOST_CHECK(!ParseUInt32("aap", &n));
|
||||
BOOST_CHECK(!ParseUInt32("0x1", &n)); // no hex
|
||||
BOOST_CHECK(!ParseUInt32(STRING_WITH_EMBEDDED_NULL_CHAR, &n));
|
||||
// Overflow and underflow
|
||||
BOOST_CHECK(!ParseUInt32("-2147483648", &n));
|
||||
BOOST_CHECK(!ParseUInt32("4294967296", &n));
|
||||
BOOST_CHECK(!ParseUInt32("-1234", &n));
|
||||
BOOST_CHECK(!ParseUInt32("-32482348723847471234", nullptr));
|
||||
BOOST_CHECK(!ParseUInt32("32482348723847471234", nullptr));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_ParseUInt64)
|
||||
{
|
||||
uint64_t n;
|
||||
// Valid values
|
||||
BOOST_CHECK(ParseUInt64("1234", nullptr));
|
||||
BOOST_CHECK(ParseUInt64("0", &n) && n == 0LL);
|
||||
BOOST_CHECK(ParseUInt64("1234", &n) && n == 1234LL);
|
||||
BOOST_CHECK(ParseUInt64("01234", &n) && n == 1234LL); // no octal
|
||||
BOOST_CHECK(ParseUInt64("2147483647", &n) && n == 2147483647LL);
|
||||
BOOST_CHECK(ParseUInt64("9223372036854775807", &n) && n == 9223372036854775807ULL);
|
||||
BOOST_CHECK(ParseUInt64("9223372036854775808", &n) && n == 9223372036854775808ULL);
|
||||
BOOST_CHECK(ParseUInt64("18446744073709551615", &n) && n == 18446744073709551615ULL);
|
||||
// Invalid values
|
||||
BOOST_CHECK(!ParseUInt64("", &n));
|
||||
BOOST_CHECK(!ParseUInt64(" 1", &n)); // no padding inside
|
||||
BOOST_CHECK(!ParseUInt64(" -1", &n));
|
||||
BOOST_CHECK(!ParseUInt64("1 ", &n));
|
||||
BOOST_CHECK(!ParseUInt64("1a", &n));
|
||||
BOOST_CHECK(!ParseUInt64("aap", &n));
|
||||
BOOST_CHECK(!ParseUInt64("0x1", &n)); // no hex
|
||||
BOOST_CHECK(!ParseUInt64(STRING_WITH_EMBEDDED_NULL_CHAR, &n));
|
||||
// Overflow and underflow
|
||||
BOOST_CHECK(!ParseUInt64("-9223372036854775809", nullptr));
|
||||
BOOST_CHECK(!ParseUInt64("18446744073709551616", nullptr));
|
||||
BOOST_CHECK(!ParseUInt64("-32482348723847471234", nullptr));
|
||||
BOOST_CHECK(!ParseUInt64("-2147483648", &n));
|
||||
BOOST_CHECK(!ParseUInt64("-9223372036854775808", &n));
|
||||
BOOST_CHECK(!ParseUInt64("-1234", &n));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_FormatParagraph)
|
||||
{
|
||||
BOOST_CHECK_EQUAL(FormatParagraph("", 79, 0), "");
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2019-2022 The Bitcoin Core developers
|
||||
// Copyright (c) 2019-present The Bitcoin Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
@@ -36,14 +36,11 @@ bool ParseHDKeypath(const std::string& keypath_str, std::vector<uint32_t>& keypa
|
||||
}
|
||||
|
||||
// Ensure this is only numbers
|
||||
if (item.find_first_not_of( "0123456789" ) != std::string::npos) {
|
||||
const auto number{ToIntegral<uint32_t>(item)};
|
||||
if (!number) {
|
||||
return false;
|
||||
}
|
||||
uint32_t number;
|
||||
if (!ParseUInt32(item, &number)) {
|
||||
return false;
|
||||
}
|
||||
path |= number;
|
||||
path |= *number;
|
||||
|
||||
keypath.push_back(path);
|
||||
first = false;
|
||||
|
||||
@@ -78,10 +78,9 @@ bool SplitHostPort(std::string_view in, uint16_t& portOut, std::string& hostOut)
|
||||
bool fBracketed = fHaveColon && (in[0] == '[' && in[colon - 1] == ']'); // if there is a colon, and in[0]=='[', colon is not 0, so in[colon-1] is safe
|
||||
bool fMultiColon{fHaveColon && colon != 0 && (in.find_last_of(':', colon - 1) != in.npos)};
|
||||
if (fHaveColon && (colon == 0 || fBracketed || !fMultiColon)) {
|
||||
uint16_t n;
|
||||
if (ParseUInt16(in.substr(colon + 1), &n)) {
|
||||
if (const auto n{ToIntegral<uint16_t>(in.substr(colon + 1))}) {
|
||||
in = in.substr(0, colon);
|
||||
portOut = n;
|
||||
portOut = *n;
|
||||
valid = (portOut != 0);
|
||||
}
|
||||
} else {
|
||||
@@ -200,57 +199,6 @@ std::optional<std::vector<unsigned char>> DecodeBase32(std::string_view str)
|
||||
return ret;
|
||||
}
|
||||
|
||||
namespace {
|
||||
template <typename T>
|
||||
bool ParseIntegral(std::string_view str, T* out)
|
||||
{
|
||||
static_assert(std::is_integral_v<T>);
|
||||
// Replicate the exact behavior of strtol/strtoll/strtoul/strtoull when
|
||||
// handling leading +/- for backwards compatibility.
|
||||
if (str.length() >= 2 && str[0] == '+' && str[1] == '-') {
|
||||
return false;
|
||||
}
|
||||
const std::optional<T> opt_int = ToIntegral<T>((!str.empty() && str[0] == '+') ? str.substr(1) : str);
|
||||
if (!opt_int) {
|
||||
return false;
|
||||
}
|
||||
if (out != nullptr) {
|
||||
*out = *opt_int;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}; // namespace
|
||||
|
||||
bool ParseInt32(std::string_view str, int32_t* out)
|
||||
{
|
||||
return ParseIntegral<int32_t>(str, out);
|
||||
}
|
||||
|
||||
bool ParseInt64(std::string_view str, int64_t* out)
|
||||
{
|
||||
return ParseIntegral<int64_t>(str, out);
|
||||
}
|
||||
|
||||
bool ParseUInt8(std::string_view str, uint8_t* out)
|
||||
{
|
||||
return ParseIntegral<uint8_t>(str, out);
|
||||
}
|
||||
|
||||
bool ParseUInt16(std::string_view str, uint16_t* out)
|
||||
{
|
||||
return ParseIntegral<uint16_t>(str, out);
|
||||
}
|
||||
|
||||
bool ParseUInt32(std::string_view str, uint32_t* out)
|
||||
{
|
||||
return ParseIntegral<uint32_t>(str, out);
|
||||
}
|
||||
|
||||
bool ParseUInt64(std::string_view str, uint64_t* out)
|
||||
{
|
||||
return ParseIntegral<uint64_t>(str, out);
|
||||
}
|
||||
|
||||
std::string FormatParagraph(std::string_view in, size_t width, size_t indent)
|
||||
{
|
||||
assert(width >= indent);
|
||||
|
||||
@@ -105,8 +105,7 @@ bool SplitHostPort(std::string_view in, uint16_t& portOut, std::string& hostOut)
|
||||
|
||||
// LocaleIndependentAtoi is provided for backwards compatibility reasons.
|
||||
//
|
||||
// New code should use ToIntegral or the ParseInt* functions
|
||||
// which provide parse error feedback.
|
||||
// New code should use ToIntegral.
|
||||
//
|
||||
// The goal of LocaleIndependentAtoi is to replicate the defined behaviour of
|
||||
// std::atoi as it behaves under the "C" locale, and remove some undefined
|
||||
@@ -187,48 +186,6 @@ std::optional<T> ToIntegral(std::string_view str)
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert string to signed 32-bit integer with strict parse error feedback.
|
||||
* @returns true if the entire string could be parsed as valid integer,
|
||||
* false if not the entire string could be parsed or when overflow or underflow occurred.
|
||||
*/
|
||||
[[nodiscard]] bool ParseInt32(std::string_view str, int32_t *out);
|
||||
|
||||
/**
|
||||
* Convert string to signed 64-bit integer with strict parse error feedback.
|
||||
* @returns true if the entire string could be parsed as valid integer,
|
||||
* false if not the entire string could be parsed or when overflow or underflow occurred.
|
||||
*/
|
||||
[[nodiscard]] bool ParseInt64(std::string_view str, int64_t *out);
|
||||
|
||||
/**
|
||||
* Convert decimal string to unsigned 8-bit integer with strict parse error feedback.
|
||||
* @returns true if the entire string could be parsed as valid integer,
|
||||
* false if not the entire string could be parsed or when overflow or underflow occurred.
|
||||
*/
|
||||
[[nodiscard]] bool ParseUInt8(std::string_view str, uint8_t *out);
|
||||
|
||||
/**
|
||||
* Convert decimal string to unsigned 16-bit integer with strict parse error feedback.
|
||||
* @returns true if the entire string could be parsed as valid integer,
|
||||
* false if the entire string could not be parsed or if overflow or underflow occurred.
|
||||
*/
|
||||
[[nodiscard]] bool ParseUInt16(std::string_view str, uint16_t* out);
|
||||
|
||||
/**
|
||||
* Convert decimal string to unsigned 32-bit integer with strict parse error feedback.
|
||||
* @returns true if the entire string could be parsed as valid integer,
|
||||
* false if not the entire string could be parsed or when overflow or underflow occurred.
|
||||
*/
|
||||
[[nodiscard]] bool ParseUInt32(std::string_view str, uint32_t *out);
|
||||
|
||||
/**
|
||||
* Convert decimal string to unsigned 64-bit integer with strict parse error feedback.
|
||||
* @returns true if the entire string could be parsed as valid integer,
|
||||
* false if not the entire string could be parsed or when overflow or underflow occurred.
|
||||
*/
|
||||
[[nodiscard]] bool ParseUInt64(std::string_view str, uint64_t *out);
|
||||
|
||||
/**
|
||||
* Format a paragraph of text to a fixed width, adding spaces for
|
||||
* indentation to any added line.
|
||||
|
||||
@@ -151,13 +151,13 @@ bool CreateFromDump(const ArgsManager& args, const std::string& name, const fs::
|
||||
return false;
|
||||
}
|
||||
// Check the version number (value of first record)
|
||||
uint32_t ver;
|
||||
if (!ParseUInt32(version_value, &ver)) {
|
||||
error =strprintf(_("Error: Unable to parse version %u as a uint32_t"), version_value);
|
||||
const auto ver{ToIntegral<uint32_t>(version_value)};
|
||||
if (!ver) {
|
||||
error = strprintf(_("Error: Unable to parse version %u as a uint32_t"), version_value);
|
||||
dump_file.close();
|
||||
return false;
|
||||
}
|
||||
if (ver != DUMP_VERSION) {
|
||||
if (*ver != DUMP_VERSION) {
|
||||
error = strprintf(_("Error: Dumpfile version is not supported. This version of bitcoin-wallet only supports version 1 dumpfiles. Got dumpfile with version %s"), version_value);
|
||||
dump_file.close();
|
||||
return false;
|
||||
|
||||
@@ -271,6 +271,8 @@ class RESTTest (BitcoinTestFramework):
|
||||
# Check invalid blockhashbyheight requests
|
||||
resp = self.test_rest_request(f"/blockhashbyheight/{INVALID_PARAM}", ret_type=RetType.OBJ, status=400)
|
||||
assert_equal(resp.read().decode('utf-8').rstrip(), f"Invalid height: {INVALID_PARAM}")
|
||||
resp = self.test_rest_request("/blockhashbyheight/+1", ret_type=RetType.OBJ, status=400)
|
||||
assert_equal(resp.read().decode('utf-8').rstrip(), "Invalid height: +1")
|
||||
resp = self.test_rest_request("/blockhashbyheight/1000000", ret_type=RetType.OBJ, status=404)
|
||||
assert_equal(resp.read().decode('utf-8').rstrip(), "Block height out of range")
|
||||
resp = self.test_rest_request("/blockhashbyheight/-1", ret_type=RetType.OBJ, status=400)
|
||||
|
||||
@@ -56,6 +56,12 @@
|
||||
"output_cmp": "blanktxv2.json",
|
||||
"description": "Creates a blank transaction when nothing is piped into bitcoin-tx (output in json)"
|
||||
},
|
||||
{ "exec": "./bitcoin-tx",
|
||||
"args": ["-create", "nversion=+1"],
|
||||
"return_code": 1,
|
||||
"error_txt": "error: Invalid TX version requested",
|
||||
"description": "Tests the check for invalid nversion value"
|
||||
},
|
||||
{ "exec": "./bitcoin-tx",
|
||||
"args": ["-create", "nversion=1foo"],
|
||||
"return_code": 1,
|
||||
@@ -126,6 +132,12 @@
|
||||
"output_cmp": "tt-locktime317000-out.json",
|
||||
"description": "Adds an nlocktime to a transaction (output in json)"
|
||||
},
|
||||
{ "exec": "./bitcoin-tx",
|
||||
"args": ["-create", "locktime=+317"],
|
||||
"return_code": 1,
|
||||
"error_txt": "error: Invalid TX locktime requested",
|
||||
"description": "Tests the check for invalid locktime value"
|
||||
},
|
||||
{ "exec": "./bitcoin-tx",
|
||||
"args": ["-create", "locktime=317000foo"],
|
||||
"return_code": 1,
|
||||
@@ -165,6 +177,15 @@
|
||||
"error_txt": "error: Invalid TX input index",
|
||||
"description": "Tests the check for an invalid string input index with replaceable"
|
||||
},
|
||||
{ "exec": "./bitcoin-tx",
|
||||
"args":
|
||||
["-create",
|
||||
"in=5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f:0",
|
||||
"replaceable=+0"],
|
||||
"return_code": 1,
|
||||
"error_txt": "error: Invalid TX input index",
|
||||
"description": "Tests the check for an invalid string input index with replaceable"
|
||||
},
|
||||
{
|
||||
"exec": "./bitcoin-tx",
|
||||
"args":
|
||||
@@ -243,6 +264,14 @@
|
||||
"error_txt": "error: invalid TX sequence id 'abcdef00'",
|
||||
"description": "Try to make invalid input replaceable"
|
||||
},
|
||||
{ "exec": "./bitcoin-tx",
|
||||
"args":
|
||||
["-create",
|
||||
"in=5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f:+0"],
|
||||
"return_code": 1,
|
||||
"error_txt": "error: invalid TX input vout",
|
||||
"description": "Tests the check for an invalid vout value when adding an input"
|
||||
},
|
||||
{ "exec": "./bitcoin-tx",
|
||||
"args":
|
||||
["-create",
|
||||
|
||||
Reference in New Issue
Block a user