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

p2p starknet 0.13.1 #1787

Merged
merged 4 commits into from
Feb 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
133 changes: 129 additions & 4 deletions crates/p2p/src/client/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
//!
//! Also includes some "bridging" types which should eventually be removed
use pathfinder_common::event::Event;
use pathfinder_common::receipt::{
BuiltinCounters, ExecutionDataAvailability, ExecutionResources, ExecutionStatus, L2ToL1Message,
};
use pathfinder_common::transaction::{
DataAvailabilityMode, DeclareTransactionV0V1, DeclareTransactionV2, DeclareTransactionV3,
DeployAccountTransactionV0V1, DeployAccountTransactionV3, DeployTransaction,
Expand All @@ -11,10 +14,12 @@ use pathfinder_common::transaction::{
use pathfinder_common::{
AccountDeploymentDataElem, BlockCommitmentSignature, BlockCommitmentSignatureElem, BlockHash,
BlockNumber, BlockTimestamp, CallParam, CasmHash, ClassHash, ConstructorParam, ContractAddress,
ContractAddressSalt, EntryPoint, EventCommitment, EventData, EventKey, Fee, GasPrice,
PaymasterDataElem, SequencerAddress, StarknetVersion, StateCommitment, Tip,
TransactionCommitment, TransactionNonce, TransactionSignatureElem, TransactionVersion,
ContractAddressSalt, EntryPoint, EthereumAddress, EventCommitment, EventData, EventKey, Fee,
GasPrice, L1DataAvailabilityMode, L2ToL1MessagePayloadElem, PaymasterDataElem,
SequencerAddress, StarknetVersion, StateCommitment, Tip, TransactionCommitment,
TransactionHash, TransactionNonce, TransactionSignatureElem, TransactionVersion,
};
use pathfinder_crypto::Felt;

/// We don't want to introduce circular dependencies between crates
/// and we need to work around for the orphan rule - implement conversion fns for types ourside our crate.
Expand All @@ -32,13 +37,17 @@ pub struct SignedBlockHeader {
pub number: BlockNumber,
pub timestamp: BlockTimestamp,
pub eth_l1_gas_price: GasPrice,
pub strk_l1_gas_price: GasPrice,
pub eth_l1_data_gas_price: GasPrice,
pub strk_l1_data_gas_price: GasPrice,
pub sequencer_address: SequencerAddress,
pub starknet_version: StarknetVersion,
pub event_commitment: EventCommitment,
pub state_commitment: StateCommitment,
pub transaction_commitment: TransactionCommitment,
pub transaction_count: usize,
pub event_count: usize,
pub l1_da_mode: L1DataAvailabilityMode,
pub signature: BlockCommitmentSignature,
}

Expand All @@ -63,14 +72,18 @@ impl TryFrom<p2p_proto::header::SignedBlockHeader> for SignedBlockHeader {
.ok_or(anyhow::anyhow!("block number > i64::MAX"))?,
timestamp: BlockTimestamp::new(dto.time)
.ok_or(anyhow::anyhow!("block timestamp > i64::MAX"))?,
eth_l1_gas_price: dto.gas_price.into(),
eth_l1_gas_price: GasPrice(dto.gas_price_wei),
strk_l1_gas_price: GasPrice(dto.gas_price_fri),
eth_l1_data_gas_price: GasPrice(dto.data_gas_price_wei),
strk_l1_data_gas_price: GasPrice(dto.data_gas_price_fri),
sequencer_address: SequencerAddress(dto.sequencer_address.0),
starknet_version: dto.protocol_version.into(),
event_commitment: EventCommitment(dto.events.root.0),
state_commitment: StateCommitment(dto.state.root.0),
transaction_commitment: TransactionCommitment(dto.transactions.root.0),
transaction_count: dto.transactions.n_leaves.try_into()?,
event_count: dto.events.n_leaves.try_into()?,
l1_da_mode: TryFromDto::try_from_dto(dto.l1_data_availability_mode)?,
signature,
})
}
Expand All @@ -94,18 +107,117 @@ impl
number: header.number,
timestamp: header.timestamp,
eth_l1_gas_price: header.eth_l1_gas_price,
strk_l1_gas_price: header.strk_l1_gas_price,
eth_l1_data_gas_price: header.eth_l1_data_gas_price,
strk_l1_data_gas_price: header.strk_l1_data_gas_price,
sequencer_address: header.sequencer_address,
starknet_version: header.starknet_version,
event_commitment: header.event_commitment,
state_commitment: header.state_commitment,
transaction_commitment: header.transaction_commitment,
transaction_count: header.transaction_count,
event_count: header.event_count,
l1_da_mode: header.l1_da_mode,
signature,
}
}
}

