Skip to content

Commit

Permalink
Add invalid post malfeasance
Browse files Browse the repository at this point in the history
  • Loading branch information
fasmat committed Aug 29, 2024
1 parent f5f96b9 commit 39883a2
Show file tree
Hide file tree
Showing 4 changed files with 552 additions and 0 deletions.
15 changes: 15 additions & 0 deletions activation/wire/malfeasance.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,21 @@ const (
MarriageATXIndex
)

type InitialPostTreeIndex uint64

const (
CommitmentATXIndex InitialPostTreeIndex = iota
InitialPostRootIndex
)

type NiPostTreeIndex uint64

const (
MembershipIndex NiPostTreeIndex = iota
ChallengeIndex
PostsRootIndex
)

// ProofType is an identifier for the type of proof that is encoded in the ATXProof.
type ProofType byte

Expand Down
205 changes: 205 additions & 0 deletions activation/wire/malfeasance_invalid_post.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
package wire

import (
"errors"
"fmt"

"github.com/spacemeshos/merkle-tree"

"github.com/spacemeshos/go-spacemesh/common/types"
"github.com/spacemeshos/go-spacemesh/signing"
)

//go:generate scalegen

// ProofInvalidPost is a proof that an ATXs with an invalid Post was published by a smesher.
//
// We are proofing the following:
// 1. The provided Post is invalid for the given SmesherID.
// 2. The ATX has a valid signature.
//
// For this we need additional information:
// 1. The initial ATX of the smesher for the Commitment ATX
// 2. The marriage ATX of the smesher in the case the smesher is part of an equivocation set.
type ProofInvalidPost struct {
InvalidPost InvalidATXPostProof
Commitment CommitmentProof

// TODO(mafa): add marriage ATX proof
}

var _ Proof = &ProofInvalidPost{}

func NewInvalidPostProof(atx, initialAtx *ActivationTxV2) (*ProofInvalidPost, error) {

Check warning on line 33 in activation/wire/malfeasance_invalid_post.go

View check run for this annotation

Codecov / codecov/patch

activation/wire/malfeasance_invalid_post.go#L33

Added line #L33 was not covered by tests
// TODO(mafa): implement
return nil, nil

Check warning on line 35 in activation/wire/malfeasance_invalid_post.go

View check run for this annotation

Codecov / codecov/patch

activation/wire/malfeasance_invalid_post.go#L35

Added line #L35 was not covered by tests
}

// Valid returns true if the proof is valid. It verifies that the two proofs have the same publish epoch, smesher ID,
// and a valid signature but different ATX IDs as well as that the provided merkle proofs are valid.
func (p ProofInvalidPost) Valid(edVerifier *signing.EdVerifier) (types.NodeID, error) {

Check warning on line 40 in activation/wire/malfeasance_invalid_post.go

View check run for this annotation

Codecov / codecov/patch

activation/wire/malfeasance_invalid_post.go#L40

Added line #L40 was not covered by tests
// TODO(mafa): implement
return types.EmptyNodeID, nil

Check warning on line 42 in activation/wire/malfeasance_invalid_post.go

View check run for this annotation

Codecov / codecov/patch

activation/wire/malfeasance_invalid_post.go#L42

Added line #L42 was not covered by tests
}

type CommitmentProof struct {
// ATXID is the ID of the ATX being proven. It is the merkle root from the contents of the ATX.
ATXID types.ATXID

// InitialPostRoot is the root of the initial PoST merkle tree.
InitialPostRoot types.Hash32

// InitialPostProof contains the merkle path from the root of the ATX merkle tree (ATXID) to the root of the
// InitialPost.
InitialPostProof []types.Hash32 `scale:"max=32"`

// CommitmentATX is the ATX that was used by the identity as their commitment ATX.
CommitmentATX types.ATXID

// Proof contains the merkle path from the root of the ATX merkle tree (ATXID) to the CommitmentATX field.
Proof []types.Hash32 `scale:"max=32"`

// SmesherID is the ID of the smesher that published the ATX.
SmesherID types.NodeID
// Signature is the signature of the ATXID by the smesher.
Signature types.EdSignature
}

