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

versioning #1637

Merged
merged 52 commits into from
Jul 10, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
0555b0b
Replace public header fields with getters
jbearer May 23, 2024
f605483
WIP upgradable types
jbearer May 28, 2024
8adbdfd
v2
imabdulbasit Jun 24, 2024
365d884
merge origin/main
imabdulbasit Jun 24, 2024
0f225bb
Merge branch 'main' into ab/ver
imabdulbasit Jun 24, 2024
9896587
cargo sort
imabdulbasit Jun 24, 2024
6e2e9e6
block impls
imabdulbasit Jun 25, 2024
ad046c3
remove unused imports
imabdulbasit Jun 25, 2024
278f1fb
export types
imabdulbasit Jun 25, 2024
82ec12f
group imports
imabdulbasit Jun 25, 2024
bcff34a
v3 header
imabdulbasit Jun 25, 2024
eac798d
lint
imabdulbasit Jun 25, 2024
69fce8b
remove v2 header definition
imabdulbasit Jun 25, 2024
8819268
move crates to workspace
imabdulbasit Jun 25, 2024
4dae934
remove types from sequencer crate
imabdulbasit Jun 26, 2024
26876bc
group imports
imabdulbasit Jun 26, 2024
aaa6f11
serialization
imabdulbasit Jul 1, 2024
0fc4398
fix test
imabdulbasit Jul 1, 2024
df2b9b5
fix deserialization
imabdulbasit Jul 2, 2024
0dbc44b
Merge remote-tracking branch 'origin/main' into ab/ver
imabdulbasit Jul 2, 2024
43d9331
cargo sort
imabdulbasit Jul 2, 2024
d68d146
lint
imabdulbasit Jul 2, 2024
013a32c
fix payload::empty()
imabdulbasit Jul 2, 2024
2c28e6c
fix: visit_map deserialization
imabdulbasit Jul 2, 2024
daeb6c4
use serde_json map
imabdulbasit Jul 2, 2024
4815708
cargo sort
imabdulbasit Jul 2, 2024
7d197dd
Merge branch 'main' into ab/ver
imabdulbasit Jul 2, 2024
420af73
fix ResolvableChainConfigOrVersion deserialization
imabdulbasit Jul 2, 2024
41d0bd9
Merge remote-tracking branch 'origin/main' into ab/ver
imabdulbasit Jul 3, 2024
179d80a
move out traits and errors
imabdulbasit Jul 3, 2024
639a903
fix imports
imabdulbasit Jul 3, 2024
7fa7f20
move errors into impls
imabdulbasit Jul 8, 2024
d0ac37b
Merge remote-tracking branch 'origin/main' into ab/ver
imabdulbasit Jul 8, 2024
1dc9da5
remove ResolvableChainConfig and generic parameters from EitherOrVersion
imabdulbasit Jul 9, 2024
18531d2
remove committable trait implementation for v1 Header
imabdulbasit Jul 9, 2024
faf5f1f
add comments for VersionedHeader
imabdulbasit Jul 9, 2024
7f3b541
remove StructFields enum
imabdulbasit Jul 10, 2024
02c9c0e
add reference tests for v1, v2, and v3 header
imabdulbasit Jul 10, 2024
95b06ab
move reference_tests to types crate
imabdulbasit Jul 10, 2024
c7d93df
fix: v2 and v3 reference test
imabdulbasit Jul 10, 2024
8c8b193
Merge remote-tracking branch 'origin/main' into ab/ver
imabdulbasit Jul 10, 2024
e7a2926
fix comments
imabdulbasit Jul 10, 2024
5a5a4da
add comments for Header::genesis()
imabdulbasit Jul 10, 2024
bfbf42f
add comments for Header::create panic
imabdulbasit Jul 10, 2024
2676df2
add comment for global error issue
imabdulbasit Jul 10, 2024
27e928f
add comment for global error issue
imabdulbasit Jul 10, 2024
1127c84
build genesis header for the current sequencer version
imabdulbasit Jul 10, 2024
bfa3d9c
version sub-directories for data dir
imabdulbasit Jul 10, 2024
4aad7ba
move messages.json and messages.bin to data dir
imabdulbasit Jul 10, 2024
be85894
update data readme
imabdulbasit Jul 10, 2024
a6cec5e
cargo update
imabdulbasit Jul 10, 2024
d2b7b51
include sub dirs binaries in gitignore
imabdulbasit Jul 10, 2024
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
27 changes: 13 additions & 14 deletions sequencer/src/reference_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ use async_compatibility_layer::logging::{setup_backtrace, setup_logging};
use committable::Committable;
use es_version::SequencerVersion;
use espresso_types::{
ChainConfig, FeeAccount, FeeInfo, Header, L1BlockInfo, NamespaceId, NsTable, Payload, SeqTypes,
Transaction, ValidatedState,
v0_1, ChainConfig, FeeAccount, FeeInfo, Header, L1BlockInfo, NamespaceId, NsTable, Payload,
SeqTypes, Transaction, ValidatedState,
};
use hotshot_query_service::availability::QueryablePayload;
use hotshot_types::traits::{
Expand All @@ -40,7 +40,7 @@ use serde::{de::DeserializeOwned, Serialize};
use serde_json::Value;
use std::{fmt::Debug, path::Path, str::FromStr};
use tagged_base64::TaggedBase64;
use vbs::{version::Version, BinarySerializer};
use vbs::BinarySerializer;

type Serializer = vbs::Serializer<SequencerVersion>;

Expand Down Expand Up @@ -126,21 +126,20 @@ async fn reference_header() -> Header {

let state = ValidatedState::default();

Header::create(
reference_chain_config().into(),
42,
789,
124,
Some(reference_l1_block()),
Header::V1(v0_1::Header {
chain_config: reference_chain_config().into(),
height: 42,
timestamp: 789,
l1_head: 124,
l1_finalized: Some(reference_l1_block()),
payload_commitment,
builder_commitment,
ns_table,
state.fee_merkle_tree.commitment(),
state.block_merkle_tree.commitment(),
block_merkle_tree_root: state.fee_merkle_tree.commitment(),
fee_merkle_tree_root: state.block_merkle_tree.commitment(),
fee_info,
Some(builder_signature),
Version { major: 0, minor: 1 },
)
builder_signature: Some(builder_signature),
})
}

const REFERENCE_HEADER_COMMITMENT: &str = "BLOCK~dh1KpdvvxSvnnPpOi2yI3DOg8h6ltr2Kv13iRzbQvtN2";
Expand Down
24 changes: 16 additions & 8 deletions types/src/v0/header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,28 @@ pub enum Header {
V3(v0_3::Header),
}

// Enum to represent the first field of different versions of a header
//
// In v1 headers, the first field is a ChainConfig, which contains either the chain config or its commitment.
// For versions > 0.1, the first field contains the version.
//
// This enum has the same variant names and types in the same positions (0 and 1) as the Either enum,
// ensuring identical serialization and deserialization for the Left and Right variants.
// However, it will deserialize successfully in one additional case due to the Version variant.
//
// Variants:
// - Left: Represents the ChainConfig variant in v1 headers.
// - Right: Represents the chain config commitment variant in v1 headers.
// - Version: Represents the versioned header for versions > 0.1.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub(crate) enum EitherOrVersion<ChainConfig, Commitment> {
pub(crate) enum EitherOrVersion {
Left(ChainConfig),
Right(Commitment),
Right(Commitment<ChainConfig>),
Version(Version),
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct VersionedHeader<Fields> {
pub(crate) version: ResolvableChainConfigOrVersion,
pub(crate) version: EitherOrVersion,
pub(crate) fields: Fields,
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct ResolvableChainConfigOrVersion {
pub(crate) chain_config: EitherOrVersion<ChainConfig, Commitment<ChainConfig>>,
}
162 changes: 88 additions & 74 deletions types/src/v0/impls/header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ use hotshot_types::{
utils::BuilderCommitment,
vid::{VidCommitment, VidCommon},
};
use itertools::Either;
use jf_merkle_tree::{AppendableMerkleTreeScheme, MerkleTreeScheme};
use serde::{
de::{self, MapAccess, SeqAccess, Visitor},
Expand All @@ -27,7 +26,7 @@ use time::OffsetDateTime;
use vbs::version::Version;

use crate::{
v0::header::{EitherOrVersion, ResolvableChainConfigOrVersion, VersionedHeader},
v0::header::{EitherOrVersion, VersionedHeader},
v0_1, v0_2, v0_3, BlockMerkleCommitment, BlockSize, BuilderSignature, ChainConfig, FeeAccount,
FeeAmount, FeeInfo, FeeMerkleCommitment, Header, L1BlockInfo, L1Snapshot, Leaf, NamespaceId,
NodeState, NsTable, NsTableValidationError, ResolvableChainConfig, SeqTypes, UpgradeType,
Expand Down Expand Up @@ -74,40 +73,46 @@ pub enum ProposalValidationError {

impl Committable for Header {
fn commit(&self) -> Commitment<Self> {
let mut bmt_bytes = vec![];
self.block_merkle_tree_root()
.serialize_with_mode(&mut bmt_bytes, ark_serialize::Compress::Yes)
.unwrap();
let mut fmt_bytes = vec![];
self.fee_merkle_tree_root()
.serialize_with_mode(&mut fmt_bytes, ark_serialize::Compress::Yes)
.unwrap();
let v1_commit = || {
let mut bmt_bytes = vec![];
self.block_merkle_tree_root()
.serialize_with_mode(&mut bmt_bytes, ark_serialize::Compress::Yes)
.unwrap();
let mut fmt_bytes = vec![];
self.fee_merkle_tree_root()
.serialize_with_mode(&mut fmt_bytes, ark_serialize::Compress::Yes)
.unwrap();

RawCommitmentBuilder::new(&Self::tag())
.field("chain_config", self.chain_config().commit())
.u64_field("height", self.height())
.u64_field("timestamp", self.timestamp())
.u64_field("l1_head", self.l1_head())
.optional("l1_finalized", &self.l1_finalized())
.constant_str("payload_commitment")
.fixed_size_bytes(self.payload_commitment().as_ref().as_ref())
.constant_str("builder_commitment")
.fixed_size_bytes(self.builder_commitment().as_ref())
.field("ns_table", self.ns_table().commit())
.var_size_field("block_merkle_tree_root", &bmt_bytes)
.var_size_field("fee_merkle_tree_root", &fmt_bytes)
.field("fee_info", self.fee_info().commit())
.finalize()
};

let mut c = RawCommitmentBuilder::new(&Self::tag());
if self.version() > v0_1::VERSION {
// The original commitment scheme (from version 0.1) did not include the version in the
// commitment. We respect this for backwards compatibility, but for all future versions,
// we want to include it.
c = c
.u64_field("version_major", self.version().major.into())
.u64_field("version_minor", self.version().minor.into());
match self {
Self::V1(_) => v1_commit(),
Self::V2(fields) => RawCommitmentBuilder::new(&Self::tag())
.u64_field("version_major", 0)
.u64_field("version_minor", 2)
.field("fields", fields.commit())
.finalize(),
Self::V3(fields) => RawCommitmentBuilder::new(&Self::tag())
.u64_field("version_major", 0)
.u64_field("version_minor", 3)
.field("fields", fields.commit())
.finalize(),
}
c = c
.field("chain_config", self.chain_config().commit())
.u64_field("height", self.height())
.u64_field("timestamp", self.timestamp())
.u64_field("l1_head", self.l1_head())
.optional("l1_finalized", &self.l1_finalized())
.constant_str("payload_commitment")
.fixed_size_bytes(self.payload_commitment().as_ref().as_ref())
.constant_str("builder_commitment")
.fixed_size_bytes(self.builder_commitment().as_ref())
.field("ns_table", self.ns_table().commit())
.var_size_field("block_merkle_tree_root", &bmt_bytes)
.var_size_field("fee_merkle_tree_root", &fmt_bytes)
.field("fee_info", self.fee_info().commit());

c.finalize()
}

fn tag() -> String {
Expand All @@ -127,26 +132,26 @@ impl Header {
}
}

impl From<Version> for ResolvableChainConfigOrVersion {
fn from(version: Version) -> Self {
Self {
chain_config: EitherOrVersion::Version(version),
}
}
}

impl From<ResolvableChainConfig> for ResolvableChainConfigOrVersion {
fn from(v: ResolvableChainConfig) -> Self {
let value = match v.chain_config {
Either::Left(cfg) => EitherOrVersion::Left(cfg),
Either::Right(commit) => EitherOrVersion::Right(commit),
};

Self {
chain_config: value,
}
}
}
// impl From<Version> for ResolvableChainConfigOrVersion {
// fn from(version: Version) -> Self {
// Self {
// chain_config: EitherOrVersion::Version(version),
// }
// }
// }

// impl From<ResolvableChainConfig> for ResolvableChainConfigOrVersion {
// fn from(v: ResolvableChainConfig) -> Self {
// let value = match v.chain_config {
// Either::Left(cfg) => EitherOrVersion::Left(cfg),
// Either::Right(commit) => EitherOrVersion::Right(commit),
// };

// Self {
// chain_config: value,
// }
// }
// }

impl Serialize for Header {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
Expand All @@ -156,12 +161,12 @@ impl Serialize for Header {
match self {
Self::V1(header) => header.serialize(serializer),
Self::V2(fields) => VersionedHeader {
version: Version { major: 0, minor: 2 }.into(),
version: EitherOrVersion::Version(Version { major: 0, minor: 2 }),
fields: fields.clone(),
}
.serialize(serializer),
Self::V3(fields) => VersionedHeader {
version: Version { major: 0, minor: 3 }.into(),
version: EitherOrVersion::Version(Version { major: 0, minor: 3 }),
fields: fields.clone(),
}
.serialize(serializer),
Expand Down Expand Up @@ -194,6 +199,7 @@ impl StructFields {
&[
"fields",
"chain_config",
"version",
"height",
"timestamp",
"l1_head",
Expand Down Expand Up @@ -227,11 +233,11 @@ impl<'de> Deserialize<'de> for Header {
where
V: SeqAccess<'de>,
{
let chain_config_or_version: ResolvableChainConfigOrVersion =
seq.next_element()?
.ok_or_else(|| de::Error::missing_field("chain_config"))?;
let chain_config_or_version: EitherOrVersion = seq
.next_element()?
.ok_or_else(|| de::Error::missing_field("chain_config"))?;

match chain_config_or_version.chain_config {
match chain_config_or_version {
// For v0.1, the first field in the sequence of fields is the first field of the struct, so we call a function to get the rest of
// the fields from the sequence and pack them into the struct.
EitherOrVersion::Left(cfg) => Ok(Header::V1(
Expand All @@ -250,7 +256,9 @@ impl<'de> Deserialize<'de> for Header {
seq.next_element()?
.ok_or_else(|| de::Error::missing_field("fields"))?,
)),
_ => Err(serde::de::Error::custom("invalid version")),
EitherOrVersion::Version(v) => {
Err(serde::de::Error::custom(format!("invalid version {v:?}")))
}
}
}

Expand All @@ -270,20 +278,17 @@ impl<'de> Deserialize<'de> for Header {
.get(&StructFields::Fields.to_string())
.ok_or_else(|| de::Error::missing_field("fields"))?;

let version =
serde_json::from_value::<ResolvableChainConfigOrVersion>(v.clone())
.map_err(de::Error::custom)?
.chain_config;
let version = serde_json::from_value::<EitherOrVersion>(v.clone())
.map_err(de::Error::custom)?;
let result = match version {
EitherOrVersion::Version(Version { major: 0, minor: 2 }) => Ok(Header::V2(
serde_json::from_value(fields.clone()).map_err(de::Error::custom)?,
)),
EitherOrVersion::Version(Version { major: 0, minor: 3 }) => Ok(Header::V3(
serde_json::from_value(fields.clone()).map_err(de::Error::custom)?,
)),
_ => Err(serde::de::Error::custom("invalid version")),
v => Err(serde::de::Error::custom(format!("invalid version {v:?}"))),
};

return result;
}

Expand All @@ -299,7 +304,7 @@ impl<'de> Deserialize<'de> for Header {

impl Header {
#[allow(clippy::too_many_arguments)]
pub fn create(
pub(crate) fn create(
chain_config: ResolvableChainConfig,
height: u64,
timestamp: u64,
Expand Down Expand Up @@ -1459,7 +1464,8 @@ mod test_headers {
);

let serialized = serde_json::to_string(&v1_header).unwrap();
let _: Header = serde_json::from_str(&serialized).unwrap();
let deserialized: Header = serde_json::from_str(&serialized).unwrap();
assert_eq!(v1_header, deserialized);

let v2_header = Header::create(
genesis.instance_state.chain_config.into(),
Expand All @@ -1481,7 +1487,8 @@ mod test_headers {
);

let serialized = serde_json::to_string(&v2_header).unwrap();
let _: Header = serde_json::from_str(&serialized).unwrap();
let deserialized: Header = serde_json::from_str(&serialized).unwrap();
assert_eq!(v2_header, deserialized);

let v3_header = Header::create(
genesis.instance_state.chain_config.into(),
Expand All @@ -1503,15 +1510,22 @@ mod test_headers {
);

let serialized = serde_json::to_string(&v3_header).unwrap();
let _: Header = serde_json::from_str(&serialized).unwrap();
let deserialized: Header = serde_json::from_str(&serialized).unwrap();
assert_eq!(v3_header, deserialized);

let v1_bytes = BincodeSerializer::<StaticVersion<0, 1>>::serialize(&v1_header).unwrap();
let _: Header = BincodeSerializer::<StaticVersion<0, 1>>::deserialize(&v1_bytes).unwrap();
let deserialized: Header =
BincodeSerializer::<StaticVersion<0, 1>>::deserialize(&v1_bytes).unwrap();
assert_eq!(v1_header, deserialized);

let v2_bytes = BincodeSerializer::<StaticVersion<0, 2>>::serialize(&v2_header).unwrap();
let _: Header = BincodeSerializer::<StaticVersion<0, 2>>::deserialize(&v2_bytes).unwrap();
let deserialized: Header =
BincodeSerializer::<StaticVersion<0, 2>>::deserialize(&v2_bytes).unwrap();
assert_eq!(v2_header, deserialized);

let v3_bytes = BincodeSerializer::<StaticVersion<0, 3>>::serialize(&v3_header).unwrap();
let _: Header = BincodeSerializer::<StaticVersion<0, 3>>::deserialize(&v3_bytes).unwrap();
let deserialized: Header =
BincodeSerializer::<StaticVersion<0, 3>>::deserialize(&v3_bytes).unwrap();
assert_eq!(v3_header, deserialized);
}
}
Loading
Loading