fixed interpreter OP_DUP operation, converting integers to hashes, added more traces

This commit is contained in:
debris 2016-11-21 17:05:42 +01:00
parent 2e51589403
commit edfc13f0ba
9 changed files with 45 additions and 40 deletions

1
Cargo.lock generated
View File

@ -594,6 +594,7 @@ dependencies = [
"bitcrypto 0.1.0", "bitcrypto 0.1.0",
"chain 0.1.0", "chain 0.1.0",
"keys 0.1.0", "keys 0.1.0",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"primitives 0.1.0", "primitives 0.1.0",
"serialization 0.1.0", "serialization 0.1.0",
] ]

View File

@ -156,6 +156,7 @@ pub fn checksum(data: &[u8]) -> H32 {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use primitives::bytes::Bytes;
use super::{ripemd160, sha1, sha256, dhash160, dhash256, checksum}; use super::{ripemd160, sha1, sha256, dhash160, dhash256, checksum};
#[test] #[test]
@ -184,6 +185,11 @@ mod tests {
let expected = "b6a9c8c230722b7c748331a8b450f05566dc7d0f".into(); let expected = "b6a9c8c230722b7c748331a8b450f05566dc7d0f".into();
let result = dhash160(b"hello"); let result = dhash160(b"hello");
assert_eq!(result, expected); assert_eq!(result, expected);
let expected = "865c71bfc7e314709207ab9e7e205c6f8e453d08".into();
let bytes: Bytes = "210292be03ed9475445cc24a34a115c641a67e4ff234ccb08cb4c5cea45caa526cb26ead6ead6ead6ead6eadac".into();
let result = dhash160(&bytes);
assert_eq!(result, expected);
} }
#[test] #[test]

View File

