Skip to content
Merged
4 changes: 2 additions & 2 deletions configure.ac
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
AC_PREREQ([2.69])
define(_CLIENT_VERSION_MAJOR, 23)
define(_CLIENT_VERSION_MINOR, 3)
define(_CLIENT_VERSION_BUILD, 2)
define(_CLIENT_VERSION_RC, 0)
define(_CLIENT_VERSION_BUILD, 3)
define(_CLIENT_VERSION_RC, 1)
define(_CLIENT_VERSION_IS_RELEASE, true)
define(_COPYRIGHT_YEAR, 2026)
define(_COPYRIGHT_HOLDERS,[The %s developers])
Expand Down
6 changes: 3 additions & 3 deletions doc/man/elements-cli.1
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3.
.TH ELEMENTS-CLI "1" "February 2026" "elements-cli v23.3.2" "User Commands"
.TH ELEMENTS-CLI "1" "February 2026" "elements-cli v23.3.3" "User Commands"
.SH NAME
elements-cli \- manual page for elements-cli v23.3.2
elements-cli \- manual page for elements-cli v23.3.3
.SH SYNOPSIS
.B elements-cli
[\fI\,options\/\fR] \fI\,<command> \/\fR[\fI\,params\/\fR] \fI\,Send command to Elements Core\/\fR
Expand All @@ -15,7 +15,7 @@ elements-cli \- manual page for elements-cli v23.3.2
.B elements-cli
[\fI\,options\/\fR] \fI\,help <command> Get help for a command\/\fR
.SH DESCRIPTION
Elements Core RPC client version v23.3.2
Elements Core RPC client version v23.3.3
.SH OPTIONS
.HP
\-?
Expand Down
32 changes: 28 additions & 4 deletions doc/man/elements-qt.1
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3.
.TH ELEMENTS-QT "1" "February 2026" "elements-qt v23.3.2" "User Commands"
.TH ELEMENTS-QT "1" "February 2026" "elements-qt v23.3.3" "User Commands"
.SH NAME
elements-qt \- manual page for elements-qt v23.3.2
elements-qt \- manual page for elements-qt v23.3.3
.SH SYNOPSIS
.B elements-qt
[\fI\,command-line options\/\fR]
.SH DESCRIPTION
Elements Core version v23.3.2
Elements Core version v23.3.3
.SH OPTIONS
.HP
\-?
Expand Down Expand Up @@ -755,6 +755,30 @@ address. (default: 111)
The byte prefix, in decimal, of the parent chain's base58 script
address. (default: 196)
.HP
\fB\-peginminamount\fR
.IP
The minimum value for a peg\-in transaction after peginminheight
(default: unset).
.HP
\fB\-peginminheight\fR
.IP
The block height at which a minimum peg\-in value is enforced (default:
not active).
.HP
\fB\-peginsubsidyheight\fR
.IP
The block height at which peg\-in transactions must have a burn subsidy
(default: not active). The subsidy is an OP_RETURN output, with
its value equal to the feerate of the parent transaction
multiplied by the vsize of spending the P2WSH output created by
the peg\-in (feerate * 396 sats for liquidv1).
.HP
\fB\-peginsubsidythreshold\fR
.IP
The output value below which peg\-in transactions must have a burn
subsidy (default: 0). Peg\-ins above this value do not require the
subsidy.
.HP
\fB\-pubkeyprefix\fR
.IP
The byte prefix, in decimal, of the chain's base58 pubkey address.
Expand Down Expand Up @@ -1057,7 +1081,7 @@ pre\-dynamic federations. Only used for testing in custom chains.
.HP
\fB\-peginconfirmationdepth=\fR<n>
.IP
Pegin claims must be this deep to be considered valid. (default: 8)
Peg\-in claims must be this deep to be considered valid. (default: 8)
.HP
\fB\-total_valid_epochs\fR
.IP
Expand Down
6 changes: 3 additions & 3 deletions doc/man/elements-tx.1
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3.
.TH ELEMENTS-TX "1" "February 2026" "elements-tx v23.3.2" "User Commands"
.TH ELEMENTS-TX "1" "February 2026" "elements-tx v23.3.3" "User Commands"
.SH NAME
elements-tx \- manual page for elements-tx v23.3.2
elements-tx \- manual page for elements-tx v23.3.3
.SH SYNOPSIS
.B elements-tx
[\fI\,options\/\fR] \fI\,<hex-tx> \/\fR[\fI\,commands\/\fR] \fI\,Update hex-encoded Elements transaction\/\fR
.br
.B elements-tx
[\fI\,options\/\fR] \fI\,-create \/\fR[\fI\,commands\/\fR] \fI\,Create hex-encoded Elements transaction\/\fR
.SH DESCRIPTION
Elements Core elements\-tx utility version v23.3.2
Elements Core elements\-tx utility version v23.3.3
.SH OPTIONS
.HP
\-?
Expand Down
6 changes: 3 additions & 3 deletions doc/man/elements-util.1
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3.
.TH ELEMENTS-UTIL "1" "February 2026" "elements-util v23.3.2" "User Commands"
.TH ELEMENTS-UTIL "1" "February 2026" "elements-util v23.3.3" "User Commands"
.SH NAME
elements-util \- manual page for elements-util v23.3.2
elements-util \- manual page for elements-util v23.3.3
.SH SYNOPSIS
.B bitcoin-util
[\fI\,options\/\fR] [\fI\,commands\/\fR] \fI\,Do stuff\/\fR
.SH DESCRIPTION
Elements Core bitcoin\-util utility version v23.3.2
Elements Core bitcoin\-util utility version v23.3.3
.SH OPTIONS
.HP
\-?
Expand Down
6 changes: 3 additions & 3 deletions doc/man/elements-wallet.1
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3.
.TH ELEMENTS-WALLET "1" "February 2026" "elements-wallet v23.3.2" "User Commands"
.TH ELEMENTS-WALLET "1" "February 2026" "elements-wallet v23.3.3" "User Commands"
.SH NAME
elements-wallet \- manual page for elements-wallet v23.3.2
elements-wallet \- manual page for elements-wallet v23.3.3
.SH DESCRIPTION
Elements Core elements\-wallet version v23.3.2
Elements Core elements\-wallet version v23.3.3
.PP
elements\-wallet is an offline tool for creating and interacting with Elements Core wallet files.
By default elements\-wallet will act on wallets in the default mainnet wallet directory in the datadir.
Expand Down
32 changes: 28 additions & 4 deletions doc/man/elementsd.1
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3.
.TH ELEMENTSD "1" "February 2026" "elementsd v23.3.2" "User Commands"
.TH ELEMENTSD "1" "February 2026" "elementsd v23.3.3" "User Commands"
.SH NAME
elementsd \- manual page for elementsd v23.3.2
elementsd \- manual page for elementsd v23.3.3
.SH SYNOPSIS
.B elementsd
[\fI\,options\/\fR] \fI\,Start Elements Core\/\fR
.SH DESCRIPTION
Elements Core version v23.3.2
Elements Core version v23.3.3
.SH OPTIONS
.HP
\-?
Expand Down Expand Up @@ -755,6 +755,30 @@ address. (default: 111)
The byte prefix, in decimal, of the parent chain's base58 script
address. (default: 196)
.HP
\fB\-peginminamount\fR
.IP
The minimum value for a peg\-in transaction after peginminheight
(default: unset).
.HP
\fB\-peginminheight\fR
.IP
The block height at which a minimum peg\-in value is enforced (default:
not active).
.HP
\fB\-peginsubsidyheight\fR
.IP
The block height at which peg\-in transactions must have a burn subsidy
(default: not active). The subsidy is an OP_RETURN output, with
its value equal to the feerate of the parent transaction
multiplied by the vsize of spending the P2WSH output created by
the peg\-in (feerate * 396 sats for liquidv1).
.HP
\fB\-peginsubsidythreshold\fR
.IP
The output value below which peg\-in transactions must have a burn
subsidy (default: 0). Peg\-ins above this value do not require the
subsidy.
.HP
\fB\-pubkeyprefix\fR
.IP
The byte prefix, in decimal, of the chain's base58 pubkey address.
Expand Down Expand Up @@ -1035,7 +1059,7 @@ pre\-dynamic federations. Only used for testing in custom chains.
.HP
\fB\-peginconfirmationdepth=\fR<n>
.IP
Pegin claims must be this deep to be considered valid. (default: 8)
Peg\-in claims must be this deep to be considered valid. (default: 8)
.HP
\fB\-total_valid_epochs\fR
.IP
Expand Down
59 changes: 58 additions & 1 deletion src/chainparams.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@

