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",
"chain 0.1.0",
"keys 0.1.0",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"primitives 0.1.0",
"serialization 0.1.0",
]

View File

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

View File

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

View File

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

View File

@ -9,5 +9,4 @@ chain = { path = "../chain" }
keys = { path = "../keys" }
primitives = { path = "../primitives" }
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));
}
}

View File

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

View File

@ -88,7 +88,7 @@ impl<T> Stack<T> {
try!(self.require(i));
let mut j = i;
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);
j -= 1;
}
@ -263,9 +263,8 @@ mod tests {
assert_eq!(stack.dup(2), Ok(()));
assert_eq!(stack, vec![0, 0, 0, 0].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, vec![0, 1, 1, 1, 1].into());
assert_eq!(stack, vec![0, 1, 0, 1].into());
}
#[test]

View File

@ -121,15 +121,11 @@ impl ChainVerifier {
for (input_index, input) in transaction.inputs().iter().enumerate() {
let store_parent_transaction = self.store.transaction(&input.previous_output.hash);
let parent_transaction = match store_parent_transaction {
Some(ref tx) => tx,
None => {
match block.transactions.iter().filter(|t| t.hash() == input.previous_output.hash).nth(0) {
Some(tx) => tx,
None => { return Err(TransactionError::Inconclusive(input.previous_output.hash.clone())); },
}
},
};
let parent_transaction = store_parent_transaction
.as_ref()
.or_else(|| block.transactions.iter().find(|t| t.hash() == input.previous_output.hash))
.ok_or_else(|| TransactionError::Inconclusive(input.previous_output.hash.clone()))?;
if parent_transaction.outputs.len() <= input.previous_output.index as usize {
return Err(TransactionError::Input(input_index));
}
@ -152,7 +148,9 @@ impl ChainVerifier {
if self.skip_sig { continue; }
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
return Err(TransactionError::Signature(input_index))
}
@ -160,10 +158,8 @@ impl ChainVerifier {
Ok(())
}
}
impl Verify for ChainVerifier {
fn verify(&self, block: &chain::Block) -> VerificationResult {
fn verify_block(&self, block: &chain::Block) -> VerificationResult {
let hash = block.hash();
// There should be at least 1 transaction
@ -206,32 +202,21 @@ impl Verify for ChainVerifier {
}
// verify transactions (except coinbase)
let mut block_sigops = try!(
utils::transaction_sigops(&block.transactions()[0])
.map_err(|e| Error::Transaction(1, TransactionError::SignatureMallformed(format!("{}", e))))
);
let mut block_sigops = utils::transaction_sigops(&block.transactions()[0])
.map_err(|e| Error::Transaction(1, TransactionError::SignatureMallformed(e.to_string())))?;
for (idx, transaction) in block.transactions().iter().skip(1).enumerate() {
for (idx, transaction) in block.transactions().iter().enumerate().skip(1) {
block_sigops += try!(
utils::transaction_sigops(transaction)
.map_err(|e| Error::Transaction(idx+1, TransactionError::SignatureMallformed(format!("{}", e))))
);
block_sigops += utils::transaction_sigops(transaction)
.map_err(|e| Error::Transaction(idx, TransactionError::SignatureMallformed(e.to_string())))?;
if block_sigops > MAX_BLOCK_SIGOPS {
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!
match self.store.accepted_location(block.header()) {
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 {
type State = usize;
fn continue_verify(&self, block: &chain::Block, state: usize) -> VerificationResult {
// 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)));
}
let _parent = match self.store.block(BlockRef::Hash(block.header().previous_header_hash.clone())) {
Some(b) => b,
None => { return Ok(Chain::Orphan); }