Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/develop' into malfeasance-v2-fou…
Browse files Browse the repository at this point in the history
…ndations
  • Loading branch information
fasmat committed Aug 6, 2024
2 parents 07eadb2 + dc5fcaf commit 15c9a4e
Show file tree
Hide file tree
Showing 21 changed files with 568 additions and 84 deletions.
6 changes: 6 additions & 0 deletions activation/e2e/checkpoint_merged_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,12 @@ func Test_CheckpointAfterMerge(t *testing.T) {
require.Equal(t, i, marriage.Index)
}

checkpointedMerged, err := atxs.Get(newDB, mergedATX.ID())
require.NoError(t, err)
require.True(t, checkpointedMerged.Golden())
require.NotNil(t, checkpointedMerged.MarriageATX)
require.Equal(t, marriageATX.ID(), *checkpointedMerged.MarriageATX)

// 4. Spawn new ATX handler and builder using the new DB
poetDb = activation.NewPoetDb(newDB, logger.Named("poetDb"))
cdb = datastore.NewCachedDB(newDB, logger)
Expand Down
80 changes: 79 additions & 1 deletion activation/handler_v2.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ func (h *HandlerV2) processATX(

atx := &types.ActivationTx{
PublishEpoch: watx.PublishEpoch,
MarriageATX: watx.MarriageATX,
Coinbase: watx.Coinbase,
BaseTickHeight: baseTickHeight,
NumUnits: parts.effectiveUnits,
Expand Down Expand Up @@ -661,6 +662,7 @@ func (h *HandlerV2) checkMalicious(
tx *sql.Tx,
watx *wire.ActivationTxV2,
marrying []marriage,
ids []types.NodeID,
) error {
malicious, err := identities.IsMalicious(tx, watx.SmesherID)
if err != nil {
Expand All @@ -678,6 +680,22 @@ func (h *HandlerV2) checkMalicious(
return nil
}

malicious, err = h.checkDoublePost(ctx, tx, watx, ids)
if err != nil {
return fmt.Errorf("checking double post: %w", err)
}
if malicious {
return nil
}

malicious, err = h.checkDoubleMerge(ctx, tx, watx)
if err != nil {
return fmt.Errorf("checking double merge: %w", err)
}
if malicious {
return nil
}

// TODO(mafa): contextual validation:
// 1. check double-publish = ID contributed post to two ATXs in the same epoch
// 2. check previous ATX
Expand Down Expand Up @@ -722,6 +740,66 @@ func (h *HandlerV2) checkDoubleMarry(
return false, nil
}

func (h *HandlerV2) checkDoublePost(
ctx context.Context,
tx *sql.Tx,
atx *wire.ActivationTxV2,
ids []types.NodeID,
) (bool, error) {
for _, id := range ids {
atxids, err := atxs.FindDoublePublish(tx, id, atx.PublishEpoch)
switch {
case errors.Is(err, sql.ErrNotFound):
continue
case err != nil:
return false, fmt.Errorf("searching for double publish: %w", err)
}
otherAtxId := slices.IndexFunc(atxids, func(other types.ATXID) bool { return other != atx.ID() })
otherAtx := atxids[otherAtxId]
h.logger.Debug(
"found ID that has already contributed its PoST in this epoch",
zap.Stringer("node_id", id),
zap.Stringer("atx_id", atx.ID()),
zap.Stringer("other_atx_id", otherAtx),
zap.Uint32("epoch", atx.PublishEpoch.Uint32()),
)
// TODO(mafa): finish proof
proof := &wire.ATXProof{
ProofType: wire.DoublePublish,
}
return true, h.malPublisher.Publish(ctx, id, proof)
}
return false, nil
}

func (h *HandlerV2) checkDoubleMerge(ctx context.Context, tx *sql.Tx, watx *wire.ActivationTxV2) (bool, error) {
if watx.MarriageATX == nil {
return false, nil
}
ids, err := atxs.MergeConflict(tx, *watx.MarriageATX, watx.PublishEpoch)
switch {
case errors.Is(err, sql.ErrNotFound):
return false, nil
case err != nil:
return false, fmt.Errorf("searching for ATXs with the same marriage ATX: %w", err)
}
otherIndex := slices.IndexFunc(ids, func(id types.ATXID) bool { return id != watx.ID() })
other := ids[otherIndex]

h.logger.Debug("second merged ATX for single marriage - creating malfeasance proof",
zap.Stringer("marriage_atx", *watx.MarriageATX),
zap.Stringer("atx", watx.ID()),
zap.Stringer("other_atx", other),
zap.Stringer("smesher_id", watx.SmesherID),
)

// TODO(mafa): finish proof
proof := &wire.ATXProof{
ProofType: wire.DoubleMerge,
}
return true, h.malPublisher.Publish(ctx, watx.SmesherID, proof)
}

// Store an ATX in the DB.
func (h *HandlerV2) storeAtx(
ctx context.Context,
Expand Down Expand Up @@ -769,7 +847,7 @@ func (h *HandlerV2) storeAtx(
// TODO(mafa): don't store own ATX if it would mark the node as malicious
// this probably needs to be done by validating and storing own ATXs eagerly and skipping validation in
// the gossip handler (not sync!)
err := h.checkMalicious(ctx, tx, watx, marrying)
err := h.checkMalicious(ctx, tx, watx, marrying, maps.Keys(units))
if err != nil {
return fmt.Errorf("check malicious: %w", err)
}
Expand Down
Loading

0 comments on commit 15c9a4e

Please sign in to comment.