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(opt): assembly shplemini #9218

Draft
wants to merge 7 commits into
base: md/opt-sol-honk
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
55 changes: 0 additions & 55 deletions barretenberg/sol/src/honk/Transcript.sol
Original file line number Diff line number Diff line change
Expand Up @@ -223,61 +223,6 @@ library TranscriptLib {
// logFr("rho", rho);
}

function generateGeminiRChallenge(Honk.Proof memory proof, Fr prevChallenge)
internal
pure
returns (Fr geminiR, Fr nextPreviousChallenge)
{
uint256[(CONST_PROOF_SIZE_LOG_N - 1) * 4 + 1] memory gR;
gR[0] = Fr.unwrap(prevChallenge);

for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N - 1; i++) {
gR[1 + i * 4] = proof.geminiFoldUnivariates[i].x_0;
gR[2 + i * 4] = proof.geminiFoldUnivariates[i].x_1;
gR[3 + i * 4] = proof.geminiFoldUnivariates[i].y_0;
gR[4 + i * 4] = proof.geminiFoldUnivariates[i].y_1;
}

nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(gR)));
Fr unused;
(geminiR, unused) = splitChallenge(nextPreviousChallenge);
}

function generateShplonkNuChallenge(Honk.Proof memory proof, Fr prevChallenge)
internal
pure
returns (Fr shplonkNu, Fr nextPreviousChallenge)
{
uint256[(CONST_PROOF_SIZE_LOG_N) + 1] memory shplonkNuChallengeElements;
shplonkNuChallengeElements[0] = Fr.unwrap(prevChallenge);

for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N; i++) {
shplonkNuChallengeElements[i + 1] = Fr.unwrap(proof.geminiAEvaluations[i]);
}

nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(shplonkNuChallengeElements)));
Fr unused;
(shplonkNu, unused) = splitChallenge(nextPreviousChallenge);
}

function generateShplonkZChallenge(Honk.Proof memory proof, Fr prevChallenge)
internal
pure
returns (Fr shplonkZ, Fr nextPreviousChallenge)
{
uint256[5] memory shplonkZChallengeElements;
shplonkZChallengeElements[0] = Fr.unwrap(prevChallenge);

shplonkZChallengeElements[1] = proof.shplonkQ.x_0;
shplonkZChallengeElements[2] = proof.shplonkQ.x_1;
shplonkZChallengeElements[3] = proof.shplonkQ.y_0;
shplonkZChallengeElements[4] = proof.shplonkQ.y_1;

nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(shplonkZChallengeElements)));
Fr unused;
(shplonkZ, unused) = splitChallenge(nextPreviousChallenge);
}

function generateGeminiRChallenge(Honk.Proof memory proof, Fr prevChallenge)
internal
pure
Expand Down
5 changes: 2 additions & 3 deletions barretenberg/sol/src/honk/instance/Add2Honk.sol
Original file line number Diff line number Diff line change
Expand Up @@ -435,7 +435,6 @@ contract Add2HonkVerifier is IVerifier {
a_0_pos = batchedEvalAccumulator;
}

// This implementation is the same as above with different constants
function batchMul(
Honk.G1Point[NUMBER_OF_ENTITIES + CONST_PROOF_SIZE_LOG_N + 2] memory base,
Fr[NUMBER_OF_ENTITIES + CONST_PROOF_SIZE_LOG_N + 2] memory scalars
Expand Down Expand Up @@ -480,14 +479,14 @@ contract Add2HonkVerifier is IVerifier {
bytes memory input = abi.encodePacked(
rhs.x,
rhs.y,
// Fixed G1 point
// G2 [1]
uint256(0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2),
uint256(0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed),
uint256(0x090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b),
uint256(0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa),
lhs.x,
lhs.y,
// G1 point from VK
// G2 [x]
uint256(0x260e01b251f6f1c7e7ff4e580791dee8ea51d87a358e038b4efe30fac09383c1),
uint256(0x0118c4d5b837bcc2bc89b5b398b5974e9f5944073b32078b7e231fec938883b0),
uint256(0x04fc6369f7110fe3d25156c1bb9a72859cf2a04641f99ba4ee413c80da6a5fe4),
Expand Down
77 changes: 60 additions & 17 deletions barretenberg/sol/src/honk/instance/BlakeHonk.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {
CONST_PROOF_SIZE_LOG_N
} from "../HonkTypes.sol";

import {ecMul, ecAdd, ecSub, negateInplace, convertProofPoint, logFr, logG1} from "../utils.sol";
import {ecMul, ecAdd, ecSub, negateInplace, convertProofPoint} from "../utils.sol";

// Field arithmetic libraries - prevent littering the code with modmul / addmul
import {MODULUS as P, MINUS_ONE, Fr, FrLib} from "../Fr.sol";
Expand All @@ -37,7 +37,12 @@ error ShpleminiFailed();
contract BlakeHonkVerifier is IVerifier {
using FrLib for Fr;

function verify(bytes calldata proof, bytes32[] calldata publicInputs) public view override returns (bool) {
function verify(bytes calldata proof, bytes32[] calldata publicInputs)
public
// view WORKTODO: bring back
override
returns (bool)
{
Honk.VerificationKey memory vk = loadVerificationKey();
Honk.Proof memory p = TranscriptLib.loadProof(proof);

Expand All @@ -55,8 +60,6 @@ contract BlakeHonkVerifier is IVerifier {
// Sumcheck
bool sumcheckVerified = verifySumcheck(p, t);
if (!sumcheckVerified) revert SumcheckFailed();
uint256 gasAfter = gasleft();
console.log("Gas used until sumcheck: ", gasBefore - gasAfter);

bool shpleminiVerified = verifyShplemini(p, vk, t);
if (!shpleminiVerified) revert ShpleminiFailed();
Expand Down Expand Up @@ -200,6 +203,9 @@ contract BlakeHonkVerifier is IVerifier {
struct ShpleminiIntermediates {
Fr unshiftedScalar;
Fr shiftedScalar;
// Negative versions of the values above - these are used in hot loops, so storing is preferred
Fr unshiftedScalarNeg;
Fr shiftedScalarNeg;
// Scalar to be multiplied by [1]₁
Fr constantTermAccumulator;
// Linear combination of multilinear (sumcheck) evaluations and powers of rho
Expand All @@ -210,8 +216,10 @@ contract BlakeHonkVerifier is IVerifier {

function verifyShplemini(Honk.Proof memory proof, Honk.VerificationKey memory vk, Transcript memory tp)
internal
view
returns (bool verified)
returns (
// WORKTODO: reinstantiate view func
bool verified
)
{
ShpleminiIntermediates memory mem; // stack

Expand Down Expand Up @@ -262,14 +270,19 @@ contract BlakeHonkVerifier is IVerifier {
mem.batchingChallenge = Fr.wrap(1);
mem.batchedEvaluation = Fr.wrap(0);

// TODO: move into mem above - same with one below!!!!
// mem.unshiftedScalarNeg = mem.unshiftedScalar.neg();
for (uint256 i = 1; i <= NUMBER_UNSHIFTED; ++i) {
scalars[i] = mem.unshiftedScalar.neg() * mem.batchingChallenge;
// scalars[i] = mem.unshiftedScalarNeg * mem.batchingChallenge;
mem.batchedEvaluation = mem.batchedEvaluation + (proof.sumcheckEvaluations[i - 1] * mem.batchingChallenge);
mem.batchingChallenge = mem.batchingChallenge * tp.rho;
}
// g commitments are accumulated at r
// mem.shiftedScalarNeg = mem.unshiftedScalar.neg();
for (uint256 i = NUMBER_UNSHIFTED + 1; i <= NUMBER_OF_ENTITIES; ++i) {
scalars[i] = mem.shiftedScalar.neg() * mem.batchingChallenge;
// scalars[i] = mem.shiftedScalarNeg * mem.batchingChallenge;
mem.batchedEvaluation = mem.batchedEvaluation + (proof.sumcheckEvaluations[i - 1] * mem.batchingChallenge);
mem.batchingChallenge = mem.batchingChallenge * tp.rho;
}
Expand Down Expand Up @@ -401,11 +414,17 @@ contract BlakeHonkVerifier is IVerifier {
Fr[CONST_PROOF_SIZE_LOG_N] memory eval_challenge_powers
) internal view returns (Fr[CONST_PROOF_SIZE_LOG_N + 1] memory inverse_vanishing_evals) {
Fr eval_challenge = tp.shplonkZ;

inverse_vanishing_evals[0] = (eval_challenge - eval_challenge_powers[0]).invert();

Fr temp = eval_challenge - eval_challenge_powers[0];

for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N; ++i) {
Fr round_inverted_denominator = Fr.wrap(0);
if (i <= LOG_N + 1) {
// TOOD(md): remove both lines
temp = (eval_challenge + eval_challenge_powers[i]);

round_inverted_denominator = (eval_challenge + eval_challenge_powers[i]).invert();
}
inverse_vanishing_evals[i + 1] = round_inverted_denominator;
Expand All @@ -418,22 +437,19 @@ contract BlakeHonkVerifier is IVerifier {
Fr[CONST_PROOF_SIZE_LOG_N] memory geminiEvaluations,
Fr[CONST_PROOF_SIZE_LOG_N] memory geminiEvalChallengePowers
) internal view returns (Fr a_0_pos) {
for (uint256 i = CONST_PROOF_SIZE_LOG_N; i > 0; --i) {
// OTP: this does not need to iterate more than LOG_N times
// There is no benefit - the current code is CONST_PROOF_SIZE_LOG_N
for (uint256 i = LOG_N; i > 0; --i) {
Fr challengePower = geminiEvalChallengePowers[i - 1];
Fr u = tp.sumCheckUChallenges[i - 1];
Fr evalNeg = geminiEvaluations[i - 1];

Fr batchedEvalRoundAcc = (
batchedEvalAccumulator = (
(challengePower * batchedEvalAccumulator * Fr.wrap(2))
- evalNeg * (challengePower * (Fr.wrap(1) - u) - u)
);
// Divide by the denominator
batchedEvalRoundAcc = batchedEvalRoundAcc * (challengePower * (Fr.wrap(1) - u) + u).invert();

bool is_dummy_round = (i > LOG_N);
if (!is_dummy_round) {
batchedEvalAccumulator = batchedEvalRoundAcc;
}
batchedEvalAccumulator = batchedEvalAccumulator * (challengePower * (Fr.wrap(1) - u) + u).invert();
}

a_0_pos = batchedEvalAccumulator;
Expand All @@ -443,7 +459,7 @@ contract BlakeHonkVerifier is IVerifier {
function batchMul(
Honk.G1Point[NUMBER_OF_ENTITIES + CONST_PROOF_SIZE_LOG_N + 2] memory base,
Fr[NUMBER_OF_ENTITIES + CONST_PROOF_SIZE_LOG_N + 2] memory scalars
) internal view returns (Honk.G1Point memory result) {
) internal returns (Honk.G1Point memory result) {
uint256 limit = NUMBER_OF_ENTITIES + CONST_PROOF_SIZE_LOG_N + 2;
assembly {
let success := 0x01
Expand All @@ -456,8 +472,24 @@ contract BlakeHonkVerifier is IVerifier {
mstore(add(free, 0x60), mload(add(0x20, mload(base))))
// Add scalar
mstore(add(free, 0x80), mload(scalars))

// Inputs
log4(
0x00,
0x00,
0x20,
// The point
mload(mload(base)),
mload(add(0x20, mload(base))),
// The scalar
mload(scalars)
)

success := and(success, staticcall(gas(), 7, add(free, 0x40), 0x60, free, 0x40))

// TEMPLOG: Initial accumualtor
log3(0x00, 0x00, 0x00, mload(free), mload(add(free, 0x20)))

let count := 0x01
for {} lt(count, limit) { count := add(count, 1) } {
// Get loop offsets
Expand All @@ -469,6 +501,17 @@ contract BlakeHonkVerifier is IVerifier {
// Add scalar
mstore(add(free, 0x80), mload(scalar_base))

log4(
0x00,
0x00,
count,
// The point
mload(add(free, 0x40)),
mload(add(free, 0x60)),
// The scalar
mload(add(free, 0x80))
)

success := and(success, staticcall(gas(), 7, add(free, 0x40), 0x60, add(free, 0x40), 0x40))
// accumulator = accumulator + accumulator_2
success := and(success, staticcall(gas(), 6, free, 0x80, free, 0x40))
Expand All @@ -484,14 +527,14 @@ contract BlakeHonkVerifier is IVerifier {
bytes memory input = abi.encodePacked(
rhs.x,
rhs.y,
// Fixed G1 point
// G2 [1]
uint256(0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2),
uint256(0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed),
uint256(0x090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b),
uint256(0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa),
lhs.x,
lhs.y,
// G1 point from VK
// G2 [x]
uint256(0x260e01b251f6f1c7e7ff4e580791dee8ea51d87a358e038b4efe30fac09383c1),
uint256(0x0118c4d5b837bcc2bc89b5b398b5974e9f5944073b32078b7e231fec938883b0),
uint256(0x04fc6369f7110fe3d25156c1bb9a72859cf2a04641f99ba4ee413c80da6a5fe4),
Expand Down
4 changes: 2 additions & 2 deletions barretenberg/sol/src/honk/instance/EcdsaHonk.sol
Original file line number Diff line number Diff line change
Expand Up @@ -483,14 +483,14 @@ contract EcdsaHonkVerifier is IVerifier {
bytes memory input = abi.encodePacked(
rhs.x,
rhs.y,
// Fixed G1 point
// G2 [1]
uint256(0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2),
uint256(0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed),
uint256(0x090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b),
uint256(0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa),
lhs.x,
lhs.y,
// G1 point from VK
// G2 [x]
uint256(0x260e01b251f6f1c7e7ff4e580791dee8ea51d87a358e038b4efe30fac09383c1),
uint256(0x0118c4d5b837bcc2bc89b5b398b5974e9f5944073b32078b7e231fec938883b0),
uint256(0x04fc6369f7110fe3d25156c1bb9a72859cf2a04641f99ba4ee413c80da6a5fe4),
Expand Down
Loading
Loading