interpreter.rs 174 KiB
Newer Older
		// <sig> <msg> <pubKey> OP_CHECKDATASIGVERIFY fails if 15 November 2018 protocol upgrade is not yet activated.
		basic_test_with_flags(&correct_signature_script, &incorrect_flags, Err(Error::DisabledOpcode(Opcode::OP_CHECKDATASIGVERIFY)), vec![].into());

		// <sig> <msg> OP_CHECKDATASIGVERIFY fails if there are fewer than 3 item on stack.
		let too_few_args_sig_script = Builder::default()
			.push_data(&[1u8; 32])
			.push_data(&*message)
			.push_opcode(Opcode::OP_CHECKDATASIGVERIFY)
			.into_script();
		basic_test_with_flags(&too_few_args_sig_script, &correct_flags, Err(Error::InvalidStackOperation), vec![].into());

		// <sig> <msg> <pubKey> OP_CHECKDATASIGVERIFYfails if <pubKey> is not a validly encoded public key.
		let incorrect_pubkey_script = Builder::default()
			.push_data(&*correct_signature)
			.push_data(&*message)
			.push_data(&[77u8; 15])
			.push_opcode(Opcode::OP_CHECKDATASIGVERIFY)
			.into_script();
		basic_test_with_flags(&incorrect_pubkey_script, &correct_flags, Err(Error::PubkeyType), vec![].into());

		// assuming that check_signature_encoding correctness is proved by other tests:
		// <sig> <msg> <pubKey> OP_CHECKDATASIGVERIFY fails if <sig> is not a validly encoded signature with strict DER encoding.
		// <sig> <msg> <pubKey> OP_CHECKDATASIGVERIFY fails if signature <sig> is not empty and does not pass the Low S check.
		let incorrectly_encoded_signature_script = Builder::default()
			.push_data(&[0u8; 65])
			.push_data(&*message)
			.push_data(&*pubkey)
			.push_opcode(Opcode::OP_CHECKDATASIGVERIFY)
			.into_script();
		basic_test_with_flags(&incorrectly_encoded_signature_script, &correct_flags, Err(Error::SignatureDer), vec![].into());

		// <sig> <msg> <pubKey> OP_CHECKDATASIGVERIFY fails if <sig> is not a valid signature of <msg> with respect to <pubKey>.
		let incorrect_signature_script = Builder::default()
			.push_data(&*correct_signature_for_other_message)
			.push_data(&*message)
			.push_data(&*pubkey)
			.push_opcode(Opcode::OP_CHECKDATASIGVERIFY)
			.into_script();
		basic_test_with_flags(&incorrect_signature_script, &correct_flags, Err(Error::CheckDataSigVerify), vec![].into());

		// <sig> <msg> <pubKey> OP_CHECKDATASIGVERIFY pops the top three stack elements if <sig> is a valid signature of <msg> with respect to <pubKey>.
		// Ok(false) means success here, because OP_CHECKDATASIGVERIFY leaves empty stack
		basic_test_with_flags(&correct_signature_script, &correct_flags, Ok(false), vec![].into());
	}

	#[test]
	fn op_equal_push_empty_bytes_to_stack() {
		// tx #95 from testnet block:
		// https://testnet.blockexplorer.com/block/00000000c7169675fc165bfeceb11b572129977ca9f9e6ca5953e3184cb403dd
		// https://tbtc.bitaps.com/raw/transaction/27c94c0ca2f66fcc09d11b510e04d21adfe19f459673029e709024d7d9a7f4b4
		// and its donor tx:
		// https://tbtc.bitaps.com/raw/transaction/25e140942ecf79d24619908185a881f95d9ecb23a7be050f7c44cd378aae26eb
		//
		// the issue was that our comparison ops implementation (OP_EQUAL, OP_WITHIN, OP_CHECKSIG, ***)
		// were pushing non-empty value (vec![0]) when comparison has failed
		// => in combination with verify_nnulldummy this caused consensus issue

		let tx: Transaction = "0100000001eb26ae8a37cd447c0f05bea723cb9e5df981a88581901946d279cf2e9440e1250000000091473044022057e887c4cb773a6ec513b285dde1209ee4213209c21bb9da9e284ffe7477979302201aba367cf84bf2c6ccfd1b18d2bec0d705e2acacfeb42324cdc0fe63fbe2524a01483045022100e3f2e5e2a0b6bb75f2a506d7b190d8ba48b1e9108dd4fc4a740fbc921d0067a3022070fccd6eec2415d6d75f7aa3d0604988ee84d856db2acde4cc01d9c43f0237a301ffffffff0100350c00000000001976a9149e2be3b4d5e7274e8fd739b09fc6fd223054616088ac00000000".into();
		let signer: TransactionInputSigner = tx.into();
		let checker = TransactionSignatureChecker {
			signer: signer,
			input_index: 0,
			input_amount: 1000000,
		};
		let input: Script = "473044022057e887c4cb773a6ec513b285dde1209ee4213209c21bb9da9e284ffe7477979302201aba367cf84bf2c6ccfd1b18d2bec0d705e2acacfeb42324cdc0fe63fbe2524a01483045022100e3f2e5e2a0b6bb75f2a506d7b190d8ba48b1e9108dd4fc4a740fbc921d0067a3022070fccd6eec2415d6d75f7aa3d0604988ee84d856db2acde4cc01d9c43f0237a301".into();
		let output: Script = "5253877c5121027fe085933328a89d0ad069071dee3bd4c908fddc852032356a318324c9ab0f6c210321e7c9eea060c099747ddcf741e9498a2b90fe8f362e2c85370722df0f88d1782102a5bc779306b40927648e73e144d430dc1b7c0730f6a3ab5bbd130374d8fe4a5a53af2102a70faff961b367875336396076a72293bf3adaa084404f8a5cbec23f41645b87ac".into();
		let flags = VerificationFlags::default().verify_nulldummy(true);
		assert_eq!(verify_script(&input, &output, &ScriptWitness::default(), &flags, &checker, SignatureVersion::Base), Ok(()));
	}