Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generalize expiry based de-duplication, dsmr #1810

Merged
merged 80 commits into from
Jan 15, 2025
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
80 commits
Select commit Hold shift + click to select a range
e5ecf69
eliminate emapChunk
tsachiherman Nov 22, 2024
ba644c3
update
tsachiherman Nov 22, 2024
2939543
update
tsachiherman Nov 25, 2024
08f0d59
Merge branch 'main' into tsachi/refactor_validity_window3
tsachiherman Nov 25, 2024
659f1fb
update per CR
tsachiherman Nov 25, 2024
921b908
lint
tsachiherman Nov 25, 2024
508cc92
apply requested changes.
tsachiherman Nov 25, 2024
7a3fed6
fix code + test.
tsachiherman Nov 25, 2024
b312a3c
rollback unneeded changes.
tsachiherman Nov 25, 2024
1238460
rename testing chain indexer.
tsachiherman Nov 25, 2024
8c1ab98
update
tsachiherman Nov 25, 2024
f8e42a8
add unit test.
tsachiherman Nov 26, 2024
b000edf
update unit test.
tsachiherman Nov 26, 2024
1d2536e
Merge branch 'main' into tsachi/refactor_validity_window3
tsachiherman Nov 27, 2024
6911f26
lint
tsachiherman Nov 27, 2024
f2816e7
update
tsachiherman Nov 28, 2024
e78f847
lint
tsachiherman Nov 28, 2024
270245a
update
tsachiherman Nov 28, 2024
144ddd4
Merge branch 'main' into tsachi/refactor_validity_window3
tsachiherman Dec 5, 2024
2fa701d
fix few CR feedback.
tsachiherman Dec 5, 2024
2220b5e
add certSet
tsachiherman Dec 6, 2024
39905b9
remove type declaration block.
tsachiherman Dec 6, 2024
d54e1a0
fix tests
tsachiherman Dec 6, 2024
8e83b6d
update
tsachiherman Dec 6, 2024
fdd4639
update
tsachiherman Dec 6, 2024
9e127f1
update
tsachiherman Dec 9, 2024
0f3fe73
create a wrapper for the block in dsmr (#1829)
tsachiherman Dec 9, 2024
fc87f31
update
tsachiherman Dec 10, 2024
cf82891
update
tsachiherman Dec 10, 2024
864acc1
updatge
tsachiherman Dec 10, 2024
d96160e
fix typo
tsachiherman Dec 10, 2024
9ea09b4
undo unwanted changes
tsachiherman Dec 10, 2024
30bcdce
update
tsachiherman Dec 10, 2024
8d52c05
update
tsachiherman Dec 10, 2024
32207b9
update unit test
tsachiherman Dec 12, 2024
5d62af7
update test
tsachiherman Dec 12, 2024
7ca779b
update
tsachiherman Dec 12, 2024
383a7ef
update
tsachiherman Dec 12, 2024
7902a6a
update per review feedback,.
tsachiherman Dec 13, 2024
1f143ea
address feedback.
tsachiherman Dec 19, 2024
6d4f94c
update per cr
tsachiherman Dec 20, 2024
dd419bb
Merge branch 'main' into tsachi/refactor_validity_window3
tsachiherman Dec 20, 2024
c87b033
update
tsachiherman Dec 23, 2024
293c6b9
Merge branch 'tsachi/refactor_validity_window3' of github.com:ava-lab…
tsachiherman Dec 23, 2024
b501cec
update per CR feedback.
tsachiherman Dec 23, 2024
68603db
update per CR
tsachiherman Dec 23, 2024
7e72626
update per feedback.
tsachiherman Dec 23, 2024
7edef6e
update
tsachiherman Dec 23, 2024
185fbf0
Merge branch 'main' into tsachi/refactor_validity_window3
tsachiherman Dec 23, 2024
9759244
Merge branch 'main' into tsachi/refactor_validity_window3
tsachiherman Jan 7, 2025
44a0e8a
initialize chunkCerts during NewValidityWindowBlock
tsachiherman Jan 7, 2025
6b8692f
update
tsachiherman Jan 9, 2025
a43f23a
update
tsachiherman Jan 9, 2025
b4b9267
Merge branch 'main' into tsachi/refactor_validity_window3
tsachiherman Jan 9, 2025
4fe3602
pin rust toolset to use 1.83.0 for now.
tsachiherman Jan 9, 2025
b900fd1
update
tsachiherman Jan 9, 2025
962cb57
update
tsachiherman Jan 9, 2025
745fea9
update
tsachiherman Jan 9, 2025
aad23ac
Merge branch 'main' into tsachi/refactor_validity_window3
tsachiherman Jan 9, 2025
3540422
undo unneeded changes.
tsachiherman Jan 9, 2025
84157c2
Merge branch 'main' into tsachi/refactor_validity_window3
tsachiherman Jan 10, 2025
58ed219
Merge branch 'main' into tsachi/refactor_validity_window3
tsachiherman Jan 13, 2025
8f243b2
update testing
tsachiherman Jan 13, 2025
69c6996
Merge branch 'tsachi/refactor_validity_window3' of github.com:ava-lab…
tsachiherman Jan 13, 2025
2e879bc
Merge branch 'main' into tsachi/refactor_validity_window3
tsachiherman Jan 13, 2025
43d5d4c
update
tsachiherman Jan 13, 2025
c088d7e
update
tsachiherman Jan 13, 2025
fd641ae
lint
tsachiherman Jan 13, 2025
2db87c4
update
tsachiherman Jan 13, 2025
fa3fc67
lint
tsachiherman Jan 13, 2025
c513464
rollback few unneeded empty lines
tsachiherman Jan 14, 2025
4dfe80b
address CR feedback.
tsachiherman Jan 14, 2025
f56f017
lint
tsachiherman Jan 14, 2025
919e852
Update internal/validitywindow/validitywindow_test.go
tsachiherman Jan 15, 2025
e0a910c
Update internal/validitywindow/validitywindow_test.go
tsachiherman Jan 15, 2025
b0f1782
remove unit test
tsachiherman Jan 15, 2025
7f21c2b
Merge branch 'main' into tsachi/refactor_validity_window3
tsachiherman Jan 15, 2025
23219b0
remove the testing for duplicate containerid from chain.ExecutionBlock
tsachiherman Jan 15, 2025
081381b
Merge branch 'tsachi/refactor_validity_window3' of github.com:ava-lab…
tsachiherman Jan 15, 2025
3f81853
update
tsachiherman Jan 15, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion chain/processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ func NewExecutionBlock(block *StatelessBlock) (*ExecutionBlock, error) {
}, nil
}

