-
Notifications
You must be signed in to change notification settings - Fork 81
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Initial draft for minimal L1 stake table * Add Schnorr verifying key * fix solhint error: named mapping keys and values * WIP: contract stake table types to rust types Missing conversion from G2 Affine to BLSPubKey. * rename: SimpleStakeTable -> PermissionedStakeTable * PermissionedStakeTable contract: add DA flag - Update bindings. - Add tests for event emission. * Allow setting an initial stake table on deployment - The stake table isn't useful without stakers I think it makes sense to require it to be provided on deployment. * deploy: load initial stake table from toml file * Use serde instead of unsafe rust We will add some more ergonomic code for conversion to jellyfish at some point. This code can be used as a stop gap until then. * Update utils/src/deployer.rs Co-authored-by: Alysia Tech <[email protected]> * WIP: load initial stake table from file * Move solidity <-> jf code to contract adapter * Load initial stake table from file * remove unused imports * remove unused module * dev-node: fix arguments to deploy function * fix clippy * fix Cargo.toml for bindings generation breaks if we use: `serde.workspace = true` * combine adding and removing into single event * update comment to match implementation (#2282) * align comment with implementation * added more clarity * comment format * clearer comment * update comment to make it clear that there may be outdated elements in the state history * update query-service * db max connections = 25 for dev node tests * update query-service * Fix no-storage decides * Branches -> tags * 2368 stake table registration with fixed stake (#2365) * add stake table tests * remove stake types * verify token allowance, balance and reprioritize verification order on registration * set the fixed stake amount, added related tests, updated data types * add more verification checks to the withdraw function * updated errror types * added TODO statements in comments to be explicit about outdated functions that need to be updated to the new spec * fix env var for permissioned_stake_table * Add test for jf / contract types conversions * cleanup: pass rng * load stake table from toml file (#2377) * change lc proxy addr * fix deploy-sequencer-contracts in docker compose * test for stake table from toml file * initial stake table toml file * exclude toml file in typos * remove custom deser * remove unnecessary rand dependency --------- Co-authored-by: Alysia Tech <[email protected]> Co-authored-by: tbro <[email protected]> Co-authored-by: imabdulbasit <[email protected]> Co-authored-by: Artemii Gerasimovich <[email protected]> Co-authored-by: Abdul Basit <[email protected]>
- Loading branch information
1 parent
bc5b7f1
commit 979cfb3
Showing
24 changed files
with
1,880 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
1,169 changes: 1,169 additions & 0 deletions
1,169
contract-bindings/src/permissioned_stake_table.rs
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,224 @@ | ||
use crate::jellyfish::u256_to_field; | ||
use ark_ec::{ | ||
short_weierstrass, | ||
twisted_edwards::{self, Affine, TECurveConfig}, | ||
AffineRepr, | ||
}; | ||
use ark_ed_on_bn254::EdwardsConfig; | ||
use ark_ff::{BigInteger, PrimeField}; | ||
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; | ||
use contract_bindings::permissioned_stake_table::{self, EdOnBN254Point, NodeInfo}; | ||
use diff_test_bn254::ParsedG2Point; | ||
use ethers::{ | ||
abi::AbiDecode, | ||
prelude::{AbiError, EthAbiCodec, EthAbiType}, | ||
types::U256, | ||
}; | ||
use hotshot_types::{light_client::StateVerKey, network::PeerConfigKeys, signature_key::BLSPubKey}; | ||
use serde::{Deserialize, Serialize}; | ||
use std::str::FromStr; | ||
|
||
// TODO: (alex) maybe move these commonly shared util to a crate | ||
/// convert a field element to U256, panic if field size is larger than 256 bit | ||
pub fn field_to_u256<F: PrimeField>(f: F) -> U256 { | ||
if F::MODULUS_BIT_SIZE > 256 { | ||
panic!("Shouldn't convert a >256-bit field to U256"); | ||
} | ||
U256::from_little_endian(&f.into_bigint().to_bytes_le()) | ||
} | ||
|
||
/// an intermediate representation of `EdOnBN254Point` in solidity. | ||
#[derive(Clone, PartialEq, Eq, Debug, EthAbiType, EthAbiCodec)] | ||
pub struct ParsedEdOnBN254Point { | ||
/// x coordinate of affine repr | ||
pub x: U256, | ||
/// y coordinate of affine repr | ||
pub y: U256, | ||
} | ||
|
||
// this is convention from BN256 precompile | ||
impl Default for ParsedEdOnBN254Point { | ||
fn default() -> Self { | ||
Self { | ||
x: U256::from(0), | ||
y: U256::from(0), | ||
} | ||
} | ||
} | ||
|
||
impl From<ParsedEdOnBN254Point> for EdOnBN254Point { | ||
fn from(value: ParsedEdOnBN254Point) -> Self { | ||
Self { | ||
x: value.x, | ||
y: value.y, | ||
} | ||
} | ||
} | ||
|
||
impl From<EdOnBN254Point> for ParsedEdOnBN254Point { | ||
fn from(value: EdOnBN254Point) -> Self { | ||
let EdOnBN254Point { x, y } = value; | ||
Self { x, y } | ||
} | ||
} | ||
|
||
impl FromStr for ParsedEdOnBN254Point { | ||
type Err = AbiError; | ||
fn from_str(s: &str) -> Result<Self, Self::Err> { | ||
let parsed: (Self,) = AbiDecode::decode_hex(s)?; | ||
Ok(parsed.0) | ||
} | ||
} | ||
|
||
impl<P: TECurveConfig> From<Affine<P>> for ParsedEdOnBN254Point | ||
where | ||
P::BaseField: PrimeField, | ||
{ | ||
fn from(p: Affine<P>) -> Self { | ||
if p.is_zero() { | ||
// this convention is from the BN precompile | ||
Self { | ||
x: U256::from(0), | ||
y: U256::from(0), | ||
} | ||
} else { | ||
Self { | ||
x: field_to_u256::<P::BaseField>(*p.x().unwrap()), | ||
y: field_to_u256::<P::BaseField>(*p.y().unwrap()), | ||
} | ||
} | ||
} | ||
} | ||
|
||
impl<P: TECurveConfig> From<ParsedEdOnBN254Point> for Affine<P> | ||
where | ||
P::BaseField: PrimeField, | ||
{ | ||
fn from(p: ParsedEdOnBN254Point) -> Self { | ||
if p == ParsedEdOnBN254Point::default() { | ||
Self::default() | ||
} else { | ||
Self::new_unchecked( | ||
u256_to_field::<P::BaseField>(p.x), | ||
u256_to_field::<P::BaseField>(p.y), | ||
) | ||
} | ||
} | ||
} | ||
|
||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] | ||
pub struct NodeInfoJf { | ||
pub stake_table_key: BLSPubKey, | ||
pub state_ver_key: StateVerKey, | ||
pub da: bool, | ||
} | ||
|
||
impl From<NodeInfoJf> for NodeInfo { | ||
fn from(value: NodeInfoJf) -> Self { | ||
let NodeInfoJf { | ||
stake_table_key, | ||
state_ver_key, | ||
da, | ||
} = value; | ||
let ParsedG2Point { x0, x1, y0, y1 } = stake_table_key.to_affine().into(); | ||
let schnorr: ParsedEdOnBN254Point = state_ver_key.to_affine().into(); | ||
Self { | ||
bls_vk: permissioned_stake_table::G2Point { | ||
x_0: x0, | ||
x_1: x1, | ||
y_0: y0, | ||
y_1: y1, | ||
}, | ||
schnorr_vk: schnorr.into(), | ||
is_da: da, | ||
} | ||
} | ||
} | ||
|
||
impl From<NodeInfo> for NodeInfoJf { | ||
fn from(value: NodeInfo) -> Self { | ||
let NodeInfo { | ||
bls_vk, | ||
schnorr_vk, | ||
is_da, | ||
} = value; | ||
let stake_table_key = { | ||
let g2 = diff_test_bn254::ParsedG2Point { | ||
x0: bls_vk.x_0, | ||
x1: bls_vk.x_1, | ||
y0: bls_vk.y_0, | ||
y1: bls_vk.y_1, | ||
}; | ||
let g2_affine = short_weierstrass::Affine::<ark_bn254::g2::Config>::from(g2); | ||
let mut bytes = vec![]; | ||
// TODO: remove serde round-trip once jellyfin provides a way to | ||
// convert from Affine representation to VerKey. | ||
// | ||
// Serialization and de-serialization shouldn't fail. | ||
g2_affine | ||
.into_group() | ||
.serialize_compressed(&mut bytes) | ||
.unwrap(); | ||
BLSPubKey::deserialize_compressed(&bytes[..]).unwrap() | ||
}; | ||
let state_ver_key = { | ||
let g1_point: ParsedEdOnBN254Point = schnorr_vk.into(); | ||
let state_sk_affine = twisted_edwards::Affine::<EdwardsConfig>::from(g1_point); | ||
StateVerKey::from(state_sk_affine) | ||
}; | ||
Self { | ||
stake_table_key, | ||
state_ver_key, | ||
da: is_da, | ||
} | ||
} | ||
} | ||
|
||
impl From<PeerConfigKeys<BLSPubKey>> for NodeInfoJf { | ||
fn from(value: PeerConfigKeys<BLSPubKey>) -> Self { | ||
let PeerConfigKeys { | ||
stake_table_key, | ||
state_ver_key, | ||
da, | ||
.. | ||
} = value; | ||
Self { | ||
stake_table_key, | ||
state_ver_key, | ||
da, | ||
} | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod test { | ||
use super::*; | ||
use ark_std::rand::{Rng, RngCore}; | ||
use hotshot_types::{light_client::StateKeyPair, traits::signature_key::BuilderSignatureKey}; | ||
|
||
impl NodeInfoJf { | ||
fn random(rng: &mut impl RngCore) -> Self { | ||
let mut seed = [0u8; 32]; | ||
rng.fill_bytes(&mut seed); | ||
|
||
let (stake_table_key, _) = BLSPubKey::generated_from_seed_indexed(seed, 0); | ||
let state_key_pair = StateKeyPair::generate_from_seed_indexed(seed, 0); | ||
Self { | ||
stake_table_key, | ||
state_ver_key: state_key_pair.ver_key(), | ||
da: rng.gen(), | ||
} | ||
} | ||
} | ||
|
||
#[test] | ||
fn test_node_info_round_trip() { | ||
let mut rng = ark_std::rand::thread_rng(); | ||
for _ in 0..20 { | ||
let jf = NodeInfoJf::random(&mut rng); | ||
let sol: NodeInfo = jf.clone().into(); | ||
let jf2: NodeInfoJf = sol.into(); | ||
assert_eq!(jf2, jf); | ||
} | ||
} | ||
} |
Oops, something went wrong.