Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

implemented mesh traversal for validation of active set #780

Merged
merged 12 commits into from Apr 10, 2019
91 changes: 48 additions & 43 deletions activation/activation.go
@@ -1,40 +1,39 @@
package activation

import (
"github.com/spacemeshos/go-spacemesh/common"
"github.com/spacemeshos/go-spacemesh/database"
"github.com/spacemeshos/go-spacemesh/log"
"github.com/spacemeshos/go-spacemesh/mesh"
"github.com/spacemeshos/go-spacemesh/miner"
"github.com/spacemeshos/go-spacemesh/nipst"
"github.com/spacemeshos/go-spacemesh/rand"
"github.com/spacemeshos/go-spacemesh/types"
)

type Network interface {
Broadcast(channel string, data []byte) error
}
const AtxProtocol = "AtxGossip"

var activesetCache = NewActivesetCache(1000)

type ActiveSetProvider interface {
GetActiveSetSize(l mesh.LayerID) uint32
GetActiveSetSize(l types.LayerID) uint32
}

type MeshProvider interface {
GetLatestView() []mesh.BlockID
LatestLayerId() mesh.LayerID
GetLatestView() []types.BlockID
LatestLayerId() types.LayerID
}

type EpochId uint64

func (l EpochId) ToBytes() []byte { return common.Uint64ToBytes(uint64(l)) }

type EpochProvider interface {
Epoch(l mesh.LayerID) EpochId
Epoch(l types.LayerID) types.EpochId
}

type Broadcaster interface {
Broadcast(channel string, data []byte) error
}

type Builder struct {
nodeId mesh.NodeId
nodeId types.NodeId
db *ActivationDb
net Network
net Broadcaster
activeSet ActiveSetProvider
mesh MeshProvider
epochProvider EpochProvider
Expand All @@ -45,56 +44,51 @@ type Processor struct {
epochProvider EpochProvider
}

func (p *Processor) ProcessBlockATXs(block *mesh.Block) {
for _, atx := range block.ATXs {
err := p.db.StoreAtx(p.epochProvider.Epoch(atx.LayerIndex), atx)
if err != nil {
log.Error("cannot store atx: %v", atx)
}
}
}

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

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

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

doesn't it make more sense to pass the atxID (and rename this GetSequence) instead of looking for the prevAtx again inside this method? Not a big deal, if you disagree.

if seq > 0 && prevAtx == nil {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

prevAtx can never be nil here.

log.Error("cannot find prev ATX for nodeid %v ", b.nodeId)
return err
}
seq++
}

l := b.mesh.LatestLayerId()
ech := b.epochProvider.Epoch(l)
var posAtx *mesh.AtxId = nil
var posAtx *types.AtxId = nil
if ech > 0 {
posAtx, err = b.GetPositioningAtxId(ech - 1)
if err != nil {
return err
}
} else {
posAtx = &mesh.EmptyAtx
}

if prevAtx == nil {
log.Info("previous ATX not found")
prevAtx = &mesh.EmptyAtx
posAtx = &types.EmptyAtx
}

atx := mesh.NewActivationTx(b.nodeId, seq+1, *prevAtx, l, 0, *posAtx, b.activeSet.GetActiveSetSize(l-1), b.mesh.GetLatestView(), nipst)
atx := types.NewActivationTx(b.nodeId, seq, *prevAtx, l, 0, *posAtx, b.activeSet.GetActiveSetSize(l-1), b.mesh.GetLatestView(), nipst)

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

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

if err != nil || len(ids) == 0 {
Expand All @@ -103,7 +97,7 @@ func (b *Builder) GetPrevAtxId(node mesh.NodeId) (*mesh.AtxId, error) {
return &ids[len(ids)-1], nil
}

func (b *Builder) GetPositioningAtxId(epochId EpochId) (*mesh.AtxId, error) {
func (b *Builder) GetPositioningAtxId(epochId types.EpochId) (*types.AtxId, error) {
atxs, err := b.db.GetEpochAtxIds(epochId)
if err != nil {
return nil, err
Expand All @@ -113,7 +107,7 @@ func (b *Builder) GetPositioningAtxId(epochId EpochId) (*mesh.AtxId, error) {
return &atxId, nil
}

func (b *Builder) GetLastSequence(node mesh.NodeId) uint64 {
func (b *Builder) GetLastSequence(node types.NodeId) uint64 {
atxId, err := b.GetPrevAtxId(node)
if err != nil {
return 0
Expand All @@ -125,3 +119,14 @@ func (b *Builder) GetLastSequence(node mesh.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
}*/
33 changes: 17 additions & 16 deletions activation/activation_test.go
Expand Up @@ -3,31 +3,33 @@ package activation
import (
"github.com/spacemeshos/go-spacemesh/common"
"github.com/spacemeshos/go-spacemesh/database"
"github.com/spacemeshos/go-spacemesh/log"
"github.com/spacemeshos/go-spacemesh/mesh"
"github.com/spacemeshos/go-spacemesh/nipst"
"github.com/spacemeshos/go-spacemesh/types"
"github.com/stretchr/testify/assert"
"testing"
)

type EchProvider struct{}

func (EchProvider) Epoch(l mesh.LayerID) EpochId {
return EpochId(l / 10)
func (EchProvider) Epoch(l types.LayerID) types.EpochId {
return types.EpochId(l / 10)
}

type ActiveSetProviderMock struct{}

func (ActiveSetProviderMock) GetActiveSetSize(l mesh.LayerID) uint32 {
func (ActiveSetProviderMock) GetActiveSetSize(l types.LayerID) uint32 {
return 10
}

type MeshProviderrMock struct{}

func (MeshProviderrMock) GetLatestView() []mesh.BlockID {
return []mesh.BlockID{1, 2, 3}
func (MeshProviderrMock) GetLatestView() []types.BlockID {
return []types.BlockID{1, 2, 3}
}

func (MeshProviderrMock) LatestLayerId() mesh.LayerID {
func (MeshProviderrMock) LatestLayerId() types.LayerID {
return 12
}

Expand All @@ -42,40 +44,39 @@ func (n *NetMock) Broadcast(id string, d []byte) error {

func TestBuilder_BuildActivationTx(t *testing.T) {
//todo: implement test
id := mesh.NodeId{"aaaa", []byte("bbb")}
id := types.NodeId{"aaaa", []byte("bbb")}
net := &NetMock{}
echp := &EchProvider{}
layers := MeshProviderrMock{}
b := NewBuilder(id, database.NewMemDatabase(), net, ActiveSetProviderMock{}, layers, echp)
b := NewBuilder(id, database.NewMemDatabase(), mesh.NewMemMeshDB(log.NewDefault("")), net, ActiveSetProviderMock{}, layers, echp, 10)
adb := b.db
prevAtx := mesh.AtxId{Hash: common.HexToHash("0x111")}
prevAtx := types.AtxId{Hash: common.HexToHash("0x111")}
npst := nipst.NIPST{}
atx := mesh.NewActivationTx(mesh.NodeId{"aaaa", []byte("bbb")},
atx := types.NewActivationTx(types.NodeId{"aaaa", []byte("bbb")},
1,
prevAtx,
5,
1,
prevAtx,
5,
[]mesh.BlockID{1, 2, 3},
[]types.BlockID{1, 2, 3},
&npst)
adb.StoreAtx(echp.Epoch(atx.LayerIndex), atx)
act := mesh.NewActivationTx(b.nodeId, b.GetLastSequence(b.nodeId)+1, atx.Id(), layers.LatestLayerId(), 0, atx.Id(), b.activeSet.GetActiveSetSize(1), b.mesh.GetLatestView(), &npst)
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{})
assert.NoError(t, err)
bts, err := mesh.AtxAsBytes(act)
bts, err := types.AtxAsBytes(act)
assert.NoError(t, err)
assert.Equal(t, bts, net.bt)
}

func TestBuilder_NoPrevATX(t *testing.T) {
//todo: implement test
id := mesh.NodeId{"aaaa", []byte("bbb")}
id := types.NodeId{"aaaa", []byte("bbb")}
net := &NetMock{}
echp := &EchProvider{}
layers := MeshProviderrMock{}
b := NewBuilder(id, database.NewMemDatabase(), net, ActiveSetProviderMock{}, layers, echp)
b := NewBuilder(id, database.NewMemDatabase(), mesh.NewMemMeshDB(log.NewDefault("")), net, ActiveSetProviderMock{}, layers, echp, 10)
err := b.PublishActivationTx(&nipst.NIPST{})
assert.Error(t, err)

}