|
1 | 1 | #[cfg(test)] |
2 | 2 | mod tests { |
3 | 3 | use bitcoin::consensus::deserialize; |
4 | | - use bitcoinkernel::core::transaction::TxIn; |
| 4 | + use bitcoinkernel::core::transaction::{TxIn, TxInExt, TxOutPointExt, TxOutPointRef}; |
5 | 5 | use bitcoinkernel::notifications::types::{BlockValidationStateExt, BlockValidationStateRef}; |
6 | 6 | use bitcoinkernel::{ |
7 | 7 | prelude::*, verify, Block, BlockHash, BlockSpentOutputs, BlockTreeEntry, ChainParams, |
@@ -457,13 +457,74 @@ mod tests { |
457 | 457 | let (context, data_dir) = testing_setup(); |
458 | 458 | let blocks_dir = data_dir.clone() + "/blocks"; |
459 | 459 | let block_data = read_block_data(); |
| 460 | + let blocks: Vec<Block> = block_data |
| 461 | + .iter() |
| 462 | + .map(|data| Block::new(data.as_slice()).unwrap()) |
| 463 | + .collect(); |
460 | 464 | let chainman = ChainstateManager::new(&context, &data_dir, &blocks_dir).unwrap(); |
461 | 465 |
|
462 | | - for raw_block in block_data.iter() { |
463 | | - let block = Block::new(raw_block.as_slice()).unwrap(); |
| 466 | + for block in blocks.iter() { |
| 467 | + let (accepted, state) = chainman.process_header(&block.header()); |
| 468 | + assert!(accepted); |
| 469 | + assert_eq!(state.mode(), ValidationMode::Valid); |
| 470 | + } |
| 471 | + } |
| 472 | + |
| 473 | + fn find_output<'a>(blocks: &'a [Block], outpoint: TxOutPointRef) -> Option<TxOut> { |
| 474 | + for block in blocks.iter() { |
| 475 | + for i in 0..block.transaction_count() { |
| 476 | + let tx = block.transaction(i).unwrap(); |
| 477 | + if tx.txid() != outpoint.txid() { |
| 478 | + continue; |
| 479 | + } |
| 480 | + return tx |
| 481 | + .output(outpoint.index() as usize) |
| 482 | + .ok() |
| 483 | + .map(|out| out.to_owned()); |
| 484 | + } |
| 485 | + } |
| 486 | + None |
| 487 | + } |
| 488 | + |
| 489 | + #[test] |
| 490 | + fn test_block_validation() { |
| 491 | + let (context, data_dir) = testing_setup(); |
| 492 | + let blocks_dir = data_dir.clone() + "/blocks"; |
| 493 | + let block_data = read_block_data(); |
| 494 | + let blocks: Vec<Block> = block_data |
| 495 | + .iter() |
| 496 | + .map(|data| Block::new(data.as_slice()).unwrap()) |
| 497 | + .collect(); |
| 498 | + let chainman = ChainstateManager::new(&context, &data_dir, &blocks_dir).unwrap(); |
| 499 | + |
| 500 | + let mut block_spent_outputs: Vec<BlockSpentOutputs> = vec![]; |
| 501 | + |
| 502 | + for block in blocks.iter() { |
| 503 | + let mut coins: Vec<Vec<Coin>> = vec![]; |
| 504 | + for i in 0..block.transaction_count() { |
| 505 | + let tx = block.transaction(i).unwrap(); |
| 506 | + if tx.is_coinbase() { |
| 507 | + println!("tx is coinbase!"); |
| 508 | + continue; |
| 509 | + } |
| 510 | + coins.push(Vec::new()); |
| 511 | + for j in 0..tx.input_count() { |
| 512 | + let output = find_output(&blocks, tx.input(j).unwrap().outpoint()).unwrap(); |
| 513 | + println!("Accessing coins i {i}"); |
| 514 | + coins[i - 1].push(Coin::new(&output)); |
| 515 | + } |
| 516 | + } |
| 517 | + block_spent_outputs.push(BlockSpentOutputs::new(&coins)); |
| 518 | + } |
| 519 | + |
| 520 | + for (block, block_spent_outputs) in blocks.iter().zip(block_spent_outputs.iter()) { |
464 | 521 | let (accepted, state) = chainman.process_header(&block.header()); |
465 | 522 | assert!(accepted); |
466 | 523 | assert_eq!(state.mode(), ValidationMode::Valid); |
| 524 | + |
| 525 | + let (result, state) = chainman.validate_block(block, &block_spent_outputs); |
| 526 | + assert!(result); |
| 527 | + assert_eq!(state.mode(), ValidationMode::Valid); |
467 | 528 | } |
468 | 529 | } |
469 | 530 |
|
|
0 commit comments