blockchain.rs 83.7 KiB
Newer Older
		let t1 = Transaction {
			nonce: 0.into(),
			gas_price: 0.into(),
			gas: 100_000.into(),
			action: Action::Create,
			value: 101.into(),
			data: "601080600c6000396000f3006000355415600957005b60203560003555".from_hex().unwrap(),
		let t2 = Transaction {
			nonce: 0.into(),
			gas_price: 0.into(),
			gas: 100_000.into(),
			action: Action::Create,
			value: 102.into(),
			data: "601080600c6000396000f3006000355415600957005b60203560003555".from_hex().unwrap(),
		let t3 = Transaction {
			nonce: 0.into(),
			gas_price: 0.into(),
			gas: 100_000.into(),
			action: Action::Create,
			value: 103.into(),
			data: "601080600c6000396000f3006000355415600957005b60203560003555".from_hex().unwrap(),
		let tx_hash1 = t1.hash();
		let tx_hash2 = t2.hash();
		let tx_hash3 = t3.hash();
		let b1 = canon_chain.with_transaction(t1).with_transaction(t2).generate(&mut finalizer).unwrap();
		let b2 = canon_chain.with_transaction(t3).generate(&mut finalizer).unwrap();

keorn's avatar
keorn committed
		let bc = new_chain(&genesis, db.clone());
		insert_block(&db, &bc, &b1, vec![Receipt {
			state_root: Some(H256::default()),
			gas_used: 10_000.into(),
			log_bloom: Default::default(),
			logs: vec![
				LogEntry { address: Default::default(), topics: vec![], data: vec![1], },
				LogEntry { address: Default::default(), topics: vec![], data: vec![2], },
			],
		},
		Receipt {
			state_root: Some(H256::default()),
			gas_used: 10_000.into(),
			log_bloom: Default::default(),
			logs: vec![
				LogEntry { address: Default::default(), topics: vec![], data: vec![3], },
			],
		}]);
		insert_block(&db, &bc, &b2, vec![
			Receipt {
				state_root: Some(H256::default()),
				gas_used: 10_000.into(),
				log_bloom: Default::default(),
				logs: vec![
					LogEntry { address: Default::default(), topics: vec![], data: vec![4], },
				],
			}
		]);

		// when
		let block1 = BlockView::new(&b1);
		let block2 = BlockView::new(&b2);
		let logs1 = bc.logs(vec![1, 2], |_| true, None);
		let logs2 = bc.logs(vec![1, 2], |_| true, Some(1));

		// then
		assert_eq!(logs1, vec![
			LocalizedLogEntry {
				entry: LogEntry { address: Default::default(), topics: vec![], data: vec![1] },
				block_hash: block1.hash(),
				block_number: block1.header().number(),
				transaction_hash: tx_hash1.clone(),
				transaction_index: 0,
				transaction_log_index: 0,
				log_index: 0,
			},
			LocalizedLogEntry {
				entry: LogEntry { address: Default::default(), topics: vec![], data: vec![2] },
				block_hash: block1.hash(),
				block_number: block1.header().number(),
				transaction_hash: tx_hash1.clone(),
				transaction_index: 0,
				transaction_log_index: 1,
				log_index: 1,
			},
			LocalizedLogEntry {
				entry: LogEntry { address: Default::default(), topics: vec![], data: vec![3] },
				block_hash: block1.hash(),
				block_number: block1.header().number(),
				transaction_hash: tx_hash2.clone(),
				transaction_index: 1,
				transaction_log_index: 0,
				log_index: 2,
			},
			LocalizedLogEntry {
				entry: LogEntry { address: Default::default(), topics: vec![], data: vec![4] },
				block_hash: block2.hash(),
				block_number: block2.header().number(),
				transaction_hash: tx_hash3.clone(),
				transaction_index: 0,
				transaction_log_index: 0,
				log_index: 0,
			}
		]);
		assert_eq!(logs2, vec![
			LocalizedLogEntry {
				entry: LogEntry { address: Default::default(), topics: vec![], data: vec![4] },
				block_hash: block2.hash(),
				block_number: block2.header().number(),
				transaction_hash: tx_hash3.clone(),
				transaction_index: 0,
				transaction_log_index: 0,
	#[test]
	fn test_bloom_filter_simple() {
		// TODO: From here
		let bloom_b1: H2048 = "00000020000000000000000000000000000000000000000002000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000400000000000000000000002000".into();
		let bloom_b2: H2048 = "00000000000000000000000000000000000000000000020000001000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000".into();
		let bloom_ba: H2048 = "00000000000000000000000000000000000000000000020000000800000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000".into();
		let mut canon_chain = ChainGenerator::default();
		let mut finalizer = BlockFinalizer::default();
		let genesis = canon_chain.generate(&mut finalizer).unwrap();
		let mut fork = canon_chain.fork(1);
		let mut fork_finalizer = finalizer.fork();
		let b1 = fork.with_bloom(bloom_b1.clone()).generate(&mut fork_finalizer).unwrap();
		let b2 = fork.with_bloom(bloom_b2.clone()).generate(&mut fork_finalizer).unwrap();
		let b3 = fork.with_bloom(bloom_ba.clone()).generate(&mut fork_finalizer).unwrap();
		let b1a = canon_chain.with_bloom(bloom_ba.clone()).generate(&mut finalizer).unwrap();
		let b2a = canon_chain.with_bloom(bloom_ba.clone()).generate(&mut finalizer).unwrap();

keorn's avatar
keorn committed
		let bc = new_chain(&genesis, db.clone());
Marek Kotewicz's avatar
Marek Kotewicz committed
		let blocks_b1 = bc.blocks_with_bloom(&bloom_b1, 0, 5);
		let blocks_b2 = bc.blocks_with_bloom(&bloom_b2, 0, 5);
Tomasz Drwięga's avatar
Tomasz Drwięga committed
		assert_eq!(blocks_b1, Vec::<BlockNumber>::new());
		assert_eq!(blocks_b2, Vec::<BlockNumber>::new());
Tomasz Drwięga's avatar
Tomasz Drwięga committed
		insert_block(&db, &bc, &b1, vec![]);
Marek Kotewicz's avatar
Marek Kotewicz committed
		let blocks_b1 = bc.blocks_with_bloom(&bloom_b1, 0, 5);
		let blocks_b2 = bc.blocks_with_bloom(&bloom_b2, 0, 5);
		assert_eq!(blocks_b1, vec![1]);
Tomasz Drwięga's avatar
Tomasz Drwięga committed
		assert_eq!(blocks_b2, Vec::<BlockNumber>::new());
Tomasz Drwięga's avatar
Tomasz Drwięga committed
		insert_block(&db, &bc, &b2, vec![]);
Marek Kotewicz's avatar
Marek Kotewicz committed
		let blocks_b1 = bc.blocks_with_bloom(&bloom_b1, 0, 5);
		let blocks_b2 = bc.blocks_with_bloom(&bloom_b2, 0, 5);
		assert_eq!(blocks_b1, vec![1]);
		assert_eq!(blocks_b2, vec![2]);
Tomasz Drwięga's avatar
Tomasz Drwięga committed
		insert_block(&db, &bc, &b1a, vec![]);
Marek Kotewicz's avatar
Marek Kotewicz committed
		let blocks_b1 = bc.blocks_with_bloom(&bloom_b1, 0, 5);
		let blocks_b2 = bc.blocks_with_bloom(&bloom_b2, 0, 5);
		let blocks_ba = bc.blocks_with_bloom(&bloom_ba, 0, 5);
		assert_eq!(blocks_b1, vec![1]);
		assert_eq!(blocks_b2, vec![2]);
Tomasz Drwięga's avatar
Tomasz Drwięga committed
		assert_eq!(blocks_ba, Vec::<BlockNumber>::new());
Tomasz Drwięga's avatar
Tomasz Drwięga committed
		insert_block(&db, &bc, &b2a, vec![]);
Marek Kotewicz's avatar
Marek Kotewicz committed
		let blocks_b1 = bc.blocks_with_bloom(&bloom_b1, 0, 5);
		let blocks_b2 = bc.blocks_with_bloom(&bloom_b2, 0, 5);
		let blocks_ba = bc.blocks_with_bloom(&bloom_ba, 0, 5);
Tomasz Drwięga's avatar
Tomasz Drwięga committed
		assert_eq!(blocks_b1, Vec::<BlockNumber>::new());
		assert_eq!(blocks_b2, Vec::<BlockNumber>::new());
		assert_eq!(blocks_ba, vec![1, 2]);
Marek Kotewicz's avatar
Marek Kotewicz committed

		// fork back
Tomasz Drwięga's avatar
Tomasz Drwięga committed
		insert_block(&db, &bc, &b3, vec![]);
Marek Kotewicz's avatar
Marek Kotewicz committed
		let blocks_b1 = bc.blocks_with_bloom(&bloom_b1, 0, 5);
		let blocks_b2 = bc.blocks_with_bloom(&bloom_b2, 0, 5);
		let blocks_ba = bc.blocks_with_bloom(&bloom_ba, 0, 5);
		assert_eq!(blocks_b1, vec![1]);
		assert_eq!(blocks_b2, vec![2]);
		assert_eq!(blocks_ba, vec![3]);

	#[test]
	fn test_best_block_update() {
		let mut canon_chain = ChainGenerator::default();
		let mut finalizer = BlockFinalizer::default();
		let genesis = canon_chain.generate(&mut finalizer).unwrap();

keorn's avatar
keorn committed
			let bc = new_chain(&genesis, db.clone());
			let uncle = canon_chain.fork(1).generate(&mut finalizer.fork()).unwrap();

			let mut batch = db.transaction();
			// create a longer fork
			for _ in 0..5 {
				let canon_block = canon_chain.generate(&mut finalizer).unwrap();
				bc.insert_block(&mut batch, &canon_block, vec![]);
			}

			assert_eq!(bc.best_block_number(), 5);
			bc.insert_block(&mut batch, &uncle, vec![]);
Tomasz Drwięga's avatar
Tomasz Drwięga committed
			db.write(batch).unwrap();
		}

		// re-loading the blockchain should load the correct best block.
		let bc = new_chain(&genesis, db);
		assert_eq!(bc.best_block_number(), 5);
	}

	#[test]
	fn test_rewind() {
		let mut canon_chain = ChainGenerator::default();
		let mut finalizer = BlockFinalizer::default();
		let genesis = canon_chain.generate(&mut finalizer).unwrap();
		let first = canon_chain.generate(&mut finalizer).unwrap();
		let second = canon_chain.generate(&mut finalizer).unwrap();
		let genesis_hash = BlockView::new(&genesis).header_view().sha3();
		let first_hash = BlockView::new(&first).header_view().sha3();
		let second_hash = BlockView::new(&second).header_view().sha3();

keorn's avatar
keorn committed
		let bc = new_chain(&genesis, db.clone());
		let mut batch =db.transaction();
		bc.insert_block(&mut batch, &first, vec![]);
		bc.insert_block(&mut batch, &second, vec![]);
Tomasz Drwięga's avatar
Tomasz Drwięga committed
		db.write(batch).unwrap();

		assert_eq!(bc.rewind(), Some(first_hash.clone()));
		assert!(!bc.is_known(&second_hash));
		assert_eq!(bc.best_block_number(), 1);
		assert_eq!(bc.best_block_hash(), first_hash.clone());

		assert_eq!(bc.rewind(), Some(genesis_hash.clone()));
		assert_eq!(bc.rewind(), None);
	}

	#[test]
	fn epoch_transitions_iter() {
		use ::engines::EpochTransition;

		let mut canon_chain = ChainGenerator::default();
		let mut finalizer = BlockFinalizer::default();
		let genesis = canon_chain.generate(&mut finalizer).unwrap();

		let db = new_db();
		{
			let bc = new_chain(&genesis, db.clone());
			let uncle = canon_chain.fork(1).generate(&mut finalizer.fork()).unwrap();

			let mut batch = db.transaction();
			// create a longer fork
			for i in 0..5 {
				let canon_block = canon_chain.generate(&mut finalizer).unwrap();
				let hash = BlockView::new(&canon_block).header_view().sha3();

				bc.insert_block(&mut batch, &canon_block, vec![]);
				bc.insert_epoch_transition(&mut batch, i, EpochTransition {
					block_hash: hash,
					block_number: i + 1,
					proof: vec![],
				});
				bc.commit();
			}

			assert_eq!(bc.best_block_number(), 5);

			let hash = BlockView::new(&uncle).header_view().sha3();
			bc.insert_block(&mut batch, &uncle, vec![]);
			bc.insert_epoch_transition(&mut batch, 999, EpochTransition {
				block_hash: hash,
				block_number: 1,
				proof: vec![],
			});

			db.write(batch).unwrap();
			bc.commit();

			// epoch 999 not in canonical chain.
			assert_eq!(bc.epoch_transitions().map(|(i, _)| i).collect::<Vec<_>>(), vec![0, 1, 2, 3, 4]);
		}

		// re-loading the blockchain should load the correct best block.
		let bc = new_chain(&genesis, db);

		assert_eq!(bc.best_block_number(), 5);
		assert_eq!(bc.epoch_transitions().map(|(i, _)| i).collect::<Vec<_>>(), vec![0, 1, 2, 3, 4]);
	}

	#[test]
	fn epoch_transition_for() {
		use ::engines::EpochTransition;

		let mut canon_chain = ChainGenerator::default();
		let mut finalizer = BlockFinalizer::default();
		let genesis = canon_chain.generate(&mut finalizer).unwrap();

		let db = new_db();

		let bc = new_chain(&genesis, db.clone());

		let mut batch = db.transaction();
		bc.insert_epoch_transition(&mut batch, 0, EpochTransition {
			block_hash: bc.genesis_hash(),
			block_number: 0,
			proof: vec![],
		});
		db.write(batch).unwrap();

		// set up a chain where we have a canonical chain of 10 blocks
		// and a non-canonical fork of 8 from genesis.
		let fork_hash = {
			let mut fork_chain = canon_chain.fork(1);
			let mut fork_finalizer = finalizer.fork();

			for _ in 0..7 {
				let mut batch = db.transaction();
				let fork_block = fork_chain.generate(&mut fork_finalizer).unwrap();

				bc.insert_block(&mut batch, &fork_block, vec![]);
				bc.commit();
				db.write(batch).unwrap();
			}

			assert_eq!(bc.best_block_number(), 7);
			bc.chain_info().best_block_hash
		};

		for _ in 0..10 {
			let mut batch = db.transaction();
			let canon_block = canon_chain.generate(&mut finalizer).unwrap();

			bc.insert_block(&mut batch, &canon_block, vec![]);
			bc.commit();

			db.write(batch).unwrap();
		}

		assert_eq!(bc.best_block_number(), 10);

		let mut batch = db.transaction();
		bc.insert_epoch_transition(&mut batch, 4, EpochTransition {
			block_hash: bc.block_hash(4).unwrap(),
			block_number: 4,
			proof: vec![],
		});
		db.write(batch).unwrap();

		// blocks where the parent is one of the first 4 will be part of genesis epoch.
		for i in 0..4 {
			let hash = bc.block_hash(i).unwrap();
			assert_eq!(bc.epoch_transition_for(hash).unwrap().block_number, 0);
		}

		// blocks where the parent is the transition at 4 or after will be
		// part of that epoch.
		for i in 4..11 {
			let hash = bc.block_hash(i).unwrap();
			assert_eq!(bc.epoch_transition_for(hash).unwrap().block_number, 4);
		}

		let fork_hashes = bc.ancestry_iter(fork_hash).unwrap().collect::<Vec<_>>();
		assert_eq!(fork_hashes.len(), 8);

		// non-canonical fork blocks should all have genesis transition
		for fork_hash in fork_hashes {
			assert_eq!(bc.epoch_transition_for(fork_hash).unwrap().block_number, 0);
		}
	}