Skip to content

Commit

Permalink
Address review comments - no need for sorted hash map
Browse files Browse the repository at this point in the history
  • Loading branch information
cyberj0g committed Jan 12, 2023
1 parent 89b86b6 commit d3a7d7d
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 53 deletions.
1 change: 0 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ require (
github.com/allegro/bigcache v1.2.1 // indirect
github.com/cenkalti/backoff v2.2.1+incompatible
github.com/cespare/cp v1.1.1 // indirect
github.com/elliotchance/orderedmap v1.5.0 // indirect
github.com/ethereum/go-ethereum v1.10.26
github.com/fatih/color v1.12.0 // indirect
github.com/golang/glog v0.0.0-20210429001901-424d2337a529
Expand Down
48 changes: 25 additions & 23 deletions pm/recipient.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"crypto/hmac"
"crypto/rand"
"crypto/sha256"
"github.com/elliotchance/orderedmap"
"math/big"
"sync"

Expand Down Expand Up @@ -89,7 +88,10 @@ type recipient struct {
secret [32]byte
maxfacevalue *big.Int

senderNonces map[string]*orderedmap.OrderedMap
senderNonces map[string]*struct {
nonceSeen map[uint32]byte
expirationBlock *big.Int
}
senderNoncesLock sync.Mutex

cfg TicketParamsConfig
Expand Down Expand Up @@ -124,9 +126,12 @@ func NewRecipientWithSecret(addr ethcommon.Address, broker Broker, val Validator
addr: addr,
secret: secret,
maxfacevalue: big.NewInt(0),
senderNonces: make(map[string]*orderedmap.OrderedMap),
cfg: cfg,
quit: make(chan struct{}),
senderNonces: make(map[string]*struct {
nonceSeen map[uint32]byte
expirationBlock *big.Int
}),
cfg: cfg,
quit: make(chan struct{}),
}
}

Expand Down Expand Up @@ -361,21 +366,24 @@ func (r *recipient) updateSenderNonce(rand *big.Int, ticket *Ticket) error {
defer r.senderNoncesLock.Unlock()

randStr := rand.String()
nonceToExpBlock, randKeySeen := r.senderNonces[randStr]
senderNonce, randKeySeen := r.senderNonces[randStr]
if randKeySeen {
_, nonceSeen := nonceToExpBlock.Get(ticket.SenderNonce)
if nonceSeen {
_, isSeen := senderNonce.nonceSeen[ticket.SenderNonce]
if isSeen {
return errors.Errorf("invalid ticket senderNonce: already seen sender=%v nonce=%v", ticket.Sender.Hex(), ticket.SenderNonce)
}
} else {
r.senderNonces[randStr] = orderedmap.NewOrderedMap()
r.senderNonces[randStr] = &struct {
nonceSeen map[uint32]byte
expirationBlock *big.Int
}{make(map[uint32]byte), ticket.ParamsExpirationBlock}
}
// add new nonce
r.senderNonces[randStr].Set(ticket.SenderNonce, ticket.ParamsExpirationBlock)
// delete first seen nonce, if ordered map exceeds max size
if r.senderNonces[randStr].Len() > maxSenderNonces {
r.senderNonces[randStr].Delete(r.senderNonces[randStr].Front().Key)
// check nonce map size
if len(r.senderNonces[randStr].nonceSeen) > maxSenderNonces - 1 {
return errors.Errorf("invalid ticket senderNonce: too many values sender=%v nonce=%v", ticket.Sender.Hex(), ticket.SenderNonce)
}
// add new nonce
r.senderNonces[randStr].nonceSeen[ticket.SenderNonce] = 1
return nil
}

Expand All @@ -396,15 +404,9 @@ func (r *recipient) senderNoncesCleanupLoop() {
glog.Error(err)
case latestL1Block := <-sink:
r.senderNoncesLock.Lock()
for recipientRand, nonceMap := range r.senderNonces {
for _, key := range nonceMap.Keys() {
expirationBlock, _ := nonceMap.Get(key)
if expirationBlock.(*big.Int).Cmp(latestL1Block) <= 0 {
nonceMap.Delete(key)
if nonceMap.Len() == 0 {
delete(r.senderNonces, recipientRand)
}
}
for recipientRand, sn := range r.senderNonces {
if sn.expirationBlock.Cmp(latestL1Block) <= 0 {
delete(r.senderNonces, recipientRand)
}
}
r.senderNoncesLock.Unlock()
Expand Down
59 changes: 30 additions & 29 deletions pm/recipient_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package pm
import (
"crypto/hmac"
"crypto/sha256"
"github.com/elliotchance/orderedmap"
"math/big"
"strings"
"sync"
Expand Down Expand Up @@ -225,8 +224,8 @@ func TestReceiveTicket_ValidNonWinningTicket(t *testing.T) {
recipientRand := genRecipientRand(sender, secret, params)
senderNonce := r.(*recipient).senderNonces[recipientRand.String()]

if senderNonce.Front().Key != newSenderNonce {
t.Errorf("expected senderNonce to be %d, got %d", newSenderNonce, senderNonce.Front().Key)
if _, ok := senderNonce.nonceSeen[newSenderNonce]; !ok {
t.Errorf("expected senderNonce to exist: %d", newSenderNonce)
}
}

Expand Down Expand Up @@ -258,8 +257,8 @@ func TestReceiveTicket_ValidWinningTicket(t *testing.T) {
recipientRand := genRecipientRand(sender, secret, params)
senderNonce := r.(*recipient).senderNonces[recipientRand.String()]

if senderNonce.Front().Key != newSenderNonce {
t.Errorf("expected senderNonce to be %d, got %d", newSenderNonce, senderNonce.Front().Key)
if _, ok := senderNonce.nonceSeen[newSenderNonce]; !ok {
t.Errorf("expected senderNonce to exist: %d", newSenderNonce)
}
}

Expand Down Expand Up @@ -343,22 +342,15 @@ func TestReceiveTicket_NonceMapFill(t *testing.T) {
params, err := r.TicketParams(sender, big.NewRat(1, 1))
require.Nil(t, err)
// fill nonce map to capacity
for i := 0; i < maxSenderNonces; i++ {
for i := 0; i < maxSenderNonces+1; i++ {
ticket := newTicket(sender, params, uint32(i))
_, _, err := r.ReceiveTicket(ticket, sig, params.Seed)
assert.NoError(err)
if i < maxSenderNonces {
assert.NoError(err)
} else {
assert.Error(err)
}
}
// ensure can't use existing nonce
_, _, err = r.ReceiveTicket(newTicket(sender, params, uint32(0)), sig, params.Seed)
assert.Error(err)

// adding new element above capacity - it should exclude nonce 0
_, _, err = r.ReceiveTicket(newTicket(sender, params, uint32(maxSenderNonces)), sig, params.Seed)

// check that we can use nonce 0 now
_, _, err = r.ReceiveTicket(newTicket(sender, params, uint32(0)), sig, params.Seed)
assert.NoError(err)

}

func TestReceiveTicket_ValidTicket_Expired(t *testing.T) {
Expand Down Expand Up @@ -676,23 +668,32 @@ func TestSenderNoncesCleanupLoop(t *testing.T) {
tm := &stubTimeManager{}

r := &recipient{
tm: tm,
quit: make(chan struct{}),
senderNonces: make(map[string]*orderedmap.OrderedMap),
tm: tm,
quit: make(chan struct{}),
senderNonces: make(map[string]*struct {
nonceSeen map[uint32]byte
expirationBlock *big.Int
}),
}

// add some senderNonces
rand0 := "blastoise"
rand1 := "charizard"
rand2 := "raichu"
r.senderNonces[rand0] = orderedmap.NewOrderedMap()
r.senderNonces[rand0].Set(1, big.NewInt(3))

r.senderNonces[rand1] = orderedmap.NewOrderedMap()
r.senderNonces[rand1].Set(1, big.NewInt(2))

r.senderNonces[rand2] = orderedmap.NewOrderedMap()
r.senderNonces[rand2].Set(1, big.NewInt(1))
r.senderNonces[rand0] = &struct {
nonceSeen map[uint32]byte
expirationBlock *big.Int
}{map[uint32]byte{1: 1}, big.NewInt(3)}

r.senderNonces[rand1] = &struct {
nonceSeen map[uint32]byte
expirationBlock *big.Int
}{map[uint32]byte{1: 1}, big.NewInt(2)}

r.senderNonces[rand2] = &struct {
nonceSeen map[uint32]byte
expirationBlock *big.Int
}{map[uint32]byte{1: 1}, big.NewInt(1)}

go r.senderNoncesCleanupLoop()
time.Sleep(20 * time.Millisecond)
Expand Down

0 comments on commit d3a7d7d

Please sign in to comment.