11//! VRF bootstrap and account derivation.
22//!
33//! This module handles:
4- //! - Deriving VRF accounts and keys from source accounts
4+ //! - Deriving VRF accounts and keys from a fixed VRF secret
55//! - Deploying VRF account and consumer contracts via RPC
66//! - Setting up VRF public keys on deployed accounts
77//!
@@ -34,6 +34,8 @@ use url::Url;
3434pub const VRF_ACCOUNT_SALT : u64 = 0x54321 ;
3535/// Salt used for deploying VRF consumer contracts via UDC.
3636pub const VRF_CONSUMER_SALT : u64 = 0x67890 ;
37+ /// Hardcoded VRF secret key used to derive VRF account credentials.
38+ pub const VRF_HARDCODED_SECRET_KEY : u64 = 0x111 ;
3739/// Default timeout for bootstrap operations.
3840pub const BOOTSTRAP_TIMEOUT : Duration = Duration :: from_secs ( 10 ) ;
3941
@@ -63,7 +65,7 @@ pub struct VrfBootstrapConfig {
6365/// Result of VRF bootstrap operations.
6466#[ derive( Debug , Clone ) ]
6567pub struct VrfBootstrapResult {
66- /// The VRF secret key (derived from source account) .
68+ /// The VRF secret key used by the VRF sidecar .
6769 pub secret_key : u64 ,
6870 pub vrf_account_address : ContractAddress ,
6971 pub vrf_account_private_key : Felt ,
@@ -74,8 +76,7 @@ pub struct VrfBootstrapResult {
7476/// Derived VRF account information.
7577#[ derive( Debug , Clone ) ]
7678pub struct VrfDerivedAccounts {
77- pub source_address : ContractAddress ,
78- pub source_private_key : Felt ,
79+ pub vrf_account_private_key : Felt ,
7980 pub vrf_account_address : ContractAddress ,
8081 pub vrf_public_key_x : Felt ,
8182 pub vrf_public_key_y : Felt ,
@@ -86,22 +87,19 @@ pub struct VrfDerivedAccounts {
8687// Bootstrap Functions
8788// ============================================================================
8889
89- /// Derive VRF accounts from source account .
90+ /// Derive VRF accounts from the hardcoded VRF secret key .
9091///
9192/// This computes the deterministic VRF account address and VRF key pair
92- /// from the source account's private key.
93- pub fn derive_vrf_accounts (
94- bootstrapper_address : ContractAddress ,
95- bootstrapper_private_key : Felt ,
96- ) -> Result < VrfDerivedAccounts > {
97- // vrf-server expects a u64 secret, so derive one from the account key.
98- let secret_key = vrf_secret_key_from_account_key ( bootstrapper_private_key) ;
93+ /// from a fixed VRF private key.
94+ pub fn get_vrf_account ( ) -> Result < VrfDerivedAccounts > {
95+ let secret_key = VRF_HARDCODED_SECRET_KEY ;
96+ let vrf_account_private_key = Felt :: from ( secret_key) ;
9997 let public_key = generate_public_key ( scalar_from_felt ( secret_key. into ( ) ) ) ;
10098 let vrf_public_key_x = felt_from_field ( public_key. x ) ?;
10199 let vrf_public_key_y = felt_from_field ( public_key. y ) ?;
102100
103101 let account_public_key =
104- SigningKey :: from_secret_scalar ( bootstrapper_private_key ) . verifying_key ( ) . scalar ( ) ;
102+ SigningKey :: from_secret_scalar ( vrf_account_private_key ) . verifying_key ( ) . scalar ( ) ;
105103
106104 let vrf_account_class_hash = CartridgeVrfAccount :: HASH ;
107105 // When using UDC with unique=0 (non-unique deployment), the deployer_address
@@ -115,8 +113,7 @@ pub fn derive_vrf_accounts(
115113 . into ( ) ;
116114
117115 Ok ( VrfDerivedAccounts {
118- source_address : bootstrapper_address,
119- source_private_key : bootstrapper_private_key,
116+ vrf_account_private_key,
120117 vrf_account_address,
121118 vrf_public_key_x,
122119 vrf_public_key_y,
@@ -135,11 +132,10 @@ pub async fn bootstrap_vrf(
135132 let chain_id_felt = provider. chain_id ( ) . await . context ( "failed to get chain ID from node" ) ?;
136133 let chain_id = ChainId :: Id ( chain_id_felt) ;
137134
138- let derived =
139- derive_vrf_accounts ( bootstrapper_account_address, bootstrapper_account_private_key) ?;
135+ let derived = get_vrf_account ( ) ?;
140136 let vrf_account_address = derived. vrf_account_address ;
141137 let account_public_key =
142- SigningKey :: from_secret_scalar ( bootstrapper_account_private_key ) . verifying_key ( ) . scalar ( ) ;
138+ SigningKey :: from_secret_scalar ( derived . vrf_account_private_key ) . verifying_key ( ) . scalar ( ) ;
143139
144140 let vrf_account_class_hash = CartridgeVrfAccount :: HASH ;
145141
@@ -205,7 +201,7 @@ pub async fn bootstrap_vrf(
205201 // Set VRF public key on the deployed account
206202 // Create account for the VRF account to call set_vrf_public_key on itself
207203 let vrf_signer =
208- LocalWallet :: from ( SigningKey :: from_secret_scalar ( bootstrapper_account_private_key ) ) ;
204+ LocalWallet :: from ( SigningKey :: from_secret_scalar ( derived . vrf_account_private_key ) ) ;
209205 let mut vrf_account = SingleOwnerAccount :: new (
210206 provider. clone ( ) ,
211207 vrf_signer,
@@ -258,8 +254,7 @@ pub async fn bootstrap_vrf(
258254 vrf_consumer_address,
259255 chain_id,
260256 vrf_account_address,
261- // right now, we take the bootstrapper account private key as the vrf account's private key
262- vrf_account_private_key : bootstrapper_account_private_key,
257+ vrf_account_private_key : derived. vrf_account_private_key ,
263258 } )
264259}
265260
@@ -350,37 +345,29 @@ fn scalar_from_felt(value: Felt) -> ScalarField {
350345 ScalarField :: from_be_bytes_mod_order ( & bytes)
351346}
352347
353- /// Derive a u64 VRF secret key from an account private key.
354- ///
355- /// Uses the low 64 bits of the account key.
356- pub fn vrf_secret_key_from_account_key ( value : Felt ) -> u64 {
357- let bytes = value. to_bytes_be ( ) ;
358- let mut tail = [ 0_u8 ; 8 ] ;
359- tail. copy_from_slice ( & bytes[ 24 ..] ) ;
360- u64:: from_be_bytes ( tail)
361- }
362-
363348fn felt_from_field < T : std:: fmt:: Display > ( value : T ) -> Result < Felt > {
364349 let decimal = value. to_string ( ) ;
365350 Felt :: from_dec_str ( & decimal) . map_err ( |err| anyhow ! ( "invalid field value: {err}" ) )
366351}
367352
368353#[ cfg( test) ]
369354mod tests {
370- use katana_primitives:: Felt ;
371-
372- use super :: vrf_secret_key_from_account_key;
355+ use super :: { get_vrf_account, VRF_HARDCODED_SECRET_KEY } ;
373356
374357 #[ test]
375- fn vrf_secret_key_uses_low_64_bits ( ) {
376- let mut bytes = [ 0_u8 ; 32 ] ;
377- for ( i , byte ) in bytes . iter_mut ( ) . enumerate ( ) {
378- * byte = i as u8 ;
379- }
358+ fn derive_vrf_accounts_uses_hardcoded_secret_key ( ) {
359+ let derived = get_vrf_account ( ) . expect ( "must derive" ) ;
360+ assert_eq ! ( derived . secret_key , VRF_HARDCODED_SECRET_KEY ) ;
361+ assert_eq ! ( derived . vrf_account_private_key , VRF_HARDCODED_SECRET_KEY . into ( ) ) ;
362+ }
380363
381- let felt = Felt :: from_bytes_be ( & bytes) ;
382- let secret = vrf_secret_key_from_account_key ( felt) ;
364+ #[ test]
365+ fn derive_vrf_accounts_is_deterministic ( ) {
366+ let first = get_vrf_account ( ) . expect ( "first derivation" ) ;
367+ let second = get_vrf_account ( ) . expect ( "second derivation" ) ;
383368
384- assert_eq ! ( secret, 0x18191a1b1c1d1e1f ) ;
369+ assert_eq ! ( first. vrf_account_address, second. vrf_account_address) ;
370+ assert_eq ! ( first. vrf_public_key_x, second. vrf_public_key_x) ;
371+ assert_eq ! ( first. vrf_public_key_y, second. vrf_public_key_y) ;
385372 }
386373}
0 commit comments