@ -77,7 +77,7 @@ mod tests {
#[test] #[test]
fn test_inventory_serialize() { fn test_inventory_serialize() {
let expected = "020000000000000000000000000000000000000000000000000000000000000000000004".into(); let expected = "020000000400000000000000000000000000000000000000000000000000000000000000".into();
let inventory = InventoryVector { let inventory = InventoryVector {
inv_type: InventoryType::MessageBlock, inv_type: InventoryType::MessageBlock,
@ -89,7 +89,7 @@ mod tests {
#[test] #[test]
fn test_inventory_deserialize() { fn test_inventory_deserialize() {
let raw: Bytes = "020000000000000000000000000000000000000000000000000000000000000000000004".into(); let raw: Bytes = "020000000400000000000000000000000000000000000000000000000000000000000000".into();
let expected = InventoryVector { let expected = InventoryVector {
inv_type: InventoryType::MessageBlock, inv_type: InventoryType::MessageBlock,

View File

@ -50,7 +50,7 @@ macro_rules! impl_hash {
impl From<u8> for $name { impl From<u8> for $name {
fn from(v: u8) -> Self { fn from(v: u8) -> Self {
let mut result = Self::default(); let mut result = Self::default();
result.0[$size - 1] = v; result.0[0] = v;
result result
} }
} }

View File

@ -9,5 +9,4 @@ chain = { path = "../chain" }
keys = { path = "../keys" } keys = { path = "../keys" }
primitives = { path = "../primitives" } primitives = { path = "../primitives" }
serialization = { path = "../serialization" } serialization = { path = "../serialization" }
log = "0.3"

View File

@ -1895,3 +1895,4 @@ mod tests {
assert_eq!(verify_script(&input, &output, &flags, &checker), Err(Error::NumberOverflow)); assert_eq!(verify_script(&input, &output, &flags, &checker), Err(Error::NumberOverflow));
} }
} }

View File

@ -1,3 +1,5 @@
#[macro_use]
extern crate log;
extern crate bitcrypto as crypto; extern crate bitcrypto as crypto;
extern crate chain; extern crate chain;
extern crate keys; extern crate keys;

View File

@ -88,7 +88,7 @@ impl<T> Stack<T> {
try!(self.require(i)); try!(self.require(i));
let mut j = i; let mut j = i;
while j > 0 { while j > 0 {
let v = self.data[self.data.len() - j].clone(); let v = self.data[self.data.len() - i].clone();
self.data.push(v); self.data.push(v);
j -= 1; j -= 1;
} }
@ -263,9 +263,8 @@ mod tests {
assert_eq!(stack.dup(2), Ok(())); assert_eq!(stack.dup(2), Ok(()));
assert_eq!(stack, vec![0, 0, 0, 0].into()); assert_eq!(stack, vec![0, 0, 0, 0].into());
let mut stack: Stack<u8> = vec![0, 1].into(); let mut stack: Stack<u8> = vec![0, 1].into();
assert_eq!(stack.dup(1), Ok(()));
assert_eq!(stack.dup(2), Ok(())); assert_eq!(stack.dup(2), Ok(()));
assert_eq!(stack, vec![0, 1, 1, 1, 1].into()); assert_eq!(stack, vec![0, 1, 0, 1].into());
} }
#[test] #[test]

View File

@ -121,15 +121,11 @@ impl ChainVerifier {
for (input_index, input) in transaction.inputs().iter().enumerate() { for (input_index, input) in transaction.inputs().iter().enumerate() {
let store_parent_transaction = self.store.transaction(&input.previous_output.hash); let store_parent_transaction = self.store.transaction(&input.previous_output.hash);
let parent_transaction = match store_parent_transaction { let parent_transaction = store_parent_transaction
Some(ref tx) => tx, .as_ref()
None => { .or_else(|| block.transactions.iter().find(|t| t.hash() == input.previous_output.hash))
match block.transactions.iter().filter(|t| t.hash() == input.previous_output.hash).nth(0) { .ok_or_else(|| TransactionError::Inconclusive(input.previous_output.hash.clone()))?;
Some(tx) => tx,
None => { return Err(TransactionError::Inconclusive(input.previous_output.hash.clone())); },
}
},
};
if parent_transaction.outputs.len() <= input.previous_output.index as usize { if parent_transaction.outputs.len() <= input.previous_output.index as usize {
return Err(TransactionError::Input(input_index)); return Err(TransactionError::Input(input_index));
} }
@ -152,7 +148,9 @@ impl ChainVerifier {
if self.skip_sig { continue; } if self.skip_sig { continue; }
if let Err(e) = verify_script(&input, &output, &flags, &checker) { if let Err(e) = verify_script(&input, &output, &flags, &checker) {
trace!(target: "verification", "transaction signature verification failure: {}", e); trace!(target: "verification", "transaction signature verification failure: {:?}", e);
trace!(target: "verification", "input:\n{}", input);
trace!(target: "verification", "output:\n{}", output);
// todo: log error here // todo: log error here
return Err(TransactionError::Signature(input_index)) return Err(TransactionError::Signature(input_index))
} }
@ -160,10 +158,8 @@ impl ChainVerifier {
Ok(()) Ok(())
} }
}
impl Verify for ChainVerifier { fn verify_block(&self, block: &chain::Block) -> VerificationResult {
fn verify(&self, block: &chain::Block) -> VerificationResult {
let hash = block.hash(); let hash = block.hash();
// There should be at least 1 transaction // There should be at least 1 transaction
@ -206,32 +202,21 @@ impl Verify for ChainVerifier {
} }
// verify transactions (except coinbase) // verify transactions (except coinbase)
let mut block_sigops = try!( let mut block_sigops = utils::transaction_sigops(&block.transactions()[0])
utils::transaction_sigops(&block.transactions()[0]) .map_err(|e| Error::Transaction(1, TransactionError::SignatureMallformed(e.to_string())))?;
.map_err(|e| Error::Transaction(1, TransactionError::SignatureMallformed(format!("{}", e))))
);
for (idx, transaction) in block.transactions().iter().skip(1).enumerate() { for (idx, transaction) in block.transactions().iter().enumerate().skip(1) {
block_sigops += try!( block_sigops += utils::transaction_sigops(transaction)
utils::transaction_sigops(transaction) .map_err(|e| Error::Transaction(idx, TransactionError::SignatureMallformed(e.to_string())))?;
.map_err(|e| Error::Transaction(idx+1, TransactionError::SignatureMallformed(format!("{}", e))))
);
if block_sigops > MAX_BLOCK_SIGOPS { if block_sigops > MAX_BLOCK_SIGOPS {
return Err(Error::MaximumSigops); return Err(Error::MaximumSigops);
} }
try!(self.verify_transaction(block, transaction).map_err(|e| Error::Transaction(idx+1, e))); try!(self.verify_transaction(block, transaction).map_err(|e| Error::Transaction(idx, e)));
} }
trace!(
target: "verification", "Block {} (transactons: {}, sigops: {}) verification finished",
&hash,
block.transactions().len(),
&block_sigops
);
// todo: pre-process projected block number once verification is parallel! // todo: pre-process projected block number once verification is parallel!
match self.store.accepted_location(block.header()) { match self.store.accepted_location(block.header()) {
None => { None => {
@ -249,16 +234,28 @@ impl Verify for ChainVerifier {
} }
} }
impl Verify for ChainVerifier {
fn verify(&self, block: &chain::Block) -> VerificationResult {
let result = self.verify_block(block);
trace!(
target: "verification", "Block {} (transactions: {}) verification finished. Result {:?}",
block.hash().to_reversed_str(),
block.transactions().len(),
result,
);
result
}
}
impl ContinueVerify for ChainVerifier { impl ContinueVerify for ChainVerifier {
type State = usize; type State = usize;
fn continue_verify(&self, block: &chain::Block, state: usize) -> VerificationResult { fn continue_verify(&self, block: &chain::Block, state: usize) -> VerificationResult {
// verify transactions (except coinbase) // verify transactions (except coinbase)
for (idx, transaction) in block.transactions().iter().skip(state-1).enumerate() { for (idx, transaction) in block.transactions().iter().enumerate().skip(state - 1) {
try!(self.verify_transaction(block, transaction).map_err(|e| Error::Transaction(idx, e))); try!(self.verify_transaction(block, transaction).map_err(|e| Error::Transaction(idx, e)));
} }
let _parent = match self.store.block(BlockRef::Hash(block.header().previous_header_hash.clone())) { let _parent = match self.store.block(BlockRef::Hash(block.header().previous_header_hash.clone())) {
Some(b) => b, Some(b) => b,
None => { return Ok(Chain::Orphan); } None => { return Ok(Chain::Orphan); }