Skip to content

Commit

Permalink
inverted control between nipst builder and atx builder (#806)
Browse files Browse the repository at this point in the history
* inverted control between nipst builder and atx builder

* added tests to poet challange builder

* fixed refactoring error

* validate nipst

* fix typo + refactor miss

* add cleanup and post init to nipst test

* nipst init post

* test validation failures

* update post

* added atx validation

* remove todo

Verified with @barakshani

* use EpochID where appropriate

* added positive and negative tests to flow

* after review and fmt

* fixed a ut

* go mod tidy
  • Loading branch information
antonlerner authored and noamnelke committed Apr 15, 2019
1 parent de9c0b8 commit 1c13cc1
Show file tree
Hide file tree
Showing 19 changed files with 841 additions and 387 deletions.
134 changes: 93 additions & 41 deletions activation/activation.go
@@ -1,6 +1,8 @@
package activation

import (
"fmt"
"github.com/davecgh/go-xdr/xdr"
"github.com/spacemeshos/go-spacemesh/database"
"github.com/spacemeshos/go-spacemesh/log"
"github.com/spacemeshos/go-spacemesh/mesh"
Expand Down Expand Up @@ -30,74 +32,135 @@ type Broadcaster interface {
Broadcast(channel string, data []byte) error
}

type PoETNumberOfTickProvider struct {
}

func (provider *PoETNumberOfTickProvider) NumOfTicks() uint64 {
return 0
}

type NipstBuilder interface {
BuildNIPST(challange []byte) (*nipst.NIPST, error)
}

type Builder struct {
nodeId types.NodeId
db *ActivationDb
net Broadcaster
activeSet ActiveSetProvider
mesh MeshProvider
epochProvider EpochProvider
nodeId types.NodeId
db *ActivationDb
net Broadcaster
activeSet ActiveSetProvider
mesh MeshProvider
epochProvider EpochProvider
layersPerEpoch uint64
tickProvider PoETNumberOfTickProvider
nipstBuilder NipstBuilder
}

type Processor struct {
db *ActivationDb
epochProvider EpochProvider
}

func NewBuilder(nodeId types.NodeId, db database.DB, meshdb *mesh.MeshDB, net Broadcaster, activeSet ActiveSetProvider, view MeshProvider, epochDuration EpochProvider, layersPerEpoch uint64) *Builder {
func NewBuilder(nodeId types.NodeId, db database.DB,
meshdb *mesh.MeshDB,
net Broadcaster,
activeSet ActiveSetProvider,
view MeshProvider,
epochDuration EpochProvider,
layersPerEpoch uint64,
nipstBuilder NipstBuilder) *Builder {
return &Builder{
nodeId, NewActivationDb(db, meshdb, layersPerEpoch), net, activeSet, view, epochDuration,
nodeId,
NewActivationDb(db, meshdb, layersPerEpoch),
net,
activeSet,
view,
epochDuration,
layersPerEpoch,
PoETNumberOfTickProvider{},
nipstBuilder,
}
}

func (b *Builder) PublishActivationTx(nipst *nipst.NIPST) error {
var seq uint64
func (b *Builder) PublishActivationTx(epoch types.EpochId) error {
prevAtx, err := b.GetPrevAtxId(b.nodeId)
if prevAtx == nil {
log.Info("previous ATX not found")
prevAtx = &types.EmptyAtx
seq = 0
} else {
seq = b.GetLastSequence(b.nodeId)
if seq > 0 && prevAtx == nil {
log.Error("cannot find prev ATX for nodeid %v ", b.nodeId)
seq := uint64(0)
if err == nil {
atx, err := b.db.GetAtx(*prevAtx)
if err != nil {
return err
}
seq++
seq = atx.Sequence + 1
} else {
prevAtx = &types.EmptyAtx
}

l := b.mesh.LatestLayerId()
ech := b.epochProvider.Epoch(l)
var posAtx *types.AtxId = nil
if ech > 0 {
posAtx, err = b.GetPositioningAtxId(ech - 1)
posAtxId := &types.EmptyAtx
endTick := uint64(0)
LayerIdx := b.mesh.LatestLayerId()
if epoch > 0 {
//positioning atx is from the last epoch
posAtxId, err = b.GetPositioningAtxId(epoch - 1)
if err != nil {
return err
}
} else {
posAtx = &types.EmptyAtx
posAtx, err := b.db.GetAtx(*posAtxId)
if err != nil {
return err
}
endTick = posAtx.EndTick
}

challenge := types.PoETChallenge{
NodeId: b.nodeId,
Sequence: seq,
PrevATXId: *prevAtx,
LayerIdx: types.LayerID(uint64(LayerIdx) + b.layersPerEpoch),
StartTick: endTick,
EndTick: b.tickProvider.NumOfTicks(), //todo: add provider when
PositioningAtx: *posAtxId,
}

atx := types.NewActivationTx(b.nodeId, seq, *prevAtx, l, 0, *posAtx, b.activeSet.GetActiveSetSize(l-1), b.mesh.GetLatestView(), nipst)
bytes, err := xdr.Marshal(challenge)
if err != nil {
return err
}
npst, err := b.nipstBuilder.BuildNIPST(bytes)
if err != nil {
return err
}
//todo: check if view should be latest layer -1
atx := types.NewActivationTxWithcChallenge(challenge, b.activeSet.GetActiveSetSize(b.mesh.LatestLayerId()-1), b.mesh.GetLatestView(), npst)

buf, err := types.AtxAsBytes(atx)
if err != nil {
return err
}
//todo: should we do something about it? wait for something?
return b.net.Broadcast(AtxProtocol, buf)

}

func (b *Builder) Persist(c *types.PoETChallenge) {
//todo: implement storing to persistent media
}

func (b *Builder) Load() *types.PoETChallenge {
//todo: implement loading from persistent media
return nil
}

func (b *Builder) GetPrevAtxId(node types.NodeId) (*types.AtxId, error) {
ids, err := b.db.GetNodeAtxIds(node)

if err != nil || len(ids) == 0 {
if err != nil {
return nil, err
}
if len(ids) == 0 {
return nil, fmt.Errorf("no prev atxs for node %v", node.Key)
}
return &ids[len(ids)-1], nil
}

func (b *Builder) GetPositioningAtxId(epochId types.EpochId) (*types.AtxId, error) {
//todo: make this on blocking until an atx is received
atxs, err := b.db.GetEpochAtxIds(epochId)
if err != nil {
return nil, err
Expand All @@ -119,14 +182,3 @@ func (b *Builder) GetLastSequence(node types.NodeId) uint64 {
}
return atx.Sequence
}

/*func (m *Mesh) UniqueAtxs(lyr *Layer) map[*ActivationTx]struct{} {
atxMap := make(map[*ActivationTx]struct{})
for _, blk := range lyr.blocks {
for _, atx := range blk.ATXs {
atxMap[atx] = struct{}{}
}
}
return atxMap
}*/
87 changes: 81 additions & 6 deletions activation/activation_test.go
@@ -1,6 +1,8 @@
package activation

import (
"fmt"
"github.com/davecgh/go-xdr/xdr"
"github.com/spacemeshos/go-spacemesh/common"
"github.com/spacemeshos/go-spacemesh/database"
"github.com/spacemeshos/go-spacemesh/log"
Expand Down Expand Up @@ -42,13 +44,29 @@ func (n *NetMock) Broadcast(id string, d []byte) error {
return nil
}

type NipstBuilderMock struct {
Challenge []byte
}

func (np *NipstBuilderMock) BuildNIPST(challange []byte) (*nipst.NIPST, error) {
np.Challenge = challange
return &nipst.NIPST{}, nil
}

type NipstErrBuilderMock struct{}

func (np *NipstErrBuilderMock) BuildNIPST(challange []byte) (*nipst.NIPST, error) {
return nil, fmt.Errorf("error")
}

func TestBuilder_BuildActivationTx(t *testing.T) {
//todo: implement test
id := types.NodeId{"aaaa", []byte("bbb")}
net := &NetMock{}
echp := &EchProvider{}
layers := MeshProviderrMock{}
b := NewBuilder(id, database.NewMemDatabase(), mesh.NewMemMeshDB(log.NewDefault("")), net, ActiveSetProviderMock{}, layers, echp, 10)
layersPerEpcoh := types.LayerID(10)
b := NewBuilder(id, database.NewMemDatabase(), mesh.NewMemMeshDB(log.NewDefault("")), net, ActiveSetProviderMock{}, layers, echp, 10, &NipstBuilderMock{})
adb := b.db
prevAtx := types.AtxId{Hash: common.HexToHash("0x111")}
npst := nipst.NIPST{}
Expand All @@ -61,9 +79,9 @@ func TestBuilder_BuildActivationTx(t *testing.T) {
5,
[]types.BlockID{1, 2, 3},
&npst)
adb.StoreAtx(echp.Epoch(atx.LayerIndex), atx)
act := types.NewActivationTx(b.nodeId, b.GetLastSequence(b.nodeId)+1, atx.Id(), layers.LatestLayerId(), 0, atx.Id(), b.activeSet.GetActiveSetSize(1), b.mesh.GetLatestView(), &npst)
err := b.PublishActivationTx(&nipst.NIPST{})
adb.StoreAtx(echp.Epoch(atx.LayerIdx), atx)
act := types.NewActivationTx(b.nodeId, b.GetLastSequence(b.nodeId)+1, atx.Id(), layers.LatestLayerId()+layersPerEpcoh, 0, atx.Id(), b.activeSet.GetActiveSetSize(1), b.mesh.GetLatestView(), &npst)
err := b.PublishActivationTx(types.EpochId(layers.LatestLayerId() / layersPerEpcoh))
assert.NoError(t, err)
bts, err := types.AtxAsBytes(act)
assert.NoError(t, err)
Expand All @@ -76,7 +94,64 @@ func TestBuilder_NoPrevATX(t *testing.T) {
net := &NetMock{}
echp := &EchProvider{}
layers := MeshProviderrMock{}
b := NewBuilder(id, database.NewMemDatabase(), mesh.NewMemMeshDB(log.NewDefault("")), net, ActiveSetProviderMock{}, layers, echp, 10)
err := b.PublishActivationTx(&nipst.NIPST{})
b := NewBuilder(id, database.NewMemDatabase(), mesh.NewMemMeshDB(log.NewDefault("")), net, ActiveSetProviderMock{}, layers, echp, 10, &NipstBuilderMock{})
err := b.PublishActivationTx(1)
assert.Error(t, err)
}

func TestBuilder_PublishActivationTx(t *testing.T) {
id := types.NodeId{"aaaa", []byte("bbb")}
net := &NetMock{}
echp := &EchProvider{}
layers := MeshProviderrMock{}
nipstBuilder := &NipstBuilderMock{}
layersPerEpcoh := uint64(10)
b := NewBuilder(id, database.NewMemDatabase(), mesh.NewMemMeshDB(log.NewDefault("")), net, ActiveSetProviderMock{}, layers, echp, layersPerEpcoh, nipstBuilder)
adb := b.db
prevAtx := types.AtxId{Hash: common.HexToHash("0x111")}
npst := nipst.NIPST{}

atx := types.NewActivationTx(types.NodeId{"aaaa", []byte("bbb")},
1,
prevAtx,
5,
1,
prevAtx,
5,
[]types.BlockID{1, 2, 3},
&npst)

err := adb.StoreAtx(echp.Epoch(types.LayerID(uint64(atx.LayerIdx)/layersPerEpcoh)), atx)
assert.NoError(t, err)

challenge := types.PoETChallenge{
NodeId: b.nodeId,
Sequence: b.GetLastSequence(b.nodeId) + 1,
PrevATXId: atx.Id(),
LayerIdx: types.LayerID(uint64(layers.LatestLayerId()) + b.layersPerEpoch),
StartTick: atx.EndTick,
EndTick: b.tickProvider.NumOfTicks(), //todo: add provider when
PositioningAtx: atx.Id(),
}

bytes, err := xdr.Marshal(challenge)
assert.NoError(t, err)

act := types.NewActivationTx(b.nodeId, b.GetLastSequence(b.nodeId)+1, atx.Id(), layers.LatestLayerId()+10, 0, atx.Id(), b.activeSet.GetActiveSetSize(1), b.mesh.GetLatestView(), &npst)
err = b.PublishActivationTx(1)
assert.NoError(t, err)
bts, err := types.AtxAsBytes(act)
assert.NoError(t, err)
assert.Equal(t, bts, net.bt)
assert.Equal(t, bytes, nipstBuilder.Challenge)

b.nipstBuilder = &NipstErrBuilderMock{}
err = b.PublishActivationTx(echp.Epoch(1))
assert.Error(t, err)
assert.Equal(t, err.Error(), "error")

bt := NewBuilder(id, database.NewMemDatabase(), mesh.NewMemMeshDB(log.NewDefault("")), net, ActiveSetProviderMock{}, layers, echp, layersPerEpcoh, &NipstBuilderMock{})
err = bt.PublishActivationTx(1)
assert.Error(t, err)

}

0 comments on commit 1c13cc1

Please sign in to comment.