int expr(char *s) { stack opnum = {0, 0}; stack opch = {0, 0}; stackpush(&opch, '#'); while(*s != '\0') { if(*s >= '0' && *s <= '9') stackpush(&opnum, *s - '0'); else { while((calcCondition(*s, stacktop(&opch)) == 1) && (stacktop(&opch) != '#') && (stacktop(&opch) != '(')) { int left, right, res; right = stackpop(&opnum); left = stackpop(&opnum); res = calculate(left, stackpop(&opch), right); stackpush(&opnum, res); } if(stacktop(&opch) == '(' && *s == ')') stackpop(&opch); else stackpush(&opch, *s); } s++; } return stackpop(&opnum); }
void constructchildtab(void *space, Suffixarray *s) { Uint i; int lastIndex = -1; Stack *stack; s->chldtab = ALLOCMEMORY(space, NULL, childtab, s->numofsuffixes); memset(s->chldtab, 0, s->numofsuffixes*sizeof(childtab)); stack = ALLOCMEMORY(space, NULL, Stack, 1); initStack(space, stack, 100000); stackpush(space, stack, 1); for(i=1; i < s->numofsuffixes; i++) { while(s->lcptab[i] < s->lcptab[stacktop(stack)]) { lastIndex = stackpop(stack); if(s->lcptab[i] <= s->lcptab[stacktop(stack)] && s->lcptab[stacktop(stack)] != s->lcptab[lastIndex]) { s->chldtab[stacktop(stack)].down = lastIndex; if (s->chldtab[stacktop(stack)].val != 0) printf("down conflict\n"); s->chldtab[stacktop(stack)].val = lastIndex; } } if (lastIndex != -1) { s->chldtab[i].up = lastIndex; if (s->chldtab[i-1].val != 0) printf("up conflict\n"); s->chldtab[i-1].val = lastIndex; lastIndex = -1; } stackpush(space, stack, i); } /*construction of nextlIndex value*/ destructStack(space, stack); initStack(space, stack, 10000); stackpush(space, stack,0); for(i=1; i < s->numofsuffixes; i++) { while(s->lcptab[i] < s->lcptab[stacktop(stack)]) { stackpop(stack); } if (s->lcptab[i] == s->lcptab[stacktop(stack)]) { lastIndex = stackpop(stack); s->chldtab[lastIndex].nextlIndex = i; s->chldtab[lastIndex].val = i; } stackpush(space, stack, i); } return; }
void main() { char a[M],post[M],k=0; int i; s.top=-1; push('~'); printf("Enter the string\n"); gets(a); for(i=0;i<strlen(a);i++) { switch(a[i]) { case '+': case '-': case '*': case '/': if(priority(a[i])>priority(stacktop())) push(a[i]); else { while(priority(a[i])>priority(stacktop())) post[k++]=pop(); push(a[i]); } break; case '(': push(a[i]); break; case ')': while(stacktop()!='(') post[k++]=pop(); pop(); break; default: post[k++]=a[i]; } } while(stacktop()!='~') post[k++]=pop(); post[k++]='\0'; puts(post); getch(); }
Map* attachproc(int pid, int kflag, int corefd, Fhdr *fp) { char buf[64], *regs; int fd; Map *map; uvlong n; map = newmap(0, 4); if (!map) return 0; if(kflag) regs = "kregs"; else regs = "regs"; if (mach->regsize) { sprint(buf, "/proc/%d/%s", pid, regs); fd = open(buf, ORDWR); if(fd < 0) fd = open(buf, OREAD); if(fd < 0) { free(map); return 0; } setmap(map, fd, 0, mach->regsize, 0, "regs"); } if (mach->fpregsize) { sprint(buf, "/proc/%d/fpregs", pid); fd = open(buf, ORDWR); if(fd < 0) fd = open(buf, OREAD); if(fd < 0) { close(map->seg[0].fd); free(map); return 0; } setmap(map, fd, mach->regsize, mach->regsize+mach->fpregsize, 0, "fpregs"); } setmap(map, corefd, fp->txtaddr, fp->txtaddr+fp->txtsz, fp->txtaddr, "text"); if(kflag || fp->dataddr >= mach->utop) { setmap(map, corefd, fp->dataddr, ~0, fp->dataddr, "data"); return map; } n = stacktop(pid); if (n == 0) { setmap(map, corefd, fp->dataddr, mach->utop, fp->dataddr, "data"); return map; } setmap(map, corefd, fp->dataddr, n, fp->dataddr, "data"); return map; }
int main(){ struct stack s; s.top = -1; char expression[MAXSIZE]; char result[MAXSIZE]; int i=0, resp=0, ch=0; while((ch = getchar()) != '\n') expression[i++] = ch; expression[i] = '\0'; for(i=0; expression[i]; i++){ if (isoperator(expression[i])){ if(precedes(stacktop(&s), expression[i])){ if((stacktop(&s) != '(') && (stacktop(&s) != ')')) result[resp++] = pop(&s); else pop(&s); } push(&s, expression[i]); printf("Pushed %c to stack. Result: %s\n", expression[i], result); } else{ result[resp++] = expression[i]; } } while(!empty(&s)){ if ((stacktop(&s) != '(') && (stacktop(&s) != ')')) result[resp++] = pop(&s); else pop(&s); } result[resp] = '\0'; printf("Result is: %s\n", result); exit(0); }
static int stackint(parr *stack, int index, bool fRequireMinimal) { struct buffer *buf = stacktop(stack, index); mpz_t bn; mpz_init(bn); int ret = -1; if (!CastToBigNum(bn, buf, fRequireMinimal, nDefaultMaxNumSize)) goto out; ret = mpz_get_si(bn); out: mpz_clear(bn); return ret; }
int main() { struct tree *root=NULL; insert(&root,10); insert(&root,20); insert(&root,5); insert(&root,4); insert(&root,6); struct stack *s; s=createstack(); struct tree *c=root; c->vl=0; c->vr=0; push(s,c); while( !stackempty(s) ) { while( ((tree*)stacktop(s))->left!=NULL && !((tree*)stacktop(s))->vl ) { struct tree *n=(tree*)stacktop(s); n->vl=1; push(s,n->left); } while( ((tree*)stacktop(s))->right!=NULL && !((tree*)stacktop(s))->vr ) { struct tree *n=(tree*)stacktop(s); n->vr=1; push(s,n->right); } struct tree *n=(tree*)pop(s); printf("%d ",n->d); } getch(); }
static int stackint(GPtrArray *stack, int index) { struct buffer *buf = stacktop(stack, index); BIGNUM bn; BN_init(&bn); int ret = -1; if (!CastToBigNum(&bn, buf)) goto out; if (!BN_is_negative(&bn)) ret = BN_get_word(&bn); else { BN_set_negative(&bn, 0); ret = BN_get_word(&bn); ret = -ret; } out: BN_clear_free(&bn); return ret; }
static bool bp_script_eval(parr *stack, const cstring *script, const struct bp_tx *txTo, unsigned int nIn, unsigned int flags, int nHashType) { struct const_buffer pc = { script->str, script->len }; struct const_buffer pend = { script->str + script->len, 0 }; struct const_buffer pbegincodehash = { script->str, script->len }; struct bscript_op op; bool rc = false; cstring *vfExec = cstr_new(NULL); parr *altstack = parr_new(0, buffer_freep); mpz_t bn, bn_Zero, bn_One; mpz_init(bn); mpz_init_set_ui(bn_Zero, 0); mpz_init_set_ui(bn_One,1); if (script->len > MAX_SCRIPT_SIZE) goto out; unsigned int nOpCount = 0; bool fRequireMinimal = (flags & SCRIPT_VERIFY_MINIMALDATA) != 0; struct bscript_parser bp; bsp_start(&bp, &pc); while (pc.p < pend.p) { bool fExec = !count_false(vfExec); if (!bsp_getop(&op, &bp)) goto out; enum opcodetype opcode = op.op; if (op.data.len > MAX_SCRIPT_ELEMENT_SIZE) goto out; if (opcode > OP_16 && ++nOpCount > MAX_OPS_PER_SCRIPT) goto out; if (disabled_op[opcode]) goto out; if (fExec && 0 <= opcode && opcode <= OP_PUSHDATA4) { if (fRequireMinimal && !CheckMinimalPush(&op.data, opcode)) goto out; stack_push(stack, (struct buffer *) &op.data); } else if (fExec || (OP_IF <= opcode && opcode <= OP_ENDIF)) switch (opcode) { // // Push value // case OP_1NEGATE: case OP_1: case OP_2: case OP_3: case OP_4: case OP_5: case OP_6: case OP_7: case OP_8: case OP_9: case OP_10: case OP_11: case OP_12: case OP_13: case OP_14: case OP_15: case OP_16: mpz_set_si(bn, (int)opcode - (int)(OP_1 - 1)); stack_push_str(stack, bn_getvch(bn)); break; // // Control // case OP_NOP: break; case OP_CHECKLOCKTIMEVERIFY: { if (!(flags & SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY)) { // not enabled; treat as a NOP2 if (flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) goto out; break; } if (stack->len < 1) goto out; // Note that elsewhere numeric opcodes are limited to // operands in the range -2**31+1 to 2**31-1, however it is // legal for opcodes to produce results exceeding that // range. This limitation is implemented by CastToBigNum's // default 4-byte limit. // // If we kept to that limit we'd have a year 2038 problem, // even though the nLockTime field in transactions // themselves is uint32 which only becomes meaningless // after the year 2106. // // Thus as a special case we tell CastToBigNum to accept up // to 5-byte bignums, which are good until 2**39-1, well // beyond the 2**32-1 limit of the nLockTime field itself. if (!CastToBigNum(bn, stacktop(stack, -1), fRequireMinimal, 5)) goto out; // In the rare event that the argument may be < 0 due to // some arithmetic being done first, you can always use // 0 MAX CHECKLOCKTIMEVERIFY. if (mpz_sgn(bn) < 0) goto out; uint64_t nLockTime = mpz_get_ui(bn); // Actually compare the specified lock time with the transaction. if (!CheckLockTime(nLockTime, txTo, nIn)) goto out; break; } case OP_CHECKSEQUENCEVERIFY: { if (!(flags & SCRIPT_VERIFY_CHECKSEQUENCEVERIFY)) { // not enabled; treat as a NOP3 if (flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) goto out; break; } if (stack->len < 1) goto out; // nSequence, like nLockTime, is a 32-bit unsigned integer // field. See the comment in CHECKLOCKTIMEVERIFY regarding // 5-byte numeric operands. if (!CastToBigNum(bn, stacktop(stack, -1), fRequireMinimal, 5)) goto out; // In the rare event that the argument may be < 0 due to // some arithmetic being done first, you can always use // 0 MAX CHECKSEQUENCEVERIFY. if (mpz_sgn(bn) < 0) goto out; uint32_t nSequence = mpz_get_ui(bn); // To provide for future soft-fork extensibility, if the // operand has the disabled lock-time flag set, // CHECKSEQUENCEVERIFY behaves as a NOP. if ((nSequence & SEQUENCE_LOCKTIME_DISABLE_FLAG) != 0) break; // Compare the specified sequence number with the input. if (!CheckSequence(nSequence, txTo, nIn)) goto out; break; } case OP_NOP1: case OP_NOP4: case OP_NOP5: case OP_NOP6: case OP_NOP7: case OP_NOP8: case OP_NOP9: case OP_NOP10: if (flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) goto out; break; case OP_IF: case OP_NOTIF: { // <expression> if [statements] [else [statements]] endif bool fValue = false; if (fExec) { if (stack->len < 1) goto out; struct buffer *vch = stacktop(stack, -1); fValue = CastToBool(vch); if (opcode == OP_NOTIF) fValue = !fValue; popstack(stack); } uint8_t vc = (uint8_t) fValue; cstr_append_c(vfExec, vc); break; } case OP_ELSE: { if (vfExec->len == 0) goto out; uint8_t *v = (uint8_t *) &vfExec->str[vfExec->len - 1]; *v = !(*v); break; } case OP_ENDIF: if (vfExec->len == 0) goto out; cstr_erase(vfExec, vfExec->len - 1, 1); break; case OP_VERIFY: { if (stack->len < 1) goto out; bool fValue = CastToBool(stacktop(stack, -1)); if (fValue) popstack(stack); else goto out; break; } case OP_RETURN: goto out; // // Stack ops // case OP_TOALTSTACK: if (stack->len < 1) goto out; stack_push(altstack, stacktop(stack, -1)); popstack(stack); break; case OP_FROMALTSTACK: if (altstack->len < 1) goto out; stack_push(stack, stacktop(altstack, -1)); popstack(altstack); break; case OP_2DROP: // (x1 x2 -- ) if (stack->len < 2) goto out; popstack(stack); popstack(stack); break; case OP_2DUP: { // (x1 x2 -- x1 x2 x1 x2) if (stack->len < 2) goto out; struct buffer *vch1 = stacktop(stack, -2); struct buffer *vch2 = stacktop(stack, -1); stack_push(stack, vch1); stack_push(stack, vch2); break; } case OP_3DUP: { // (x1 x2 x3 -- x1 x2 x3 x1 x2 x3) if (stack->len < 3) goto out; struct buffer *vch1 = stacktop(stack, -3); struct buffer *vch2 = stacktop(stack, -2); struct buffer *vch3 = stacktop(stack, -1); stack_push(stack, vch1); stack_push(stack, vch2); stack_push(stack, vch3); break; } case OP_2OVER: { // (x1 x2 x3 x4 -- x1 x2 x3 x4 x1 x2) if (stack->len < 4) goto out; struct buffer *vch1 = stacktop(stack, -4); struct buffer *vch2 = stacktop(stack, -3); stack_push(stack, vch1); stack_push(stack, vch2); break; } case OP_2ROT: { // (x1 x2 x3 x4 x5 x6 -- x3 x4 x5 x6 x1 x2) if (stack->len < 6) goto out; struct buffer *vch1 = stack_take(stack, -6); struct buffer *vch2 = stack_take(stack, -5); parr_remove_range(stack, stack->len - 6, 2); stack_push_nocopy(stack, vch1); stack_push_nocopy(stack, vch2); break; } case OP_2SWAP: // (x1 x2 x3 x4 -- x3 x4 x1 x2) if (stack->len < 4) goto out; stack_swap(stack, -4, -2); stack_swap(stack, -3, -1); break; case OP_IFDUP: { // (x - 0 | x x) if (stack->len < 1) goto out; struct buffer *vch = stacktop(stack, -1); if (CastToBool(vch)) stack_push(stack, vch); break; } case OP_DEPTH: // -- stacksize mpz_set_ui(bn, stack->len); stack_push_str(stack, bn_getvch(bn)); break; case OP_DROP: // (x -- ) if (stack->len < 1) goto out; popstack(stack); break; case OP_DUP: { // (x -- x x) if (stack->len < 1) goto out; struct buffer *vch = stacktop(stack, -1); stack_push(stack, vch); break; } case OP_NIP: // (x1 x2 -- x2) if (stack->len < 2) goto out; parr_remove_idx(stack, stack->len - 2); break; case OP_OVER: { // (x1 x2 -- x1 x2 x1) if (stack->len < 2) goto out; struct buffer *vch = stacktop(stack, -2); stack_push(stack, vch); break; } case OP_PICK: case OP_ROLL: { // (xn ... x2 x1 x0 n - xn ... x2 x1 x0 xn) // (xn ... x2 x1 x0 n - ... x2 x1 x0 xn) if (stack->len < 2) goto out; int n = stackint(stack, -1, fRequireMinimal); popstack(stack); if (n < 0 || n >= (int)stack->len) goto out; struct buffer *vch = stacktop(stack, -n-1); if (opcode == OP_ROLL) { vch = buffer_copy(vch->p, vch->len); parr_remove_idx(stack, stack->len - n - 1); stack_push_nocopy(stack, vch); } else stack_push(stack, vch); break; } case OP_ROT: { // (x1 x2 x3 -- x2 x3 x1) // x2 x1 x3 after first swap // x2 x3 x1 after second swap if (stack->len < 3) goto out; stack_swap(stack, -3, -2); stack_swap(stack, -2, -1); break; } case OP_SWAP: { // (x1 x2 -- x2 x1) if (stack->len < 2) goto out; stack_swap(stack, -2, -1); break; } case OP_TUCK: { // (x1 x2 -- x2 x1 x2) if (stack->len < 2) goto out; struct buffer *vch = stacktop(stack, -1); stack_insert(stack, vch, -2); break; } case OP_SIZE: { // (in -- in size) if (stack->len < 1) goto out; struct buffer *vch = stacktop(stack, -1); mpz_set_ui(bn, vch->len); stack_push_str(stack, bn_getvch(bn)); break; } case OP_EQUAL: case OP_EQUALVERIFY: { // (x1 x2 - bool) if (stack->len < 2) goto out; struct buffer *vch1 = stacktop(stack, -2); struct buffer *vch2 = stacktop(stack, -1); bool fEqual = buffer_equal(vch1, vch2); // OP_NOTEQUAL is disabled because it would be too easy to say // something like n != 1 and have some wiseguy pass in 1 with extra // zero bytes after it (numerically, 0x01 == 0x0001 == 0x000001) //if (opcode == OP_NOTEQUAL) // fEqual = !fEqual; popstack(stack); popstack(stack); stack_push_str(stack, fEqual ? bn_getvch(bn_One) : bn_getvch(bn_Zero)); if (opcode == OP_EQUALVERIFY) { if (fEqual) popstack(stack); else goto out; } break; } // // Numeric // case OP_1ADD: case OP_1SUB: case OP_NEGATE: case OP_ABS: case OP_NOT: case OP_0NOTEQUAL: { // (in -- out) if (stack->len < 1) goto out; if (!CastToBigNum(bn, stacktop(stack, -1), fRequireMinimal, nDefaultMaxNumSize)) goto out; switch (opcode) { case OP_1ADD: mpz_add_ui(bn, bn, 1); break; case OP_1SUB: mpz_sub_ui(bn, bn, 1); break; case OP_NEGATE: mpz_neg(bn, bn); break; case OP_ABS: mpz_abs(bn, bn); break; case OP_NOT: mpz_set_ui(bn, mpz_sgn(bn) == 0 ? 1 : 0); break; case OP_0NOTEQUAL: mpz_set_ui(bn, mpz_sgn(bn) == 0 ? 0 : 1); break; default: // impossible goto out; } popstack(stack); stack_push_str(stack, bn_getvch(bn)); break; } case OP_ADD: case OP_SUB: case OP_BOOLAND: case OP_BOOLOR: case OP_NUMEQUAL: case OP_NUMEQUALVERIFY: case OP_NUMNOTEQUAL: case OP_LESSTHAN: case OP_GREATERTHAN: case OP_LESSTHANOREQUAL: case OP_GREATERTHANOREQUAL: case OP_MIN: case OP_MAX: { // (x1 x2 -- out) if (stack->len < 2) goto out; mpz_t bn1, bn2; mpz_init(bn1); mpz_init(bn2); if (!CastToBigNum(bn1, stacktop(stack, -2), fRequireMinimal, nDefaultMaxNumSize) || !CastToBigNum(bn2, stacktop(stack, -1), fRequireMinimal, nDefaultMaxNumSize)) { mpz_clear(bn1); mpz_clear(bn2); goto out; } switch (opcode) { case OP_ADD: mpz_add(bn, bn1, bn2); break; case OP_SUB: mpz_sub(bn, bn1, bn2); break; case OP_BOOLAND: mpz_set_ui(bn, !(mpz_sgn(bn1) == 0) && !(mpz_sgn(bn2) == 0) ? 1 : 0); break; case OP_BOOLOR: mpz_set_ui(bn, !(mpz_sgn(bn1) == 0) || !(mpz_sgn(bn2) == 0) ? 1 : 0); break; case OP_NUMEQUAL: case OP_NUMEQUALVERIFY: mpz_set_ui(bn, mpz_cmp(bn1, bn2) == 0 ? 1 : 0); break; case OP_NUMNOTEQUAL: mpz_set_ui(bn, mpz_cmp(bn1, bn2) != 0 ? 1 : 0); break; case OP_LESSTHAN: mpz_set_ui(bn, mpz_cmp(bn1, bn2) < 0 ? 1 : 0); break; case OP_GREATERTHAN: mpz_set_ui(bn, mpz_cmp(bn1, bn2) > 0 ? 1 : 0); break; case OP_LESSTHANOREQUAL: mpz_set_ui(bn, mpz_cmp(bn1, bn2) <= 0 ? 1 : 0); break; case OP_GREATERTHANOREQUAL: mpz_set_ui(bn, mpz_cmp(bn1, bn2) >= 0 ? 1 : 0); break; case OP_MIN: if (mpz_cmp(bn1, bn2) < 0) mpz_set(bn, bn1); else mpz_set(bn, bn2); break; case OP_MAX: if (mpz_cmp(bn1, bn2) > 0) mpz_set(bn, bn1); else mpz_set(bn, bn2); break; default: // impossible break; } popstack(stack); popstack(stack); stack_push_str(stack, bn_getvch(bn)); mpz_clear(bn1); mpz_clear(bn2); if (opcode == OP_NUMEQUALVERIFY) { if (CastToBool(stacktop(stack, -1))) popstack(stack); else goto out; } break; } case OP_WITHIN: { // (x min max -- out) if (stack->len < 3) goto out; mpz_t bn1, bn2, bn3; mpz_init(bn1); mpz_init(bn2); mpz_init(bn3); bool rc1 = CastToBigNum(bn1, stacktop(stack, -3), fRequireMinimal, nDefaultMaxNumSize); bool rc2 = CastToBigNum(bn2, stacktop(stack, -2), fRequireMinimal, nDefaultMaxNumSize); bool rc3 = CastToBigNum(bn3, stacktop(stack, -1), fRequireMinimal, nDefaultMaxNumSize); bool fValue = (mpz_cmp(bn2, bn1) <= 0 && mpz_cmp(bn1, bn3) < 0); popstack(stack); popstack(stack); popstack(stack); stack_push_str(stack, fValue ? bn_getvch(bn_One) : bn_getvch(bn_Zero)); mpz_clear(bn1); mpz_clear(bn2); mpz_clear(bn3); if (!rc1 || !rc2 || !rc3) goto out; break; } // // Crypto // case OP_RIPEMD160: case OP_SHA1: case OP_SHA256: case OP_HASH160: case OP_HASH256: { // (in -- hash) if (stack->len < 1) goto out; struct buffer *vch = stacktop(stack, -1); unsigned int hashlen; unsigned char md[32]; switch (opcode) { case OP_RIPEMD160: hashlen = 20; ripemd160(vch->p, vch->len, md); break; case OP_SHA1: hashlen = 20; sha1_Raw(vch->p, vch->len, md); break; case OP_SHA256: hashlen = 32; sha256_Raw(vch->p, vch->len, md); break; case OP_HASH160: hashlen = 20; bu_Hash160(md, vch->p, vch->len); break; case OP_HASH256: hashlen = 32; bu_Hash(md, vch->p, vch->len); break; default: // impossible goto out; } popstack(stack); struct buffer buf = { md, hashlen }; stack_push(stack, &buf); break; } case OP_CODESEPARATOR: // Hash starts after the code separator memcpy(&pbegincodehash, &pc, sizeof(pc)); break; case OP_CHECKSIG: case OP_CHECKSIGVERIFY: { // (sig pubkey -- bool) if (stack->len < 2) goto out; struct buffer *vchSig = stacktop(stack, -2); struct buffer *vchPubKey = stacktop(stack, -1); // Subset of script starting at the most recent codeseparator cstring *scriptCode = cstr_new_buf(pbegincodehash.p, pbegincodehash.len); // Drop the signature, since there's no way for // a signature to sign itself string_find_del(scriptCode, vchSig); if (!CheckSignatureEncoding(vchSig, flags) || !CheckPubKeyEncoding(vchPubKey, flags)) { cstr_free(scriptCode, true); goto out; } bool fSuccess = bp_checksig(vchSig, vchPubKey, scriptCode, txTo, nIn); cstr_free(scriptCode, true); popstack(stack); popstack(stack); stack_push_str(stack, fSuccess ? bn_getvch(bn_One) : bn_getvch(bn_Zero)); if (opcode == OP_CHECKSIGVERIFY) { if (fSuccess) popstack(stack); else goto out; } break; } case OP_CHECKMULTISIG: case OP_CHECKMULTISIGVERIFY: { // ([sig ...] num_of_signatures [pubkey ...] num_of_pubkeys -- bool) int i = 1; if ((int)stack->len < i) goto out; int nKeysCount = stackint(stack, -i, fRequireMinimal); if (nKeysCount < 0 || nKeysCount > MAX_PUBKEYS_PER_MULTISIG) goto out; nOpCount += nKeysCount; if (nOpCount > MAX_OPS_PER_SCRIPT) goto out; int ikey = ++i; i += nKeysCount; if ((int)stack->len < i) goto out; int nSigsCount = stackint(stack, -i, fRequireMinimal); if (nSigsCount < 0 || nSigsCount > nKeysCount) goto out; int isig = ++i; i += nSigsCount; if ((int)stack->len < i) goto out; // Subset of script starting at the most recent codeseparator cstring *scriptCode = cstr_new_buf(pbegincodehash.p, pbegincodehash.len); // Drop the signatures, since there's no way for // a signature to sign itself int k; for (k = 0; k < nSigsCount; k++) { struct buffer *vchSig =stacktop(stack, -isig-k); string_find_del(scriptCode, vchSig); } bool fSuccess = true; while (fSuccess && nSigsCount > 0) { struct buffer *vchSig = stacktop(stack, -isig); struct buffer *vchPubKey = stacktop(stack, -ikey); // Note how this makes the exact order of pubkey/signature evaluation // distinguishable by CHECKMULTISIG NOT if the STRICTENC flag is set. // See the script_(in)valid tests for details. if (!CheckSignatureEncoding(vchSig, flags) || !CheckPubKeyEncoding(vchPubKey, flags)) { cstr_free(scriptCode, true); goto out; } // Check signature bool fOk = bp_checksig(vchSig, vchPubKey, scriptCode, txTo, nIn); if (fOk) { isig++; nSigsCount--; } ikey++; nKeysCount--; // If there are more signatures left than keys left, // then too many signatures have failed if (nSigsCount > nKeysCount) fSuccess = false; } cstr_free(scriptCode, true); // Clean up stack of actual arguments while (i-- > 1) popstack(stack); // A bug causes CHECKMULTISIG to consume one extra argument // whose contents were not checked in any way. // // Unfortunately this is a potential source of mutability, // so optionally verify it is exactly equal to zero prior // to removing it from the stack. if ((int)stack->len < 1) goto out; if ((flags & SCRIPT_VERIFY_NULLDUMMY) && stacktop(stack, -1)->len) goto out; popstack(stack); stack_push_str(stack, fSuccess ? bn_getvch(bn_One) : bn_getvch(bn_Zero)); if (opcode == OP_CHECKMULTISIGVERIFY) { if (fSuccess) popstack(stack); else goto out; } break; } default: goto out; } // Size limits if (stack->len + altstack->len > 1000) goto out; } rc = (vfExec->len == 0 && bp.error == false); out: mpz_clears(bn, bn_Zero, bn_One, NULL); parr_free(altstack, true); cstr_free(vfExec, true); return rc; }
bool bp_script_verify(const cstring *scriptSig, const cstring *scriptPubKey, const struct bp_tx *txTo, unsigned int nIn, unsigned int flags, int nHashType) { bool rc = false; parr *stack = parr_new(0, buffer_freep); parr *stackCopy = NULL; struct const_buffer sigbuf = { scriptSig->str, scriptSig->len }; if ((flags & SCRIPT_VERIFY_SIGPUSHONLY) != 0 && !is_bsp_pushonly(&sigbuf)) goto out; if (!bp_script_eval(stack, scriptSig, txTo, nIn, flags, nHashType)) goto out; if (flags & SCRIPT_VERIFY_P2SH) { stackCopy = parr_new(stack->len, buffer_freep); stack_copy(stackCopy, stack); } if (!bp_script_eval(stack, scriptPubKey, txTo, nIn, flags, nHashType)) goto out; if (stack->len == 0) goto out; if (CastToBool(stacktop(stack, -1)) == false) goto out; if ((flags & SCRIPT_VERIFY_P2SH) && is_bsp_p2sh_str(scriptPubKey)) { // scriptSig must be literals-only or validation fails if (!is_bsp_pushonly(&sigbuf)) goto out; // stack cannot be empty here, because if it was the // P2SH HASH <> EQUAL scriptPubKey would be evaluated with // an empty stack and the script_eval above would return false. if (stackCopy->len < 1) goto out; struct buffer *pubKeySerialized = stack_take(stackCopy, -1); popstack(stackCopy); cstring *pubkey2 = cstr_new_buf(pubKeySerialized->p, pubKeySerialized->len); buffer_freep(pubKeySerialized); bool rc2 = bp_script_eval(stackCopy, pubkey2, txTo, nIn, flags, nHashType); cstr_free(pubkey2, true); if (!rc2) goto out; if (stackCopy->len == 0) goto out; if (CastToBool(stacktop(stackCopy, -1)) == false) goto out; } // The CLEANSTACK check is only performed after potential P2SH evaluation, // as the non-P2SH evaluation of a P2SH script will obviously not result in // a clean stack (the P2SH inputs remain). if ((flags & SCRIPT_VERIFY_CLEANSTACK) != 0) { // Disallow CLEANSTACK without P2SH, as otherwise a switch CLEANSTACK->P2SH+CLEANSTACK // would be possible, which is not a softfork (and P2SH should be one). assert((flags & SCRIPT_VERIFY_P2SH) != 0); if (stackCopy->len != 1) goto out; } rc = true; out: parr_free(stack, true); if (stackCopy) parr_free(stackCopy, true); return rc; }
void main(){ FILE *infile,*outfile; NODE *current,*first_01; TOKEN *token,t; STACKBYARRAY *stack=create_stack_by_array(50); SYMTAB_ENTRY **symtab=create_symbol_table_array(SYMTAB_ARRAY_SIZE); int unique_no=1; int hashval=0; int number_of; char *pointer,*pointer2,count_string[20]; int alfeof=0; int g2_001_FORMAT_OR_STOP_A; int g3_001_LEVEL_NUMBER_A; int g5_001_NINE_SUBTREE_A; int g6_001_X_SUBTREE_A; int g4_001_FORMAT_SUBTREE_A; /**************************************************************************/ /**************************************************************************/ /******************** DRIVING PROCEDURE B:\SYMCOB *********************/ /**************************************************************************/ PROCEDURE_DIVISION: /**/ C1_001_GENERATE_SYMBOL: goto C1_002_SYMBOL_START; C1_002_SYMBOL_START_EX: goto C1_003_BEFORE_WORKING; C1_003_BEFORE_WORKING_EX: goto C1_005_SECTION; C1_005_SECTION_EX: goto C1_006_WORKING_STORAGE; C1_006_WORKING_STORAGE_EX: goto C1_021_END; C1_021_END_EX: goto veryend; /**/ C1_002_SYMBOL_START: /*001*/ infile=open_input("b:testout2.dat"); outfile=open_output("b:symtable.out"); token=&t; /*002*/ if(!feof(infile)) alfeof=get_token(infile,token); goto C1_002_SYMBOL_START_EX; /**/ C1_003_BEFORE_WORKING: C1_004_JUST_DATA_EX: if(!( /*C01*/ (token->value.keyword_number==WORKING_STORAGE) )) goto C1_004_JUST_DATA; goto C1_003_BEFORE_WORKING_EX; /**/ C1_004_JUST_DATA: /*002*/ if(!feof(infile)) alfeof=get_token(infile,token); goto C1_004_JUST_DATA_EX; /**/ C1_005_SECTION: /*002*/ if(!feof(infile)) alfeof=get_token(infile,token); /*002*/ if(!feof(infile)) alfeof=get_token(infile,token); /*002*/ if(!feof(infile)) alfeof=get_token(infile,token); goto C1_005_SECTION_EX; /**/ C1_006_WORKING_STORAGE: goto C1_007_FIRST_01; C1_007_FIRST_01_EX: goto C1_012_REST; C1_012_REST_EX: goto C1_006_WORKING_STORAGE_EX; /**/ C1_007_FIRST_01: goto C1_008_NUM; C1_008_NUM_EX: goto C1_009_VARIABLE_NAME; C1_009_VARIABLE_NAME_EX: goto C1_010_FORMAT_OR_STOP; C1_010_FORMAT_OR_STOP_EX: goto C1_011_END_LEVEL; C1_011_END_LEVEL_EX: goto C1_007_FIRST_01_EX; /**/ C1_008_NUM: /*003*/ current=create_node(); current->level=str_to_int(token->value.string); /*002*/ if(!feof(infile)) alfeof=get_token(infile,token); goto C1_008_NUM_EX; /**/ C1_009_VARIABLE_NAME: /*007*/ NAME(current)=token->value.string; /*002*/ if(!feof(infile)) alfeof=get_token(infile,token); /*012*/ hashval=hash(NAME(current))%SYMTAB_ARRAY_SIZE; current->own.hash=hashval; add_node_to_sym(current,hashval,symtab); goto C1_009_VARIABLE_NAME_EX; /**/ C1_010_FORMAT_OR_STOP: g2_001_FORMAT_OR_STOP_A=0; goto C2_001_FORMAT_OR_STOP; C2_001_EXIT01: goto C1_010_FORMAT_OR_STOP_EX; /**/ C1_011_END_LEVEL: /*011*/ PARENT(current)=NULL; first_01=current; /*010*/ stackpush(stack,current); /*013*/ current->own.unique=unique_no; unique_no++; goto C1_011_END_LEVEL_EX; /**/ C1_012_REST: C1_013_LEVEL_EX: if(!( /*C02*/ (alfeof==1) )) goto C1_013_LEVEL; goto C1_012_REST_EX; /**/ C1_013_LEVEL: goto C1_014_LEVEL_NUMBER; C1_014_LEVEL_NUMBER_EX: goto C1_015_VARIABLE_NAME; C1_015_VARIABLE_NAME_EX: goto C1_016_FORMAT_OR_STOP; C1_016_FORMAT_OR_STOP_EX: goto C1_017_END_LEVEL; C1_017_END_LEVEL_EX: goto C1_013_LEVEL_EX; /**/ C1_014_LEVEL_NUMBER: g3_001_LEVEL_NUMBER_A=0; goto C3_001_LEVEL_NUMBER; C3_001_EXIT01: goto C1_014_LEVEL_NUMBER_EX; /**/ C1_015_VARIABLE_NAME: /*007*/ NAME(current)=token->value.string; /*002*/ if(!feof(infile)) alfeof=get_token(infile,token); /*012*/ hashval=hash(NAME(current))%SYMTAB_ARRAY_SIZE; current->own.hash=hashval; add_node_to_sym(current,hashval,symtab); goto C1_015_VARIABLE_NAME_EX; /**/ C1_016_FORMAT_OR_STOP: g2_001_FORMAT_OR_STOP_A=1; goto C2_001_FORMAT_OR_STOP; C2_001_EXIT02: goto C1_016_FORMAT_OR_STOP_EX; /**/ C1_017_END_LEVEL: goto C1_018_POSS_OVERWRITE; C1_018_POSS_OVERWRITE_EX: goto C1_020_END; C1_020_END_EX: goto C1_017_END_LEVEL_EX; /**/ C1_018_POSS_OVERWRITE: if(( /*C04*/ (current->level==stacktop(stack)->level) )) goto C1_019_OVERWRITE; C1_019_OVERWRITE_EX: goto C1_018_POSS_OVERWRITE_EX; /**/ C1_019_OVERWRITE: /*005*/ stackpop(stack); goto C1_019_OVERWRITE_EX; /**/ C1_020_END: /*010*/ stackpush(stack,current); /*013*/ current->own.unique=unique_no; unique_no++; goto C1_020_END_EX; /**/ C1_021_END: /*014*/ close_file(infile); save_nodes(symtab,outfile); close_file(outfile); goto C1_021_END_EX; /**/ C4_001_FORMAT_SUBTREE: goto C4_002_PICTURE; C4_002_PICTURE_EX: goto C4_003_LIMITED; C4_003_LIMITED_EX: goto C4_010_FULLSTOP; C4_010_FULLSTOP_EX: C4_001_FORMAT_SUBTREE_A: switch(g4_001_FORMAT_SUBTREE_A){ case 0 : goto C4_001_EXIT02;break; } /**/ C4_002_PICTURE: /*002*/ if(!feof(infile)) alfeof=get_token(infile,token); /*016*/ pointer=token->value.string; /*008*/ current->info->type=VARIABLE; goto C4_002_PICTURE_EX; /**/ C4_003_LIMITED: if(( /*C08*/ (*pointer=='9') )) goto C4_004_NINE; if(!( /*C08*/ (*pointer=='9') )) goto C4_007_X; C4_004_NINE_EX: C4_007_X_EX: goto C4_003_LIMITED_EX; /**/ C4_004_NINE: goto C4_005_NINE_START; C4_005_NINE_START_EX: goto C4_006_NINE_SUBTREE; C4_006_NINE_SUBTREE_EX: goto C4_004_NINE_EX; /**/ C4_005_NINE_START: /*022*/ current->info->type=INT; /*015*/ number_of=0; /*017*/ pointer++; goto C4_005_NINE_START_EX; /**/ C4_006_NINE_SUBTREE: g5_001_NINE_SUBTREE_A=0; goto C5_001_NINE_SUBTREE; C5_001_EXIT01: goto C4_006_NINE_SUBTREE_EX; /**/ C4_007_X: goto C4_008_X_START; C4_008_X_START_EX: goto C4_009_X_SUBTREE; C4_009_X_SUBTREE_EX: goto C4_007_X_EX; /**/ C4_008_X_START: /*023*/ current->info->type=CHAR; /*015*/ number_of=0; /*017*/ pointer++; goto C4_008_X_START_EX; /**/ C4_009_X_SUBTREE: g6_001_X_SUBTREE_A=0; goto C6_001_X_SUBTREE; C6_001_EXIT01: goto C4_009_X_SUBTREE_EX; /**/ C4_010_FULLSTOP: goto C4_010_FULLSTOP_EX; /**/ C3_001_LEVEL_NUMBER: goto C3_002_NUMBER_START; C3_002_NUMBER_START_EX: goto C3_003_NUMBER_BODY; C3_003_NUMBER_BODY_EX: goto C3_011_NUMBER_END; C3_011_NUMBER_END_EX: C3_001_LEVEL_NUMBER_A: switch(g3_001_LEVEL_NUMBER_A){ case 0 : goto C3_001_EXIT01;break; } /**/ C3_002_NUMBER_START: /*003*/ current=create_node(); current->level=str_to_int(token->value.string); goto C3_002_NUMBER_START_EX; /**/ C3_003_NUMBER_BODY: if(( /*C03*/ (current->level > stacktop(stack)->level) )) goto C3_004_FURTHER_DOWN; if(( /*C05*/ (current->level < stacktop(stack)->level) )) goto C3_005_BACK_UP; if(( /*C04*/ (current->level==stacktop(stack)->level) )) goto C3_010_SAME; C3_004_FURTHER_DOWN_EX: C3_005_BACK_UP_EX: C3_010_SAME_EX: goto C3_003_NUMBER_BODY_EX; /**/ C3_004_FURTHER_DOWN: /*004*/ PARENT(current)=stacktop(stack); CHILD(stacktop(stack))=current; goto C3_004_FURTHER_DOWN_EX; /**/ C3_005_BACK_UP: goto C3_006_BUS; C3_006_BUS_EX: goto C3_007_BUB; C3_007_BUB_EX: goto C3_009_BUE; C3_009_BUE_EX: goto C3_005_BACK_UP_EX; /**/ C3_006_BUS: goto C3_006_BUS_EX; /**/ C3_007_BUB: C3_008_LEVEL_EX: if(!( /*C04*/ (current->level==stacktop(stack)->level) )) goto C3_008_LEVEL; goto C3_007_BUB_EX; /**/ C3_008_LEVEL: /*005*/ stackpop(stack); goto C3_008_LEVEL_EX; /**/ C3_009_BUE: /*006*/ SIBLING(stacktop(stack))=current; PARENT(current)=PARENT(stacktop(stack)); goto C3_009_BUE_EX; /**/ C3_010_SAME: /*006*/ SIBLING(stacktop(stack))=current; PARENT(current)=PARENT(stacktop(stack)); goto C3_010_SAME_EX; /**/ C3_011_NUMBER_END: /*002*/ if(!feof(infile)) alfeof=get_token(infile,token); goto C3_011_NUMBER_END_EX; /**/ C2_001_FORMAT_OR_STOP: goto C2_002_POSS_FORMAT; C2_002_POSS_FORMAT_EX: goto C2_006_NEXT; C2_006_NEXT_EX: C2_001_FORMAT_OR_STOP_A: switch(g2_001_FORMAT_OR_STOP_A){ case 0 : goto C2_001_EXIT01;break; case 1 : goto C2_001_EXIT02;break; } /**/ C2_002_POSS_FORMAT: if(!( /*C06*/ (token->token_type==FULLSTOP) )) goto C2_003_FORMAT; if(( /*C06*/ (token->token_type==FULLSTOP) )) goto C2_005_FULLSTOP; C2_003_FORMAT_EX: C2_005_FULLSTOP_EX: goto C2_002_POSS_FORMAT_EX; /**/ C2_003_FORMAT: goto C2_004_FORMAT_SUBTREE; C2_004_FORMAT_SUBTREE_EX: goto C2_003_FORMAT_EX; /**/ C2_004_FORMAT_SUBTREE: g4_001_FORMAT_SUBTREE_A=0; goto C4_001_FORMAT_SUBTREE; C4_001_EXIT02: goto C2_004_FORMAT_SUBTREE_EX; /**/ C2_005_FULLSTOP: /*009*/ current->info->type=QUALIFIER; goto C2_005_FULLSTOP_EX; /**/ C2_006_NEXT: /*002*/ if(!feof(infile)) alfeof=get_token(infile,token); goto C2_006_NEXT_EX; /**/ C5_001_NINE_SUBTREE: goto C5_002_NINE_BODY; C5_002_NINE_BODY_EX: C5_001_NINE_SUBTREE_A: switch(g5_001_NINE_SUBTREE_A){ case 0 : goto C5_001_EXIT01;break; } /**/ C5_002_NINE_BODY: C5_003_NINE_CHAR_EX: if(!( /*C06*/ (token->token_type==FULLSTOP) )) goto C5_003_NINE_CHAR; goto C5_002_NINE_BODY_EX; /**/ C5_003_NINE_CHAR: goto C5_004_PIECES; C5_004_PIECES_EX: goto C5_017_END; C5_017_END_EX: goto C5_003_NINE_CHAR_EX; /**/ C5_004_PIECES: if(( /*C10*/ (token->token_type==OPEN_BRACE) )) goto C5_005_BRACE_N9; if(( /*C08*/ (*pointer=='9') )) goto C5_012_ONLY_9; C5_005_BRACE_N9_EX: C5_012_ONLY_9_EX: goto C5_004_PIECES_EX; /**/ C5_005_BRACE_N9: goto C5_006_OPEN_BRACE; C5_006_OPEN_BRACE_EX: goto C5_007_N9; C5_007_N9_EX: goto C5_011_CLOSE_BRAC_E; C5_011_CLOSE_BRAC_E_EX: goto C5_005_BRACE_N9_EX; /**/ C5_006_OPEN_BRACE: /*020*/ pointer2=count_string; /*002*/ if(!feof(infile)) alfeof=get_token(infile,token); /*016*/ pointer=token->value.string; goto C5_006_OPEN_BRACE_EX; /**/ C5_007_N9: goto C5_008_NUM_CHARS; C5_008_NUM_CHARS_EX: goto C5_010_NUM_END; C5_010_NUM_END_EX: goto C5_007_N9_EX; /**/ C5_008_NUM_CHARS: C5_009_NUM_CHAR_EX: if(!( /*C07*/ (*pointer=='\0') )) goto C5_009_NUM_CHAR; goto C5_008_NUM_CHARS_EX; /**/ C5_009_NUM_CHAR: /*019*/ *pointer2=*pointer; pointer++; pointer2++; goto C5_009_NUM_CHAR_EX; /**/ C5_010_NUM_END: /*021*/ *pointer2='\0'; number_of+=str_to_int(count_string); /*002*/ if(!feof(infile)) alfeof=get_token(infile,token); goto C5_010_NUM_END_EX; /**/ C5_011_CLOSE_BRAC_E: /*002*/ if(!feof(infile)) alfeof=get_token(infile,token); goto C5_011_CLOSE_BRAC_E_EX; /**/ C5_012_ONLY_9: goto C5_013_ONLY9START; C5_013_ONLY9START_EX: goto C5_014_ONLY9BODY; C5_014_ONLY9BODY_EX: goto C5_016_ONLY_NINE_END; C5_016_ONLY_NINE_END_EX: goto C5_012_ONLY_9_EX; /**/ C5_013_ONLY9START: /*018*/ number_of++; goto C5_013_ONLY9START_EX; /**/ C5_014_ONLY9BODY: C5_015_NINE_EX: if(!( /*C07*/ (*pointer=='\0') )) goto C5_015_NINE; goto C5_014_ONLY9BODY_EX; /**/ C5_015_NINE: /*018*/ number_of++; /*017*/ pointer++; /*026*/ current->info->data_c=NULL; current->info->data_n=0; goto C5_015_NINE_EX; /**/ C5_016_ONLY_NINE_END: /*002*/ if(!feof(infile)) alfeof=get_token(infile,token); goto C5_016_ONLY_NINE_END_EX; /**/ C5_017_END: /*016*/ pointer=token->value.string; goto C5_017_END_EX; /**/ C6_001_X_SUBTREE: goto C6_002_X_BODY; C6_002_X_BODY_EX: C6_001_X_SUBTREE_A: switch(g6_001_X_SUBTREE_A){ case 0 : goto C6_001_EXIT01;break; } /**/ C6_002_X_BODY: C6_003_X_CHAR_EX: if(!( /*C06*/ (token->token_type==FULLSTOP) )) goto C6_003_X_CHAR; goto C6_002_X_BODY_EX; /**/ C6_003_X_CHAR: goto C6_004_PIECES; C6_004_PIECES_EX: goto C6_016_END; C6_016_END_EX: goto C6_003_X_CHAR_EX; /**/ C6_004_PIECES: if(( /*C10*/ (token->token_type==OPEN_BRACE) )) goto C6_005_BRACE_NX; if(( /*C09*/ (*pointer=='X') )) goto C6_012_ONLY_X; C6_005_BRACE_NX_EX: C6_012_ONLY_X_EX: goto C6_004_PIECES_EX; /**/ C6_005_BRACE_NX: goto C6_006_OPEN_BRACE; C6_006_OPEN_BRACE_EX: goto C6_007_NX; C6_007_NX_EX: goto C6_011_CLOSE_BRAC_E; C6_011_CLOSE_BRAC_E_EX: goto C6_005_BRACE_NX_EX; /**/ C6_006_OPEN_BRACE: /*020*/ pointer2=count_string; /*002*/ if(!feof(infile)) alfeof=get_token(infile,token); /*016*/ pointer=token->value.string; goto C6_006_OPEN_BRACE_EX; /**/ C6_007_NX: goto C6_008_NUM_CHARS; C6_008_NUM_CHARS_EX: goto C6_010_NUM_END; C6_010_NUM_END_EX: goto C6_007_NX_EX; /**/ C6_008_NUM_CHARS: C6_009_NUM_CHAR_EX: if(!( /*C07*/ (*pointer=='\0') )) goto C6_009_NUM_CHAR; goto C6_008_NUM_CHARS_EX; /**/ C6_009_NUM_CHAR: /*019*/ *pointer2=*pointer; pointer++; pointer2++; goto C6_009_NUM_CHAR_EX; /**/ C6_010_NUM_END: /*021*/ *pointer2='\0'; number_of+=str_to_int(count_string); /*002*/ if(!feof(infile)) alfeof=get_token(infile,token); goto C6_010_NUM_END_EX; /**/ C6_011_CLOSE_BRAC_E: /*002*/ if(!feof(infile)) alfeof=get_token(infile,token); goto C6_011_CLOSE_BRAC_E_EX; /**/ C6_012_ONLY_X: goto C6_013_ONLYXBODY; C6_013_ONLYXBODY_EX: goto C6_015_ONLYXEND; C6_015_ONLYXEND_EX: goto C6_012_ONLY_X_EX; /**/ C6_013_ONLYXBODY: C6_014_X_EX: if(!( /*C07*/ (*pointer=='\0') )) goto C6_014_X; goto C6_013_ONLYXBODY_EX; /**/ C6_014_X: /*018*/ number_of++; /*017*/ pointer++; /*024*/ current->info->data_c=(char *)malloc(number_of+1); current->info->data_c[0]='\0'; /*025*/ current->info->data_n=number_of; goto C6_014_X_EX; /**/ C6_015_ONLYXEND: /*002*/ if(!feof(infile)) alfeof=get_token(infile,token); goto C6_015_ONLYXEND_EX; /**/ C6_016_END: /*016*/ pointer=token->value.string; goto C6_016_END_EX; /**/ /* Data Analysis Map*/ /**/ /* ------------- Data Analysis By -------------*/ /**/ /* BOX TYPE OPERATION ALLOCATION*/ /* Tree name: GENERATE-SYMBOL*/ /**/ /* Leaf : 10 Operations: 21*/ /* Quits : 0*/ /* Selections: 1*/ /* Sequences : 5*/ /* Iterations: 2*/ /* Backtracks: 0*/ /* Subtrees : 3 --> FORMAT_OR-STOP*/ /* LEVEL-NUMBER*/ /* FORMAT_OR-STOP*/ /**/ /* Tree name: FORMAT-SUBTREE*/ /**/ /* Leaf : 4 Operations: 9*/ /* Quits : 0*/ /* Selections: 1*/ /* Sequences : 3*/ /* Iterations: 0*/ /* Backtracks: 0*/ /* Subtrees : 2 --> NINE-SUBTREE*/ /* X_SUBTREE*/ /**/ /* Tree name: LEVEL-NUMBER*/ /**/ /* Leaf : 7 Operations: 6*/ /* Quits : 0*/ /* Selections: 1*/ /* Sequences : 2*/ /* Iterations: 1*/ /* Backtracks: 0*/ /* Subtrees : 0*/ /**/ /* Tree name: FORMAT_OR-STOP*/ /**/ /* Leaf : 2 Operations: 2*/ /* Quits : 0*/ /* Selections: 1*/ /* Sequences : 2*/ /* Iterations: 0*/ /* Backtracks: 0*/ /* Subtrees : 1 --> FORMAT-SUBTREE*/ /**/ /* Tree name: NINE-SUBTREE*/ /**/ /* Leaf : 8 Operations: 13*/ /* Quits : 0*/ /* Selections: 1*/ /* Sequences : 5*/ /* Iterations: 3*/ /* Backtracks: 0*/ /* Subtrees : 0*/ /**/ /* Tree name: X_SUBTREE*/ /**/ /* Leaf : 7 Operations: 13*/ /* Quits : 0*/ /* Selections: 1*/ /* Sequences : 5*/ /* Iterations: 3*/ /* Backtracks: 0*/ /* Subtrees : 0*/ /**/ /**/ /**/ veryend: ; }
static bool bp_script_eval(GPtrArray *stack, const GString *script, const struct bp_tx *txTo, unsigned int nIn, unsigned int flags, int nHashType) { struct const_buffer pc = { script->str, script->len }; struct const_buffer pend = { script->str + script->len, 0 }; struct const_buffer pbegincodehash = { script->str, script->len }; struct bscript_op op; bool rc = false; GByteArray *vfExec = g_byte_array_new(); GPtrArray *altstack = g_ptr_array_new_with_free_func( (GDestroyNotify) buffer_free); BIGNUM bn; BN_init(&bn); if (script->len > 10000) goto out; bool fStrictEncodings = flags & SCRIPT_VERIFY_STRICTENC; unsigned int nOpCount = 0; struct bscript_parser bp; bsp_start(&bp, &pc); while (pc.p < pend.p) { bool fExec = !count_false(vfExec); if (!bsp_getop(&op, &bp)) goto out; enum opcodetype opcode = op.op; if (op.data.len > 520) goto out; if (opcode > OP_16 && ++nOpCount > 201) goto out; if (disabled_op[opcode]) goto out; if (fExec && is_bsp_pushdata(opcode)) stack_push(stack, (struct buffer *) &op.data); else if (fExec || (OP_IF <= opcode && opcode <= OP_ENDIF)) switch (opcode) { // // Push value // case OP_1NEGATE: case OP_1: case OP_2: case OP_3: case OP_4: case OP_5: case OP_6: case OP_7: case OP_8: case OP_9: case OP_10: case OP_11: case OP_12: case OP_13: case OP_14: case OP_15: case OP_16: bn_set_int(&bn, (int)opcode - (int)(OP_1 - 1)); stack_push_str(stack, bn_getvch(&bn)); break; // // Control // case OP_NOP: case OP_NOP1: case OP_NOP2: case OP_NOP3: case OP_NOP4: case OP_NOP5: case OP_NOP6: case OP_NOP7: case OP_NOP8: case OP_NOP9: case OP_NOP10: break; case OP_IF: case OP_NOTIF: { // <expression> if [statements] [else [statements]] endif bool fValue = false; if (fExec) { if (stack->len < 1) goto out; struct buffer *vch = stacktop(stack, -1); fValue = CastToBool(vch); if (opcode == OP_NOTIF) fValue = !fValue; popstack(stack); } guint8 vc = (guint8) fValue; g_byte_array_append(vfExec, &vc, 1); break; } case OP_ELSE: { if (vfExec->len == 0) goto out; guint8 *v = &vfExec->data[vfExec->len - 1]; *v = !(*v); break; } case OP_ENDIF: if (vfExec->len == 0) goto out; g_byte_array_remove_index(vfExec, vfExec->len - 1); break; case OP_VERIFY: { if (stack->len < 1) goto out; bool fValue = CastToBool(stacktop(stack, -1)); if (fValue) popstack(stack); else goto out; break; } case OP_RETURN: goto out; // // Stack ops // case OP_TOALTSTACK: if (stack->len < 1) goto out; stack_push(altstack, stacktop(stack, -1)); popstack(stack); break; case OP_FROMALTSTACK: if (altstack->len < 1) goto out; stack_push(stack, stacktop(altstack, -1)); popstack(altstack); break; case OP_2DROP: // (x1 x2 -- ) if (stack->len < 2) goto out; popstack(stack); popstack(stack); break; case OP_2DUP: { // (x1 x2 -- x1 x2 x1 x2) if (stack->len < 2) goto out; struct buffer *vch1 = stacktop(stack, -2); struct buffer *vch2 = stacktop(stack, -1); stack_push(stack, vch1); stack_push(stack, vch2); break; } case OP_3DUP: { // (x1 x2 x3 -- x1 x2 x3 x1 x2 x3) if (stack->len < 3) goto out; struct buffer *vch1 = stacktop(stack, -3); struct buffer *vch2 = stacktop(stack, -2); struct buffer *vch3 = stacktop(stack, -1); stack_push(stack, vch1); stack_push(stack, vch2); stack_push(stack, vch3); break; } case OP_2OVER: { // (x1 x2 x3 x4 -- x1 x2 x3 x4 x1 x2) if (stack->len < 4) goto out; struct buffer *vch1 = stacktop(stack, -4); struct buffer *vch2 = stacktop(stack, -3); stack_push(stack, vch1); stack_push(stack, vch2); break; } case OP_2ROT: { // (x1 x2 x3 x4 x5 x6 -- x3 x4 x5 x6 x1 x2) if (stack->len < 6) goto out; struct buffer *vch1 = stack_take(stack, -6); struct buffer *vch2 = stack_take(stack, -5); g_ptr_array_remove_range(stack, stack->len - 6, 2); stack_push(stack, vch1); stack_push(stack, vch2); break; } case OP_2SWAP: // (x1 x2 x3 x4 -- x3 x4 x1 x2) if (stack->len < 4) goto out; stack_swap(stack, -4, -2); stack_swap(stack, -3, -1); break; case OP_IFDUP: { // (x - 0 | x x) if (stack->len < 1) goto out; struct buffer *vch = stacktop(stack, -1); if (CastToBool(vch)) stack_push(stack, vch); break; } case OP_DEPTH: // -- stacksize BN_set_word(&bn, stack->len); stack_push_str(stack, bn_getvch(&bn)); break; case OP_DROP: // (x -- ) if (stack->len < 1) goto out; popstack(stack); break; case OP_DUP: { // (x -- x x) if (stack->len < 1) goto out; struct buffer *vch = stacktop(stack, -1); stack_push(stack, vch); break; } case OP_NIP: // (x1 x2 -- x2) if (stack->len < 2) goto out; g_ptr_array_remove_index(stack, stack->len - 2); break; case OP_OVER: { // (x1 x2 -- x1 x2 x1) if (stack->len < 2) goto out; struct buffer *vch = stacktop(stack, -2); stack_push(stack, vch); break; } case OP_PICK: case OP_ROLL: { // (xn ... x2 x1 x0 n - xn ... x2 x1 x0 xn) // (xn ... x2 x1 x0 n - ... x2 x1 x0 xn) if (stack->len < 2) goto out; int n = stackint(stack, -1); popstack(stack); if (n < 0 || n >= (int)stack->len) goto out; struct buffer *vch = stacktop(stack, -n-1); if (opcode == OP_ROLL) { vch = buffer_copy(vch->p, vch->len); g_ptr_array_remove_index(stack, stack->len - n - 1); stack_push_nocopy(stack, vch); } else stack_push(stack, vch); break; } case OP_ROT: { // (x1 x2 x3 -- x2 x3 x1) // x2 x1 x3 after first swap // x2 x3 x1 after second swap if (stack->len < 3) goto out; stack_swap(stack, -3, -2); stack_swap(stack, -2, -1); break; } case OP_SWAP: { // (x1 x2 -- x2 x1) if (stack->len < 2) goto out; stack_swap(stack, -2, -1); break; } case OP_TUCK: { // (x1 x2 -- x2 x1 x2) if (stack->len < 2) goto out; struct buffer *vch = stacktop(stack, -1); stack_insert(stack, vch, -2); break; } case OP_SIZE: { // (in -- in size) if (stack->len < 1) goto out; struct buffer *vch = stacktop(stack, -1); BN_set_word(&bn, vch->len); stack_push_str(stack, bn_getvch(&bn)); break; } case OP_EQUAL: case OP_EQUALVERIFY: { // (x1 x2 - bool) if (stack->len < 2) goto out; struct buffer *vch1 = stacktop(stack, -2); struct buffer *vch2 = stacktop(stack, -1); bool fEqual = ((vch1->len == vch2->len) && memcmp(vch1->p, vch2->p, vch1->len) == 0); // OP_NOTEQUAL is disabled because it would be too easy to say // something like n != 1 and have some wiseguy pass in 1 with extra // zero bytes after it (numerically, 0x01 == 0x0001 == 0x000001) //if (opcode == OP_NOTEQUAL) // fEqual = !fEqual; popstack(stack); popstack(stack); stack_push_char(stack, fEqual ? 1 : 0); if (opcode == OP_EQUALVERIFY) { if (fEqual) popstack(stack); else goto out; } break; } // // Numeric // case OP_1ADD: case OP_1SUB: case OP_NEGATE: case OP_ABS: case OP_NOT: case OP_0NOTEQUAL: { // (in -- out) if (stack->len < 1) goto out; if (!CastToBigNum(&bn, stacktop(stack, -1))) goto out; switch (opcode) { case OP_1ADD: BN_add_word(&bn, 1); break; case OP_1SUB: BN_sub_word(&bn, 1); break; case OP_NEGATE: BN_set_negative(&bn, !BN_is_negative(&bn)); break; case OP_ABS: if (BN_is_negative(&bn)) BN_set_negative(&bn, 0); break; case OP_NOT: BN_set_word(&bn, BN_is_zero(&bn) ? 1 : 0); break; case OP_0NOTEQUAL: BN_set_word(&bn, BN_is_zero(&bn) ? 0 : 1); break; default: // impossible goto out; } popstack(stack); stack_push_str(stack, bn_getvch(&bn)); break; } case OP_ADD: case OP_SUB: case OP_BOOLAND: case OP_BOOLOR: case OP_NUMEQUAL: case OP_NUMEQUALVERIFY: case OP_NUMNOTEQUAL: case OP_LESSTHAN: case OP_GREATERTHAN: case OP_LESSTHANOREQUAL: case OP_GREATERTHANOREQUAL: case OP_MIN: case OP_MAX: { // (x1 x2 -- out) if (stack->len < 2) goto out; BIGNUM bn1, bn2; BN_init(&bn1); BN_init(&bn2); if (!CastToBigNum(&bn1, stacktop(stack, -2)) || !CastToBigNum(&bn2, stacktop(stack, -1))) { BN_clear_free(&bn1); BN_clear_free(&bn2); goto out; } switch (opcode) { case OP_ADD: BN_add(&bn, &bn1, &bn2); break; case OP_SUB: BN_sub(&bn, &bn1, &bn2); break; case OP_BOOLAND: BN_set_word(&bn, (!BN_is_zero(&bn1) && !BN_is_zero(&bn2)) ? 1 : 0); break; case OP_BOOLOR: BN_set_word(&bn, (!BN_is_zero(&bn1) || !BN_is_zero(&bn2)) ? 1 : 0); break; case OP_NUMEQUAL: case OP_NUMEQUALVERIFY: BN_set_word(&bn, (BN_cmp(&bn1, &bn2) == 0) ? 1 : 0); break; case OP_NUMNOTEQUAL: BN_set_word(&bn, (BN_cmp(&bn1, &bn2) != 0) ? 1 : 0); break; case OP_LESSTHAN: BN_set_word(&bn, (BN_cmp(&bn1, &bn2) < 0) ? 1 : 0); break; case OP_GREATERTHAN: BN_set_word(&bn, (BN_cmp(&bn1, &bn2) > 0) ? 1 : 0); break; case OP_LESSTHANOREQUAL: BN_set_word(&bn, (BN_cmp(&bn1, &bn2) <= 0) ? 1 : 0); break; case OP_GREATERTHANOREQUAL: BN_set_word(&bn, (BN_cmp(&bn1, &bn2) >= 0) ? 1 : 0); break; case OP_MIN: if (BN_cmp(&bn1, &bn2) < 0) BN_copy(&bn, &bn1); else BN_copy(&bn, &bn2); break; case OP_MAX: if (BN_cmp(&bn1, &bn2) > 0) BN_copy(&bn, &bn1); else BN_copy(&bn, &bn2); break; default: // impossible break; } popstack(stack); popstack(stack); stack_push_str(stack, bn_getvch(&bn)); BN_clear_free(&bn1); BN_clear_free(&bn2); if (opcode == OP_NUMEQUALVERIFY) { if (CastToBool(stacktop(stack, -1))) popstack(stack); else goto out; } break; } case OP_WITHIN: { // (x min max -- out) if (stack->len < 3) goto out; BIGNUM bn1, bn2, bn3; BN_init(&bn1); BN_init(&bn2); BN_init(&bn3); bool rc1 = CastToBigNum(&bn1, stacktop(stack, -3)); bool rc2 = CastToBigNum(&bn2, stacktop(stack, -2)); bool rc3 = CastToBigNum(&bn3, stacktop(stack, -1)); bool fValue = (BN_cmp(&bn2, &bn1) <= 0 && BN_cmp(&bn1, &bn3) < 0); popstack(stack); popstack(stack); popstack(stack); stack_push_char(stack, fValue ? 1 : 0); BN_clear_free(&bn1); BN_clear_free(&bn2); BN_clear_free(&bn3); if (!rc1 || !rc2 || !rc3) goto out; break; } // // Crypto // case OP_RIPEMD160: case OP_SHA1: case OP_SHA256: case OP_HASH160: case OP_HASH256: { // (in -- hash) if (stack->len < 1) goto out; struct buffer *vch = stacktop(stack, -1); unsigned int hashlen; unsigned char md[32]; switch (opcode) { case OP_RIPEMD160: hashlen = 20; RIPEMD160(vch->p, vch->len, md); break; case OP_SHA1: hashlen = 20; SHA1(vch->p, vch->len, md); break; case OP_SHA256: hashlen = 32; SHA256(vch->p, vch->len, md); break; case OP_HASH160: hashlen = 20; bu_Hash160(md, vch->p, vch->len); break; case OP_HASH256: hashlen = 32; bu_Hash(md, vch->p, vch->len); break; default: // impossible goto out; } popstack(stack); struct buffer buf = { md, hashlen }; stack_push(stack, &buf); break; } case OP_CODESEPARATOR: // Hash starts after the code separator memcpy(&pbegincodehash, &pc, sizeof(pc)); break; case OP_CHECKSIG: case OP_CHECKSIGVERIFY: { // (sig pubkey -- bool) if (stack->len < 2) goto out; struct buffer *vchSig = stacktop(stack, -2); struct buffer *vchPubKey = stacktop(stack, -1); ////// debug print //PrintHex(vchSig.begin(), vchSig.end(), "sig: %s\n"); //PrintHex(vchPubKey.begin(), vchPubKey.end(), "pubkey: %s\n"); // Subset of script starting at the most recent codeseparator GString *scriptCode = g_string_sized_new(pbegincodehash.len); g_string_append_len(scriptCode, pbegincodehash.p, pbegincodehash.len); // Drop the signature, since there's no way for // a signature to sign itself string_find_del(scriptCode, vchSig); bool fSuccess = (!fStrictEncodings || (IsCanonicalSignature(vchSig) && IsCanonicalPubKey(vchPubKey))); if (fSuccess) fSuccess = bp_checksig(vchSig, vchPubKey, scriptCode, txTo, nIn, nHashType); g_string_free(scriptCode, TRUE); popstack(stack); popstack(stack); stack_push_char(stack, fSuccess ? 1 : 0); if (opcode == OP_CHECKSIGVERIFY) { if (fSuccess) popstack(stack); else goto out; } break; } case OP_CHECKMULTISIG: case OP_CHECKMULTISIGVERIFY: { // ([sig ...] num_of_signatures [pubkey ...] num_of_pubkeys -- bool) int i = 1; if ((int)stack->len < i) goto out; int nKeysCount = stackint(stack, -i); if (nKeysCount < 0 || nKeysCount > 20) goto out; nOpCount += nKeysCount; if (nOpCount > 201) goto out; int ikey = ++i; i += nKeysCount; if ((int)stack->len < i) goto out; int nSigsCount = stackint(stack, -i); if (nSigsCount < 0 || nSigsCount > nKeysCount) goto out; int isig = ++i; i += nSigsCount; if ((int)stack->len < i) goto out; // Subset of script starting at the most recent codeseparator GString *scriptCode = g_string_sized_new(pbegincodehash.len); g_string_append_len(scriptCode, pbegincodehash.p, pbegincodehash.len); // Drop the signatures, since there's no way for // a signature to sign itself int k; for (k = 0; k < nSigsCount; k++) { struct buffer *vchSig =stacktop(stack, -isig-k); string_find_del(scriptCode, vchSig); } bool fSuccess = true; while (fSuccess && nSigsCount > 0) { struct buffer *vchSig = stacktop(stack, -isig); struct buffer *vchPubKey = stacktop(stack, -ikey); // Check signature bool fOk = (!fStrictEncodings || (IsCanonicalSignature(vchSig) && IsCanonicalPubKey(vchPubKey))); if (fOk) fOk = bp_checksig(vchSig, vchPubKey, scriptCode, txTo, nIn, nHashType); if (fOk) { isig++; nSigsCount--; } ikey++; nKeysCount--; // If there are more signatures left than keys left, // then too many signatures have failed if (nSigsCount > nKeysCount) fSuccess = false; } g_string_free(scriptCode, TRUE); while (i-- > 0) popstack(stack); stack_push_char(stack, fSuccess ? 1 : 0); if (opcode == OP_CHECKMULTISIGVERIFY) { if (fSuccess) popstack(stack); else goto out; } break; } default: goto out; } if (stack->len + altstack->len > 1000) goto out; } rc = (vfExec->len == 0 && bp.error == false); out: BN_clear_free(&bn); g_ptr_array_free(altstack, TRUE); g_byte_array_unref(vfExec); return rc; }
bool bp_script_verify(const GString *scriptSig, const GString *scriptPubKey, const struct bp_tx *txTo, unsigned int nIn, unsigned int flags, int nHashType) { bool rc = false; GPtrArray *stack = g_ptr_array_new_with_free_func( (GDestroyNotify) buffer_free); GString *pubkey2 = NULL; GPtrArray *stackCopy = NULL; if (!bp_script_eval(stack, scriptSig, txTo, nIn, flags, nHashType)) goto out; if (flags & SCRIPT_VERIFY_P2SH) { stackCopy = g_ptr_array_new_full(stack->len, (GDestroyNotify) buffer_free); stack_copy(stackCopy, stack); } if (!bp_script_eval(stack, scriptPubKey, txTo, nIn, flags, nHashType)) goto out; if (stack->len == 0) goto out; if (CastToBool(stacktop(stack, -1)) == false) goto out; if ((flags & SCRIPT_VERIFY_P2SH) && is_bsp_p2sh_str(scriptPubKey)) { struct const_buffer sigbuf = { scriptSig->str, scriptSig->len }; if (!is_bsp_pushonly(&sigbuf)) goto out; if (stackCopy->len < 1) goto out; struct buffer *pubkey2_buf = stack_take(stackCopy, -1); popstack(stackCopy); GString *pubkey2 = g_string_sized_new(pubkey2_buf->len); g_string_append_len(pubkey2, pubkey2_buf->p, pubkey2_buf->len); buffer_free(pubkey2_buf); bool rc2 = bp_script_eval(stackCopy, pubkey2, txTo, nIn, flags, nHashType); g_string_free(pubkey2, TRUE); if (!rc2) goto out; if (stackCopy->len == 0) goto out; if (CastToBool(stacktop(stackCopy, -1)) == false) goto out; } rc = true; out: g_ptr_array_free(stack, TRUE); if (pubkey2) g_string_free(pubkey2, TRUE); if (stackCopy) g_ptr_array_free(stackCopy, TRUE); return rc; }
bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, const CTransaction& txTo, unsigned int nIn, int nHashType) { CAutoBN_CTX pctx; CScript::const_iterator pc = script.begin(); CScript::const_iterator pend = script.end(); CScript::const_iterator pbegincodehash = script.begin(); opcodetype opcode; valtype vchPushValue; vector<bool> vfExec; vector<valtype> altstack; if (script.size() > 10000) return false; int nOpCount = 0; try { while (pc < pend) { bool fExec = !count(vfExec.begin(), vfExec.end(), false); // // Read instruction // if (!script.GetOp(pc, opcode, vchPushValue)) return false; if (vchPushValue.size() > 520) return false; if (opcode > OP_16 && ++nOpCount > 201) return false; if (opcode == OP_CAT || opcode == OP_SUBSTR || opcode == OP_LEFT || opcode == OP_RIGHT || opcode == OP_INVERT || opcode == OP_AND || opcode == OP_OR || opcode == OP_XOR || opcode == OP_2MUL || opcode == OP_2DIV || opcode == OP_MUL || opcode == OP_DIV || opcode == OP_MOD || opcode == OP_LSHIFT || opcode == OP_RSHIFT) return false; if (fExec && 0 <= opcode && opcode <= OP_PUSHDATA4) stack.push_back(vchPushValue); else if (fExec || (OP_IF <= opcode && opcode <= OP_ENDIF)) switch (opcode) { // // Push value // case OP_1NEGATE: case OP_1: case OP_2: case OP_3: case OP_4: case OP_5: case OP_6: case OP_7: case OP_8: case OP_9: case OP_10: case OP_11: case OP_12: case OP_13: case OP_14: case OP_15: case OP_16: { // ( -- value) CBigNum bn((int)opcode - (int)(OP_1 - 1)); stack.push_back(bn.getvch()); } break; // // Control // case OP_NOP: case OP_NOP1: case OP_NOP2: case OP_NOP3: case OP_NOP4: case OP_NOP5: case OP_NOP6: case OP_NOP7: case OP_NOP8: case OP_NOP9: case OP_NOP10: break; case OP_IF: case OP_NOTIF: { // <expression> if [statements] [else [statements]] endif bool fValue = false; if (fExec) { if (stack.size() < 1) return false; valtype& vch = stacktop(-1); fValue = CastToBool(vch); if (opcode == OP_NOTIF) fValue = !fValue; popstack(stack); } vfExec.push_back(fValue); } break; case OP_ELSE: { if (vfExec.empty()) return false; vfExec.back() = !vfExec.back(); } break; case OP_ENDIF: { if (vfExec.empty()) return false; vfExec.pop_back(); } break; case OP_VERIFY: { // (true -- ) or // (false -- false) and return if (stack.size() < 1) return false; bool fValue = CastToBool(stacktop(-1)); if (fValue) popstack(stack); else return false; } break; case OP_RETURN: { return false; } break; // // Stack ops // case OP_TOALTSTACK: { if (stack.size() < 1) return false; altstack.push_back(stacktop(-1)); popstack(stack); } break; case OP_FROMALTSTACK: { if (altstack.size() < 1) return false; stack.push_back(altstacktop(-1)); popstack(altstack); } break; case OP_2DROP: { // (x1 x2 -- ) if (stack.size() < 2) return false; popstack(stack); popstack(stack); } break; case OP_2DUP: { // (x1 x2 -- x1 x2 x1 x2) if (stack.size() < 2) return false; valtype vch1 = stacktop(-2); valtype vch2 = stacktop(-1); stack.push_back(vch1); stack.push_back(vch2); } break; case OP_3DUP: { // (x1 x2 x3 -- x1 x2 x3 x1 x2 x3) if (stack.size() < 3) return false; valtype vch1 = stacktop(-3); valtype vch2 = stacktop(-2); valtype vch3 = stacktop(-1); stack.push_back(vch1); stack.push_back(vch2); stack.push_back(vch3); } break; case OP_2OVER: { // (x1 x2 x3 x4 -- x1 x2 x3 x4 x1 x2) if (stack.size() < 4) return false; valtype vch1 = stacktop(-4); valtype vch2 = stacktop(-3); stack.push_back(vch1); stack.push_back(vch2); } break; case OP_2ROT: { // (x1 x2 x3 x4 x5 x6 -- x3 x4 x5 x6 x1 x2) if (stack.size() < 6) return false; valtype vch1 = stacktop(-6); valtype vch2 = stacktop(-5); stack.erase(stack.end()-6, stack.end()-4); stack.push_back(vch1); stack.push_back(vch2); } break; case OP_2SWAP: { // (x1 x2 x3 x4 -- x3 x4 x1 x2) if (stack.size() < 4) return false; swap(stacktop(-4), stacktop(-2)); swap(stacktop(-3), stacktop(-1)); } break; case OP_IFDUP: { // (x - 0 | x x) if (stack.size() < 1) return false; valtype vch = stacktop(-1); if (CastToBool(vch)) stack.push_back(vch); } break; case OP_DEPTH: { // -- stacksize CBigNum bn(stack.size()); stack.push_back(bn.getvch()); } break; case OP_DROP: { // (x -- ) if (stack.size() < 1) return false; popstack(stack); } break; case OP_DUP: { // (x -- x x) if (stack.size() < 1) return false; valtype vch = stacktop(-1); stack.push_back(vch); } break; case OP_NIP: { // (x1 x2 -- x2) if (stack.size() < 2) return false; stack.erase(stack.end() - 2); } break; case OP_OVER: { // (x1 x2 -- x1 x2 x1) if (stack.size() < 2) return false; valtype vch = stacktop(-2); stack.push_back(vch); } break; case OP_PICK: case OP_ROLL: { // (xn ... x2 x1 x0 n - xn ... x2 x1 x0 xn) // (xn ... x2 x1 x0 n - ... x2 x1 x0 xn) if (stack.size() < 2) return false; int n = CastToBigNum(stacktop(-1)).getint(); popstack(stack); if (n < 0 || n >= stack.size()) return false; valtype vch = stacktop(-n-1); if (opcode == OP_ROLL) stack.erase(stack.end()-n-1); stack.push_back(vch); } break; case OP_ROT: { // (x1 x2 x3 -- x2 x3 x1) // x2 x1 x3 after first swap // x2 x3 x1 after second swap if (stack.size() < 3) return false; swap(stacktop(-3), stacktop(-2)); swap(stacktop(-2), stacktop(-1)); } break; case OP_SWAP: { // (x1 x2 -- x2 x1) if (stack.size() < 2) return false; swap(stacktop(-2), stacktop(-1)); } break; case OP_TUCK: { // (x1 x2 -- x2 x1 x2) if (stack.size() < 2) return false; valtype vch = stacktop(-1); stack.insert(stack.end()-2, vch); } break; // // Splice ops // case OP_CAT: { // (x1 x2 -- out) if (stack.size() < 2) return false; valtype& vch1 = stacktop(-2); valtype& vch2 = stacktop(-1); vch1.insert(vch1.end(), vch2.begin(), vch2.end()); popstack(stack); if (stacktop(-1).size() > 520) return false; } break; case OP_SUBSTR: { // (in begin size -- out) if (stack.size() < 3) return false; valtype& vch = stacktop(-3); int nBegin = CastToBigNum(stacktop(-2)).getint(); int nEnd = nBegin + CastToBigNum(stacktop(-1)).getint(); if (nBegin < 0 || nEnd < nBegin) return false; if (nBegin > vch.size()) nBegin = vch.size(); if (nEnd > vch.size()) nEnd = vch.size(); vch.erase(vch.begin() + nEnd, vch.end()); vch.erase(vch.begin(), vch.begin() + nBegin); popstack(stack); popstack(stack); } break; case OP_LEFT: case OP_RIGHT: { // (in size -- out) if (stack.size() < 2) return false; valtype& vch = stacktop(-2); int nSize = CastToBigNum(stacktop(-1)).getint(); if (nSize < 0) return false; if (nSize > vch.size()) nSize = vch.size(); if (opcode == OP_LEFT) vch.erase(vch.begin() + nSize, vch.end()); else vch.erase(vch.begin(), vch.end() - nSize); popstack(stack); } break; case OP_SIZE: { // (in -- in size) if (stack.size() < 1) return false; CBigNum bn(stacktop(-1).size()); stack.push_back(bn.getvch()); } break; // // Bitwise logic // case OP_INVERT: { // (in - out) if (stack.size() < 1) return false; valtype& vch = stacktop(-1); for (int i = 0; i < vch.size(); i++) vch[i] = ~vch[i]; } break; case OP_AND: case OP_OR: case OP_XOR: { // (x1 x2 - out) if (stack.size() < 2) return false; valtype& vch1 = stacktop(-2); valtype& vch2 = stacktop(-1); MakeSameSize(vch1, vch2); if (opcode == OP_AND) { for (int i = 0; i < vch1.size(); i++) vch1[i] &= vch2[i]; } else if (opcode == OP_OR) { for (int i = 0; i < vch1.size(); i++) vch1[i] |= vch2[i]; } else if (opcode == OP_XOR) { for (int i = 0; i < vch1.size(); i++) vch1[i] ^= vch2[i]; } popstack(stack); } break; case OP_EQUAL: case OP_EQUALVERIFY: //case OP_NOTEQUAL: // use OP_NUMNOTEQUAL { // (x1 x2 - bool) if (stack.size() < 2) return false; valtype& vch1 = stacktop(-2); valtype& vch2 = stacktop(-1); bool fEqual = (vch1 == vch2); // OP_NOTEQUAL is disabled because it would be too easy to say // something like n != 1 and have some wiseguy pass in 1 with extra // zero bytes after it (numerically, 0x01 == 0x0001 == 0x000001) //if (opcode == OP_NOTEQUAL) // fEqual = !fEqual; popstack(stack); popstack(stack); stack.push_back(fEqual ? vchTrue : vchFalse); if (opcode == OP_EQUALVERIFY) { if (fEqual) popstack(stack); else return false; } } break; // // Numeric // case OP_1ADD: case OP_1SUB: case OP_2MUL: case OP_2DIV: case OP_NEGATE: case OP_ABS: case OP_NOT: case OP_0NOTEQUAL: { // (in -- out) if (stack.size() < 1) return false; CBigNum bn = CastToBigNum(stacktop(-1)); switch (opcode) { case OP_1ADD: bn += bnOne; break; case OP_1SUB: bn -= bnOne; break; case OP_2MUL: bn <<= 1; break; case OP_2DIV: bn >>= 1; break; case OP_NEGATE: bn = -bn; break; case OP_ABS: if (bn < bnZero) bn = -bn; break; case OP_NOT: bn = (bn == bnZero); break; case OP_0NOTEQUAL: bn = (bn != bnZero); break; } popstack(stack); stack.push_back(bn.getvch()); } break; case OP_ADD: case OP_SUB: case OP_MUL: case OP_DIV: case OP_MOD: case OP_LSHIFT: case OP_RSHIFT: case OP_BOOLAND: case OP_BOOLOR: case OP_NUMEQUAL: case OP_NUMEQUALVERIFY: case OP_NUMNOTEQUAL: case OP_LESSTHAN: case OP_GREATERTHAN: case OP_LESSTHANOREQUAL: case OP_GREATERTHANOREQUAL: case OP_MIN: case OP_MAX: { // (x1 x2 -- out) if (stack.size() < 2) return false; CBigNum bn1 = CastToBigNum(stacktop(-2)); CBigNum bn2 = CastToBigNum(stacktop(-1)); CBigNum bn; switch (opcode) { case OP_ADD: bn = bn1 + bn2; break; case OP_SUB: bn = bn1 - bn2; break; case OP_MUL: if (!BN_mul(&bn, &bn1, &bn2, pctx)) return false; break; case OP_DIV: if (!BN_div(&bn, NULL, &bn1, &bn2, pctx)) return false; break; case OP_MOD: if (!BN_mod(&bn, &bn1, &bn2, pctx)) return false; break; case OP_LSHIFT: if (bn2 < bnZero || bn2 > CBigNum(2048)) return false; bn = bn1 << bn2.getulong(); break; case OP_RSHIFT: if (bn2 < bnZero || bn2 > CBigNum(2048)) return false; bn = bn1 >> bn2.getulong(); break; case OP_BOOLAND: bn = (bn1 != bnZero && bn2 != bnZero); break; case OP_BOOLOR: bn = (bn1 != bnZero || bn2 != bnZero); break; case OP_NUMEQUAL: bn = (bn1 == bn2); break; case OP_NUMEQUALVERIFY: bn = (bn1 == bn2); break; case OP_NUMNOTEQUAL: bn = (bn1 != bn2); break; case OP_LESSTHAN: bn = (bn1 < bn2); break; case OP_GREATERTHAN: bn = (bn1 > bn2); break; case OP_LESSTHANOREQUAL: bn = (bn1 <= bn2); break; case OP_GREATERTHANOREQUAL: bn = (bn1 >= bn2); break; case OP_MIN: bn = (bn1 < bn2 ? bn1 : bn2); break; case OP_MAX: bn = (bn1 > bn2 ? bn1 : bn2); break; } popstack(stack); popstack(stack); stack.push_back(bn.getvch()); if (opcode == OP_NUMEQUALVERIFY) { if (CastToBool(stacktop(-1))) popstack(stack); else return false; } } break; case OP_WITHIN: { // (x min max -- out) if (stack.size() < 3) return false; CBigNum bn1 = CastToBigNum(stacktop(-3)); CBigNum bn2 = CastToBigNum(stacktop(-2)); CBigNum bn3 = CastToBigNum(stacktop(-1)); bool fValue = (bn2 <= bn1 && bn1 < bn3); popstack(stack); popstack(stack); popstack(stack); stack.push_back(fValue ? vchTrue : vchFalse); } break; // // Crypto // case OP_RIPEMD160: case OP_SHA1: case OP_SHA256: case OP_HASH160: case OP_HASH256: { // (in -- hash) if (stack.size() < 1) return false; valtype& vch = stacktop(-1); valtype vchHash((opcode == OP_RIPEMD160 || opcode == OP_SHA1 || opcode == OP_HASH160) ? 20 : 32); if (opcode == OP_RIPEMD160) RIPEMD160(&vch[0], vch.size(), &vchHash[0]); else if (opcode == OP_SHA1) SHA1(&vch[0], vch.size(), &vchHash[0]); else if (opcode == OP_SHA256) SHA256(&vch[0], vch.size(), &vchHash[0]); else if (opcode == OP_HASH160) { uint160 hash160 = Hash160(vch); memcpy(&vchHash[0], &hash160, sizeof(hash160)); } else if (opcode == OP_HASH256) { uint256 hash = Hash(vch.begin(), vch.end()); memcpy(&vchHash[0], &hash, sizeof(hash)); } popstack(stack); stack.push_back(vchHash); } break; case OP_CODESEPARATOR: { // Hash starts after the code separator pbegincodehash = pc; } break; case OP_CHECKSIG: case OP_CHECKSIGVERIFY: { // (sig pubkey -- bool) if (stack.size() < 2) return false; valtype& vchSig = stacktop(-2); valtype& vchPubKey = stacktop(-1); ////// debug print //PrintHex(vchSig.begin(), vchSig.end(), "sig: %s\n"); //PrintHex(vchPubKey.begin(), vchPubKey.end(), "pubkey: %s\n"); // Subset of script starting at the most recent codeseparator CScript scriptCode(pbegincodehash, pend); // Drop the signature, since there's no way for a signature to sign itself scriptCode.FindAndDelete(CScript(vchSig)); bool fSuccess = CheckSig(vchSig, vchPubKey, scriptCode, txTo, nIn, nHashType); popstack(stack); popstack(stack); stack.push_back(fSuccess ? vchTrue : vchFalse); if (opcode == OP_CHECKSIGVERIFY) { if (fSuccess) popstack(stack); else return false; } } break; case OP_CHECKMULTISIG: case OP_CHECKMULTISIGVERIFY: { // ([sig ...] num_of_signatures [pubkey ...] num_of_pubkeys -- bool) int i = 1; if (stack.size() < i) return false; int nKeysCount = CastToBigNum(stacktop(-i)).getint(); if (nKeysCount < 0 || nKeysCount > 20) return false; nOpCount += nKeysCount; if (nOpCount > 201) return false; int ikey = ++i; i += nKeysCount; if (stack.size() < i) return false; int nSigsCount = CastToBigNum(stacktop(-i)).getint(); if (nSigsCount < 0 || nSigsCount > nKeysCount) return false; int isig = ++i; i += nSigsCount; if (stack.size() < i) return false; // Subset of script starting at the most recent codeseparator CScript scriptCode(pbegincodehash, pend); // Drop the signatures, since there's no way for a signature to sign itself for (int k = 0; k < nSigsCount; k++) { valtype& vchSig = stacktop(-isig-k); scriptCode.FindAndDelete(CScript(vchSig)); } bool fSuccess = true; while (fSuccess && nSigsCount > 0) { valtype& vchSig = stacktop(-isig); valtype& vchPubKey = stacktop(-ikey); // Check signature if (CheckSig(vchSig, vchPubKey, scriptCode, txTo, nIn, nHashType)) { isig++; nSigsCount--; } ikey++; nKeysCount--; // If there are more signatures left than keys left, // then too many signatures have failed if (nSigsCount > nKeysCount) fSuccess = false; } while (i-- > 0) popstack(stack); stack.push_back(fSuccess ? vchTrue : vchFalse); if (opcode == OP_CHECKMULTISIGVERIFY) { if (fSuccess) popstack(stack); else return false; } } break; default: return false; } // Size limits if (stack.size() + altstack.size() > 1000) return false; } } catch (...) { return false; } if (!vfExec.empty()) return false; return true; }
xlfail(char *emsg) { xlerror(emsg,stacktop()); }