// Valid returns no error if the proof is valid. It verifies that the signature is valid and that the merkle proofs
// are valid.
func (p CommitmentProof) Valid(edVerifier *signing.EdVerifier) error {
if !edVerifier.Verify(signing.ATX, p.SmesherID, p.ATXID.Bytes(), p.Signature) {
return errors.New("invalid signature")

Check warning on line 72 in activation/wire/malfeasance_invalid_post.go

View check run for this annotation

Codecov / codecov/patch

activation/wire/malfeasance_invalid_post.go#L70-L72

Added lines #L70 - L72 were not covered by tests
}

initialPostProof := make([][]byte, len(p.InitialPostProof))
for i, h := range p.InitialPostProof {
initialPostProof[i] = h.Bytes()

Check warning on line 77 in activation/wire/malfeasance_invalid_post.go

View check run for this annotation

Codecov / codecov/patch

activation/wire/malfeasance_invalid_post.go#L75-L77

Added lines #L75 - L77 were not covered by tests
}
ok, err := merkle.ValidatePartialTree(
[]uint64{uint64(InitialPostIndex)},
[][]byte{p.InitialPostRoot.Bytes()},
initialPostProof,
p.ATXID.Bytes(),
atxTreeHash,
)
if err != nil {
return fmt.Errorf("validate initial PoST proof: %w", err)

Check warning on line 87 in activation/wire/malfeasance_invalid_post.go

View check run for this annotation

Codecov / codecov/patch

activation/wire/malfeasance_invalid_post.go#L79-L87

Added lines #L79 - L87 were not covered by tests
}
if !ok {
return errors.New("invalid initial PoST proof")

Check warning on line 90 in activation/wire/malfeasance_invalid_post.go

View check run for this annotation

Codecov / codecov/patch

activation/wire/malfeasance_invalid_post.go#L89-L90

Added lines #L89 - L90 were not covered by tests
}

proof := make([][]byte, len(p.Proof))
for i, h := range p.Proof {
proof[i] = h.Bytes()

Check warning on line 95 in activation/wire/malfeasance_invalid_post.go

View check run for this annotation

Codecov / codecov/patch

activation/wire/malfeasance_invalid_post.go#L93-L95

Added lines #L93 - L95 were not covered by tests
}
ok, err = merkle.ValidatePartialTree(
[]uint64{uint64(CommitmentATXIndex)},
[][]byte{p.CommitmentATX.Bytes()},
proof,
p.InitialPostRoot.Bytes(),
atxTreeHash,
)
if err != nil {
return fmt.Errorf("validate commitment ATX proof: %w", err)

Check warning on line 105 in activation/wire/malfeasance_invalid_post.go

View check run for this annotation

Codecov / codecov/patch

activation/wire/malfeasance_invalid_post.go#L97-L105

Added lines #L97 - L105 were not covered by tests
}
if !ok {
return errors.New("invalid commitment ATX proof")

Check warning on line 108 in activation/wire/malfeasance_invalid_post.go

View check run for this annotation

Codecov / codecov/patch

activation/wire/malfeasance_invalid_post.go#L107-L108

Added lines #L107 - L108 were not covered by tests
}

return nil

Check warning on line 111 in activation/wire/malfeasance_invalid_post.go

View check run for this annotation

Codecov / codecov/patch

activation/wire/malfeasance_invalid_post.go#L111

Added line #L111 was not covered by tests
}

type InvalidATXPostProof struct {
// ATXID is the ID of the ATX being proven. It is the merkle root from the contents of the ATX.
ATXID types.ATXID

// NiPostsRoot is the root of the NiPoST merkle tree.
NiPostsRoot types.Hash32
// NiPostsProof contains the merkle path from the root of the ATX merkle tree (ATXID) to the Post field.
NiPostsProof []types.Hash32 `scale:"max=32"`

// Challenge for the NiPoST.
Challenge types.Hash32
// ChallengeProof contains the merkle path from the NiPostsRoot to the Challenge field.
ChallengeProof []types.Hash32 `scale:"max=32"`

// PostsRoot is the root of the PoST merkle tree.
PostsRoot types.Hash32
// PostsProof contains the merkle path from the NiPostsRoot to the PostsRoot field.
PostsProof []types.Hash32 `scale:"max=32"`

// TODO(mafa): include invalid post and merkle proof for it

// SmesherID is the ID of the smesher that published the ATX.
SmesherID types.NodeID
// Signature is the signature of the ATXID by the smesher.
Signature types.EdSignature
}

// Valid returns no error if the proof is valid. It verifies that the signature is valid, that the merkle proofs are
// and that the provided post is invalid.
func (p InvalidATXPostProof) Valid(edVerifier *signing.EdVerifier) error {
if !edVerifier.Verify(signing.ATX, p.SmesherID, p.ATXID.Bytes(), p.Signature) {
return errors.New("invalid signature")

Check warning on line 145 in activation/wire/malfeasance_invalid_post.go

View check run for this annotation

Codecov / codecov/patch

activation/wire/malfeasance_invalid_post.go#L143-L145

Added lines #L143 - L145 were not covered by tests
}

nipostsProof := make([][]byte, len(p.NiPostsProof))
for i, h := range p.NiPostsProof {
nipostsProof[i] = h.Bytes()

Check warning on line 150 in activation/wire/malfeasance_invalid_post.go

View check run for this annotation

Codecov / codecov/patch

activation/wire/malfeasance_invalid_post.go#L148-L150

Added lines #L148 - L150 were not covered by tests
}
ok, err := merkle.ValidatePartialTree(
[]uint64{uint64(NIPostsRootIndex)},
[][]byte{p.NiPostsRoot.Bytes()},
nipostsProof,
p.ATXID.Bytes(),
atxTreeHash,
)
if err != nil {
return fmt.Errorf("validate NiPoST root proof: %w", err)

Check warning on line 160 in activation/wire/malfeasance_invalid_post.go

View check run for this annotation

Codecov / codecov/patch

activation/wire/malfeasance_invalid_post.go#L152-L160

Added lines #L152 - L160 were not covered by tests
}
if !ok {
return errors.New("invalid NiPoST root proof")

Check warning on line 163 in activation/wire/malfeasance_invalid_post.go

View check run for this annotation

Codecov / codecov/patch

activation/wire/malfeasance_invalid_post.go#L162-L163

Added lines #L162 - L163 were not covered by tests
}

challengeProof := make([][]byte, len(p.ChallengeProof))
for i, h := range p.ChallengeProof {
challengeProof[i] = h.Bytes()

Check warning on line 168 in activation/wire/malfeasance_invalid_post.go

View check run for this annotation

Codecov / codecov/patch

activation/wire/malfeasance_invalid_post.go#L166-L168

Added lines #L166 - L168 were not covered by tests
}
ok, err = merkle.ValidatePartialTree(
[]uint64{uint64(ChallengeIndex)},
[][]byte{p.Challenge.Bytes()},
challengeProof,
p.NiPostsRoot.Bytes(),
atxTreeHash,
)
if err != nil {
return fmt.Errorf("validate NiPoST challenge proof: %w", err)

Check warning on line 178 in activation/wire/malfeasance_invalid_post.go

View check run for this annotation

Codecov / codecov/patch

activation/wire/malfeasance_invalid_post.go#L170-L178

Added lines #L170 - L178 were not covered by tests
}
if !ok {
return errors.New("invalid NiPoST challenge proof")

Check warning on line 181 in activation/wire/malfeasance_invalid_post.go

View check run for this annotation

Codecov / codecov/patch

activation/wire/malfeasance_invalid_post.go#L180-L181

Added lines #L180 - L181 were not covered by tests
}

postsProof := make([][]byte, len(p.PostsProof))
for i, h := range p.PostsProof {
postsProof[i] = h.Bytes()

Check warning on line 186 in activation/wire/malfeasance_invalid_post.go

View check run for this annotation

Codecov / codecov/patch

activation/wire/malfeasance_invalid_post.go#L184-L186

Added lines #L184 - L186 were not covered by tests
}
ok, err = merkle.ValidatePartialTree(
[]uint64{uint64(PostsRootIndex)},
[][]byte{p.PostsRoot.Bytes()},
postsProof,
p.NiPostsRoot.Bytes(),
atxTreeHash,
)
if err != nil {
return fmt.Errorf("validate PoST root proof: %w", err)

Check warning on line 196 in activation/wire/malfeasance_invalid_post.go

View check run for this annotation

Codecov / codecov/patch

activation/wire/malfeasance_invalid_post.go#L188-L196

Added lines #L188 - L196 were not covered by tests
}
if !ok {
return errors.New("invalid PoST root proof")

Check warning on line 199 in activation/wire/malfeasance_invalid_post.go

View check run for this annotation

Codecov / codecov/patch

activation/wire/malfeasance_invalid_post.go#L198-L199

Added lines #L198 - L199 were not covered by tests
}

// TODO(mafa): continue with validation of provided post

return nil

Check warning on line 204 in activation/wire/malfeasance_invalid_post.go

View check run for this annotation

Codecov / codecov/patch

activation/wire/malfeasance_invalid_post.go#L204

Added line #L204 was not covered by tests
}
Loading

0 comments on commit 39883a2

Please sign in to comment.