Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sync ethereum headers using unsigned (substrate) transactions #45

Merged
merged 43 commits into from
Apr 7, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
09bbf48
reward submitters on finalization
svyatonik Mar 18, 2020
191641d
PoA -> Substrate: unsigned_import_header API
svyatonik Mar 19, 2020
a7999d5
fix grumble
svyatonik Mar 19, 2020
4ddbd67
make submitter part of ImportContext
svyatonik Mar 19, 2020
8c0070d
Merge branch 'reward_on_finalization' into unsigned-eth-headers-submit
svyatonik Mar 19, 2020
e6e8961
verify using next validators set + tests
svyatonik Mar 23, 2020
d21d32b
fix nostd compilation
svyatonik Mar 23, 2020
cf5ce5d
add sub-tx-mode argument
svyatonik Mar 23, 2020
b8963c4
support sub-tx-mode
svyatonik Mar 23, 2020
f2c46d0
impl ValidateUnsigned for Runtime
svyatonik Mar 23, 2020
01e9dc7
do not submit too much transactions to the pool
svyatonik Mar 23, 2020
13b9c1d
Merge branch 'master' into unsigned-eth-headers-submit
svyatonik Mar 23, 2020
bd69a86
cargo fmt
svyatonik Mar 23, 2020
cc8b9de
fix bad merge
svyatonik Mar 23, 2020
e3edd52
revert license fix
svyatonik Mar 23, 2020
4fe0f68
Update modules/ethereum/src/lib.rs
svyatonik Mar 27, 2020
523f261
Update modules/ethereum/src/verification.rs
svyatonik Mar 27, 2020
6d9f5f0
updated comment
svyatonik Mar 27, 2020
0694962
Merge branch 'unsigned-eth-headers-submit' of https://github.com/pari…
svyatonik Mar 27, 2020
d875ed4
validate receipts before accepting unsigned tx to pool
svyatonik Mar 27, 2020
4b66de4
cargo fmt
svyatonik Mar 27, 2020
90725ed
fix comment
svyatonik Mar 27, 2020
aa3691b
fix grumbles
svyatonik Mar 27, 2020
7295b04
Update modules/ethereum/src/verification.rs
svyatonik Mar 27, 2020
d850b98
cargo fmt --all
svyatonik Mar 27, 2020
2399254
Merge branch 'unsigned-eth-headers-submit' of https://github.com/pari…
svyatonik Mar 27, 2020
4fb9ad9
struct ChangeToEnact
svyatonik Mar 30, 2020
4acb97f
updated doc
svyatonik Mar 31, 2020
9cc72e3
fix doc
svyatonik Mar 31, 2020
43bdc20
add docs to the code method
svyatonik Apr 3, 2020
3653a08
simplify fn ancestry
svyatonik Apr 3, 2020
d120be4
finish incomplete docs
svyatonik Apr 3, 2020
a7c1986
Update modules/ethereum/src/lib.rs
svyatonik Apr 3, 2020
dac2a17
Update modules/ethereum/src/lib.rs
svyatonik Apr 3, 2020
15c892e
return err from unsigned_import_header
svyatonik Apr 3, 2020
572f9f9
Merge branch 'unsigned-eth-headers-submit' of https://github.com/pari…
svyatonik Apr 3, 2020
b4788a1
get header once
svyatonik Apr 3, 2020
88e61e3
Update relays/ethereum/src/ethereum_sync.rs
svyatonik Apr 3, 2020
01c99fd
fix
svyatonik Apr 3, 2020
0ab555b
UnsignedTooFarInTheFuture -> Custom(err.code())
svyatonik Apr 3, 2020
c105ee4
updated ImportContext::last_signal_block
svyatonik Apr 3, 2020
cf2278a
cargo fmt --all
svyatonik Apr 3, 2020
85582b3
rename runtime calls
svyatonik Apr 6, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion bin/node/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ construct_runtime!(
Balances: pallet_balances::{Module, Call, Storage, Config<T>, Event<T>},
TransactionPayment: pallet_transaction_payment::{Module, Storage},
Sudo: pallet_sudo::{Module, Call, Config<T>, Storage, Event<T>},
BridgeEthPoA: pallet_bridge_eth_poa::{Module, Call, Config, Storage},
BridgeEthPoA: pallet_bridge_eth_poa::{Module, Call, Config, Storage, ValidateUnsigned},
}
);

Expand Down
51 changes: 31 additions & 20 deletions modules/ethereum/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,45 +33,49 @@
use sp_runtime::RuntimeDebug;

/// Header import error.
#[derive(RuntimeDebug)]
#[derive(Clone, Copy, RuntimeDebug)]
#[cfg_attr(feature = "std", derive(PartialEq))]
pub enum Error {
/// The header is beyound last finalized and can not be imported.
AncientHeader,
/// The header is beyond last finalized and can not be imported.
AncientHeader = 0,
/// The header is already imported.
KnownHeader,
KnownHeader = 1,
/// Seal has an incorrect format.
InvalidSealArity,
InvalidSealArity = 2,
/// Block number isn't sensible.
RidiculousNumber,
RidiculousNumber = 3,
/// Block has too much gas used.
TooMuchGasUsed,
TooMuchGasUsed = 4,
/// Gas limit header field is invalid.
InvalidGasLimit,
InvalidGasLimit = 5,
/// Extra data is of an invalid length.
ExtraDataOutOfBounds,
ExtraDataOutOfBounds = 6,
/// Timestamp header overflowed.
TimestampOverflow,
TimestampOverflow = 7,
/// The parent header is missing from the blockchain.
MissingParentBlock,
MissingParentBlock = 8,
/// The header step is missing from the header.
MissingStep,
MissingStep = 9,
/// The header signature is missing from the header.
MissingSignature,
MissingSignature = 10,
/// Empty steps are missing from the header.
MissingEmptySteps,
MissingEmptySteps = 11,
/// The same author issued different votes at the same step.
DoubleVote,
DoubleVote = 12,
/// Validation proof insufficient.
InsufficientProof,
InsufficientProof = 13,
/// Difficulty header field is invalid.
InvalidDifficulty,
InvalidDifficulty = 14,
/// The received block is from an incorrect proposer.
NotValidator,
NotValidator = 15,
/// Missing transaction receipts for the operation.
MissingTransactionsReceipts,
MissingTransactionsReceipts = 16,
/// Redundant transaction receipts are provided.
RedundantTransactionsReceipts = 17,
/// Provided transactions receipts are not matching the header.
TransactionsReceiptsMismatch,
TransactionsReceiptsMismatch = 18,
/// Can't accept unsigned header from the far future.
UnsignedTooFarInTheFuture = 19,
}

impl Error {
Expand All @@ -94,7 +98,14 @@ impl Error {
Error::InvalidDifficulty => "Header has invalid difficulty",
Error::NotValidator => "Header is sealed by unexpected validator",
Error::MissingTransactionsReceipts => "The import operation requires transactions receipts",
Error::RedundantTransactionsReceipts => "Redundant transactions receipts are provided",
Error::TransactionsReceiptsMismatch => "Invalid transactions receipts provided",
Error::UnsignedTooFarInTheFuture => "The unsigned header is too far in future",
}
}

/// Return unique error code.
pub fn code(&self) -> u8 {
svyatonik marked this conversation as resolved.
Show resolved Hide resolved
*self as u8
}
}
33 changes: 27 additions & 6 deletions modules/ethereum/src/finality.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,18 @@
// along with Parity-Bridge. If not, see <http://www.gnu.org/licenses/>.

use crate::error::Error;
use crate::{ancestry, Storage};
use crate::Storage;
use primitives::{public_to_address, Address, Header, SealedEmptyStep, H256};
use sp_io::crypto::secp256k1_ecdsa_recover;
use sp_std::collections::{
btree_map::{BTreeMap, Entry},
btree_set::BTreeSet,
vec_deque::VecDeque,
};
use sp_std::prelude::*;
use sp_std::{
collections::{
btree_map::{BTreeMap, Entry},
btree_set::BTreeSet,
vec_deque::VecDeque,
},
iter::from_fn,
};

/// Tries to finalize blocks when given block is imported.
///
Expand Down Expand Up @@ -206,6 +209,24 @@ fn empty_step_signer(empty_step: &SealedEmptyStep, parent_hash: &H256) -> Option
.map(|public| public_to_address(&public))
}

/// Return iterator of given header ancestors.
pub(crate) fn ancestry<'a, S: Storage>(
storage: &'a S,
header: &Header,
) -> impl Iterator<Item = (H256, Header, Option<S::Submitter>)> + 'a {
let mut parent_hash = header.parent_hash.clone();
from_fn(move || {
let (header, submitter) = storage.header(&parent_hash)?;
if header.number == 0 {
return None;
}

let hash = parent_hash.clone();
parent_hash = header.parent_hash.clone();
Some((hash, header, submitter))
})
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
32 changes: 10 additions & 22 deletions modules/ethereum/src/import.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,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::*};

Expand Down Expand Up @@ -121,16 +121,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)
Expand Down Expand Up @@ -173,24 +179,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::*;
Expand Down
Loading