Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
19 changes: 19 additions & 0 deletions cmake/module/ProcessConfigurations.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,23 @@ function(remove_cxx_flag_from_all_configs flag)
endforeach()
endfunction()

function(remove_c_flag_from_all_configs flag)
get_all_configs(all_configs)
foreach(config IN LISTS all_configs)
string(TOUPPER "${config}" config_uppercase)
set(flags "${CMAKE_C_FLAGS_${config_uppercase}}")
separate_arguments(flags)
list(FILTER flags EXCLUDE REGEX "${flag}")
list(JOIN flags " " new_flags)
set(CMAKE_C_FLAGS_${config_uppercase} "${new_flags}" PARENT_SCOPE)
set(CMAKE_C_FLAGS_${config_uppercase} "${new_flags}"
CACHE STRING
"Flags used by the C compiler during ${config_uppercase} builds."
FORCE
)
endforeach()
endfunction()

function(replace_cxx_flag_in_config config old_flag new_flag)
string(TOUPPER "CMAKE_CXX_FLAGS_${config}" var_name)
if("${var_name}" IN_LIST precious_variables)
Expand All @@ -121,8 +138,10 @@ include(TryAppendCXXFlags)
# We leave assertions on.
if(MSVC)
remove_cxx_flag_from_all_configs(/DNDEBUG)
remove_c_flag_from_all_configs(/DNDEBUG)
else()
remove_cxx_flag_from_all_configs(-DNDEBUG)
remove_c_flag_from_all_configs(-DNDEBUG)

# Adjust flags used by the CXX compiler during RELEASE builds.
# Prefer -O2 optimization level. (-O3 is CMake's default for Release for many compilers.)
Expand Down
2 changes: 2 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ include(../cmake/crc32c.cmake)
include(../cmake/leveldb.cmake)
include(../cmake/minisketch.cmake)
add_subdirectory(univalue)
add_subdirectory(simplicity)
if (ENABLE_IPC AND NOT WITH_EXTERNAL_LIBMULTIPROCESS)
include(../cmake/libmultiprocess.cmake)
add_libmultiprocess(ipc/libmultiprocess)
Expand Down Expand Up @@ -76,6 +77,7 @@ target_link_libraries(bitcoin_consensus
core_interface
bitcoin_crypto
secp256k1
BitcoinSimplicity
)

if(WITH_ZMQ)
Expand Down
1 change: 1 addition & 0 deletions src/consensus/params.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ constexpr bool ValidDeployment(BuriedDeployment dep) { return dep <= DEPLOYMENT_
enum DeploymentPos : uint16_t {
DEPLOYMENT_TESTDUMMY,
DEPLOYMENT_TAPROOT, // Deployment of Schnorr/Taproot (BIPs 340-342)
DEPLOYMENT_SIMPLICITY, // Deployment of Simplicity
// NOTE: Also add new deployments to VersionBitsDeploymentInfo in deploymentinfo.cpp
MAX_VERSION_BITS_DEPLOYMENTS
};
Expand Down
4 changes: 4 additions & 0 deletions src/deploymentinfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ const std::array<VBDeploymentInfo,Consensus::MAX_VERSION_BITS_DEPLOYMENTS> Versi
.name = "taproot",
.gbt_optional_rule = true,
},
VBDeploymentInfo{
.name = "simplicity",
.gbt_optional_rule = true,
},
};

std::string DeploymentName(Consensus::BuriedDeployment dep)
Expand Down
1 change: 1 addition & 0 deletions src/kernel/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ target_link_libraries(bitcoinkernel
PRIVATE
core_interface
secp256k1_objs
BitcoinSimplicity
$<$<PLATFORM_ID:Windows>:bcrypt>
$<TARGET_NAME_IF_EXISTS:USDT::headers>
PUBLIC
Expand Down
35 changes: 35 additions & 0 deletions src/kernel/chainparams.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,13 @@ class CMainParams : public CChainParams {
consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].threshold = 1815; // 90%
consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].period = 2016;

consensus.vDeployments[Consensus::DEPLOYMENT_SIMPLICITY].bit = 24;
consensus.vDeployments[Consensus::DEPLOYMENT_SIMPLICITY].nStartTime = Consensus::BIP9Deployment::NEVER_ACTIVE;
consensus.vDeployments[Consensus::DEPLOYMENT_SIMPLICITY].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT;
consensus.vDeployments[Consensus::DEPLOYMENT_SIMPLICITY].min_activation_height = 0; // No activation delay
consensus.vDeployments[Consensus::DEPLOYMENT_SIMPLICITY].threshold = 1815; // 90%
consensus.vDeployments[Consensus::DEPLOYMENT_SIMPLICITY].period = 2016;

