Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
640e4ae
wallet: allow mintxfee=0
delta1 May 22, 2024
aef3f5a
Squashed 'src/simplicity/' changes from b549192109..6d503ea4f8
roconnor-blockstream Jun 24, 2025
f41af64
Merge commit 'aef3f5a7e581883e18df6793eb6dbc8286aeb8dc' into simplicity
roconnor-blockstream Jun 24, 2025
0a0a69f
Update Simplicity integeration
roconnor-blockstream Jun 18, 2025
b379bb2
Merge pull request #1459 from ElementsProject/simplicity
delta1 Jul 17, 2025
e8e1952
Zero fee transactions without fee output
Jul 22, 2025
cd1b94e
Merge remote-tracking branch 'origin/master' into mintxfee
Jul 22, 2025
ef7525a
re-enable zero fee check
Jul 22, 2025
ddda11c
Unconditionally accept Simplicity spends in the mempool
roconnor-blockstream Jul 23, 2025
ab5777e
test: minor improvements for send_zero_fee
delta1 Jul 25, 2025
c1a4713
prevent reused utxo
Jul 28, 2025
3524ec0
Merge pull request #1480 from tomt1664/fix/mempool_unbroadcast_test
delta1 Jul 30, 2025
2eb5b08
Enable sending of different assets to the same address (#1479)
tomt1664 Jul 30, 2025
6e2d879
Merge pull request #1333 from delta1/mintxfee
delta1 Jul 31, 2025
fcaa080
update macos ci install
Aug 4, 2025
b1749fb
Merge pull request #1482 from tomt1664/fix/macos_ci_pip_install
delta1 Aug 5, 2025
da9d7c1
fix feature_pak test
Jul 30, 2025
f49f0a2
Merge pull request #1481 from tomt1664/fix/feature_pak_test
delta1 Aug 5, 2025
7cb85f1
Merge pull request #1477 from ElementsProject/simplicity
psgreco Aug 6, 2025
7532092
fix intermittent functional test failures
Aug 8, 2025
992147b
Merge pull request #1483 from tomt1664/fix/functional_sync
delta1 Aug 11, 2025
9f1cc94
Fix: address error messages and test (#1486)
tomt1664 Aug 25, 2025
e145690
apply mandatory coinbase only to policyAsset (#1488)
tomt1664 Sep 19, 2025
93c84a9
fix: unblinded re/issuance for non-policy asset greater than 21 milli…
delta1 Sep 23, 2025
a937d53
moved acceptunlimitedissuances to chainparams and set defaults
Sep 26, 2025
cc7aee3
Merge pull request #1492 from tomt1664/unlimited_issuance_defaults
psgreco Sep 29, 2025
2dd017d
added unlimitedissuance config option for CLiquidV1TestParams
Sep 30, 2025
6150a74
Merge pull request #1493 from tomt1664/unlimitedissuances_chainparams
psgreco Sep 30, 2025
16799ae
Remove 'pops a' duplication
Nazarevsky Oct 2, 2025
af1463a
Merge pull request #1494 from Nazarevsky/fix/tapscript-opcodes-word-r…
delta1 Oct 2, 2025
afb63a4
Merge branch 'master' into elem-23.3.1-rc2
psgreco Oct 7, 2025
ec67e56
Bump version to 23.3.1-rc2
psgreco Oct 7, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions build_msvc/libelementssimplicity/libelementssimplicity.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
</PropertyGroup>
<ItemGroup>
<ClCompile Include="..\..\src\simplicity\bitstream.c" />
<ClCompile Include="..\..\src\simplicity\cmr.c" />
<ClCompile Include="..\..\src\simplicity\dag.c" />
<ClCompile Include="..\..\src\simplicity\deserialize.c" />
<ClCompile Include="..\..\src\simplicity\eval.c" />
Expand All @@ -20,11 +19,13 @@
<ClCompile Include="..\..\src\simplicity\sha256.c" />
<ClCompile Include="..\..\src\simplicity\type.c" />
<ClCompile Include="..\..\src\simplicity\typeInference.c" />
<ClCompile Include="..\..\src\simplicity\primitive\elements\env.c" />
<ClCompile Include="..\..\src\simplicity\primitive\elements\exec.c" />
<ClCompile Include="..\..\src\simplicity\primitive\elements\elementsJets.c" />
<ClCompile Include="..\..\src\simplicity\primitive\elements\ops.c" />
<ClCompile Include="..\..\src\simplicity\primitive\elements\primitive.c" />
<ClCompile Include="..\..\src\simplicity\elements\cmr.c" />
<ClCompile Include="..\..\src\simplicity\elements\env.c" />
<ClCompile Include="..\..\src\simplicity\elements\exec.c" />
<ClCompile Include="..\..\src\simplicity\elements\elementsJets.c" />
<ClCompile Include="..\..\src\simplicity\elements\ops.c" />
<ClCompile Include="..\..\src\simplicity\elements\primitive.c" />
<ClCompile Include="..\..\src\simplicity\elements\txEnv.c" />
</ItemGroup>
<ItemDefinitionGroup>
<ClCompile>
Expand Down
2 changes: 1 addition & 1 deletion ci/test/04_install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ if [[ $QEMU_USER_CMD == qemu-s390* ]]; then
fi

if [ "$CI_OS_NAME" == "macos" ]; then
sudo -H pip3 install --upgrade --break-system-packages pip
sudo -H pip3 install --upgrade --break-system-packages --ignore-installed pip
# shellcheck disable=SC2086
IN_GETOPT_BIN="$(brew --prefix gnu-getopt)/bin/getopt" ${CI_RETRY_EXE} pip3 install --user $PIP_PACKAGES
fi
Expand Down
2 changes: 1 addition & 1 deletion configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ AC_PREREQ([2.69])
define(_CLIENT_VERSION_MAJOR, 23)
define(_CLIENT_VERSION_MINOR, 3)
define(_CLIENT_VERSION_BUILD, 1)
define(_CLIENT_VERSION_RC, 1)
define(_CLIENT_VERSION_RC, 2)
define(_CLIENT_VERSION_IS_RELEASE, true)
define(_COPYRIGHT_YEAR, 2025)
define(_COPYRIGHT_HOLDERS,[The %s developers])
Expand Down
2 changes: 1 addition & 1 deletion doc/tapscript_opcodes.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ Taproot already increases a lot of resource limitations from segwitv0, so there
1. **Streaming Opcodes for streaming hashes**: There is an existing limitation of `MAX_SCRIPT_ELEMENT_SIZE`(520 bytes) because of which we cannot operate hash functions like `OP_SHA256` on messages more than 520 bytes. This allows hashing on more than 520 bytes while still preserving the existing security against resource exhaustion attacks. The proposal for this by Russell O'Connor can be found in the description [here](https://github.com/ElementsProject/elements/pull/817).
1. Define `OP_SUCCESS196` as `OP_SHA256INITIALIZE` which pops a bytestring and push SHA256 context creating by adding the bytestring to the initial SHA256 context.
1. Define `OP_SUCCESS197` as `OP_SHA256UPDATE` which first pops a bytestring followed by another pop for SHA256 context and pushes an updated context by adding the bytestring to the data stream being hashed.
1. Define `OP_SUCCESS198` as `OP_SHA256FINALIZE` which first pops a pops a bytestring followed by another pop for SHA256 context and finally pushes a SHA256 hash value after adding the bytestring and completing the padding.
1. Define `OP_SUCCESS198` as `OP_SHA256FINALIZE` which first pops a bytestring followed by another pop for SHA256 context and finally pushes a SHA256 hash value after adding the bytestring and completing the padding.


2. **Transaction Introspection codes**: Transaction introspection is already possible in elements script by use of `OP_CHECKSIGFROMSTACKVERIFY`, however the current solutions are really expensive in applications like [covenants](https://github.com/sanket1729/covenants-demo). Therefore, we are not adding any new functionality by supporting introspection, only making it easier to use. The warning still remains the same as with covenants, if the user is inspecting data from parts of the transaction that are not signed, the script can cause unexpected behavior.
Expand Down
10 changes: 10 additions & 0 deletions src/chainparams.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,7 @@ class CMainParams : public CChainParams {
consensus.connect_genesis_outputs = false;
consensus.subsidy_asset = CAsset();
anyonecanspend_aremine = false;
accept_unlimited_issuances = false;
enforce_pak = false;
multi_data_permitted = false;
accept_discount_ct = false;
Expand Down Expand Up @@ -374,6 +375,7 @@ class CTestNetParams : public CChainParams {
consensus.subsidy_asset = CAsset();
anyonecanspend_aremine = false;
enforce_pak = false;
accept_unlimited_issuances = false;
multi_data_permitted = false;
accept_discount_ct = false;
create_discount_ct = false;
Expand Down Expand Up @@ -538,6 +540,7 @@ class SigNetParams : public CChainParams {
consensus.subsidy_asset = CAsset();
anyonecanspend_aremine = false;
enforce_pak = false;
accept_unlimited_issuances = false;
multi_data_permitted = false;
accept_discount_ct = false;
create_discount_ct = false;
Expand Down Expand Up @@ -641,6 +644,7 @@ class CRegTestParams : public CChainParams {
consensus.subsidy_asset = CAsset();
anyonecanspend_aremine = false;
enforce_pak = false;
accept_unlimited_issuances = false;
multi_data_permitted = false;
accept_discount_ct = false;
create_discount_ct = false;
Expand Down Expand Up @@ -909,6 +913,8 @@ class CCustomParams : public CRegTestParams {

enforce_pak = args.GetBoolArg("-enforce_pak", false);

accept_unlimited_issuances = args.GetBoolArg("-acceptunlimitedissuances", accept_unlimited_issuances);

// Allow multiple op_return outputs by relay policy
multi_data_permitted = args.GetBoolArg("-multi_data_permitted", enforce_pak);

Expand Down Expand Up @@ -1167,6 +1173,8 @@ class CLiquidV1Params : public CChainParams {

enforce_pak = true;

accept_unlimited_issuances = false;

multi_data_permitted = true;
create_discount_ct = args.GetBoolArg("-creatediscountct", false);
accept_discount_ct = args.GetBoolArg("-acceptdiscountct", true) || create_discount_ct;
Expand Down Expand Up @@ -1525,6 +1533,8 @@ class CLiquidV1TestParams : public CLiquidV1Params {

enforce_pak = args.GetBoolArg("-enforce_pak", enforce_pak);

accept_unlimited_issuances = args.GetBoolArg("-acceptunlimitedissuances", accept_unlimited_issuances);

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;
Expand Down
2 changes: 2 additions & 0 deletions src/chainparams.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ class CChainParams
const std::string& ParentBech32HRP() const { return parent_bech32_hrp; }
const std::string& ParentBlech32HRP() const { return parent_blech32_hrp; }
bool GetEnforcePak() const { return enforce_pak; }
bool GetAcceptUnlimitedIssuances() const { return accept_unlimited_issuances; }
bool GetMultiDataPermitted() const { return multi_data_permitted; }
bool GetAcceptDiscountCT() const { return accept_discount_ct; }
bool GetCreateDiscountCT() const { return create_discount_ct; }
Expand Down Expand Up @@ -168,6 +169,7 @@ class CChainParams
std::string parent_bech32_hrp;
std::string parent_blech32_hrp;
bool enforce_pak;
bool accept_unlimited_issuances;
bool multi_data_permitted;
bool accept_discount_ct;
bool create_discount_ct;
Expand Down
1 change: 1 addition & 0 deletions src/chainparamsbase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ void SetupChainParamsBaseOptions(ArgsManager& argsman)
argsman.AddArg("-total_valid_epochs", "Per-chain parameter that sets how long a particular fedpegscript is in effect for.", ArgsManager::ALLOW_ANY, OptionsCategory::ELEMENTS);
argsman.AddArg("-evbparams=deployment:start:end:period:threshold", "Use given start/end times for specified version bits deployment (regtest or custom only)", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::ELEMENTS);
argsman.AddArg("-con_start_p2wsh_script", "Create p2wsh addresses when starting in dynafed mode (regtest or custom only)", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::ELEMENTS);
argsman.AddArg("-acceptunlimitedissuances", "Allow unblinded issuance amounts to exceed 21 million units", ArgsManager::ALLOW_ANY, OptionsCategory::ELEMENTS);
// END ELEMENTS
//
}
Expand Down
7 changes: 4 additions & 3 deletions src/confidential_validation.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@

#include <chainparams.h>
#include <confidential_validation.h>
#include <issuance.h>
#include <pegins.h>
Expand Down Expand Up @@ -30,8 +31,9 @@ bool HasValidFee(const CTransaction& tx) {
CAmount fee = 0;
if (tx.vout[i].IsFee()) {
fee = tx.vout[i].nValue.GetAmount();
if (fee == 0 || !MoneyRange(fee))
if (fee == 0 || !MoneyRange(fee)) {
return false;
}
totalFee[tx.vout[i].nAsset.GetAsset()] += fee;
if (!MoneyRange(totalFee)) {
return false;
Expand Down Expand Up @@ -102,14 +104,13 @@ static bool VerifyIssuanceAmount(secp256k1_pedersen_commitment& value_commit, se

// Build value commitment
if (value.IsExplicit()) {
if (!MoneyRange(value.GetAmount()) || value.GetAmount() == 0) {
if ((asset == Params().GetConsensus().pegged_asset && !MoneyRange(value.GetAmount())) || value.GetAmount() <= 0) {
return false;
}
if (!rangeproof.empty()) {
return false;
}


ret = secp256k1_pedersen_commit(secp256k1_ctx_verify_amounts, &value_commit, explicit_blinds, value.GetAmount(), &asset_gen);
// The explicit_blinds are all 0, and the amount is not 0. So secp256k1_pedersen_commit does not fail.
assert(ret == 1);
Expand Down
13 changes: 8 additions & 5 deletions src/key_io.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,11 +152,14 @@ CTxDestination DecodeDestination(const std::string& str, const CChainParams& par
uint160 hash;
error_str = "";

bool is_bech32 = !(bech32::Decode(str).encoding == bech32::Encoding::INVALID);
bool is_blech32 = !(blech32::Decode(str).encoding == blech32::Encoding::INVALID);

// Note this will be false if it is a valid Bech32 address for a different network
bool is_bech32 = (ToLower(str.substr(0, params.Bech32HRP().size())) == params.Bech32HRP());
bool is_blech32 = (ToLower(str.substr(0, params.Blech32HRP().size())) == params.Blech32HRP());
bool is_bech32_hrp = (ToLower(str.substr(0, params.Bech32HRP().size())) == params.Bech32HRP());
bool is_blech32_hrp = (ToLower(str.substr(0, params.Blech32HRP().size())) == params.Blech32HRP());

if (!is_bech32 && !is_blech32 && DecodeBase58Check(str, data, 55)) {
if (!is_bech32 && !is_blech32 && !is_bech32_hrp && !is_blech32_hrp && DecodeBase58Check(str, data, 55)) {
// base58-encoded Bitcoin addresses.
// Public-key-hash-addresses have version 0 (or 111 testnet).
// The data vector contains RIPEMD160(SHA256(pubkey)), where pubkey is the serialized public key.
Expand Down Expand Up @@ -206,14 +209,14 @@ CTxDestination DecodeDestination(const std::string& str, const CChainParams& par
error_str = "Invalid prefix for Base58-encoded address";
}
return CNoDestination();
} else if (!is_bech32 && !is_blech32) {
} else if (!is_bech32 && !is_blech32 && !is_bech32_hrp && !is_blech32_hrp) {
// Try Base58 decoding without the checksum, using a much larger max length
if (!DecodeBase58(str, data, 100)) {
error_str = "Not a valid Bech32 or Base58 encoding";
} else {
error_str = "Invalid checksum or length of Base58 address";
}
// return CNoDestination(); // ELEMENTS: FIXME
return CNoDestination();
}

data.clear();
Expand Down
14 changes: 14 additions & 0 deletions src/policy/policy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,20 @@ bool IsWitnessStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
return true;
}

bool IsIssuanceInMoneyRange(const CTransaction& tx)
{
for (size_t i = 0; i < tx.vin.size(); ++i) {
const CAssetIssuance& issuance = tx.vin[i].assetIssuance;
if (issuance.IsNull()) {
continue;
}
if (issuance.nAmount.IsExplicit() && !MoneyRange(issuance.nAmount.GetAmount())) {
return false;
}
}
return true;
}

int64_t GetVirtualTransactionSize(int64_t nWeight, int64_t nSigOpCost, unsigned int bytes_per_sigop)
{
return (std::max(nWeight, nSigOpCost * bytes_per_sigop) + WITNESS_SCALE_FACTOR - 1) / WITNESS_SCALE_FACTOR;
Expand Down
12 changes: 11 additions & 1 deletion src/policy/policy.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,9 @@ static constexpr unsigned int STANDARD_SCRIPT_VERIFY_FLAGS = MANDATORY_SCRIPT_VE
SCRIPT_VERIFY_TAPROOT |
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_TAPROOT_VERSION |
SCRIPT_VERIFY_DISCOURAGE_OP_SUCCESS |
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_PUBKEYTYPE;
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_PUBKEYTYPE |
SCRIPT_VERIFY_SIMPLICITY;


/** For convenience, standard but not mandatory verify flags. */
static constexpr unsigned int STANDARD_NOT_MANDATORY_VERIFY_FLAGS = STANDARD_SCRIPT_VERIFY_FLAGS & ~MANDATORY_SCRIPT_VERIFY_FLAGS;
Expand All @@ -92,6 +94,9 @@ static constexpr unsigned int STANDARD_LOCKTIME_VERIFY_FLAGS = LOCKTIME_VERIFY_S
// ELEMENTS: keep a copy of the upstream default dust relay fee rate
static const unsigned int DUST_RELAY_TX_FEE_BITCOIN = 3000;

// ELEMENTS: allow unblinded issuances/reissuances greater than MAX_MONEY
static const bool DEFAULT_ACCEPT_UNLIMITED_ISSUANCES = true;

CAmount GetDustThreshold(const CTxOut& txout, const CFeeRate& dustRelayFee);

bool IsDust(const CTxOut& txout, const CFeeRate& dustRelayFee);
Expand Down Expand Up @@ -124,6 +129,11 @@ bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
*/
bool IsWitnessStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs);

/* ELEMENTS
* Check if unblinded issuance/reissuance is in MoneyRange
*/
bool IsIssuanceInMoneyRange(const CTransaction& tx);

/** Compute the virtual transaction size (weight reinterpreted as bytes). */
int64_t GetVirtualTransactionSize(int64_t nWeight, int64_t nSigOpCost, unsigned int bytes_per_sigop);
int64_t GetVirtualTransactionSize(const CTransaction& tx, int64_t nSigOpCost, unsigned int bytes_per_sigop);
Expand Down
16 changes: 10 additions & 6 deletions src/rpc/rawtransaction_util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ CMutableTransaction ConstructTransaction(const UniValue& inputs_in, const UniVal
CTxOut fee_out;

// Duplicate checking
std::set<CTxDestination> destinations;
std::set<std::pair<CTxDestination,CAsset>> destinations;
bool has_data{false};

std::vector<PSBTOutput> psbt_outs;
Expand All @@ -297,6 +297,8 @@ CMutableTransaction ConstructTransaction(const UniValue& inputs_in, const UniVal
CTxOut out(::policyAsset, 0, CScript());

bool is_fee = false;
CTxDestination destination;
std::string dest;
for (const std::string& name_ : output.getKeys()) {
if (name_ == "data") {
if (has_data) {
Expand Down Expand Up @@ -337,14 +339,11 @@ CMutableTransaction ConstructTransaction(const UniValue& inputs_in, const UniVal
// For PSET
psbt_out.m_blinder_index = find_value(output, name_).get_int();
} else {
CTxDestination destination = DecodeDestination(name_);
destination = DecodeDestination(name_);
if (!IsValidDestination(destination)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Bitcoin address: ") + name_);
}

if (!destinations.insert(destination).second) {
throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, duplicated address: ") + name_);
}
dest = name_;

CScript scriptPubKey = GetScriptForDestination(destination);
CAmount nAmount = AmountFromValue(output[name_]);
Expand All @@ -362,6 +361,11 @@ CMutableTransaction ConstructTransaction(const UniValue& inputs_in, const UniVal
psbt_out.m_blinding_pubkey = blind_pub;
}
}

if (!destinations.emplace(destination, out.nAsset.GetAsset()).second) {
throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, duplicated address and asset: " + dest + " " + out.nAsset.GetHex()));
}

if (is_fee) {
fee_out = out;
} else {
Expand Down
Loading