Skip to content

Commit

Permalink
Merge 6b099f4 into e3ea298
Browse files Browse the repository at this point in the history
  • Loading branch information
Maddiaa0 authored Sep 17, 2024
2 parents e3ea298 + 6b099f4 commit f2f5e8a
Show file tree
Hide file tree
Showing 37 changed files with 432 additions and 151 deletions.
5 changes: 2 additions & 3 deletions l1-contracts/src/core/sequencer_selection/Leonidas.sol
Original file line number Diff line number Diff line change
Expand Up @@ -375,16 +375,15 @@ contract Leonidas is Ownable, ILeonidas {
// Validate the attestations
uint256 validAttestations = 0;

bytes32 ethSignedDigest = _digest.toEthSignedMessageHash();

bytes32 digest = _digest.toEthSignedMessageHash();
for (uint256 i = 0; i < _signatures.length; i++) {
SignatureLib.Signature memory signature = _signatures[i];
if (signature.isEmpty) {
continue;
}

// The verification will throw if invalid
signature.verify(committee[i], ethSignedDigest);
signature.verify(committee[i], digest);
validAttestations++;
}

Expand Down
9 changes: 5 additions & 4 deletions l1-contracts/test/sparta/Sparta.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import {DecoderBase} from "../decoders/Base.sol";
import {DataStructures} from "../../src/core/libraries/DataStructures.sol";
import {Constants} from "../../src/core/libraries/ConstantsGen.sol";
import {SignatureLib} from "../../src/core/sequencer_selection/SignatureLib.sol";
import {MessageHashUtils} from "@oz/utils/cryptography/MessageHashUtils.sol";

import {Registry} from "../../src/core/messagebridge/Registry.sol";
import {Inbox} from "../../src/core/messagebridge/Inbox.sol";
Expand All @@ -20,11 +19,12 @@ import {MerkleTestUtil} from "../merkle/TestUtil.sol";
import {PortalERC20} from "../portals/PortalERC20.sol";
import {TxsDecoderHelper} from "../decoders/helpers/TxsDecoderHelper.sol";
import {IFeeJuicePortal} from "../../src/core/interfaces/IFeeJuicePortal.sol";
import {MessageHashUtils} from "@oz/utils/cryptography/MessageHashUtils.sol";

/**
* We are using the same blocks as from Rollup.t.sol.
* The tests in this file is testing the sequencer selection
*/

contract SpartaTest is DecoderBase {
using MessageHashUtils for bytes32;

Expand Down Expand Up @@ -283,8 +283,9 @@ contract SpartaTest is DecoderBase {
returns (SignatureLib.Signature memory)
{
uint256 privateKey = privateKeys[_signer];
bytes32 digestForSig = _digest.toEthSignedMessageHash();
(uint8 v, bytes32 r, bytes32 s) = vm.sign(privateKey, digestForSig);

bytes32 digest = _digest.toEthSignedMessageHash();
(uint8 v, bytes32 r, bytes32 s) = vm.sign(privateKey, digest);

return SignatureLib.Signature({isEmpty: false, v: v, r: r, s: s});
}
Expand Down
3 changes: 2 additions & 1 deletion yarn-project/archiver/src/archiver/eth_log_handlers.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Body, InboxLeaf, L2Block, type ViemSignature } from '@aztec/circuit-types';
import { Body, InboxLeaf, L2Block } from '@aztec/circuit-types';
import { AppendOnlyTreeSnapshot, Header, Proof } from '@aztec/circuits.js';
import { type EthAddress } from '@aztec/foundation/eth-address';
import { type ViemSignature } from '@aztec/foundation/eth-signature';
import { Fr } from '@aztec/foundation/fields';
import { numToUInt32BE } from '@aztec/foundation/serialize';
import { InboxAbi, RollupAbi } from '@aztec/l1-artifacts';
Expand Down
12 changes: 6 additions & 6 deletions yarn-project/circuit-types/src/p2p/block_attestation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,26 @@ import { BlockAttestation } from './block_attestation.js';
import { makeBlockAttestation, randomSigner } from './mocks.js';

describe('Block Attestation serialization / deserialization', () => {
it('Should serialize / deserialize', async () => {
const attestation = await makeBlockAttestation();
it('Should serialize / deserialize', () => {
const attestation = makeBlockAttestation();

const serialized = attestation.toBuffer();
const deserialized = BlockAttestation.fromBuffer(serialized);

expect(deserialized).toEqual(attestation);
});

it('Should serialize / deserialize + recover sender', async () => {
it('Should serialize / deserialize + recover sender', () => {
const account = randomSigner();

const proposal = await makeBlockAttestation(account);
const proposal = makeBlockAttestation(account);
const serialized = proposal.toBuffer();
const deserialized = BlockAttestation.fromBuffer(serialized);

expect(deserialized).toEqual(proposal);

// Recover signature
const sender = await deserialized.getSender();
expect(sender.toChecksumString()).toEqual(account.address);
const sender = deserialized.getSender();
expect(sender).toEqual(account.address);
});
});
19 changes: 7 additions & 12 deletions yarn-project/circuit-types/src/p2p/block_attestation.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import { EthAddress, Header } from '@aztec/circuits.js';
import { type EthAddress, Header } from '@aztec/circuits.js';
import { Buffer32 } from '@aztec/foundation/buffer';
import { recoverAddress } from '@aztec/foundation/crypto';
import { Signature } from '@aztec/foundation/eth-signature';
import { Fr } from '@aztec/foundation/fields';
import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize';

import { recoverMessageAddress } from 'viem';

import { TxHash } from '../tx/tx_hash.js';
import { get0xStringHashedSignaturePayload, getSignaturePayload } from './block_utils.js';
import { getHashedSignaturePayloadEthSignedMessage, getSignaturePayload } from './block_utils.js';
import { Gossipable } from './gossipable.js';
import { Signature } from './signature.js';
import { TopicType, createTopicString } from './topic_type.js';

export class BlockAttestationHash extends Buffer32 {
Expand Down Expand Up @@ -53,16 +52,12 @@ export class BlockAttestation extends Gossipable {
* Lazily evaluate and cache the sender of the attestation
* @returns The sender of the attestation
*/
async getSender() {
getSender() {
if (!this.sender) {
// Recover the sender from the attestation
const hashed = get0xStringHashedSignaturePayload(this.archive, this.txHashes);
const address = await recoverMessageAddress({
message: { raw: hashed },
signature: this.signature.to0xString(),
});
const hashed = getHashedSignaturePayloadEthSignedMessage(this.archive, this.txHashes);
// Cache the sender for later use
this.sender = EthAddress.fromString(address);
this.sender = recoverAddress(hashed, this.signature);
}

return this.sender;
Expand Down
12 changes: 6 additions & 6 deletions yarn-project/circuit-types/src/p2p/block_proposal.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,26 @@ import { BlockProposal } from './block_proposal.js';
import { makeBlockProposal, randomSigner } from './mocks.js';

describe('Block Proposal serialization / deserialization', () => {
it('Should serialize / deserialize', async () => {
const proposal = await makeBlockProposal();
it('Should serialize / deserialize', () => {
const proposal = makeBlockProposal();

const serialized = proposal.toBuffer();
const deserialized = BlockProposal.fromBuffer(serialized);

expect(deserialized).toEqual(proposal);
});

it('Should serialize / deserialize + recover sender', async () => {
it('Should serialize / deserialize + recover sender', () => {
const account = randomSigner();

const proposal = await makeBlockProposal(account);
const proposal = makeBlockProposal(account);
const serialized = proposal.toBuffer();
const deserialized = BlockProposal.fromBuffer(serialized);

expect(deserialized).toEqual(proposal);

// Recover signature
const sender = await deserialized.getSender();
expect(sender.toChecksumString()).toEqual(account.address);
const sender = deserialized.getSender();
expect(sender).toEqual(account.address);
});
});
26 changes: 12 additions & 14 deletions yarn-project/circuit-types/src/p2p/block_proposal.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
import { EthAddress, Header } from '@aztec/circuits.js';
import { type EthAddress, Header } from '@aztec/circuits.js';
import { Buffer32 } from '@aztec/foundation/buffer';
import { recoverAddress } from '@aztec/foundation/crypto';
import { Signature } from '@aztec/foundation/eth-signature';
import { Fr } from '@aztec/foundation/fields';
import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize';

import { recoverMessageAddress } from 'viem';

import { TxHash } from '../tx/tx_hash.js';
import { get0xStringHashedSignaturePayload, getHashedSignaturePayload, getSignaturePayload } from './block_utils.js';
import {
getHashedSignaturePayload,
getHashedSignaturePayloadEthSignedMessage,
getSignaturePayload,
} from './block_utils.js';
import { Gossipable } from './gossipable.js';
import { Signature } from './signature.js';
import { TopicType, createTopicString } from './topic_type.js';

export class BlockProposalHash extends Buffer32 {
Expand Down Expand Up @@ -54,7 +57,7 @@ export class BlockProposal extends Gossipable {
header: Header,
archive: Fr,
txs: TxHash[],
payloadSigner: (payload: Buffer) => Promise<Signature>,
payloadSigner: (payload: Buffer32) => Promise<Signature>,
) {
const hashed = getHashedSignaturePayload(archive, txs);
const sig = await payloadSigner(hashed);
Expand All @@ -65,16 +68,11 @@ export class BlockProposal extends Gossipable {
/**Get Sender
* Lazily evaluate the sender of the proposal; result is cached
*/
async getSender() {
getSender() {
if (!this.sender) {
// performance note(): this signature method requires another hash behind the scenes
const hashed = get0xStringHashedSignaturePayload(this.archive, this.txs);
const address = await recoverMessageAddress({
message: { raw: hashed },
signature: this.signature.to0xString(),
});
const hashed = getHashedSignaturePayloadEthSignedMessage(this.archive, this.txs);
// Cache the sender for later use
this.sender = EthAddress.fromString(address);
this.sender = recoverAddress(hashed, this.signature);
}

return this.sender;
Expand Down
20 changes: 14 additions & 6 deletions yarn-project/circuit-types/src/p2p/block_utils.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { keccak256 as keccak256Buffer } from '@aztec/foundation/crypto';
import { Buffer32 } from '@aztec/foundation/buffer';
import { keccak256, makeEthSignDigest } from '@aztec/foundation/crypto';
import { type Fr } from '@aztec/foundation/fields';

import { encodeAbiParameters, keccak256 as keccak2560xString, parseAbiParameters } from 'viem';
import { encodeAbiParameters, parseAbiParameters } from 'viem';

import { type TxHash } from '../tx/tx_hash.js';

Expand All @@ -25,10 +26,17 @@ export function getSignaturePayload(archive: Fr, txs: TxHash[]) {
* @param txs - The transactions in the block
* @returns The hashed payload for the signature of the block proposal
*/
export function getHashedSignaturePayload(archive: Fr, txs: TxHash[]): Buffer {
return keccak256Buffer(getSignaturePayload(archive, txs));
export function getHashedSignaturePayload(archive: Fr, txs: TxHash[]): Buffer32 {
return Buffer32.fromBuffer(keccak256(getSignaturePayload(archive, txs)));
}

export function get0xStringHashedSignaturePayload(archive: Fr, txs: TxHash[]): `0x${string}` {
return keccak2560xString(getSignaturePayload(archive, txs));
/**
* Get the hashed payload for the signature of the block proposal as an Ethereum signed message EIP-712
* @param archive - The archive of the block
* @param txs - The transactions in the block
* @returns The hashed payload for the signature of the block proposal as an Ethereum signed message
*/
export function getHashedSignaturePayloadEthSignedMessage(archive: Fr, txs: TxHash[]): Buffer32 {
const payload = getHashedSignaturePayload(archive, txs);
return makeEthSignDigest(payload);
}
1 change: 0 additions & 1 deletion yarn-project/circuit-types/src/p2p/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,4 @@ export * from './block_proposal.js';
export * from './interface.js';
export * from './gossipable.js';
export * from './topic_type.js';
export * from './signature.js';
export * from './block_utils.js';
26 changes: 12 additions & 14 deletions yarn-project/circuit-types/src/p2p/mocks.ts
Original file line number Diff line number Diff line change
@@ -1,41 +1,39 @@
import { makeHeader } from '@aztec/circuits.js/testing';
import { Buffer32 } from '@aztec/foundation/buffer';
import { Secp256k1Signer } from '@aztec/foundation/crypto';
import { Fr } from '@aztec/foundation/fields';

import { type PrivateKeyAccount } from 'viem';
import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts';

import { TxHash } from '../tx/tx_hash.js';
import { BlockAttestation } from './block_attestation.js';
import { BlockProposal } from './block_proposal.js';
import { get0xStringHashedSignaturePayload } from './block_utils.js';
import { Signature } from './signature.js';
import { getHashedSignaturePayloadEthSignedMessage } from './block_utils.js';

export const makeBlockProposal = async (signer?: PrivateKeyAccount): Promise<BlockProposal> => {
export const makeBlockProposal = (signer?: Secp256k1Signer): BlockProposal => {
signer = signer || randomSigner();

const blockHeader = makeHeader(1);
const archive = Fr.random();
const txs = [0, 1, 2, 3, 4, 5].map(() => TxHash.random());
const hash = get0xStringHashedSignaturePayload(archive, txs);
const signature = Signature.from0xString(await signer.signMessage({ message: { raw: hash } }));
const hash = getHashedSignaturePayloadEthSignedMessage(archive, txs);
const signature = signer.sign(hash);

return new BlockProposal(blockHeader, archive, txs, signature);
};

// TODO(https://github.com/AztecProtocol/aztec-packages/issues/8028)
export const makeBlockAttestation = async (signer?: PrivateKeyAccount): Promise<BlockAttestation> => {
export const makeBlockAttestation = (signer?: Secp256k1Signer): BlockAttestation => {
signer = signer || randomSigner();

const blockHeader = makeHeader(1);
const archive = Fr.random();
const txs = [0, 1, 2, 3, 4, 5].map(() => TxHash.random());
const hash = get0xStringHashedSignaturePayload(archive, txs);
const signature = Signature.from0xString(await signer.signMessage({ message: { raw: hash } }));
const hash = getHashedSignaturePayloadEthSignedMessage(archive, txs);
const signature = signer.sign(hash);

return new BlockAttestation(blockHeader, archive, txs, signature);
};

export const randomSigner = (): PrivateKeyAccount => {
const privateKey = generatePrivateKey();
return privateKeyToAccount(privateKey);
export const randomSigner = (): Secp256k1Signer => {
const privateKey = Buffer32.random();
return new Secp256k1Signer(privateKey);
};
31 changes: 0 additions & 31 deletions yarn-project/circuit-types/src/p2p/signature.test.ts

This file was deleted.

4 changes: 3 additions & 1 deletion yarn-project/foundation/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"./crypto": "./dest/crypto/index.js",
"./error": "./dest/error/index.js",
"./eth-address": "./dest/eth-address/index.js",
"./eth-signature": "./dest/eth-signature/index.js",
"./queue": "./dest/queue/index.js",
"./fs": "./dest/fs/index.js",
"./buffer": "./dest/buffer/index.js",
Expand Down Expand Up @@ -144,7 +145,8 @@
"prettier": "^2.7.1",
"supertest": "^6.3.3",
"ts-node": "^10.9.1",
"typescript": "^5.0.4"
"typescript": "^5.0.4",
"viem": "^2.7.15"
},
"files": [
"dest",
Expand Down
18 changes: 18 additions & 0 deletions yarn-project/foundation/src/buffer/buffer32.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,25 @@ export class Buffer32 {
* @param str - The TX hash in string format.
* @returns A new Buffer32 object.
*/
public static fromStringUnchecked(str: string): Buffer32 {
return new Buffer32(Buffer.from(str, 'hex'));
}

/**
* Converts a string into a Buffer32 object.
* NOTE: this method includes checks for the 0x prefix and the length of the string.
* if you dont need this checks, use fromStringUnchecked instead.
*
* @param str - The TX hash in string format.
* @returns A new Buffer32 object.
*/
public static fromString(str: string): Buffer32 {
if (str.startsWith('0x')) {
str = str.slice(2);
}
if (str.length !== 64) {
throw new Error(`Expected string to be 64 characters long, but was ${str.length}`);
}
return new Buffer32(Buffer.from(str, 'hex'));
}

Expand Down
1 change: 1 addition & 0 deletions yarn-project/foundation/src/crypto/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export * from './sha256/index.js';
export * from './sha512/index.js';
export * from './pedersen/index.js';
export * from './poseidon/index.js';
export * from './secp256k1-signer/index.js';

/**
* Init the bb singleton. This constructs (if not already) the barretenberg sync api within bb.js itself.
Expand Down
2 changes: 2 additions & 0 deletions yarn-project/foundation/src/crypto/secp256k1-signer/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './secp256k1_signer.js';
export * from './utils.js';
Loading

0 comments on commit f2f5e8a

Please sign in to comment.