/// Represents a simplified [`pathfinder_common::receipt::Receipt`] (events and transaction index excluded).
#[derive(Clone, Default, Debug, PartialEq)]
pub struct Receipt {
pub actual_fee: Option<Fee>,
pub execution_resources: Option<ExecutionResources>,
pub l2_to_l1_messages: Vec<L2ToL1Message>,
pub execution_status: ExecutionStatus,
pub transaction_hash: TransactionHash,
}

impl From<pathfinder_common::receipt::Receipt> for Receipt {
fn from(x: pathfinder_common::receipt::Receipt) -> Self {
Self {
transaction_hash: x.transaction_hash,
actual_fee: x.actual_fee,
execution_resources: x.execution_resources,
l2_to_l1_messages: x.l2_to_l1_messages,
execution_status: x.execution_status,
}
}
}

impl TryFrom<p2p_proto::receipt::Receipt> for Receipt {
type Error = anyhow::Error;

fn try_from(proto: p2p_proto::receipt::Receipt) -> anyhow::Result<Self>
where
Self: Sized,
{
use p2p_proto::receipt::Receipt::{Declare, Deploy, DeployAccount, Invoke, L1Handler};
use p2p_proto::receipt::{
DeclareTransactionReceipt, DeployAccountTransactionReceipt, DeployTransactionReceipt,
InvokeTransactionReceipt, L1HandlerTransactionReceipt,
};
match proto {
Invoke(InvokeTransactionReceipt { common })
| Declare(DeclareTransactionReceipt { common })
| L1Handler(L1HandlerTransactionReceipt { common, .. })
| Deploy(DeployTransactionReceipt { common, .. })
| DeployAccount(DeployAccountTransactionReceipt { common, .. }) => {
let data_availability = (common.execution_resources.l1_gas != Felt::ZERO
|| common.execution_resources.l1_data_gas != Felt::ZERO)
.then_some(ExecutionDataAvailability {
l1_gas: GasPrice::from(common.execution_resources.l1_gas).0,
l1_data_gas: GasPrice::from(common.execution_resources.l1_data_gas).0,
});
Ok(Self {
transaction_hash: TransactionHash(common.transaction_hash.0),
actual_fee: Some(Fee(common.actual_fee)),
execution_resources: Some(ExecutionResources {
builtin_instance_counter: BuiltinCounters {
output_builtin: common.execution_resources.builtins.output.into(),
pedersen_builtin: common.execution_resources.builtins.pedersen.into(),
range_check_builtin: common
.execution_resources
.builtins
.range_check
.into(),
ecdsa_builtin: common.execution_resources.builtins.ecdsa.into(),
bitwise_builtin: common.execution_resources.builtins.bitwise.into(),
ec_op_builtin: common.execution_resources.builtins.ec_op.into(),
keccak_builtin: common.execution_resources.builtins.keccak.into(),
poseidon_builtin: common.execution_resources.builtins.poseidon.into(),
segment_arena_builtin: 0,
},
n_steps: common.execution_resources.steps.into(),
n_memory_holes: common.execution_resources.memory_holes.into(),
data_availability,
}),
l2_to_l1_messages: common
.messages_sent
.into_iter()
.map(|x| L2ToL1Message {
from_address: ContractAddress(x.from_address),
payload: x
.payload
.into_iter()
.map(L2ToL1MessagePayloadElem)
.collect(),
to_address: EthereumAddress(x.to_address.0),
})
.collect(),
execution_status: if common.revert_reason.is_empty() {
ExecutionStatus::Succeeded
} else {
ExecutionStatus::Reverted {
reason: common.revert_reason,
}
},
})
}
}
}
}

