Skip to content

Commit 7cbad55

Browse files
committed
Only check signature if block not requested
1 parent 4047f24 commit 7cbad55

File tree

10 files changed

+114
-67
lines changed

10 files changed

+114
-67
lines changed

consensus/system_contract/api.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@ import (
99
// API is a user facing RPC API to allow controlling the signer and voting
1010
// mechanisms of the proof-of-authority scheme.
1111
type API struct {
12-
chain consensus.ChainHeaderReader
12+
chain consensus.ChainHeaderReader
1313
}
1414

1515
// GetSigners retrieves the list of authorized signers at the specified block.
1616
func (api *API) GetSigners(number *rpc.BlockNumber) ([]common.Address, error) {
1717
return nil, nil
18-
}
18+
}

consensus/system_contract/consensus.go

+12-8
Original file line numberDiff line numberDiff line change
@@ -174,17 +174,21 @@ func (s *SystemContract) verifyCascadingFields(chain consensus.ChainHeaderReader
174174
return err
175175
}
176176

177-
signer, err := ecrecover(header)
178-
if err != nil {
179-
return err
180-
}
177+
// only if block header has NOT been requested, then verify the signature against the current signer
178+
if !header.Requested {
179+
signer, err := ecrecover(header)
180+
if err != nil {
181+
return err
182+
}
181183

182-
s.lock.Lock()
183-
defer s.lock.Unlock()
184+
s.lock.RLock()
185+
defer s.lock.RUnlock()
184186

185-
if signer != s.signerAddressL1 {
186-
return errUnauthorizedSigner
187+
if signer != s.signerAddressL1 {
188+
return errUnauthorizedSigner
189+
}
187190
}
191+
188192
return nil
189193
}
190194

consensus/system_contract/system_contract.go

+9-3
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,15 @@ func (s *SystemContract) Start() {
7979
if err != nil {
8080
log.Error("failed to get signer address from L1 System Contract", "err", err)
8181
}
82-
s.lock.Lock()
83-
s.signerAddressL1 = common.BytesToAddress(address)
84-
s.lock.Unlock()
82+
bAddress := common.BytesToAddress(address)
83+
s.lock.RLock()
84+
addressChanged := s.signerAddressL1 != bAddress
85+
s.lock.RUnlock()
86+
if addressChanged {
87+
s.lock.Lock()
88+
s.signerAddressL1 = bAddress
89+
s.lock.Unlock()
90+
}
8591
}
8692
}
8793
}()

core/types/block.go

+5
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,11 @@ type Header struct {
101101
// ParentBeaconRoot was added by EIP-4788 and is ignored in legacy headers.
102102
// Included for Ethereum compatibility in Scroll SDK
103103
ParentBeaconRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"`
104+
105+
//Hacky: used internally to mark the header as requested by the downloader at the deliver queue
106+
// The tag "rlp:\"-\"" ensures it's excluded from the RLP encoding (and thus, from the hash computation).
107+
108+
Requested bool `json:"requested" rlp:"-"`
104109
}
105110

106111
// field type overrides for gencodec

eth/downloader/downloader.go

+21-19
Original file line numberDiff line numberDiff line change
@@ -702,9 +702,11 @@ func (d *Downloader) fetchHead(p *peerConnection) (head *types.Header, pivot *ty
702702
// calculateRequestSpan calculates what headers to request from a peer when trying to determine the
703703
// common ancestor.
704704
// It returns parameters to be used for peer.RequestHeadersByNumber:
705-
// from - starting block number
706-
// count - number of headers to request
707-
// skip - number of headers to skip
705+
//
706+
// from - starting block number
707+
// count - number of headers to request
708+
// skip - number of headers to skip
709+
//
708710
// and also returns 'max', the last block which is expected to be returned by the remote peers,
709711
// given the (from,count,skip)
710712
func calculateRequestSpan(remoteHeight, localHeight uint64) (int64, int, int, uint64) {
@@ -1319,22 +1321,22 @@ func (d *Downloader) fetchReceipts(from uint64) error {
13191321
// various callbacks to handle the slight differences between processing them.
13201322
//
13211323
// The instrumentation parameters:
1322-
// - errCancel: error type to return if the fetch operation is cancelled (mostly makes logging nicer)
1323-
// - deliveryCh: channel from which to retrieve downloaded data packets (merged from all concurrent peers)
1324-
// - deliver: processing callback to deliver data packets into type specific download queues (usually within `queue`)
1325-
// - wakeCh: notification channel for waking the fetcher when new tasks are available (or sync completed)
1326-
// - expire: task callback method to abort requests that took too long and return the faulty peers (traffic shaping)
1327-
// - pending: task callback for the number of requests still needing download (detect completion/non-completability)
1328-
// - inFlight: task callback for the number of in-progress requests (wait for all active downloads to finish)
1329-
// - throttle: task callback to check if the processing queue is full and activate throttling (bound memory use)
1330-
// - reserve: task callback to reserve new download tasks to a particular peer (also signals partial completions)
1331-
// - fetchHook: tester callback to notify of new tasks being initiated (allows testing the scheduling logic)
1332-
// - fetch: network callback to actually send a particular download request to a physical remote peer
1333-
// - cancel: task callback to abort an in-flight download request and allow rescheduling it (in case of lost peer)
1334-
// - capacity: network callback to retrieve the estimated type-specific bandwidth capacity of a peer (traffic shaping)
1335-
// - idle: network callback to retrieve the currently (type specific) idle peers that can be assigned tasks
1336-
// - setIdle: network callback to set a peer back to idle and update its estimated capacity (traffic shaping)
1337-
// - kind: textual label of the type being downloaded to display in log messages
1324+
// - errCancel: error type to return if the fetch operation is cancelled (mostly makes logging nicer)
1325+
// - deliveryCh: channel from which to retrieve downloaded data packets (merged from all concurrent peers)
1326+
// - deliver: processing callback to deliver data packets into type specific download queues (usually within `queue`)
1327+
// - wakeCh: notification channel for waking the fetcher when new tasks are available (or sync completed)
1328+
// - expire: task callback method to abort requests that took too long and return the faulty peers (traffic shaping)
1329+
// - pending: task callback for the number of requests still needing download (detect completion/non-completability)
1330+
// - inFlight: task callback for the number of in-progress requests (wait for all active downloads to finish)
1331+
// - throttle: task callback to check if the processing queue is full and activate throttling (bound memory use)
1332+
// - reserve: task callback to reserve new download tasks to a particular peer (also signals partial completions)
1333+
// - fetchHook: tester callback to notify of new tasks being initiated (allows testing the scheduling logic)
1334+
// - fetch: network callback to actually send a particular download request to a physical remote peer
1335+
// - cancel: task callback to abort an in-flight download request and allow rescheduling it (in case of lost peer)
1336+
// - capacity: network callback to retrieve the estimated type-specific bandwidth capacity of a peer (traffic shaping)
1337+
// - idle: network callback to retrieve the currently (type specific) idle peers that can be assigned tasks
1338+
// - setIdle: network callback to set a peer back to idle and update its estimated capacity (traffic shaping)
1339+
// - kind: textual label of the type being downloaded to display in log messages
13381340
func (d *Downloader) fetchParts(deliveryCh chan dataPack, deliver func(dataPack) (int, error), wakeCh chan bool,
13391341
expire func() map[string]int, pending func() int, inFlight func() bool, reserve func(*peerConnection, int) (*fetchRequest, bool, bool),
13401342
fetchHook func([]*types.Header), fetch func(*peerConnection, *fetchRequest) error, cancel func(*fetchRequest), capacity func(*peerConnection) int,

eth/downloader/queue.go

+17-4
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ type queue struct {
132132
receiptTaskQueue *prque.Prque // Priority queue of the headers to fetch the receipts for
133133
receiptPendPool map[string]*fetchRequest // Currently pending receipt retrieval operations
134134

135-
resultCache *resultStore // Downloaded but not yet delivered fetch results
135+
resultCache *resultStore // Requested but not yet delivered fetch results
136136
resultSize common.StorageSize // Approximate size of a block (exponential moving average)
137137

138138
lock *sync.RWMutex
@@ -477,9 +477,10 @@ func (q *queue) ReserveReceipts(p *peerConnection, count int) (*fetchRequest, bo
477477
// to access the queue, so they already need a lock anyway.
478478
//
479479
// Returns:
480-
// item - the fetchRequest
481-
// progress - whether any progress was made
482-
// throttle - if the caller should throttle for a while
480+
//
481+
// item - the fetchRequest
482+
// progress - whether any progress was made
483+
// throttle - if the caller should throttle for a while
483484
func (q *queue) reserveHeaders(p *peerConnection, count int, taskPool map[common.Hash]*types.Header, taskQueue *prque.Prque,
484485
pendPool map[string]*fetchRequest, kind uint) (*fetchRequest, bool, bool) {
485486
// Short circuit if the pool has been depleted, or if the peer's already
@@ -705,6 +706,13 @@ func (q *queue) DeliverHeaders(id string, headers []*types.Header, headerProcCh
705706
headerReqTimer.UpdateSince(request.Time)
706707
delete(q.headerPendPool, id)
707708

709+
// Hacky: mark that the header was explicitly requested
710+
// This extra field is used by the custom consensus to
711+
// verify against current signerAddressL1 if the header was not requested
712+
for _, header := range headers {
713+
header.Requested = true
714+
}
715+
708716
// Ensure headers can be mapped onto the skeleton chain
709717
target := q.headerTaskPool[request.From].Hash()
710718

@@ -842,6 +850,11 @@ func (q *queue) deliver(id string, taskPool map[common.Hash]*types.Header,
842850
reqTimer.UpdateSince(request.Time)
843851
delete(pendPool, id)
844852

853+
// Hacky: mark that the header was explicitly requested
854+
for _, header := range request.Headers {
855+
header.Requested = true
856+
}
857+
845858
// If no data items were retrieved, mark them as unavailable for the origin peer
846859
if results == 0 {
847860
for _, header := range request.Headers {

eth/downloader/resultstore.go

+6-5
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import (
2727
// resultStore implements a structure for maintaining fetchResults, tracking their
2828
// download-progress and delivering (finished) results.
2929
type resultStore struct {
30-
items []*fetchResult // Downloaded but not yet delivered fetch results
30+
items []*fetchResult // Delivered but not yet delivered fetch results
3131
resultOffset uint64 // Offset of the first cached fetch result in the block chain
3232

3333
// Internal index of first non-completed entry, updated atomically when needed.
@@ -71,10 +71,11 @@ func (r *resultStore) SetThrottleThreshold(threshold uint64) uint64 {
7171
// wants to reserve headers for fetching.
7272
//
7373
// It returns the following:
74-
// stale - if true, this item is already passed, and should not be requested again
75-
// throttled - if true, the store is at capacity, this particular header is not prio now
76-
// item - the result to store data into
77-
// err - any error that occurred
74+
//
75+
// stale - if true, this item is already passed, and should not be requested again
76+
// throttled - if true, the store is at capacity, this particular header is not prio now
77+
// item - the result to store data into
78+
// err - any error that occurred
7879
func (r *resultStore) AddFetch(header *types.Header, fastSync bool) (stale, throttled bool, item *fetchResult, err error) {
7980
r.lock.Lock()
8081
defer r.lock.Unlock()

les/downloader/downloader.go

+21-19
Original file line numberDiff line numberDiff line change
@@ -705,9 +705,11 @@ func (d *Downloader) fetchHead(p *peerConnection) (head *types.Header, pivot *ty
705705
// calculateRequestSpan calculates what headers to request from a peer when trying to determine the
706706
// common ancestor.
707707
// It returns parameters to be used for peer.RequestHeadersByNumber:
708-
// from - starting block number
709-
// count - number of headers to request
710-
// skip - number of headers to skip
708+
//
709+
// from - starting block number
710+
// count - number of headers to request
711+
// skip - number of headers to skip
712+
//
711713
// and also returns 'max', the last block which is expected to be returned by the remote peers,
712714
// given the (from,count,skip)
713715
func calculateRequestSpan(remoteHeight, localHeight uint64) (int64, int, int, uint64) {
@@ -1322,22 +1324,22 @@ func (d *Downloader) fetchReceipts(from uint64) error {
13221324
// various callbacks to handle the slight differences between processing them.
13231325
//
13241326
// The instrumentation parameters:
1325-
// - errCancel: error type to return if the fetch operation is cancelled (mostly makes logging nicer)
1326-
// - deliveryCh: channel from which to retrieve downloaded data packets (merged from all concurrent peers)
1327-
// - deliver: processing callback to deliver data packets into type specific download queues (usually within `queue`)
1328-
// - wakeCh: notification channel for waking the fetcher when new tasks are available (or sync completed)
1329-
// - expire: task callback method to abort requests that took too long and return the faulty peers (traffic shaping)
1330-
// - pending: task callback for the number of requests still needing download (detect completion/non-completability)
1331-
// - inFlight: task callback for the number of in-progress requests (wait for all active downloads to finish)
1332-
// - throttle: task callback to check if the processing queue is full and activate throttling (bound memory use)
1333-
// - reserve: task callback to reserve new download tasks to a particular peer (also signals partial completions)
1334-
// - fetchHook: tester callback to notify of new tasks being initiated (allows testing the scheduling logic)
1335-
// - fetch: network callback to actually send a particular download request to a physical remote peer
1336-
// - cancel: task callback to abort an in-flight download request and allow rescheduling it (in case of lost peer)
1337-
// - capacity: network callback to retrieve the estimated type-specific bandwidth capacity of a peer (traffic shaping)
1338-
// - idle: network callback to retrieve the currently (type specific) idle peers that can be assigned tasks
1339-
// - setIdle: network callback to set a peer back to idle and update its estimated capacity (traffic shaping)
1340-
// - kind: textual label of the type being downloaded to display in log messages
1327+
// - errCancel: error type to return if the fetch operation is cancelled (mostly makes logging nicer)
1328+
// - deliveryCh: channel from which to retrieve downloaded data packets (merged from all concurrent peers)
1329+
// - deliver: processing callback to deliver data packets into type specific download queues (usually within `queue`)
1330+
// - wakeCh: notification channel for waking the fetcher when new tasks are available (or sync completed)
1331+
// - expire: task callback method to abort requests that took too long and return the faulty peers (traffic shaping)
1332+
// - pending: task callback for the number of requests still needing download (detect completion/non-completability)
1333+
// - inFlight: task callback for the number of in-progress requests (wait for all active downloads to finish)
1334+
// - throttle: task callback to check if the processing queue is full and activate throttling (bound memory use)
1335+
// - reserve: task callback to reserve new download tasks to a particular peer (also signals partial completions)
1336+
// - fetchHook: tester callback to notify of new tasks being initiated (allows testing the scheduling logic)
1337+
// - fetch: network callback to actually send a particular download request to a physical remote peer
1338+
// - cancel: task callback to abort an in-flight download request and allow rescheduling it (in case of lost peer)
1339+
// - capacity: network callback to retrieve the estimated type-specific bandwidth capacity of a peer (traffic shaping)
1340+
// - idle: network callback to retrieve the currently (type specific) idle peers that can be assigned tasks
1341+
// - setIdle: network callback to set a peer back to idle and update its estimated capacity (traffic shaping)
1342+
// - kind: textual label of the type being downloaded to display in log messages
13411343
func (d *Downloader) fetchParts(deliveryCh chan dataPack, deliver func(dataPack) (int, error), wakeCh chan bool,
13421344
expire func() map[string]int, pending func() int, inFlight func() bool, reserve func(*peerConnection, int) (*fetchRequest, bool, bool),
13431345
fetchHook func([]*types.Header), fetch func(*peerConnection, *fetchRequest) error, cancel func(*fetchRequest), capacity func(*peerConnection) int,

les/downloader/queue.go

+16-3
Original file line numberDiff line numberDiff line change
@@ -477,9 +477,10 @@ func (q *queue) ReserveReceipts(p *peerConnection, count int) (*fetchRequest, bo
477477
// to access the queue, so they already need a lock anyway.
478478
//
479479
// Returns:
480-
// item - the fetchRequest
481-
// progress - whether any progress was made
482-
// throttle - if the caller should throttle for a while
480+
//
481+
// item - the fetchRequest
482+
// progress - whether any progress was made
483+
// throttle - if the caller should throttle for a while
483484
func (q *queue) reserveHeaders(p *peerConnection, count int, taskPool map[common.Hash]*types.Header, taskQueue *prque.Prque,
484485
pendPool map[string]*fetchRequest, kind uint) (*fetchRequest, bool, bool) {
485486
// Short circuit if the pool has been depleted, or if the peer's already
@@ -705,6 +706,13 @@ func (q *queue) DeliverHeaders(id string, headers []*types.Header, headerProcCh
705706
headerReqTimer.UpdateSince(request.Time)
706707
delete(q.headerPendPool, id)
707708

709+
// Hacky: mark that the header was explicitly requested
710+
// This extra field is used by the custom consensus to
711+
// verify against current signerAddressL1 if the header was not requested
712+
for _, header := range headers {
713+
header.Requested = true
714+
}
715+
708716
// Ensure headers can be mapped onto the skeleton chain
709717
target := q.headerTaskPool[request.From].Hash()
710718

@@ -842,6 +850,11 @@ func (q *queue) deliver(id string, taskPool map[common.Hash]*types.Header,
842850
reqTimer.UpdateSince(request.Time)
843851
delete(pendPool, id)
844852

853+
// Hacky: mark that the header was explicitly requested
854+
for _, header := range request.Headers {
855+
header.Requested = true
856+
}
857+
845858
// If no data items were retrieved, mark them as unavailable for the origin peer
846859
if results == 0 {
847860
for _, header := range request.Headers {

les/downloader/resultstore.go

+5-4
Original file line numberDiff line numberDiff line change
@@ -71,10 +71,11 @@ func (r *resultStore) SetThrottleThreshold(threshold uint64) uint64 {
7171
// wants to reserve headers for fetching.
7272
//
7373
// It returns the following:
74-
// stale - if true, this item is already passed, and should not be requested again
75-
// throttled - if true, the store is at capacity, this particular header is not prio now
76-
// item - the result to store data into
77-
// err - any error that occurred
74+
//
75+
// stale - if true, this item is already passed, and should not be requested again
76+
// throttled - if true, the store is at capacity, this particular header is not prio now
77+
// item - the result to store data into
78+
// err - any error that occurred
7879
func (r *resultStore) AddFetch(header *types.Header, fastSync bool) (stale, throttled bool, item *fetchResult, err error) {
7980
r.lock.Lock()
8081
defer r.lock.Unlock()

0 commit comments

Comments
 (0)