fixed interpreter OP_DUP operation, converting integers to hashes, added more traces
This commit is contained in:
parent
2e51589403
commit
edfc13f0ba
|
@ -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",
|
||||||
]
|
]
|
||||||
|
|
|
@ -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]
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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"
|
||||||
|
|
||||||
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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]
|
||||||
|
|
|
@ -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); }
|
||||||
|
|
Loading…
Reference in New Issue