use super::{ProofPlan, VerifiableQueryResult};
use crate::{
base::{
commitment::{Commitment, CommittableColumn},
database::{owned_table_utility::*, OwnedColumn, OwnedTable, TableRef, TestAccessor},
scalar::Scalar,
},
proof_primitive::inner_product::curve_25519_scalar::Curve25519Scalar,
};
use blitzar::proof::InnerProductProof;
use curve25519_dalek::{ristretto::RistrettoPoint, traits::Identity};
use num_traits::One;
use serde::Serialize;
pub fn exercise_verification(
res: &VerifiableQueryResult<InnerProductProof>,
expr: &(impl ProofPlan + Serialize),
accessor: &impl TestAccessor<RistrettoPoint>,
table_ref: &TableRef,
) {
res.clone()
.verify(expr, accessor, &(), &[])
.expect("Verification failed");
let mut res_p = res.clone();
res_p.result = tampered_table(&res.result);
assert!(res_p.verify(expr, accessor, &(), &[]).is_err());
for i in 0..res.proof.pcs_proof_evaluations.final_round.len() {
let mut res_p = res.clone();
res_p.proof.pcs_proof_evaluations.final_round[i] += Curve25519Scalar::one();
assert!(res_p.verify(expr, accessor, &(), &[]).is_err());
}
let commit_p = RistrettoPoint::compute_commitments(
&[CommittableColumn::BigInt(&[
353_453_245_i64,
93_402_346_i64,
])],
0_usize,
&(),
)[0];
for i in 0..res.proof.final_round_message.round_commitments.len() {
let mut res_p = res.clone();
res_p.proof.final_round_message.round_commitments[i] = commit_p;
assert!(res_p.verify(expr, accessor, &(), &[]).is_err());
}
if accessor.get_length(table_ref) > 1
|| res
.proof
.final_round_message
.round_commitments
.iter()
.any(|&c| c != Identity::identity())
{
let offset_generators = accessor.get_offset(table_ref);
let mut fake_accessor = accessor.clone();
fake_accessor.update_offset(table_ref, offset_generators);
res.clone().verify(expr, &fake_accessor, &(), &[]).unwrap();
fake_accessor.update_offset(table_ref, offset_generators + 1);
assert!(res.clone().verify(expr, &fake_accessor, &(), &[]).is_err());
}
}
fn tampered_table<S: Scalar>(table: &OwnedTable<S>) -> OwnedTable<S> {
if table.num_columns() == 0 {
owned_table([bigint("col", [0; 0])])
} else if table.num_rows() == 0 {
append_single_row_to_table(table)
} else {
tamper_first_element_of_table(table)
}
}
fn append_single_row_to_table<S: Scalar>(table: &OwnedTable<S>) -> OwnedTable<S> {
OwnedTable::try_from_iter(
table
.inner_table()
.iter()
.map(|(name, col)| (name.clone(), append_single_row_to_column(col))),
)
.expect("Failed to create table")
}
fn append_single_row_to_column<S: Scalar>(column: &OwnedColumn<S>) -> OwnedColumn<S> {
let mut column = column.clone();
match &mut column {
OwnedColumn::Boolean(col) => col.push(false),
OwnedColumn::Uint8(col) => col.push(0),
OwnedColumn::TinyInt(col) => col.push(0),
OwnedColumn::SmallInt(col) => col.push(0),
OwnedColumn::Int(col) => col.push(0),
OwnedColumn::BigInt(col) | OwnedColumn::TimestampTZ(_, _, col) => col.push(0),
OwnedColumn::VarChar(col) => col.push(String::new()),
OwnedColumn::VarBinary(col) => col.push(vec![0u8]),
OwnedColumn::Int128(col) => col.push(0),
OwnedColumn::Decimal75(_, _, col) | OwnedColumn::Scalar(col) => col.push(S::ZERO),
}
column
}
fn tamper_first_element_of_table<S: Scalar>(table: &OwnedTable<S>) -> OwnedTable<S> {
OwnedTable::try_from_iter(
table
.inner_table()
.iter()
.enumerate()
.map(|(i, (name, col))| {
(
name.clone(),
if i == 0 {
tamper_first_row_of_column(col)
} else {
col.clone()
},
)
}),
)
.expect("Failed to create table")
}
pub fn tamper_first_row_of_column<S: Scalar>(column: &OwnedColumn<S>) -> OwnedColumn<S> {
let mut column = column.clone();
match &mut column {
OwnedColumn::Boolean(col) => col[0] ^= true,
OwnedColumn::Uint8(col) => col[0] = col[0].wrapping_add(1),
OwnedColumn::TinyInt(col) => col[0] = col[0].wrapping_add(1),
OwnedColumn::SmallInt(col) => col[0] = col[0].wrapping_add(1),
OwnedColumn::Int(col) => col[0] = col[0].wrapping_add(1),
OwnedColumn::BigInt(col) | OwnedColumn::TimestampTZ(_, _, col) => {
col[0] = col[0].wrapping_add(1);
}
OwnedColumn::VarChar(col) => col[0].push('1'),
OwnedColumn::VarBinary(col) => col[0].push(1u8),
OwnedColumn::Int128(col) => col[0] = col[0].wrapping_add(1),
OwnedColumn::Decimal75(_, _, col) | OwnedColumn::Scalar(col) => col[0] += S::ONE,
}
column
}