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

feat: make signing eip 712 compliant #916

Merged
merged 29 commits into from
Sep 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
bcd6663
feat: first version
NicolasRampoldi Aug 29, 2024
206cabf
feat: working implementation
NicolasRampoldi Sep 3, 2024
d333b62
docs: comment
NicolasRampoldi Sep 3, 2024
d48a42e
Merge branch 'main' into feat-make-signing-eip-712-compliant
NicolasRampoldi Sep 3, 2024
b2b512a
chore: anvil state
NicolasRampoldi Sep 3, 2024
88d0248
fix: linter
NicolasRampoldi Sep 3, 2024
3e671e9
forge install: openzeppelin-contracts
NicolasRampoldi Sep 3, 2024
a96d73e
chore: install openzepellin and bump solidity version
NicolasRampoldi Sep 3, 2024
9db71b0
fix: lower gap
NicolasRampoldi Sep 3, 2024
f259a96
refactor: hasher update
NicolasRampoldi Sep 3, 2024
801f690
Merge branch 'main' into feat-make-signing-eip-712-compliant
NicolasRampoldi Sep 4, 2024
b82987e
chore: merge
NicolasRampoldi Sep 4, 2024
83d8d77
chore: bump up protocol version
NicolasRampoldi Sep 5, 2024
aab9476
feat: add chain param to submit and submit_multiple
NicolasRampoldi Sep 5, 2024
e8be0d7
refactor: add errors
NicolasRampoldi Sep 5, 2024
76ed477
forge install: openzeppelin-contracts-upgradeable
NicolasRampoldi Sep 6, 2024
7772e3b
Merge branch 'main' into feat-make-signing-eip-712-compliant
NicolasRampoldi Sep 6, 2024
2d9e71f
chore: anvil state
NicolasRampoldi Sep 6, 2024
4ffd79c
feat: add setHashType in contract
NicolasRampoldi Sep 6, 2024
ab2b391
Merge branch 'main' into feat-make-signing-eip-712-compliant
NicolasRampoldi Sep 6, 2024
6610aca
fix: deployment script
NicolasRampoldi Sep 6, 2024
516c00d
feat: spearate BatcherPaymentServiceStorage
uri-99 Sep 6, 2024
71f8359
feat: include the storage in the contract
uri-99 Sep 6, 2024
a679cdd
fix: deploy batche
uri-99 Sep 6, 2024
ae1f63e
refactor: change make target to upgrade_batcher_payments_add_type_hash
uri-99 Sep 6, 2024
1bf323d
fix: remove 0x from nonced verification data type hash
NicolasRampoldi Sep 9, 2024
1bd4352
chore: new line
NicolasRampoldi Sep 9, 2024
7672899
refactor: nonce from bytes32 to uint256
NicolasRampoldi Sep 9, 2024
8d619bb
chore: anvil state
NicolasRampoldi Sep 9, 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
6 changes: 6 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,9 @@
[submodule "examples/validating-public-input/contracts/lib/forge-std"]
path = examples/validating-public-input/contracts/lib/forge-std
url = https://github.com/foundry-rs/forge-std
[submodule "contracts/lib/openzeppelin-contracts"]
path = contracts/lib/openzeppelin-contracts
url = https://github.com/OpenZeppelin/openzeppelin-contracts
[submodule "contracts/lib/openzeppelin-contracts-upgradeable"]
path = contracts/lib/openzeppelin-contracts-upgradeable
url = https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable
12 changes: 12 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ anvil_upgrade_aligned_contracts:
@echo "Upgrading Aligned Contracts..."
. contracts/scripts/anvil/upgrade_aligned_contracts.sh

anvil_upgrade_batcher_payment_service:
@echo "Upgrading BatcherPayments contract..."
. contracts/scripts/anvil/upgrade_batcher_payment_service.sh

anvil_upgrade_registry_coordinator:
@echo "Upgrading Registry Coordinator Contracts..."
. contracts/scripts/anvil/upgrade_registry_coordinator.sh
Expand All @@ -75,6 +79,10 @@ anvil_upgrade_add_aggregator:
@echo "Adding Aggregator to Aligned Contracts..."
. contracts/scripts/anvil/upgrade_add_aggregator_to_service_manager.sh

anvil_add_type_hash_to_batcher_payment_service:
@echo "Adding Type Hash to Batcher Payment Service..."
. contracts/scripts/anvil/upgrade_add_type_hash_to_batcher_payment_service.sh

lint_contracts:
@cd contracts && npm run lint:sol

