Skip to content

Commit c1b51a0

Browse files
committed
Don't decode ATX blob when fetching types.ActivationTx from DB (#5891)
## Motivation There is no need to decode the blob since types.ActivationTx only contains data available in `atxs` table.
1 parent 2ed4b55 commit c1b51a0

File tree

16 files changed

+109
-149
lines changed

16 files changed

+109
-149
lines changed

activation/activation.go

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -759,23 +759,6 @@ func (b *Builder) Regossip(ctx context.Context, nodeID types.NodeID) error {
759759
return nil
760760
}
761761

762-
// SignAndFinalizeAtx signs the atx with specified signer and calculates the ID of the ATX.
763-
// DO NOT USE for new code. This function is deprecated and will be removed.
764-
// The proper way to create an ATX in tests is to use the specific wire type and sign it.
765-
func SignAndFinalizeAtx(signer *signing.EdSigner, atx *types.ActivationTx) error {
766-
wireAtx := wire.ActivationTxToWireV1(atx)
767-
wireAtx.Signature = signer.Sign(signing.ATX, wireAtx.SignedBytes())
768-
wireAtx.SmesherID = signer.NodeID()
769-
atx.AtxBlob = types.AtxBlob{
770-
Version: types.AtxV1,
771-
Blob: codec.MustEncode(wireAtx),
772-
}
773-
atx.Signature = wireAtx.Signature
774-
atx.SmesherID = wireAtx.SmesherID
775-
atx.SetID(types.ATXID(wireAtx.HashInnerBytes()))
776-
return nil
777-
}
778-
779762
func buildNipostChallengeStartDeadline(roundStart time.Time, gracePeriod time.Duration) time.Time {
780763
jitter := randomDurationInRange(time.Duration(0), gracePeriod*maxNipostChallengeBuildJitter/100.0)
781764
return roundStart.Add(jitter).Add(-gracePeriod)

activation/handler.go

Lines changed: 47 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -373,7 +373,11 @@ func (h *Handler) cacheAtx(ctx context.Context, atx *types.ActivationTx, nonce t
373373
}
374374

375375
// storeAtx stores an ATX and notifies subscribers of the ATXID.
376-
func (h *Handler) storeAtx(ctx context.Context, atx *types.ActivationTx) (*mwire.MalfeasanceProof, error) {
376+
func (h *Handler) storeAtx(
377+
ctx context.Context,
378+
atx *types.ActivationTx,
379+
signature types.EdSignature,
380+
) (*mwire.MalfeasanceProof, error) {
377381
var nonce *types.VRFPostIndex
378382
malicious, err := h.cdb.IsMalicious(atx.SmesherID)
379383
if err != nil {
@@ -394,25 +398,35 @@ func (h *Handler) storeAtx(ctx context.Context, atx *types.ActivationTx) (*mwire
394398
}
395399

396400
// do ID check to be absolutely sure.
397-
if prev != nil && prev.ID() != atx.ID() {
401+
if err == nil && prev != atx.ID() {
398402
if _, ok := h.signers[atx.SmesherID]; ok {
399403
// if we land here we tried to publish 2 ATXs in the same epoch
400404
// don't punish ourselves but fail validation and thereby the handling of the incoming ATX
401405
return fmt.Errorf("%s already published an ATX in epoch %d", atx.SmesherID.ShortString(),
402406
atx.PublishEpoch,
403407
)
404408
}
409+
prevSignature, err := atxSignature(ctx, tx, prev)
410+
if err != nil {
411+
return fmt.Errorf("extracting signature for malfeasance proof: %w", err)
412+
}
405413

406-
var atxProof mwire.AtxProof
407-
for i, a := range []*types.ActivationTx{prev, atx} {
408-
atxProof.Messages[i] = mwire.AtxProofMsg{
414+
atxProof := mwire.AtxProof{
415+
Messages: [2]mwire.AtxProofMsg{{
409416
InnerMsg: types.ATXMetadata{
410-
PublishEpoch: a.PublishEpoch,
411-
MsgHash: a.ID().Hash32(),
417+
PublishEpoch: atx.PublishEpoch,
418+
MsgHash: prev.Hash32(),
412419
},
413-
SmesherID: a.SmesherID,
414-
Signature: a.Signature,
415-
}
420+
SmesherID: atx.SmesherID,
421+
Signature: prevSignature,
422+
}, {
423+
InnerMsg: types.ATXMetadata{
424+
PublishEpoch: atx.PublishEpoch,
425+
MsgHash: atx.ID().Hash32(),
426+
},
427+
SmesherID: atx.SmesherID,
428+
Signature: signature,
429+
}},
416430
}
417431
proof = &mwire.MalfeasanceProof{
418432
Layer: atx.PublishEpoch.FirstLayer(),
@@ -431,8 +445,8 @@ func (h *Handler) storeAtx(ctx context.Context, atx *types.ActivationTx) (*mwire
431445

432446
h.log.WithContext(ctx).With().Warning("smesher produced more than one atx in the same epoch",
433447
log.Stringer("smesher", atx.SmesherID),
434-
log.Object("prev", prev),
435-
log.Object("curr", atx),
448+
log.Stringer("previous", prev),
449+
log.Object("current", atx),
436450
)
437451
}
438452

@@ -619,7 +633,7 @@ func (h *Handler) processATX(
619633
atx.BaseTickHeight = baseTickHeight
620634
atx.TickCount = leaves / h.tickSize
621635

622-
proof, err = h.storeAtx(ctx, atx)
636+
proof, err = h.storeAtx(ctx, atx, watx.Signature)
623637
if err != nil {
624638
return nil, fmt.Errorf("cannot store atx %s: %w", atx.ShortString(), err)
625639
}
@@ -675,3 +689,23 @@ func collectAtxDeps(goldenAtxId types.ATXID, atx *wire.ActivationTxV1) (types.Ha
675689

676690
return types.BytesToHash(atx.NIPost.PostMetadata.Challenge), maps.Keys(filtered)
677691
}
692+
693+
// Obtain the atxSignature of the given ATX.
694+
func atxSignature(ctx context.Context, db sql.Executor, id types.ATXID) (types.EdSignature, error) {
695+
var blob sql.Blob
696+
if err := atxs.LoadBlob(ctx, db, id.Bytes(), &blob); err != nil {
697+
return types.EmptyEdSignature, err
698+
}
699+
700+
if blob.Bytes == nil {
701+
// An empty blob indicates a golden ATX (after a checkpoint-recovery).
702+
return types.EmptyEdSignature, fmt.Errorf("can't get signature for a golden (checkpointed) ATX: %s", id)
703+
}
704+
705+
// TODO: decide how to decode based on the `version` column.
706+
var prev wire.ActivationTxV1
707+
if err := codec.Decode(blob.Bytes, &prev); err != nil {
708+
return types.EmptyEdSignature, fmt.Errorf("decoding previous atx: %w", err)
709+
}
710+
return prev.Signature, nil
711+
}

activation/handler_test.go

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -712,13 +712,14 @@ func TestHandler_StoreAtx(t *testing.T) {
712712

713713
atxHdlr.mbeacon.EXPECT().OnAtx(vAtx.ToHeader())
714714
atxHdlr.mtortoise.EXPECT().OnAtx(gomock.Any(), vAtx.ID(), gomock.Any())
715-
proof, err := atxHdlr.storeAtx(context.Background(), vAtx)
715+
proof, err := atxHdlr.storeAtx(context.Background(), vAtx, watx.Signature)
716716
require.NoError(t, err)
717717
require.Nil(t, proof)
718718

719719
atxFromDb, err := atxs.Get(atxHdlr.cdb, vAtx.ID())
720720
require.NoError(t, err)
721721
vAtx.SetReceived(time.Unix(0, vAtx.Received().UnixNano()))
722+
vAtx.AtxBlob = types.AtxBlob{}
722723
require.Equal(t, vAtx, atxFromDb)
723724
})
724725

@@ -731,13 +732,13 @@ func TestHandler_StoreAtx(t *testing.T) {
731732

732733
atxHdlr.mbeacon.EXPECT().OnAtx(vAtx.ToHeader())
733734
atxHdlr.mtortoise.EXPECT().OnAtx(gomock.Any(), vAtx.ID(), gomock.Any())
734-
proof, err := atxHdlr.storeAtx(context.Background(), vAtx)
735+
proof, err := atxHdlr.storeAtx(context.Background(), vAtx, watx.Signature)
735736
require.NoError(t, err)
736737
require.Nil(t, proof)
737738

738739
atxHdlr.mbeacon.EXPECT().OnAtx(vAtx.ToHeader())
739740
// Note: tortoise is not informed about the same ATX again
740-
proof, err = atxHdlr.storeAtx(context.Background(), vAtx)
741+
proof, err = atxHdlr.storeAtx(context.Background(), vAtx, watx.Signature)
741742
require.NoError(t, err)
742743
require.Nil(t, proof)
743744
})
@@ -752,7 +753,7 @@ func TestHandler_StoreAtx(t *testing.T) {
752753
atxHdlr.mbeacon.EXPECT().OnAtx(vAtx0.ToHeader())
753754
atxHdlr.mtortoise.EXPECT().OnAtx(gomock.Any(), vAtx0.ID(), gomock.Any())
754755

755-
proof, err := atxHdlr.storeAtx(context.Background(), vAtx0)
756+
proof, err := atxHdlr.storeAtx(context.Background(), vAtx0, watx0.Signature)
756757
require.NoError(t, err)
757758
require.Nil(t, proof)
758759

@@ -765,7 +766,7 @@ func TestHandler_StoreAtx(t *testing.T) {
765766
atxHdlr.mtortoise.EXPECT().OnAtx(gomock.Any(), vAtx1.ID(), gomock.Any())
766767
atxHdlr.mtortoise.EXPECT().OnMalfeasance(sig.NodeID())
767768

768-
proof, err = atxHdlr.storeAtx(context.Background(), vAtx1)
769+
proof, err = atxHdlr.storeAtx(context.Background(), vAtx1, watx1.Signature)
769770
require.NoError(t, err)
770771
require.NotNil(t, proof)
771772
require.Equal(t, mwire.MultipleATXs, proof.Proof.Type)
@@ -798,7 +799,7 @@ func TestHandler_StoreAtx(t *testing.T) {
798799
atxHdlr.mbeacon.EXPECT().OnAtx(vAtx0.ToHeader())
799800
atxHdlr.mtortoise.EXPECT().OnAtx(gomock.Any(), vAtx0.ID(), gomock.Any())
800801

801-
proof, err := atxHdlr.storeAtx(context.Background(), vAtx0)
802+
proof, err := atxHdlr.storeAtx(context.Background(), vAtx0, watx0.Signature)
802803
require.NoError(t, err)
803804
require.Nil(t, proof)
804805

@@ -807,7 +808,7 @@ func TestHandler_StoreAtx(t *testing.T) {
807808
watx1.Sign(sig)
808809
vAtx1 := toAtx(t, watx1)
809810

810-
proof, err = atxHdlr.storeAtx(context.Background(), vAtx1)
811+
proof, err = atxHdlr.storeAtx(context.Background(), vAtx1, watx1.Signature)
811812
require.ErrorContains(t,
812813
err,
813814
fmt.Sprintf("%s already published an ATX", sig.NodeID().ShortString()),

activation/post_test.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,8 @@ func TestPostSetupManager_findCommitmentAtx_UsesLatestAtx(t *testing.T) {
277277
PublishEpoch: 1,
278278
}
279279
atx := types.NewActivationTx(challenge, types.Address{}, 2, nil)
280-
require.NoError(t, SignAndFinalizeAtx(signer, atx))
280+
atx.SmesherID = signer.NodeID()
281+
atx.SetID(types.RandomATXID())
281282
atx.SetReceived(time.Now())
282283
atx.TickCount = 1
283284
require.NoError(t, err)
@@ -323,7 +324,8 @@ func TestPostSetupManager_getCommitmentAtx_getsCommitmentAtxFromInitialAtx(t *te
323324
commitmentAtx := types.RandomATXID()
324325
atx := types.NewActivationTx(types.NIPostChallenge{}, types.Address{}, 1, nil)
325326
atx.CommitmentATX = &commitmentAtx
326-
require.NoError(t, SignAndFinalizeAtx(signer, atx))
327+
atx.SmesherID = signer.NodeID()
328+
atx.SetID(types.RandomATXID())
327329
atx.SetReceived(time.Now())
328330
atx.TickCount = 1
329331
require.NoError(t, atxs.Add(mgr.cdb, atx))

activation/wire/wire_v1.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,6 @@ func ActivationTxToWireV1(a *types.ActivationTx) *ActivationTxV1 {
162162
VRFNonce: (*uint64)(a.VRFNonce),
163163
},
164164
SmesherID: a.SmesherID,
165-
Signature: a.Signature,
166165
}
167166
}
168167

@@ -176,7 +175,6 @@ func ActivationTxFromWireV1(atx *ActivationTxV1, blob ...byte) *types.Activation
176175
NumUnits: atx.NumUnits,
177176
VRFNonce: (*types.VRFPostIndex)(atx.VRFNonce),
178177
SmesherID: atx.SmesherID,
179-
Signature: atx.Signature,
180178
AtxBlob: types.AtxBlob{
181179
Version: types.AtxV1,
182180
Blob: blob,

api/grpcserver/v2alpha1/activation.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,6 @@ func (s *ActivationStreamService) Stream(
154154
func toAtx(atx *types.ActivationTx) *spacemeshv2alpha1.ActivationV1 {
155155
return &spacemeshv2alpha1.ActivationV1{
156156
Id: atx.ID().Bytes(),
157-
Signature: atx.Signature.Bytes(),
158157
PublishEpoch: atx.PublishEpoch.Uint32(),
159158
PreviousAtx: atx.PrevATXID[:],
160159
Coinbase: atx.Coinbase.String(),

beacon/beacon_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ import (
1717
"go.uber.org/mock/gomock"
1818
"golang.org/x/sync/errgroup"
1919

20-
"github.com/spacemeshos/go-spacemesh/activation"
2120
"github.com/spacemeshos/go-spacemesh/beacon/metrics"
2221
"github.com/spacemeshos/go-spacemesh/beacon/weakcoin"
2322
"github.com/spacemeshos/go-spacemesh/common/types"
@@ -124,7 +123,8 @@ func createATX(
124123
)
125124

126125
atx.SetReceived(received)
127-
require.NoError(tb, activation.SignAndFinalizeAtx(sig, atx))
126+
atx.SmesherID = sig.NodeID()
127+
atx.SetID(types.RandomATXID())
128128
atx.TickCount = 1
129129
require.NoError(tb, atxs.Add(db, atx))
130130
return atx.ID()

blocks/generator_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import (
1515
"github.com/stretchr/testify/require"
1616
"go.uber.org/mock/gomock"
1717

18-
"github.com/spacemeshos/go-spacemesh/activation"
1918
"github.com/spacemeshos/go-spacemesh/atxsdata"
2019
"github.com/spacemeshos/go-spacemesh/blocks/mocks"
2120
"github.com/spacemeshos/go-spacemesh/common/types"
@@ -163,7 +162,8 @@ func createModifiedATXs(
163162
nil,
164163
)
165164
atx.SetReceived(time.Now())
166-
require.NoError(tb, activation.SignAndFinalizeAtx(signer, atx))
165+
atx.SmesherID = signer.NodeID()
166+
atx.SetID(types.RandomATXID())
167167
onAtx(atx)
168168
data.AddFromAtx(atx, 0, false)
169169
atxes = append(atxes, atx)

common/types/activation.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -168,9 +168,7 @@ type ActivationTx struct {
168168
BaseTickHeight uint64
169169
TickCount uint64
170170
VRFNonce *VRFPostIndex
171-
172-
SmesherID NodeID
173-
Signature EdSignature
171+
SmesherID NodeID
174172

175173
AtxBlob
176174

fetch/mesh_data_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import (
1313
"go.uber.org/mock/gomock"
1414
"golang.org/x/sync/errgroup"
1515

16-
"github.com/spacemeshos/go-spacemesh/activation"
1716
"github.com/spacemeshos/go-spacemesh/codec"
1817
"github.com/spacemeshos/go-spacemesh/common/types"
1918
"github.com/spacemeshos/go-spacemesh/datastore"
@@ -453,7 +452,8 @@ func genATXs(tb testing.TB, num uint32) []*types.ActivationTx {
453452
i,
454453
nil,
455454
)
456-
require.NoError(tb, activation.SignAndFinalizeAtx(sig, atx))
455+
atx.SmesherID = sig.NodeID()
456+
atx.SetID(types.RandomATXID())
457457
atxs = append(atxs, atx)
458458
}
459459
return atxs

malfeasance/wire/malfeasance_test.go

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,13 @@ func TestCodec_MultipleATXs(t *testing.T) {
2828

2929
var atxProof wire.AtxProof
3030
for i, a := range []*types.ActivationTx{a1, a2} {
31-
a.Signature = types.RandomEdSignature()
32-
a.SmesherID = types.RandomNodeID()
3331
atxProof.Messages[i] = wire.AtxProofMsg{
3432
InnerMsg: types.ATXMetadata{
3533
PublishEpoch: a.PublishEpoch,
36-
// MsgHash: types.Hash32(a.ToWireV1().HashInnerBytes()),
34+
MsgHash: types.RandomHash(),
3735
},
38-
SmesherID: a.SmesherID,
39-
Signature: a.Signature,
36+
SmesherID: types.RandomNodeID(),
37+
Signature: types.RandomEdSignature(),
4038
}
4139
}
4240
proof := &wire.MalfeasanceProof{

node/node.go

Lines changed: 0 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ import (
3636
"google.golang.org/grpc/keepalive"
3737

3838
"github.com/spacemeshos/go-spacemesh/activation"
39-
"github.com/spacemeshos/go-spacemesh/activation/wire"
4039
"github.com/spacemeshos/go-spacemesh/api/grpcserver"
4140
"github.com/spacemeshos/go-spacemesh/api/grpcserver/v2alpha1"
4241
"github.com/spacemeshos/go-spacemesh/atxsdata"
@@ -75,7 +74,6 @@ import (
7574
"github.com/spacemeshos/go-spacemesh/sql"
7675
"github.com/spacemeshos/go-spacemesh/sql/activesets"
7776
"github.com/spacemeshos/go-spacemesh/sql/atxs"
78-
"github.com/spacemeshos/go-spacemesh/sql/builder"
7977
"github.com/spacemeshos/go-spacemesh/sql/layers"
8078
"github.com/spacemeshos/go-spacemesh/sql/localsql"
8179
dbmetrics "github.com/spacemeshos/go-spacemesh/sql/metrics"
@@ -1948,48 +1946,6 @@ func (app *App) Start(ctx context.Context) error {
19481946
}
19491947
}
19501948

1951-
// verifyDB performs a verification of ATX signatures in the database.
1952-
//
1953-
//lint:ignore U1000 This function is currently unused but is left here for future use.
1954-
func (app *App) verifyDB(ctx context.Context) {
1955-
app.eg.Go(func() error {
1956-
app.log.Info("checking ATX signatures")
1957-
count := 0
1958-
1959-
// check ATX signatures
1960-
atxs.IterateAtxsOps(app.cachedDB, builder.Operations{}, func(atx *types.ActivationTx) bool {
1961-
select {
1962-
case <-ctx.Done():
1963-
// stop on context cancellation
1964-
return false
1965-
default:
1966-
}
1967-
1968-
// verify atx signature
1969-
// TODO: use atx handler to verify signature
1970-
if !app.edVerifier.Verify(
1971-
signing.ATX,
1972-
atx.SmesherID, wire.ActivationTxToWireV1(atx).SignedBytes(),
1973-
atx.Signature,
1974-
) {
1975-
app.log.With().Error("ATX signature verification failed",
1976-
log.Stringer("atx_id", atx.ID()),
1977-
log.Stringer("smesher", atx.SmesherID),
1978-
)
1979-
}
1980-
1981-
count++
1982-
if count%1000 == 0 {
1983-
app.log.With().Info("verifying ATX signatures", log.Int("count", count))
1984-
}
1985-
return true
1986-
})
1987-
1988-
app.log.With().Info("ATX signatures verified", log.Int("count", count))
1989-
return nil
1990-
})
1991-
}
1992-
19931949
func (app *App) startSynchronous(ctx context.Context) (err error) {
19941950
// notify anyone who might be listening that the app has finished starting.
19951951
// this can be used by, e.g., app tests.

0 commit comments

Comments
 (0)