Consolidate validation in Block and Transaction (#1354)
* Consolidate validation in Block and Transaction Introduce TransactionBody which is included into block and tx. Fixes #1333
This commit is contained in:
+27
-29
@@ -12,25 +12,25 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
extern crate chrono;
|
||||
extern crate grin_core;
|
||||
extern crate grin_keychain as keychain;
|
||||
extern crate grin_util as util;
|
||||
extern crate grin_wallet as wallet;
|
||||
extern crate chrono;
|
||||
|
||||
pub mod common;
|
||||
|
||||
use chrono::Duration;
|
||||
use common::{new_block, tx1i2o, tx2i1o, txspend1i1o};
|
||||
use grin_core::consensus::{BLOCK_OUTPUT_WEIGHT, MAX_BLOCK_WEIGHT};
|
||||
use grin_core::core::Committed;
|
||||
use grin_core::core::block::Error;
|
||||
use grin_core::core::hash::Hashed;
|
||||
use grin_core::core::id::{ShortId, ShortIdentifiable};
|
||||
use grin_core::core::Committed;
|
||||
use grin_core::core::{Block, BlockHeader, CompactBlock, KernelFeatures, OutputFeatures};
|
||||
use grin_core::{global, ser};
|
||||
use keychain::{BlindingFactor, ExtKeychain, Keychain};
|
||||
use std::time::Instant;
|
||||
use chrono::Duration;
|
||||
use util::{secp, secp_static};
|
||||
use wallet::libtx::build::{self, input, output, with_fee};
|
||||
|
||||
@@ -68,12 +68,7 @@ fn too_large_block() {
|
||||
// block with no inputs/outputs/kernels
|
||||
// no fees, no reward, no coinbase
|
||||
fn very_empty_block() {
|
||||
let b = Block {
|
||||
header: BlockHeader::default(),
|
||||
inputs: vec![],
|
||||
outputs: vec![],
|
||||
kernels: vec![],
|
||||
};
|
||||
let b = Block::with_header(BlockHeader::default());
|
||||
|
||||
assert_eq!(
|
||||
b.verify_coinbase(),
|
||||
@@ -113,8 +108,8 @@ fn block_with_cut_through() {
|
||||
// output) and should still be valid
|
||||
println!("3");
|
||||
b.validate(&BlindingFactor::zero(), &zero_commit).unwrap();
|
||||
assert_eq!(b.inputs.len(), 3);
|
||||
assert_eq!(b.outputs.len(), 3);
|
||||
assert_eq!(b.inputs().len(), 3);
|
||||
assert_eq!(b.outputs().len(), 3);
|
||||
println!("4");
|
||||
}
|
||||
|
||||
@@ -126,18 +121,20 @@ fn empty_block_with_coinbase_is_valid() {
|
||||
let key_id = keychain.derive_key_id(1).unwrap();
|
||||
let b = new_block(vec![], &keychain, &prev, &key_id);
|
||||
|
||||
assert_eq!(b.inputs.len(), 0);
|
||||
assert_eq!(b.outputs.len(), 1);
|
||||
assert_eq!(b.kernels.len(), 1);
|
||||
assert_eq!(b.inputs().len(), 0);
|
||||
assert_eq!(b.outputs().len(), 1);
|
||||
assert_eq!(b.kernels().len(), 1);
|
||||
|
||||
let coinbase_outputs = b.outputs
|
||||
let coinbase_outputs = b
|
||||
.outputs()
|
||||
.iter()
|
||||
.filter(|out| out.features.contains(OutputFeatures::COINBASE_OUTPUT))
|
||||
.map(|o| o.clone())
|
||||
.collect::<Vec<_>>();
|
||||
assert_eq!(coinbase_outputs.len(), 1);
|
||||
|
||||
let coinbase_kernels = b.kernels
|
||||
let coinbase_kernels = b
|
||||
.kernels()
|
||||
.iter()
|
||||
.filter(|out| out.features.contains(KernelFeatures::COINBASE_KERNEL))
|
||||
.map(|o| o.clone())
|
||||
@@ -161,11 +158,11 @@ fn remove_coinbase_output_flag() {
|
||||
let mut b = new_block(vec![], &keychain, &prev, &key_id);
|
||||
|
||||
assert!(
|
||||
b.outputs[0]
|
||||
b.outputs()[0]
|
||||
.features
|
||||
.contains(OutputFeatures::COINBASE_OUTPUT)
|
||||
);
|
||||
b.outputs[0]
|
||||
b.outputs_mut()[0]
|
||||
.features
|
||||
.remove(OutputFeatures::COINBASE_OUTPUT);
|
||||
|
||||
@@ -191,11 +188,11 @@ fn remove_coinbase_kernel_flag() {
|
||||
let mut b = new_block(vec![], &keychain, &prev, &key_id);
|
||||
|
||||
assert!(
|
||||
b.kernels[0]
|
||||
b.kernels()[0]
|
||||
.features
|
||||
.contains(KernelFeatures::COINBASE_KERNEL)
|
||||
);
|
||||
b.kernels[0]
|
||||
b.kernels_mut()[0]
|
||||
.features
|
||||
.remove(KernelFeatures::COINBASE_KERNEL);
|
||||
|
||||
@@ -224,12 +221,13 @@ fn serialize_deserialize_block() {
|
||||
// After header serialization, timestamp will lose 'nanos' info, that's the designed behavior.
|
||||
// To suppress 'nanos' difference caused assertion fail, we force b.header also lose 'nanos'.
|
||||
let origin_ts = b.header.timestamp;
|
||||
b.header.timestamp = origin_ts - Duration::nanoseconds(origin_ts.timestamp_subsec_nanos() as i64);
|
||||
b.header.timestamp =
|
||||
origin_ts - Duration::nanoseconds(origin_ts.timestamp_subsec_nanos() as i64);
|
||||
|
||||
assert_eq!(b.header, b2.header);
|
||||
assert_eq!(b.inputs, b2.inputs);
|
||||
assert_eq!(b.outputs, b2.outputs);
|
||||
assert_eq!(b.kernels, b2.kernels);
|
||||
assert_eq!(b.inputs(), b2.inputs());
|
||||
assert_eq!(b.outputs(), b2.outputs());
|
||||
assert_eq!(b.kernels(), b2.kernels());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -341,11 +339,11 @@ fn compact_block_hash_with_nonce() {
|
||||
// correctly in both of the compact_blocks
|
||||
assert_eq!(
|
||||
cb1.kern_ids[0],
|
||||
tx.kernels[0].short_id(&cb1.hash(), cb1.nonce)
|
||||
tx.kernels()[0].short_id(&cb1.hash(), cb1.nonce)
|
||||
);
|
||||
assert_eq!(
|
||||
cb2.kern_ids[0],
|
||||
tx.kernels[0].short_id(&cb2.hash(), cb2.nonce)
|
||||
tx.kernels()[0].short_id(&cb2.hash(), cb2.nonce)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -364,7 +362,7 @@ fn convert_block_to_compact_block() {
|
||||
|
||||
assert_eq!(
|
||||
cb.kern_ids[0],
|
||||
b.kernels
|
||||
b.kernels()
|
||||
.iter()
|
||||
.find(|x| !x.features.contains(KernelFeatures::COINBASE_KERNEL))
|
||||
.unwrap()
|
||||
@@ -381,8 +379,8 @@ fn hydrate_empty_compact_block() {
|
||||
let cb = b.as_compact_block();
|
||||
let hb = Block::hydrate_from(cb, vec![]);
|
||||
assert_eq!(hb.header, b.header);
|
||||
assert_eq!(hb.outputs, b.outputs);
|
||||
assert_eq!(hb.kernels, b.kernels);
|
||||
assert_eq!(hb.outputs(), b.outputs());
|
||||
assert_eq!(hb.kernels(), b.kernels());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
+34
-24
@@ -28,8 +28,9 @@ use grin_core::core::{aggregate, deaggregate, KernelFeatures, Output, Transactio
|
||||
use grin_core::ser;
|
||||
use keychain::{BlindingFactor, ExtKeychain, Keychain};
|
||||
use util::{secp_static, static_secp_instance};
|
||||
use wallet::libtx::build::{self, initial_tx, input, output, with_excess, with_fee,
|
||||
with_lock_height};
|
||||
use wallet::libtx::build::{
|
||||
self, initial_tx, input, output, with_excess, with_fee, with_lock_height,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn simple_tx_ser() {
|
||||
@@ -47,8 +48,8 @@ fn simple_tx_ser_deser() {
|
||||
ser::serialize(&mut vec, &tx).expect("serialization failed");
|
||||
let dtx: Transaction = ser::deserialize(&mut &vec[..]).unwrap();
|
||||
assert_eq!(dtx.fee(), 2);
|
||||
assert_eq!(dtx.inputs.len(), 2);
|
||||
assert_eq!(dtx.outputs.len(), 1);
|
||||
assert_eq!(dtx.inputs().len(), 2);
|
||||
assert_eq!(dtx.outputs().len(), 1);
|
||||
assert_eq!(tx.hash(), dtx.hash());
|
||||
}
|
||||
|
||||
@@ -108,8 +109,8 @@ fn build_tx_kernel() {
|
||||
tx.validate(false).unwrap();
|
||||
|
||||
// check the kernel is also itself valid
|
||||
assert_eq!(tx.kernels.len(), 1);
|
||||
let kern = &tx.kernels[0];
|
||||
assert_eq!(tx.kernels().len(), 1);
|
||||
let kern = &tx.kernels()[0];
|
||||
kern.verify().unwrap();
|
||||
|
||||
assert_eq!(kern.features, KernelFeatures::DEFAULT_KERNEL);
|
||||
@@ -145,7 +146,10 @@ fn multi_kernel_transaction_deaggregation() {
|
||||
assert!(tx3.validate(false).is_ok());
|
||||
assert!(tx4.validate(false).is_ok());
|
||||
|
||||
let tx1234 = aggregate(vec![tx1.clone(), tx2.clone(), tx3.clone(), tx4.clone()], None).unwrap();
|
||||
let tx1234 = aggregate(
|
||||
vec![tx1.clone(), tx2.clone(), tx3.clone(), tx4.clone()],
|
||||
None,
|
||||
).unwrap();
|
||||
let tx12 = aggregate(vec![tx1.clone(), tx2.clone()], None).unwrap();
|
||||
let tx34 = aggregate(vec![tx3.clone(), tx4.clone()], None).unwrap();
|
||||
|
||||
@@ -220,13 +224,16 @@ fn multi_kernel_transaction_deaggregation_4() {
|
||||
assert!(tx4.validate(false).is_ok());
|
||||
assert!(tx5.validate(false).is_ok());
|
||||
|
||||
let tx12345 = aggregate(vec![
|
||||
tx1.clone(),
|
||||
tx2.clone(),
|
||||
tx3.clone(),
|
||||
tx4.clone(),
|
||||
tx5.clone(),
|
||||
], None).unwrap();
|
||||
let tx12345 = aggregate(
|
||||
vec![
|
||||
tx1.clone(),
|
||||
tx2.clone(),
|
||||
tx3.clone(),
|
||||
tx4.clone(),
|
||||
tx5.clone(),
|
||||
],
|
||||
None,
|
||||
).unwrap();
|
||||
assert!(tx12345.validate(false).is_ok());
|
||||
|
||||
let deaggregated_tx5 = deaggregate(
|
||||
@@ -251,13 +258,16 @@ fn multi_kernel_transaction_deaggregation_5() {
|
||||
assert!(tx4.validate(false).is_ok());
|
||||
assert!(tx5.validate(false).is_ok());
|
||||
|
||||
let tx12345 = aggregate(vec![
|
||||
tx1.clone(),
|
||||
tx2.clone(),
|
||||
tx3.clone(),
|
||||
tx4.clone(),
|
||||
tx5.clone(),
|
||||
], None).unwrap();
|
||||
let tx12345 = aggregate(
|
||||
vec![
|
||||
tx1.clone(),
|
||||
tx2.clone(),
|
||||
tx3.clone(),
|
||||
tx4.clone(),
|
||||
tx5.clone(),
|
||||
],
|
||||
None,
|
||||
).unwrap();
|
||||
let tx12 = aggregate(vec![tx1.clone(), tx2.clone()], None).unwrap();
|
||||
let tx34 = aggregate(vec![tx3.clone(), tx4.clone()], None).unwrap();
|
||||
|
||||
@@ -309,9 +319,9 @@ fn hash_output() {
|
||||
],
|
||||
&keychain,
|
||||
).unwrap();
|
||||
let h = tx.outputs[0].hash();
|
||||
let h = tx.outputs()[0].hash();
|
||||
assert!(h != ZERO_HASH);
|
||||
let h2 = tx.outputs[1].hash();
|
||||
let h2 = tx.outputs()[1].hash();
|
||||
assert!(h != h2);
|
||||
}
|
||||
|
||||
@@ -325,7 +335,7 @@ fn blind_tx() {
|
||||
// with a bullet proof causes painful errors
|
||||
|
||||
// checks that the range proof on our blind output is sufficiently hiding
|
||||
let Output { proof, .. } = btx.outputs[0];
|
||||
let Output { proof, .. } = btx.outputs()[0];
|
||||
|
||||
let secp = static_secp_instance();
|
||||
let secp = secp.lock().unwrap();
|
||||
|
||||
Reference in New Issue
Block a user