Skip to content

Commit 17f0cbb

Browse files
author
yujiezhu0
committed
Replace nonce with request hashing
1 parent 1db0a42 commit 17f0cbb

File tree

16 files changed

+192
-242
lines changed

16 files changed

+192
-242
lines changed

api/clients/v2/disperser_client.go

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package clients
22

33
import (
44
"context"
5-
"crypto/rand"
65
"fmt"
76
"sync"
87
"time"
@@ -297,21 +296,15 @@ func (c *disperserClient) GetPaymentState(ctx context.Context) (*disperser_rpc.G
297296
return nil, fmt.Errorf("error getting signer's account ID: %w", err)
298297
}
299298

300-
nonce, err := GenerateNonce(32)
301-
if err != nil {
302-
return nil, fmt.Errorf("failed to generate nonce: %v", err)
303-
}
304-
305-
signature, err := c.signer.SignPaymentStateRequest(nonce)
299+
signature, err := c.signer.SignPaymentStateRequest()
306300
if err != nil {
307301
return nil, fmt.Errorf("error signing payment state request: %w", err)
308302
}
309303

310304
request := &disperser_rpc.GetPaymentStateRequest{
311305
AccountId: accountID.Hex(),
312306
Signature: signature,
313-
Timestamp: uint32(time.Now().Unix()),
314-
Nonce: nonce,
307+
Timestamp: uint64(time.Now().UnixNano()),
315308
}
316309
return c.client.GetPaymentState(ctx, request)
317310
}
@@ -371,13 +364,3 @@ func (c *disperserClient) initOncePopulateAccountant(ctx context.Context) error
371364
}
372365
return nil
373366
}
374-
375-
// GenerateNonce creates a random nonce of the specified length.
376-
func GenerateNonce(length int) ([]byte, error) {
377-
nonce := make([]byte, length)
378-
_, err := rand.Read(nonce)
379-
if err != nil {
380-
return nil, err
381-
}
382-
return nonce, nil
383-
}

api/clients/v2/disperser_client_test.go

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -116,20 +116,3 @@ func TestMutexPreventsSimultaneousRequests(t *testing.T) {
116116
require.GreaterOrEqual(t, totalTime.Milliseconds(), expectedMinTime.Milliseconds()-10, // allow small timing variations
117117
"Total execution time was less than expected, suggesting concurrent execution")
118118
}
119-
120-
func TestGenerateNonce(t *testing.T) {
121-
nonce, err := GenerateNonce(32)
122-
require.NoError(t, err)
123-
require.Len(t, nonce, 32, "nonce should be 32 bytes")
124-
125-
// Test multiple calls to ensure nonces are unique.
126-
nonceMap := make(map[string]struct{})
127-
for i := 0; i < 100; i++ {
128-
n, err := GenerateNonce(32)
129-
require.NoError(t, err)
130-
require.Len(t, n, 32, "nonce should be 32 bytes")
131-
key := string(n)
132-
require.NotContains(t, nonceMap, key, "nonce should be unique")
133-
nonceMap[key] = struct{}{}
134-
}
135-
}

api/docs/disperser_v2.html

Lines changed: 2 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/docs/eigenda-protos.html

Lines changed: 2 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/grpc/disperser/v2/disperser_v2.pb.go

Lines changed: 134 additions & 145 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/hashing/payment_state_hashing.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package hashing
2+
3+
import (
4+
"fmt"
5+
pb "github.com/Layr-Labs/eigenda/api/grpc/disperser/v2"
6+
"golang.org/x/crypto/sha3"
7+
)
8+
9+
// HashGetPaymentStateRequest hashes the given GetPaymentStateRequest.
10+
func HashGetPaymentStateRequest(request *pb.GetPaymentStateRequest) ([]byte, error) {
11+
hasher := sha3.NewLegacyKeccak256()
12+
13+
// Hash the account ID
14+
err := hashByteArray(hasher, []byte(request.GetAccountId()))
15+
if err != nil {
16+
return nil, fmt.Errorf("failed to hash account id: %w", err)
17+
}
18+
19+
// Hash the timestamp
20+
hashUint64(hasher, request.GetTimestamp())
21+
22+
return hasher.Sum(nil), nil
23+
}

api/proto/disperser/v2/disperser_v2.proto

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -120,11 +120,9 @@ message GetPaymentStateRequest {
120120
string account_id = 1;
121121
// Signature over the account ID
122122
bytes signature = 2;
123-
// Timestamp of the request in seconds since the Unix epoch. If too far out of sync with the server's clock,
123+
// Timestamp of the request in nanoseconds since the Unix epoch. If too far out of sync with the server's clock,
124124
// request may be rejected.
125-
uint32 timestamp = 3;
126-
// A client-generated nonce to ensure the request is unique.
127-
bytes nonce = 4;
125+
uint64 timestamp = 3;
128126
}
129127

130128
// GetPaymentStateReply contains the payment state of an account.

core/auth/v2/auth_test.go

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package v2_test
22

33
import (
44
"crypto/sha256"
5-
"encoding/hex"
65
disperser_rpc "github.com/Layr-Labs/eigenda/api/grpc/disperser/v2"
76
"math/big"
87
"testing"
@@ -20,9 +19,8 @@ import (
2019

2120
var (
2221
privateKeyHex = "0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
23-
nonce, _ = hex.DecodeString("3132333435363738393031323334353637383930313233343536373839303132")
24-
maxPastAge = 30 * time.Second
25-
maxFutureAge = 30 * time.Second
22+
maxPastAge = 5 * time.Minute
23+
maxFutureAge = 5 * time.Minute
2624
)
2725

2826
func TestAuthentication(t *testing.T) {
@@ -126,7 +124,7 @@ func TestAuthenticatePaymentStateRequestValid(t *testing.T) {
126124
assert.NoError(t, err)
127125
authenticator := auth.NewAuthenticator(maxPastAge, maxFutureAge)
128126

129-
signature, err := signer.SignPaymentStateRequest(nonce)
127+
signature, err := signer.SignPaymentStateRequest()
130128
assert.NoError(t, err)
131129

132130
accountId, err := signer.GetAccountID()
@@ -169,7 +167,7 @@ func TestAuthenticatePaymentStateRequestSignatureMismatch(t *testing.T) {
169167
accountId, err := signer.GetAccountID()
170168
assert.NoError(t, err)
171169

172-
signature, err := wrongSigner.SignPaymentStateRequest(nonce)
170+
signature, err := wrongSigner.SignPaymentStateRequest()
173171
assert.NoError(t, err)
174172

175173
request := mockGetPaymentStateRequest(accountId, signature)
@@ -203,7 +201,6 @@ func mockGetPaymentStateRequest(accountId gethcommon.Address, signature []byte)
203201
return &disperser_rpc.GetPaymentStateRequest{
204202
AccountId: accountId.Hex(),
205203
Signature: signature,
206-
Timestamp: uint32(time.Now().Unix()),
207-
Nonce: nonce,
204+
Timestamp: uint64(time.Now().UnixNano()),
208205
}
209206
}

core/auth/v2/authenticator.go

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"errors"
66
"fmt"
77
pb "github.com/Layr-Labs/eigenda/api/grpc/disperser/v2"
8+
"github.com/Layr-Labs/eigenda/api/hashing"
89
"time"
910

1011
"github.com/Layr-Labs/eigenda/common/replay"
@@ -53,7 +54,7 @@ func (*authenticator) AuthenticateBlobRequest(header *core.BlobHeader, signature
5354
}
5455

5556
// AuthenticatePaymentStateRequest verifies the signature of the payment state request
56-
// The signature is signed over the byte representation of the account ID and nonce
57+
// The signature is signed over the byte representation of the account ID
5758
// See implementation of BlobRequestSigner.SignPaymentStateRequest for more details
5859
func (a *authenticator) AuthenticatePaymentStateRequest(accountAddr common.Address, request *pb.GetPaymentStateRequest) error {
5960
sig := request.GetSignature()
@@ -63,11 +64,9 @@ func (a *authenticator) AuthenticatePaymentStateRequest(accountAddr common.Addre
6364
}
6465

6566
timestamp := request.GetTimestamp()
66-
nonce := request.GetNonce()
6767

6868
// Verify the signature
69-
accountAddrWithNonce := append(accountAddr.Bytes(), nonce...)
70-
hash := sha256.Sum256(accountAddrWithNonce)
69+
hash := sha256.Sum256(accountAddr.Bytes())
7170
sigPublicKeyECDSA, err := crypto.SigToPub(hash[:], sig)
7271
if err != nil {
7372
return fmt.Errorf("failed to recover public key from signature: %v", err)
@@ -79,8 +78,13 @@ func (a *authenticator) AuthenticatePaymentStateRequest(accountAddr common.Addre
7978
return errors.New("signature doesn't match with provided public key")
8079
}
8180

82-
if err := a.replayGuardian.VerifyRequest(nonce, time.Unix(int64(timestamp), 0)); err != nil {
83-
return fmt.Errorf("invalid request: the provided nonce has already been used or the request has expired (%v)", err)
81+
requestHash, err := hashing.HashGetPaymentStateRequest(request)
82+
if err != nil {
83+
return fmt.Errorf("failed to hash request: %w", err)
84+
}
85+
86+
if err := a.replayGuardian.VerifyRequest(requestHash, time.Unix(0, int64(timestamp))); err != nil {
87+
return fmt.Errorf("failed to verify request: %v", err)
8488
}
8589

8690
return nil

core/auth/v2/signer.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,13 @@ func (s *LocalBlobRequestSigner) SignBlobRequest(header *core.BlobHeader) ([]byt
4444
return sig, nil
4545
}
4646

47-
func (s *LocalBlobRequestSigner) SignPaymentStateRequest(nonce []byte) ([]byte, error) {
47+
func (s *LocalBlobRequestSigner) SignPaymentStateRequest() ([]byte, error) {
4848
accountId, err := s.GetAccountID()
4949
if err != nil {
5050
return nil, fmt.Errorf("failed to get account ID: %v", err)
5151
}
5252

53-
accountAddrWithNonce := append(accountId.Bytes(), nonce...)
54-
hash := sha256.Sum256(accountAddrWithNonce)
53+
hash := sha256.Sum256(accountId.Bytes())
5554
// Sign the account ID using the private key
5655
sig, err := crypto.Sign(hash[:], s.PrivateKey)
5756
if err != nil {
@@ -78,7 +77,7 @@ func (s *LocalNoopSigner) SignBlobRequest(header *core.BlobHeader) ([]byte, erro
7877
return nil, fmt.Errorf("noop signer cannot sign blob request")
7978
}
8079

81-
func (s *LocalNoopSigner) SignPaymentStateRequest(nonce []byte) ([]byte, error) {
80+
func (s *LocalNoopSigner) SignPaymentStateRequest() ([]byte, error) {
8281
return nil, fmt.Errorf("noop signer cannot sign payment state request")
8382
}
8483

0 commit comments

Comments
 (0)