func (b *ExecutionBlock) ContainsTx(id ids.ID) bool {
func (b *ExecutionBlock) Contains(id ids.ID) bool {
return b.txsSet.Contains(id)
}

Expand Down
2 changes: 1 addition & 1 deletion internal/validitywindow/dependencies.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ type ExecutionBlock[Container emap.Item] interface {
Timestamp() int64
Height() uint64
Txs() []Container
ContainsTx(ids.ID) bool
Contains(ids.ID) bool
}

type ChainIndex[Container emap.Item] interface {
Expand Down
12 changes: 11 additions & 1 deletion internal/validitywindow/validitywindow.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"fmt"
"sync"

"github.com/ava-labs/avalanchego/ids"
"github.com/ava-labs/avalanchego/trace"
"github.com/ava-labs/avalanchego/utils/logging"
"github.com/ava-labs/avalanchego/utils/set"
Expand Down Expand Up @@ -69,6 +70,15 @@ func (v *TimeValidityWindow[Container]) VerifyExpiryReplayProtection(
if dup.Len() > 0 {
return fmt.Errorf("%w: duplicate in ancestry", ErrDuplicateContainer)
}
// make sure we have no repeats within the block itself.
blkTxsIDs := make(map[ids.ID]bool, len(blk.Txs()))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we use set.Set here?

for _, tx := range blk.Txs() {
id := tx.GetID()
if _, has := blkTxsIDs[id]; has {
return fmt.Errorf("%w: duplicate in block", ErrDuplicateContainer)
}
blkTxsIDs[id] = true
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We do this check twice now in chain since we previously handled this within NewExecutionBlock

We should only apply the check once, which do you think is the better place for it? The other addition within NewExecutionBlock is pre-populating the signature job. It would probably be better to remove that from the execution block and handle it in AsyncVerify. One good reason to do this is that handling this within ParseBlock can be a DoS vector.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see why testing this twice is an issue on it's own, and I think that I have a better solution here;
Testing it in NewExecutionBlock is not ideal from my perspective, as it should be construction step ( i.e. no errors ).
How do you feel about the following:
in ExecutionBlock, we would add the following function:

func (b *ExecutionBlock) ValidateDuplicateTransactions() error {
    if len(b.Txs) != b.txsSet.Len() {
        ErrDuplicateTx
    }
    return nil

than in validitywindow.go VerifyExpiryReplayProtection, we can just call this method:

   ...
   if err := blk.ValidateDuplicateTransactions(); err != nil {
      return err
   }
   ...

and remove the test from NewExecutionBlock

return nil
}

Expand Down Expand Up @@ -110,7 +120,7 @@ func (v *TimeValidityWindow[Container]) isRepeat(
if marker.Contains(i) {
continue
}
if ancestorBlk.ContainsTx(tx.GetID()) {
if ancestorBlk.Contains(tx.GetID()) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same comment on tx.GetID() here

marker.Add(i)
if stop {
return marker, nil
Expand Down
2 changes: 1 addition & 1 deletion x/dsmr/assembler.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ func (b *BlockHandler[T, S, B, R]) Accept(ctx context.Context, block *Block) err
}

// Assemble and execute the block
innerBlock, result, state, err := b.Assembler.AssembleBlock(ctx, b.lastAcceptedState, b.lastAcceptedBlock, block.Timestamp, block.Height+1, txs)
innerBlock, result, state, err := b.Assembler.AssembleBlock(ctx, b.lastAcceptedState, b.lastAcceptedBlock, block.Tmstmp, block.Hght+1, txs)
if err != nil {
return err
}
Expand Down
43 changes: 38 additions & 5 deletions x/dsmr/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@ import (

"github.com/ava-labs/hypersdk/codec"
"github.com/ava-labs/hypersdk/consts"
"github.com/ava-labs/hypersdk/internal/emap"
"github.com/ava-labs/hypersdk/utils"
)

const InitialChunkSize = 250 * 1024

type Tx interface {
GetID() ids.ID
GetExpiry() int64
emap.Item
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This exposes the internal/emap package into the caller. I think the previous wrapping pattern where we wrapped this interface w/ a type that implemented the emap interface actually looked cleaner.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

once merged, we won't need wrapping interface anymore. . unless I'm missing something ?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think @joshua-kim 's point is to have the internal type implemented as makes sense in this package and then wrap it with another type that converts between that structure and the required interface when we need to use it in the validity window or expiry map where we need a specific interface. Correct me if I'm wrong @joshua-kim

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

GetSponsor() codec.Address
}

Expand Down Expand Up @@ -51,6 +51,14 @@ func (c *Chunk[T]) init() error {
return nil
}

func (c Chunk[T]) GetID() ids.ID {
return c.id
}

func (c Chunk[T]) GetExpiry() int64 {
return c.Expiry
}

func signChunk[T Tx](
chunk UnsignedChunk[T],
networkID uint32,
Expand Down Expand Up @@ -106,9 +114,9 @@ func ParseChunk[T Tx](chunkBytes []byte) (Chunk[T], error) {
}

type Block struct {
ParentID ids.ID `serialize:"true"`
Height uint64 `serialize:"true"`
Timestamp int64 `serialize:"true"`
ParentID ids.ID `serialize:"true"`
Hght uint64 `serialize:"true"`
Tmstmp int64 `serialize:"true"`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I dislike us naming fields like this because of the interface signature we're trying to implement... is there a way we can get around this?


ChunkCerts []*ChunkCertificate `serialize:"true"`

Expand All @@ -119,3 +127,28 @@ type Block struct {
func (b Block) GetID() ids.ID {
return b.blkID
}

func (b Block) Parent() ids.ID {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't care which we pick, but we should be consistent on the naming of either Foo() or GetFoo().

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm going to dodge this one by saying that this method is no longer needed.

return b.ParentID
}

func (b Block) Timestamp() int64 {
return b.Tmstmp
}

func (b Block) Height() uint64 {
return b.Hght
}

func (b Block) Txs() []*ChunkCertificate {
return b.ChunkCerts
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems weird because these are not returning txs

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, I agree. let's discuss this as a group ?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we use the term containers?


func (b Block) Contains(id ids.ID) bool {
for _, c := range b.ChunkCerts {
if c.ChunkID == id {
return true
}
}
return false
}
aaronbuchwald marked this conversation as resolved.
Show resolved Hide resolved
5 changes: 3 additions & 2 deletions x/dsmr/certificate.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ type ChunkCertificate struct {
Signature NoVerifyChunkSignature `serialize:"true"`
}

func (c *ChunkCertificate) GetChunkID() ids.ID { return c.ChunkID }
func (c ChunkCertificate) GetID() ids.ID { return c.ChunkID }
func (c ChunkCertificate) GetExpiry() int64 { return c.Expiry }

func (c *ChunkCertificate) GetSlot() int64 { return c.Expiry }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think these are duplicated - GetSlot is meant to be Expiry


Expand Down Expand Up @@ -209,7 +210,7 @@ func ParseWarpChunkCertificate(b []byte) (*WarpChunkCertificate, error) {
}, nil
}

func (c *WarpChunkCertificate) GetChunkID() ids.ID { return c.UnsignedCertificate.ChunkID() }
func (c *WarpChunkCertificate) GetID() ids.ID { return c.UnsignedCertificate.ChunkID() }

func (c *WarpChunkCertificate) GetSlot() int64 { return c.UnsignedCertificate.Slot() }

Expand Down
105 changes: 77 additions & 28 deletions x/dsmr/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,31 @@ import (
"github.com/ava-labs/avalanchego/ids"
"github.com/ava-labs/avalanchego/network/p2p"
"github.com/ava-labs/avalanchego/network/p2p/acp118"
"github.com/ava-labs/avalanchego/trace"
"github.com/ava-labs/avalanchego/utils/crypto/bls"
"github.com/ava-labs/avalanchego/utils/logging"
"github.com/ava-labs/avalanchego/utils/wrappers"
"github.com/ava-labs/avalanchego/vms/platformvm/warp"

"github.com/ava-labs/hypersdk/codec"
"github.com/ava-labs/hypersdk/consts"
"github.com/ava-labs/hypersdk/internal/validitywindow"
"github.com/ava-labs/hypersdk/proto/pb/dsmr"
"github.com/ava-labs/hypersdk/utils"
)

var (
ErrEmptyChunk = errors.New("empty chunk")
ErrNoAvailableChunkCerts = errors.New("no available chunk certs")
ErrAllChunkCertsDuplicate = errors.New("all chunk certs are duplicated")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is there a specific error type to all chunk certs being duplicated? Shouldn't the verification fail if any chunk cert is a duplicate?

Also I don't think this error type is used

ErrTimestampNotMonotonicallyIncreasing = errors.New("block timestamp must be greater than parent timestamp")
)

type (
ChainIndex = validitywindow.ChainIndex[*ChunkCertificate]
timeValidityWindow = *validitywindow.TimeValidityWindow[*ChunkCertificate]
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like we're doing this to avoid the caller depending on an internal package. I'm wondering if it even makes sense for validitywindow to be in internal at all... should this just be merged into dsmr?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@aaronbuchwald asked to remove this section completely.


type Validator struct {
NodeID ids.NodeID
Weight uint64
Expand All @@ -46,6 +55,10 @@ func New[T Tx](
getChunkSignatureClient *p2p.Client,
chunkCertificateGossipClient *p2p.Client,
validators []Validator,
log logging.Logger,
tracer trace.Tracer,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: make these (logger + tracer) the first args in this fn

chainIndex ChainIndex,
validityWindowDuration int64,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we use time.Duration here?

) (*Node[T], error) {
storage, err := newChunkStorage[T](NoVerifier[T]{}, memdb.New())
if err != nil {
Expand Down Expand Up @@ -79,26 +92,36 @@ func New[T Tx](
ChunkCertificateGossipHandler: &ChunkCertificateGossipHandler[T]{
storage: storage,
},
storage: storage,
storage: storage,
log: log,
tracer: tracer,
validityWindow: validitywindow.NewTimeValidityWindow(log, tracer, chainIndex),
validityWindowDuration: validityWindowDuration,
}, nil
}

type Node[T Tx] struct {
nodeID ids.NodeID
networkID uint32
chainID ids.ID
pk *bls.PublicKey
signer warp.Signer
getChunkClient *TypedClient[*dsmr.GetChunkRequest, Chunk[T], []byte]
getChunkSignatureClient *TypedClient[*dsmr.GetChunkSignatureRequest, *dsmr.GetChunkSignatureResponse, []byte]
chunkCertificateGossipClient *TypedClient[[]byte, []byte, *dsmr.ChunkCertificateGossip]
validators []Validator

GetChunkHandler *GetChunkHandler[T]
GetChunkSignatureHandler *acp118.Handler
ChunkCertificateGossipHandler *ChunkCertificateGossipHandler[T]
storage *chunkStorage[T]
}
type (
Node[T Tx] struct {
nodeID ids.NodeID
networkID uint32
chainID ids.ID
pk *bls.PublicKey
signer warp.Signer
getChunkClient *TypedClient[*dsmr.GetChunkRequest, Chunk[T], []byte]
getChunkSignatureClient *TypedClient[*dsmr.GetChunkSignatureRequest, *dsmr.GetChunkSignatureResponse, []byte]
chunkCertificateGossipClient *TypedClient[[]byte, []byte, *dsmr.ChunkCertificateGossip]
validators []Validator
validityWindow timeValidityWindow

GetChunkHandler *GetChunkHandler[T]
GetChunkSignatureHandler *acp118.Handler
ChunkCertificateGossipHandler *ChunkCertificateGossipHandler[T]
storage *chunkStorage[T]
log logging.Logger
tracer trace.Tracer
validityWindowDuration int64
}
)
aaronbuchwald marked this conversation as resolved.
Show resolved Hide resolved

// BuildChunk builds transactions into a Chunk
// TODO handle frozen sponsor + validator assignments
Expand Down Expand Up @@ -172,29 +195,40 @@ func (n *Node[T]) BuildChunk(
return chunk, n.storage.AddLocalChunkWithCert(chunk, &chunkCert)
}

func (n *Node[T]) BuildBlock(parent Block, timestamp int64) (Block, error) {
if timestamp <= parent.Timestamp {
func (n *Node[T]) BuildBlock(ctx context.Context, parent Block, timestamp int64) (Block, error) {
if timestamp <= parent.Tmstmp {
return Block{}, ErrTimestampNotMonotonicallyIncreasing
}

chunkCerts := n.storage.GatherChunkCerts()
oldestAllowed := timestamp - n.validityWindowDuration
if oldestAllowed < 0 {
oldestAllowed = 0
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: min(0, oldestAllowed)

dup, err := n.validityWindow.IsRepeat(ctx, parent, chunkCerts, oldestAllowed)
if err != nil {
return Block{}, err
}

availableChunkCerts := make([]*ChunkCertificate, 0)
for _, chunkCert := range chunkCerts {
// avoid building blocks with expired chunk certs
if chunkCert.Expiry < timestamp {
for i, chunkCert := range chunkCerts {
// avoid building blocks with duplicate or expired chunk certs
if chunkCert.Expiry < timestamp || dup.Contains(i) {
continue
}

availableChunkCerts = append(availableChunkCerts, chunkCert)
}
if len(availableChunkCerts) == 0 {
if dup.Len() == len(chunkCerts) && len(chunkCerts) > 0 {
return Block{}, ErrAllChunkCertsDuplicate
}
return Block{}, ErrNoAvailableChunkCerts
aaronbuchwald marked this conversation as resolved.
Show resolved Hide resolved
}

blk := Block{
ParentID: parent.GetID(),
Height: parent.Height + 1,
Timestamp: timestamp,
Hght: parent.Hght + 1,
Tmstmp: timestamp,
ChunkCerts: availableChunkCerts,
}

Expand All @@ -208,9 +242,22 @@ func (n *Node[T]) BuildBlock(parent Block, timestamp int64) (Block, error) {
return blk, nil
}

func (*Node[T]) Execute(ctx context.Context, _ Block, block Block) error {
func (n *Node[T]) Execute(ctx context.Context, parentBlock Block, block Block) error {
// TODO: Verify header fields
// TODO: de-duplicate chunk certificates (internal to block and across history)
if block.Tmstmp <= parentBlock.Tmstmp && parentBlock.Hght > 0 {
return ErrTimestampNotMonotonicallyIncreasing
}

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we remove this check from this PR?

We should enforce timestamp >= parent timestamp (should allow them to be equal in case a block builder pushes the timestamp ahead of wall clock time for some nodes.

We should not allow the case that a malicious node builds a block with a timestamp that we consider valid less than 1s ahead of our wall clock time, but still ahead of our wall clock time, such that when we build a block on top of it, we fail because the current timestamp is ahead of our local timestamp.

We should update the check applied in BuildBlock imo.

We should also never execute the genesis block, so the check for parentBlock.Hght > 0 should be removed.

// Find repeats

oldestAllowed := block.Timestamp() - n.validityWindowDuration
if oldestAllowed < 0 {
oldestAllowed = 0
}
if err := n.validityWindow.VerifyExpiryReplayProtection(ctx, block, oldestAllowed); err != nil {
return err
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should be wrapping this error to check for the duplicate case in tests

}

for _, chunkCert := range block.ChunkCerts {
// TODO: verify chunks within a provided context
if err := chunkCert.Verify(ctx, struct{}{}); err != nil {
Expand Down Expand Up @@ -263,6 +310,8 @@ func (n *Node[T]) Accept(ctx context.Context, block Block) error {
}
}
}
// update the validity window with the accepted block.
n.validityWindow.Accept(block)

return n.storage.SetMin(block.Timestamp, chunkIDs)
return n.storage.SetMin(block.Tmstmp, chunkIDs)
}
Loading
Loading