interpreter.rs 174 KiB
Newer Older
		assert_eq!(Ok(()), run_witness_test_tx_test("51".into(), &tx, &flags, 3100, 0)
			.and_then(|_| run_witness_test_tx_test("00144c9c3dfac4207d5d8cb89df5722cb3d712385e3f".into(), &tx, &flags, 2000, 1))
			.and_then(|_| run_witness_test_tx_test("51".into(), &tx, &flags, 1100, 2))
			.and_then(|_| run_witness_test_tx_test("51".into(), &tx, &flags, 4100, 2)));
	}

	// https://github.com/bitcoin/bitcoin/blob/7ee6c434ce8df9441abcf1718555cc7728a4c575/src/test/data/tx_valid.json#L349
	#[test]
	fn witness_valid_single() {
		let tx = "0100000000010300010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000200000000ffffffff0484030000000000000151d0070000000000000151540b0000000000000151c800000000000000015100024730440220699e6b0cfe015b64ca3283e6551440a34f901ba62dd4c72fe1cb815afb2e6761022021cc5e84db498b1479de14efda49093219441adc6c543e5534979605e273d80b032103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000".into();
		let flags = VerificationFlags::default().verify_witness(true).verify_p2sh(true);
		assert_eq!(Ok(()), run_witness_test_tx_test("51".into(), &tx, &flags, 1000, 0)
			.and_then(|_| run_witness_test_tx_test("00144c9c3dfac4207d5d8cb89df5722cb3d712385e3f".into(), &tx, &flags, 2000, 1))
			.and_then(|_| run_witness_test_tx_test("51".into(), &tx, &flags, 3000, 2)));
	}

	// https://github.com/bitcoin/bitcoin/blob/7ee6c434ce8df9441abcf1718555cc7728a4c575/src/test/data/tx_valid.json#L355
	#[test]
	fn witness_valid_single_same_signature() {
		let tx = "0100000000010300010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000200000000ffffffff03e8030000000000000151d0070000000000000151b80b000000000000015100024730440220699e6b0cfe015b64ca3283e6551440a34f901ba62dd4c72fe1cb815afb2e6761022021cc5e84db498b1479de14efda49093219441adc6c543e5534979605e273d80b032103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000".into();
		let flags = VerificationFlags::default().verify_witness(true).verify_p2sh(true);
		assert_eq!(Ok(()), run_witness_test_tx_test("51".into(), &tx, &flags, 1000, 0)
			.and_then(|_| run_witness_test_tx_test("00144c9c3dfac4207d5d8cb89df5722cb3d712385e3f".into(), &tx, &flags, 2000, 1))
			.and_then(|_| run_witness_test_tx_test("51".into(), &tx, &flags, 3000, 2)));
	}

	// https://github.com/bitcoin/bitcoin/blob/7ee6c434ce8df9441abcf1718555cc7728a4c575/src/test/data/tx_valid.json#L361
	#[test]
	fn witness_valid_none_anyone() {
		let tx = "0100000000010400010000000000000000000000000000000000000000000000000000000000000200000000ffffffff00010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000300000000ffffffff04b60300000000000001519e070000000000000151860b00000000000001009600000000000000015100000248304502210091b32274295c2a3fa02f5bce92fb2789e3fc6ea947fbe1a76e52ea3f4ef2381a022079ad72aefa3837a2e0c033a8652a59731da05fa4a813f4fc48e87c075037256b822103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000".into();
		let flags = VerificationFlags::default().verify_witness(true).verify_p2sh(true);
		assert_eq!(Ok(()), run_witness_test_tx_test("51".into(), &tx, &flags, 3100, 0)
			.and_then(|_| run_witness_test_tx_test("51".into(), &tx, &flags, 1100, 1))
			.and_then(|_| run_witness_test_tx_test("00144c9c3dfac4207d5d8cb89df5722cb3d712385e3f".into(), &tx, &flags, 2000, 2))
			.and_then(|_| run_witness_test_tx_test("51".into(), &tx, &flags, 4100, 3)));
	}

	// https://github.com/bitcoin/bitcoin/blob/7ee6c434ce8df9441abcf1718555cc7728a4c575/src/test/data/tx_valid.json#L368
	#[test]
	fn witness_valid_none_anyone_same_signature() {
		let tx = "0100000000010300010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000200000000ffffffff03e8030000000000000151d0070000000000000151b80b0000000000000151000248304502210091b32274295c2a3fa02f5bce92fb2789e3fc6ea947fbe1a76e52ea3f4ef2381a022079ad72aefa3837a2e0c033a8652a59731da05fa4a813f4fc48e87c075037256b822103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000".into();
		let flags = VerificationFlags::default().verify_witness(true).verify_p2sh(true);
		assert_eq!(Ok(()), run_witness_test_tx_test("51".into(), &tx, &flags, 1000, 0)
			.and_then(|_| run_witness_test_tx_test("00144c9c3dfac4207d5d8cb89df5722cb3d712385e3f".into(), &tx, &flags, 2000, 1))
			.and_then(|_| run_witness_test_tx_test("51".into(), &tx, &flags, 3000, 2)));
	}

	// https://github.com/bitcoin/bitcoin/blob/7ee6c434ce8df9441abcf1718555cc7728a4c575/src/test/data/tx_valid.json#L374
	#[test]
	fn witness_none() {
		let tx = "0100000000010300010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000200000000ffffffff04b60300000000000001519e070000000000000151860b0000000000000100960000000000000001510002473044022022fceb54f62f8feea77faac7083c3b56c4676a78f93745adc8a35800bc36adfa022026927df9abcf0a8777829bcfcce3ff0a385fa54c3f9df577405e3ef24ee56479022103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000".into();
		let flags = VerificationFlags::default().verify_witness(true).verify_p2sh(true);
		assert_eq!(Ok(()), run_witness_test_tx_test("51".into(), &tx, &flags, 1000, 0)
			.and_then(|_| run_witness_test_tx_test("00144c9c3dfac4207d5d8cb89df5722cb3d712385e3f".into(), &tx, &flags, 2000, 1))
			.and_then(|_| run_witness_test_tx_test("51".into(), &tx, &flags, 3000, 2)));
	}

	// https://github.com/bitcoin/bitcoin/blob/7ee6c434ce8df9441abcf1718555cc7728a4c575/src/test/data/tx_valid.json#L380
	#[test]
	fn witness_none_same_signature() {
		let tx = "0100000000010300010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000200000000ffffffff03e8030000000000000151d0070000000000000151b80b00000000000001510002473044022022fceb54f62f8feea77faac7083c3b56c4676a78f93745adc8a35800bc36adfa022026927df9abcf0a8777829bcfcce3ff0a385fa54c3f9df577405e3ef24ee56479022103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000".into();
		let flags = VerificationFlags::default().verify_witness(true).verify_p2sh(true);
		assert_eq!(Ok(()), run_witness_test_tx_test("51".into(), &tx, &flags, 1000, 0)
			.and_then(|_| run_witness_test_tx_test("00144c9c3dfac4207d5d8cb89df5722cb3d712385e3f".into(), &tx, &flags, 2000, 1))
			.and_then(|_| run_witness_test_tx_test("51".into(), &tx, &flags, 3000, 2)));
	}

	// https://github.com/bitcoin/bitcoin/blob/7ee6c434ce8df9441abcf1718555cc7728a4c575/src/test/data/tx_valid.json#L386
	#[test]
	fn witness_none_same_signature_sequence_changed() {
		let tx = "01000000000103000100000000000000000000000000000000000000000000000000000000000000000000000200000000010000000000000000000000000000000000000000000000000000000000000100000000ffffffff000100000000000000000000000000000000000000000000000000000000000002000000000200000003e8030000000000000151d0070000000000000151b80b00000000000001510002473044022022fceb54f62f8feea77faac7083c3b56c4676a78f93745adc8a35800bc36adfa022026927df9abcf0a8777829bcfcce3ff0a385fa54c3f9df577405e3ef24ee56479022103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000".into();
		let flags = VerificationFlags::default().verify_witness(true).verify_p2sh(true);
		assert_eq!(Ok(()), run_witness_test_tx_test("51".into(), &tx, &flags, 1000, 0)
			.and_then(|_| run_witness_test_tx_test("00144c9c3dfac4207d5d8cb89df5722cb3d712385e3f".into(), &tx, &flags, 2000, 1))
			.and_then(|_| run_witness_test_tx_test("51".into(), &tx, &flags, 3000, 2)));
	}

	// https://github.com/bitcoin/bitcoin/blob/7ee6c434ce8df9441abcf1718555cc7728a4c575/src/test/data/tx_valid.json#L392
	#[test]
	fn witness_all_anyone() {
		let tx = "0100000000010400010000000000000000000000000000000000000000000000000000000000000200000000ffffffff00010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000300000000ffffffff03e8030000000000000151d0070000000000000151b80b0000000000000151000002483045022100a3cec69b52cba2d2de623eeef89e0ba1606184ea55476c0f8189fda231bc9cbb022003181ad597f7c380a7d1c740286b1d022b8b04ded028b833282e055e03b8efef812103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000".into();
		let flags = VerificationFlags::default().verify_witness(true).verify_p2sh(true);
		assert_eq!(Ok(()), run_witness_test_tx_test("51".into(), &tx, &flags, 3100, 0)
			.and_then(|_| run_witness_test_tx_test("51".into(), &tx, &flags, 1100, 1))
			.and_then(|_| run_witness_test_tx_test("00144c9c3dfac4207d5d8cb89df5722cb3d712385e3f".into(), &tx, &flags, 2000, 2))
			.and_then(|_| run_witness_test_tx_test("51".into(), &tx, &flags, 4100, 3)));
	}

	// https://github.com/bitcoin/bitcoin/blob/7ee6c434ce8df9441abcf1718555cc7728a4c575/src/test/data/tx_valid.json#L399
	#[test]
	fn witness_all_anyone_same_signature() {
		let tx = "0100000000010300010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000200000000ffffffff03e8030000000000000151d0070000000000000151b80b00000000000001510002483045022100a3cec69b52cba2d2de623eeef89e0ba1606184ea55476c0f8189fda231bc9cbb022003181ad597f7c380a7d1c740286b1d022b8b04ded028b833282e055e03b8efef812103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000".into();
		let flags = VerificationFlags::default().verify_witness(true).verify_p2sh(true);
		assert_eq!(Ok(()), run_witness_test_tx_test("51".into(), &tx, &flags, 1000, 0)
			.and_then(|_| run_witness_test_tx_test("00144c9c3dfac4207d5d8cb89df5722cb3d712385e3f".into(), &tx, &flags, 2000, 1))
			.and_then(|_| run_witness_test_tx_test("51".into(), &tx, &flags, 3000, 2)));
	}

	// https://github.com/bitcoin/bitcoin/blob/7ee6c434ce8df9441abcf1718555cc7728a4c575/src/test/data/tx_valid.json#L405
	#[test]
	fn witness_unknown_witness_program_version() {
		let tx = "0100000000010300010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000200000000ffffffff03e8030000000000000151d0070000000000000151b80b00000000000001510002483045022100a3cec69b52cba2d2de623ffffffffff1606184ea55476c0f8189fda231bc9cbb022003181ad597f7c380a7d1c740286b1d022b8b04ded028b833282e055e03b8efef812103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000".into();
		let flags = VerificationFlags::default().verify_witness(true).verify_p2sh(true);
		assert_eq!(Ok(()), run_witness_test_tx_test("51".into(), &tx, &flags, 1000, 0)
			.and_then(|_| run_witness_test_tx_test("60144c9c3dfac4207d5d8cb89df5722cb3d712385e3f".into(), &tx, &flags, 2000, 1))
			.and_then(|_| run_witness_test_tx_test("51".into(), &tx, &flags, 3000, 2)));
	}

	// https://github.com/bitcoin/bitcoin/blob/7ee6c434ce8df9441abcf1718555cc7728a4c575/src/test/data/tx_valid.json#L411
	#[test]
	fn witness_push_520_bytes() {
		let tx = "0100000000010100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff010000000000000000015102fd08020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002755100000000".into();
		let flags = VerificationFlags::default().verify_witness(true).verify_p2sh(true);
		assert_eq!(Ok(()), run_witness_test_tx_test("002033198a9bfef674ebddb9ffaa52928017b8472791e54c609cb95f278ac6b1e349".into(), &tx, &flags, 1000, 0));
	}

	// https://github.com/bitcoin/bitcoin/blob/7ee6c434ce8df9441abcf1718555cc7728a4c575/src/test/data/tx_valid.json#L415
	#[test]
	fn witness_mixed_transaction() {
		let tx = "0100000000010c00010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff0001000000000000000000000000000000000000000000000000000000000000020000006a473044022026c2e65b33fcd03b2a3b0f25030f0244bd23cc45ae4dec0f48ae62255b1998a00220463aa3982b718d593a6b9e0044513fd67a5009c2fdccc59992cffc2b167889f4012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71ffffffff0001000000000000000000000000000000000000000000000000000000000000030000006a4730440220008bd8382911218dcb4c9f2e75bf5c5c3635f2f2df49b36994fde85b0be21a1a02205a539ef10fb4c778b522c1be852352ea06c67ab74200977c722b0bc68972575a012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71ffffffff0001000000000000000000000000000000000000000000000000000000000000040000006b483045022100d9436c32ff065127d71e1a20e319e4fe0a103ba0272743dbd8580be4659ab5d302203fd62571ee1fe790b182d078ecfd092a509eac112bea558d122974ef9cc012c7012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71ffffffff0001000000000000000000000000000000000000000000000000000000000000050000006a47304402200e2c149b114ec546015c13b2b464bbcb0cdc5872e6775787527af6cbc4830b6c02207e9396c6979fb15a9a2b96ca08a633866eaf20dc0ff3c03e512c1d5a1654f148012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71ffffffff0001000000000000000000000000000000000000000000000000000000000000060000006b483045022100b20e70d897dc15420bccb5e0d3e208d27bdd676af109abbd3f88dbdb7721e6d6022005836e663173fbdfe069f54cde3c2decd3d0ea84378092a5d9d85ec8642e8a41012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71ffffffff00010000000000000000000000000000000000000000000000000000000000000700000000ffffffff00010000000000000000000000000000000000000000000000000000000000000800000000ffffffff00010000000000000000000000000000000000000000000000000000000000000900000000ffffffff00010000000000000000000000000000000000000000000000000000000000000a00000000ffffffff00010000000000000000000000000000000000000000000000000000000000000b0000006a47304402206639c6e05e3b9d2675a7f3876286bdf7584fe2bbd15e0ce52dd4e02c0092cdc60220757d60b0a61fc95ada79d23746744c72bac1545a75ff6c2c7cdb6ae04e7e9592012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71ffffffff0ce8030000000000000151e9030000000000000151ea030000000000000151eb030000000000000151ec030000000000000151ed030000000000000151ee030000000000000151ef030000000000000151f0030000000000000151f1030000000000000151f2030000000000000151f30300000000000001510248304502210082219a54f61bf126bfc3fa068c6e33831222d1d7138c6faa9d33ca87fd4202d6022063f9902519624254d7c2c8ea7ba2d66ae975e4e229ae38043973ec707d5d4a83012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc7102473044022017fb58502475848c1b09f162cb1688d0920ff7f142bed0ef904da2ccc88b168f02201798afa61850c65e77889cbcd648a5703b487895517c88f85cdd18b021ee246a012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc7100000000000247304402202830b7926e488da75782c81a54cd281720890d1af064629ebf2e31bf9f5435f30220089afaa8b455bbeb7d9b9c3fe1ed37d07685ade8455c76472cda424d93e4074a012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc7102473044022026326fcdae9207b596c2b05921dbac11d81040c4d40378513670f19d9f4af893022034ecd7a282c0163b89aaa62c22ec202cef4736c58cd251649bad0d8139bcbf55012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71024730440220214978daeb2f38cd426ee6e2f44131a33d6b191af1c216247f1dd7d74c16d84a02205fdc05529b0bc0c430b4d5987264d9d075351c4f4484c16e91662e90a72aab24012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710247304402204a6e9f199dc9672cf2ff8094aaa784363be1eb62b679f7ff2df361124f1dca3302205eeb11f70fab5355c9c8ad1a0700ea355d315e334822fa182227e9815308ee8f012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000".into();
		let flags = VerificationFlags::default().verify_witness(true).verify_p2sh(true);
		assert_eq!(Ok(()), run_witness_test_tx_test("00144c9c3dfac4207d5d8cb89df5722cb3d712385e3f".into(), &tx, &flags, 1000, 0)
			.and_then(|_| run_witness_test_tx_test("00144c9c3dfac4207d5d8cb89df5722cb3d712385e3f".into(), &tx, &flags, 1001, 1))
			.and_then(|_| run_witness_test_tx_test("76a9144c9c3dfac4207d5d8cb89df5722cb3d712385e3f88ac".into(), &tx, &flags, 1002, 2))
			.and_then(|_| run_witness_test_tx_test("76a9144c9c3dfac4207d5d8cb89df5722cb3d712385e3f88ac".into(), &tx, &flags, 1003, 3))
			.and_then(|_| run_witness_test_tx_test("76a9144c9c3dfac4207d5d8cb89df5722cb3d712385e3f88ac".into(), &tx, &flags, 1004, 4))
			.and_then(|_| run_witness_test_tx_test("76a9144c9c3dfac4207d5d8cb89df5722cb3d712385e3f88ac".into(), &tx, &flags, 1005, 5))
			.and_then(|_| run_witness_test_tx_test("76a9144c9c3dfac4207d5d8cb89df5722cb3d712385e3f88ac".into(), &tx, &flags, 1006, 6))
			.and_then(|_| run_witness_test_tx_test("00144c9c3dfac4207d5d8cb89df5722cb3d712385e3f".into(), &tx, &flags, 1007, 7))
			.and_then(|_| run_witness_test_tx_test("00144c9c3dfac4207d5d8cb89df5722cb3d712385e3f".into(), &tx, &flags, 1008, 8))
			.and_then(|_| run_witness_test_tx_test("00144c9c3dfac4207d5d8cb89df5722cb3d712385e3f".into(), &tx, &flags, 1009, 9))
			.and_then(|_| run_witness_test_tx_test("00144c9c3dfac4207d5d8cb89df5722cb3d712385e3f".into(), &tx, &flags, 1010, 10))
			.and_then(|_| run_witness_test_tx_test("76a9144c9c3dfac4207d5d8cb89df5722cb3d712385e3f88ac".into(), &tx, &flags, 1011, 11)));
	}

	// https://github.com/bitcoin/bitcoin/blob/7ee6c434ce8df9441abcf1718555cc7728a4c575/src/test/data/tx_valid.json#L430
	#[test]
	fn witness_unknown_version_with_empty_witness() {
		let tx = "010000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff01e803000000000000015100000000".into();
		let flags = VerificationFlags::default().verify_witness(true).verify_p2sh(true);
		assert_eq!(Ok(()), run_witness_test_tx_test("60144c9c3dfac4207d5d8cb89df5722cb3d712385e3f".into(), &tx, &flags, 1000, 0));
	}

	// https://github.com/bitcoin/bitcoin/blob/7ee6c434ce8df9441abcf1718555cc7728a4c575/src/test/data/tx_valid.json#L434
	#[test]
	fn witness_single_output_oob() {
		let tx = "0100000000010200010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff01d00700000000000001510003483045022100e078de4e96a0e05dcdc0a414124dd8475782b5f3f0ed3f607919e9a5eeeb22bf02201de309b3a3109adb3de8074b3610d4cf454c49b61247a2779a0bcbf31c889333032103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc711976a9144c9c3dfac4207d5d8cb89df5722cb3d712385e3f88ac00000000".into();
		let flags = VerificationFlags::default().verify_witness(true).verify_p2sh(true);
		assert_eq!(Ok(()), run_witness_test_tx_test("51".into(), &tx, &flags, 1000, 0)
			.and_then(|_| run_witness_test_tx_test("00204d6c2a32c87821d68fc016fca70797abdb80df6cd84651d40a9300c6bad79e62".into(), &tx, &flags, 1000, 1)));
	}

	// https://github.com/bitcoin/bitcoin/blob/7ee6c434ce8df9441abcf1718555cc7728a4c575/src/test/data/tx_valid.json#L439
	#[test]
	fn witness_1_byte_push_not_witness_script_pubkey() {
		let tx = "010000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff01e803000000000000015100000000".into();
		let flags = VerificationFlags::default().verify_witness(true).verify_p2sh(true);
		assert_eq!(Ok(()), run_witness_test_tx_test("600101".into(), &tx, &flags, 1000, 0));
	}

	// https://github.com/bitcoin/bitcoin/blob/7ee6c434ce8df9441abcf1718555cc7728a4c575/src/test/data/tx_valid.json#L443
	#[test]
	fn witness_41_byte_push_not_witness_script_pubkey() {
		let tx = "010000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff01e803000000000000015100000000".into();
		let flags = VerificationFlags::default().verify_witness(true).verify_p2sh(true);
		assert_eq!(Ok(()), run_witness_test_tx_test("6029ff25429251b5a84f452230a3c75fd886b7fc5a7865ce4a7bb7a9d7c5be6da3dbff0000000000000000".into(), &tx, &flags, 1000, 0));
	}

	// https://github.com/bitcoin/bitcoin/blob/7ee6c434ce8df9441abcf1718555cc7728a4c575/src/test/data/tx_valid.json#L447
	#[test]
	fn witness_version_must_use_op1_to_op16() {
		let tx = "010000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff01e803000000000000015100000000".into();
		let flags = VerificationFlags::default().verify_witness(true).verify_p2sh(true);
		assert_eq!(Ok(()), run_witness_test_tx_test("0110020001".into(), &tx, &flags, 1000, 0));
	}

	// https://github.com/bitcoin/bitcoin/blob/7ee6c434ce8df9441abcf1718555cc7728a4c575/src/test/data/tx_valid.json#L451
	#[test]
	fn witness_program_push_must_be_canonical() {
		let tx = "010000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff01e803000000000000015100000000".into();
		let flags = VerificationFlags::default().verify_witness(true).verify_p2sh(true);
		assert_eq!(Ok(()), run_witness_test_tx_test("604c020001".into(), &tx, &flags, 1000, 0));
	}

	// https://github.com/bitcoin/bitcoin/blob/7ee6c434ce8df9441abcf1718555cc7728a4c575/src/test/data/tx_valid.json#L455
	#[test]
	fn witness_single_anyone_does_not_hash_input_position() {
		let tx = "0100000000010200010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff02e8030000000000000151e90300000000000001510247304402206d59682663faab5e4cb733c562e22cdae59294895929ec38d7c016621ff90da0022063ef0af5f970afe8a45ea836e3509b8847ed39463253106ac17d19c437d3d56b832103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710248304502210085001a820bfcbc9f9de0298af714493f8a37b3b354bfd21a7097c3e009f2018c022050a8b4dbc8155d4d04da2f5cdd575dcf8dd0108de8bec759bd897ea01ecb3af7832103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc7100000000".into();
		let flags = VerificationFlags::default().verify_witness(true).verify_p2sh(true);
		assert_eq!(Ok(()), run_witness_test_tx_test("00144c9c3dfac4207d5d8cb89df5722cb3d712385e3f".into(), &tx, &flags, 1000, 0)
			.and_then(|_| run_witness_test_tx_test("00144c9c3dfac4207d5d8cb89df5722cb3d712385e3f".into(), &tx, &flags, 1001, 1)));
	}

	// https://github.com/bitcoin/bitcoin/blob/7ee6c434ce8df9441abcf1718555cc7728a4c575/src/test/data/tx_valid.json#L460
	#[test]
	fn witness_single_anyone_does_not_hash_input_position_permutation() {
		let tx = "0100000000010200010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000000000000ffffffff02e9030000000000000151e80300000000000001510248304502210085001a820bfcbc9f9de0298af714493f8a37b3b354bfd21a7097c3e009f2018c022050a8b4dbc8155d4d04da2f5cdd575dcf8dd0108de8bec759bd897ea01ecb3af7832103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710247304402206d59682663faab5e4cb733c562e22cdae59294895929ec38d7c016621ff90da0022063ef0af5f970afe8a45ea836e3509b8847ed39463253106ac17d19c437d3d56b832103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc7100000000".into();
		let flags = VerificationFlags::default().verify_witness(true).verify_p2sh(true);
		assert_eq!(Ok(()), run_witness_test_tx_test("00144c9c3dfac4207d5d8cb89df5722cb3d712385e3f".into(), &tx, &flags, 1001, 0)
			.and_then(|_| run_witness_test_tx_test("00144c9c3dfac4207d5d8cb89df5722cb3d712385e3f".into(), &tx, &flags, 1000, 1)));
	}

	// https://github.com/bitcoin/bitcoin/blob/7ee6c434ce8df9441abcf1718555cc7728a4c575/src/test/data/tx_valid.json#L465
	#[test]
	fn witness_non_witness_single_anyone_hash_input_position_ok() {
		let tx = "01000000020001000000000000000000000000000000000000000000000000000000000000000000004847304402202a0b4b1294d70540235ae033d78e64b4897ec859c7b6f1b2b1d8a02e1d46006702201445e756d2254b0f1dfda9ab8e1e1bc26df9668077403204f32d16a49a36eb6983ffffffff00010000000000000000000000000000000000000000000000000000000000000100000049483045022100acb96cfdbda6dc94b489fd06f2d720983b5f350e31ba906cdbd800773e80b21c02200d74ea5bdf114212b4bbe9ed82c36d2e369e302dff57cb60d01c428f0bd3daab83ffffffff02e8030000000000000151e903000000000000015100000000".into();
		let flags = VerificationFlags::default().verify_witness(true).verify_p2sh(true);
		assert_eq!(Ok(()), run_witness_test_tx_test("2103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71ac".into(), &tx, &flags, 1000, 0)
			.and_then(|_| run_witness_test_tx_test("2103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71ac".into(), &tx, &flags, 1001, 1)));
	}

	// https://github.com/bitcoin/bitcoin/blob/7ee6c434ce8df9441abcf1718555cc7728a4c575/src/test/data/tx_valid.json#L471
	#[test]
	fn witness_bip143_example1() {
		let tx = "01000000000102fe3dc9208094f3ffd12645477b3dc56f60ec4fa8e6f5d67c565d1c6b9216b36e000000004847304402200af4e47c9b9629dbecc21f73af989bdaa911f7e6f6c2e9394588a3aa68f81e9902204f3fcf6ade7e5abb1295b6774c8e0abd94ae62217367096bc02ee5e435b67da201ffffffff0815cf020f013ed6cf91d29f4202e8a58726b1ac6c79da47c23d1bee0a6925f80000000000ffffffff0100f2052a010000001976a914a30741f8145e5acadf23f751864167f32e0963f788ac000347304402200de66acf4527789bfda55fc5459e214fa6083f936b430a762c629656216805ac0220396f550692cd347171cbc1ef1f51e15282e837bb2b30860dc77c8f78bc8501e503473044022027dc95ad6b740fe5129e7e62a75dd00f291a2aeb1200b84b09d9e3789406b6c002201a9ecd315dd6a0e632ab20bbb98948bc0c6fb204f2c286963bb48517a7058e27034721026dccc749adc2a9d0d89497ac511f760f45c47dc5ed9cf352a58ac706453880aeadab210255a9626aebf5e29c0e6538428ba0d1dcf6ca98ffdf086aa8ced5e0d0215ea465ac00000000".into();
		let flags = VerificationFlags::default().verify_witness(true).verify_p2sh(true);
		assert_eq!(Ok(()), run_witness_test_tx_test("21036d5c20fa14fb2f635474c1dc4ef5909d4568e5569b79fc94d3448486e14685f8ac".into(), &tx, &flags, 156250000, 0)
			.and_then(|_| run_witness_test_tx_test("00205d1b56b63d714eebe542309525f484b7e9d6f686b3781b6f61ef925d66d6f6a0".into(), &tx, &flags, 4900000000, 1)));
	}

	// https://github.com/bitcoin/bitcoin/blob/7ee6c434ce8df9441abcf1718555cc7728a4c575/src/test/data/tx_valid.json#L476
	#[test]
	fn witness_bip143_example2() {
		let tx = "01000000000102e9b542c5176808107ff1df906f46bb1f2583b16112b95ee5380665ba7fcfc0010000000000ffffffff80e68831516392fcd100d186b3c2c7b95c80b53c77e77c35ba03a66b429a2a1b0000000000ffffffff0280969800000000001976a914de4b231626ef508c9a74a8517e6783c0546d6b2888ac80969800000000001976a9146648a8cd4531e1ec47f35916de8e259237294d1e88ac02483045022100f6a10b8604e6dc910194b79ccfc93e1bc0ec7c03453caaa8987f7d6c3413566002206216229ede9b4d6ec2d325be245c5b508ff0339bf1794078e20bfe0babc7ffe683270063ab68210392972e2eb617b2388771abe27235fd5ac44af8e61693261550447a4c3e39da98ac024730440220032521802a76ad7bf74d0e2c218b72cf0cbc867066e2e53db905ba37f130397e02207709e2188ed7f08f4c952d9d13986da504502b8c3be59617e043552f506c46ff83275163ab68210392972e2eb617b2388771abe27235fd5ac44af8e61693261550447a4c3e39da98ac00000000".into();
		let flags = VerificationFlags::default().verify_witness(true).verify_p2sh(true);
		assert_eq!(Ok(()), run_witness_test_tx_test("0020ba468eea561b26301e4cf69fa34bde4ad60c81e70f059f045ca9a79931004a4d".into(), &tx, &flags, 16777215, 0)
			.and_then(|_| run_witness_test_tx_test("0020d9bbfbe56af7c4b7f960a70d7ea107156913d9e5a26b0a71429df5e097ca6537".into(), &tx, &flags, 16777215, 1)));
	}

	// https://github.com/bitcoin/bitcoin/blob/7ee6c434ce8df9441abcf1718555cc7728a4c575/src/test/data/tx_valid.json#L481
	#[test]
	fn witness_bip143_example3() {
		let tx = "0100000000010280e68831516392fcd100d186b3c2c7b95c80b53c77e77c35ba03a66b429a2a1b0000000000ffffffffe9b542c5176808107ff1df906f46bb1f2583b16112b95ee5380665ba7fcfc0010000000000ffffffff0280969800000000001976a9146648a8cd4531e1ec47f35916de8e259237294d1e88ac80969800000000001976a914de4b231626ef508c9a74a8517e6783c0546d6b2888ac024730440220032521802a76ad7bf74d0e2c218b72cf0cbc867066e2e53db905ba37f130397e02207709e2188ed7f08f4c952d9d13986da504502b8c3be59617e043552f506c46ff83275163ab68210392972e2eb617b2388771abe27235fd5ac44af8e61693261550447a4c3e39da98ac02483045022100f6a10b8604e6dc910194b79ccfc93e1bc0ec7c03453caaa8987f7d6c3413566002206216229ede9b4d6ec2d325be245c5b508ff0339bf1794078e20bfe0babc7ffe683270063ab68210392972e2eb617b2388771abe27235fd5ac44af8e61693261550447a4c3e39da98ac00000000".into();
		let flags = VerificationFlags::default().verify_witness(true).verify_p2sh(true);
		assert_eq!(Ok(()), run_witness_test_tx_test("0020d9bbfbe56af7c4b7f960a70d7ea107156913d9e5a26b0a71429df5e097ca6537".into(), &tx, &flags, 16777215, 0)
			.and_then(|_| run_witness_test_tx_test("0020ba468eea561b26301e4cf69fa34bde4ad60c81e70f059f045ca9a79931004a4d".into(), &tx, &flags, 16777215, 1)));
	}

	// https://github.com/bitcoin/bitcoin/blob/7ee6c434ce8df9441abcf1718555cc7728a4c575/src/test/data/tx_valid.json#L486
	#[test]
	fn witness_bip143_example4() {
		let tx = "0100000000010136641869ca081e70f394c6948e8af409e18b619df2ed74aa106c1ca29787b96e0100000023220020a16b5755f7f6f96dbd65f5f0d6ab9418b89af4b1f14a1bb8a09062c35f0dcb54ffffffff0200e9a435000000001976a914389ffce9cd9ae88dcc0631e88a821ffdbe9bfe2688acc0832f05000000001976a9147480a33f950689af511e6e84c138dbbd3c3ee41588ac080047304402206ac44d672dac41f9b00e28f4df20c52eeb087207e8d758d76d92c6fab3b73e2b0220367750dbbe19290069cba53d096f44530e4f98acaa594810388cf7409a1870ce01473044022068c7946a43232757cbdf9176f009a928e1cd9a1a8c212f15c1e11ac9f2925d9002205b75f937ff2f9f3c1246e547e54f62e027f64eefa2695578cc6432cdabce271502473044022059ebf56d98010a932cf8ecfec54c48e6139ed6adb0728c09cbe1e4fa0915302e022007cd986c8fa870ff5d2b3a89139c9fe7e499259875357e20fcbb15571c76795403483045022100fbefd94bd0a488d50b79102b5dad4ab6ced30c4069f1eaa69a4b5a763414067e02203156c6a5c9cf88f91265f5a942e96213afae16d83321c8b31bb342142a14d16381483045022100a5263ea0553ba89221984bd7f0b13613db16e7a70c549a86de0cc0444141a407022005c360ef0ae5a5d4f9f2f87a56c1546cc8268cab08c73501d6b3be2e1e1a8a08824730440220525406a1482936d5a21888260dc165497a90a15669636d8edca6b9fe490d309c022032af0c646a34a44d1f4576bf6a4a74b67940f8faa84c7df9abe12a01a11e2b4783cf56210307b8ae49ac90a048e9b53357a2354b3334e9c8bee813ecb98e99a7e07e8c3ba32103b28f0c28bfab54554ae8c658ac5c3e0ce6e79ad336331f78c428dd43eea8449b21034b8113d703413d57761b8b9781957b8c0ac1dfe69f492580ca4195f50376ba4a21033400f6afecb833092a9a21cfdf1ed1376e58c5d1f47de74683123987e967a8f42103a6d48b1131e94ba04d9737d61acdaa1322008af9602b3b14862c07a1789aac162102d8b661b0b3302ee2f162b09e07a55ad5dfbe673a9f01d9f0c19617681024306b56ae00000000".into();
		let flags = VerificationFlags::default().verify_witness(true).verify_p2sh(true);
		assert_eq!(Ok(()), run_witness_test_tx_test("a9149993a429037b5d912407a71c252019287b8d27a587".into(), &tx, &flags, 987654321, 0));
	}
