diff --git a/.gitignore b/.gitignore
index c77303f50e2ee..b8d783ea21ec2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -135,7 +135,6 @@ test/.mypy_cache/
/doc/doxygen/
-libbitcoinconsensus.pc
contrib/devtools/split-debug.sh
# Output from running db4 installation
diff --git a/Makefile.am b/Makefile.am
index eec498dc0e937..2329fad9b974d 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -14,11 +14,6 @@ endif
.PHONY: deploy FORCE
.INTERMEDIATE: $(COVERAGE_INFO)
-if BUILD_BITCOIN_LIBS
-pkgconfigdir = $(libdir)/pkgconfig
-pkgconfig_DATA = libbitcoinconsensus.pc
-endif
-
BITCOIND_BIN=$(top_builddir)/src/$(BITCOIN_DAEMON_NAME)$(EXEEXT)
BITCOIN_QT_BIN=$(top_builddir)/src/qt/$(BITCOIN_GUI_NAME)$(EXEEXT)
BITCOIN_TEST_BIN=$(top_builddir)/src/test/$(BITCOIN_TEST_NAME)$(EXEEXT)
diff --git a/build_msvc/libbitcoin_consensus/libbitcoin_consensus.vcxproj b/build_msvc/libbitcoin_consensus/libbitcoin_consensus.vcxproj
index 95fdcdb79b4ef..a34ef41d164be 100644
--- a/build_msvc/libbitcoin_consensus/libbitcoin_consensus.vcxproj
+++ b/build_msvc/libbitcoin_consensus/libbitcoin_consensus.vcxproj
@@ -15,7 +15,6 @@
-
diff --git a/ci/test/00_setup_env_native_previous_releases.sh b/ci/test/00_setup_env_native_previous_releases.sh
index 94e88f872f577..6d536170e2dd9 100755
--- a/ci/test/00_setup_env_native_previous_releases.sh
+++ b/ci/test/00_setup_env_native_previous_releases.sh
@@ -16,5 +16,5 @@ export RUN_UNIT_TESTS_SEQUENTIAL="true"
export RUN_UNIT_TESTS="false"
export GOAL="install"
export DOWNLOAD_PREVIOUS_RELEASES="true"
-export BITCOIN_CONFIG="--enable-zmq --with-libs=no --with-gui=qt5 --enable-reduce-exports --enable-debug \
+export BITCOIN_CONFIG="--enable-zmq --with-gui=qt5 --enable-reduce-exports --enable-debug \
CFLAGS=\"-g0 -O2 -funsigned-char\" CPPFLAGS='-DBOOST_MULTI_INDEX_ENABLE_SAFE_MODE' CXXFLAGS=\"-g0 -O2 -funsigned-char\""
diff --git a/configure.ac b/configure.ac
index 0305918bc4bf1..4e31ccaf24d71 100644
--- a/configure.ac
+++ b/configure.ac
@@ -626,15 +626,9 @@ AC_ARG_ENABLE([experimental-util-chainstate],
[build_bitcoin_chainstate=$enableval],
[build_bitcoin_chainstate=no])
-AC_ARG_WITH([libs],
- [AS_HELP_STRING([--with-libs],
- [build libraries (default=yes)])],
- [build_bitcoin_libs=$withval],
- [build_bitcoin_libs=yes])
-
AC_ARG_WITH([experimental-kernel-lib],
[AS_HELP_STRING([--with-experimental-kernel-lib],
- [build experimental bitcoinkernel library (default is to build if we're building libraries and the experimental build-chainstate executable)])],
+ [build experimental bitcoinkernel library (default is to build if we're building the experimental build-chainstate executable)])],
[build_experimental_kernel_lib=$withval],
[build_experimental_kernel_lib=auto])
@@ -1246,7 +1240,6 @@ if test "$enable_fuzz" = "yes"; then
build_bitcoin_chainstate=no
build_bitcoin_wallet=no
build_bitcoind=no
- build_bitcoin_libs=no
bitcoin_enable_qt=no
bitcoin_enable_qt_test=no
bitcoin_enable_qt_dbus=no
@@ -1405,7 +1398,7 @@ if test "$use_boost" = "yes"; then
dnl Check for Boost headers
AX_BOOST_BASE([1.73.0],[],[AC_MSG_ERROR([Boost is not available!])])
if test "$want_boost" = "no"; then
- AC_MSG_ERROR([only libbitcoinconsensus can be built without Boost])
+ AC_MSG_ERROR([Boost is required])
fi
dnl we don't use multi_index serialization
@@ -1619,18 +1612,8 @@ fi
AM_CONDITIONAL([BUILD_BITCOIN_CHAINSTATE], [test $build_bitcoin_chainstate = "yes"])
AC_MSG_RESULT($build_bitcoin_chainstate)
-AC_MSG_CHECKING([whether to build libraries])
-AM_CONDITIONAL([BUILD_BITCOIN_LIBS], [test $build_bitcoin_libs = "yes"])
-
-if test "$build_bitcoin_libs" = "yes"; then
- AC_DEFINE([HAVE_CONSENSUS_LIB], [1], [Define this symbol if the consensus lib has been built])
- AC_CONFIG_FILES([libbitcoinconsensus.pc:libbitcoinconsensus.pc.in])
-fi
-
AM_CONDITIONAL([BUILD_BITCOIN_KERNEL_LIB], [test "$build_experimental_kernel_lib" != "no" && ( test "$build_experimental_kernel_lib" = "yes" || test "$build_bitcoin_chainstate" = "yes" )])
-AC_MSG_RESULT($build_bitcoin_libs)
-
AC_LANG_POP
if test "$use_ccache" != "no"; then
@@ -1764,8 +1747,8 @@ else
AC_MSG_RESULT([no])
fi
-if test "$build_bitcoin_wallet$build_bitcoin_cli$build_bitcoin_tx$build_bitcoin_util$build_bitcoin_libs$build_bitcoind$bitcoin_enable_qt$enable_fuzz_binary$use_bench$use_tests" = "nononononononononono"; then
- AC_MSG_ERROR([No targets! Please specify at least one of: --with-utils --with-libs --with-daemon --with-gui --enable-fuzz(-binary) --enable-bench or --enable-tests])
+if test "$build_bitcoin_wallet$build_bitcoin_cli$build_bitcoin_tx$build_bitcoin_util$build_bitcoind$bitcoin_enable_qt$enable_fuzz_binary$use_bench$use_tests" = "nonononononononono"; then
+ AC_MSG_ERROR([No targets! Please specify at least one of: --with-utils --with-daemon --with-gui --enable-fuzz(-binary) --enable-bench or --enable-tests])
fi
AM_CONDITIONAL([TARGET_DARWIN], [test "$TARGET_OS" = "darwin"])
@@ -1925,7 +1908,6 @@ echo
echo "Options used to compile and link:"
echo " external signer = $use_external_signer"
echo " multiprocess = $build_multiprocess"
-echo " with libs = $build_bitcoin_libs"
echo " with wallet = $enable_wallet"
if test "$enable_wallet" != "no"; then
echo " with sqlite = $use_sqlite"
diff --git a/contrib/signet/miner b/contrib/signet/miner
index e5daf9f993eaa..02a2f1b70dcad 100755
--- a/contrib/signet/miner
+++ b/contrib/signet/miner
@@ -21,7 +21,7 @@ sys.path.insert(0, PATH_BASE_TEST_FUNCTIONAL)
from test_framework.blocktools import get_witness_script, script_BIP34_coinbase_height # noqa: E402
from test_framework.messages import CBlock, CBlockHeader, COutPoint, CTransaction, CTxIn, CTxInWitness, CTxOut, from_binary, from_hex, ser_string, ser_uint256, tx_from_hex # noqa: E402
from test_framework.psbt import PSBT, PSBTMap, PSBT_GLOBAL_UNSIGNED_TX, PSBT_IN_FINAL_SCRIPTSIG, PSBT_IN_FINAL_SCRIPTWITNESS, PSBT_IN_NON_WITNESS_UTXO, PSBT_IN_SIGHASH_TYPE # noqa: E402
-from test_framework.script import CScriptOp # noqa: E402
+from test_framework.script import CScript, CScriptOp # noqa: E402
logging.basicConfig(
format='%(asctime)s %(levelname)s %(message)s',
@@ -32,12 +32,6 @@ SIGNET_HEADER = b"\xec\xc7\xda\xa2"
PSBT_SIGNET_BLOCK = b"\xfc\x06signetb" # proprietary PSBT global field holding the block being signed
RE_MULTIMINER = re.compile(r"^(\d+)(-(\d+))?/(\d+)$")
-def create_coinbase(height, value, spk):
- cb = CTransaction()
- cb.vin = [CTxIn(COutPoint(0, 0xffffffff), script_BIP34_coinbase_height(height), 0xffffffff)]
- cb.vout = [CTxOut(value, spk)]
- return cb
-
def signet_txs(block, challenge):
# assumes signet solution has not been added yet so does not need
# to be removed
@@ -72,18 +66,7 @@ def signet_txs(block, challenge):
return spend, to_spend
-def do_createpsbt(block, signme, spendme):
- psbt = PSBT()
- psbt.g = PSBTMap( {PSBT_GLOBAL_UNSIGNED_TX: signme.serialize(),
- PSBT_SIGNET_BLOCK: block.serialize()
- } )
- psbt.i = [ PSBTMap( {PSBT_IN_NON_WITNESS_UTXO: spendme.serialize(),
- PSBT_IN_SIGHASH_TYPE: bytes([1,0,0,0])})
- ]
- psbt.o = [ PSBTMap() ]
- return psbt.to_base64()
-
-def do_decode_psbt(b64psbt):
+def decode_psbt(b64psbt):
psbt = PSBT.from_base64(b64psbt)
assert len(psbt.tx.vin) == 1
@@ -110,11 +93,17 @@ def finish_block(block, signet_solution, grind_cmd):
block.rehash()
return block
-def generate_psbt(tmpl, reward_spk, *, blocktime=None):
+def generate_psbt(tmpl, reward_spk, *, blocktime=None, poolid=None):
signet_spk = tmpl["signet_challenge"]
signet_spk_bin = bytes.fromhex(signet_spk)
- cbtx = create_coinbase(height=tmpl["height"], value=tmpl["coinbasevalue"], spk=reward_spk)
+ scriptSig = script_BIP34_coinbase_height(tmpl["height"])
+ if poolid is not None:
+ scriptSig = CScript(b"" + scriptSig + CScriptOp.encode_op_pushdata(poolid))
+
+ cbtx = CTransaction()
+ cbtx.vin = [CTxIn(COutPoint(0, 0xffffffff), scriptSig, 0xffffffff)]
+ cbtx.vout = [CTxOut(tmpl["coinbasevalue"], reward_spk)]
cbtx.vin[0].nSequence = 2**32-2
cbtx.rehash()
@@ -137,29 +126,26 @@ def generate_psbt(tmpl, reward_spk, *, blocktime=None):
signme, spendme = signet_txs(block, signet_spk_bin)
- return do_createpsbt(block, signme, spendme)
-
-def get_reward_address(args, height):
- if args.address is not None:
- return args.address
-
- if '*' not in args.descriptor:
- addr = json.loads(args.bcli("deriveaddresses", args.descriptor))[0]
- args.address = addr
- return addr
-
- remove = [k for k in args.derived_addresses.keys() if k+20 <= height]
- for k in remove:
- del args.derived_addresses[k]
-
- addr = args.derived_addresses.get(height, None)
- if addr is None:
- addrs = json.loads(args.bcli("deriveaddresses", args.descriptor, "[%d,%d]" % (height, height+20)))
- addr = addrs[0]
- for k, a in enumerate(addrs):
- args.derived_addresses[height+k] = a
+ psbt = PSBT()
+ psbt.g = PSBTMap( {PSBT_GLOBAL_UNSIGNED_TX: signme.serialize(),
+ PSBT_SIGNET_BLOCK: block.serialize()
+ } )
+ psbt.i = [ PSBTMap( {PSBT_IN_NON_WITNESS_UTXO: spendme.serialize(),
+ PSBT_IN_SIGHASH_TYPE: bytes([1,0,0,0])})
+ ]
+ psbt.o = [ PSBTMap() ]
+ return psbt.to_base64()
- return addr
+def get_poolid(args):
+ if args.poolid is not None:
+ if args.poolnum is not None:
+ logging.error("Can only specify one of --poolid and --poolnum")
+ raise Exception("bad arguments")
+ return args.poolid.encode('utf8')
+ elif args.poolnum is not None:
+ return b"/signet:%d/" % (args.poolnum)
+ else:
+ return None
def get_reward_addr_spk(args, height):
assert args.address is not None or args.descriptor is not None
@@ -167,7 +153,20 @@ def get_reward_addr_spk(args, height):
if hasattr(args, "reward_spk"):
return args.address, args.reward_spk
- reward_addr = get_reward_address(args, height)
+ if args.address is not None:
+ reward_addr = args.address
+ elif '*' not in args.descriptor:
+ reward_addr = args.address = json.loads(args.bcli("deriveaddresses", args.descriptor))[0]
+ else:
+ remove = [k for k in args.derived_addresses.keys() if k+20 <= height]
+ for k in remove:
+ del args.derived_addresses[k]
+ if height not in args.derived_addresses:
+ addrs = json.loads(args.bcli("deriveaddresses", args.descriptor, "[%d,%d]" % (height, height+20)))
+ for k, a in enumerate(addrs):
+ args.derived_addresses[height+k] = a
+ reward_addr = args.derived_addresses[height]
+
reward_spk = bytes.fromhex(json.loads(args.bcli("getaddressinfo", reward_addr))["scriptPubKey"])
if args.address is not None:
# will always be the same, so cache
@@ -176,13 +175,14 @@ def get_reward_addr_spk(args, height):
return reward_addr, reward_spk
def do_genpsbt(args):
+ poolid = get_poolid(args)
tmpl = json.load(sys.stdin)
_, reward_spk = get_reward_addr_spk(args, tmpl["height"])
- psbt = generate_psbt(tmpl, reward_spk)
+ psbt = generate_psbt(tmpl, reward_spk, poolid=poolid)
print(psbt)
def do_solvepsbt(args):
- block, signet_solution = do_decode_psbt(sys.stdin.read())
+ block, signet_solution = decode_psbt(sys.stdin.read())
block = finish_block(block, signet_solution, args.grind_cmd)
print(block.serialize().hex())
@@ -225,36 +225,115 @@ def seconds_to_hms(s):
out = "-" + out
return out
-def next_block_delta(last_nbits, last_hash, ultimate_target, do_poisson, max_interval):
- # strategy:
- # 1) work out how far off our desired target we are
- # 2) cap it to a factor of 4 since that's the best we can do in a single retarget period
- # 3) use that to work out the desired average interval in this retarget period
- # 4) if doing poisson, use the last hash to pick a uniformly random number in [0,1), and work out a random multiplier to vary the average by
- # 5) cap the resulting interval between 1 second and 1 hour to avoid extremes
-
+class Generate:
INTERVAL = 600.0*2016/2015 # 10 minutes, adjusted for the off-by-one bug
- current_target = nbits_to_target(last_nbits)
- retarget_factor = ultimate_target / current_target
- retarget_factor = max(0.25, min(retarget_factor, 4.0))
- avg_interval = INTERVAL * retarget_factor
+ def __init__(self, multiminer=None, ultimate_target=None, poisson=False, max_interval=1800,
+ standby_delay=0, backup_delay=0, set_block_time=None,
+ poolid=None):
+ if multiminer is None:
+ multiminer = (0, 1, 1)
+ (self.multi_low, self.multi_high, self.multi_period) = multiminer
+ self.ultimate_target = ultimate_target
+ self.poisson = poisson
+ self.max_interval = max_interval
+ self.standby_delay = standby_delay
+ self.backup_delay = backup_delay
+ self.set_block_time = set_block_time
+ self.poolid = poolid
+
+ def next_block_delta(self, last_nbits, last_hash):
+ # strategy:
+ # 1) work out how far off our desired target we are
+ # 2) cap it to a factor of 4 since that's the best we can do in a single retarget period
+ # 3) use that to work out the desired average interval in this retarget period
+ # 4) if doing poisson, use the last hash to pick a uniformly random number in [0,1), and work out a random multiplier to vary the average by
+ # 5) cap the resulting interval between 1 second and 1 hour to avoid extremes
+
+ current_target = nbits_to_target(last_nbits)
+ retarget_factor = self.ultimate_target / current_target
+ retarget_factor = max(0.25, min(retarget_factor, 4.0))
+
+ avg_interval = self.INTERVAL * retarget_factor
+
+ if self.poisson:
+ det_rand = int(last_hash[-8:], 16) * 2**-32
+ this_interval_variance = -math.log1p(-det_rand)
+ else:
+ this_interval_variance = 1
- if do_poisson:
- det_rand = int(last_hash[-8:], 16) * 2**-32
- this_interval_variance = -math.log1p(-det_rand)
- else:
- this_interval_variance = 1
+ this_interval = avg_interval * this_interval_variance
+ this_interval = max(1, min(this_interval, self.max_interval))
+
+ return this_interval
+
+ def next_block_is_mine(self, last_hash):
+ det_rand = int(last_hash[-16:-8], 16)
+ return self.multi_low <= (det_rand % self.multi_period) < self.multi_high
+
+ def next_block_time(self, now, bestheader, is_first_block):
+ if self.set_block_time is not None:
+ logging.debug("Setting start time to %d", self.set_block_time)
+ self.mine_time = self.set_block_time
+ self.action_time = now
+ self.is_mine = True
+ elif bestheader["height"] == 0:
+ time_delta = self.INTERVAL * 100 # plenty of time to mine 100 blocks
+ logging.info("Backdating time for first block to %d minutes ago" % (time_delta/60))
+ self.mine_time = now - time_delta
+ self.action_time = now
+ self.is_mine = True
+ else:
+ time_delta = self.next_block_delta(int(bestheader["bits"], 16), bestheader["hash"])
+ self.mine_time = bestheader["time"] + time_delta
+
+ self.is_mine = self.next_block_is_mine(bestheader["hash"])
+
+ self.action_time = self.mine_time
+ if not self.is_mine:
+ self.action_time += self.backup_delay
+
+ if self.standby_delay > 0:
+ self.action_time += self.standby_delay
+ elif is_first_block:
+ # for non-standby, always mine immediately on startup,
+ # even if the next block shouldn't be ours
+ self.action_time = now
- this_interval = avg_interval * this_interval_variance
- this_interval = max(1, min(this_interval, max_interval))
+ # don't want fractional times so round down
+ self.mine_time = int(self.mine_time)
+ self.action_time = int(self.action_time)
- return this_interval
+ # can't mine a block 2h in the future; 1h55m for some safety
+ self.action_time = max(self.action_time, self.mine_time - 6900)
-def next_block_is_mine(last_hash, my_blocks):
- det_rand = int(last_hash[-16:-8], 16)
- return my_blocks[0] <= (det_rand % my_blocks[2]) < my_blocks[1]
+ def gbt(self, bcli, bestblockhash, now):
+ tmpl = json.loads(bcli("getblocktemplate", '{"rules":["signet","segwit"]}'))
+ if tmpl["previousblockhash"] != bestblockhash:
+ logging.warning("GBT based off unexpected block (%s not %s), retrying", tmpl["previousblockhash"], bci["bestblockhash"])
+ time.sleep(1)
+ return None
+
+ if tmpl["mintime"] > self.mine_time:
+ logging.info("Updating block time from %d to %d", self.mine_time, tmpl["mintime"])
+ self.mine_time = tmpl["mintime"]
+ if self.mine_time > now:
+ logging.error("GBT mintime is in the future: %d is %d seconds later than %d", self.mine_time, (self.mine_time-now), now)
+ return None
+
+ return tmpl
+
+ def mine(self, bcli, grind_cmd, tmpl, reward_spk):
+ psbt = generate_psbt(tmpl, reward_spk, blocktime=self.mine_time, poolid=self.poolid)
+ input_stream = os.linesep.join([psbt, "true", "ALL"]).encode('utf8')
+ psbt_signed = json.loads(bcli("-stdin", "walletprocesspsbt", input=input_stream))
+ if not psbt_signed.get("complete",False):
+ logging.debug("Generated PSBT: %s" % (psbt,))
+ sys.stderr.write("PSBT signing failed\n")
+ return None
+ block, signet_solution = decode_psbt(psbt_signed["psbt"])
+ return finish_block(block, signet_solution, grind_cmd)
def do_generate(args):
if args.max_blocks is not None:
@@ -312,8 +391,13 @@ def do_generate(args):
logging.error("--max-interval must be at least 960 (16 minutes)")
return 1
+ poolid = get_poolid(args)
+
ultimate_target = nbits_to_target(int(args.nbits,16))
+ gen = Generate(multiminer=my_blocks, ultimate_target=ultimate_target, poisson=args.poisson, max_interval=args.max_interval,
+ standby_delay=args.standby_delay, backup_delay=args.backup_delay, set_block_time=args.set_block_time, poolid=poolid)
+
mined_blocks = 0
bestheader = {"hash": None}
lastheader = None
@@ -328,104 +412,55 @@ def do_generate(args):
if lastheader is None:
lastheader = bestheader["hash"]
elif bestheader["hash"] != lastheader:
- next_delta = next_block_delta(int(bestheader["bits"], 16), bestheader["hash"], ultimate_target, args.poisson, args.max_interval)
+ next_delta = gen.next_block_delta(int(bestheader["bits"], 16), bestheader["hash"])
next_delta += bestheader["time"] - time.time()
- next_is_mine = next_block_is_mine(bestheader["hash"], my_blocks)
+ next_is_mine = gen.next_block_is_mine(bestheader["hash"])
logging.info("Received new block at height %d; next in %s (%s)", bestheader["height"], seconds_to_hms(next_delta), ("mine" if next_is_mine else "backup"))
lastheader = bestheader["hash"]
# when is the next block due to be mined?
now = time.time()
- if args.set_block_time is not None:
- logging.debug("Setting start time to %d", args.set_block_time)
- mine_time = args.set_block_time
- action_time = now
- is_mine = True
- elif bestheader["height"] == 0:
- time_delta = next_block_delta(int(bestheader["bits"], 16), bci["bestblockhash"], ultimate_target, args.poisson, args.max_interval)
- time_delta *= 100 # 100 blocks
- logging.info("Backdating time for first block to %d minutes ago" % (time_delta/60))
- mine_time = now - time_delta
- action_time = now
- is_mine = True
- else:
- time_delta = next_block_delta(int(bestheader["bits"], 16), bci["bestblockhash"], ultimate_target, args.poisson, args.max_interval)
- mine_time = bestheader["time"] + time_delta
-
- is_mine = next_block_is_mine(bci["bestblockhash"], my_blocks)
-
- action_time = mine_time
- if not is_mine:
- action_time += args.backup_delay
-
- if args.standby_delay > 0:
- action_time += args.standby_delay
- elif mined_blocks == 0:
- # for non-standby, always mine immediately on startup,
- # even if the next block shouldn't be ours
- action_time = now
-
- # don't want fractional times so round down
- mine_time = int(mine_time)
- action_time = int(action_time)
-
- # can't mine a block 2h in the future; 1h55m for some safety
- action_time = max(action_time, mine_time - 6900)
+ gen.next_block_time(now, bestheader, (mined_blocks == 0))
# ready to go? otherwise sleep and check for new block
- if now < action_time:
- sleep_for = min(action_time - now, 60)
- if mine_time < now:
+ if now < gen.action_time:
+ sleep_for = min(gen.action_time - now, 60)
+ if gen.mine_time < now:
# someone else might have mined the block,
# so check frequently, so we don't end up late
# mining the next block if it's ours
sleep_for = min(20, sleep_for)
- minestr = "mine" if is_mine else "backup"
- logging.debug("Sleeping for %s, next block due in %s (%s)" % (seconds_to_hms(sleep_for), seconds_to_hms(mine_time - now), minestr))
+ minestr = "mine" if gen.is_mine else "backup"
+ logging.debug("Sleeping for %s, next block due in %s (%s)" % (seconds_to_hms(sleep_for), seconds_to_hms(gen.mine_time - now), minestr))
time.sleep(sleep_for)
continue
# gbt
- tmpl = json.loads(args.bcli("getblocktemplate", '{"rules":["signet","segwit"]}'))
- if tmpl["previousblockhash"] != bci["bestblockhash"]:
- logging.warning("GBT based off unexpected block (%s not %s), retrying", tmpl["previousblockhash"], bci["bestblockhash"])
- time.sleep(1)
+ tmpl = gen.gbt(args.bcli, bci["bestblockhash"], now)
+ if tmpl is None:
continue
logging.debug("GBT template: %s", tmpl)
- if tmpl["mintime"] > mine_time:
- logging.info("Updating block time from %d to %d", mine_time, tmpl["mintime"])
- mine_time = tmpl["mintime"]
- if mine_time > now:
- logging.error("GBT mintime is in the future: %d is %d seconds later than %d", mine_time, (mine_time-now), now)
- return 1
-
# address for reward
reward_addr, reward_spk = get_reward_addr_spk(args, tmpl["height"])
# mine block
- logging.debug("Mining block delta=%s start=%s mine=%s", seconds_to_hms(mine_time-bestheader["time"]), mine_time, is_mine)
+ logging.debug("Mining block delta=%s start=%s mine=%s", seconds_to_hms(gen.mine_time-bestheader["time"]), gen.mine_time, gen.is_mine)
mined_blocks += 1
- psbt = generate_psbt(tmpl, reward_spk, blocktime=mine_time)
- input_stream = os.linesep.join([psbt, "true", "ALL"]).encode('utf8')
- psbt_signed = json.loads(args.bcli("-stdin", "walletprocesspsbt", input=input_stream))
- if not psbt_signed.get("complete",False):
- logging.debug("Generated PSBT: %s" % (psbt,))
- sys.stderr.write("PSBT signing failed\n")
+ block = gen.mine(args.bcli, args.grind_cmd, tmpl, reward_spk)
+ if block is None:
return 1
- block, signet_solution = do_decode_psbt(psbt_signed["psbt"])
- block = finish_block(block, signet_solution, args.grind_cmd)
# submit block
r = args.bcli("-stdin", "submitblock", input=block.serialize().hex().encode('utf8'))
# report
- bstr = "block" if is_mine else "backup block"
+ bstr = "block" if gen.is_mine else "backup block"
- next_delta = next_block_delta(block.nBits, block.hash, ultimate_target, args.poisson, args.max_interval)
+ next_delta = gen.next_block_delta(block.nBits, block.hash)
next_delta += block.nTime - time.time()
- next_is_mine = next_block_is_mine(block.hash, my_blocks)
+ next_is_mine = gen.next_block_is_mine(block.hash)
logging.debug("Block hash %s payout to %s", block.hash, reward_addr)
logging.info("Mined %s at height %d; next in %s (%s)", bstr, tmpl["height"], seconds_to_hms(next_delta), ("mine" if next_is_mine else "backup"))
@@ -486,6 +521,8 @@ def main():
cmds = parser.add_subparsers(help="sub-commands")
genpsbt = cmds.add_parser("genpsbt", help="Generate a block PSBT for signing")
genpsbt.set_defaults(fn=do_genpsbt)
+ genpsbt.add_argument("--poolnum", default=None, type=int, help="Identify blocks that you mine")
+ genpsbt.add_argument("--poolid", default=None, type=str, help="Identify blocks that you mine (eg: /signet:1/)")
solvepsbt = cmds.add_parser("solvepsbt", help="Solve a signed block PSBT")
solvepsbt.set_defaults(fn=do_solvepsbt)
@@ -502,6 +539,8 @@ def main():
generate.add_argument("--backup-delay", default=300, type=int, help="Seconds to delay before mining blocks reserved for other miners (default=300)")
generate.add_argument("--standby-delay", default=0, type=int, help="Seconds to delay before mining blocks (default=0)")
generate.add_argument("--max-interval", default=1800, type=int, help="Maximum interblock interval (seconds)")
+ generate.add_argument("--poolnum", default=None, type=int, help="Identify blocks that you mine")
+ generate.add_argument("--poolid", default=None, type=str, help="Identify blocks that you mine (eg: /signet:1/)")
calibrate = cmds.add_parser("calibrate", help="Calibrate difficulty")
calibrate.set_defaults(fn=do_calibrate)
diff --git a/doc/README.md b/doc/README.md
index 446684b4821ea..7b6dacaf4f704 100644
--- a/doc/README.md
+++ b/doc/README.md
@@ -59,7 +59,6 @@ The Bitcoin repo's [root README](/README.md) contains relevant information on th
- [Translation Strings Policy](translation_strings_policy.md)
- [JSON-RPC Interface](JSON-RPC-interface.md)
- [Unauthenticated REST Interface](REST-interface.md)
-- [Shared Libraries](shared-libraries.md)
- [BIPS](bips.md)
- [Dnsseed Policy](dnsseed-policy.md)
- [Benchmarking](benchmarking.md)
diff --git a/doc/design/libraries.md b/doc/design/libraries.md
index 7cda64e713a05..3346c8e81b544 100644
--- a/doc/design/libraries.md
+++ b/doc/design/libraries.md
@@ -4,10 +4,9 @@
|--------------------------|-------------|
| *libbitcoin_cli* | RPC client functionality used by *bitcoin-cli* executable |
| *libbitcoin_common* | Home for common functionality shared by different executables and libraries. Similar to *libbitcoin_util*, but higher-level (see [Dependencies](#dependencies)). |
-| *libbitcoin_consensus* | Stable, backwards-compatible consensus functionality used by *libbitcoin_node* and *libbitcoin_wallet* and also exposed as a [shared library](../shared-libraries.md). |
-| *libbitcoinconsensus* | Shared library build of static *libbitcoin_consensus* library |
-| *libbitcoin_kernel* | Consensus engine and support library used for validation by *libbitcoin_node* and also exposed as a [shared library](../shared-libraries.md). |
-| *libbitcoinqt* | GUI functionality used by *bitcoin-qt* and *bitcoin-gui* executables |
+| *libbitcoin_consensus* | Stable, backwards-compatible consensus functionality used by *libbitcoin_node* and *libbitcoin_wallet*. |
+| *libbitcoin_kernel* | Consensus engine and support library used for validation by *libbitcoin_node*. |
+| *libbitcoinqt* | GUI functionality used by *bitcoin-qt* and *bitcoin-gui* executables. |
| *libbitcoin_ipc* | IPC functionality used by *bitcoin-node*, *bitcoin-wallet*, *bitcoin-gui* executables to communicate when [`--enable-multiprocess`](multiprocess.md) is used. |
| *libbitcoin_node* | P2P and RPC server functionality used by *bitcoind* and *bitcoin-qt* executables. |
| *libbitcoin_util* | Home for common functionality shared by different executables and libraries. Similar to *libbitcoin_common*, but lower-level (see [Dependencies](#dependencies)). |
@@ -17,7 +16,7 @@
## Conventions
-- Most libraries are internal libraries and have APIs which are completely unstable! There are few or no restrictions on backwards compatibility or rules about external dependencies. Exceptions are *libbitcoin_consensus* and *libbitcoin_kernel* which have external interfaces documented at [../shared-libraries.md](../shared-libraries.md).
+- Most libraries are internal libraries and have APIs which are completely unstable! There are few or no restrictions on backwards compatibility or rules about external dependencies. An exception is *libbitcoin_kernel*, which, at some future point, will have a documented external interface.
- Generally each library should have a corresponding source directory and namespace. Source code organization is a work in progress, so it is true that some namespaces are applied inconsistently, and if you look at [`libbitcoin_*_SOURCES`](../../src/Makefile.am) lists you can see that many libraries pull in files from outside their source directory. But when working with libraries, it is good to follow a consistent pattern like:
diff --git a/doc/shared-libraries.md b/doc/shared-libraries.md
deleted file mode 100644
index 3a448c655612e..0000000000000
--- a/doc/shared-libraries.md
+++ /dev/null
@@ -1,78 +0,0 @@
-Shared Libraries
-================
-
-## bitcoinconsensus
-***This library is deprecated and will be removed in v28***
-
-The purpose of this library is to make the verification functionality that is critical to Bitcoin's consensus available to other applications, e.g. to language bindings.
-
-### API
-
-The interface is defined in the C header `bitcoinconsensus.h` located in `src/script/bitcoinconsensus.h`.
-
-#### Version
-
-`bitcoinconsensus_version` returns an `unsigned int` with the API version *(currently `2`)*.
-
-#### Script Validation
-
-`bitcoinconsensus_verify_script`, `bitcoinconsensus_verify_script_with_amount` and `bitcoinconsensus_verify_script_with_spent_outputs` return an `int` with the status of the verification. It will be `1` if the input script correctly spends the previous output `scriptPubKey`.
-
-##### Parameters
-###### bitcoinconsensus_verify_script
-- `const unsigned char *scriptPubKey` - The previous output script that encumbers spending.
-- `unsigned int scriptPubKeyLen` - The number of bytes for the `scriptPubKey`.
-- `const unsigned char *txTo` - The transaction with the input that is spending the previous output.
-- `unsigned int txToLen` - The number of bytes for the `txTo`.
-- `unsigned int nIn` - The index of the input in `txTo` that spends the `scriptPubKey`.
-- `unsigned int flags` - The script validation flags *(see below)*.
-- `bitcoinconsensus_error* err` - Will have the error/success code for the operation *(see below)*.
-
-###### bitcoinconsensus_verify_script_with_amount
-- `const unsigned char *scriptPubKey` - The previous output script that encumbers spending.
-- `unsigned int scriptPubKeyLen` - The number of bytes for the `scriptPubKey`.
-- `int64_t amount` - The amount spent in the input
-- `const unsigned char *txTo` - The transaction with the input that is spending the previous output.
-- `unsigned int txToLen` - The number of bytes for the `txTo`.
-- `unsigned int nIn` - The index of the input in `txTo` that spends the `scriptPubKey`.
-- `unsigned int flags` - The script validation flags *(see below)*.
-- `bitcoinconsensus_error* err` - Will have the error/success code for the operation *(see below)*.
-
-###### bitcoinconsensus_verify_script_with_spent_outputs
-- `const unsigned char *scriptPubKey` - The previous output script that encumbers spending.
-- `unsigned int scriptPubKeyLen` - The number of bytes for the `scriptPubKey`.
-- `int64_t amount` - The amount spent in the input
-- `const unsigned char *txTo` - The transaction with the input that is spending the previous output.
-- `unsigned int txToLen` - The number of bytes for the `txTo`.
-- `UTXO *spentOutputs` - Previous outputs spent in the transaction. `UTXO` is a struct composed by `const unsigned char *scriptPubKey`, `unsigned int scriptPubKeySize` (the number of bytes for the `scriptPubKey`) and `unsigned int value`.
-- `unsigned int spentOutputsLen` - The number of bytes for the `spentOutputs`.
-- `unsigned int nIn` - The index of the input in `txTo` that spends the `scriptPubKey`.
-- `unsigned int flags` - The script validation flags *(see below)*.
-- `bitcoinconsensus_error* err` - Will have the error/success code for the operation *(see below)*.
-
-##### Script Flags
-- `bitcoinconsensus_SCRIPT_FLAGS_VERIFY_NONE`
-- `bitcoinconsensus_SCRIPT_FLAGS_VERIFY_P2SH` - Evaluate P2SH ([BIP16](https://github.com/bitcoin/bips/blob/master/bip-0016.mediawiki)) subscripts
-- `bitcoinconsensus_SCRIPT_FLAGS_VERIFY_DERSIG` - Enforce strict DER ([BIP66](https://github.com/bitcoin/bips/blob/master/bip-0066.mediawiki)) compliance
-- `bitcoinconsensus_SCRIPT_FLAGS_VERIFY_NULLDUMMY` - Enforce NULLDUMMY ([BIP147](https://github.com/bitcoin/bips/blob/master/bip-0147.mediawiki))
-- `bitcoinconsensus_SCRIPT_FLAGS_VERIFY_CHECKLOCKTIMEVERIFY` - Enable CHECKLOCKTIMEVERIFY ([BIP65](https://github.com/bitcoin/bips/blob/master/bip-0065.mediawiki))
-- `bitcoinconsensus_SCRIPT_FLAGS_VERIFY_CHECKSEQUENCEVERIFY` - Enable CHECKSEQUENCEVERIFY ([BIP112](https://github.com/bitcoin/bips/blob/master/bip-0112.mediawiki))
-- `bitcoinconsensus_SCRIPT_FLAGS_VERIFY_WITNESS` - Enable WITNESS ([BIP141](https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki))
-- `bitcoinconsensus_SCRIPT_FLAGS_VERIFY_TAPROOT` - Enable TAPROOT ([BIP340](https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki), [BIP341](https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki), [BIP342](https://github.com/bitcoin/bips/blob/master/bip-0342.mediawiki))
-
-##### Errors
-- `bitcoinconsensus_ERR_OK` - No errors with input parameters *(see the return value of `bitcoinconsensus_verify_script` for the verification status)*
-- `bitcoinconsensus_ERR_TX_INDEX` - An invalid index for `txTo`
-- `bitcoinconsensus_ERR_TX_SIZE_MISMATCH` - `txToLen` did not match with the size of `txTo`
-- `bitcoinconsensus_ERR_DESERIALIZE` - An error deserializing `txTo`
-- `bitcoinconsensus_ERR_AMOUNT_REQUIRED` - Input amount is required if WITNESS is used
-- `bitcoinconsensus_ERR_INVALID_FLAGS` - Script verification `flags` are invalid (i.e. not part of the libconsensus interface)
-- `bitcoinconsensus_ERR_SPENT_OUTPUTS_REQUIRED` - Spent outputs are required if TAPROOT is used
-- `bitcoinconsensus_ERR_SPENT_OUTPUTS_MISMATCH` - Spent outputs size doesn't match tx inputs size
-
-### Example Implementations
-- [NBitcoin](https://github.com/MetacoSA/NBitcoin/blob/5e1055cd7c4186dee4227c344af8892aea54faec/NBitcoin/Script.cs#L979-#L1031) (.NET Bindings)
-- [node-libbitcoinconsensus](https://github.com/bitpay/node-libbitcoinconsensus) (Node.js Bindings)
-- [java-libbitcoinconsensus](https://github.com/dexX7/java-libbitcoinconsensus) (Java Bindings)
-- [bitcoinconsensus-php](https://github.com/Bit-Wasp/bitcoinconsensus-php) (PHP Bindings)
-- [rust-bitcoinconsensus](https://github.com/rust-bitcoin/rust-bitcoinconsensus) (Rust Bindings)
\ No newline at end of file
diff --git a/libbitcoinconsensus.pc.in b/libbitcoinconsensus.pc.in
deleted file mode 100644
index 1ceab280bb114..0000000000000
--- a/libbitcoinconsensus.pc.in
+++ /dev/null
@@ -1,10 +0,0 @@
-prefix=@prefix@
-exec_prefix=@exec_prefix@
-libdir=@libdir@
-includedir=@includedir@
-
-Name: @PACKAGE_NAME@ consensus library
-Description: Library for the Bitcoin consensus protocol.
-Version: @PACKAGE_VERSION@
-Libs: -L${libdir} -lbitcoinconsensus
-Cflags: -I${includedir}
diff --git a/src/Makefile.am b/src/Makefile.am
index b5d5c4652ab0c..3e142943c5aa8 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -38,9 +38,6 @@ LIBSECP256K1=secp256k1/libsecp256k1.la
if ENABLE_ZMQ
LIBBITCOIN_ZMQ=libbitcoin_zmq.a
endif
-if BUILD_BITCOIN_LIBS
-LIBBITCOINCONSENSUS=libbitcoinconsensus.la
-endif
if BUILD_BITCOIN_KERNEL_LIB
LIBBITCOINKERNEL=libbitcoinkernel.la
endif
@@ -646,7 +643,6 @@ libbitcoin_consensus_a_SOURCES = \
primitives/transaction.h \
pubkey.cpp \
pubkey.h \
- script/bitcoinconsensus.cpp \
script/interpreter.cpp \
script/interpreter.h \
script/script.cpp \
@@ -1008,21 +1004,6 @@ libbitcoinkernel_la-clientversion.l$(OBJEXT): obj/build.h
endif # BUILD_BITCOIN_KERNEL_LIB
#
-# bitcoinconsensus library #
-if BUILD_BITCOIN_LIBS
-lib_LTLIBRARIES += $(LIBBITCOINCONSENSUS)
-
-include_HEADERS = script/bitcoinconsensus.h
-libbitcoinconsensus_la_SOURCES = support/cleanse.cpp $(crypto_libbitcoin_crypto_base_la_SOURCES) $(libbitcoin_consensus_a_SOURCES)
-
-libbitcoinconsensus_la_LDFLAGS = $(AM_LDFLAGS) -no-undefined $(RELDFLAGS)
-libbitcoinconsensus_la_LIBADD = $(LIBSECP256K1)
-libbitcoinconsensus_la_CPPFLAGS = $(AM_CPPFLAGS) -I$(builddir)/obj -I$(srcdir)/secp256k1/include -DBUILD_BITCOIN_INTERNAL -DDISABLE_OPTIMIZED_SHA256
-libbitcoinconsensus_la_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-
-endif
-#
-
CTAES_DIST = crypto/ctaes/bench.c
CTAES_DIST += crypto/ctaes/ctaes.c
CTAES_DIST += crypto/ctaes/ctaes.h
diff --git a/src/Makefile.test.include b/src/Makefile.test.include
index 9f9bdbbd0cd4b..8d44e8df0a405 100644
--- a/src/Makefile.test.include
+++ b/src/Makefile.test.include
@@ -362,7 +362,6 @@ test_fuzz_fuzz_SOURCES = \
test/fuzz/rpc.cpp \
test/fuzz/script.cpp \
test/fuzz/script_assets_test_minimizer.cpp \
- test/fuzz/script_bitcoin_consensus.cpp \
test/fuzz/script_descriptor_cache.cpp \
test/fuzz/script_flags.cpp \
test/fuzz/script_format.cpp \
diff --git a/src/bench/verify_script.cpp b/src/bench/verify_script.cpp
index e7166a91cf4eb..ee750bc1f8a35 100644
--- a/src/bench/verify_script.cpp
+++ b/src/bench/verify_script.cpp
@@ -2,15 +2,8 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#if defined(HAVE_CONFIG_H)
-#include
-#endif
-
#include
#include
-#if defined(HAVE_CONSENSUS_LIB)
-#include