Example #1
0
// OP_CHECKMULTISIG
// OP_CHECKMULTISIGVERIFY
func execCheckMultiSig(ctx *execContext, op Opcode, _ []byte) error {
	i := 1
	if ctx.stack.height() < i {
		return errStackItemMissing
	}
	kCount := int(klib.ToScriptInt(ctx.stack.top(-i)))
	if kCount < 0 || kCount > numbers.MaxMultiSigKeyCount {
		return errKeySigCountOutOfRange
	}
	ctx.opCount += kCount
	if ctx.opCount > numbers.MaxOpcodeCount {
		return errOpcodeCount
	}
	i++
	iKey := i
	i += kCount
	if ctx.stack.height() < i {
		return errStackItemMissing
	}
	sCount := int(klib.ToScriptInt(ctx.stack.top(-i)))
	if sCount < 0 || sCount > kCount {
		return errKeySigCountOutOfRange
	}
	i++
	iSig := i
	i += sCount
	if ctx.stack.height() < i {
		return errStackItemMissing
	}

	subScript := make([]byte, len(ctx.script)-ctx.separator)
	copy(subScript, ctx.script[ctx.separator:])
	for k := 0; k < sCount; k++ {
		var err error
		subScript, err = removeSig(subScript, ctx.stack.top(-(iSig + k)))
		if err != nil {
			return err
		}
	}
	success := true
	for success && (sCount > 0) {
		pk := ctx.stack.top(-iKey)
		sig := ctx.stack.top(-iSig)
		err := checkKeySig(ctx.sctx, pk, sig, subScript, ctx.flags)
		if err == nil {
			iSig++
			sCount--
		}
		iKey++
		kCount--
		// If there are more signatures left than keys left,
		// then too many signatures have failed
		if sCount > kCount {
			success = false
		}
	}

	// A Satoshi Bug causes CHECKMULTISIG to consume an extra item on the stack
	// We first clear all the "real" arguments
	stk := *ctx.stack
	*ctx.stack = stk[:len(stk)-i+1]
	// The dummy item is still requried
	if ctx.stack.empty() {
		return errStackItemMissing
	}
	// Now we check dummy being null when required
	si := ctx.stack.pop()
	if (ctx.flags&EvalFlagNullDummy) != 0 && len(si) > 0 {
		return errDummyArgNotNull
	}

	if op == OP_CHECKMULTISIGVERIFY {
		if !success {
			return errSigVerify
		}
	} else { // OP_CHECKMULTISIG
		b := klib.ScriptInt(1)
		if !success {
			b = 0
		}
		ctx.stack.push(b.Bytes())
	}
	return nil
}
Example #2
0
func execStackOp(ctx *execContext, op Opcode, _ []byte) error {
	switch op {
	case OP_TOALTSTACK:
		if ctx.stack.empty() {
			return errStackItemMissing
		}
		ctx.altStack.push(ctx.stack.pop())
	case OP_FROMALTSTACK:
		if ctx.altStack.empty() {
			return errStackItemMissing
		}
		ctx.stack.push(ctx.altStack.pop())
	case OP_2DROP:
		// (x1 x2 -- )
		if ctx.stack.height() < 2 {
			return errStackItemMissing
		}
		ctx.stack.pop()
		ctx.stack.pop()
	case OP_2DUP:
		// (x1 x2 -- x1 x2 x1 x2)
		if ctx.stack.height() < 2 {
			return errStackItemMissing
		}
		si1, si2 := ctx.stack.top(-2), ctx.stack.top(-1)
		ctx.stack.push(si1)
		ctx.stack.push(si2)
	case OP_3DUP:
		// (x1 x2 x3 -- x1 x2 x3 x1 x2 x3)
		if ctx.stack.height() < 3 {
			return errStackItemMissing
		}
		si1, si2, si3 := ctx.stack.top(-3), ctx.stack.top(-2), ctx.stack.top(-1)
		ctx.stack.push(si1)
		ctx.stack.push(si2)
		ctx.stack.push(si3)
	case OP_2OVER:
		// (x1 x2 x3 x4 -- x1 x2 x3 x4 x1 x2)
		if ctx.stack.height() < 4 {
			return errStackItemMissing
		}
		si1, si2 := ctx.stack.top(-4), ctx.stack.top(-3)
		ctx.stack.push(si1)
		ctx.stack.push(si2)
	case OP_2ROT:
		// (x1 x2 x3 x4 x5 x6 -- x3 x4 x5 x6 x1 x2)
		if ctx.stack.height() < 6 {
			return errStackItemMissing
		}
		s := *(ctx.stack)
		l := len(s)
		*(ctx.stack) = append(s[:l-6], s[l-4], s[l-3], s[l-2], s[l-1], s[l-6], s[l-5])
	case OP_2SWAP:
		// (x1 x2 x3 x4 -- x3 x4 x1 x2)
		if ctx.stack.height() < 4 {
			return errStackItemMissing
		}
		s := *(ctx.stack)
		l := len(s)
		*(ctx.stack) = append(s[:l-4], s[l-2], s[l-1], s[l-4], s[l-3])
	case OP_IFDUP:
		// Duplicate if true
		if ctx.stack.empty() {
			return errStackItemMissing
		}
		si := ctx.stack.top(-1)
		if si.toBool() {
			ctx.stack.push(si)
		}
	case OP_DEPTH:
		// Push stack height on to stack
		ctx.stack.push(intToStackItem(ctx.stack.height()))
	case OP_DROP:
		if ctx.stack.empty() {
			return errStackItemMissing
		}
		ctx.stack.pop()
	case OP_DUP:
		// Duplicate stack top
		if ctx.stack.empty() {
			return errStackItemMissing
		}
		ctx.stack.push(ctx.stack.top(-1))
	case OP_NIP:
		// (x1 x2 -- x2)
		if ctx.stack.height() < 2 {
			return errStackItemMissing
		}
		s := *(ctx.stack)
		l := len(s)
		*ctx.stack = append(s[:l-2], s[l-1])
	case OP_OVER:
		// (x1 x2 -- x1 x2 x1)
		if ctx.stack.height() < 2 {
			return errStackItemMissing
		}
		s := *(ctx.stack)
		ctx.stack.push(s[len(s)-2])
	case OP_PICK, OP_ROLL:
		// (xn ... x2 x1 x0 n - xn ... x2 x1 x0 xn)
		// (xn ... x2 x1 x0 n - ... x2 x1 x0 xn)
		if ctx.stack.height() < 2 {
			return errStackItemMissing
		}
		top := ctx.stack.pop()
		if klib.ScriptIntOverflow(top) {
			return errScriptIntOverflow
		}
		n := int(klib.ToScriptInt(top))
		if n < 0 || n >= ctx.stack.height() {
			return errIndexOutOfRange
		}
		s := *(ctx.stack)
		l := len(s)
		si := s[l-n-1]
		if op == OP_ROLL {
			s = append(s[:l-n-1], s[l-n:]...)
		}
		*ctx.stack = append(s, si)
	case OP_ROT:
		// (x1 x2 x3 -- x2 x3 x1)
		if ctx.stack.height() < 3 {
			return errStackItemMissing
		}
		s := *(ctx.stack)
		l := len(s)
		*(ctx.stack) = append(s[:l-3], s[l-2], s[l-1], s[l-3])
	case OP_SWAP:
		// (x1 x2 -- x2 x1)
		if ctx.stack.height() < 2 {
			return errStackItemMissing
		}
		s := *(ctx.stack)
		l := len(s)
		*(ctx.stack) = append(s[:l-2], s[l-1], s[l-2])
	case OP_TUCK:
		// (x1 x2 -- x2 x1 x2)
		if ctx.stack.height() < 2 {
			return errStackItemMissing
		}
		s := *(ctx.stack)
		l := len(s)
		*(ctx.stack) = append(s[:l-2], s[l-1], s[l-2], s[l-1])
	}
	return nil
}