Svyatoslav Nikolsky's avatar
Svyatoslav Nikolsky committed
	fn op_cat_disabled_by_default() {
		let script = Builder::default()
			.push_data(&[1; 1])
			.push_data(&[1; 1])
			.push_opcode(Opcode::OP_CAT)
			.into_script();
		let result = Err(Error::DisabledOpcode(Opcode::OP_CAT));
		basic_test_with_flags(&script, &VerificationFlags::default(), result,
			vec![].into());
	}

	#[test]
	fn op_cat_max_and_non_empty_succeeds() {
		// maxlen_x empty OP_CAT → ok
		let script = Builder::default()
			.push_data(&[1; MAX_SCRIPT_ELEMENT_SIZE])
			.push_data(&[1; 0])
			.push_opcode(Opcode::OP_CAT)
			.into_script();
		let result = Ok(true);
		basic_test_with_flags(&script, &VerificationFlags::default().verify_concat(true), result,
			vec![vec![1; MAX_SCRIPT_ELEMENT_SIZE].into()].into());
	}

	#[test]
	fn op_cat_max_and_non_empty_fails() {
		// maxlen_x y OP_CAT → failure
		let script = Builder::default()
			.push_data(&[1; MAX_SCRIPT_ELEMENT_SIZE])
			.push_data(&[1; 1])
			.push_opcode(Opcode::OP_CAT)
			.into_script();
		let result = Err(Error::PushSize);
		basic_test_with_flags(&script, &VerificationFlags::default().verify_concat(true), result,
			vec![].into());
	}

	#[test]
	fn op_cat_large_and_large_fails() {
		// large_x large_y OP_CAT → failure
		let script = Builder::default()
			.push_data(&[1; MAX_SCRIPT_ELEMENT_SIZE / 2 + 1])
			.push_data(&[1; MAX_SCRIPT_ELEMENT_SIZE / 2 + 1])
			.push_opcode(Opcode::OP_CAT)
			.into_script();
		let result = Err(Error::PushSize);
		basic_test_with_flags(&script, &VerificationFlags::default().verify_concat(true), result,
			vec![].into());
	}

	#[test]
	fn op_cat_empty_and_empty_succeeds() {
		// OP_0 OP_0 OP_CAT → OP_0
		let script = Builder::default()
			.push_opcode(Opcode::OP_0)
			.push_opcode(Opcode::OP_0)
			.push_opcode(Opcode::OP_CAT)
			.into_script();
		let result = Ok(false);
		basic_test_with_flags(&script, &VerificationFlags::default().verify_concat(true), result,
			vec![Bytes::default()].into());
	}

	#[test]
	fn op_cat_non_empty_and_empty_succeeds() {
		// x OP_0 OP_CAT → x
		let script = Builder::default()
			.push_data(&[1; 1])
			.push_opcode(Opcode::OP_0)
			.push_opcode(Opcode::OP_CAT)
			.into_script();
		let result = Ok(true);
		basic_test_with_flags(&script, &VerificationFlags::default().verify_concat(true), result,
			vec![vec![1; 1].into()].into());
	}

	#[test]
	fn op_cat_empty_and_non_empty_succeeds() {
		// OP_0 x OP_CAT → x
		let script = Builder::default()
			.push_opcode(Opcode::OP_0)
			.push_data(&[1; 1])
			.push_opcode(Opcode::OP_CAT)
			.into_script();
		let result = Ok(true);
		basic_test_with_flags(&script, &VerificationFlags::default().verify_concat(true), result,
			vec![vec![1; 1].into()].into());
	}

	#[test]
	fn op_cat_non_empty_and_non_empty_succeeds() {
		// x y OP_CAT → concat(x,y)
		let script = Builder::default()
			.push_data(&[0x11])
			.push_data(&[0x22, 0x33])
			.push_opcode(Opcode::OP_CAT)
			.into_script();
		let result = Ok(true);
		basic_test_with_flags(&script, &VerificationFlags::default().verify_concat(true), result,
			vec![vec![0x11, 0x22, 0x33].into()].into());
	}

	#[test]
	fn op_split_disabled_by_default() {
		let script = Builder::default()
			.push_data(&[0x11, 0x22])
			.push_num(1.into())
			.push_opcode(Opcode::OP_SUBSTR)
			.into_script();
		let result = Err(Error::DisabledOpcode(Opcode::OP_SUBSTR));
		basic_test_with_flags(&script, &VerificationFlags::default(), result,
			vec![].into());
	}

	#[test]
	fn op_split_empty_at_zero_succeeds() {
		// OP_0 0 OP_SPLIT -> OP_0 OP_0
		let script = Builder::default()
			.push_opcode(Opcode::OP_0)
			.push_num(0.into())
			.push_opcode(Opcode::OP_SUBSTR)
			.into_script();
		let result = Ok(false);
		basic_test_with_flags(&script, &VerificationFlags::default().verify_split(true), result,
			vec![vec![0; 0].into(), vec![0; 0].into()].into());
	}

	#[test]
	fn op_split_non_empty_at_zero_succeeds() {
		// x 0 OP_SPLIT -> OP_0 x
		let script = Builder::default()
			.push_data(&[0x00, 0x11, 0x22])
			.push_num(0.into())
			.push_opcode(Opcode::OP_SUBSTR)
			.into_script();
		let result = Ok(true);
		basic_test_with_flags(&script, &VerificationFlags::default().verify_split(true), result,
			vec![vec![0; 0].into(), vec![0x00, 0x11, 0x22].into()].into());
	}

	#[test]
	fn op_split_non_empty_at_len_succeeds() {
		// x len(x) OP_SPLIT -> x OP_0
		let script = Builder::default()
			.push_data(&[0x00, 0x11, 0x22])
			.push_num(3.into())
			.push_opcode(Opcode::OP_SUBSTR)
			.into_script();
		let result = Ok(false);
		basic_test_with_flags(&script, &VerificationFlags::default().verify_split(true), result,
			vec![vec![0x00, 0x11, 0x22].into(), vec![0; 0].into()].into());
	}

	#[test]
	fn op_split_non_empty_at_post_len_fails() {
		// x (len(x) + 1) OP_SPLIT -> FAIL
		let script = Builder::default()
			.push_data(&[0x00, 0x11, 0x22])
			.push_num(4.into())
			.push_opcode(Opcode::OP_SUBSTR)
			.into_script();
		let result = Err(Error::InvalidSplitRange);
		basic_test_with_flags(&script, &VerificationFlags::default().verify_split(true), result,
			vec![].into());
	}

	#[test]
	fn op_split_non_empty_at_mid_succeeds() {
		let script = Builder::default()
			.push_data(&[0x00, 0x11, 0x22])
			.push_num(2.into())
			.push_opcode(Opcode::OP_SUBSTR)
			.into_script();
		let result = Ok(true);
		basic_test_with_flags(&script, &VerificationFlags::default().verify_split(true), result,
			vec![vec![0x00, 0x11].into(), vec![0x22].into()].into());
	}

	#[test]
	fn op_split_fails_if_position_is_nan() {
		let script = Builder::default()
			.push_data(&[0x00, 0x11, 0x22])
			.push_opcode(Opcode::OP_1NEGATE) // NaN
			.push_opcode(Opcode::OP_SUBSTR)
			.into_script();
		let result = Err(Error::InvalidStackOperation);
		basic_test_with_flags(&script, &VerificationFlags::default().verify_split(true), result,
			vec![].into());
	}

	#[test]
	fn op_split_fails_if_position_is_negative() {
		let script = Builder::default()
			.push_data(&[0x00, 0x11, 0x22])
			.push_num((-10).into())
			.push_opcode(Opcode::OP_SUBSTR)
			.into_script();
		let result = Err(Error::InvalidStackOperation);
		basic_test_with_flags(&script, &VerificationFlags::default().verify_split(true), result,
			vec![].into());
	}

	#[test]
	fn op_and_disabled_by_default() {
		let script = Builder::default()
			.push_data(&[0x11])
			.push_data(&[0x22])
			.push_opcode(Opcode::OP_AND)
			.into_script();
		let result = Err(Error::DisabledOpcode(Opcode::OP_AND));
		basic_test_with_flags(&script, &VerificationFlags::default(), result,
			vec![].into());
	}

	#[test]
	fn op_and_fails_with_different_len_args() {
		let script = Builder::default()
			.push_data(&[0x11, 0x22])
			.push_data(&[0x22])
			.push_opcode(Opcode::OP_AND)
			.into_script();
		let result = Err(Error::InvalidOperandSize);
		basic_test_with_flags(&script, &VerificationFlags::default().verify_and(true), result,
			vec![].into());
	}

	#[test]
	fn op_and_succeeds() {
		let script = Builder::default()
			.push_data(&[0x34, 0x56])
			.push_data(&[0x56, 0x78])
			.push_opcode(Opcode::OP_AND)
			.into_script();
		let result = Ok(true);
		basic_test_with_flags(&script, &VerificationFlags::default().verify_and(true), result,
			vec![vec![0x14, 0x50].into()].into());
	}

	#[test]
	fn op_or_disabled_by_default() {
		let script = Builder::default()
			.push_data(&[0x11])
			.push_data(&[0x22])
			.push_opcode(Opcode::OP_OR)
			.into_script();
		let result = Err(Error::DisabledOpcode(Opcode::OP_OR));
		basic_test_with_flags(&script, &VerificationFlags::default(), result,
			vec![].into());
	}

	#[test]
	fn op_or_fails_with_different_len_args() {
		let script = Builder::default()
			.push_data(&[0x11, 0x22])
			.push_data(&[0x22])
			.push_opcode(Opcode::OP_OR)
			.into_script();
		let result = Err(Error::InvalidOperandSize);
		basic_test_with_flags(&script, &VerificationFlags::default().verify_or(true), result,
			vec![].into());
	}

	#[test]
	fn op_or_succeeds() {
		let script = Builder::default()
			.push_data(&[0x34, 0x56])
			.push_data(&[0x56, 0x78])
			.push_opcode(Opcode::OP_OR)
			.into_script();
		let result = Ok(true);
		basic_test_with_flags(&script, &VerificationFlags::default().verify_or(true), result,
			vec![vec![0x76, 0x7e].into()].into());
	}

	#[test]
	fn op_xor_disabled_by_default() {
		let script = Builder::default()
			.push_data(&[0x11])
			.push_data(&[0x22])
			.push_opcode(Opcode::OP_XOR)
			.into_script();
		let result = Err(Error::DisabledOpcode(Opcode::OP_XOR));
		basic_test_with_flags(&script, &VerificationFlags::default(), result,
			vec![].into());
	}

	#[test]
	fn op_xor_fails_with_different_len_args() {
		let script = Builder::default()
			.push_data(&[0x11, 0x22])
			.push_data(&[0x22])
			.push_opcode(Opcode::OP_XOR)
			.into_script();
		let result = Err(Error::InvalidOperandSize);
		basic_test_with_flags(&script, &VerificationFlags::default().verify_xor(true), result,
			vec![].into());
	}

	#[test]
	fn op_xor_succeeds() {
		let script = Builder::default()
			.push_data(&[0x34, 0x56])
			.push_data(&[0x56, 0x78])
			.push_opcode(Opcode::OP_XOR)
			.into_script();
		let result = Ok(true);
		basic_test_with_flags(&script, &VerificationFlags::default().verify_xor(true), result,
			vec![vec![0x62, 0x2e].into()].into());
	}

	#[test]
	fn op_div_disabled_by_default() {
		let script = Builder::default()
			.push_num(13.into())
			.push_num(5.into())
			.push_opcode(Opcode::OP_DIV)
			.into_script();
		let result = Err(Error::DisabledOpcode(Opcode::OP_DIV));
		basic_test_with_flags(&script, &VerificationFlags::default(), result,
			vec![].into());
	}

	#[test]
	fn op_div_num_by_nan_fails() {
		// a b OP_DIV -> failure where !isnum(a) or !isnum(b). Both operands must be valid numbers
		let script = Builder::default()
			.push_opcode(Opcode::OP_1SUB)
			.push_num(5.into())
			.push_opcode(Opcode::OP_DIV)
			.into_script();
		let result = Err(Error::InvalidStackOperation);
		basic_test_with_flags(&script, &VerificationFlags::default().verify_div(true), result,
			vec![].into());
	}

	#[test]
	fn op_div_nan_by_num_fails() {
		// a b OP_DIV -> failure where !isnum(a) or !isnum(b). Both operands must be valid numbers
		let script = Builder::default()
			.push_num(5.into())
			.push_opcode(Opcode::OP_1SUB)
			.push_opcode(Opcode::OP_DIV)
			.into_script();
		let result = Err(Error::InvalidStackOperation);
		basic_test_with_flags(&script, &VerificationFlags::default().verify_div(true), result,
			vec![].into());
	}

	#[test]
	fn op_div_num_by_zero_fails() {
		// a 0 OP_DIV -> failure. Division by positive zero (all sizes), negative zero (all sizes), OP_0
		let script = Builder::default()
			.push_num(0.into())
			.push_num(5.into())
			.push_opcode(Opcode::OP_DIV)
			.into_script();
		let result = Err(Error::DivisionByZero);
		basic_test_with_flags(&script, &VerificationFlags::default().verify_div(true), result,
			vec![].into());
	}

	#[test]
	fn op_div_negative_by_negative_succeeds() {
		let script = Builder::default()
			.push_num((-5).into())
			.push_num((-13).into())
			.push_opcode(Opcode::OP_DIV)
			.into_script();
		let result = Ok(true);
		basic_test_with_flags(&script, &VerificationFlags::default().verify_div(true), result,
			vec![Num::from(2).to_bytes()].into());
	}

	#[test]
	fn op_div_negative_by_positive_succeeds() {
		let script = Builder::default()
			.push_num(5.into())
			.push_num((-13).into())
			.push_opcode(Opcode::OP_DIV)
			.into_script();
		let result = Ok(true);
		basic_test_with_flags(&script, &VerificationFlags::default().verify_div(true), result,
			vec![Num::from(-2).to_bytes()].into());
	}

	#[test]
	fn op_div_positive_by_negative_succeeds() {
		let script = Builder::default()
			.push_num((-5).into())
			.push_num(13.into())
			.push_opcode(Opcode::OP_DIV)
			.into_script();
		let result = Ok(true);
		basic_test_with_flags(&script, &VerificationFlags::default().verify_div(true), result,
			vec![Num::from(-2).to_bytes()].into());
	}

	#[test]
	fn op_div_positive_by_positive_succeeds() {
		let script = Builder::default()
			.push_num(5.into())
			.push_num(13.into())
			.push_opcode(Opcode::OP_DIV)
			.into_script();
		let result = Ok(true);
		basic_test_with_flags(&script, &VerificationFlags::default().verify_div(true), result,
			vec![Num::from(2).to_bytes()].into());
	}

	#[test]
	fn op_mod_disabled_by_default() {
		let script = Builder::default()
			.push_num(13.into())
			.push_num(5.into())
			.push_opcode(Opcode::OP_MOD)
			.into_script();
		let result = Err(Error::DisabledOpcode(Opcode::OP_MOD));
		basic_test_with_flags(&script, &VerificationFlags::default(), result,
			vec![].into());
	}

	#[test]
	fn op_mod_num_by_nan_fails() {
		// a b OP_MOD -> failure where !isnum(a) or !isnum(b). Both operands must be valid numbers
		let script = Builder::default()
			.push_opcode(Opcode::OP_1SUB)
			.push_num(5.into())
			.push_opcode(Opcode::OP_MOD)
			.into_script();
		let result = Err(Error::InvalidStackOperation);
		basic_test_with_flags(&script, &VerificationFlags::default().verify_mod(true), result,
			vec![].into());
	}

	#[test]
	fn op_mod_nan_by_num_fails() {
		// a b OP_MOD -> failure where !isnum(a) or !isnum(b). Both operands must be valid numbers
		let script = Builder::default()
			.push_num(5.into())
			.push_opcode(Opcode::OP_1SUB)
			.push_opcode(Opcode::OP_MOD)
			.into_script();
		let result = Err(Error::InvalidStackOperation);
		basic_test_with_flags(&script, &VerificationFlags::default().verify_mod(true), result,
			vec![].into());
	}

	#[test]
	fn op_mod_num_by_zero_fails() {
		// a 0 OP_MOD -> failure. Division by positive zero (all sizes), negative zero (all sizes), OP_0
		let script = Builder::default()
			.push_num(0.into())
			.push_num(5.into())
			.push_opcode(Opcode::OP_MOD)
			.into_script();
		let result = Err(Error::DivisionByZero);
		basic_test_with_flags(&script, &VerificationFlags::default().verify_mod(true), result,
			vec![].into());
	}

	#[test]
	fn op_mod_negative_by_negative_succeeds() {
		let script = Builder::default()
			.push_num((-5).into())
			.push_num((-13).into())
			.push_opcode(Opcode::OP_MOD)
			.into_script();
		let result = Ok(true);
		basic_test_with_flags(&script, &VerificationFlags::default().verify_mod(true), result,
			vec![Num::from(-3).to_bytes()].into());
	}

	#[test]
	fn op_mod_negative_by_positive_succeeds() {
		let script = Builder::default()
			.push_num(5.into())
			.push_num((-13).into())
			.push_opcode(Opcode::OP_MOD)
			.into_script();
		let result = Ok(true);
		basic_test_with_flags(&script, &VerificationFlags::default().verify_mod(true), result,
			vec![Num::from(-3).to_bytes()].into());
	}

	#[test]
	fn op_mod_positive_by_negative_succeeds() {
		let script = Builder::default()
			.push_num((-5).into())
			.push_num(13.into())
			.push_opcode(Opcode::OP_MOD)
			.into_script();
		let result = Ok(true);
		basic_test_with_flags(&script, &VerificationFlags::default().verify_mod(true), result,
			vec![Num::from(3).to_bytes()].into());
	}

	#[test]
	fn op_mod_positive_by_positive_succeeds() {
		let script = Builder::default()
			.push_num(5.into())
			.push_num(13.into())
			.push_opcode(Opcode::OP_MOD)
			.into_script();
		let result = Ok(true);
		basic_test_with_flags(&script, &VerificationFlags::default().verify_mod(true), result,
			vec![Num::from(3).to_bytes()].into());
	}
	#[test]
	fn op_bin2num_disabled_by_default() {
		let script = Builder::default()
			.push_num(0.into())
			.push_opcode(Opcode::OP_RIGHT)
			.into_script();
		let result = Err(Error::DisabledOpcode(Opcode::OP_RIGHT));
		basic_test_with_flags(&script, &VerificationFlags::default(), result,
			vec![].into());
	}

	#[test]
	fn test_bin2num_all() {
		fn test_bin2num(input: &[u8], result: Result<bool, Error>, output: Vec<u8>) {
			let script = Builder::default()
				.push_bytes(input)
				.push_opcode(Opcode::OP_RIGHT)
				.into_script();
			let stack = if result.is_ok() {
				vec![output.into()].into()
			} else {
				vec![]
			}.into();
			let flags = VerificationFlags::default()
				.verify_bin2num(true);
			basic_test_with_flags(&script, &flags, result, stack);
		}

		test_bin2num(&[0x02, 0x00, 0x00, 0x00, 0x00], Ok(true), vec![0x02]);
		test_bin2num(&[0x05, 0x00, 0x80], Ok(true), vec![0x85]);
		test_bin2num(&[0x02, 0x02, 0x02, 0x02, 0x02], Err(Error::NumberOverflow), vec![]);
		test_bin2num(&[0x00], Ok(false), vec![]);
		test_bin2num(&[0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], Ok(true), vec![0x01]);
		test_bin2num(&[0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80], Ok(true), vec![0x81]);
		test_bin2num(&[0x80], Ok(false), vec![]);
		test_bin2num(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80], Ok(false), vec![]);
	}

	#[test]
	fn op_num2bin_disabled_by_default() {
		let script = Builder::default()
			.push_num(1.into())
			.push_num(1.into())
			.push_opcode(Opcode::OP_LEFT)
			.into_script();
		let result = Err(Error::DisabledOpcode(Opcode::OP_LEFT));
		basic_test_with_flags(&script, &VerificationFlags::default(), result,
			vec![].into());
	}

	#[test]
	fn test_num2bin_all() {
		fn test_num2bin(num: &[u8], size: &[u8], result: Result<bool, Error>, output: Vec<u8>) {
			let script = Builder::default()
				.push_data(num)
				.push_data(size)
				.push_opcode(Opcode::OP_LEFT)
				.into_script();
			let stack = if result.is_ok() {
				vec![output.into()].into()
			} else {
				vec![]
			}.into();

			let flags = VerificationFlags::default()
				.verify_num2bin(true);
			basic_test_with_flags(&script, &flags, result, stack);
		}

		fn test_num2bin_num(num: Num, size: Num, result: Result<bool, Error>, output: Vec<u8>) {
			test_num2bin(&*num.to_bytes(), &*size.to_bytes(), result, output)
		}

		test_num2bin_num(256.into(), 1.into(), Err(Error::ImpossibleEncoding), vec![0x00]);
		test_num2bin_num(1.into(), (MAX_SCRIPT_ELEMENT_SIZE + 1).into(), Err(Error::PushSize), vec![0x00]);

		test_num2bin_num(0.into(), 0.into(), Ok(false), vec![]);
		test_num2bin_num(0.into(), 1.into(), Ok(false), vec![0x00]);
		test_num2bin_num(0.into(), 7.into(), Ok(false), vec![0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
		test_num2bin_num(1.into(), 1.into(), Ok(true), vec![0x01]);
		test_num2bin_num((-42).into(), 1.into(), Ok(true), Num::from(-42).to_bytes().to_vec());
		test_num2bin_num((-42).into(), 2.into(), Ok(true), vec![0x2a, 0x80]);
		test_num2bin_num((-42).into(), 10.into(), Ok(true), vec![0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80]);
		test_num2bin_num((-42).into(), 520.into(), Ok(true), ::std::iter::once(0x2a)
			.chain(::std::iter::repeat(0x00).take(518))
			.chain(::std::iter::once(0x80)).collect());
		test_num2bin_num((-42).into(), 521.into(), Err(Error::PushSize), vec![]);
		test_num2bin_num((-42).into(), (-3).into(), Err(Error::PushSize), vec![]);

		test_num2bin(&vec![0xab, 0xcd, 0xef, 0x42, 0x80], &vec![0x04], Ok(true), vec![0xab, 0xcd, 0xef, 0xc2]);
		test_num2bin(&vec![0x80], &vec![0x00], Ok(false), vec![]);
		test_num2bin(&vec![0x80], &vec![0x03], Ok(false), vec![0x00, 0x00, 0x00]);
	}

	#[test]
	fn test_num_bin_conversions_are_reverse_ops() {
		let script = Builder::default()
			// convert num2bin
			.push_num(123456789.into())
			.push_num(8.into())
			.push_opcode(Opcode::OP_LEFT)
			// and then back bin2num
			.push_opcode(Opcode::OP_RIGHT)
			// check that numbers are the same
			.push_num(123456789.into())
			.push_opcode(Opcode::OP_EQUAL)
			.into_script();

		let flags = VerificationFlags::default()
			.verify_num2bin(true)
			.verify_bin2num(true);
		basic_test_with_flags(&script, &flags, Ok(true), vec![vec![0x01].into()].into());
	}

	#[test]
	fn test_split_cat_are_reverse_ops() {
		let script = Builder::default()
			// split array
			.push_data(&vec![0x01, 0x02, 0x03, 0x04, 0x05])
			.push_num(2.into())
			.push_opcode(Opcode::OP_SUBSTR)
			// and then concat again
			.push_opcode(Opcode::OP_CAT)
			// check that numbers are the same
			.push_data(&vec![0x01, 0x02, 0x03, 0x04, 0x05])
			.push_opcode(Opcode::OP_EQUAL)
			.into_script();

		let flags = VerificationFlags::default()
			.verify_concat(true)
			.verify_split(true);
		basic_test_with_flags(&script, &flags, Ok(true), vec![vec![0x01].into()].into());
	}

	#[test]
	fn checkdatasig_spec_tests() {
		// official tests from:
		// https://github.com/bitcoincashorg/bitcoincash.org/blob/0c6f91b0b713aae3bc6c9834b46e80e247ff5fab/spec/op_checkdatasig.md

		let kp = KeyPair::from_private(Private { network: Network::Mainnet, secret: 1.into(), compressed: false, }).unwrap();
		let pubkey = kp.public().clone();
		let message = vec![42u8; 32];
		let correct_signature = kp.private().sign(&Message::from(sha256(&message))).unwrap();
		let correct_signature_for_other_message = kp.private().sign(&[43u8; 32].into()).unwrap();
		let mut correct_signature = correct_signature.to_vec();
		let mut correct_signature_for_other_message = correct_signature_for_other_message.to_vec();
		correct_signature.push(0x81);
		correct_signature_for_other_message.push(0x81);

		let correct_flags = VerificationFlags::default()
			.verify_checkdatasig(true)
			.verify_dersig(true)
			.verify_strictenc(true);
		let incorrect_flags = VerificationFlags::default().verify_checkdatasig(false);

		let correct_signature_script = Builder::default()
			.push_data(&*correct_signature)
			.push_data(&*message)
			.push_data(&*pubkey)
			.push_opcode(Opcode::OP_CHECKDATASIG)
			.into_script();

		// <sig> <msg> <pubKey> OP_CHECKDATASIG 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_CHECKDATASIG)), vec![].into());

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

		// <sig> <msg> <pubKey> OP_CHECKDATASIG fails 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_CHECKDATASIG)
			.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_CHECKDATASIG fails if <sig> is not a validly encoded signature with strict DER encoding.
		// <sig> <msg> <pubKey> OP_CHECKDATASIG 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_CHECKDATASIG)
			.into_script();
		basic_test_with_flags(&incorrectly_encoded_signature_script, &correct_flags, Err(Error::SignatureDer), vec![].into());

		// <sig> <msg> <pubKey> OP_CHECKDATASIG fails if signature <sig> is not empty and does not pass signature validation of <msg> and <pubKey>.
		let incorrect_signature_script = Builder::default()
			.push_data(&*correct_signature_for_other_message)
			.push_data(&*message)
			.push_data(&*pubkey)
			.push_opcode(Opcode::OP_CHECKDATASIG)
			.into_script();
		basic_test_with_flags(&incorrect_signature_script, &correct_flags, Ok(false), vec![Bytes::new()].into());

		// <sig> <msg> <pubKey> OP_CHECKDATASIG pops three elements and pushes false onto the stack if <sig> is an empty byte array.
		let empty_signature_script = Builder::default()
			.push_data(&[])
			.push_data(&*message)
			.push_data(&*pubkey)
			.push_opcode(Opcode::OP_CHECKDATASIG)
			.into_script();
		basic_test_with_flags(&empty_signature_script, &correct_flags, Ok(false), vec![Bytes::new()].into());

		// <sig> <msg> <pubKey> OP_CHECKDATASIG pops three elements and pushes true onto the stack if <sig> is a valid signature of <msg> with respect to <pubKey>.
		basic_test_with_flags(&correct_signature_script, &correct_flags, Ok(true), vec![vec![1].into()].into());
	}

	#[test]
	fn checkdatasigverify_spec_tests() {
		// official tests from:
		// https://github.com/bitcoincashorg/bitcoincash.org/blob/0c6f91b0b713aae3bc6c9834b46e80e247ff5fab/spec/op_checkdatasig.md

		let kp = KeyPair::from_private(Private { network: Network::Mainnet, secret: 1.into(), compressed: false, }).unwrap();
		let pubkey = kp.public().clone();
		let message = vec![42u8; 32];
		let correct_signature = kp.private().sign(&Message::from(sha256(&message))).unwrap();
		let correct_signature_for_other_message = kp.private().sign(&[43u8; 32].into()).unwrap();
		let mut correct_signature = correct_signature.to_vec();
		let mut correct_signature_for_other_message = correct_signature_for_other_message.to_vec();
		correct_signature.push(0x81);
		correct_signature_for_other_message.push(0x81);

		let correct_flags = VerificationFlags::default()
			.verify_checkdatasig(true)
			.verify_dersig(true)
			.verify_strictenc(true);
		let incorrect_flags = VerificationFlags::default().verify_checkdatasig(false);

		let correct_signature_script = Builder::default()
			.push_data(&*correct_signature)
			.push_data(&*message)
			.push_data(&*pubkey)
			.push_opcode(Opcode::OP_CHECKDATASIGVERIFY)
			.into_script();