Skip to content

Commit 0e6c141

Browse files
authored
Merge pull request #396 from anoma/fix/missing-input-point-validation
fix(low): check if points are on the curve before addition
2 parents a703cf2 + 95f23e1 commit 0e6c141

File tree

7 files changed

+426
-37
lines changed

7 files changed

+426
-37
lines changed

bindings/src/conversion.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use arm_risc0::logic_instance::{AppData, ExpirableBlob};
77
use arm_risc0::logic_proof::LogicVerifierInputs;
88
use arm_risc0::proving_system::encode_seal;
99

10-
use arm_risc0::transaction::{Delta, Transaction};
10+
use arm_risc0::transaction::{Delta as ArmDelta, Transaction};
1111
use arm_risc0::utils::words_to_bytes;
1212

1313
sol!(
@@ -120,8 +120,8 @@ impl From<Action> for ProtocolAdapter::Action {
120120
impl From<Transaction> for ProtocolAdapter::Transaction {
121121
fn from(tx: Transaction) -> Self {
122122
let delta_proof = match &tx.delta_proof {
123-
Delta::Witness(_) => panic!("Unbalanced Transactions cannot be converted"),
124-
Delta::Proof(proof) => proof.to_bytes().to_vec(),
123+
ArmDelta::Witness(_) => panic!("Unbalanced Transactions cannot be converted"),
124+
ArmDelta::Proof(proof) => proof.to_bytes().to_vec(),
125125
};
126126

127127
Self {

contracts/src/ProtocolAdapter.sol

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ contract ProtocolAdapter is
3535
CommitmentTree,
3636
NullifierSet
3737
{
38-
using Delta for Delta.CurvePoint;
38+
using Delta for Delta.Point;
3939
using MerkleTree for bytes32[];
4040
using Logic for Logic.VerifierInput[];
4141
using Logic for Logic.VerifierInput;
@@ -61,7 +61,7 @@ contract ProtocolAdapter is
6161
bytes32[] tags;
6262
bytes32[] logicRefs;
6363
bytes32 latestCommitmentTreeRoot;
64-
Delta.CurvePoint transactionDelta;
64+
Delta.Point transactionDelta;
6565
uint256 tagCounter;
6666
/* Proof aggregation-related variables */
6767
bool isProofAggregated;
@@ -146,7 +146,7 @@ contract ProtocolAdapter is
146146
// Add the unit delta to the transaction delta.
147147
vars.transactionDelta = vars.transactionDelta
148148
.add(
149-
Delta.CurvePoint({
149+
Delta.Point({
150150
x: uint256(complianceVerifierInput.instance.unitDeltaX),
151151
y: uint256(complianceVerifierInput.instance.unitDeltaY)
152152
})

contracts/src/libs/proving/Delta.sol

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,43 +10,62 @@ import {EfficientHashLib} from "@solady/utils/EfficientHashLib.sol";
1010
/// @notice A library containing methods of the delta proving system.
1111
/// @custom:security-contact [email protected]
1212
library Delta {
13-
using Delta for CurvePoint;
13+
using Delta for Point;
1414

1515
/// @notice An elliptic curve point representing a delta value.
1616
/// @param x The x component of the point.
1717
/// @param y The y component of the point.
18-
struct CurvePoint {
18+
struct Point {
1919
uint256 x;
2020
uint256 y;
2121
}
2222

23-
/// @notice The constant of the secp256k1 (K-256) elliptic curve.
23+
/// @notice The x-coordinate of the curve generator point.
24+
uint256 internal constant _GX = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798;
25+
26+
/// @notice The y-coordinate of the curve generator point.
27+
uint256 internal constant _GY = 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8;
28+
29+
// @notice The coefficient a of th secp256k1 (K-256) elliptic curve (y² = x³ + ax + b).
2430
uint256 internal constant _AA = 0;
2531

26-
/// @notice The modulus of the secp256k1 (K-256) elliptic curve.
32+
// @notice The coefficient b of th secp256k1 (K-256) elliptic curve (y² = x³ + ax + b).
33+
uint256 internal constant _BB = 7;
34+
35+
/// @notice The field prime modulus (2^256 - 2^32 - 977) of the secp256k1 (K-256) elliptic curve (y² = x³ + ax + b).
2736
uint256 internal constant _PP = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F;
2837

2938
/// @notice Thrown if the recovered delta public key doesn't match the delta instance.
3039
error DeltaMismatch(address expected, address actual);
3140

41+
/// @notice Thrown when a provided point is not on the curve.
42+
error PointNotOnCurve(Point point);
43+
3244
/// @notice Returns the elliptic curve point representing the zero delta.
3345
/// @return zeroDelta The zero delta.
34-
function zero() internal pure returns (CurvePoint memory zeroDelta) {
35-
zeroDelta = CurvePoint({x: 0, y: 0});
46+
function zero() internal pure returns (Point memory zeroDelta) {
47+
zeroDelta = Point({x: 0, y: 0});
3648
}
3749

38-
/// @notice Adds two elliptic curve points and returns the resulting value.
39-
/// @param p1 The first curve point.
40-
/// @param p2 The second curve point.
50+
/// @notice Adds two delta points and returns the sum.
51+
/// @param lhs The left-hand side point that can also be the zero delta.
52+
/// @param rhs The right-hand side point that must be a curve point.
4153
/// @return sum The resulting curve point.
42-
function add(CurvePoint memory p1, CurvePoint memory p2) internal pure returns (CurvePoint memory sum) {
43-
(sum.x, sum.y) = EllipticCurve.ecAdd({_x1: p1.x, _y1: p1.y, _x2: p2.x, _y2: p2.y, _aa: _AA, _pp: _PP});
54+
/// @dev Note that only the right-hand side point is checked to allow adding the zero delta from the left. This is
55+
/// done due to the delta points being added sequentially starting from the zero delta in the
56+
/// `ProtocolAdapter.execute()` function.
57+
function add(Point memory lhs, Point memory rhs) internal pure returns (Point memory sum) {
58+
if (!EllipticCurve.isOnCurve({_x: rhs.x, _y: rhs.y, _aa: _AA, _bb: _BB, _pp: _PP})) {
59+
revert PointNotOnCurve(rhs);
60+
}
61+
62+
(sum.x, sum.y) = EllipticCurve.ecAdd({_x1: lhs.x, _y1: lhs.y, _x2: rhs.x, _y2: rhs.y, _aa: _AA, _pp: _PP});
4463
}
4564

4665
/// @notice Converts an elliptic curve point to an Ethereum account address.
4766
/// @param delta The elliptic curve point.
4867
/// @return account The associated account.
49-
function toAccount(CurvePoint memory delta) internal pure returns (address account) {
68+
function toAccount(Point memory delta) internal pure returns (address account) {
5069
// Hash the public key with Keccak-256.
5170
bytes32 hashedKey = EfficientHashLib.hash(delta.x, delta.y);
5271

@@ -66,7 +85,7 @@ library Delta {
6685
/// @param proof The delta proof.
6786
/// @param instance The transaction delta.
6887
/// @param verifyingKey The Keccak-256 hash of all nullifiers and commitments as ordered in the compliance units.
69-
function verify(bytes memory proof, CurvePoint memory instance, bytes32 verifyingKey) internal pure {
88+
function verify(bytes memory proof, Point memory instance, bytes32 verifyingKey) internal pure {
7089
// Verify the delta proof using the ECDSA.recover API to obtain the address
7190
address recovered = ECDSA.recover({hash: verifyingKey, signature: proof});
7291

contracts/test/libs/DeltaGen.sol

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ library DeltaGen {
4949
/// @return instance The delta instance corresponding to the parameters
5050
function generateInstance(VmSafe vm, InstanceInputs memory deltaInputs)
5151
internal
52-
returns (Delta.CurvePoint memory instance)
52+
returns (Delta.Point memory instance)
5353
{
5454
deltaInputs.valueCommitmentRandomness = deltaInputs.valueCommitmentRandomness.modOrder();
5555
if (deltaInputs.valueCommitmentRandomness == 0) {
@@ -69,7 +69,7 @@ library DeltaGen {
6969
VmSafe.Wallet memory valueWallet = vm.createWallet(preDelta);
7070

7171
// Extract the transaction delta from the wallet
72-
instance = Delta.CurvePoint({x: valueWallet.publicKeyX, y: valueWallet.publicKeyY});
72+
instance = Delta.Point({x: valueWallet.publicKeyX, y: valueWallet.publicKeyY});
7373
}
7474

7575
/// @notice Generates a transaction delta proof by signing verifyingKey with

0 commit comments

Comments
 (0)