Introduce inherent digests (#2466)

* Introduce inherent digests

* Implement inherent digests

* fix silly error

* Implementation of inherent digests in BABE

All tests pass. There are still limitations:

1. The runtime strips out inherent digests, so BABE must re-add them.
2. The test runtime checks that it can re-compute all digests.  It
   can’t, so I had to comment out that test.

* Fix compilation and seal import

Seals were not imported correctly: the pre-digest was imported twice,
instead of both it and the seal being imported.  Also, other parts of
the code did not compile due to incomplete refactoring.

* Remove bogus assertion

* Fix testsuite compilation

* Remove unused import

* Fix compiler diagnostics

* Add inherent digest parameters to block constructors

This enforces that inherent digests are added first.

* Fixup Cargo.lock

* Fix build errors

* Re-add an incorrectly removed import

* Bump primitive-types version

* Update Cargo.lock

* Refactoring

* Use inherent digests for AuRa

They do reach the runtime, but get stripped.  I have not figured out
where.

* Fix compilation errors

* Fix compilation errors due to incorrect types

* Fix whitespace

Suggested-by: Tomasz Drwiega <tomasz@parity.io>

* Add preamble

Suggested-by: Tomasz Drwiega <tomasz@parity.io>

* Fix silly compile error

* Refactor pre-digest finding code into a separate function

* Remove unwanted assertion

It is too likely to bring down the entire blockchain.

Suggested-by: Tomasz Drwiega <tomasz@parity.io>

* Use `find_pre_digest` after runtime, too

Also, use `Member` trait rather than rolling our own requirements.

Suggested-by: Tomasz Drwiega <tomasz@parity.io>

* Fix various warnings

mostly due to upgrading the dependency on `error_chain`.

* Pre-digests nearly complete

This nearly completes the implementation of pre-runtime digests.

* `Seal2` → `Seal` and fix test suite

* Try to fix the storage error

* Try to fix storage (again)

* Fix tests

* Hopefully finish pre-runtime digests

The key is to pass *only* the pre-runtime digests to the runtime.  The
others must be stripped out by `initialize_block`.

* Fix silly typo

* Fix another silly mistake

* Remove unnecessary filtering of BABE pre-digests

We no longer get duplicate BABE pre-digests, so if they appear, the
header should be rejected outright.

* Update Cargo.lock files

* Reformatting

* Fix silly typo in inherent digest code

Also, revert `error.rs` files that contained calls to the `error_chain!`
macro.

* Try to keep the runtime from stripping pre-digests

Currently runs into the “Storage root must match that calculated”
assertion.

* Don’t compute storage root until storage changes are done.

Also, fix a compilation error.

* Fix compile-time error

* Fix compilation errors

* Fix more compile errors

* Hopefully it compiles this time…

* Fix compilation and add docs

* Prevent BABE from adding duplicate pre-runtime digests

Found by comparing with the AuRa code.  I also did some refactoring.

* Respond to review and fix some warnings

* Delete some dead code introduced earlier

* More dead code goes away

* `ref mut` → `&mut`

* Respond to review and fix some warnings

* Fix compilation error

* Remove unneeded `HashT` type parameter

Suggested-by: Robert Habermeier <robert@parity.io>

* Remove spurious #[allow(deprecated)]

* Document inherent digest parameter to `build_block`

* Delete `Simple` trait

It wasn’t needed

* delete wrongly added files

* Fix trait bounds

* Digest serialization tests

I also did some reformatting and cleanup.

* Apply suggestions from code review

Reformatting

Co-Authored-By: André Silva <andre.beat@gmail.com>

* Swap two arguments to `propose` and `propose_with`

Also, remove some needless unsafe code.

* Remove bogus `#![allow(deprecated)]` annotations

With the removal of the deprecated `Seal` variant, these are not needed.

* Add a missing `#[allow(deprecated)]` in the AuRa tests

* Fix silly compile error

* Fix silly compiler error

RLS did not tell me that I hadn’t fixed `babe/lib.rs`, so I missed it.

* Fixes made automatically by Cargo
This commit is contained in:
DemiMarie-parity
2019-05-29 08:13:38 -04:00
committed by Gavin Wood
parent e9a4c80c40
commit c7d1204ce5
55 changed files with 1031 additions and 871 deletions
+2 -2
View File
@@ -73,7 +73,7 @@ fn aura_reports_offline() {
}
with_externalities(&mut new_test_ext(vec![0, 1, 2, 3]), || {
System::initialize(&1, &Default::default(), &Default::default());
System::initialize(&1, &Default::default(), &Default::default(), &Default::default());
let slot_duration = Aura::slot_duration();
Aura::on_timestamp_set::<HandleTestReport>(5 * slot_duration, slot_duration);
@@ -82,7 +82,7 @@ fn aura_reports_offline() {
// no slashing when last step was 0.
assert_eq!(SLASH_COUNTS.lock().as_slice(), &[0, 0, 0, 0]);
System::initialize(&2, &header.hash(), &Default::default());
System::initialize(&2, &header.hash(), &Default::default(), &Default::default());
Aura::on_timestamp_set::<HandleTestReport>(8 * slot_duration, slot_duration);
let _header = System::finalize();
+6 -6
View File
@@ -26,7 +26,7 @@ use inherents::{InherentData, ProvideInherent};
#[test]
fn authorities_change_logged() {
with_externalities(&mut new_test_ext(vec![1, 2, 3]), || {
System::initialize(&1, &Default::default(), &Default::default());
System::initialize(&1, &Default::default(), &Default::default(), &Default::default());
Consensus::set_authorities(&[UintAuthorityId(4), UintAuthorityId(5), UintAuthorityId(6)]);
Consensus::on_finalize(1);
let header = System::finalize();
@@ -47,7 +47,7 @@ fn authorities_change_logged() {
#[test]
fn partial_authorities_change_logged() {
with_externalities(&mut new_test_ext(vec![1, 2, 3]), || {
System::initialize(&2, &Default::default(), &Default::default());
System::initialize(&2, &Default::default(), &Default::default(), &Default::default());
Consensus::set_authorities(&[UintAuthorityId(2), UintAuthorityId(4), UintAuthorityId(5)]);
Consensus::on_finalize(2);
let header = System::finalize();
@@ -68,7 +68,7 @@ fn partial_authorities_change_logged() {
#[test]
fn authorities_change_is_not_logged_when_not_changed() {
with_externalities(&mut new_test_ext(vec![1, 2, 3]), || {
System::initialize(&1, &Default::default(), &Default::default());
System::initialize(&1, &Default::default(), &Default::default(), &Default::default());
Consensus::on_finalize(1);
let header = System::finalize();
assert_eq!(header.digest, testing::Digest {
@@ -80,7 +80,7 @@ fn authorities_change_is_not_logged_when_not_changed() {
#[test]
fn authorities_change_is_not_logged_when_changed_back_to_original() {
with_externalities(&mut new_test_ext(vec![1, 2, 3]), || {
System::initialize(&1, &Default::default(), &Default::default());
System::initialize(&1, &Default::default(), &Default::default(), &Default::default());
Consensus::set_authorities(&[UintAuthorityId(4), UintAuthorityId(5), UintAuthorityId(6)]);
Consensus::set_authorities(&[UintAuthorityId(1), UintAuthorityId(2), UintAuthorityId(3)]);
Consensus::on_finalize(1);
@@ -94,7 +94,7 @@ fn authorities_change_is_not_logged_when_changed_back_to_original() {
#[test]
fn offline_report_can_be_excluded() {
with_externalities(&mut new_test_ext(vec![1, 2, 3]), || {
System::initialize(&1, &Default::default(), &Default::default());
System::initialize(&1, &Default::default(), &Default::default(), &Default::default());
assert!(Consensus::create_inherent(&InherentData::new()).is_none());
let offline_report: Vec<u32> = vec![0];
@@ -110,7 +110,7 @@ fn set_and_kill_storage_work() {
use srml_support::storage;
with_externalities(&mut new_test_ext(vec![1, 2, 3]), || {
System::initialize(&1, &Default::default(), &Default::default());
System::initialize(&1, &Default::default(), &Default::default(), &Default::default());
let item = (vec![42u8], vec![42u8]);
+12 -12
View File
@@ -736,7 +736,7 @@ fn deduct_blocks() {
assert_eq!(bob_contract.rent_allowance, 1_000);
// Advance 4 blocks
System::initialize(&5, &[0u8; 32].into(), &[0u8; 32].into());
System::initialize(&5, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default());
// Trigger rent through call
assert_ok!(Contract::call(Origin::signed(ALICE), BOB, 0, 100_000, call::null()));
@@ -751,7 +751,7 @@ fn deduct_blocks() {
assert_eq!(Balances::free_balance(BOB), 30_000 - rent);
// Advance 7 blocks more
System::initialize(&12, &[0u8; 32].into(), &[0u8; 32].into());
System::initialize(&12, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default());
// Trigger rent through call
assert_ok!(Contract::call(Origin::signed(ALICE), BOB, 0, 100_000, call::null()));
@@ -825,7 +825,7 @@ fn claim_surcharge(blocks: u64, trigger_call: impl Fn() -> bool, removes: bool)
));
// Advance blocks
System::initialize(&blocks, &[0u8; 32].into(), &[0u8; 32].into());
System::initialize(&blocks, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default());
// Trigger rent through call
assert!(trigger_call());
@@ -865,14 +865,14 @@ fn removals(trigger_call: impl Fn() -> bool) {
assert_eq!(ContractInfoOf::<Test>::get(BOB).unwrap().get_alive().unwrap().rent_allowance, 1_000);
// Advance blocks
System::initialize(&10, &[0u8; 32].into(), &[0u8; 32].into());
System::initialize(&10, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default());
// Trigger rent through call
assert!(trigger_call());
assert!(ContractInfoOf::<Test>::get(BOB).unwrap().get_tombstone().is_some());
// Advance blocks
System::initialize(&20, &[0u8; 32].into(), &[0u8; 32].into());
System::initialize(&20, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default());
// Trigger rent must have no effect
assert!(trigger_call());
@@ -899,14 +899,14 @@ fn removals(trigger_call: impl Fn() -> bool) {
assert_eq!(ContractInfoOf::<Test>::get(BOB).unwrap().get_alive().unwrap().rent_allowance, 100);
// Advance blocks
System::initialize(&10, &[0u8; 32].into(), &[0u8; 32].into());
System::initialize(&10, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default());
// Trigger rent through call
assert!(trigger_call());
assert!(ContractInfoOf::<Test>::get(BOB).unwrap().get_tombstone().is_some());
// Advance blocks
System::initialize(&20, &[0u8; 32].into(), &[0u8; 32].into());
System::initialize(&20, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default());
// Trigger rent must have no effect
assert!(trigger_call());
@@ -937,14 +937,14 @@ fn removals(trigger_call: impl Fn() -> bool) {
assert_eq!(ContractInfoOf::<Test>::get(BOB).unwrap().get_alive().unwrap().rent_allowance, 1_000);
// Advance blocks
System::initialize(&10, &[0u8; 32].into(), &[0u8; 32].into());
System::initialize(&10, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default());
// Trigger rent through call
assert!(trigger_call());
assert!(ContractInfoOf::<Test>::get(BOB).is_none());
// Advance blocks
System::initialize(&20, &[0u8; 32].into(), &[0u8; 32].into());
System::initialize(&20, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default());
// Trigger rent must have no effect
assert!(trigger_call());
@@ -1027,7 +1027,7 @@ fn default_rent_allowance_on_create() {
assert_eq!(bob_contract.rent_allowance, <BalanceOf<Test>>::max_value());
// Advance blocks
System::initialize(&5, &[0u8; 32].into(), &[0u8; 32].into());
System::initialize(&5, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default());
// Trigger rent through call
assert_ok!(Contract::call(Origin::signed(ALICE), BOB, 0, 100_000, call::null()));
@@ -1179,7 +1179,7 @@ fn restoration(test_different_storage: bool, test_restore_to_with_dirty_storage:
}
// Advance 4 blocks
System::initialize(&5, &[0u8; 32].into(), &[0u8; 32].into());
System::initialize(&5, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default());
// Trigger rent through call
assert_ok!(Contract::call(Origin::signed(ALICE), BOB, 0, 100_000, call::null()));
@@ -1198,7 +1198,7 @@ fn restoration(test_different_storage: bool, test_restore_to_with_dirty_storage:
if !test_restore_to_with_dirty_storage {
// Advance 1 blocks
System::initialize(&6, &[0u8; 32].into(), &[0u8; 32].into());
System::initialize(&6, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default());
}
assert_ok!(Contract::call(
+8 -5
View File
@@ -80,7 +80,7 @@ use rstd::result;
use primitives::traits::{
self, Header, Zero, One, Checkable, Applyable, CheckEqual, OnFinalize,
OnInitialize, Digest, NumberFor, Block as BlockT, OffchainWorker,
ValidateUnsigned,
ValidateUnsigned, DigestItem,
};
use srml_support::{Dispatchable, traits::MakePayment};
use parity_codec::{Codec, Encode};
@@ -152,11 +152,13 @@ where
{
/// Start the execution of a particular block.
pub fn initialize_block(header: &System::Header) {
Self::initialize_block_impl(header.number(), header.parent_hash(), header.extrinsics_root());
let mut digests = System::Digest::default();
header.digest().logs().iter().for_each(|d| if d.as_pre_runtime().is_some() { digests.push(d.clone()) });
Self::initialize_block_impl(header.number(), header.parent_hash(), header.extrinsics_root(), &digests);
}
fn initialize_block_impl(block_number: &System::BlockNumber, parent_hash: &System::Hash, extrinsics_root: &System::Hash) {
<system::Module<System>>::initialize(block_number, parent_hash, extrinsics_root);
fn initialize_block_impl(block_number: &System::BlockNumber, parent_hash: &System::Hash, extrinsics_root: &System::Hash, digest: &System::Digest) {
<system::Module<System>>::initialize(block_number, parent_hash, extrinsics_root, digest);
<AllModules as OnInitialize<System::BlockNumber>>::on_initialize(*block_number);
}
@@ -262,7 +264,8 @@ where
Payment::make_payment(sender, encoded_len).map_err(|_| internal::ApplyError::CantPay)?;
// AUDIT: Under no circumstances may this function panic from here onwards.
// FIXME: ensure this at compile-time (such as by not defining a panic function, forcing
// a linker error unless the compiler can prove it cannot be called).
// increment nonce in storage
<system::Module<System>>::inc_account_nonce(sender);
}
+2 -2
View File
@@ -344,7 +344,7 @@ mod tests {
with_externalities(&mut TestExternalities::new(t), || {
let mut parent_hash = System::parent_hash();
for i in 2..106 {
System::initialize(&i, &parent_hash, &Default::default());
System::initialize(&i, &parent_hash, &Default::default(), &Default::default());
FinalityTracker::on_finalize(i);
let hdr = System::finalize();
parent_hash = hdr.hash();
@@ -369,7 +369,7 @@ mod tests {
with_externalities(&mut TestExternalities::new(t), || {
let mut parent_hash = System::parent_hash();
for i in 2..106 {
System::initialize(&i, &parent_hash, &Default::default());
System::initialize(&i, &parent_hash, &Default::default(), &Default::default());
assert_ok!(FinalityTracker::dispatch(
Call::final_hint(i-1),
Origin::NONE,
+12 -12
View File
@@ -30,7 +30,7 @@ use super::*;
#[test]
fn authorities_change_logged() {
with_externalities(&mut new_test_ext(vec![(1, 1), (2, 1), (3, 1)]), || {
System::initialize(&1, &Default::default(), &Default::default());
System::initialize(&1, &Default::default(), &Default::default(), &Default::default());
Grandpa::schedule_change(vec![(4, 1), (5, 1), (6, 1)], 0, None).unwrap();
System::note_finished_extrinsics();
@@ -56,7 +56,7 @@ fn authorities_change_logged() {
#[test]
fn authorities_change_logged_after_delay() {
with_externalities(&mut new_test_ext(vec![(1, 1), (2, 1), (3, 1)]), || {
System::initialize(&1, &Default::default(), &Default::default());
System::initialize(&1, &Default::default(), &Default::default(), &Default::default());
Grandpa::schedule_change(vec![(4, 1), (5, 1), (6, 1)], 1, None).unwrap();
Grandpa::on_finalize(1);
let header = System::finalize();
@@ -69,7 +69,7 @@ fn authorities_change_logged_after_delay() {
// no change at this height.
assert_eq!(System::events(), vec![]);
System::initialize(&2, &header.hash(), &Default::default());
System::initialize(&2, &header.hash(), &Default::default(), &Default::default());
System::note_finished_extrinsics();
Grandpa::on_finalize(2);
@@ -87,7 +87,7 @@ fn authorities_change_logged_after_delay() {
#[test]
fn cannot_schedule_change_when_one_pending() {
with_externalities(&mut new_test_ext(vec![(1, 1), (2, 1), (3, 1)]), || {
System::initialize(&1, &Default::default(), &Default::default());
System::initialize(&1, &Default::default(), &Default::default(), &Default::default());
Grandpa::schedule_change(vec![(4, 1), (5, 1), (6, 1)], 1, None).unwrap();
assert!(Grandpa::pending_change().is_some());
assert!(Grandpa::schedule_change(vec![(5, 1)], 1, None).is_err());
@@ -95,14 +95,14 @@ fn cannot_schedule_change_when_one_pending() {
Grandpa::on_finalize(1);
let header = System::finalize();
System::initialize(&2, &header.hash(), &Default::default());
System::initialize(&2, &header.hash(), &Default::default(), &Default::default());
assert!(Grandpa::pending_change().is_some());
assert!(Grandpa::schedule_change(vec![(5, 1)], 1, None).is_err());
Grandpa::on_finalize(2);
let header = System::finalize();
System::initialize(&3, &header.hash(), &Default::default());
System::initialize(&3, &header.hash(), &Default::default(), &Default::default());
assert!(Grandpa::pending_change().is_none());
assert!(Grandpa::schedule_change(vec![(5, 1)], 1, None).is_ok());
@@ -130,7 +130,7 @@ fn new_decodes_from_old() {
#[test]
fn dispatch_forced_change() {
with_externalities(&mut new_test_ext(vec![(1, 1), (2, 1), (3, 1)]), || {
System::initialize(&1, &Default::default(), &Default::default());
System::initialize(&1, &Default::default(), &Default::default(), &Default::default());
Grandpa::schedule_change(
vec![(4, 1), (5, 1), (6, 1)],
5,
@@ -144,7 +144,7 @@ fn dispatch_forced_change() {
let mut header = System::finalize();
for i in 2..7 {
System::initialize(&i, &header.hash(), &Default::default());
System::initialize(&i, &header.hash(), &Default::default(), &Default::default());
assert!(Grandpa::pending_change().unwrap().forced.is_some());
assert_eq!(Grandpa::next_forced(), Some(11));
assert!(Grandpa::schedule_change(vec![(5, 1)], 1, None).is_err());
@@ -157,7 +157,7 @@ fn dispatch_forced_change() {
// change has been applied at the end of block 6.
// add a normal change.
{
System::initialize(&7, &header.hash(), &Default::default());
System::initialize(&7, &header.hash(), &Default::default(), &Default::default());
assert!(Grandpa::pending_change().is_none());
assert_eq!(Grandpa::grandpa_authorities(), vec![(4, 1), (5, 1), (6, 1)]);
assert!(Grandpa::schedule_change(vec![(5, 1)], 1, None).is_ok());
@@ -167,7 +167,7 @@ fn dispatch_forced_change() {
// run the normal change.
{
System::initialize(&8, &header.hash(), &Default::default());
System::initialize(&8, &header.hash(), &Default::default(), &Default::default());
assert!(Grandpa::pending_change().is_some());
assert_eq!(Grandpa::grandpa_authorities(), vec![(4, 1), (5, 1), (6, 1)]);
assert!(Grandpa::schedule_change(vec![(5, 1)], 1, None).is_err());
@@ -178,7 +178,7 @@ fn dispatch_forced_change() {
// normal change applied. but we can't apply a new forced change for some
// time.
for i in 9..11 {
System::initialize(&i, &header.hash(), &Default::default());
System::initialize(&i, &header.hash(), &Default::default(), &Default::default());
assert!(Grandpa::pending_change().is_none());
assert_eq!(Grandpa::grandpa_authorities(), vec![(5, 1)]);
assert_eq!(Grandpa::next_forced(), Some(11));
@@ -188,7 +188,7 @@ fn dispatch_forced_change() {
}
{
System::initialize(&11, &header.hash(), &Default::default());
System::initialize(&11, &header.hash(), &Default::default(), &Default::default());
assert!(Grandpa::pending_change().is_none());
assert!(Grandpa::schedule_change(vec![(5, 1), (6, 1), (7, 1)], 5, Some(0)).is_ok());
assert_eq!(Grandpa::next_forced(), Some(21));
+48 -28
View File
@@ -465,10 +465,16 @@ impl<T: Trait> Module<T> {
}
/// Start the execution of a particular block.
pub fn initialize(number: &T::BlockNumber, parent_hash: &T::Hash, txs_root: &T::Hash) {
pub fn initialize(
number: &T::BlockNumber,
parent_hash: &T::Hash,
txs_root: &T::Hash,
digest: &T::Digest,
) {
// populate environment
storage::unhashed::put(well_known_keys::EXTRINSIC_INDEX, &0u32);
<Number<T>>::put(number);
<Digest<T>>::put(digest);
<ParentHash<T>>::put(parent_hash);
<BlockHash<T>>::insert(*number - One::one(), parent_hash);
<ExtrinsicsRoot<T>>::put(txs_root);
@@ -553,38 +559,51 @@ impl<T: Trait> Module<T> {
/// Get the basic random seed.
///
/// In general you won't want to use this, but rather `Self::random` which allows you to give a subject for the
/// random result and whose value will be independently low-influence random from any other such seeds.
/// In general you won't want to use this, but rather `Self::random` which
/// allows you to give a subject for the random result and whose value will
/// be independently low-influence random from any other such seeds.
pub fn random_seed() -> T::Hash {
Self::random(&[][..])
}
/// Get a low-influence "random" value.
///
/// Being a deterministic block chain, real randomness is difficult to come by. This gives you something that
/// approximates it. `subject` is a context identifier and allows you to get a different result to other callers
/// of this function; use it like `random(&b"my context"[..])`.
/// Being a deterministic block chain, real randomness is difficult to come
/// by. This gives you something that approximates it. `subject` is a
/// context identifier and allows you to get a different result to other
/// callers of this function; use it like `random(&b"my context"[..])`.
///
/// This is initially implemented through a low-influence "triplet mix" convolution of previous block hash values.
/// In the future it will be generated from a secure "VRF".
/// This is initially implemented through a low-influence "triplet mix"
/// convolution of previous block hash values. In the future it will be
/// generated from a secure verifiable random function (VRF).
///
/// ### Security Notes
/// This randomness uses a low-influence function, drawing upon the block hashes from the previous 81 blocks. Its
/// result for any given subject will be known in advance by the block producer of this block (and, indeed, anyone
/// who knows the block's `parent_hash`). However, it is mostly impossible for the producer of this block *alone*
/// to influence the value of this hash. A sizable minority of dishonest and coordinating block producers would be
/// required in order to affect this value. If that is an insufficient security guarantee then two things can be
/// used to improve this randomness:
/// - Name, in advance, the block number whose random value will be used; ensure your module retains a buffer of
/// previous random values for its subject and then index into these in order to obviate the ability of your user
/// to look up the parent hash and choose when to transact based upon it.
/// - Require your user to first commit to an additional value by first posting its hash. Require them to reveal
/// the value to determine the final result, hashing it with the output of this random function. This reduces the
/// ability of a cabal of block producers from conspiring against individuals.
///
/// WARNING: Hashing the result of this function will remove any low-infleunce properties it has and mean that
/// all bits of the resulting value are entirely manipulatable by the author of the parent block, who can determine
/// the value of `parent_hash`.
/// This randomness uses a low-influence function, drawing upon the block
/// hashes from the previous 81 blocks. Its result for any given subject
/// will be known in advance by the block producer of this block (and,
/// indeed, anyone who knows the block's `parent_hash`). However, it is
/// mostly impossible for the producer of this block *alone* to influence
/// the value of this hash. A sizable minority of dishonest and coordinating
/// block producers would be required in order to affect this value. If that
/// is an insufficient security guarantee then two things can be used to
/// improve this randomness:
///
/// - Name, in advance, the block number whose random value will be used;
/// ensure your module retains a buffer of previous random values for its
/// subject and then index into these in order to obviate the ability of
/// your user to look up the parent hash and choose when to transact based
/// upon it.
/// - Require your user to first commit to an additional value by first
/// posting its hash. Require them to reveal the value to determine the
/// final result, hashing it with the output of this random function. This
/// reduces the ability of a cabal of block producers from conspiring
/// against individuals.
///
/// WARNING: Hashing the result of this function will remove any
/// low-influnce properties it has and mean that all bits of the resulting
/// value are entirely manipulatable by the author of the parent block, who
/// can determine the value of `parent_hash`.
pub fn random(subject: &[u8]) -> T::Hash {
let (index, hash_series) = <RandomMaterial<T>>::get();
if hash_series.len() > 0 {
@@ -606,8 +625,9 @@ impl<T: Trait> Module<T> {
<AccountNonce<T>>::insert(who, Self::account_nonce(who) + T::Index::one());
}
/// Note what the extrinsic data of the current extrinsic index is. If this is called, then
/// ensure `derive_extrinsics` is also called before block-building is completed.
/// Note what the extrinsic data of the current extrinsic index is. If this
/// is called, then ensure `derive_extrinsics` is also called before
/// block-building is completed.
///
/// NOTE: This function is called only when the block is being constructed locally.
/// `execute_block` doesn't note any extrinsics.
@@ -722,7 +742,7 @@ mod tests {
#[test]
fn deposit_event_should_work() {
with_externalities(&mut new_test_ext(), || {
System::initialize(&1, &[0u8; 32].into(), &[0u8; 32].into());
System::initialize(&1, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default());
System::note_finished_extrinsics();
System::deposit_event(1u16);
System::finalize();
@@ -737,7 +757,7 @@ mod tests {
]
);
System::initialize(&2, &[0u8; 32].into(), &[0u8; 32].into());
System::initialize(&2, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default());
System::deposit_event(42u16);
System::note_applied_extrinsic(&Ok(()), 0);
System::note_applied_extrinsic(&Err(""), 0);
@@ -758,7 +778,7 @@ mod tests {
with_externalities(&mut new_test_ext(), || {
const BLOCK_NUMBER: u64 = 1;
System::initialize(&BLOCK_NUMBER, &[0u8; 32].into(), &[0u8; 32].into());
System::initialize(&BLOCK_NUMBER, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default());
System::note_finished_extrinsics();
let topics = vec![