Skip to content

Commit

Permalink
wip: use evm IO
Browse files Browse the repository at this point in the history
  • Loading branch information
dndll committed Feb 12, 2024
1 parent 94a4442 commit 4b3015f
Show file tree
Hide file tree
Showing 4 changed files with 152 additions and 13 deletions.
3 changes: 1 addition & 2 deletions Cargo.lock

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

40 changes: 32 additions & 8 deletions circuits/plonky2x/src/circuits/verify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ use serde::{Deserialize, Serialize};
use crate::{
builder::Verify,
hint::{FetchProofInputs, ProofInputVariable},
variables::{CryptoHashVariable, EncodeInner, HeaderVariable, TransactionOrReceiptIdVariable},
variables::{
byte_from_bool, CryptoHashVariable, EncodeInner, HeaderVariable,
TransactionOrReceiptIdVariable,
},
};

#[derive(CircuitVariable, Debug, Clone)]
Expand All @@ -34,10 +37,13 @@ impl<const N: usize, const B: usize, const NETWORK: usize> Circuit
<<L as PlonkParameters<D>>::Config as GenericConfig<D>>::Hasher:
AlgebraicHasher<<L as PlonkParameters<D>>::Field>,
{
let trusted_head = b.read::<HeaderVariable>();
let ids = b.read::<ArrayVariable<TransactionOrReceiptIdVariable, N>>();
let trusted_head = b.evm_read::<HeaderVariable>();
let mut ids = vec![];
for _ in 0..N {
ids.push(b.evm_read::<TransactionOrReceiptIdVariable>());
}

let proofs = FetchProofInputs::<N>(NETWORK.into()).fetch(b, &trusted_head, &ids.data);
let proofs = FetchProofInputs::<N>(NETWORK.into()).fetch(b, &trusted_head, &ids);

// TODO: write some outputs here for each ID
let output = b.mapreduce_dynamic::<_, _, _, Self, B, _, _>(
Expand Down Expand Up @@ -66,7 +72,12 @@ impl<const N: usize, const B: usize, const NETWORK: usize> Circuit
},
|_, l, r, b| MergeProofHint::<N>.merge(b, &l, &r),
);
b.write::<ProofMapReduceVariable<N>>(output);
for r in output.data {
b.evm_write::<CryptoHashVariable>(r.id);
let _true = b._true();
let passed = byte_from_bool(b, r.result);
b.evm_write::<ByteVariable>(passed);
}
}

fn register_generators<L: PlonkParameters<D>, const D: usize>(registry: &mut HintRegistry<L, D>)
Expand All @@ -90,6 +101,8 @@ impl<const N: usize, const B: usize, const NETWORK: usize> Circuit
B,
D,
>>(dynamic_id);

// TODO: register_watch_generator!
}
}

