Sync ethereum headers using unsigned (substrate) transactions (#45)

* reward submitters on finalization

* PoA -> Substrate: unsigned_import_header API

* fix grumble

* make submitter part of ImportContext

* verify using next validators set + tests

* fix nostd compilation

* add sub-tx-mode argument

* support sub-tx-mode

* impl ValidateUnsigned for Runtime

* do not submit too much transactions to the pool

* cargo fmt

* fix bad merge

* revert license fix

* Update modules/ethereum/src/lib.rs

Co-Authored-By: Hernando Castano <HCastano@users.noreply.github.com>

* Update modules/ethereum/src/verification.rs

Co-Authored-By: Hernando Castano <HCastano@users.noreply.github.com>

* updated comment

* validate receipts before accepting unsigned tx to pool

* cargo fmt

* fix comment

* fix grumbles

* Update modules/ethereum/src/verification.rs

Co-Authored-By: Hernando Castano <HCastano@users.noreply.github.com>

* cargo fmt --all

* struct ChangeToEnact

* updated doc

* fix doc

* add docs to the code method

* simplify fn ancestry

* finish incomplete docs

* Update modules/ethereum/src/lib.rs

Co-Authored-By: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* Update modules/ethereum/src/lib.rs

Co-Authored-By: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* return err from unsigned_import_header

* get header once

* Update relays/ethereum/src/ethereum_sync.rs

Co-Authored-By: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* fix

* UnsignedTooFarInTheFuture -> Custom(err.code())

* updated ImportContext::last_signal_block

* cargo fmt --all

* rename runtime calls

Co-authored-by: Hernando Castano <HCastano@users.noreply.github.com>
Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com>
This commit is contained in:
Svyatoslav Nikolsky
2020-04-07 15:53:59 +03:00
committed by Bastian Köcher
parent b055027161
commit c6c46462ab
12 changed files with 1043 additions and 211 deletions
+10 -22
View File
@@ -17,8 +17,8 @@
use crate::error::Error;
use crate::finality::finalize_blocks;
use crate::validators::{Validators, ValidatorsConfiguration};
use crate::verification::verify_aura_header;
use crate::{AuraConfiguration, Storage};
use crate::verification::{is_importable_header, verify_aura_header};
use crate::{AuraConfiguration, ChangeToEnact, Storage};
use primitives::{Header, Receipt, H256};
use sp_std::{collections::btree_map::BTreeMap, prelude::*};
@@ -105,16 +105,22 @@ pub fn import_header<S: Storage>(
let (scheduled_change, enacted_change) = validators.extract_validators_change(&header, receipts)?;
// check if block finalizes some other blocks and corresponding scheduled validators
let validators_set = import_context.validators_set();
let finalized_blocks = finalize_blocks(
storage,
&prev_finalized_hash,
(import_context.validators_start(), import_context.validators()),
(&validators_set.enact_block, &validators_set.validators),
&hash,
import_context.submitter(),
&header,
aura_config.two_thirds_majority_transition,
)?;
let enacted_change = enacted_change.or_else(|| validators.finalize_validators_change(storage, &finalized_blocks));
let enacted_change = enacted_change
.map(|validators| ChangeToEnact {
signal_block: None,
validators,
})
.or_else(|| validators.finalize_validators_change(storage, &finalized_blocks));
// NOTE: we can't return Err() from anywhere below this line
// (because otherwise we'll have inconsistent storage if transaction will fail)
@@ -157,24 +163,6 @@ pub fn header_import_requires_receipts<S: Storage>(
.unwrap_or(false)
}
/// Checks that we are able to ***try to** import this header.
/// Returns error if we should not try to import this block.
/// Returns hash of the header and number of the last finalized block.
fn is_importable_header<S: Storage>(storage: &S, header: &Header) -> Result<(H256, H256), Error> {
// we never import any header that competes with finalized header
let (finalized_block_number, finalized_block_hash) = storage.finalized_block();
if header.number <= finalized_block_number {
return Err(Error::AncientHeader);
}
// we never import any header with known hash
let hash = header.hash();
if storage.header(&hash).is_some() {
return Err(Error::KnownHeader);
}
Ok((hash, finalized_block_hash))
}
#[cfg(test)]
mod tests {
use super::*;