/// Deployed contract address has not been computed for deploy account transactions.
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum RawTransactionVariant {
Expand Down Expand Up @@ -473,3 +585,16 @@ impl TryFromDto<String> for DataAvailabilityMode {
}
}
}

impl TryFromDto<p2p_proto::common::L1DataAvailabilityMode> for L1DataAvailabilityMode {
fn try_from_dto(dto: p2p_proto::common::L1DataAvailabilityMode) -> anyhow::Result<Self>
where
Self: Sized,
{
use p2p_proto::common::L1DataAvailabilityMode::{Blob, Calldata};
Ok(match dto {
Calldata => Self::Calldata,
Blob => Self::Blob,
})
}
}
12 changes: 11 additions & 1 deletion crates/p2p_proto/proto/common.proto
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,18 @@ message PeerID {
bytes id = 1;
}

message Uint128 {
uint64 low = 1;
uint64 high = 2;
}

message ConsensusSignature {
Felt252 r = 1;
Felt252 s = 2;
}

message Merkle {
uint32 n_leaves = 1; // needed to know the height, so as to how many nodes to expect in a proof.
uint64 n_leaves = 1; // needed to know the height, so as to how many nodes to expect in a proof.
// and also when receiving all leaves, how many to expect
Hash root = 2;
}
Expand All @@ -43,6 +48,11 @@ message BlockID {
Hash header = 2;
}

enum L1DataAvailabilityMode {
Calldata = 0;
Blob = 1;
}

