Skip to content

Conversation

@justinfilip
Copy link

Policy items (each reject reason and where enforced).

Defaults and new flags (e.g., -v1perinputwitnesslimit, default -acceptunknownwitness=0).

Deployment stub: new deployment ID/name, TBD versionbits params, BIP8 delayed activation.

Testing plan: might add unit/functional tests for SPK size/push caps, tapscript IF-ban, push-run/IF-body, control block cap, per-input v1 cap.

Link to BIP-0444 PR/discussion.

Justin Filip added 9 commits October 14, 2025 20:49
… expose -datacarrierwitnesslimit and -v1perinputwitnesslimit
…n SetupServerArgs; remove stray scoped block in InitParameterInteraction
…ript push-run and IF-branch push-only guards; drop redundant element check
…mits) with TBD params and versionbits wiring
…ushlen<=256, disallow OP_IF in tapscript policy; default -acceptunknownwitness=false
Copy link

@kwsantiago kwsantiago left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs work. Here are the main points:

  1. No test coverage: No functional tests added for new policy rules
  2. Performance concerns: Triple-parsing tapscripts (witness check, push runs, IF bodies) is inefficient. Should be single-pass.
  3. Policy rationale undocumented: Why 1024, 256, 80, 257? Need comments linking to BIP-0444 or analysis.
  4. Code duplication: Opcode parser copy-pasted 3+ times
  5. Incomplete opcode handling: OP_0, OP_1NEGATE, OP_1-OP_16 not recognized as pushes

Justin Filip added 5 commits October 15, 2025 10:18
…n; constants for limits; bounds for -v1perinputwitnesslimit; fix whichType use order; add comments with BIP-0444 rationale
…itness default; note tapscript tests as follow-up
…per-input witness cap, IF ban, push-run cap, and IF-body cap
@justinfilip
Copy link
Author

All points should be addressed @kwsantiago, very much appreciate the feedback

Copy link

@kwsantiago kwsantiago left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Excellent improvements @justinfilip !

Most previous issues were addressed. I left some remaining minor comments.

// Small integer push has no explicit payload
return true;
}
size_t need = 0;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an unused variable?

if (pos >= s.size()) return false;
pushed_len = s[pos++];
} else if (op == OP_PUSHDATA2) {
if (pos + 1 >= s.size()) return false;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if (pos + 1 >= s.size()) should be if (pos + 2 > s.size()) for consistency (needs 2 bytes). Same pattern in lines 73, 94, 95.

pushed_len = s[pos++];
} else if (op == OP_PUSHDATA2) {
if (pos + 1 >= s.size()) return false;
pushed_len = s[pos] | (uint32_t(s[pos+1]) << 8);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On lines 70 and 74, casting to uint32_t then assigning to uint64_t pushed_len. If PUSHDATA4 has value > 2^32-1, the upper bits are lost.

Should cast directly to uint64_t.

size_t payload = 0;
if (op >= 0x01 && op <= 0x4b) payload = op;
else if (op == OP_PUSHDATA1) { if (pos >= s.size()) return false; payload = s[pos++]; }
else if (op == OP_PUSHDATA2) { if (pos + 1 >= s.size()) return false; payload = s[pos] | (uint32_t(s[pos+1]) << 8); pos += 2; }

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AdvanceOneOp repeats the same bounds checks as ParsePush.

Consider refactoring to share logic.

} else if (op == OP_ELSE) {
if (!if_stack.empty()) {
size_t body_start = if_stack.back();
size_t body_end = j - 1;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When body_end == body_start, no branch is added, but this represents an empty IF body.

Should this be checked/rejected?

control[0] = 0xc0;

// Leaf with OP_IF containing 80-byte push-only body (would be rejected by IF ban first)
CScript leaf_if_80 = CScript() << OP_FALSE << OP_IF << std::vector<unsigned char>(80, 0) << OP_ENDIF << OP_TRUE;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On lines 228 and 237, these scripts use OP_FALSE << OP_IF which means the IF body never executes. The test is checking IF ban, not IF-body limit.

Consider testing actual IF-body limit separately if IF ban is lifted.

args.SoftSetArg("-blockmaxweight", "4000000");
}


Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Empty lines added without purpose. Remove.

mempool_opts.persist_v1_dat = argsman.GetBoolArg("-persistmempoolv1", mempool_opts.persist_v1_dat);

// Policy flags to constrain per-input witness size for segwit v1
if (auto lim = argsman.GetIntArg("-v1perinputwitnesslimit")) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

User sets -v1perinputwitnesslimit=50, gets 128 with no warning.

Should log when clamping occurs or return error for out-of-range values.

bool permitephemeral_send{DEFAULT_PERMITEPHEMERAL_SEND};
bool permitephemeral_dust{DEFAULT_PERMITEPHEMERAL_DUST};
bool persist_v1_dat{DEFAULT_PERSIST_V1_DAT};
// Policy to limit inscription-like data in witnesses/tapscripts

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"inscription-like data" is vague.

Be more specific: "Total witness bytes per v1 input to prevent witness stuffing/inscription abuse."


## References

- BIP-0444: https://github.com/bitcoin/bips/blob/master/bip-0444.mediawiki (pending merge)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BIP-0444 link shows "(pending merge)" but links to non-existent file (404).

Update when BIP number is assigned or remove until finalized.

@justinfilip
Copy link
Author

Excellent improvements @justinfilip !

Most previous issues were addressed. I left some remaining minor comments.

Appreciate the continual feedback and have noted the additional code review you've done.

Before I continue with addressing the code problems you've pointed out, I'd like to get your thoughts on my response in the BIP discussion: bitcoin/bips#2005 (comment)

@kwsantiago
Copy link

kwsantiago commented Oct 15, 2025

I'd like to get @luke-jr thoughts on moving forward with this on Knots, given that Core shut down the BIP discussion.

@luke-jr luke-jr changed the title BIP-0444 taproot/script limits; default unknown-witness off; BIP8 stub taproot/script limits; default unknown-witness off; BIP8 stub Oct 15, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants