Skip to content

Commit 98a836b

Browse files
committed
wip
1 parent 719e481 commit 98a836b

File tree

10 files changed

+109
-83
lines changed

10 files changed

+109
-83
lines changed

crates/cartridge/src/lib.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ pub mod vrf;
66
pub use client::Client;
77
pub use vrf::{
88
bootstrap_vrf, get_vrf_account, resolve_executable, wait_for_http_ok, InfoResponse,
9-
RequestContext, SignedOutsideExecution, VrfBootstrap, VrfBootstrapConfig, VrfBootstrapResult,
10-
VrfClient, VrfClientError, VrfDerivedAccounts, VrfOutsideExecution, VrfService,
11-
VrfServiceConfig, VrfServiceProcess, VRF_ACCOUNT_SALT, VRF_CONSUMER_SALT,
9+
RequestContext, SignedOutsideExecution, VrfAccountCredentials, VrfBootstrap,
10+
VrfBootstrapConfig, VrfBootstrapResult, VrfClient, VrfClientError, VrfOutsideExecution,
11+
VrfService, VrfServiceConfig, VrfServiceProcess, VRF_ACCOUNT_SALT, VRF_CONSUMER_SALT,
1212
VRF_HARDCODED_SECRET_KEY, VRF_SERVER_PORT,
1313
};
1414

crates/cartridge/src/vrf/bootstrap.rs

Lines changed: 88 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,19 @@
77
//!
88
//! This module uses the starknet crate's account abstraction for transaction handling.
99
10-
use std::sync::Arc;
1110
use std::time::{Duration, Instant};
1211