message Iteration {
enum Direction {
Forward = 0;
Expand Down
38 changes: 21 additions & 17 deletions crates/p2p_proto/proto/header.proto
Original file line number Diff line number Diff line change
Expand Up @@ -7,26 +7,30 @@ package starknet.header;
// Note: commitments may change to be for the previous blocks like comet/tendermint
// hash of block header sent to L1
message SignedBlockHeader {
starknet.common.Hash block_hash = 1; // For the structure of the block hash, see https://docs.starknet.io/documentation/architecture_and_concepts/Network_Architecture/header/#block_hash
starknet.common.Hash parent_hash = 2;
uint64 number = 3;
uint64 time = 4; // Encoded in Unix time.
starknet.common.Address sequencer_address = 5;
starknet.common.Hash state_diff_commitment = 6; // The state diff commitment returned by the Starknet Feeder Gateway.
starknet.common.Hash block_hash = 1; // For the structure of the block hash, see https://docs.starknet.io/documentation/architecture_and_concepts/Network_Architecture/header/#block_hash
starknet.common.Hash parent_hash = 2;
uint64 number = 3;
uint64 time = 4; // Encoded in Unix time.
starknet.common.Address sequencer_address = 5;
starknet.common.Hash state_diff_commitment = 6; // The state diff commitment returned by the Starknet Feeder Gateway.
// For more info, see https://community.starknet.io/t/introducing-p2p-authentication-and-mismatch-resolution-in-v0-12-2/97993
starknet.common.Patricia state = 7; // hash of contract and class patricia tries. Same as in L1. Later more trees will be included
starknet.common.Patricia state = 7; // hash of contract and class patricia tries. Same as in L1. Later more trees will be included
// The following merkles can be built on the fly while sequencing/validating txs.
starknet.common.Merkle transactions = 8; // By order of execution. TBD: required? the client can execute (powerful machine) and match state diff
starknet.common.Merkle events = 9; // By order of issuance. TBD: in receipts?
starknet.common.Merkle receipts = 10; // By order of issuance.
string protocol_version = 11; // Starknet version
starknet.common.Felt252 gas_price = 12;
uint64 num_storage_diffs = 13;
uint64 num_nonce_updates = 14;
uint64 num_declared_classes = 15; // Includes both Cairo 0 and Cairo 1.
uint64 num_deployed_contracts = 16; // This includes the replaced classes too.
starknet.common.Merkle transactions = 8; // By order of execution. TBD: required? the client can execute (powerful machine) and match state diff
starknet.common.Merkle events = 9; // By order of issuance. TBD: in receipts?
starknet.common.Merkle receipts = 10; // By order of issuance.
string protocol_version = 11; // Starknet version
starknet.common.Uint128 gas_price_fri = 12;
starknet.common.Uint128 gas_price_wei = 13;
starknet.common.Uint128 data_gas_price_fri = 14;
starknet.common.Uint128 data_gas_price_wei = 15;
starknet.common.L1DataAvailabilityMode l1_data_availability_mode = 16;
uint64 num_storage_diffs = 17;
uint64 num_nonce_updates = 18;
uint64 num_declared_classes = 19; // Includes both Cairo 0 and Cairo 1.
uint64 num_deployed_contracts = 20; // This includes the replaced classes too.
// for now, we assume a small consensus, so this fits in 1M. Else, these will be repeated and extracted from this message.
repeated starknet.common.ConsensusSignature signatures = 17; //
repeated starknet.common.ConsensusSignature signatures = 21;
// can be more explicit here about the signature structure as this is not part of account abstraction
}

Expand Down
8 changes: 5 additions & 3 deletions crates/p2p_proto/proto/receipt.proto
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,11 @@ message Receipt {
uint32 output = 8;
}

BuiltinCounter builtins = 1;
uint32 steps = 2;
uint32 memory_holes = 3;
BuiltinCounter builtins = 1;
uint32 steps = 2;
uint32 memory_holes = 3;
starknet.common.Felt252 l1_gas = 4;
starknet.common.Felt252 l1_data_gas = 5;
}

message Common {
Expand Down
46 changes: 45 additions & 1 deletion crates/p2p_proto/src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ pub struct ConsensusSignature {
#[derive(Debug, Copy, Clone, PartialEq, Eq, ToProtobuf, TryFromProtobuf, Dummy, Default)]
#[protobuf(name = "crate::proto::common::Merkle")]
pub struct Merkle {
pub n_leaves: u32,
pub n_leaves: u64,
pub root: Hash,
}

Expand All @@ -48,6 +48,12 @@ pub struct BlockId {
pub hash: Hash,
}

#[derive(Debug, Copy, Clone, PartialEq, Eq, Dummy)]
pub enum L1DataAvailabilityMode {
Calldata,
Blob,
}

#[derive(Debug, Copy, Clone, PartialEq, Eq, ToProtobuf, TryFromProtobuf, Dummy)]
#[protobuf(name = "crate::proto::common::Iteration")]
pub struct Iteration {
Expand Down Expand Up @@ -154,6 +160,26 @@ impl Display for BlockId {
}
}

impl ToProtobuf<i32> for L1DataAvailabilityMode {
fn to_protobuf(self) -> i32 {
use proto::common::L1DataAvailabilityMode::{Blob, Calldata};
match self {
L1DataAvailabilityMode::Calldata => Calldata as i32,
L1DataAvailabilityMode::Blob => Blob as i32,
}
}
}

impl TryFromProtobuf<i32> for L1DataAvailabilityMode {
fn try_from_protobuf(input: i32, _: &'static str) -> Result<Self, std::io::Error> {
use proto::common::L1DataAvailabilityMode::{Blob, Calldata};
Ok(match TryFrom::try_from(input)? {
Calldata => L1DataAvailabilityMode::Calldata,
Blob => L1DataAvailabilityMode::Blob,
})
}
}

impl ToProtobuf<proto::common::PeerId> for PeerId {
fn to_protobuf(self) -> proto::common::PeerId {
proto::common::PeerId {
Expand All @@ -177,6 +203,24 @@ impl TryFromProtobuf<proto::common::PeerId> for PeerId {
}
}

impl ToProtobuf<proto::common::Uint128> for u128 {
fn to_protobuf(self) -> proto::common::Uint128 {
proto::common::Uint128 {
low: (self & 0xFFFF_FFFF_FFFF_FFFF) as u64,
high: (self >> 64) as u64,
}
}
}

impl TryFromProtobuf<proto::common::Uint128> for u128 {
fn try_from_protobuf(
input: proto::common::Uint128,
_: &'static str,
) -> Result<Self, std::io::Error> {
Ok((input.high as u128) << 64 | input.low as u128)
}
}

impl From<u64> for BlockNumberOrHash {
fn from(x: u64) -> Self {
Self::Number(x)
Expand Down
Loading
Loading