Skip to content

Commit

Permalink
bisecting...
Browse files Browse the repository at this point in the history
  • Loading branch information
luke-jr committed Jun 19, 2024
1 parent 4370482 commit b018c13
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 2 deletions.
5 changes: 3 additions & 2 deletions .cirrus.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,14 @@ env: # Global defaults

# https://cirrus-ci.org/guide/tips-and-tricks/#sharing-configuration-between-tasks
filter_template: &FILTER_TEMPLATE
skip: $CIRRUS_REPO_FULL_NAME == "bitcoin-core/gui" && $CIRRUS_PR == "" # No need to run on the read-only mirror, unless it is a PR. https://cirrus-ci.org/guide/writing-tasks/#conditional-task-execution
skip: true
stateful: false # https://cirrus-ci.org/guide/writing-tasks/#stateful-tasks

base_template: &BASE_TEMPLATE
<< : *FILTER_TEMPLATE
merge_base_script:
# Unconditionally install git (used in fingerprint_script).
- bash -c "$PACKAGE_MANAGER_INSTALL git"
- git --version || bash -c "$PACKAGE_MANAGER_INSTALL git"
- if [ "$CIRRUS_PR" = "" ]; then exit 0; fi
- git fetch --depth=1 $CIRRUS_REPO_CLONE_URL "pull/${CIRRUS_PR}/merge"
- git checkout FETCH_HEAD # Use merged changes to detect silent merge conflicts
Expand Down Expand Up @@ -181,6 +181,7 @@ task:
task:
name: 'multiprocess, i686, DEBUG'
<< : *GLOBAL_TASK_TEMPLATE
skip: false
persistent_worker:
labels:
type: medium
Expand Down
50 changes: 50 additions & 0 deletions src/script/script.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,56 @@ bool CScript::HasValidOps() const
return true;
}

std::pair<size_t, size_t> CScript::DatacarrierBytes() const
{
size_t counted{0};
opcodetype opcode, last_opcode{OP_INVALIDOPCODE};
std::vector<unsigned char> push_data;
unsigned int inside_noop{0}, inside_conditional{0};
CScript::const_iterator opcode_it = begin(), data_began = begin();
for (CScript::const_iterator it = begin(); it < end(); last_opcode = opcode) {
opcode_it = it;
if (!GetOp(it, opcode, push_data)) {
// Invalid scripts are necessarily all data
return {0, size()};
}

if (opcode == OP_IF || opcode == OP_NOTIF) {
++inside_conditional;
} else if (opcode == OP_ENDIF) {
if (!inside_conditional) return {0, size()}; // invalid
--inside_conditional;
} else if (opcode == OP_RETURN && !inside_conditional) {
// unconditional OP_RETURN is unspendable
return {size(), 0};
}

// Match OP_FALSE OP_IF
if (inside_noop) {
switch (opcode) {
case OP_IF: case OP_NOTIF:
++inside_noop;
break;
case OP_ENDIF:
if (0 == --inside_noop) {
counted += it - data_began + 1;
}
break;
default: /* do nothing */;
}
} else if (opcode == OP_IF && last_opcode == OP_FALSE) {
inside_noop = 1;
data_began = opcode_it;
// Match <data> OP_DROP
} else if (opcode <= OP_PUSHDATA4) {
data_began = opcode_it;
} else if (opcode == OP_DROP && last_opcode <= OP_PUSHDATA4) {
counted += it - data_began;
}
}
return {0, counted};
}

bool GetScriptOp(CScriptBase::const_iterator& pc, CScriptBase::const_iterator end, opcodetype& opcodeRet, std::vector<unsigned char>* pvchRet)
{
opcodeRet = OP_INVALIDOPCODE;
Expand Down
2 changes: 2 additions & 0 deletions src/script/script.h
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,8 @@ class CScript : public CScriptBase
return (size() > 0 && *begin() == OP_RETURN) || (size() > MAX_SCRIPT_SIZE);
}

std::pair<size_t, size_t> DatacarrierBytes() const;

void clear()
{
// The default prevector::clear() does not release memory
Expand Down
29 changes: 29 additions & 0 deletions src/test/script_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1467,6 +1467,35 @@ BOOST_AUTO_TEST_CASE(script_HasValidOps)
BOOST_CHECK(!script.HasValidOps());
}

static std::string DatacarrierBytesStr(const CScript &script) {
auto dcb = script.DatacarrierBytes();
return strprintf("%s+%s", dcb.first, dcb.second);
}

BOOST_AUTO_TEST_CASE(script_DataCarrierBytes)
{
using zeros = std::vector<unsigned char>;

// empty script
BOOST_CHECK_EQUAL("0+0", DatacarrierBytesStr(CScript()));
// series of pushes are not data
BOOST_CHECK_EQUAL("0+0", DatacarrierBytesStr(CScript() << OP_0 << OP_0 << OP_0));
// unspendable if first op is OP_RETURN, then length(1), zeros(11)
BOOST_CHECK_EQUAL("13+0", DatacarrierBytesStr(CScript() << OP_RETURN << zeros(11)));
// invalid script (no data following PUSHDATA) makes it all data
BOOST_CHECK_EQUAL("0+2", DatacarrierBytesStr(CScript() << OP_0 << OP_PUSHDATA4));
// no data here
BOOST_CHECK_EQUAL("0+0", DatacarrierBytesStr(CScript() << OP_TRUE << OP_IF << OP_ENDIF));
// specific data pattern, entire script is data
BOOST_CHECK_EQUAL("0+4", DatacarrierBytesStr(CScript() << OP_FALSE << OP_IF << OP_7 << OP_ENDIF));
// consecutive data
BOOST_CHECK_EQUAL("0+6", DatacarrierBytesStr(CScript() << OP_FALSE << OP_IF << OP_ENDIF << OP_FALSE << OP_IF << OP_ENDIF));
// nested data (all is data)
BOOST_CHECK_EQUAL("0+6", DatacarrierBytesStr(CScript() << OP_FALSE << OP_IF << OP_TRUE << OP_IF << OP_ENDIF << OP_ENDIF));
// pushing then immediately dropping is data: length(1), zero(11), OP_DROP
BOOST_CHECK_EQUAL("0+13", DatacarrierBytesStr(CScript() << zeros(11) << OP_DROP));
}

static CMutableTransaction TxFromHex(const std::string& str)
{
CMutableTransaction tx;
Expand Down

0 comments on commit b018c13

Please sign in to comment.