@@ -303,6 +303,56 @@ bool CScript::HasValidOps() const
303
303
return true ;
304
304
}
305
305
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
+
306
356
bool GetScriptOp (CScriptBase::const_iterator& pc, CScriptBase::const_iterator end, opcodetype& opcodeRet, std::vector<unsigned char >* pvchRet)
307
357
{
308
358
opcodeRet = OP_INVALIDOPCODE;
0 commit comments