consensus.nMinimumChainWork = uint256{"0000000000000000000000000000000000000000dee8e2a309ad8a9820433c68"};
consensus.defaultAssumeValid = uint256{"00000000000000000000611fd22f2df7c8fbd0688745c3a6c3bb5109cc2a12cb"}; // 912683

Expand Down Expand Up @@ -243,6 +250,13 @@ class CTestNetParams : public CChainParams {
consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].threshold = 1512; // 75%
consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].period = 2016;

consensus.vDeployments[Consensus::DEPLOYMENT_SIMPLICITY].bit = 24;
consensus.vDeployments[Consensus::DEPLOYMENT_SIMPLICITY].nStartTime = Consensus::BIP9Deployment::NEVER_ACTIVE;
consensus.vDeployments[Consensus::DEPLOYMENT_SIMPLICITY].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT;
consensus.vDeployments[Consensus::DEPLOYMENT_SIMPLICITY].min_activation_height = 0; // No activation delay
consensus.vDeployments[Consensus::DEPLOYMENT_SIMPLICITY].threshold = 1815; // 90%
consensus.vDeployments[Consensus::DEPLOYMENT_SIMPLICITY].period = 2016;

consensus.nMinimumChainWork = uint256{"0000000000000000000000000000000000000000000016dd270dd94fac1d7632"};
consensus.defaultAssumeValid = uint256{"0000000000000065c6c38258e201971a3fdfcc2ceee0dd6e85a6c022d45dee34"}; // 4550000

Expand Down Expand Up @@ -345,6 +359,13 @@ class CTestNet4Params : public CChainParams {
consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].threshold = 1512; // 75%
consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].period = 2016;

consensus.vDeployments[Consensus::DEPLOYMENT_SIMPLICITY].bit = 24;
consensus.vDeployments[Consensus::DEPLOYMENT_SIMPLICITY].nStartTime = Consensus::BIP9Deployment::NEVER_ACTIVE;
consensus.vDeployments[Consensus::DEPLOYMENT_SIMPLICITY].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT;
consensus.vDeployments[Consensus::DEPLOYMENT_SIMPLICITY].min_activation_height = 0; // No activation delay
consensus.vDeployments[Consensus::DEPLOYMENT_SIMPLICITY].threshold = 1815; // 90%
consensus.vDeployments[Consensus::DEPLOYMENT_SIMPLICITY].period = 2016;

consensus.nMinimumChainWork = uint256{"00000000000000000000000000000000000000000000034a4690fe592dc49c7c"};
consensus.defaultAssumeValid = uint256{"000000000000000180a58e7fa3b0db84b5ea76377524894f53660d93ac839d9b"}; // 91000

Expand Down Expand Up @@ -490,6 +511,13 @@ class SigNetParams : public CChainParams {
consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].threshold = 1815; // 90%
consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].period = 2016;

consensus.vDeployments[Consensus::DEPLOYMENT_SIMPLICITY].bit = 24;
consensus.vDeployments[Consensus::DEPLOYMENT_SIMPLICITY].nStartTime = Consensus::BIP9Deployment::NEVER_ACTIVE;
consensus.vDeployments[Consensus::DEPLOYMENT_SIMPLICITY].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT;
consensus.vDeployments[Consensus::DEPLOYMENT_SIMPLICITY].min_activation_height = 0; // No activation delay
consensus.vDeployments[Consensus::DEPLOYMENT_SIMPLICITY].threshold = 1815; // 90%
consensus.vDeployments[Consensus::DEPLOYMENT_SIMPLICITY].period = 2016;

// message start is defined as the first 4 bytes of the sha256d of the block script
HashWriter h{};
h << consensus.signet_challenge;
Expand Down Expand Up @@ -573,6 +601,13 @@ class CRegTestParams : public CChainParams
consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].threshold = 108; // 75%
consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].period = 144;

consensus.vDeployments[Consensus::DEPLOYMENT_SIMPLICITY].bit = 24;
consensus.vDeployments[Consensus::DEPLOYMENT_SIMPLICITY].nStartTime = Consensus::BIP9Deployment::ALWAYS_ACTIVE;
consensus.vDeployments[Consensus::DEPLOYMENT_SIMPLICITY].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT;
consensus.vDeployments[Consensus::DEPLOYMENT_SIMPLICITY].min_activation_height = 0; // No activation delay
consensus.vDeployments[Consensus::DEPLOYMENT_SIMPLICITY].threshold = 1815; // 90%
consensus.vDeployments[Consensus::DEPLOYMENT_SIMPLICITY].period = 2016;

consensus.nMinimumChainWork = uint256{};
consensus.defaultAssumeValid = uint256{};

Expand Down
1 change: 1 addition & 0 deletions src/policy/policy.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ static constexpr script_verify_flags STANDARD_SCRIPT_VERIFY_FLAGS{MANDATORY_SCRI
SCRIPT_VERIFY_CONST_SCRIPTCODE |
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_TAPROOT_VERSION |
SCRIPT_VERIFY_DISCOURAGE_OP_SUCCESS |
SCRIPT_VERIFY_SIMPLICITY |
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_PUBKEYTYPE};

/** For convenience, standard but not mandatory verify flags. */
Expand Down
130 changes: 130 additions & 0 deletions src/script/interpreter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@
#include <script/script.h>
#include <tinyformat.h>
#include <uint256.h>
extern "C" {
#include <simplicity/bitcoin/env.h>
#include <simplicity/bitcoin/exec.h>
#include <simplicity/errorCodes.h>
}

typedef std::vector<unsigned char> valtype;

Expand Down Expand Up @@ -1399,6 +1404,10 @@ uint256 GetSpentScriptsSHA256(const std::vector<CTxOut>& outputs_spent)

} // namespace

void SimplicityTransactionDeleter::operator()(bitcoinTransaction* ptr) const {
simplicity_bitcoin_freeTransaction(ptr);
}

template <class T>
void PrecomputedTransactionData::Init(const T& txTo, std::vector<CTxOut>&& spent_outputs, bool force)
{
Expand Down Expand Up @@ -1447,6 +1456,44 @@ void PrecomputedTransactionData::Init(const T& txTo, std::vector<CTxOut>&& spent
if (uses_bip341_taproot && m_spent_outputs_ready) {
m_spent_amounts_single_hash = GetSpentAmountsSHA256(m_spent_outputs);
m_spent_scripts_single_hash = GetSpentScriptsSHA256(m_spent_outputs);

std::vector<rawBitcoinBuffer> simplicityRawAnnex(txTo.vin.size());
std::vector<rawBitcoinInput> simplicityRawInput(txTo.vin.size());
for (size_t i = 0; i < txTo.vin.size(); ++i) {
simplicityRawInput[i].prevTxid = txTo.vin[i].prevout.hash.ToUint256().data();
simplicityRawInput[i].prevIx = txTo.vin[i].prevout.n;
simplicityRawInput[i].sequence = txTo.vin[i].nSequence;
simplicityRawInput[i].txo.value = m_spent_outputs[i].nValue;
simplicityRawInput[i].txo.scriptPubKey.buf = m_spent_outputs[i].scriptPubKey.data();
simplicityRawInput[i].txo.scriptPubKey.len = m_spent_outputs[i].scriptPubKey.size();
simplicityRawInput[i].annex = NULL;
std::span<const valtype> stack{txTo.vin[i].scriptWitness.stack};
if (stack.size() >= 2 && !stack.back().empty() && stack.back()[0] == ANNEX_TAG) {
simplicityRawAnnex[i].buf = stack.back().data()+1;
simplicityRawAnnex[i].len = stack.back().size()-1;
simplicityRawInput[i].annex = &simplicityRawAnnex[i];
}
}

std::vector<rawBitcoinOutput> simplicityRawOutput(txTo.vout.size());
for (size_t i = 0; i < txTo.vout.size(); ++i) {
simplicityRawOutput[i].value = txTo.vout[i].nValue;
simplicityRawOutput[i].scriptPubKey.buf = txTo.vout[i].scriptPubKey.data();
simplicityRawOutput[i].scriptPubKey.len = txTo.vout[i].scriptPubKey.size();
}

rawBitcoinTransaction simplicityRawTx;
uint256 rawHash = txTo.GetHash().ToUint256();
simplicityRawTx.txid = rawHash.begin();
simplicityRawTx.input = simplicityRawInput.data();
simplicityRawTx.numInputs = simplicityRawInput.size();
simplicityRawTx.output = simplicityRawOutput.data();
simplicityRawTx.numOutputs = simplicityRawOutput.size();
simplicityRawTx.version = txTo.version;
simplicityRawTx.lockTime = txTo.nLockTime;

m_simplicity_tx_data = SimplicityTransactionUniquePtr(simplicity_bitcoin_mallocTransaction(&simplicityRawTx));

m_bip341_taproot_ready = true;
}
}
Expand Down Expand Up @@ -1825,6 +1872,52 @@ bool GenericTransactionSignatureChecker<T>::CheckSequence(const CScriptNum& nSeq
return true;
}

template <class T>
bool GenericTransactionSignatureChecker<T>::CheckSimplicity(const valtype& program, const valtype& witness, const rawBitcoinTapEnv& simplicityRawTap, int64_t minCost, int64_t budget, ScriptError* serror) const
{
simplicity_err error;
bitcoinTapEnv* simplicityTapEnv = simplicity_bitcoin_mallocTapEnv(&simplicityRawTap);

assert(txdata->m_simplicity_tx_data);
assert(simplicityTapEnv);
if (!simplicity_bitcoin_execSimplicity(&error, 0, txdata->m_simplicity_tx_data.get(), nIn, simplicityTapEnv, minCost, budget, 0, program.data(), program.size(), witness.data(), witness.size())) {
assert(!"simplicity_elements_execSimplicity internal error");
}
simplicity_bitcoin_freeTapEnv(simplicityTapEnv);
switch (error) {
case SIMPLICITY_NO_ERROR: return set_success(serror);
case SIMPLICITY_ERR_MALLOC:
case SIMPLICITY_ERR_NOT_YET_IMPLEMENTED:
assert(!"simplicity_elements_execSimplicity internal error");
break;
case SIMPLICITY_ERR_DATA_OUT_OF_RANGE: return set_error(serror, SCRIPT_ERR_SIMPLICITY_DATA_OUT_OF_RANGE);
case SIMPLICITY_ERR_DATA_OUT_OF_ORDER: return set_error(serror, SCRIPT_ERR_SIMPLICITY_DATA_OUT_OF_ORDER);
case SIMPLICITY_ERR_FAIL_CODE: return set_error(serror, SCRIPT_ERR_SIMPLICITY_FAIL_CODE);
case SIMPLICITY_ERR_RESERVED_CODE: return set_error(serror, SCRIPT_ERR_SIMPLICITY_RESERVED_CODE);
case SIMPLICITY_ERR_HIDDEN: return set_error(serror, SCRIPT_ERR_SIMPLICITY_HIDDEN);
case SIMPLICITY_ERR_BITSTREAM_EOF: return set_error(serror, SCRIPT_ERR_SIMPLICITY_BITSTREAM_EOF);
case SIMPLICITY_ERR_BITSTREAM_TRAILING_BYTES: return set_error(serror, SCRIPT_ERR_SIMPLICITY_BITSTREAM_TRAILING_BYTES);
case SIMPLICITY_ERR_BITSTREAM_ILLEGAL_PADDING: return set_error(serror, SCRIPT_ERR_SIMPLICITY_BITSTREAM_ILLEGAL_PADDING);
case SIMPLICITY_ERR_TYPE_INFERENCE_UNIFICATION: return set_error(serror, SCRIPT_ERR_SIMPLICITY_TYPE_INFERENCE_UNIFICATION);
case SIMPLICITY_ERR_TYPE_INFERENCE_OCCURS_CHECK: return set_error(serror, SCRIPT_ERR_SIMPLICITY_TYPE_INFERENCE_OCCURS_CHECK);
case SIMPLICITY_ERR_TYPE_INFERENCE_NOT_PROGRAM: return set_error(serror, SCRIPT_ERR_SIMPLICITY_TYPE_INFERENCE_NOT_PROGRAM);
case SIMPLICITY_ERR_WITNESS_EOF: return set_error(serror, SCRIPT_ERR_SIMPLICITY_WITNESS_EOF);
case SIMPLICITY_ERR_WITNESS_TRAILING_BYTES: return set_error(serror, SCRIPT_ERR_SIMPLICITY_WITNESS_TRAILING_BYTES);
case SIMPLICITY_ERR_WITNESS_ILLEGAL_PADDING: return set_error(serror, SCRIPT_ERR_SIMPLICITY_WITNESS_ILLEGAL_PADDING);
case SIMPLICITY_ERR_UNSHARED_SUBEXPRESSION: return set_error(serror, SCRIPT_ERR_SIMPLICITY_UNSHARED_SUBEXPRESSION);
case SIMPLICITY_ERR_CMR: return set_error(serror, SCRIPT_ERR_SIMPLICITY_CMR);
case SIMPLICITY_ERR_EXEC_BUDGET: return set_error(serror, SCRIPT_ERR_SIMPLICITY_EXEC_BUDGET);
case SIMPLICITY_ERR_EXEC_MEMORY: return set_error(serror, SCRIPT_ERR_SIMPLICITY_EXEC_MEMORY);
case SIMPLICITY_ERR_EXEC_JET: return set_error(serror, SCRIPT_ERR_SIMPLICITY_EXEC_JET);
case SIMPLICITY_ERR_EXEC_ASSERT: return set_error(serror, SCRIPT_ERR_SIMPLICITY_EXEC_ASSERT);
case SIMPLICITY_ERR_ANTIDOS: return set_error(serror, SCRIPT_ERR_SIMPLICITY_ANTIDOS);
case SIMPLICITY_ERR_HIDDEN_ROOT: return set_error(serror, SCRIPT_ERR_SIMPLICITY_HIDDEN_ROOT);
case SIMPLICITY_ERR_AMR: return set_error(serror, SCRIPT_ERR_SIMPLICITY_AMR);
case SIMPLICITY_ERR_OVERWEIGHT: return set_error(serror, SCRIPT_ERR_SIMPLICITY_OVERWEIGHT);
default: return set_error(serror, SCRIPT_ERR_UNKNOWN_ERROR);
}
}

// explicit instantiation
template class GenericTransactionSignatureChecker<CTransaction>;
template class GenericTransactionSignatureChecker<CMutableTransaction>;
Expand Down Expand Up @@ -1982,6 +2075,42 @@ static bool VerifyWitnessProgram(const CScriptWitness& witness, int witversion,
execdata.m_validation_weight_left_init = true;
return ExecuteWitnessScript(stack, exec_script, flags, SigVersion::TAPSCRIPT, checker, execdata, serror);
}
if ((flags & SCRIPT_VERIFY_SIMPLICITY) && (script.size() == 32) && (control[0] & TAPROOT_LEAF_MASK) == TAPROOT_LEAF_TAPSIMPLICITY) {
if (stack.size() < 2 || 3 < stack.size()) return set_error(serror, SCRIPT_ERR_SIMPLICITY_WRONG_LENGTH);
// Tapsimplicity (leaf version 0xbe)
const valtype& simplicity_program = SpanPopBack(stack);
const valtype& simplicity_witness = SpanPopBack(stack);
const int64_t budget = ::GetSerializeSize(witness.stack) + VALIDATION_WEIGHT_OFFSET;
int64_t minCost = 0;
rawBitcoinTapEnv simplicityRawTap;
simplicityRawTap.controlBlock = control.data();
simplicityRawTap.pathLen = (control.size() - TAPROOT_CONTROL_BASE_SIZE) / TAPROOT_CONTROL_NODE_SIZE;
simplicityRawTap.scriptCMR = script.data();
// If a padding stack item exists, we want to make sure it is minimal.
if (!stack.empty()) {
const valtype& padding = SpanPopBack(stack);
valtype zero_padding(padding.size());

// There should be no more stack items.
assert(stack.empty());

// Padding must be all zeros.
if (padding != zero_padding) {
return set_error(serror, SCRIPT_ERR_SIMPLICITY_PADDING_NONZERO);
}

// Compute what the budget would have been without the padding.
// budget includes the padding cost, so subtracting this stack item won't underflow.
minCost = budget - ::GetSerializeSize(padding);

if (!zero_padding.empty()) {
// Set the minCost to what the budget would have been if the padding were one byte smaller.
zero_padding.pop_back();
minCost += ::GetSerializeSize(zero_padding);
}
}
return checker.CheckSimplicity(simplicity_program, simplicity_witness, simplicityRawTap, minCost, budget, serror);
}
if (flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_TAPROOT_VERSION) {
return set_error(serror, SCRIPT_ERR_DISCOURAGE_UPGRADABLE_TAPROOT_VERSION);
}
Expand Down Expand Up @@ -2187,6 +2316,7 @@ const std::map<std::string, script_verify_flag_name>& ScriptFlagNamesToEnum()
FLAG_NAME(WITNESS_PUBKEYTYPE),
FLAG_NAME(CONST_SCRIPTCODE),
FLAG_NAME(TAPROOT),
FLAG_NAME(SIMPLICITY),
FLAG_NAME(DISCOURAGE_UPGRADABLE_PUBKEYTYPE),
FLAG_NAME(DISCOURAGE_OP_SUCCESS),
FLAG_NAME(DISCOURAGE_UPGRADABLE_TAPROOT_VERSION),
Expand Down
Loading
Loading