Skip to content

Commit 938f427

Browse files
committed
script: Add CScript::DatacarrierBytes
Github-Pull: bitcoin#28408 Rebased-From: 9be9407
1 parent 9c8f0d3 commit 938f427

File tree

2 files changed

+52
-0
lines changed

2 files changed

+52
-0
lines changed

src/script/script.cpp

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,56 @@ bool CScript::HasValidOps() const
303303
return true;
304304
}
305305

306+
size_t CScript::DatacarrierBytes() const
307+
{
308+
size_t counted{0};
309+
opcodetype opcode, last_opcode{OP_INVALIDOPCODE};
310+
std::vector<unsigned char> push_data;
311+
unsigned int inside_noop{0}, inside_conditional{0};
312+
CScript::const_iterator opcode_it = begin(), data_began = begin();
313+
for (CScript::const_iterator it = begin(); it < end(); last_opcode = opcode) {
314+
opcode_it = it;
315+
if (!GetOp(it, opcode, push_data)) {
316+
// Invalid scripts are necessarily all data
317+
return size();
318+
}
319+
320+
if (opcode == OP_IF || opcode == OP_NOTIF) {
321+
++inside_conditional;
322+
} else if (opcode == OP_ENDIF) {
323+
if (!inside_conditional) return size(); // invalid
324+
--inside_conditional;
325+
} else if (opcode == OP_RETURN && !inside_conditional) {
326+
// unconditional OP_RETURN is unspendable
327+
return size();
328+
}
329+
330+
// Match OP_FALSE OP_IF
331+
if (inside_noop) {
332+
switch (opcode) {
333+
case OP_IF: case OP_NOTIF:
334+
++inside_noop;
335+
break;
336+
case OP_ENDIF:
337+
if (0 == --inside_noop) {
338+
counted += it - data_began + 1;
339+
}
340+
break;
341+
default: /* do nothing */;
342+
}
343+
} else if (opcode == OP_IF && last_opcode == OP_FALSE) {
344+
inside_noop = 1;
345+
data_began = opcode_it;
346+
// Match <data> OP_DROP
347+
} else if (opcode <= OP_PUSHDATA4) {
348+
data_began = opcode_it;
349+
} else if (opcode == OP_DROP && last_opcode <= OP_PUSHDATA4) {
350+
counted += it - data_began;
351+
}
352+
}
353+
return counted;
354+
}
355+
306356
bool GetScriptOp(CScriptBase::const_iterator& pc, CScriptBase::const_iterator end, opcodetype& opcodeRet, std::vector<unsigned char>* pvchRet)
307357
{
308358
opcodeRet = OP_INVALIDOPCODE;

src/script/script.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -562,6 +562,8 @@ class CScript : public CScriptBase
562562
return (size() > 0 && *begin() == OP_RETURN) || (size() > MAX_SCRIPT_SIZE);
563563
}
564564

565+
size_t DatacarrierBytes() const;
566+
565567
void clear()
566568
{
567569
// The default prevector::clear() does not release memory

0 commit comments

Comments
 (0)