-
Notifications
You must be signed in to change notification settings - Fork 1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Payload Attestation Sync package changes
- Loading branch information
Showing
15 changed files
with
423 additions
and
0 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,116 @@ | ||
package cache | ||
|
||
import ( | ||
"errors" | ||
"sync" | ||
|
||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" | ||
"github.com/prysmaticlabs/prysm/v5/crypto/bls" | ||
"github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" | ||
eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" | ||
) | ||
|
||
var errNilPayloadAttestationMessage = errors.New("nil Payload Attestation Message") | ||
|
||
// PayloadAttestationCache keeps a map of all the PTC votes that were seen, | ||
// already aggregated. The key is the beacon block root. | ||
type PayloadAttestationCache struct { | ||
root [32]byte | ||
attestations [primitives.PAYLOAD_INVALID_STATUS]*eth.PayloadAttestation | ||
sync.Mutex | ||
} | ||
|
||
// Seen returns true if a vote for the given Beacon Block Root has already been processed | ||
// for this Payload Timeliness Committee index. This will return true even if | ||
// the Payload status differs. | ||
func (p *PayloadAttestationCache) Seen(root [32]byte, idx uint64) bool { | ||
p.Lock() | ||
defer p.Unlock() | ||
if p.root != root { | ||
return false | ||
} | ||
for _, agg := range p.attestations { | ||
if agg == nil { | ||
continue | ||
} | ||
if agg.AggregationBits.BitAt(idx) { | ||
return true | ||
} | ||
} | ||
return false | ||
} | ||
|
||
// messageToPayloadAttestation creates a PayloadAttestation with a single | ||
// aggregated bit from the passed PayloadAttestationMessage | ||
func messageToPayloadAttestation(att *eth.PayloadAttestationMessage, idx uint64) *eth.PayloadAttestation { | ||
bits := primitives.NewPayloadAttestationAggregationBits() | ||
bits.SetBitAt(idx, true) | ||
data := ð.PayloadAttestationData{ | ||
BeaconBlockRoot: bytesutil.SafeCopyBytes(att.Data.BeaconBlockRoot), | ||
Slot: att.Data.Slot, | ||
PayloadStatus: att.Data.PayloadStatus, | ||
} | ||
return ð.PayloadAttestation{ | ||
AggregationBits: bits, | ||
Data: data, | ||
Signature: bytesutil.SafeCopyBytes(att.Signature), | ||
} | ||
} | ||
|
||
// aggregateSigFromMessage returns the aggregated signature from a Payload | ||
// Attestation by adding the passed signature in the PayloadAttestationMessage, | ||
// no signature validation is performed. | ||
func aggregateSigFromMessage(aggregated *eth.PayloadAttestation, message *eth.PayloadAttestationMessage) ([]byte, error) { | ||
aggSig, err := bls.SignatureFromBytesNoValidation(aggregated.Signature) | ||
if err != nil { | ||
return nil, err | ||
} | ||
sig, err := bls.SignatureFromBytesNoValidation(message.Signature) | ||
if err != nil { | ||
return nil, err | ||
} | ||
return bls.AggregateSignatures([]bls.Signature{aggSig, sig}).Marshal(), nil | ||
} | ||
|
||
// Add adds a PayloadAttestationMessage to the internal cache of aggregated | ||
// PayloadAttestations. | ||
// If the index has already been seen for this attestation status the function does nothing. | ||
// If the root is not the cached root, the function will clear the previous cache | ||
// This function assumes that the message has already been validated. In | ||
// particular that the signature is valid and that the block root corresponds to | ||
// the given slot in the attestation data. | ||
func (p *PayloadAttestationCache) Add(att *eth.PayloadAttestationMessage, idx uint64) error { | ||
if att == nil || att.Data == nil || att.Data.BeaconBlockRoot == nil { | ||
return errNilPayloadAttestationMessage | ||
} | ||
p.Lock() | ||
defer p.Unlock() | ||
root := [32]byte(att.Data.BeaconBlockRoot) | ||
if p.root != root { | ||
p.root = root | ||
p.attestations = [primitives.PAYLOAD_INVALID_STATUS]*eth.PayloadAttestation{} | ||
} | ||
agg := p.attestations[att.Data.PayloadStatus] | ||
if agg == nil { | ||
p.attestations[att.Data.PayloadStatus] = messageToPayloadAttestation(att, idx) | ||
return nil | ||
} | ||
if agg.AggregationBits.BitAt(idx) { | ||
return nil | ||
} | ||
agg.AggregationBits.SetBitAt(idx, true) | ||
sig, err := aggregateSigFromMessage(agg, att) | ||
if err != nil { | ||
return err | ||
} | ||
agg.Signature = sig | ||
return nil | ||
} | ||
|
||
// Clear clears the internal map | ||
func (p *PayloadAttestationCache) Clear() { | ||
p.Lock() | ||
defer p.Unlock() | ||
p.root = [32]byte{} | ||
p.attestations = [primitives.PAYLOAD_INVALID_STATUS]*eth.PayloadAttestation{} | ||
} |
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,95 @@ | ||
package cache | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" | ||
"github.com/prysmaticlabs/prysm/v5/crypto/bls" | ||
"github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" | ||
eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" | ||
"github.com/prysmaticlabs/prysm/v5/testing/require" | ||
) | ||
|
||
func TestPayloadAttestationCache(t *testing.T) { | ||
p := &PayloadAttestationCache{} | ||
|
||
//Test Has seen | ||
root := [32]byte{'r'} | ||
idx := uint64(5) | ||
require.Equal(t, false, p.Seen(root, idx)) | ||
|
||
// Test Add | ||
msg := ð.PayloadAttestationMessage{ | ||
Signature: bls.NewAggregateSignature().Marshal(), | ||
Data: ð.PayloadAttestationData{ | ||
BeaconBlockRoot: root[:], | ||
Slot: 1, | ||
PayloadStatus: primitives.PAYLOAD_PRESENT, | ||
}, | ||
} | ||
|
||
// Add new root | ||
require.NoError(t, p.Add(msg, idx)) | ||
require.Equal(t, true, p.Seen(root, idx)) | ||
require.Equal(t, root, p.root) | ||
att := p.attestations[primitives.PAYLOAD_PRESENT] | ||
indices := att.AggregationBits.BitIndices() | ||
require.DeepEqual(t, []int{int(idx)}, indices) | ||
singleSig := bytesutil.SafeCopyBytes(msg.Signature) | ||
require.DeepEqual(t, singleSig, att.Signature) | ||
|
||
// Test Seen | ||
require.Equal(t, true, p.Seen(root, idx)) | ||
require.Equal(t, false, p.Seen(root, idx+1)) | ||
|
||
// Add another attestation on the same data | ||
msg2 := ð.PayloadAttestationMessage{ | ||
Signature: bls.NewAggregateSignature().Marshal(), | ||
Data: att.Data, | ||
} | ||
idx2 := uint64(7) | ||
require.NoError(t, p.Add(msg2, idx2)) | ||
att = p.attestations[primitives.PAYLOAD_PRESENT] | ||
indices = att.AggregationBits.BitIndices() | ||
require.DeepEqual(t, []int{int(idx), int(idx2)}, indices) | ||
require.DeepNotEqual(t, att.Signature, msg.Signature) | ||
|
||
// Try again the same index | ||
require.NoError(t, p.Add(msg2, idx2)) | ||
att2 := p.attestations[primitives.PAYLOAD_PRESENT] | ||
indices = att.AggregationBits.BitIndices() | ||
require.DeepEqual(t, []int{int(idx), int(idx2)}, indices) | ||
require.DeepEqual(t, att, att2) | ||
|
||
// Test Seen | ||
require.Equal(t, true, p.Seen(root, idx2)) | ||
require.Equal(t, false, p.Seen(root, idx2+1)) | ||
|
||
// Add another payload status for a different payload status | ||
msg3 := ð.PayloadAttestationMessage{ | ||
Signature: bls.NewAggregateSignature().Marshal(), | ||
Data: ð.PayloadAttestationData{ | ||
BeaconBlockRoot: root[:], | ||
Slot: 1, | ||
PayloadStatus: primitives.PAYLOAD_WITHHELD, | ||
}, | ||
} | ||
idx3 := uint64(17) | ||
|
||
require.NoError(t, p.Add(msg3, idx3)) | ||
att3 := p.attestations[primitives.PAYLOAD_WITHHELD] | ||
indices3 := att3.AggregationBits.BitIndices() | ||
require.DeepEqual(t, []int{int(idx3)}, indices3) | ||
require.DeepEqual(t, singleSig, att3.Signature) | ||
|
||
// Add a different root | ||
root2 := [32]byte{'s'} | ||
msg.Data.BeaconBlockRoot = root2[:] | ||
require.NoError(t, p.Add(msg, idx)) | ||
require.Equal(t, root2, p.root) | ||
require.Equal(t, true, p.Seen(root2, idx)) | ||
require.Equal(t, false, p.Seen(root, idx)) | ||
att = p.attestations[primitives.PAYLOAD_PRESENT] | ||
indices = att.AggregationBits.BitIndices() | ||
require.DeepEqual(t, []int{int(idx)}, indices) | ||
} |
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
Oops, something went wrong.