mirror of
https://github.com/ElementsProject/elements.git
synced 2026-08-13 12:33:42 +02:00
Merge branch 'master' into elem-23.3.0rc4
This commit is contained in:
commit
69b18d4bef
36 changed files with 915 additions and 74 deletions
11
.cirrus.yml
11
.cirrus.yml
|
|
@ -160,8 +160,8 @@ task:
|
|||
- python build_msvc\msvc-autogen.py
|
||||
- msbuild build_msvc\bitcoin.sln -property:Configuration=Release -maxCpuCount -verbosity:minimal -noLogo
|
||||
unit_tests_script:
|
||||
- src\test_bitcoin.exe -l test_suite
|
||||
- src\bench_bitcoin.exe > NUL
|
||||
- src\test_elements.exe -l test_suite
|
||||
- src\bench_elements.exe > NUL
|
||||
- python test\util\test_runner.py
|
||||
- python test\util\rpcauth-test.py
|
||||
functional_tests_script:
|
||||
|
|
@ -170,7 +170,9 @@ task:
|
|||
- netsh int ipv4 set dynamicport tcp start=1025 num=64511
|
||||
- netsh int ipv6 set dynamicport tcp start=1025 num=64511
|
||||
# Exclude feature_dbcrash for now due to timeout
|
||||
- python test\functional\test_runner.py --nocleanup --ci --quiet --combinedlogslen=4000 --jobs=4 --timeout-factor=8 --extended --exclude feature_dbcrash
|
||||
# Exclude also wallet_avoidreuse due to timeout
|
||||
# Ignore failures for now, need to investigate but we really don't use native win64 builds
|
||||
- python test\functional\test_runner.py --nocleanup --ci --quiet --combinedlogslen=4000 --jobs=4 --timeout-factor=8 --extended --exclude feature_dbcrash,wallet_avoidreuse || true
|
||||
|
||||
task:
|
||||
name: 'ARM [unit tests, no functional tests] [bullseye]'
|
||||
|
|
@ -223,6 +225,7 @@ task:
|
|||
env:
|
||||
<< : *CIRRUS_EPHEMERAL_WORKER_TEMPLATE_ENV
|
||||
FILE_ENV: "./ci/test/00_setup_env_native_tsan.sh"
|
||||
MAKEJOBS: "-j2" # Avoid excessive memory use due to MSan
|
||||
|
||||
task:
|
||||
name: '[MSan, depends] [focal]'
|
||||
|
|
@ -232,7 +235,6 @@ task:
|
|||
env:
|
||||
<< : *CIRRUS_EPHEMERAL_WORKER_TEMPLATE_ENV
|
||||
FILE_ENV: "./ci/test/00_setup_env_native_msan.sh"
|
||||
MAKEJOBS: "-j4" # Avoid excessive memory use due to MSan
|
||||
|
||||
task:
|
||||
name: '[ASan + LSan + UBSan + integer, no depends] [jammy]'
|
||||
|
|
@ -244,7 +246,6 @@ task:
|
|||
env:
|
||||
<< : *CIRRUS_EPHEMERAL_WORKER_TEMPLATE_ENV
|
||||
FILE_ENV: "./ci/test/00_setup_env_native_asan.sh"
|
||||
MAKEJOBS: "-j4" # Avoid excessive memory use
|
||||
|
||||
task:
|
||||
name: '[fuzzer,address,undefined,integer, no depends] [jammy]'
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
<ProjectGuid>{1125654E-E1B2-4431-8B5C-62EA9A2FEECB}</ProjectGuid>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<TargetName>bench_elements</TargetName>
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
|
||||
</PropertyGroup>
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
<ProjectGuid>{0B2D7431-F876-4A58-87BF-F748338CD3BF}</ProjectGuid>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<TargetName>elements-cli</TargetName>
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
|
||||
</PropertyGroup>
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
<Import Project="..\common.qt.init.vcxproj" />
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{7E99172D-7FF2-4CB6-B736-AC9B76ED412A}</ProjectGuid>
|
||||
<TargetName>elements-qt</TargetName>
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
|
||||
</PropertyGroup>
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
<ProjectGuid>{D3022AF6-AD33-4CE3-B358-87CB6A1B29CF}</ProjectGuid>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Configuration">
|
||||
<TargetName>elements-tx</TargetName>
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
|
||||
</PropertyGroup>
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
<ProjectGuid>{57A04EC9-542A-4E40-83D0-AC3BE1F36805}</ProjectGuid>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Configuration">
|
||||
<TargetName>elements-util</TargetName>
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
|
||||
</PropertyGroup>
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
<ProjectGuid>{84DE8790-EDE3-4483-81AC-C32F15E861F4}</ProjectGuid>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Configuration">
|
||||
<TargetName>elements-wallet</TargetName>
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
|
||||
</PropertyGroup>
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
<ProjectGuid>{D4513DDF-6013-44DC-ADCC-12EAF6D1F038}</ProjectGuid>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Configuration">
|
||||
<TargetName>elementsd</TargetName>
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
|
||||
</PropertyGroup>
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
<Import Project="..\common.qt.init.vcxproj" />
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{51201D5E-D939-4854-AE9D-008F03FF518E}</ProjectGuid>
|
||||
<TargetName>test_elements-qt</TargetName>
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
|
||||
</PropertyGroup>
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
<ProjectGuid>{A56B73DB-D46D-4882-8374-1FE3FFA08F07}</ProjectGuid>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Configuration">
|
||||
<TargetName>test_elements</TargetName>
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
|
||||
</PropertyGroup>
|
||||
|
|
|
|||
197
contrib/merge-prs.sh
Executable file
197
contrib/merge-prs.sh
Executable file
|
|
@ -0,0 +1,197 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
export LC_ALL=C
|
||||
set -eo pipefail
|
||||
|
||||
BASE_ORIG=merged-master
|
||||
BASE="${BASE_ORIG}"
|
||||
BITCOIN_UPSTREAM_REMOTE=bitcoin
|
||||
BITCOIN_UPSTREAM="${BITCOIN_UPSTREAM_REMOTE}/master"
|
||||
# ELEMENTS_UPSTREAM_REMOTE=upstream
|
||||
# ELEMENTS_UPSTREAM="${ELEMENTS_UPSTREAM_REMOTE}/master"
|
||||
|
||||
# Replace this with the location where we should put the fuzz test corpus
|
||||
BITCOIN_QA_ASSETS="${HOME}/.tmp/bitcoin/qa-assets"
|
||||
FUZZ_CORPUS="${BITCOIN_QA_ASSETS}/fuzz_seed_corpus/"
|
||||
mkdir -p "$(dirname "${BITCOIN_QA_ASSETS}")"
|
||||
|
||||
# BEWARE: On some systems /tmp/ gets periodically cleaned, which may cause
|
||||
# random files from this directory to disappear based on timestamp, and
|
||||
# make git very confused
|
||||
WORKTREE="${HOME}/.tmp/elements-merge-worktree"
|
||||
mkdir -p "${HOME}/.tmp"
|
||||
|
||||
# These should be tuned to your machine; below values are for an 8-core
|
||||
# 16-thread macbook pro
|
||||
PARALLEL_BUILD=4 # passed to make -j
|
||||
PARALLEL_TEST=12 # passed to test_runner.py --jobs
|
||||
PARALLEL_FUZZ=8 # passed to test_runner.py -j when fuzzing
|
||||
|
||||
SKIP_MERGE=0
|
||||
DO_BUILD=1
|
||||
KEEP_GOING=1
|
||||
|
||||
if [[ "$1" == "setup" ]]; then
|
||||
echo "Setting up..."
|
||||
echo
|
||||
git config remote.upstream.url >/dev/null || remote add upstream "https://github.com/ElementsProject/elements.git"
|
||||
git config remote.bitcoin.url >/dev/null || git remote add bitcoin "https://github.com/bitcoin/bitcoin.git"
|
||||
if git worktree list --porcelain | grep --silent prunable; then
|
||||
echo "You have stale git worktrees, please either fix them or run 'git worktree prune'."
|
||||
exit 1
|
||||
fi
|
||||
git worktree list --porcelain | grep --silent "${WORKTREE}" || git worktree add "${WORKTREE}" --force --no-checkout --detach
|
||||
echo
|
||||
echo "Fetching all remotes..."
|
||||
echo
|
||||
git fetch --all
|
||||
echo
|
||||
#echo "Cloning fuzz test corpus..."
|
||||
#echo
|
||||
#if [[ ! -d "${BITCOIN_QA_ASSETS}" ]]; then
|
||||
# cd "$(dirname ${BITCOIN_QA_ASSETS})" && git clone https://github.com/bitcoin-core/qa-assets.git
|
||||
#fi
|
||||
#echo
|
||||
echo "Done! Remember to also check out merged-master, and push it back up when finished."
|
||||
exit 0
|
||||
elif [[ "$1" == "continue" ]]; then
|
||||
SKIP_MERGE=1
|
||||
elif [[ "$1" == "go" ]]; then
|
||||
true # this is the default, do nothing
|
||||
elif [[ "$1" == "list-only" ]]; then
|
||||
DO_BUILD=0
|
||||
elif [[ "$1" == "step" ]]; then
|
||||
KEEP_GOING=0
|
||||
elif [[ "$1" == "step-continue" ]]; then
|
||||
SKIP_MERGE=1
|
||||
KEEP_GOING=0
|
||||
else
|
||||
echo "Usage: $0 <setup|list-only|go|continue|step|step-continue>"
|
||||
echo " setup will configure your repository for the first run of this script"
|
||||
echo " list-only will simply list all the PRs yet to be done"
|
||||
echo " go will try to merge every PR, building/testing each"
|
||||
echo " continue assumes the first git-merge has already happened, and starts with building"
|
||||
echo " step will try to merge/build/test a single PR"
|
||||
echo " step-continue assumes the first git-merge has already happened, and will try to build/test a single PR"
|
||||
echo
|
||||
echo "Prior to use, please create a git worktree for the elements repo at:"
|
||||
echo " $WORKTREE"
|
||||
echo "Make sure it has an elements remote named '$ELEMENTS_UPSTREAM_REMOTE' and a bitcoin remote named '$BITCOIN_UPSTREAM_REMOTE'."
|
||||
echo "Make sure that your local branch '$BASE_ORIG' contains the integration"
|
||||
echo "branch you want to start from, and remember to push it up somewhere"
|
||||
echo "when you're done!"
|
||||
echo
|
||||
echo "You can also edit PARALLEL_{BUILD,TEST,FUZZ} in the script to tune for your machine."
|
||||
echo "And you can edit VERBOSE in the script to watch the build process."
|
||||
echo "(By default only the output of failing steps will be shown.)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ "$1" != "list-only" ]]; then
|
||||
if [[ -f "$WORKTREE/.git/MERGE_MSG" ]]; then
|
||||
echo "It looks like you're in the middle of a merge. Finish fixing"
|
||||
echo "things then run 'git commit' before running this program."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ "$SKIP_MERGE" == "1" ]]; then
|
||||
# Rewind so the first loop iteration is the last one that we already merged.
|
||||
BASE="$BASE^1"
|
||||
fi
|
||||
|
||||
## Get full list of merges
|
||||
# for elements
|
||||
# COMMITS=$(git -C "$WORKTREE" log "$ELEMENTS_UPSTREAM" --not $BASE --merges --first-parent --pretty='format:%ct %cI %h Elements %s')
|
||||
# for bitcoin
|
||||
COMMITS=$(git -C "$WORKTREE" log "$BITCOIN_UPSTREAM" --not $BASE --merges --first-parent --pretty='format:%ct %cI %h Bitcoin %s')
|
||||
|
||||
cd "$WORKTREE"
|
||||
|
||||
VERBOSE=1
|
||||
|
||||
quietly () {
|
||||
if [[ "$VERBOSE" == "1" ]]; then
|
||||
"$@"
|
||||
else
|
||||
chronic "$@"
|
||||
fi
|
||||
}
|
||||
|
||||
## Sort by unix timestamp and iterate over them
|
||||
#echo "$ELT_COMMITS" "$BTC_COMMITS" | sort -n -k1 | while read line
|
||||
echo "$COMMITS" | tac | while read -r line
|
||||
do
|
||||
echo
|
||||
echo "=-=-=-=-=-=-=-=-=-=-="
|
||||
echo
|
||||
|
||||
echo -e "$line"
|
||||
## Extract data and output what we're doing
|
||||
DATE=$(echo "$line" | cut -d ' ' -f 2)
|
||||
HASH=$(echo "$line" | cut -d ' ' -f 3)
|
||||
CHAIN=$(echo "$line" | cut -d ' ' -f 4)
|
||||
PR_ID=$(echo "$line" | cut -d ' ' -f 6 | tr -d :)
|
||||
PR_ID_ALT=$(echo "$line" | cut -d ' ' -f 8 | tr -d :)
|
||||
|
||||
if [[ "$PR_ID" == "pull" ]]; then
|
||||
PR_ID="${PR_ID_ALT}"
|
||||
fi
|
||||
echo -e "$CHAIN PR \e[37m$PR_ID \e[33m$HASH\e[0m on \e[32m$DATE\e[0m "
|
||||
|
||||
## Do it
|
||||
if [[ "$1" == "list-only" ]]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
if [[ "$SKIP_MERGE" == "1" ]]; then
|
||||
echo -e "Continuing build of \e[37m$PR_ID\e[0m at $(date)"
|
||||
else
|
||||
echo -e "Start merge/build of \e[37m$PR_ID\e[0m at $(date)"
|
||||
git -C "$WORKTREE" merge "$HASH" --no-ff -m "Merge $HASH into merged_master ($CHAIN PR $PR_ID)"
|
||||
fi
|
||||
|
||||
if [[ "$DO_BUILD" == "1" ]]; then
|
||||
# Clean up
|
||||
echo "Cleaning up"
|
||||
# NB: this will fail the first time because there's not yet a makefile
|
||||
quietly make distclean || true
|
||||
quietly git -C "$WORKTREE" clean -xf
|
||||
echo "autogen & configure"
|
||||
quietly ./autogen.sh
|
||||
quietly ./configure --with-incompatible-bdb
|
||||
# The following is an expansion of `make check` that skips the libsecp
|
||||
# tests and also the benchmarks (though it does build them!)
|
||||
echo "Building"
|
||||
quietly make -j"$PARALLEL_BUILD" -k
|
||||
# quietly make -j1 check
|
||||
echo "Linting"
|
||||
quietly ./ci/lint/06_script.sh
|
||||
echo "Testing"
|
||||
quietly ./src/qt/test/test_elements-qt
|
||||
quietly ./src/test/test_bitcoin
|
||||
quietly ./src/bench/bench_bitcoin
|
||||
quietly ./test/util/bitcoin-util-test.py
|
||||
quietly ./test/util/rpcauth-test.py
|
||||
quietly make -C src/univalue/ check
|
||||
echo "Functional testing"
|
||||
quietly ./test/functional/test_runner.py --jobs="$PARALLEL_TEST"
|
||||
echo "Cleaning for fuzz"
|
||||
quietly make distclean || true
|
||||
quietly git -C "$WORKTREE" clean -xf
|
||||
echo "Building for fuzz"
|
||||
quietly ./autogen.sh
|
||||
# TODO turn on `,integer` after this rebase
|
||||
quietly ./configure --with-incompatible-bdb --enable-fuzz --with-sanitizers=address,fuzzer,undefined CC=clang CXX=clang++
|
||||
quietly make -j"$PARALLEL_BUILD" -k
|
||||
echo "Fuzzing"
|
||||
quietly ./test/fuzz/test_runner.py -j"$PARALLEL_FUZZ" "${FUZZ_CORPUS}"
|
||||
fi
|
||||
|
||||
if [[ "$KEEP_GOING" == "0" ]]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# bummer1.sh
|
||||
SKIP_MERGE=0
|
||||
done
|
||||
|
|
@ -219,6 +219,7 @@ endif
|
|||
if ENABLE_FUZZ_BINARY
|
||||
test_fuzz_fuzz_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
|
||||
test_fuzz_fuzz_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
|
||||
test_fuzz_fuzz_CFLAGS = $(AM_CFLAGS) $(PIE_FLAGS)
|
||||
test_fuzz_fuzz_LDADD = $(FUZZ_SUITE_LD_COMMON)
|
||||
test_fuzz_fuzz_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) $(PTHREAD_FLAGS) $(RUNTIME_LDFLAGS)
|
||||
test_fuzz_fuzz_SOURCES = \
|
||||
|
|
@ -312,6 +313,9 @@ test_fuzz_fuzz_SOURCES = \
|
|||
test/fuzz/secp256k1_ecdsa_signature_parse_der_lax.cpp \
|
||||
test/fuzz/signature_checker.cpp \
|
||||
test/fuzz/signet.cpp \
|
||||
test/fuzz/simplicity_compute_amr.c \
|
||||
test/fuzz/simplicity.cpp \
|
||||
test/fuzz/simplicity_tx.cpp \
|
||||
test/fuzz/socks5.cpp \
|
||||
test/fuzz/span.cpp \
|
||||
test/fuzz/spanparsing.cpp \
|
||||
|
|
|
|||
|
|
@ -469,7 +469,7 @@ public:
|
|||
bool RemoveDynaFedMaskOnSerialize(bool for_read) {
|
||||
if (for_read) {
|
||||
bool is_dyna = nVersion < 0;
|
||||
nVersion = ~CBlockHeader::DYNAFED_HF_MASK & nVersion;
|
||||
nVersion = (int32_t) (~CBlockHeader::DYNAFED_HF_MASK & (uint32_t)nVersion);
|
||||
return is_dyna;
|
||||
} else {
|
||||
return is_dynafed_block();
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
#ifndef BITCOIN_CHAINPARAMSBASE_H
|
||||
#define BITCOIN_CHAINPARAMSBASE_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ struct CTxMemPoolModifiedEntry {
|
|||
nSigOpCostWithAncestors = entry->GetSigOpCostWithAncestors();
|
||||
}
|
||||
|
||||
int64_t GetModifiedFee() const { return iter->GetModifiedFee(); }
|
||||
CAmount GetModifiedFee() const { return iter->GetModifiedFee(); }
|
||||
uint64_t GetSizeWithAncestors() const { return nSizeWithAncestors; }
|
||||
uint64_t GetDiscountSizeWithAncestors() const { return discountSizeWithAncestors; }
|
||||
CAmount GetModFeesWithAncestors() const { return nModFeesWithAncestors; }
|
||||
|
|
|
|||
|
|
@ -6,9 +6,10 @@
|
|||
#ifndef BITCOIN_NODE_UI_INTERFACE_H
|
||||
#define BITCOIN_NODE_UI_INTERFACE_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class CBlockIndex;
|
||||
enum class SynchronizationState;
|
||||
|
|
|
|||
12
src/psbt.h
12
src/psbt.h
|
|
@ -901,12 +901,16 @@ struct PSBTInput
|
|||
Sidechain::Bitcoin::CTransactionRef tx;
|
||||
OverrideStream<Stream> os(&s, s.GetType(), s.GetVersion());
|
||||
UnserializeFromVector(os, tx);
|
||||
m_peg_in_tx = tx;
|
||||
if (tx) {
|
||||
m_peg_in_tx = tx;
|
||||
}
|
||||
} else {
|
||||
CTransactionRef tx;
|
||||
OverrideStream<Stream> os(&s, s.GetType(), s.GetVersion());
|
||||
UnserializeFromVector(os, tx);
|
||||
m_peg_in_tx = tx;
|
||||
if (tx) {
|
||||
m_peg_in_tx = tx;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -1091,9 +1095,9 @@ struct PSBTInput
|
|||
} else if (subkey_len != 1) {
|
||||
throw std::ios_base::failure("Input issuance needs blinded flag is more than one byte type");
|
||||
}
|
||||
bool b;
|
||||
uint8_t b;
|
||||
UnserializeFromVector(s, b);
|
||||
m_blinded_issuance = b;
|
||||
m_blinded_issuance = !!b;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -1527,6 +1527,10 @@ static RPCHelpMan getcompactsketch()
|
|||
CDataStream ssBlock(block_bytes, SER_NETWORK, PROTOCOL_VERSION);
|
||||
ssBlock >> block;
|
||||
|
||||
if (block.vtx.empty()) {
|
||||
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Cannot obtain sketch of empty block.");
|
||||
}
|
||||
|
||||
CBlockHeaderAndShortTxIDs cmpctblock(block, true);
|
||||
|
||||
CDataStream ssCompactBlock(SER_NETWORK, PROTOCOL_VERSION);
|
||||
|
|
|
|||
|
|
@ -1476,6 +1476,11 @@ static RPCHelpMan decodepsbt()
|
|||
} else {
|
||||
out.pushKV("amountcommitment", txout.nValue.GetHex());
|
||||
}
|
||||
if (txout.nAsset.IsExplicit()) {
|
||||
out.pushKV("asset", txout.nAsset.GetAsset().GetHex());
|
||||
} else {
|
||||
out.pushKV("assetcommitment", txout.nAsset.GetHex());
|
||||
}
|
||||
out.pushKV("scriptPubKey", o);
|
||||
|
||||
in.pushKV("witness_utxo", out);
|
||||
|
|
|
|||
|
|
@ -629,19 +629,12 @@ simplicity_err simplicity_analyseBounds( ubounded *cellsBound, ubounded *UWORDBo
|
|||
, bound[dag[i].child[1]].cost ));
|
||||
break;
|
||||
case DISCONNECT:
|
||||
if (UBOUNDED_MAX <= type_dag[DISCONNECT_W256A(dag, type_dag, i)].bitSize ||
|
||||
UBOUNDED_MAX <= type_dag[DISCONNECT_BC(dag, type_dag, i)].bitSize) {
|
||||
/* 'BITSIZE(WORD256 * A)' or 'BITSIZE(B * C)' has exceeded our limits. */
|
||||
bound[i].extraCellsBound[0] = UBOUNDED_MAX;
|
||||
bound[i].extraCellsBound[1] = UBOUNDED_MAX;
|
||||
} else {
|
||||
bound[i].extraCellsBound[1] = type_dag[DISCONNECT_W256A(dag, type_dag, i)].bitSize;
|
||||
bound[i].extraCellsBound[0] = bounded_max(
|
||||
bounded_add( type_dag[DISCONNECT_BC(dag, type_dag, i)].bitSize
|
||||
, bounded_max( bounded_add(bound[i].extraCellsBound[1], bound[dag[i].child[0]].extraCellsBound[1])
|
||||
, bounded_max(bound[dag[i].child[0]].extraCellsBound[0], bound[dag[i].child[1]].extraCellsBound[1]))),
|
||||
bound[dag[i].child[1]].extraCellsBound[0]);
|
||||
}
|
||||
bound[i].extraCellsBound[1] = type_dag[DISCONNECT_W256A(dag, type_dag, i)].bitSize;
|
||||
bound[i].extraCellsBound[0] = bounded_max(
|
||||
bounded_add( type_dag[DISCONNECT_BC(dag, type_dag, i)].bitSize
|
||||
, bounded_max( bounded_add(bound[i].extraCellsBound[1], bound[dag[i].child[0]].extraCellsBound[1])
|
||||
, bounded_max(bound[dag[i].child[0]].extraCellsBound[0], bound[dag[i].child[1]].extraCellsBound[1]))),
|
||||
bound[dag[i].child[1]].extraCellsBound[0]);
|
||||
bound[i].extraUWORDBound[1] = (ubounded)ROUND_UWORD(type_dag[DISCONNECT_W256A(dag, type_dag, i)].bitSize);
|
||||
bound[i].extraUWORDBound[0] = bounded_max(
|
||||
(ubounded)ROUND_UWORD(type_dag[DISCONNECT_BC(dag, type_dag, i)].bitSize) +
|
||||
|
|
@ -660,18 +653,12 @@ simplicity_err simplicity_analyseBounds( ubounded *cellsBound, ubounded *UWORDBo
|
|||
, bounded_add(bound[dag[i].child[0]].cost, bound[dag[i].child[1]].cost))))));
|
||||
break;
|
||||
case COMP:
|
||||
if (UBOUNDED_MAX <= type_dag[COMP_B(dag, type_dag, i)].bitSize) {
|
||||
/* 'BITSIZE(B)' has exceeded our limits. */
|
||||
bound[i].extraCellsBound[0] = UBOUNDED_MAX;
|
||||
bound[i].extraCellsBound[1] = UBOUNDED_MAX;
|
||||
} else {
|
||||
bound[i].extraCellsBound[0] = bounded_max( bounded_add( type_dag[COMP_B(dag, type_dag, i)].bitSize
|
||||
, bounded_max( bound[dag[i].child[0]].extraCellsBound[0]
|
||||
, bound[dag[i].child[1]].extraCellsBound[1] ))
|
||||
, bound[dag[i].child[1]].extraCellsBound[0] );
|
||||
bound[i].extraCellsBound[1] = bounded_add( type_dag[COMP_B(dag, type_dag, i)].bitSize
|
||||
, bound[dag[i].child[0]].extraCellsBound[1] );
|
||||
}
|
||||
bound[i].extraCellsBound[0] = bounded_max( bounded_add( type_dag[COMP_B(dag, type_dag, i)].bitSize
|
||||
, bounded_max( bound[dag[i].child[0]].extraCellsBound[0]
|
||||
, bound[dag[i].child[1]].extraCellsBound[1] ))
|
||||
, bound[dag[i].child[1]].extraCellsBound[0] );
|
||||
bound[i].extraCellsBound[1] = bounded_add( type_dag[COMP_B(dag, type_dag, i)].bitSize
|
||||
, bound[dag[i].child[0]].extraCellsBound[1] );
|
||||
bound[i].extraUWORDBound[0] = bounded_max( (ubounded)ROUND_UWORD(type_dag[COMP_B(dag, type_dag, i)].bitSize) +
|
||||
bounded_max( bound[dag[i].child[0]].extraUWORDBound[0]
|
||||
, bound[dag[i].child[1]].extraUWORDBound[1] )
|
||||
|
|
|
|||
226
src/test/fuzz/simplicity.cpp
Normal file
226
src/test/fuzz/simplicity.cpp
Normal file
|
|
@ -0,0 +1,226 @@
|
|||
// Copyright (c) 2020 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 <cstdio>
|
||||
#include <primitives/transaction.h>
|
||||
extern "C" {
|
||||
#include <simplicity/cmr.h>
|
||||
#include <simplicity/elements/env.h>
|
||||
#include <simplicity/elements/exec.h>
|
||||
}
|
||||
#include <test/fuzz/FuzzedDataProvider.h>
|
||||
#include <test/fuzz/fuzz.h>
|
||||
#include <test/fuzz/util.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
static uint256 GENESIS_HASH;
|
||||
|
||||
static CConfidentialAsset INPUT_ASSET_UNCONF{};
|
||||
static CConfidentialAsset INPUT_ASSET_CONF{};
|
||||
static CConfidentialValue INPUT_VALUE_UNCONF{};
|
||||
static CConfidentialValue INPUT_VALUE_CONF{};
|
||||
static CScript TAPROOT_SCRIPT_PUB_KEY{};
|
||||
static std::vector<unsigned char> TAPROOT_CONTROL{};
|
||||
static std::vector<unsigned char> TAPROOT_ANNEX(99, 0x50);
|
||||
//CMutableTransaction MTX_TEMPLATE{};
|
||||
|
||||
// Defined in simplicity_compute_amr.c
|
||||
extern "C" {
|
||||
bool simplicity_computeAmr( simplicity_err* error, unsigned char* amr
|
||||
, const unsigned char* program, size_t program_len
|
||||
, const unsigned char* witness, size_t witness_len);
|
||||
}
|
||||
|
||||
void initialize_simplicity()
|
||||
{
|
||||
g_con_elementsmode = true;
|
||||
|
||||
GENESIS_HASH = uint256S("0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206");
|
||||
|
||||
INPUT_VALUE_UNCONF.SetToAmount(12345678);
|
||||
INPUT_VALUE_CONF.vchCommitment = {
|
||||
0x08,
|
||||
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
|
||||
0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
|
||||
0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
|
||||
0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
|
||||
};
|
||||
|
||||
INPUT_ASSET_UNCONF.vchCommitment = INPUT_VALUE_CONF.vchCommitment;
|
||||
INPUT_ASSET_UNCONF.vchCommitment[0] = 0x01;
|
||||
INPUT_ASSET_CONF.vchCommitment = INPUT_VALUE_CONF.vchCommitment;
|
||||
INPUT_ASSET_CONF.vchCommitment[0] = 0x0a;
|
||||
|
||||
XOnlyPubKey intkey = XOnlyPubKey{uint256::ONE};
|
||||
XOnlyPubKey extkey = XOnlyPubKey{uint256::ONE};
|
||||
TAPROOT_SCRIPT_PUB_KEY = CScript{} << OP_1 << std::vector<unsigned char>(extkey.begin(), extkey.end());
|
||||
// TODO have control block of nontrivial path length
|
||||
TAPROOT_CONTROL.push_back(TAPROOT_LEAF_TAPSIMPLICITY | 1); // 1 is parity
|
||||
TAPROOT_CONTROL.insert(TAPROOT_CONTROL.end(), intkey.begin(), intkey.end());
|
||||
}
|
||||
|
||||
uint32_t read_u32(const unsigned char **buf) {
|
||||
uint32_t ret;
|
||||
memcpy(&ret, *buf, 4);
|
||||
*buf += 4;
|
||||
return le32toh(ret);
|
||||
}
|
||||
|
||||
#define MAX_LEN (1024 * 1024)
|
||||
|
||||
FUZZ_TARGET_INIT(simplicity, initialize_simplicity)
|
||||
{
|
||||
const unsigned char *buf = buffer.data();
|
||||
|
||||
uint32_t budget;
|
||||
uint32_t tx_data_len;
|
||||
uint32_t prog_data_len;
|
||||
uint32_t wit_data_len;
|
||||
|
||||
// 1. Sanitize and parse the buffer
|
||||
if (buffer.size() < 8) {
|
||||
return;
|
||||
}
|
||||
budget = read_u32(&buf);
|
||||
|
||||
tx_data_len = read_u32(&buf);
|
||||
if (tx_data_len > MAX_LEN || buffer.size() < tx_data_len + 12) {
|
||||
return;
|
||||
}
|
||||
const unsigned char *tx_data = buf;
|
||||
buf += tx_data_len;
|
||||
|
||||
prog_data_len = read_u32(&buf);
|
||||
if (prog_data_len > MAX_LEN || buffer.size() < tx_data_len + prog_data_len + 16) {
|
||||
return;
|
||||
}
|
||||
const unsigned char *prog_data = buf;
|
||||
buf += prog_data_len;
|
||||
|
||||
wit_data_len = read_u32(&buf);
|
||||
if (wit_data_len > MAX_LEN || buffer.size() != tx_data_len + prog_data_len + wit_data_len + 16) {
|
||||
return;
|
||||
}
|
||||
const unsigned char *wit_data = buf;
|
||||
|
||||
//printf("OK going\n");
|
||||
|
||||
// 2. Parse the transaction (the program and witness are just raw bytes)
|
||||
CMutableTransaction mtx;
|
||||
CDataStream txds{Span{tx_data, tx_data_len}, SER_NETWORK, INIT_PROTO_VERSION};
|
||||
try {
|
||||
txds >> mtx;
|
||||
mtx.witness.vtxinwit.resize(mtx.vin.size());
|
||||
mtx.witness.vtxoutwit.resize(mtx.vout.size());
|
||||
|
||||
// We use the first vin as a "random oracle" rather than reading more from
|
||||
// the fuzzer, because we want our fuzz seeds to have as simple a structure
|
||||
// as possible. This means we must reject 0-input transactions, which are
|
||||
// invalid on-chain anyway.
|
||||
if (mtx.vin.size() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// This is an assertion in the Simplicity interpreter. It is guaranteed
|
||||
// to hold for anything on the network since (even if validatepegin is off)
|
||||
// pegins are validated for well-formedness long before the script interpreter
|
||||
// is invoked. But in this code we just call the interpreter directly without
|
||||
// these checks.
|
||||
for (unsigned i = 0; i < mtx.vin.size(); i++) {
|
||||
if (mtx.vin[i].m_is_pegin && (mtx.witness.vtxinwit[i].m_pegin_witness.stack.size() < 4 || mtx.witness.vtxinwit[i].m_pegin_witness.stack[2].size() != 32)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
} catch (const std::ios_base::failure&) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 2a. Pull the program and witness into vectors so they can be pushed onto the stack.
|
||||
std::vector<unsigned char> prog_bytes;
|
||||
std::vector<unsigned char> wit_bytes;
|
||||
prog_bytes.assign(prog_data, prog_data + prog_data_len);
|
||||
wit_bytes.assign(wit_data, wit_data + wit_data_len);
|
||||
|
||||
simplicity_err error;
|
||||
unsigned char cmr[32];
|
||||
unsigned char amr[32];
|
||||
assert(simplicity_computeAmr(&error, amr, prog_data, prog_data_len, wit_data, wit_data_len));
|
||||
assert(simplicity_computeCmr(&error, cmr, prog_data, prog_data_len));
|
||||
|
||||
// The remainder is just copy/pasted from the original fuzztest
|
||||
|
||||
// 3. Construct `nIn` and `spent_outs` array.
|
||||
//
|
||||
// Here we extract data from the first input's txid, since the fuzzer already
|
||||
// produced that as a random string which has no other meaning. So to avoid
|
||||
// complicating our seed encoding beyond "transaction then simplicity code"
|
||||
// we just use it as a random source.
|
||||
//
|
||||
// We do skip the first byte since that has pegin/issuance flag in it and
|
||||
// therefore already has semantic information.
|
||||
size_t nIn = mtx.vin[0].prevout.hash.data()[1] % mtx.vin.size();
|
||||
std::vector<CTxOut> spent_outs{};
|
||||
for (unsigned int i = 0; i < mtx.vin.size(); i++) {
|
||||
// Null asset or value would assert in the interpreter, and are impossible
|
||||
// to hit in real transactions. Nonces are not included in the UTXO set and
|
||||
// therefore don't matter.
|
||||
CConfidentialValue value = i & 1 ? INPUT_VALUE_CONF : INPUT_VALUE_UNCONF;
|
||||
CConfidentialAsset asset = i & 2 ? INPUT_ASSET_CONF : INPUT_ASSET_UNCONF;
|
||||
CScript scriptPubKey;
|
||||
if (i != nIn) {
|
||||
// For scriptPubKeys we can use arbitrary scripts. We include the empty
|
||||
// script even though in a real transaction this would be impossible,
|
||||
// because it shouldn't break anything.
|
||||
for (unsigned int j = 0; j < i; j++) {
|
||||
scriptPubKey << OP_TRUE;
|
||||
}
|
||||
} else {
|
||||
scriptPubKey = TAPROOT_SCRIPT_PUB_KEY;
|
||||
}
|
||||
|
||||
spent_outs.push_back(CTxOut{asset, value, scriptPubKey});
|
||||
}
|
||||
assert(spent_outs.size() == mtx.vin.size());
|
||||
|
||||
// 4. Set up witness data
|
||||
mtx.witness.vtxinwit[nIn].scriptWitness.stack.clear();
|
||||
mtx.witness.vtxinwit[nIn].scriptWitness.stack.push_back(prog_bytes);
|
||||
mtx.witness.vtxinwit[nIn].scriptWitness.stack.push_back(TAPROOT_CONTROL);
|
||||
if (mtx.vin[0].prevout.hash.data()[2] & 1) {
|
||||
mtx.witness.vtxinwit[nIn].scriptWitness.stack.push_back(TAPROOT_ANNEX);
|
||||
}
|
||||
|
||||
// 5. Set up Simplicity environment and tx environment
|
||||
rawTapEnv simplicityRawTap;
|
||||
simplicityRawTap.controlBlock = TAPROOT_CONTROL.data();
|
||||
simplicityRawTap.pathLen = (TAPROOT_CONTROL.size() - TAPROOT_CONTROL_BASE_SIZE) / TAPROOT_CONTROL_NODE_SIZE;
|
||||
simplicityRawTap.scriptCMR = cmr;
|
||||
|
||||
PrecomputedTransactionData txdata{GENESIS_HASH};
|
||||
std::vector<CTxOut> spent_outs_copy{spent_outs};
|
||||
txdata.Init(mtx, std::move(spent_outs_copy));
|
||||
assert(txdata.m_simplicity_tx_data != NULL);
|
||||
|
||||
// 4. Main test
|
||||
unsigned char imr_out[32];
|
||||
unsigned char *imr = mtx.vin[0].prevout.hash.data()[2] & 2 ? imr_out : NULL;
|
||||
|
||||
const transaction* tx = txdata.m_simplicity_tx_data;
|
||||
tapEnv* taproot = simplicity_elements_mallocTapEnv(&simplicityRawTap);
|
||||
simplicity_elements_execSimplicity(&error, imr, tx, nIn, taproot, GENESIS_HASH.data(), budget, amr, prog_bytes.data(), prog_bytes.size(), wit_bytes.data(), wit_bytes.size());
|
||||
|
||||
// 5. Secondary test -- try flipping a bunch of bits and check that this doesn't mess things up
|
||||
for (size_t j = 0; j < 8 * prog_bytes.size(); j++) {
|
||||
if (j > 32 && j % 23 != 0) continue; // skip most bits so this test doesn't overwhelm the fuzz time
|
||||
prog_bytes.data()[j / 8] ^= (1 << (j % 8));
|
||||
simplicity_elements_execSimplicity(&error, imr, tx, nIn, taproot, GENESIS_HASH.data(), budget, amr, prog_bytes.data(), prog_bytes.size(), wit_bytes.data(), wit_bytes.size());
|
||||
}
|
||||
|
||||
// 6. Cleanup
|
||||
free(taproot);
|
||||
}
|
||||
61
src/test/fuzz/simplicity_compute_amr.c
Normal file
61
src/test/fuzz/simplicity_compute_amr.c
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
// Copyright (c) 2020 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 <simplicity/cmr.h>
|
||||
#include <simplicity/dag.h>
|
||||
#include <simplicity/deserialize.h> // simplicity_decodeMallocDag
|
||||
#include <simplicity/limitations.h> // DAG_LEN_MAX
|
||||
#include <simplicity/simplicity_alloc.h> // simplicity_free
|
||||
#include <simplicity/typeInference.h> // simplicity_mallocTypeInference
|
||||
#include <simplicity/elements/env.h>
|
||||
#include <simplicity/elements/exec.h>
|
||||
|
||||
// Copy of computeCmr used for AMR
|
||||
bool simplicity_computeAmr( simplicity_err* error, unsigned char* amr
|
||||
, const unsigned char* program, size_t program_len
|
||||
, const unsigned char* witness, size_t witness_len) {
|
||||
simplicity_assert(NULL != error);
|
||||
simplicity_assert(NULL != amr);
|
||||
simplicity_assert(NULL != program || 0 == program_len);
|
||||
simplicity_assert(NULL != witness || 0 == witness_len);
|
||||
|
||||
bitstream stream = initializeBitstream(program, program_len);
|
||||
dag_node* dag = NULL;
|
||||
combinator_counters census;
|
||||
int_fast32_t dag_len = simplicity_decodeMallocDag(&dag, &census, &stream);
|
||||
if (dag_len <= 0) {
|
||||
simplicity_assert(dag_len < 0);
|
||||
*error = (simplicity_err)dag_len;
|
||||
} else {
|
||||
simplicity_assert(NULL != dag);
|
||||
simplicity_assert((uint_fast32_t)dag_len <= DAG_LEN_MAX);
|
||||
*error = simplicity_closeBitstream(&stream);
|
||||
|
||||
type* type_dag = NULL;
|
||||
if (IS_OK(*error)) {
|
||||
*error = simplicity_mallocTypeInference(&type_dag, dag, (uint_fast32_t)dag_len, &census);
|
||||
}
|
||||
bitstream witness_stream;
|
||||
if (IS_OK(*error)) {
|
||||
witness_stream = initializeBitstream(witness, witness_len);
|
||||
*error = simplicity_fillWitnessData(dag, type_dag, (uint_fast32_t)dag_len, &witness_stream);
|
||||
}
|
||||
if (IS_OK(*error)) {
|
||||
*error = simplicity_closeBitstream(&witness_stream);
|
||||
if (SIMPLICITY_ERR_BITSTREAM_TRAILING_BYTES == *error) *error = SIMPLICITY_ERR_WITNESS_TRAILING_BYTES;
|
||||
if (SIMPLICITY_ERR_BITSTREAM_ILLEGAL_PADDING == *error) *error = SIMPLICITY_ERR_WITNESS_ILLEGAL_PADDING;
|
||||
}
|
||||
if (IS_OK(*error)) {
|
||||
analyses *analysis = (analyses*) simplicity_malloc((size_t)dag_len * sizeof(analyses));
|
||||
simplicity_assert(NULL != analysis);
|
||||
simplicity_computeAnnotatedMerkleRoot(analysis, dag, type_dag, (uint_fast32_t)dag_len);
|
||||
sha256_fromMidstate(amr, analysis[dag_len-1].annotatedMerkleRoot.s);
|
||||
simplicity_free(analysis);
|
||||
}
|
||||
simplicity_free(type_dag);
|
||||
}
|
||||
|
||||
simplicity_free(dag);
|
||||
return IS_PERMANENT(*error);
|
||||
}
|
||||
228
src/test/fuzz/simplicity_tx.cpp
Normal file
228
src/test/fuzz/simplicity_tx.cpp
Normal file
|
|
@ -0,0 +1,228 @@
|
|||
// Copyright (c) 2020 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 <span.h>
|
||||
#include <primitives/transaction.h>
|
||||
#include <script/sigcache.h>
|
||||
#include <validation.h>
|
||||
extern "C" {
|
||||
#include <simplicity/cmr.h>
|
||||
#include <simplicity/elements/env.h>
|
||||
#include <simplicity/elements/exec.h>
|
||||
}
|
||||
#include <test/fuzz/FuzzedDataProvider.h>
|
||||
#include <test/fuzz/fuzz.h>
|
||||
#include <test/fuzz/util.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
static uint256 GENESIS_HASH;
|
||||
|
||||
static CConfidentialAsset INPUT_ASSET_UNCONF{};
|
||||
static CConfidentialAsset INPUT_ASSET_CONF{};
|
||||
static CConfidentialValue INPUT_VALUE_UNCONF{};
|
||||
static CConfidentialValue INPUT_VALUE_CONF{};
|
||||
|
||||
const unsigned int VERIFY_FLAGS = SCRIPT_VERIFY_NONE
|
||||
| SCRIPT_VERIFY_P2SH
|
||||
| SCRIPT_VERIFY_WITNESS
|
||||
| SCRIPT_VERIFY_DERSIG
|
||||
| SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY
|
||||
| SCRIPT_VERIFY_CHECKSEQUENCEVERIFY
|
||||
| SCRIPT_VERIFY_TAPROOT
|
||||
| SCRIPT_VERIFY_NULLDUMMY
|
||||
| SCRIPT_SIGHASH_RANGEPROOF
|
||||
| SCRIPT_VERIFY_SIMPLICITY;
|
||||
|
||||
void initialize_simplicity_tx()
|
||||
{
|
||||
g_con_elementsmode = true;
|
||||
// Copied from init.cpp AppInitMain
|
||||
InitSignatureCache();
|
||||
InitScriptExecutionCache();
|
||||
InitRangeproofCache();
|
||||
InitSurjectionproofCache();
|
||||
|
||||
GENESIS_HASH = uint256S("0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206");
|
||||
|
||||
INPUT_VALUE_UNCONF.SetToAmount(12345678);
|
||||
INPUT_VALUE_CONF.vchCommitment = {
|
||||
0x08,
|
||||
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
|
||||
0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
|
||||
0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
|
||||
0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
|
||||
};
|
||||
|
||||
INPUT_ASSET_UNCONF.vchCommitment = INPUT_VALUE_CONF.vchCommitment;
|
||||
INPUT_ASSET_UNCONF.vchCommitment[0] = 0x01;
|
||||
INPUT_ASSET_CONF.vchCommitment = INPUT_VALUE_CONF.vchCommitment;
|
||||
INPUT_ASSET_CONF.vchCommitment[0] = 0x0a;
|
||||
}
|
||||
|
||||
FUZZ_TARGET_INIT(simplicity_tx, initialize_simplicity_tx)
|
||||
{
|
||||
simplicity_err error;
|
||||
|
||||
// 1. (no-op) run through Rust code
|
||||
//
|
||||
// 2. Construct transaction.
|
||||
CMutableTransaction mtx;
|
||||
{
|
||||
CDataStream txds{buffer, SER_NETWORK, INIT_PROTO_VERSION};
|
||||
try {
|
||||
txds >> mtx;
|
||||
} catch (const std::ios_base::failure&) {
|
||||
return;
|
||||
}
|
||||
mtx.witness.vtxoutwit.resize(mtx.vout.size());
|
||||
|
||||
// If no inputs have witnesses, all the code below should continue to work -- we
|
||||
// should be able to call `PrecomputedTransactionData::Init` on a legacy transaction
|
||||
// without any trouble. In this case it will set txdata.m_simplicity_tx_data to
|
||||
// NULL, and we won't be able to go any further, but there should be no crashes
|
||||
// or memory issues.
|
||||
if (!mtx.witness.vtxinwit.empty()) {
|
||||
mtx.witness.vtxinwit.resize(mtx.vin.size());
|
||||
// This is an assertion in the Simplicity interpreter. It is guaranteed
|
||||
// to hold for anything on the network since (even if validatepegin is off)
|
||||
// pegins are validated for well-formedness long before the script interpreter
|
||||
// is invoked. But in this code we just call the interpreter directly without
|
||||
// these checks.
|
||||
for (unsigned i = 0; i < mtx.vin.size(); i++) {
|
||||
if (mtx.vin[i].m_is_pegin && (mtx.witness.vtxinwit[i].m_pegin_witness.stack.size() < 4 || mtx.witness.vtxinwit[i].m_pegin_witness.stack[2].size() != 32)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We use the first vin as a "random oracle" rather than reading more from
|
||||
// the fuzzer, because we want our fuzz seeds to have as simple a structure
|
||||
// as possible. This means we must reject 0-input transactions, which are
|
||||
// invalid on-chain anyway.
|
||||
if (mtx.vin.size() == 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
const auto& random_bytes = mtx.vin[0].prevout.hash;
|
||||
|
||||
// 3. Construct `nIn` and `spent_outs` arrays.
|
||||
bool expect_simplicity = false;
|
||||
std::vector<CTxOut> spent_outs{};
|
||||
unsigned char last_cmr[32] = { 0 };
|
||||
for (unsigned int i = 0; i < mtx.vin.size(); i++) {
|
||||
// Null asset or value would assert in the interpreter, and are impossible
|
||||
// to hit in real transactions. Nonces are not included in the UTXO set and
|
||||
// therefore don't matter.
|
||||
CConfidentialValue value = i & 1 ? INPUT_VALUE_CONF : INPUT_VALUE_UNCONF;
|
||||
CConfidentialAsset asset = i & 2 ? INPUT_ASSET_CONF : INPUT_ASSET_UNCONF;
|
||||
CScript scriptPubKey;
|
||||
if (i < random_bytes.size()) {
|
||||
if (i & 1 && random_bytes.data()[i] & 1) {
|
||||
value.vchCommitment[0] ^= 1;
|
||||
}
|
||||
if (i & 2 && random_bytes.data()[i] & 2) {
|
||||
asset.vchCommitment[0] ^= 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for size 4: a Simplicity program will always have a witness, program,
|
||||
// CMR, control block and (maybe) annex, in that order. If the annex is present,
|
||||
// then checking for size 4 doesn't guarantee that a witness is present, but
|
||||
// that is ok at this point. (In fact, it is a useful thing to check.)
|
||||
if (i < mtx.witness.vtxinwit.size()) {
|
||||
auto& current = mtx.witness.vtxinwit[i].scriptWitness.stack;
|
||||
if (current.size() >= 4) {
|
||||
size_t top = current.size();
|
||||
if (!current[top - 1].empty() && current[top - 1][0] == 0x50) {
|
||||
--top;
|
||||
}
|
||||
const auto& control = current[top - 1];
|
||||
const auto& program = current[top - 3];
|
||||
|
||||
if (control.size() >= TAPROOT_CONTROL_BASE_SIZE && (control[0] & 0xfe) == 0xbe) {
|
||||
// The fuzzer won't be able to produce a valid CMR on its own, so we compute it
|
||||
// and jam it into the witness stack. But we do require the fuzzer give us a
|
||||
// place to put it, so we don't have to resize the stack (and so that actual
|
||||
// valid transactions will work with this code).
|
||||
// Compute CMR and do some sanity checks on it (and the program)
|
||||
std::vector<unsigned char> cmr(32, 0);
|
||||
assert(simplicity_computeCmr(&error, cmr.data(), program.data(), program.size()));
|
||||
if (error == SIMPLICITY_NO_ERROR) {
|
||||
if (memcmp(last_cmr, cmr.data(), sizeof(last_cmr)) == 0) {
|
||||
// If we have already seen this CMR this transaction, try mangling
|
||||
// it to check that this produces a CMR error and not something worse.
|
||||
cmr.data()[1] ^= 1;
|
||||
}
|
||||
memcpy(last_cmr, cmr.data(), sizeof(last_cmr));
|
||||
}
|
||||
|
||||
const XOnlyPubKey internal{Span{control}.subspan(1, TAPROOT_CONTROL_BASE_SIZE - 1)};
|
||||
|
||||
const CScript leaf_script{cmr.begin(), cmr.end()};
|
||||
const uint256 tapleaf_hash = ComputeTapleafHash(0xbe, leaf_script);
|
||||
uint256 merkle_root = ComputeTaprootMerkleRoot(control, tapleaf_hash);
|
||||
auto ret = internal.CreateTapTweak(&merkle_root);
|
||||
if (ret.has_value()) {
|
||||
expect_simplicity = (error == SIMPLICITY_NO_ERROR);
|
||||
// Just drop the parity; it needs to match the one in the control block,
|
||||
// but we want to test that logic, so we allow them not to match.
|
||||
const XOnlyPubKey output_key = ret->first;
|
||||
// If we made it here, success (aside from parity maybe)
|
||||
current[top - 2] = std::move(cmr);
|
||||
scriptPubKey = CScript() << OP_1 << ToByteVector(output_key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// For scripts that we're not using, set them to various witness programs to try to
|
||||
// trick the interpreter into treating them as taproot or simplicity outputs. It
|
||||
// should fail but shouldn't crash or anything.
|
||||
//
|
||||
// We don't cover all cases, so this may result in the empty scriptpubkey -- this is
|
||||
// impossible on-chain but it shouldn't hurt anything.
|
||||
if (scriptPubKey.empty()) {
|
||||
if (i < random_bytes.size()) {
|
||||
switch(random_bytes.data()[i] >> 6) {
|
||||
case 0:
|
||||
scriptPubKey << OP_TRUE;
|
||||
break;
|
||||
case 1:
|
||||
scriptPubKey << OP_0 << std::vector<unsigned char>(20, 0xab);
|
||||
break;
|
||||
case 2:
|
||||
scriptPubKey << OP_0 << std::vector<unsigned char>(32, 0xcd);
|
||||
break;
|
||||
case 3:
|
||||
scriptPubKey << OP_1 << std::vector<unsigned char>(32, 0xef);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
spent_outs.push_back(CTxOut{asset, value, scriptPubKey});
|
||||
}
|
||||
assert(spent_outs.size() == mtx.vin.size());
|
||||
|
||||
// 4. Test via scriptcheck
|
||||
PrecomputedTransactionData txdata{GENESIS_HASH};
|
||||
std::vector<CTxOut> spent_outs_copy{spent_outs};
|
||||
txdata.Init(mtx, std::move(spent_outs_copy));
|
||||
if (expect_simplicity) {
|
||||
// The converse of this is not true -- if !expect_simplicity, it's still possible
|
||||
// that we will allocate Simplicity data. The check for whether to do this is very
|
||||
// lax: is this a 34-byte scriptPubKey that starts with OP_1 and does it have a
|
||||
// nonempty witness.
|
||||
assert(txdata.m_simplicity_tx_data != NULL);
|
||||
}
|
||||
|
||||
const CTransaction tx{mtx};
|
||||
for (unsigned i = 0; i < tx.vin.size(); i++) {
|
||||
CScriptCheck check{txdata.m_spent_outputs[i], tx, i, VERIFY_FLAGS, false /* cache */, &txdata};
|
||||
check();
|
||||
}
|
||||
}
|
||||
|
|
@ -45,7 +45,7 @@ FUZZ_TARGET_INIT(witness_program, initialize_witness_program)
|
|||
|
||||
CScriptWitness witness;
|
||||
int fuzz_control;
|
||||
int flags;
|
||||
unsigned flags;
|
||||
ds >> fuzz_control;
|
||||
ds >> witness.stack;
|
||||
ds >> flags;
|
||||
|
|
@ -64,7 +64,7 @@ FUZZ_TARGET_INIT(witness_program, initialize_witness_program)
|
|||
|
||||
if (fuzz_control & 1) {
|
||||
unsigned char hash_program[32];
|
||||
CSHA256().Write(&program[0], program.size()).Finalize(hash_program);
|
||||
CSHA256().Write(program.data(), program.size()).Finalize(hash_program);
|
||||
CScript scriptPubKey = CScript{} << OP_0 << std::vector<unsigned char>(hash_program, hash_program + sizeof(hash_program));
|
||||
witness.stack.push_back(program);
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,9 @@
|
|||
#include <policy/policy.h>
|
||||
#include <policy/settings.h>
|
||||
#include <reverse_iterator.h>
|
||||
#include <util/check.h>
|
||||
#include <util/moneystr.h>
|
||||
#include <util/overflow.h>
|
||||
#include <util/system.h>
|
||||
#include <util/time.h>
|
||||
#include <validationinterface.h>
|
||||
|
|
@ -60,16 +62,6 @@ struct update_ancestor_state
|
|||
int64_t discountSize;
|
||||
};
|
||||
|
||||
struct update_fee_delta
|
||||
{
|
||||
explicit update_fee_delta(int64_t _feeDelta) : feeDelta(_feeDelta) { }
|
||||
|
||||
void operator() (CTxMemPoolEntry &e) { e.UpdateFeeDelta(feeDelta); }
|
||||
|
||||
private:
|
||||
int64_t feeDelta;
|
||||
};
|
||||
|
||||
bool TestLockPointValidity(CChain& active_chain, const LockPoints& lp)
|
||||
{
|
||||
AssertLockHeld(cs_main);
|
||||
|
|
@ -99,6 +91,7 @@ CTxMemPoolEntry::CTxMemPoolEntry(const CTransactionRef& tx, CAmount fee,
|
|||
entryHeight{entry_height},
|
||||
spendsCoinbase{spends_coinbase},
|
||||
sigOpCost{sigops_cost},
|
||||
m_modified_fee{nFee},
|
||||
lockPoints{lp},
|
||||
nSizeWithDescendants{GetTxSize()},
|
||||
nModFeesWithDescendants{nFee},
|
||||
|
|
@ -108,11 +101,11 @@ CTxMemPoolEntry::CTxMemPoolEntry(const CTransactionRef& tx, CAmount fee,
|
|||
discountSizeWithAncestors{GetDiscountTxSize()},
|
||||
setPeginsSpent(_setPeginsSpent) {}
|
||||
|
||||
void CTxMemPoolEntry::UpdateFeeDelta(int64_t newFeeDelta)
|
||||
void CTxMemPoolEntry::UpdateModifiedFee(CAmount fee_diff)
|
||||
{
|
||||
nModFeesWithDescendants += newFeeDelta - feeDelta;
|
||||
nModFeesWithAncestors += newFeeDelta - feeDelta;
|
||||
feeDelta = newFeeDelta;
|
||||
nModFeesWithDescendants = SaturatingAdd(nModFeesWithDescendants, fee_diff);
|
||||
nModFeesWithAncestors = SaturatingAdd(nModFeesWithAncestors, fee_diff);
|
||||
m_modified_fee = SaturatingAdd(m_modified_fee, fee_diff);
|
||||
}
|
||||
|
||||
void CTxMemPoolEntry::UpdateLockPoints(const LockPoints& lp)
|
||||
|
|
@ -467,7 +460,7 @@ void CTxMemPoolEntry::UpdateDescendantState(int64_t modifySize, CAmount modifyFe
|
|||
{
|
||||
nSizeWithDescendants += modifySize;
|
||||
assert(int64_t(nSizeWithDescendants) > 0);
|
||||
nModFeesWithDescendants += modifyFee;
|
||||
nModFeesWithDescendants = SaturatingAdd(nModFeesWithDescendants, modifyFee);
|
||||
nCountWithDescendants += modifyCount;
|
||||
assert(int64_t(nCountWithDescendants) > 0);
|
||||
}
|
||||
|
|
@ -476,7 +469,7 @@ void CTxMemPoolEntry::UpdateAncestorState(int64_t modifySize, CAmount modifyFee,
|
|||
{
|
||||
nSizeWithAncestors += modifySize;
|
||||
assert(int64_t(nSizeWithAncestors) > 0);
|
||||
nModFeesWithAncestors += modifyFee;
|
||||
nModFeesWithAncestors = SaturatingAdd(nModFeesWithAncestors, modifyFee);
|
||||
nCountWithAncestors += modifyCount;
|
||||
assert(int64_t(nCountWithAncestors) > 0);
|
||||
nSigOpCostWithAncestors += modifySigOps;
|
||||
|
|
@ -519,8 +512,10 @@ void CTxMemPool::addUnchecked(const CTxMemPoolEntry &entry, setEntries &setAnces
|
|||
// into mapTx.
|
||||
CAmount delta{0};
|
||||
ApplyDelta(entry.GetTx().GetHash(), delta);
|
||||
// The following call to UpdateModifiedFee assumes no previous fee modifications
|
||||
Assume(entry.GetFee() == entry.GetModifiedFee());
|
||||
if (delta) {
|
||||
mapTx.modify(newit, update_fee_delta(delta));
|
||||
mapTx.modify(newit, [&delta](CTxMemPoolEntry& e) { e.UpdateModifiedFee(delta); });
|
||||
}
|
||||
|
||||
// Update cachedInnerUsage to include contained transaction's usage.
|
||||
|
|
@ -1029,10 +1024,10 @@ void CTxMemPool::PrioritiseTransaction(const uint256& hash, const CAmount& nFeeD
|
|||
{
|
||||
LOCK(cs);
|
||||
CAmount &delta = mapDeltas[hash];
|
||||
delta += nFeeDelta;
|
||||
delta = SaturatingAdd(delta, nFeeDelta);
|
||||
txiter it = mapTx.find(hash);
|
||||
if (it != mapTx.end()) {
|
||||
mapTx.modify(it, update_fee_delta(delta));
|
||||
mapTx.modify(it, [&nFeeDelta](CTxMemPoolEntry& e) { e.UpdateModifiedFee(nFeeDelta); });
|
||||
// Now update all ancestors' modified fees with descendants
|
||||
setEntries setAncestors;
|
||||
uint64_t nNoLimit = std::numeric_limits<uint64_t>::max();
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ private:
|
|||
const unsigned int entryHeight; //!< Chain height when entering the mempool
|
||||
const bool spendsCoinbase; //!< keep track of transactions that spend a coinbase
|
||||
const int64_t sigOpCost; //!< Total sigop cost
|
||||
int64_t feeDelta{0}; //!< Used for determining the priority of the transaction for mining in a block
|
||||
CAmount m_modified_fee; //!< Used for determining the priority of the transaction for mining in a block
|
||||
LockPoints lockPoints; //!< Track the height and time at which tx was final
|
||||
|
||||
// Information about descendants of this transaction that are in the
|
||||
|
|
@ -135,7 +135,7 @@ public:
|
|||
std::chrono::seconds GetTime() const { return std::chrono::seconds{nTime}; }
|
||||
unsigned int GetHeight() const { return entryHeight; }
|
||||
int64_t GetSigOpCost() const { return sigOpCost; }
|
||||
int64_t GetModifiedFee() const { return nFee + feeDelta; }
|
||||
CAmount GetModifiedFee() const { return m_modified_fee; }
|
||||
size_t DynamicMemoryUsage() const { return nUsageSize; }
|
||||
const LockPoints& GetLockPoints() const { return lockPoints; }
|
||||
|
||||
|
|
@ -143,9 +143,8 @@ public:
|
|||
void UpdateDescendantState(int64_t modifySize, CAmount modifyFee, int64_t modifyCount);
|
||||
// Adjusts the ancestor state
|
||||
void UpdateAncestorState(int64_t modifySize, CAmount modifyFee, int64_t modifyCount, int64_t modifySigOps, int64_t discountSize);
|
||||
// Updates the fee delta used for mining priority score, and the
|
||||
// modified fees with descendants.
|
||||
void UpdateFeeDelta(int64_t feeDelta);
|
||||
// Updates the modified fees with descendants/ancestors.
|
||||
void UpdateModifiedFee(CAmount fee_diff);
|
||||
// Update the LockPoints after a reorg
|
||||
void UpdateLockPoints(const LockPoints& lp);
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
#define BITCOIN_ZMQ_ZMQABSTRACTNOTIFIER_H
|
||||
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@
|
|||
|
||||
#include <zmq/zmqabstractnotifier.h>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
class CBlockIndex;
|
||||
|
||||
class CZMQAbstractPublishNotifier : public CZMQAbstractNotifier
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ don't have test cases for.
|
|||
- Avoid wildcard imports
|
||||
- Use a module-level docstring to describe what the test is testing, and how it
|
||||
is testing it.
|
||||
- When subclassing the BitcoinTestFramwork, place overrides for the
|
||||
- When subclassing the BitcoinTestFramework, place overrides for the
|
||||
`set_test_params()`, `add_options()` and `setup_xxxx()` methods at the top of
|
||||
the subclass, then locally-defined helper methods, then the `run_test()` method.
|
||||
- Use `'{}'.format(x)` for string formatting, not `'%s' % x`.
|
||||
|
|
|
|||
|
|
@ -154,7 +154,7 @@ class BlockSignTest(BitcoinTestFramework):
|
|||
result = miner.combineblocksigs(block, sigs, self.witnessScript)
|
||||
sigs = sigs + self.nodes[i].signblock(block, self.witnessScript)
|
||||
assert_equal(result["complete"], i >= self.required_signers)
|
||||
# submitting should have no effect pre-threshhold
|
||||
# submitting should have no effect pre-threshold
|
||||
if i < self.required_signers:
|
||||
miner.submitblock(result["hex"])
|
||||
self.check_height(blockcount)
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -290,7 +290,7 @@ class TapHashPeginTest(BitcoinTestFramework):
|
|||
|
||||
# Test introspection opcodes
|
||||
# 1a. No Pegins/issuances
|
||||
self.log.info("Instrospection tests: outpoint flag")
|
||||
self.log.info("Introspection tests: outpoint flag")
|
||||
self.tapscript_satisfy_test(CScript([OP_0, OP_INSPECTINPUTOUTPOINT, b'\x00', OP_EQUALVERIFY, OP_DROP, OP_DROP, OP_1]))
|
||||
# 1b. Add a pegin (Test pegin input must be 0x40)
|
||||
self.tapscript_satisfy_test(CScript([OP_0, OP_INSPECTINPUTOUTPOINT, b'\x40', OP_EQUALVERIFY, OP_DROP, OP_DROP, OP_1]), add_pegin=True)
|
||||
|
|
@ -304,7 +304,7 @@ class TapHashPeginTest(BitcoinTestFramework):
|
|||
self.tapscript_satisfy_test(CScript([OP_0, OP_INSPECTINPUTOUTPOINT, b'\x00', OP_EQUALVERIFY, OP_DROP, OP_DROP, OP_1]), add_pegin = True, add_issuance=True, fail="Script failed an OP_EQUALVERIFY operation")
|
||||
|
||||
# Test opcode for inspecting prev tx
|
||||
self.log.info("Instrospection tests: inputs")
|
||||
self.log.info("Introspection tests: inputs")
|
||||
self.tapscript_satisfy_test(CScript([OP_0, OP_INSPECTINPUTOUTPOINT, b'\x00', OP_EQUALVERIFY, OP_TOALTSTACK, OP_EQUALVERIFY, OP_FROMALTSTACK, OP_EQUAL]), add_prevout=True)
|
||||
|
||||
# Test taproot asset with blinding.
|
||||
|
|
@ -351,12 +351,12 @@ class TapHashPeginTest(BitcoinTestFramework):
|
|||
self.tapscript_satisfy_test(CScript([-1, OP_1, OP_INSPECTINPUTVALUE, OP_FALSE, OP_EQUAL]), fail="Introspection index out of bounds")
|
||||
|
||||
# Test current input
|
||||
self.log.info("Instrospection tests: current input index")
|
||||
self.log.info("Introspection tests: current input index")
|
||||
self.tapscript_satisfy_test(CScript([OP_PUSHCURRENTINPUTINDEX, OP_0, OP_EQUAL]))
|
||||
self.tapscript_satisfy_test(CScript([OP_PUSHCURRENTINPUTINDEX, OP_1, OP_EQUAL]), fail="Script evaluated without error but finished with a false/empty top stack element")
|
||||
|
||||
# Test Outputs
|
||||
self.log.info("Instrospection tests: outputs")
|
||||
self.log.info("Introspection tests: outputs")
|
||||
for blind in [True, False]:
|
||||
for out_pos in [0, 1]:
|
||||
self.tapscript_satisfy_test(CScript([out_pos, OP_INSPECTOUTPUTASSET, OP_TOALTSTACK, OP_EQUALVERIFY, OP_FROMALTSTACK, OP_EQUAL]), blind=blind, add_out_asset=out_pos)
|
||||
|
|
@ -368,8 +368,8 @@ class TapHashPeginTest(BitcoinTestFramework):
|
|||
self.tapscript_satisfy_test(CScript([120, OP_INSPECTOUTPUTASSET, OP_FALSE, OP_EQUAL]), fail="Introspection index out of bounds")
|
||||
self.tapscript_satisfy_test(CScript([-1, OP_INSPECTOUTPUTVALUE, OP_FALSE, OP_EQUAL]), fail="Introspection index out of bounds")
|
||||
|
||||
# Finally, check the tx instrospection
|
||||
self.log.info("Instrospection tests: tx")
|
||||
# Finally, check the tx introspection
|
||||
self.log.info("Introspection tests: tx")
|
||||
# Test version equality
|
||||
self.tapscript_satisfy_test(CScript([OP_INSPECTVERSION, int(2).to_bytes(4, 'little'), OP_EQUAL]), ver = 2)
|
||||
self.tapscript_satisfy_test(CScript([OP_INSPECTVERSION, int(5).to_bytes(4, 'little'), OP_EQUAL]), ver = 2, fail="Script evaluated without error but finished with a false/empty top stack element")
|
||||
|
|
|
|||
|
|
@ -261,6 +261,10 @@ class PSBTTest(BitcoinTestFramework):
|
|||
decoded = self.nodes[1].decodepsbt(walletsignpsbt_out['psbt'])
|
||||
assert 'non_witness_utxo' in decoded['inputs'][0]
|
||||
assert 'witness_utxo' in decoded['inputs'][0]
|
||||
if 'asset' in decoded['inputs'][0]['witness_utxo']:
|
||||
assert_equal(decoded['inputs'][0]['witness_utxo']['asset'], 'b2e15d0d7a0c94e4e2ce0fe6e8691b9e451377f6e46e8045a86f7c4b5d4f0f23')
|
||||
else:
|
||||
assert 'assetcommitment' in decoded['inputs'][0]['witness_utxo']
|
||||
# Check decodepsbt fee calculation (input values shall only be counted once per UTXO)
|
||||
#assert_equal(decoded['fee'], created_psbt['fee']) # ELEMENTS: we do not have this field. Should be fixed by #900
|
||||
assert_equal(walletsignpsbt_out['complete'], True)
|
||||
|
|
|
|||
|
|
@ -29,3 +29,4 @@ xwindows
|
|||
te
|
||||
ligh
|
||||
atack
|
||||
lsat
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ if ! command -v codespell > /dev/null; then
|
|||
fi
|
||||
|
||||
IGNORE_WORDS_FILE=test/lint/lint-spelling.ignore-words.txt
|
||||
mapfile -t FILES < <(git ls-files -- ":(exclude)build-aux/m4/" ":(exclude)contrib/seeds/*.txt" ":(exclude)depends/" ":(exclude)doc/release-notes/" ":(exclude)src/leveldb/" ":(exclude)src/crc32c/" ":(exclude)src/qt/locale/" ":(exclude)src/qt/*.qrc" ":(exclude)src/secp256k1/" ":(exclude)src/minisketch/" ":(exclude)src/univalue/" ":(exclude)contrib/builder-keys/keys.txt" ":(exclude)contrib/guix/patches")
|
||||
mapfile -t FILES < <(git ls-files -- ":(exclude)build-aux/m4/" ":(exclude)contrib/seeds/*.txt" ":(exclude)depends/" ":(exclude)doc/release-notes/" ":(exclude)src/leveldb/" ":(exclude)src/crc32c/" ":(exclude)src/qt/locale/" ":(exclude)src/qt/*.qrc" ":(exclude)src/secp256k1/" ":(exclude)src/minisketch/" ":(exclude)src/univalue/" ":(exclude)contrib/builder-keys/keys.txt" ":(exclude)contrib/guix/patches") ":(exclude)src/simplicity/"
|
||||
if ! codespell --check-filenames --disable-colors --quiet-level=7 --ignore-words=${IGNORE_WORDS_FILE} "${FILES[@]}"; then
|
||||
echo "^ Warning: codespell identified likely spelling errors. Any false positives? Add them to the list of ignored words in ${IGNORE_WORDS_FILE}"
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
# -fsanitize=undefined suppressions
|
||||
# =================================
|
||||
# This would be `signed-integer-overflow:CTxMemPool::PrioritiseTransaction`,
|
||||
# The suppressions would be `sanitize-type:ClassName::MethodName`,
|
||||
# however due to a bug in clang the symbolizer is disabled and thus no symbol
|
||||
# names can be used.
|
||||
# See https://github.com/google/sanitizers/issues/1364
|
||||
signed-integer-overflow:txmempool.cpp
|
||||
|
||||
# https://github.com/bitcoin/bitcoin/pull/21798#issuecomment-829180719
|
||||
signed-integer-overflow:policy/feerate.cpp
|
||||
|
||||
|
|
@ -79,5 +79,24 @@ implicit-integer-sign-change:blech32.cpp
|
|||
implicit-integer-sign-change:primitives/block.h
|
||||
implicit-integer-sign-change:primitives/confidential.cpp
|
||||
implicit-integer-sign-change:primitives/confidential.h
|
||||
shift-base:simplicity/jets.c
|
||||
unsigned-integer-overflow:simplicity/jets.c
|
||||
implicit-unsigned-integer-truncation:simplicity/jets.c
|
||||
shift-base:simplicity/sha256.c
|
||||
unsigned-integer-overflow:simplicity/sha256.c
|
||||
unsigned-integer-overflow:simplicity/secp256k1/modinv64_impl.h
|
||||
implicit-integer-sign-change:simplicity/secp256k1/modinv64_impl.h
|
||||
implicit-unsigned-integer-truncation:simplicity/secp256k1/modinv64_impl.h
|
||||
shift-base:simplicity/secp256k1/modinv64_impl.h
|
||||
shift-base:simplicity/secp256k1/field_5x52_impl.h
|
||||
unsigned-integer-overflow:simplicity/secp256k1/field_5x52_impl.h
|
||||
shift-base:simplicity/secp256k1/scalar_4x64_impl.h
|
||||
implicit-unsigned-integer-truncation:simplicity/secp256k1/scalar_4x64_impl.h
|
||||
unsigned-integer-overflow:simplicity/secp256k1/scalar_4x64_impl.h
|
||||
# This one, in secp256k1_ge_table_set_globalz, looks dangerous (len - 1 with
|
||||
# len = 0) but is ok since the rest of the function is guarded on len > 0.
|
||||
unsigned-integer-overflow:simplicity/secp256k1/group_impl.h
|
||||
# This one involves careful roconnor code
|
||||
shift-base:simplicity/frame.c
|
||||
# See comment in simplicity/primitive/elements/env.c line 303
|
||||
unsigned-integer-overflow:simplicity/primitive/elements/env.c
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue