Skip to content

Commit

Permalink
Merge pull request #351 from iotaledger/chore/encode-attestations-by-…
Browse files Browse the repository at this point in the history
…version

Encode each attestation by version when sending over the wire
  • Loading branch information
alexsporn authored Sep 19, 2023
2 parents 83057da + 89433c5 commit 8241799
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 12 deletions.
51 changes: 40 additions & 11 deletions pkg/network/protocols/core/protocol.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package core

import (
"encoding/binary"
"encoding/json"

"github.com/libp2p/go-libp2p/core/peer"
Expand All @@ -14,6 +15,7 @@ import (
"github.com/iotaledger/hive.go/runtime/options"
"github.com/iotaledger/hive.go/runtime/syncutils"
"github.com/iotaledger/hive.go/runtime/workerpool"
"github.com/iotaledger/hive.go/serializer/v2/marshalutil"
"github.com/iotaledger/hive.go/serializer/v2/serix"
"github.com/iotaledger/iota-core/pkg/model"
"github.com/iotaledger/iota-core/pkg/network"
Expand Down Expand Up @@ -73,16 +75,16 @@ func (p *Protocol) SendSlotCommitment(cm *model.Commitment, to ...peer.ID) {
}

func (p *Protocol) SendAttestations(cm *model.Commitment, attestations []*iotago.Attestation, merkleProof *merklehasher.Proof[iotago.Identifier], to ...peer.ID) {
var iotagoAPI iotago.API
if len(attestations) > 0 {
// TODO: there are multiple attestations potentially spanning multiple epochs/versions, we need to use the correct API for each one
iotagoAPI = lo.PanicOnErr(p.apiProvider.APIForVersion(attestations[0].ProtocolVersion))
} else {
iotagoAPI = p.apiProvider.APIForSlot(cm.Index()) // we need an api to serialize empty slices as well
encodedAttestations := marshalutil.New()
encodedAttestations.WriteUint32(uint32(len(attestations)))
for _, att := range attestations {
iotagoAPI := lo.PanicOnErr(p.apiProvider.APIForVersion(att.ProtocolVersion))
encodedAttestations.WriteBytes(lo.PanicOnErr(iotagoAPI.Encode(att)))
}

p.network.Send(&nwmodels.Packet{Body: &nwmodels.Packet_Attestations{Attestations: &nwmodels.Attestations{
Commitment: cm.Data(),
Attestations: lo.PanicOnErr(iotagoAPI.Encode(attestations)),
Attestations: encodedAttestations.Bytes(),
MerkleProof: lo.PanicOnErr(json.Marshal(merkleProof)),
}}}, to...)
}
Expand Down Expand Up @@ -200,10 +202,37 @@ func (p *Protocol) onAttestations(commitmentBytes []byte, attestationsBytes []by
return
}

var attestations []*iotago.Attestation
// TODO: there could be multiple versions of attestations in the same packet
if _, err := lo.PanicOnErr(p.apiProvider.APIForVersion(iotago.Version(commitmentBytes[0]))).Decode(attestationsBytes, &attestations, serix.WithValidation()); err != nil {
p.Events.Error.Trigger(ierrors.Wrap(err, "failed to deserialize attestations"), id)
if len(attestationsBytes) < 4 {
p.Events.Error.Trigger(ierrors.Errorf("failed to deserialize attestations, invalid attestation count"), id)

return
}

attestationCount := binary.LittleEndian.Uint32(attestationsBytes[0:4])
readOffset := 4
attestations := make([]*iotago.Attestation, attestationCount)
for i := uint32(0); i < attestationCount; i++ {
version := iotago.Version(attestationsBytes[readOffset])
apiForVersion, err := p.apiProvider.APIForVersion(version)
if err != nil {
p.Events.Error.Trigger(ierrors.Wrapf(err, "failed to deserialize attestations for commitment %s", cm.ID()), id)

return
}

attestation := new(iotago.Attestation)
consumed, err := apiForVersion.Decode(attestationsBytes[readOffset:], attestation, serix.WithValidation())
if err != nil {
p.Events.Error.Trigger(ierrors.Wrap(err, "failed to deserialize attestations"), id)

return
}

readOffset += consumed
attestations[i] = attestation
}
if readOffset != len(attestationsBytes) {
p.Events.Error.Trigger(ierrors.Errorf("failed to deserialize attestations: %d bytes remaining", len(attestationsBytes)-readOffset), id)

return
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/protocol/protocol_fork.go
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ func (p *Protocol) processFork(fork *chainmanager.Fork) (anchorBlockIDs iotago.B

result, err := p.requestAttestation(ctx, fork.ForkedChain.Commitment(i).ID(), fork.Source, ch)
if err != nil {
return nil, false, true, ierrors.Wrapf(err, "failed to verify commitment %s", result.commitment.ID())
return nil, false, true, ierrors.Wrapf(err, "failed to verify commitment %s", fork.ForkedChain.Commitment(i).ID())
}

// Count how many consecutive slots are heavier/lighter than the main chain.
Expand Down

0 comments on commit 8241799

Please sign in to comment.