-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement EIP7805: Fork-choice enforced Inclusion Lists
Make the naive interop work betweem Prysm and Geth (#14819)
- Loading branch information
1 parent
e473d7c
commit 15968d4
Showing
68 changed files
with
3,563 additions
and
1,623 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
package blockchain | ||
|
||
import ( | ||
"context" | ||
"time" | ||
|
||
"github.com/prysmaticlabs/prysm/v5/config/params" | ||
"github.com/prysmaticlabs/prysm/v5/time/slots" | ||
) | ||
|
||
const updateInclusionListBlockInterval = time.Second | ||
|
||
// Routine that updates block building with inclusion lists one second before the slot starts. | ||
func (s *Service) updateBlockWithInclusionListRoutine() { | ||
if err := s.waitForSync(); err != nil { | ||
log.WithError(err).Error("Failed to wait for initial sync") | ||
return | ||
} | ||
|
||
interval := time.Second*time.Duration(params.BeaconConfig().SecondsPerSlot) - updateInclusionListBlockInterval | ||
ticker := slots.NewSlotTickerWithIntervals(s.genesisTime, []time.Duration{interval}) | ||
|
||
for { | ||
select { | ||
case <-s.ctx.Done(): | ||
return | ||
case <-ticker.C(): | ||
s.updateBlockWithInclusionList(context.Background()) | ||
} | ||
} | ||
} | ||
|
||
// Updates block building with inclusion lists, the current payload ID, and the new upload ID. | ||
func (s *Service) updateBlockWithInclusionList(ctx context.Context) { | ||
currentSlot := s.CurrentSlot() | ||
|
||
// Skip update if not in or past the FOCIL fork epoch. | ||
if slots.ToEpoch(currentSlot) < params.BeaconConfig().FuluForkEpoch { | ||
return | ||
} | ||
|
||
s.cfg.ForkChoiceStore.RLock() | ||
defer s.cfg.ForkChoiceStore.RUnlock() | ||
|
||
headRoot := s.headRoot() | ||
id, found := s.cfg.PayloadIDCache.PayloadID(currentSlot+1, headRoot) | ||
if !found { | ||
return | ||
} | ||
|
||
txs := s.inclusionListCache.Get(currentSlot) | ||
if len(txs) == 0 { | ||
log.WithField("slot", currentSlot).Warn("Proposer: no IL TX to update next block") | ||
return | ||
} | ||
|
||
newID, err := s.cfg.ExecutionEngineCaller.UpdatePayloadWithInclusionList(ctx, id, txs) | ||
if err != nil { | ||
log.WithError(err).Error("Failed to update block with inclusion list") | ||
return | ||
} | ||
|
||
s.cfg.PayloadIDCache.Set(currentSlot+1, headRoot, *newID) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
package cache | ||
|
||
import ( | ||
"crypto/sha256" | ||
"sync" | ||
|
||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" | ||
) | ||
|
||
type InclusionLists struct { | ||
mu sync.RWMutex | ||
ils map[primitives.Slot]map[primitives.ValidatorIndex]struct { | ||
txs [][]byte | ||
seenTwice bool | ||
} | ||
} | ||
|
||
// NewInclusionLists initializes a new InclusionLists instance. | ||
func NewInclusionLists() *InclusionLists { | ||
return &InclusionLists{ | ||
ils: make(map[primitives.Slot]map[primitives.ValidatorIndex]struct { | ||
txs [][]byte | ||
seenTwice bool | ||
}), | ||
} | ||
} | ||
|
||
// Add adds a set of transactions for a specific slot and validator index. | ||
func (i *InclusionLists) Add(slot primitives.Slot, validatorIndex primitives.ValidatorIndex, txs [][]byte) { | ||
i.mu.Lock() | ||
defer i.mu.Unlock() | ||
|
||
if _, ok := i.ils[slot]; !ok { | ||
i.ils[slot] = make(map[primitives.ValidatorIndex]struct { | ||
txs [][]byte | ||
seenTwice bool | ||
}) | ||
} | ||
|
||
entry := i.ils[slot][validatorIndex] | ||
if entry.seenTwice { | ||
return // No need to modify if already marked as seen twice. | ||
} | ||
|
||
if entry.txs == nil { | ||
entry.txs = txs | ||
} else { | ||
entry.seenTwice = true | ||
entry.txs = nil // Clear transactions to save space if seen twice. | ||
} | ||
i.ils[slot][validatorIndex] = entry | ||
} | ||
|
||
// Get retrieves unique transactions for a specific slot. | ||
func (i *InclusionLists) Get(slot primitives.Slot) [][]byte { | ||
i.mu.RLock() | ||
defer i.mu.RUnlock() | ||
|
||
ils, exists := i.ils[slot] | ||
if !exists { | ||
return [][]byte{} | ||
} | ||
|
||
var uniqueTxs [][]byte | ||
seen := make(map[[32]byte]struct{}) | ||
for _, entry := range ils { | ||
for _, tx := range entry.txs { | ||
hash := sha256.Sum256(tx) | ||
if _, duplicate := seen[hash]; !duplicate { | ||
uniqueTxs = append(uniqueTxs, tx) | ||
seen[hash] = struct{}{} | ||
} | ||
} | ||
} | ||
return uniqueTxs | ||
} | ||
|
||
// Delete removes all inclusion lists for a specific slot. | ||
func (i *InclusionLists) Delete(slot primitives.Slot) { | ||
i.mu.Lock() | ||
defer i.mu.Unlock() | ||
|
||
delete(i.ils, slot) | ||
} | ||
|
||
// SeenTwice checks if a validator's transactions were marked as seen twice for a specific slot. | ||
func (i *InclusionLists) SeenTwice(slot primitives.Slot, idx primitives.ValidatorIndex) bool { | ||
i.mu.RLock() | ||
defer i.mu.RUnlock() | ||
|
||
ils, exists := i.ils[slot] | ||
if !exists { | ||
return false | ||
} | ||
|
||
entry, exists := ils[idx] | ||
return exists && entry.seenTwice | ||
} |
Oops, something went wrong.