op-pool: propagate errors, sort by transfer fee
This commit is contained in:
parent
95ed402228
commit
3396f2f08e
@ -1,7 +1,10 @@
|
|||||||
use int_to_bytes::int_to_bytes8;
|
use int_to_bytes::int_to_bytes8;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use ssz::ssz_encode;
|
use ssz::ssz_encode;
|
||||||
use state_processing::per_block_processing::errors::ProposerSlashingValidationError;
|
use state_processing::per_block_processing::errors::{
|
||||||
|
AttestationValidationError, DepositValidationError, ExitValidationError,
|
||||||
|
ProposerSlashingValidationError, TransferValidationError,
|
||||||
|
};
|
||||||
use state_processing::per_block_processing::{
|
use state_processing::per_block_processing::{
|
||||||
validate_attestation, verify_deposit, verify_exit, verify_exit_time_independent_only,
|
validate_attestation, verify_deposit, verify_exit, verify_exit_time_independent_only,
|
||||||
verify_proposer_slashing, verify_transfer, verify_transfer_time_independent_only,
|
verify_proposer_slashing, verify_transfer, verify_transfer_time_independent_only,
|
||||||
@ -108,10 +111,10 @@ impl OperationPool {
|
|||||||
attestation: Attestation,
|
attestation: Attestation,
|
||||||
state: &BeaconState,
|
state: &BeaconState,
|
||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
) -> Result<(), ()> {
|
) -> Result<(), AttestationValidationError> {
|
||||||
// Check that attestation signatures are valid.
|
// Check that attestation signatures are valid.
|
||||||
// FIXME: should disable the time-dependent checks.
|
// FIXME: should disable the time-dependent checks.
|
||||||
validate_attestation(state, &attestation, spec).map_err(|_| ())?;
|
validate_attestation(state, &attestation, spec)?;
|
||||||
|
|
||||||
let id = AttestationId::from_data(&attestation.data, state, spec);
|
let id = AttestationId::from_data(&attestation.data, state, spec);
|
||||||
|
|
||||||
@ -143,7 +146,7 @@ impl OperationPool {
|
|||||||
/// Get a list of attestations for inclusion in a block.
|
/// Get a list of attestations for inclusion in a block.
|
||||||
pub fn get_attestations(&self, state: &BeaconState, spec: &ChainSpec) -> Vec<Attestation> {
|
pub fn get_attestations(&self, state: &BeaconState, spec: &ChainSpec) -> Vec<Attestation> {
|
||||||
// Attestations for the current fork...
|
// Attestations for the current fork...
|
||||||
// TODO: should we also check domain bytes for the previous epoch?
|
// FIXME: should we also check domain bytes for the previous epoch?
|
||||||
let current_epoch = state.slot.epoch(spec.slots_per_epoch);
|
let current_epoch = state.slot.epoch(spec.slots_per_epoch);
|
||||||
let domain_bytes = AttestationId::compute_domain_bytes(current_epoch, state, spec);
|
let domain_bytes = AttestationId::compute_domain_bytes(current_epoch, state, spec);
|
||||||
self.attestations
|
self.attestations
|
||||||
@ -184,13 +187,12 @@ impl OperationPool {
|
|||||||
deposit: Deposit,
|
deposit: Deposit,
|
||||||
state: &BeaconState,
|
state: &BeaconState,
|
||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
) -> Result<DepositInsertStatus, ()> {
|
) -> Result<DepositInsertStatus, DepositValidationError> {
|
||||||
use DepositInsertStatus::*;
|
use DepositInsertStatus::*;
|
||||||
|
|
||||||
match self.deposits.entry(deposit.index) {
|
match self.deposits.entry(deposit.index) {
|
||||||
Entry::Vacant(entry) => {
|
Entry::Vacant(entry) => {
|
||||||
// FIXME: error prop
|
verify_deposit(state, &deposit, VERIFY_DEPOSIT_PROOFS, spec)?;
|
||||||
verify_deposit(state, &deposit, VERIFY_DEPOSIT_PROOFS, spec).map_err(|_| ())?;
|
|
||||||
entry.insert(deposit);
|
entry.insert(deposit);
|
||||||
Ok(Fresh)
|
Ok(Fresh)
|
||||||
}
|
}
|
||||||
@ -198,7 +200,7 @@ impl OperationPool {
|
|||||||
if entry.get() == &deposit {
|
if entry.get() == &deposit {
|
||||||
Ok(Duplicate)
|
Ok(Duplicate)
|
||||||
} else {
|
} else {
|
||||||
verify_deposit(state, &deposit, VERIFY_DEPOSIT_PROOFS, spec).map_err(|_| ())?;
|
verify_deposit(state, &deposit, VERIFY_DEPOSIT_PROOFS, spec)?;
|
||||||
Ok(Replaced(Box::new(entry.insert(deposit))))
|
Ok(Replaced(Box::new(entry.insert(deposit))))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -279,7 +281,7 @@ impl OperationPool {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: copy ProposerSlashing code for AttesterSlashing
|
// FIXME: copy ProposerSlashing code for AttesterSlashing
|
||||||
|
|
||||||
/// Insert a voluntary exit, validating it almost-entirely (future exits are permitted).
|
/// Insert a voluntary exit, validating it almost-entirely (future exits are permitted).
|
||||||
pub fn insert_voluntary_exit(
|
pub fn insert_voluntary_exit(
|
||||||
@ -287,14 +289,13 @@ impl OperationPool {
|
|||||||
exit: VoluntaryExit,
|
exit: VoluntaryExit,
|
||||||
state: &BeaconState,
|
state: &BeaconState,
|
||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
) -> Result<(), ()> {
|
) -> Result<(), ExitValidationError> {
|
||||||
verify_exit_time_independent_only(state, &exit, spec).map_err(|_| ())?;
|
verify_exit_time_independent_only(state, &exit, spec)?;
|
||||||
self.voluntary_exits.insert(exit.validator_index, exit);
|
self.voluntary_exits.insert(exit.validator_index, exit);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a list of voluntary exits for inclusion in a block.
|
/// Get a list of voluntary exits for inclusion in a block.
|
||||||
// TODO: could optimise this by eliding the checks that have already been done on insert
|
|
||||||
pub fn get_voluntary_exits(&self, state: &BeaconState, spec: &ChainSpec) -> Vec<VoluntaryExit> {
|
pub fn get_voluntary_exits(&self, state: &BeaconState, spec: &ChainSpec) -> Vec<VoluntaryExit> {
|
||||||
filter_limit_operations(
|
filter_limit_operations(
|
||||||
self.voluntary_exits.values(),
|
self.voluntary_exits.values(),
|
||||||
@ -318,25 +319,26 @@ impl OperationPool {
|
|||||||
transfer: Transfer,
|
transfer: Transfer,
|
||||||
state: &BeaconState,
|
state: &BeaconState,
|
||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
) -> Result<(), ()> {
|
) -> Result<(), TransferValidationError> {
|
||||||
// The signature of the transfer isn't hashed, but because we check
|
// The signature of the transfer isn't hashed, but because we check
|
||||||
// it before we insert into the HashSet, we can't end up with duplicate
|
// it before we insert into the HashSet, we can't end up with duplicate
|
||||||
// transactions.
|
// transactions.
|
||||||
verify_transfer_time_independent_only(state, &transfer, spec).map_err(|_| ())?;
|
verify_transfer_time_independent_only(state, &transfer, spec)?;
|
||||||
self.transfers.insert(transfer);
|
self.transfers.insert(transfer);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a list of transfers for inclusion in a block.
|
/// Get a list of transfers for inclusion in a block.
|
||||||
// TODO: improve the economic optimality of this function by taking the transfer
|
// TODO: improve the economic optimality of this function by accounting for
|
||||||
// fees into account, and dependencies between transfers in the same block
|
// dependencies between transfers in the same block e.g. A pays B, B pays C
|
||||||
// e.g. A pays B, B pays C
|
|
||||||
pub fn get_transfers(&self, state: &BeaconState, spec: &ChainSpec) -> Vec<Transfer> {
|
pub fn get_transfers(&self, state: &BeaconState, spec: &ChainSpec) -> Vec<Transfer> {
|
||||||
filter_limit_operations(
|
self.transfers
|
||||||
&self.transfers,
|
.iter()
|
||||||
|transfer| verify_transfer(state, transfer, spec).is_ok(),
|
.filter(|transfer| verify_transfer(state, transfer, spec).is_ok())
|
||||||
spec.max_transfers,
|
.sorted_by_key(|transfer| std::cmp::Reverse(transfer.fee))
|
||||||
)
|
.take(spec.max_transfers as usize)
|
||||||
|
.cloned()
|
||||||
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Prune the set of transfers by removing all those whose slot has already passed.
|
/// Prune the set of transfers by removing all those whose slot has already passed.
|
||||||
|
Loading…
Reference in New Issue
Block a user