Skip to content

Commit

Permalink
Bonds for Fortified DSMR (#1835)
Browse files Browse the repository at this point in the history
Signed-off-by: Joshua Kim <20001595+joshua-kim@users.noreply.github.com>
  • Loading branch information
joshua-kim authored Dec 23, 2024
1 parent 36fab89 commit c371a78
Show file tree
Hide file tree
Showing 8 changed files with 906 additions and 316 deletions.
12 changes: 11 additions & 1 deletion x/dsmr/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,11 +105,14 @@ func ParseChunk[T Tx](chunkBytes []byte) (Chunk[T], error) {
return c, c.init()
}

type Block struct {
type BlockHeader struct {
ParentID ids.ID `serialize:"true"`
Height uint64 `serialize:"true"`
Timestamp int64 `serialize:"true"`
}

type Block struct {
BlockHeader
ChunkCerts []*ChunkCertificate `serialize:"true"`

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

// ExecutedBlock contains block data with any referenced chunks reconstructed
type ExecutedBlock[T Tx] struct {
BlockHeader
ID ids.ID
Chunks []Chunk[T] `serialize:"true"`
}
28 changes: 28 additions & 0 deletions x/dsmr/dsmrtest/dsmr.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright (C) 2024, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.

package dsmrtest

import (
"github.com/ava-labs/avalanchego/ids"

"github.com/ava-labs/hypersdk/codec"
)

type Tx struct {
ID ids.ID `serialize:"true"`
Expiry int64 `serialize:"true"`
Sponsor codec.Address `serialize:"true"`
}

func (t Tx) GetID() ids.ID {
return t.ID
}

func (t Tx) GetExpiry() int64 {
return t.Expiry
}

func (t Tx) GetSponsor() codec.Address {
return t.Sponsor
}
63 changes: 42 additions & 21 deletions x/dsmr/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,9 +118,9 @@ func (n *Node[T]) BuildChunk(
txs []T,
expiry int64,
beneficiary codec.Address,
) (Chunk[T], ChunkCertificate, error) {
) error {
if len(txs) == 0 {
return Chunk[T]{}, ChunkCertificate{}, ErrEmptyChunk
return ErrEmptyChunk
}

chunk, err := signChunk[T](
Expand All @@ -136,7 +136,7 @@ func (n *Node[T]) BuildChunk(
n.Signer,
)
if err != nil {
return Chunk[T]{}, ChunkCertificate{}, fmt.Errorf("failed to sign chunk: %w", err)
return fmt.Errorf("failed to sign chunk: %w", err)
}

packer := wrappers.Packer{MaxSize: MaxMessageSize}
Expand All @@ -145,12 +145,12 @@ func (n *Node[T]) BuildChunk(
Producer: chunk.Producer,
Expiry: chunk.Expiry,
}, &packer); err != nil {
return Chunk[T]{}, ChunkCertificate{}, fmt.Errorf("failed to marshal chunk reference: %w", err)
return fmt.Errorf("failed to marshal chunk reference: %w", err)
}

unsignedMsg, err := warp.NewUnsignedMessage(n.networkID, n.chainID, packer.Bytes)
if err != nil {
return Chunk[T]{}, ChunkCertificate{}, fmt.Errorf("failed to initialize unsigned warp message: %w", err)
return fmt.Errorf("failed to initialize unsigned warp message: %w", err)
}
msg, err := warp.NewMessage(
unsignedMsg,
Expand All @@ -159,7 +159,7 @@ func (n *Node[T]) BuildChunk(
},
)
if err != nil {
return Chunk[T]{}, ChunkCertificate{}, fmt.Errorf("failed to initialize warp message: %w", err)
return fmt.Errorf("failed to initialize warp message: %w", err)
}

canonicalValidators, _, err := warp.GetCanonicalValidatorSet(
Expand All @@ -169,7 +169,7 @@ func (n *Node[T]) BuildChunk(
ids.Empty,
)
if err != nil {
return Chunk[T]{}, ChunkCertificate{}, fmt.Errorf("failed to get canonical validator set: %w", err)
return fmt.Errorf("failed to get canonical validator set: %w", err)
}

aggregatedMsg, _, _, ok, err := n.chunkSignatureAggregator.AggregateSignatures(
Expand All @@ -181,16 +181,16 @@ func (n *Node[T]) BuildChunk(
n.quorumDen,
)
if err != nil {
return Chunk[T]{}, ChunkCertificate{}, fmt.Errorf("failed to aggregate signatures: %w", err)
return fmt.Errorf("failed to aggregate signatures: %w", err)
}

if !ok {
return Chunk[T]{}, ChunkCertificate{}, ErrFailedToReplicate
return ErrFailedToReplicate
}

bitSetSignature, ok := aggregatedMsg.Signature.(*warp.BitSetSignature)
if !ok {
return Chunk[T]{}, ChunkCertificate{}, ErrInvalidSignatureType
return ErrInvalidSignatureType
}

chunkCert := ChunkCertificate{
Expand All @@ -204,17 +204,17 @@ func (n *Node[T]) BuildChunk(

packer = wrappers.Packer{MaxSize: MaxMessageSize}
if err := codec.LinearCodec.MarshalInto(&chunkCert, &packer); err != nil {
return Chunk[T]{}, ChunkCertificate{}, err
return err
}

if err := n.chunkCertificateGossipClient.AppGossip(
ctx,
&dsmr.ChunkCertificateGossip{ChunkCertificate: packer.Bytes},
); err != nil {
return Chunk[T]{}, ChunkCertificate{}, err
return err
}

return chunk, chunkCert, n.storage.AddLocalChunkWithCert(chunk, &chunkCert)
return n.storage.AddLocalChunkWithCert(chunk, &chunkCert)
}

func (n *Node[T]) BuildBlock(parent Block, timestamp int64) (Block, error) {
Expand All @@ -237,9 +237,11 @@ func (n *Node[T]) BuildBlock(parent Block, timestamp int64) (Block, error) {
}

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

Expand Down Expand Up @@ -298,12 +300,14 @@ func (n *Node[T]) Verify(ctx context.Context, parent Block, block Block) error {
return nil
}

func (n *Node[T]) Accept(ctx context.Context, block Block) error {
func (n *Node[T]) Accept(ctx context.Context, block Block) (ExecutedBlock[T], error) {
chunkIDs := make([]ids.ID, 0, len(block.ChunkCerts))
chunks := make([]Chunk[T], 0, len(block.ChunkCerts))

for _, chunkCert := range block.ChunkCerts {
chunkIDs = append(chunkIDs, chunkCert.ChunkID)

_, _, err := n.storage.GetChunkBytes(chunkCert.Expiry, chunkCert.ChunkID)
chunkBytes, _, err := n.storage.GetChunkBytes(chunkCert.Expiry, chunkCert.ChunkID)
if errors.Is(err, database.ErrNotFound) {
for {
result := make(chan error)
Expand All @@ -318,6 +322,8 @@ func (n *Node[T]) Accept(ctx context.Context, block Block) error {
result <- err
return
}

chunks = append(chunks, response)
}

// TODO better request strategy
Expand All @@ -331,22 +337,37 @@ func (n *Node[T]) Accept(ctx context.Context, block Block) error {
},
onResponse,
); err != nil {
return fmt.Errorf("failed to request chunk referenced in block: %w", err)
return ExecutedBlock[T]{}, fmt.Errorf("failed to request chunk referenced in block: %w", err)
}

if <-result == nil {
break
}
}
}

chunk, err := ParseChunk[T](chunkBytes)
if err != nil {
return ExecutedBlock[T]{}, fmt.Errorf("failed to parse chunk: %w", err)
}

chunks = append(chunks, chunk)
}

if err := n.storage.SetMin(block.Timestamp, chunkIDs); err != nil {
return fmt.Errorf("failed to prune chunks: %w", err)
return ExecutedBlock[T]{}, fmt.Errorf("failed to prune chunks: %w", err)
}

n.LastAccepted = block
return nil
return ExecutedBlock[T]{
BlockHeader: BlockHeader{
ParentID: block.ParentID,
Height: block.Height,
Timestamp: block.Timestamp,
},
ID: block.GetID(),
Chunks: chunks,
}, nil
}

type pChain struct {
Expand Down
Loading

0 comments on commit c371a78

Please sign in to comment.