1312
use anyhow::{anyhow, Context, Result};
1413
use ark_ff::PrimeField;
15-
use katana_contracts::vrf::CartridgeVrfAccount;
14+
use katana_contracts::vrf::{CartridgeVrfAccount, CartridgeVrfConsumer};
1615
use katana_genesis::constant::DEFAULT_STRK_FEE_TOKEN_ADDRESS;
1716
use katana_primitives::chain::ChainId;
1817
use katana_primitives::class::ClassHash;
1918
use katana_primitives::utils::get_contract_address;
2019
use katana_primitives::{ContractAddress, Felt};
2120
use katana_rpc_types::RpcSierraContractClass;
2221
use stark_vrf::{generate_public_key, ScalarField};
23-
use starknet::accounts::{Account, ExecutionEncoding, SingleOwnerAccount};
22+
use starknet::accounts::{Account, ConnectedAccount, ExecutionEncoding, SingleOwnerAccount};
2423
use starknet::contract::ContractFactory;
2524
use starknet::core::types::{BlockId, BlockTag, Call, FlattenedSierraClass, StarknetError};
2625
use starknet::macros::selector;
@@ -75,9 +74,9 @@ pub struct VrfBootstrapResult {
7574

7675
/// Derived VRF account information.
7776
#[derive(Debug, Clone)]
78-
pub struct VrfDerivedAccounts {
79-
pub vrf_account_private_key: Felt,
80-
pub vrf_account_address: ContractAddress,
77+
pub struct VrfAccountCredentials {
78+
pub private_key: Felt,
79+
pub account_address: ContractAddress,
8180
pub vrf_public_key_x: Felt,
8281
pub vrf_public_key_y: Felt,
8382
pub secret_key: u64,
@@ -91,7 +90,7 @@ pub struct VrfDerivedAccounts {
9190
///
9291
/// This computes the deterministic VRF account address and VRF key pair
9392
/// from a fixed VRF private key.
94-
pub fn get_vrf_account() -> Result<VrfDerivedAccounts> {
93+
pub fn get_vrf_account() -> Result<VrfAccountCredentials> {
9594
let secret_key = VRF_HARDCODED_SECRET_KEY;
9695
let vrf_account_private_key = Felt::from(secret_key);
9796
let public_key = generate_public_key(scalar_from_felt(secret_key.into()));
@@ -108,13 +107,13 @@ pub fn get_vrf_account() -> Result<VrfDerivedAccounts> {
108107
Felt::from(VRF_ACCOUNT_SALT),
109108
vrf_account_class_hash,
110109
&[account_public_key],
111-
Felt::ZERO,
110+
ContractAddress::ZERO,
112111
)
113112
.into();
114113

115-
Ok(VrfDerivedAccounts {
116-
vrf_account_private_key,
117-
vrf_account_address,
114+
Ok(VrfAccountCredentials {
115+
private_key: vrf_account_private_key,
116+
account_address: vrf_account_address,
118117
vrf_public_key_x,
119118
vrf_public_key_y,
120119
secret_key,
@@ -126,18 +125,10 @@ pub async fn bootstrap_vrf(
126125
bootstrapper_account_address: ContractAddress,
127126
bootstrapper_account_private_key: Felt,
128127
) -> Result<VrfBootstrapResult> {
129-
let provider = Arc::new(JsonRpcClient::new(HttpTransport::new(rpc_url.clone())));
128+
let provider = JsonRpcClient::new(HttpTransport::new(rpc_url.clone()));
130129

131130
// Get chain ID from the node
132-
let chain_id_felt = provider.chain_id().await.context("failed to get chain ID from node")?;
133-
let chain_id = ChainId::Id(chain_id_felt);
134-
135-
let derived = get_vrf_account()?;
136-
let vrf_account_address = derived.vrf_account_address;
137-
let account_public_key =
138-
SigningKey::from_secret_scalar(derived.vrf_account_private_key).verifying_key().scalar();
139-
140-
let vrf_account_class_hash = CartridgeVrfAccount::HASH;
131+
let chain_id = provider.chain_id().await.context("failed to get chain ID from node")?;
141132

142133
// Create the source account for transactions
143134
let signer =
@@ -146,38 +137,61 @@ pub async fn bootstrap_vrf(
146137
provider.clone(),
147138
signer,
148139
bootstrapper_account_address.into(),
149-
chain_id_felt,
140+
chain_id,
150141
ExecutionEncoding::New,
151142
);
152143

153-
if !is_declared(&provider, vrf_account_class_hash).await? {
144+
let vrf_acc_cred = bootstrap_vrf_account(&account).await?;
145+
let vrf_consumer_addr = bootstrap_vrf_consumer(&account, vrf_acc_cred.account_address).await?;
146+
147+
Ok(VrfBootstrapResult {
148+
chain_id: chain_id.into(),
149+
secret_key: vrf_acc_cred.secret_key,
150+
vrf_consumer_address: vrf_consumer_addr,
151+
vrf_account_address: vrf_acc_cred.account_address,
152+
vrf_account_private_key: vrf_acc_cred.private_key,
153+
})
154+
}
155+
156+
async fn bootstrap_vrf_account(
157+
bootstrapper_account: &SingleOwnerAccount<JsonRpcClient<HttpTransport>, LocalWallet>,
158+
) -> Result<VrfAccountCredentials> {
159+
let provider = bootstrapper_account.provider();
160+
161+
let vrf_acc_cred = get_vrf_account()?;
162+
let vrf_account_address = vrf_acc_cred.account_address;
163+
164+
if !is_declared(provider, CartridgeVrfAccount::HASH).await? {
154165
let class = CartridgeVrfAccount::CLASS.clone();
155166
let compiled_hash = CartridgeVrfAccount::CASM_HASH;
156167

157168
let rpc_class = RpcSierraContractClass::from(class.to_sierra().unwrap());
158169
let rpc_class = FlattenedSierraClass::try_from(rpc_class).unwrap();
159170

160-
let result = account
171+
let result = bootstrapper_account
161172
.declare_v3(rpc_class.into(), compiled_hash)
162173
.send()
163174
.await
164175
.expect("fail to declare class");
165176

166-
assert_eq!(result.class_hash, vrf_account_class_hash, "Class hash mismatch");
167-
wait_for_class(&provider, vrf_account_class_hash, BOOTSTRAP_TIMEOUT).await?;
177+
assert_eq!(result.class_hash, CartridgeVrfAccount::HASH, "Class hash mismatch");
178+
wait_for_class(provider, CartridgeVrfAccount::HASH, BOOTSTRAP_TIMEOUT).await?;
168179
}
169180

170181
// Deploy VRF account if not already deployed
171-
if !is_deployed(&provider, vrf_account_address).await? {
182+
if !is_deployed(provider, vrf_account_address).await? {
183+
let account_public_key =
184+
SigningKey::from_secret_scalar(vrf_acc_cred.private_key).verifying_key().scalar();
185+
172186
#[allow(deprecated)]
173-
let factory = ContractFactory::new(vrf_account_class_hash, &account);
187+
let factory = ContractFactory::new(CartridgeVrfAccount::HASH, &bootstrapper_account);
174188
factory
175189
.deploy_v3(vec![account_public_key], Felt::from(VRF_ACCOUNT_SALT), false)
176190
.send()
177191
.await
178192
.map_err(|e| anyhow!("failed to deploy VRF account: {e}"))?;
179193

180-
wait_for_contract(&provider, vrf_account_address, BOOTSTRAP_TIMEOUT).await?;
194+
wait_for_contract(provider, vrf_account_address, BOOTSTRAP_TIMEOUT).await?;
181195
}
182196

183197
// Fund VRF account
@@ -189,32 +203,29 @@ pub async fn bootstrap_vrf(
189203
calldata: vec![vrf_account_address.into(), amount, Felt::ZERO],
190204
};
191205

192-
let result = account
206+
let result = bootstrapper_account
193207
.execute_v3(vec![transfer_call])
194208
.send()
195209
.await
196210
.map_err(|e| anyhow!("failed to fund VRF account: {e}"))?;
197211

198-
wait_for_tx(&provider, result.transaction_hash, BOOTSTRAP_TIMEOUT).await?;
212+
wait_for_tx(provider, result.transaction_hash, BOOTSTRAP_TIMEOUT).await?;
199213
}
200214

201215
// Set VRF public key on the deployed account
202216
// Create account for the VRF account to call set_vrf_public_key on itself
203-
let vrf_signer =
204-
LocalWallet::from(SigningKey::from_secret_scalar(derived.vrf_account_private_key));
205-
let mut vrf_account = SingleOwnerAccount::new(
206-
provider.clone(),
207-
vrf_signer,
217+
let vrf_account = SingleOwnerAccount::new(
218+
provider,
219+
LocalWallet::from(SigningKey::from_secret_scalar(vrf_acc_cred.private_key)),
208220
vrf_account_address.into(),
209-
chain_id_felt,
221+
bootstrapper_account.chain_id(),
210222
ExecutionEncoding::New,
211223
);
212-
vrf_account.set_block_id(BlockId::Tag(BlockTag::PreConfirmed));
213224

214225
let set_vrf_key_call = Call {
215226
to: vrf_account_address.into(),
216227
selector: selector!("set_vrf_public_key"),
217-
calldata: vec![derived.vrf_public_key_x, derived.vrf_public_key_y],
228+
calldata: vec![vrf_acc_cred.vrf_public_key_x, vrf_acc_cred.vrf_public_key_y],
218229
};
219230

220231
let result = vrf_account
@@ -223,39 +234,56 @@ pub async fn bootstrap_vrf(
223234
.await
224235
.map_err(|e| anyhow!("failed to set VRF public key: {e}"))?;
225236

226-
wait_for_tx(&provider, result.transaction_hash, BOOTSTRAP_TIMEOUT).await?;
237+
wait_for_tx(provider, result.transaction_hash, BOOTSTRAP_TIMEOUT).await?;
238+
239+
Ok(vrf_acc_cred)
240+
}
241+
242+
async fn bootstrap_vrf_consumer(
243+
bootstrapper_account: &SingleOwnerAccount<JsonRpcClient<HttpTransport>, LocalWallet>,
244+
vrf_account: ContractAddress,
245+
) -> Result<ContractAddress> {
246+
let provider = bootstrapper_account.provider();
227247

228-
// Deploy VRF consumer
229-
let vrf_consumer_class_hash = katana_contracts::vrf::CartridgeVrfConsumer::HASH;
230248
// When using UDC with unique=0 (non-unique deployment), the deployer_address
231249
// used in address computation is 0, not the actual deployer or UDC address.
232250
let vrf_consumer_address = get_contract_address(
233251
Felt::from(VRF_CONSUMER_SALT),
234-
vrf_consumer_class_hash,
235-
&[vrf_account_address.into()],
236-
Felt::ZERO,
237-
)
238-
.into();
252+
CartridgeVrfConsumer::HASH,
253+
&[vrf_account.into()],
254+
ContractAddress::ZERO,
255+
);
256+
257+
if !is_declared(provider, CartridgeVrfConsumer::HASH).await? {
258+
let class = CartridgeVrfConsumer::CLASS.clone();
259+
let compiled_hash = CartridgeVrfConsumer::CASM_HASH;
260+
261+
let rpc_class = RpcSierraContractClass::from(class.to_sierra().unwrap());
262+
let rpc_class = FlattenedSierraClass::try_from(rpc_class).unwrap();
263+
264+
let result = bootstrapper_account
265+
.declare_v3(rpc_class.into(), compiled_hash)
266+
.send()
267+
.await
268+
.expect("fail to declare class");
239269

240-
if !is_deployed(&provider, vrf_consumer_address).await? {
270+
assert_eq!(result.class_hash, CartridgeVrfConsumer::HASH, "Class hash mismatch");
271+
wait_for_class(provider, CartridgeVrfConsumer::HASH, BOOTSTRAP_TIMEOUT).await?;
272+
}
273+
274+
if !is_deployed(provider, vrf_consumer_address.into()).await? {
241275
#[allow(deprecated)]
242-
let factory = ContractFactory::new(vrf_consumer_class_hash, &account);
276+
let factory = ContractFactory::new(CartridgeVrfConsumer::HASH, &bootstrapper_account);
243277
factory
244-
.deploy_v3(vec![vrf_account_address.into()], Felt::from(VRF_CONSUMER_SALT), false)
278+
.deploy_v3(vec![vrf_account.into()], Felt::from(VRF_CONSUMER_SALT), false)
245279
.send()
246280
.await
247281
.map_err(|e| anyhow!("failed to deploy VRF consumer: {e}"))?;
248282

249-
wait_for_contract(&provider, vrf_consumer_address, BOOTSTRAP_TIMEOUT).await?;
283+
wait_for_contract(provider, vrf_consumer_address.into(), BOOTSTRAP_TIMEOUT).await?;
250284
}
251285

252-
Ok(VrfBootstrapResult {
253-
secret_key: derived.secret_key,
254-
vrf_consumer_address,
255-
chain_id,
256-
vrf_account_address,
257-
vrf_account_private_key: derived.vrf_account_private_key,
258-
})
286+
Ok(vrf_consumer_address.into())
259287
}
260288

261289
// ============================================================================
@@ -358,15 +386,15 @@ mod tests {
358386
fn derive_vrf_accounts_uses_hardcoded_secret_key() {
359387
let derived = get_vrf_account().expect("must derive");
360388
assert_eq!(derived.secret_key, VRF_HARDCODED_SECRET_KEY);
361-
assert_eq!(derived.vrf_account_private_key, VRF_HARDCODED_SECRET_KEY.into());
389+
assert_eq!(derived.private_key, VRF_HARDCODED_SECRET_KEY.into());
362390
}
363391

364392
#[test]
365393
fn derive_vrf_accounts_is_deterministic() {
366394
let first = get_vrf_account().expect("first derivation");
367395
let second = get_vrf_account().expect("second derivation");
368396

369-
assert_eq!(first.vrf_account_address, second.vrf_account_address);
397+
assert_eq!(first.account_address, second.account_address);
370398
assert_eq!(first.vrf_public_key_x, second.vrf_public_key_x);
371399
assert_eq!(first.vrf_public_key_y, second.vrf_public_key_y);
372400
}

crates/cartridge/src/vrf/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ use std::time::{Duration, Instant};
1515
use std::{env, io};
1616

1717
pub use bootstrap::{
18-
bootstrap_vrf, get_vrf_account, VrfBootstrap, VrfBootstrapConfig, VrfBootstrapResult,
19-
VrfDerivedAccounts, BOOTSTRAP_TIMEOUT, VRF_ACCOUNT_SALT, VRF_CONSUMER_SALT,
18+
bootstrap_vrf, get_vrf_account, VrfAccountCredentials, VrfBootstrap, VrfBootstrapConfig,
19+
VrfBootstrapResult, BOOTSTRAP_TIMEOUT, VRF_ACCOUNT_SALT, VRF_CONSUMER_SALT,
2020
VRF_HARDCODED_SECRET_KEY,
2121
};
2222
pub use client::*;

crates/chain-spec/src/rollup/utils.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ impl<'c> GenesisTransactionsBuilder<'c> {
132132
const DEPLOY_CONTRACT_SELECTOR: &str = "deploy_contract";
133133
let master_address = *self.master_address.get().expect("must be initialized first");
134134

135-
let contract_address = get_contract_address(salt, class, &ctor_args, Felt::ZERO);
135+
let contract_address = get_contract_address(salt, class, &ctor_args, ContractAddress::ZERO);
136136

137137
let ctor_args_len = Felt::from_usize(ctor_args.len()).unwrap();
138138
let args: Vec<Felt> = iter::once(class) // class_hash
@@ -189,7 +189,8 @@ impl<'c> GenesisTransactionsBuilder<'c> {
189189

190190
let class_hash = account.class_hash;
191191
let calldata = vec![pubkey];
192-
let account_address = get_contract_address(account.salt, class_hash, &calldata, Felt::ZERO);
192+
let account_address =
193+
get_contract_address(account.salt, class_hash, &calldata, ContractAddress::ZERO);
193194

194195
let tx_hash = compute_deploy_account_v1_tx_hash(
195196
account_address,
@@ -231,7 +232,8 @@ impl<'c> GenesisTransactionsBuilder<'c> {
231232
let master_pubkey = self.master_signer.verifying_key().scalar();
232233
let calldata = vec![master_pubkey];
233234
let salt = Felt::ONE;
234-
let master_address = get_contract_address(salt, account_class_hash, &calldata, Felt::ZERO);
235+
let master_address =
236+
get_contract_address(salt, account_class_hash, &calldata, ContractAddress::ZERO);
235237

236238
self.master_address.set(master_address.into()).expect("must be uninitialized");
237239

crates/cli/src/args.rs

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -416,12 +416,6 @@ impl SequencerNodeArgs {
416416
katana_slot_controller::add_vrf_provider_class(&mut chain_spec.genesis);
417417
}
418418

419-
#[cfg(feature = "vrf")]
420-
if self.cartridge.vrf.enabled {
421-
katana_slot_controller::add_vrf_account_class(&mut chain_spec.genesis);
422-
katana_slot_controller::add_vrf_consumer_class(&mut chain_spec.genesis);
423-
}
424-
425419
Ok((Arc::new(ChainSpec::Dev(chain_spec)), None))
426420
}
427421
}
@@ -627,7 +621,7 @@ impl SequencerNodeArgs {
627621
let url = Url::parse(&format!("http://{addr}"))?;
628622

629623
let vrf_account_info = get_vrf_account()?;
630-
let vrf_account_address = vrf_account_info.vrf_account_address;
624+
let vrf_account_address = vrf_account_info.account_address;
631625

632626
Ok(Some(VrfConfig { url, vrf_account: vrf_account_address }))
633627
}

crates/cli/src/sidecar.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::net::SocketAddr;
33
use anyhow::{anyhow, Result};
44
#[cfg(feature = "vrf")]
55
pub use cartridge::vrf::{
6-
get_vrf_account, VrfBootstrapResult, VrfDerivedAccounts, VrfService, VrfServiceConfig,
6+
get_vrf_account, VrfAccountCredentials, VrfBootstrapResult, VrfService, VrfServiceConfig,
77
VrfServiceProcess, VRF_SERVER_PORT,
88
};
99
use katana_chain_spec::ChainSpec;

crates/genesis/src/allocation.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,8 @@ impl GenesisAccount {
219219

220220
/// Returns the address of this account.
221221
pub fn address(&self) -> ContractAddress {
222-
get_contract_address(self.salt, self.class_hash, &[self.public_key], Felt::ZERO).into()
222+
get_contract_address(self.salt, self.class_hash, &[self.public_key], ContractAddress::ZERO)
223+
.into()
223224
}
224225
}
225226

crates/paymaster/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -410,7 +410,7 @@ impl PaymasterService {
410410
Felt::from(FORWARDER_SALT),
411411
avnu_forwarder_class_hash,
412412
&[self.config.relayer_address.into(), self.config.gas_tank_address.into()],
413-
Felt::ZERO,
413+
ContractAddress::ZERO,
414414
)
415415
.into();
416416

0 commit comments

Comments
 (0)