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

Implement the transaction pool #255

Closed
wants to merge 28 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
7d908d8
Start implementation of the transaction pool
sebastiencs Mar 3, 2024
d5dcba0
Implement new caching logic in `to_all_verifiable`
sebastiencs Mar 5, 2024
b1457cc
Verify commands in the tx pool
sebastiencs Mar 6, 2024
fa1aedb
Compute weight of commands
sebastiencs Mar 6, 2024
7f8d318
wip
sebastiencs Mar 6, 2024
ed4a48f
Implement time-related types/methods for tx pool
sebastiencs Mar 7, 2024
28ad681
Implement `IndexedPool::add_from_backtrack`
sebastiencs Mar 7, 2024
471dfa6
Implement part of `IndexedPool::add_from_gossip_exn`
sebastiencs Mar 7, 2024
9e057db
Implement rest of `add_from_gossip_exn`
sebastiencs Mar 9, 2024
2da771c
Implement `IndexedPool::revalidate`
sebastiencs Mar 9, 2024
2569c35
Make `group_by_zkapp_command_rev` generic, to use it in tx pool
sebastiencs Mar 9, 2024
304f50b
Implement `ZkappCommand::valid_size`
sebastiencs Mar 9, 2024
90369d3
Fix after rebase
sebastiencs Mar 19, 2024
8c8098e
Fix new warning "reduntant import"
sebastiencs Mar 19, 2024
d2bc3aa
Add type `AccountIdOrderable` to make `AccountId` comparable
sebastiencs Mar 20, 2024
d9d3725
Implement `TransactionPool::get_rebroadcastable`
sebastiencs Mar 20, 2024
ac4ab8e
Use shared pointer for `BlakeHash`
sebastiencs Mar 21, 2024
196ce0f
Integrate the pool in the state machine
sebastiencs Mar 26, 2024
c7ac527
Fix after rebase
sebastiencs Mar 26, 2024
fb236d6
Split `TransactionPoolAction::BestTipChanged` in 2 actions
sebastiencs Mar 27, 2024
b8b6cbd
Split other actions in 2 actions
sebastiencs Mar 28, 2024
44f2979
Implement `TransactionPool::transactions`
sebastiencs Apr 2, 2024
dd0dd02
Add `snark/user_command_verify` Service
sebastiencs Apr 11, 2024
8027cd0
Fix usage of `SnarkUserCommandVerifyService`
sebastiencs Apr 11, 2024
c0bfa27
Fix after rebase
sebastiencs Apr 12, 2024
4bca9b5
Serialize `verifiable::UserCommand`
sebastiencs Apr 16, 2024
df6cb14
Fix after rebase
sebastiencs May 6, 2024
8e88dcf
Remove `TransactionPoolLedgerService`
sebastiencs May 9, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
14 changes: 14 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion core/src/block/genesis.rs
Expand Up @@ -145,7 +145,7 @@ fn consensus_state(
let is_genesis = if negative_one { 0 } else { 1 };
let (blockchain_length, global_slot_since_genesis) = match CONSTRAINT_CONSTANTS.fork.as_ref() {
None => (is_genesis, 0),
Some(fork) => (fork.previous_length + is_genesis, fork.previous_global_slot),
Some(fork) => (fork.previous_length + is_genesis, fork.genesis_slot),
};

v2::ConsensusProofOfStakeDataConsensusStateValueStableV2 {
Expand Down
8 changes: 4 additions & 4 deletions core/src/constants.rs
Expand Up @@ -29,7 +29,7 @@ pub const CONSTRAINT_CONSTANTS: ConstraintConstants = ConstraintConstants {
pub struct ForkConstants {
pub previous_state_hash: Fp,
pub previous_length: u32,
pub previous_global_slot: u32,
pub genesis_slot: u32,
}

#[derive(Clone, Debug)]
Expand All @@ -49,15 +49,15 @@ pub struct ConstraintConstants {
pub struct ForkConstantsUnversioned {
previous_state_hash: bigint::BigInt,
previous_length: number::Int32,
previous_global_slot: number::Int32,
genesis_slot: number::Int32,
}

impl From<&ForkConstants> for ForkConstantsUnversioned {
fn from(fork_constants: &ForkConstants) -> Self {
Self {
previous_state_hash: fork_constants.previous_state_hash.into(),
previous_length: fork_constants.previous_length.into(),
previous_global_slot: fork_constants.previous_global_slot.into(),
genesis_slot: fork_constants.genesis_slot.into(),
}
}
}
Expand Down Expand Up @@ -125,6 +125,6 @@ pub fn grace_period_end(constants: &v2::MinaBaseProtocolConstantsCheckedValueSta
};
match CONSTRAINT_CONSTANTS.fork.as_ref() {
None => slots,
Some(fork) => slots + fork.previous_global_slot,
Some(fork) => slots + fork.genesis_slot,
}
}
5 changes: 1 addition & 4 deletions core/src/snark/snark.rs
@@ -1,9 +1,6 @@
use std::sync::Arc;

use mina_p2p_messages::binprot::{
self,
macros::{BinProtRead, BinProtWrite},
};
use mina_p2p_messages::binprot::macros::{BinProtRead, BinProtWrite};
use mina_p2p_messages::v2::{
CurrencyFeeStableV1, MinaBaseFeeWithProverStableV1,
MinaStateBlockchainStateValueStableV2LedgerProofStatement, MinaStateSnarkedLedgerStateStableV2,
Expand Down
5 changes: 1 addition & 4 deletions core/src/snark/snark_info.rs
@@ -1,7 +1,4 @@
use mina_p2p_messages::binprot::{
self,
macros::{BinProtRead, BinProtWrite},
};
use mina_p2p_messages::binprot::macros::{BinProtRead, BinProtWrite};
use mina_p2p_messages::v2::{CurrencyFeeStableV1, NonZeroCurvePoint};
use serde::{Deserialize, Serialize};

Expand Down
5 changes: 1 addition & 4 deletions core/src/snark/snark_job_commitment.rs
@@ -1,7 +1,4 @@
use mina_p2p_messages::binprot::{
self,
macros::{BinProtRead, BinProtWrite},
};
use mina_p2p_messages::binprot::macros::{BinProtRead, BinProtWrite};
use mina_p2p_messages::v2::{CurrencyFeeStableV1, NonZeroCurvePoint};
use redux::Timestamp;
use serde::{Deserialize, Serialize};
Expand Down
5 changes: 1 addition & 4 deletions core/src/snark/snark_job_id.rs
@@ -1,9 +1,6 @@
use std::str::FromStr;

use mina_p2p_messages::binprot::{
self,
macros::{BinProtRead, BinProtWrite},
};
use mina_p2p_messages::binprot::macros::{BinProtRead, BinProtWrite};
use mina_p2p_messages::v2::{
LedgerHash, MinaStateBlockchainStateValueStableV2LedgerProofStatementSource,
TransactionSnarkWorkTStableV2Proofs,
Expand Down
1 change: 1 addition & 0 deletions ledger/Cargo.toml
Expand Up @@ -70,6 +70,7 @@ crc32fast = "1"
chrono = "0.4"
serde_with = "3.6.1"
anyhow = "1.0.75"
fraction = { version = "=0.15.1", default-features = false, features = ["with-serde-support"] }

[target.'cfg(target_family = "wasm")'.dependencies]
getrandom = { version = "0.2", features = ["js"] }
Expand Down
156 changes: 137 additions & 19 deletions ledger/src/account/account.rs
Expand Up @@ -2,7 +2,10 @@ use std::{fmt::Write, io::Cursor, str::FromStr};

use ark_ff::{BigInteger256, One, UniformRand, Zero};
use mina_hasher::Fp;
use mina_p2p_messages::binprot::{BinProtRead, BinProtWrite};
use mina_p2p_messages::{
binprot::{BinProtRead, BinProtWrite},
v2,
};
use mina_signer::CompressedPubKey;
use rand::{prelude::ThreadRng, seq::SliceRandom, Rng};
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -386,7 +389,7 @@ impl ToFieldElements<Fp> for ProofVerified {
}
}

#[derive(Clone, Debug, PartialEq, Eq)]
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct VerificationKey {
pub max_proofs_verified: ProofVerified,
pub actual_wrap_domain_size: ProofVerified,
Expand Down Expand Up @@ -750,39 +753,126 @@ impl ZkAppAccount {
}
}

/// An `AccountId` implementing `Ord` & `PartialOrd`, reproducing OCaml ordering.
///
/// We compare them using `BigInteger256`, not `Fp`.
/// This is a different type than `AccountId` because we want to keep the
/// `BigInteger256` values around, without re-computing them every time
/// `<Self as PartialOrd>::partial_cmp` is called.
///
/// So far this is used only when `AccountId` are used as keys in BTreeMap, in zkapp application.
#[derive(Clone, Eq)]
pub struct AccountId {
pub public_key: CompressedPubKey,
pub token_id: TokenId,
pub struct AccountIdOrderable {
// Keep the values as `BigInteger256`. This avoid re-computing them
// every time `<Self as PartialOrd>::partial_cmp` is called
bigint_public_key_x: BigInteger256,
bigint_public_key_is_odd: bool,
bigint_token_id: BigInteger256,
// We keep the original values, to convert back into `AccountId` without computing
public_key: CompressedPubKey,
token_id: TokenId,
}

impl Ord for AccountId {
impl PartialEq for AccountIdOrderable {
fn eq(&self, other: &Self) -> bool {
let Self {
bigint_public_key_x: self_x,
bigint_public_key_is_odd: self_is_odd,
bigint_token_id: self_token_id,
public_key: _,
token_id: _,
} = self;
let Self {
bigint_public_key_x: other_x,
bigint_public_key_is_odd: other_is_odd,
bigint_token_id: other_token_id,
public_key: _,
token_id: _,
} = other;

self_x == other_x && self_is_odd == other_is_odd && self_token_id == other_token_id
}
}
impl Ord for AccountIdOrderable {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.partial_cmp(other).unwrap_or(std::cmp::Ordering::Equal)
}
}

impl PartialOrd for AccountId {
impl PartialOrd for AccountIdOrderable {
/// Ignore `Self::public_key` and `Self::token_id`
/// We only use their bigint representations
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
let self_pk: BigInteger256 = self.public_key.x.into();
let other_pk: BigInteger256 = other.public_key.x.into();
match self_pk.partial_cmp(&other_pk) {
Some(core::cmp::Ordering::Equal) | None => {}
let Self {
bigint_public_key_x: self_x,
bigint_public_key_is_odd: self_is_odd,
bigint_token_id: self_token_id,
public_key: _,
token_id: _,
} = self;

let Self {
bigint_public_key_x: other_x,
bigint_public_key_is_odd: other_is_odd,
bigint_token_id: other_token_id,
public_key: _,
token_id: _,
} = other;

match self_x.partial_cmp(other_x) {
None | Some(core::cmp::Ordering::Equal) => {}
ord => return ord,
}

match self.public_key.is_odd.partial_cmp(&other.public_key.is_odd) {
Some(core::cmp::Ordering::Equal) | None => {}
match self_is_odd.partial_cmp(other_is_odd) {
None | Some(core::cmp::Ordering::Equal) => {}
ord => return ord,
}
self_token_id.partial_cmp(other_token_id)
}
}

impl From<AccountId> for AccountIdOrderable {
fn from(value: AccountId) -> Self {
let AccountId {
public_key,
token_id,
} = value;
let CompressedPubKey { x, is_odd } = &public_key;

Self {
bigint_public_key_x: (*x).into(),
bigint_public_key_is_odd: *is_odd,
bigint_token_id: token_id.0.into(),
public_key,
token_id,
}
}
}

let self_token_id: BigInteger256 = self.token_id.0.into();
let other_token_id: BigInteger256 = other.token_id.0.into();
impl From<AccountIdOrderable> for AccountId {
fn from(value: AccountIdOrderable) -> Self {
let AccountIdOrderable {
bigint_public_key_x: _,
bigint_public_key_is_odd: _,
bigint_token_id: _,
public_key,
token_id,
} = value;

self_token_id.partial_cmp(&other_token_id)
Self {
public_key,
token_id,
}
}
}

#[derive(Clone, Eq, PartialOrd, Ord, serde::Serialize, serde::Deserialize)]
#[serde(into = "v2::MinaBaseAccountIdStableV2")]
#[serde(from = "v2::MinaBaseAccountIdStableV2")]
pub struct AccountId {
pub public_key: CompressedPubKey,
pub token_id: TokenId,
}

impl ToInputs for AccountId {
fn to_inputs(&self, inputs: &mut Inputs) {
let Self {
Expand Down Expand Up @@ -1014,7 +1104,9 @@ pub struct PermsConst {
}

// https://github.com/MinaProtocol/mina/blob/1765ba6bdfd7c454e5ae836c49979fa076de1bea/src/lib/mina_base/account.ml#L368
#[derive(Clone, Debug, PartialEq, Eq)]
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(into = "v2::MinaBaseAccountBinableArgStableV2")]
#[serde(from = "v2::MinaBaseAccountBinableArgStableV2")]
pub struct Account {
pub public_key: CompressedPubKey, // Public_key.Compressed.t
pub token_id: TokenId, // Token_id.t
Expand Down Expand Up @@ -1178,6 +1270,32 @@ impl Account {
zero_min_balance.neg()
}

pub fn liquid_balance_at_slot(&self, global_slot: Slot) -> Balance {
match self.timing {
Timing::Untimed => self.balance,
Timing::Timed {
initial_minimum_balance,
cliff_time,
cliff_amount,
vesting_period,
vesting_increment,
} => self
.balance
.sub_amount(
account_min_balance_at_slot(
global_slot,
cliff_time,
cliff_amount,
vesting_period,
vesting_increment,
initial_minimum_balance,
)
.to_amount(),
)
.unwrap(),
}
}

/// https://github.com/MinaProtocol/mina/blob/2ff0292b637684ce0372e7b8e23ec85404dc5091/src/lib/mina_base/account.ml#L794
pub fn has_permission_to(&self, control: ControlTag, to: PermissionTo) -> bool {
match to {
Expand Down