Expand Down Expand Up @@ -437,6 +445,10 @@ upgrade_add_aggregator: ## Add Aggregator to Aligned Contracts
@echo "Adding Aggregator to Aligned Contracts..."
@. contracts/scripts/.env && . contracts/scripts/upgrade_add_aggregator_to_service_manager.sh

upgrade_batcher_payments_add_type_hash: ## Add Type Hash to Batcher Payment Service
@echo "Adding Type Hash to Batcher Payment Service..."
@. contracts/scripts/.env && . contracts/scripts/upgrade_add_type_hash_to_batcher_payment_service.sh

deploy_verify_batch_inclusion_caller:
@echo "Deploying VerifyBatchInclusionCaller contract..."
@. examples/verify/.env && . examples/verify/scripts/deploy_verify_batch_inclusion_caller.sh
Expand Down
33 changes: 15 additions & 18 deletions batcher/aligned-batcher/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,11 +103,7 @@ impl BatchState {
self.batch_queue
.iter()
.map(|(entry, _)| entry)
.find(|entry| {
entry.sender == sender
&& U256::from_big_endian(entry.nonced_verification_data.nonce.as_slice())
== nonce
})
.find(|entry| entry.sender == sender && entry.nonced_verification_data.nonce == nonce)
}

/// Checks if the entry is valid
Expand All @@ -122,8 +118,7 @@ impl BatchState {
replacement_entry: BatchQueueEntry,
) -> Option<ValidityResponseMessage> {
let replacement_max_fee = replacement_entry.nonced_verification_data.max_fee;
let nonce =
U256::from_big_endian(replacement_entry.nonced_verification_data.nonce.as_slice());
let nonce = replacement_entry.nonced_verification_data.nonce;
let sender = replacement_entry.sender;

debug!(
Expand All @@ -134,7 +129,7 @@ impl BatchState {
// it is a valid entry only if there is no entry with the same sender, lower nonce and a lower fee
let is_valid = !self.batch_queue.iter().any(|(entry, _)| {
entry.sender == sender
&& U256::from_big_endian(entry.nonced_verification_data.nonce.as_slice()) < nonce
&& entry.nonced_verification_data.nonce < nonce
&& entry.nonced_verification_data.max_fee < replacement_max_fee
});

Expand Down Expand Up @@ -439,7 +434,7 @@ impl Batcher {

info!(
"Received message with nonce: {}",
U256::from_big_endian(client_msg.verification_data.nonce.as_slice())
client_msg.verification_data.nonce
);

if client_msg.verification_data.chain_id != self.chain_id {
Expand Down Expand Up @@ -495,7 +490,7 @@ impl Batcher {
}

// Nonce and max fee verification
let nonce = U256::from_big_endian(nonced_verification_data.nonce.as_slice());
let nonce = nonced_verification_data.nonce;
let max_fee = nonced_verification_data.max_fee;

if max_fee < U256::from(MIN_FEE_PER_PROOF) {
Expand Down Expand Up @@ -644,7 +639,7 @@ impl Batcher {
return false;
}

let nonce = U256::from_big_endian(&nonced_verification_data.nonce);
let nonce = nonced_verification_data.nonce;

batch_state.user_nonces.insert(addr, nonce + U256::one());
batch_state.user_min_fee.insert(addr, max_fee);
Expand Down Expand Up @@ -678,7 +673,7 @@ impl Batcher {
expected_user_nonce: U256,
) -> bool {
let replacement_max_fee = nonced_verification_data.max_fee;
let nonce = U256::from_big_endian(&nonced_verification_data.nonce);
let nonce = nonced_verification_data.nonce;

let mut replacement_entry = match batch_state.get_entry(addr, nonce) {
Some(entry) => {
Expand Down Expand Up @@ -761,7 +756,7 @@ impl Batcher {
info!("Adding verification data to batch...");

let max_fee = verification_data.max_fee;
let nonce = U256::from_big_endian(verification_data.nonce.as_slice());
let nonce = verification_data.nonce;

batch_state.batch_queue.push(
BatchQueueEntry::new(
Expand Down Expand Up @@ -1254,24 +1249,26 @@ impl Batcher {
}
};

debug!("non paying nonce: {:?}", nonpaying_nonce);
info!("non paying nonce: {:?}", nonpaying_nonce);

let nonce_value = *nonpaying_nonce;

let mut nonce_bytes = [0u8; 32];
nonpaying_nonce.to_big_endian(&mut nonce_bytes);
*nonpaying_nonce += U256::one();

NoncedVerificationData::new(
client_msg.verification_data.verification_data.clone(),
nonce_bytes,
nonce_value,
DEFAULT_MAX_FEE_PER_PROOF.into(), // 13_000 gas per proof * 100 gwei gas price (upper bound)
self.chain_id,
self.payment_service.address(),
)
};

let client_msg = ClientMessage::new(
nonced_verification_data.clone(),
non_paying_config.replacement.clone(),
);
)
.await;

let batch_state = self.batch_state.lock().await;
self.clone()
Expand Down
2 changes: 1 addition & 1 deletion batcher/aligned-sdk/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ version = "0.1.0"
edition = "2021"

[dependencies]
ethers = { tag = "v2.0.15-fix-reconnections", features = ["ws", "rustls"], git = "https://github.com/yetanotherco/ethers-rs.git" }
ethers = { tag = "v2.0.15-fix-reconnections", features = ["ws", "rustls", "eip712"], git = "https://github.com/yetanotherco/ethers-rs.git" }
log = { version = "0.4.21"}
serde_json = "1.0.117"
tokio-tungstenite = { version = "0.23.1", features = ["native-tls"] }
Expand Down
11 changes: 5 additions & 6 deletions batcher/aligned-sdk/src/communication/messaging.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use ethers::signers::Signer;
use ethers::types::Address;
use futures_util::{stream::SplitStream, SinkExt, StreamExt};
use log::{debug, error, info};
use std::sync::Arc;
Expand Down Expand Up @@ -30,6 +31,7 @@ pub type ResponseStream = TryFilter<
pub async fn send_messages(
response_stream: Arc<Mutex<ResponseStream>>,
ws_write: Arc<Mutex<SplitSink<WebSocketStream<MaybeTlsStream<TcpStream>>, Message>>>,
payment_service_addr: Address,
verification_data: &[VerificationData],
max_fees: &[U256],
wallet: Wallet<SigningKey>,
Expand All @@ -39,25 +41,22 @@ pub async fn send_messages(

let mut ws_write = ws_write.lock().await;

let mut nonce_bytes = [0u8; 32];

let mut response_stream = response_stream.lock().await;

let chain_id = U256::from(wallet.chain_id());

for (idx, verification_data) in verification_data.iter().enumerate() {
nonce.to_big_endian(&mut nonce_bytes);

let verification_data = NoncedVerificationData::new(
verification_data.clone(),
nonce_bytes,
nonce,
max_fees[idx],
chain_id,
payment_service_addr,
);

nonce += U256::one();

let msg = ClientMessage::new(verification_data.clone(), wallet.clone());
let msg = ClientMessage::new(verification_data.clone(), wallet.clone()).await;
let msg_bin = cbor_serialize(&msg).map_err(SubmitError::SerializationError)?;
ws_write
.send(Message::Binary(msg_bin.clone()))
Expand Down
2 changes: 1 addition & 1 deletion batcher/aligned-sdk/src/communication/protocol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::core::{errors::SubmitError, types::ResponseMessage};

use super::serialization::cbor_deserialize;

pub const EXPECTED_PROTOCOL_VERSION: u16 = 3;
pub const EXPECTED_PROTOCOL_VERSION: u16 = 4;

pub async fn check_protocol_version(
ws_read: &mut SplitStream<WebSocketStream<MaybeTlsStream<TcpStream>>>,
Expand Down
31 changes: 31 additions & 0 deletions batcher/aligned-sdk/src/core/errors.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use core::fmt;
use ethers::providers::ProviderError;
use ethers::signers::WalletError;
use ethers::types::transaction::eip712::Eip712Error;
use ethers::types::SignatureError;
use std::io;
use std::path::PathBuf;
use tokio_tungstenite::tungstenite::protocol::CloseFrame;
Expand Down Expand Up @@ -233,3 +235,32 @@ impl fmt::Display for ChainIdError {
}
}
}

#[derive(Debug)]
pub enum VerifySignatureError {
RecoverTypedDataError(SignatureError),
EncodeError(Eip712Error),
}

impl From<SignatureError> for VerifySignatureError {
fn from(e: SignatureError) -> Self {
VerifySignatureError::RecoverTypedDataError(e)
}
}

impl From<Eip712Error> for VerifySignatureError {
fn from(e: Eip712Error) -> Self {
VerifySignatureError::EncodeError(e)
}
}

impl fmt::Display for VerifySignatureError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
VerifySignatureError::RecoverTypedDataError(e) => {
write!(f, "Recover typed data error: {}", e)
}
VerifySignatureError::EncodeError(e) => write!(f, "Encode error: {}", e),
}
}
}
Loading
Loading