#include <chainparamsseeds.h>
#include <consensus/merkle.h>
#include <crypto/sha256.h>
#include <deploymentinfo.h>
#include <hash.h> // for signet block challenge hash
#include <issuance.h>
#include <primitives/transaction.h>
#include <util/moneystr.h>
#include <util/system.h>
#include <crypto/sha256.h>

#include <assert.h>

Expand Down Expand Up @@ -232,6 +233,8 @@ class CMainParams : public CChainParams {
multi_data_permitted = false;
accept_discount_ct = false;
create_discount_ct = false;
pegin_subsidy = PeginSubsidy();
pegin_minimum = PeginMinimum();
consensus.has_parent_chain = false;
g_signed_blocks = false;
g_con_elementsmode = false;
Expand Down Expand Up @@ -379,6 +382,8 @@ class CTestNetParams : public CChainParams {
multi_data_permitted = false;
accept_discount_ct = false;
create_discount_ct = false;
pegin_subsidy = PeginSubsidy();
pegin_minimum = PeginMinimum();
consensus.has_parent_chain = false;
g_signed_blocks = false;
g_con_elementsmode = false;
Expand Down Expand Up @@ -544,6 +549,8 @@ class SigNetParams : public CChainParams {
multi_data_permitted = false;
accept_discount_ct = false;
create_discount_ct = false;
pegin_subsidy = PeginSubsidy();
pegin_minimum = PeginMinimum();
consensus.has_parent_chain = false;
g_signed_blocks = false; // lol
g_con_elementsmode = false;
Expand Down Expand Up @@ -648,6 +655,8 @@ class CRegTestParams : public CChainParams {
multi_data_permitted = false;
accept_discount_ct = false;
create_discount_ct = false;
pegin_subsidy = PeginSubsidy();
pegin_minimum = PeginMinimum();
consensus.has_parent_chain = false;
g_signed_blocks = false;
g_con_elementsmode = false;
Expand Down Expand Up @@ -792,6 +801,39 @@ void CRegTestParams::UpdateActivationParametersFromArgs(const ArgsManager& args)
}
}

// ELEMENTS
PeginSubsidy ParsePeginSubsidy(const ArgsManager& args) {
PeginSubsidy pegin_subsidy;

pegin_subsidy.height = args.GetIntArg("-peginsubsidyheight", std::numeric_limits<int>::max());
if (pegin_subsidy.height < 0) {
throw std::runtime_error(strprintf("Invalid block height (%d) for -peginsubsidyheight. Must be positive.", pegin_subsidy.height));
}
if (std::optional<CAmount> amount = ParseMoney(args.GetArg("-peginsubsidythreshold", "0"))) {
pegin_subsidy.threshold = amount.value();
} else {
throw std::runtime_error("Invalid -peginsubsidythreshold");
}

return pegin_subsidy;
};

PeginMinimum ParsePeginMinimum(const ArgsManager& args) {
PeginMinimum pegin_minimum;

pegin_minimum.height = args.GetIntArg("-peginminheight", std::numeric_limits<int>::max());
if (pegin_minimum.height < 0) {
throw std::runtime_error(strprintf("Invalid block height (%d) for -peginminheight. Must be positive.", pegin_minimum.height));
}
if (std::optional<CAmount> amount = ParseMoney(args.GetArg("-peginminamount", "0"))) {
pegin_minimum.amount = amount.value();
} else {
throw std::runtime_error("Invalid -peginminamount");
}

return pegin_minimum;
};

/**
* Custom params for testing.
*/
Expand Down Expand Up @@ -932,6 +974,11 @@ class CCustomParams : public CRegTestParams {
consensus.start_p2wsh_script = args.GetIntArg("-con_start_p2wsh_script", consensus.start_p2wsh_script);
create_discount_ct = args.GetBoolArg("-creatediscountct", create_discount_ct);
accept_discount_ct = args.GetBoolArg("-acceptdiscountct", accept_discount_ct) || create_discount_ct;
pegin_subsidy = ParsePeginSubsidy(args);
pegin_minimum = ParsePeginMinimum(args);
if (pegin_subsidy.threshold < pegin_minimum.amount) {
throw std::runtime_error(strprintf("Peg-in subsidy threshold (%s) must be greater than or equal to peg-in minimum amount (%s)", FormatMoney(pegin_subsidy.threshold), FormatMoney(pegin_minimum.amount)));
}

// Calculate pegged Bitcoin asset
std::vector<unsigned char> commit = CommitToArguments(consensus, strNetworkID);
Expand Down Expand Up @@ -1178,6 +1225,11 @@ class CLiquidV1Params : public CChainParams {
multi_data_permitted = true;
create_discount_ct = args.GetBoolArg("-creatediscountct", false);
accept_discount_ct = args.GetBoolArg("-acceptdiscountct", true) || create_discount_ct;
pegin_subsidy = ParsePeginSubsidy(args);
pegin_minimum = ParsePeginMinimum(args);
if (pegin_subsidy.threshold < pegin_minimum.amount) {
throw std::runtime_error(strprintf("Peg-in subsidy threshold (%s) must be greater than or equal to peg-in minimum amount (%s)", FormatMoney(pegin_subsidy.threshold), FormatMoney(pegin_minimum.amount)));
}

parentGenesisBlockHash = uint256S("000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f");
const bool parent_genesis_is_null = parentGenesisBlockHash == uint256();
Expand Down Expand Up @@ -1538,6 +1590,11 @@ class CLiquidV1TestParams : public CLiquidV1Params {
multi_data_permitted = args.GetBoolArg("-multi_data_permitted", multi_data_permitted);
create_discount_ct = args.GetBoolArg("-creatediscountct", create_discount_ct);
accept_discount_ct = args.GetBoolArg("-acceptdiscountct", accept_discount_ct) || create_discount_ct;
pegin_subsidy = ParsePeginSubsidy(args);
pegin_minimum = ParsePeginMinimum(args);
if (pegin_subsidy.threshold < pegin_minimum.amount) {
throw std::runtime_error(strprintf("Peg-in subsidy threshold (%s) must be greater than or equal to peg-in minimum amount (%s)", FormatMoney(pegin_subsidy.threshold), FormatMoney(pegin_minimum.amount)));
}

if (args.IsArgSet("-parentgenesisblockhash")) {
parentGenesisBlockHash = uint256S(args.GetArg("-parentgenesisblockhash", ""));
Expand Down
25 changes: 25 additions & 0 deletions src/chainparams.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,27 @@ struct CCheckpointData {
}
};

// ELEMENTS
struct PeginSubsidy {
int height{std::numeric_limits<int>::max()};
CAmount threshold{0};

PeginSubsidy() {};
bool IsDefined() {
return threshold > 0 || height < std::numeric_limits<int>::max();
};
};

struct PeginMinimum {
int height{std::numeric_limits<int>::max()};
CAmount amount{0};

PeginMinimum() {};
bool IsDefined() {
return amount > 0 || height < std::numeric_limits<int>::max();
};
};

struct AssumeutxoHash : public BaseHash<uint256> {
explicit AssumeutxoHash(const uint256& hash) : BaseHash(hash) {}
};
Expand Down Expand Up @@ -138,6 +159,8 @@ class CChainParams
bool GetMultiDataPermitted() const { return multi_data_permitted; }
bool GetAcceptDiscountCT() const { return accept_discount_ct; }
bool GetCreateDiscountCT() const { return create_discount_ct; }
PeginSubsidy GetPeginSubsidy() const { return pegin_subsidy; }
PeginMinimum GetPeginMinimum() const { return pegin_minimum; }

protected:
CChainParams() {}
Expand Down Expand Up @@ -173,6 +196,8 @@ class CChainParams
bool multi_data_permitted;
bool accept_discount_ct;
bool create_discount_ct;
PeginSubsidy pegin_subsidy;
PeginMinimum pegin_minimum;
};

/**
Expand Down
31 changes: 31 additions & 0 deletions src/dynafed.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,3 +123,34 @@ DynaFedParamEntry ComputeNextBlockCurrentParameters(const CBlockIndex* pindexPre
}
}

bool ParseFedPegQuorum(const CScript& fedpegscript, int& t, int& n) {
CScript::const_iterator it = fedpegscript.begin();
std::vector<unsigned char> vch;
opcodetype opcode;

// parse the required threshold number
if (!fedpegscript.GetOp(it, opcode, vch)) return false;
t = CScript::DecodeOP_N(opcode);
if (t < 1 || t > MAX_PUBKEYS_PER_MULTISIG) return false;

// support a fedpegscript like OP_TRUE if we're at the end of the script
if (it == fedpegscript.end()) return true;

// count the pubkeys
int pubkeys = 0;
while (fedpegscript.GetOp(it, opcode, vch)) {
if (opcode != 0x21) break;
if (vch.size() != 33) return false;
pubkeys++;
}

// parse the total number of pubkeys
n = CScript::DecodeOP_N(opcode);
if (n < 1 || n > MAX_PUBKEYS_PER_MULTISIG || n < t) return false;
if (pubkeys != n) return false;

// the next opcode must be OP_CHECKMULTISIG
if (!fedpegscript.GetOp(it, opcode, vch)) return false;

return opcode == OP_CHECKMULTISIG;
}
Loading