Expand Down Expand Up @@ -215,11 +228,22 @@ mod beefy_tests {
VerifyCircuit::<AMT, BATCH, NETWORK>::define(b);
};
let writer = |input: &mut PI| {
input.write::<HeaderVariable>(header.into());
input.write::<ArrayVariable<TransactionOrReceiptIdVariable, AMT>>(txs.into());
input.evm_write::<HeaderVariable>(header.into());
for tx in txs {
input.evm_write::<TransactionOrReceiptIdVariable>(tx.into());
}
};
let assertions = |mut output: PO| {
println!("{:#?}", output.read::<ProofMapReduceVariable<AMT>>());
let mut results = vec![];
for _ in 0..AMT {
let id = output.evm_read::<CryptoHashVariable>();
let result = output.evm_read::<ByteVariable>();
results.push(ProofVerificationResultVariableValue::<GoldilocksField> {
id,
result: result != 0,
});
}
println!("{:#?}", results);
};
builder_suite(define, writer, assertions);
}
Expand Down
1 change: 0 additions & 1 deletion circuits/plonky2x/src/test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ pub fn builder_suite<F, WriteInputs, Assertions>(
.unwrap();
}
PublicInput::Elements(elements) => {
println!("Writing input.elements.json");
let req = ProofRequest::<DefaultParameters, 2>::Elements(
plonky2x::backend::function::ProofRequestBase {
release_id: "todo".to_string(),
Expand Down
121 changes: 119 additions & 2 deletions circuits/plonky2x/src/variables.rs
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,11 @@ impl<F: RichField> From<ValidatorStake> for ValidatorStakeVariableValue<F> {
}

pub(crate) fn pad_account_id(account_id: &AccountId) -> [u8; AccountId::MAX_LEN] {
let mut account_id = account_id.as_str().as_bytes().to_vec();
let account_id = account_id.as_str().as_bytes().to_vec();
pad_account_bytes(account_id)
}

pub(crate) fn pad_account_bytes(mut account_id: Vec<u8>) -> [u8; AccountId::MAX_LEN] {
account_id.resize(AccountId::MAX_LEN, ACCOUNT_ID_PADDING_BYTE);
account_id.try_into().expect("invalid account bytes")
}
Expand Down Expand Up @@ -658,12 +662,125 @@ impl<F: RichField> From<GetProof> for TransactionOrReceiptIdVariableValue<F> {
}
}

pub fn byte_from_bool<L: PlonkParameters<D>, const D: usize>(
b: &mut CircuitBuilder<L, D>,
bool: BoolVariable,
) -> ByteVariable {
let zero = b._false();
let mut bits = [zero; 8];
bits[7] = bool.into();

ByteVariable::from_be_bits(bits)
}

impl EvmVariable for TransactionOrReceiptIdVariable {
fn encode<L: PlonkParameters<D>, const D: usize>(
&self,
builder: &mut CircuitBuilder<L, D>,
) -> Vec<ByteVariable> {
let mut bytes = vec![];
bytes.extend_from_slice(&byte_from_bool(builder, self.is_transaction).encode(builder));
bytes.extend_from_slice(&self.id.encode(builder));
bytes.extend_from_slice(&self.account.encode(builder));
bytes
}

fn decode<L: PlonkParameters<D>, const D: usize>(
builder: &mut CircuitBuilder<L, D>,
bytes: &[ByteVariable],
) -> Self {
let zero = builder.zero::<ByteVariable>();
let is_receipt = builder.is_equal(bytes[0], zero);
let is_transaction = builder.not(is_receipt);
Self {
is_transaction,
id: CryptoHashVariable::decode(builder, &bytes[1..33]),
account: AccountIdVariable::decode(builder, &bytes[33..33 + AccountId::MAX_LEN]),
}
}
fn encode_value<F: RichField>(value: Self::ValueType<F>) -> Vec<u8> {
let mut bytes = vec![value.is_transaction as u8];
bytes.extend_from_slice(&CryptoHashVariable::encode_value::<F>(value.id));
bytes.extend_from_slice(&AccountIdVariable::encode_value::<F>(pad_account_bytes(
value.account.to_vec(),
)));
bytes
}
fn decode_value<F: RichField>(bytes: &[u8]) -> Self::ValueType<F> {
assert_eq!(bytes.len(), 1 + 32 + AccountId::MAX_LEN);

Self::ValueType {
is_transaction: bytes[0] != 0,
id: CryptoHashVariable::decode_value::<F>(&bytes[1..33]),
account: AccountIdVariable::decode_value::<F>(&bytes[33..33 + AccountId::MAX_LEN]),
}
}
}
#[cfg(test)]
mod tests {
use std::str::FromStr;

use ::test_utils::CryptoHash;
use near_light_client_protocol::prelude::Itertools;
use near_primitives::types::TransactionOrReceiptId;
use serial_test::serial;
use test_utils::fixture;

use super::*;
use crate::{
test_utils::{builder_suite, testnet_state, B, NETWORK, PI, PO},
variables::TransactionOrReceiptIdVariableValue,
};

#[test]
fn test_serialise_tx() {
fn tx(hash: &str, sender: &str) -> TransactionOrReceiptId {
TransactionOrReceiptId::Transaction {
transaction_hash: CryptoHash::from_str(hash).unwrap(),
sender_id: sender.parse().unwrap(),
}
}
fn rx(hash: &str, receiver: &str) -> TransactionOrReceiptId {
TransactionOrReceiptId::Receipt {
receipt_id: CryptoHash::from_str(hash).unwrap(),
receiver_id: receiver.parse().unwrap(),
}
}

// TODO: test way more of these, pull the last 64 transactions and prove them
let txs: Vec<TransactionOrReceiptIdVariableValue<GoldilocksField>> = vec![
tx(
"3z2zqitrXNYQs19z5tK5a4bZSxdx7baqzGFUyGAkW9Mz",
"zavodil.testnet",
),
rx(
"9cVuYLKYF26QevZ315RLb9ArU3gbcgPc4LDRJfZQyZHo",
"priceoracle.testnet",
),
]
.into_iter()
.map(Into::into)
.collect_vec();

let define = |b: &mut B| {
let receipt = b.evm_read::<TransactionOrReceiptIdVariable>();
b.evm_write::<TransactionOrReceiptIdVariable>(receipt);
let tx = b.evm_read::<TransactionOrReceiptIdVariable>();
b.evm_write::<TransactionOrReceiptIdVariable>(tx);
};
let writer = |input: &mut PI| {
input.evm_write::<TransactionOrReceiptIdVariable>(txs[0].clone().into());
input.evm_write::<TransactionOrReceiptIdVariable>(txs[1].clone().into());
};
let assertions = |mut output: PO| {
println!("{:#?}", output.evm_read::<TransactionOrReceiptIdVariable>());
println!("{:#?}", output.evm_read::<TransactionOrReceiptIdVariable>());
};
builder_suite(define, writer, assertions);
}

#[test]
fn tests() {
fn test_encode_transaction() {
todo!()
}
}

0 comments on commit 4b3015f

Please sign in to comment.