Skip to content
Permalink
Browse files

Nipst struct creation with mocks (#662)

* added stubs for communication with poet and post server to build nipst

* after cr
  • Loading branch information...
antonlerner committed Mar 18, 2019
1 parent 6a50382 commit c70e6383d128996509cc2e4d204eb478f95aa8c4
Showing with 300 additions and 0 deletions.
  1. +230 −0 nipst/nipst_builder.go
  2. +70 −0 nipst/nipst_test.go
@@ -0,0 +1,230 @@
package nipst

import (
"github.com/spacemeshos/go-spacemesh/common"
"github.com/spacemeshos/go-spacemesh/log"
"sync"
"time"
)

//todo: decide what does the proof contain
type proof struct{}

type Round uint64

type postCommitment struct {
Root common.Hash
Proof proof
}

func (p *postCommitment) Valid() bool {
return true
}

//todo: figure out which fields are needed
type MembershipProof struct {
Root common.Hash
Proof proof
}

func (p *MembershipProof) Valid() bool {
return true
}

//todo: poet proof
type PoetProof struct {
Root common.Hash
Proof proof
}

func (p *PoetProof) Valid() bool {
return true
}

type PoetService interface {
SendPostProof(root common.Hash, p proof) (Round, error)
GetMembershipProof(rnd Round, root common.Hash, timeout time.Duration) (*MembershipProof, error)
Proof(rnd Round, root common.Hash, timeout time.Duration) (*PoetProof, error)
}

type PostService interface {
SendChallenge(root common.Hash, challenge common.Hash) error
ChallengeOutput(root common.Hash, challenge common.Hash, timeout time.Duration) (*postCommitment, error)
}

type ActivationBuilder interface {
BuildActivationTx(proof Nipst)
}

type Nipst struct {
initialPost *postCommitment
membershipProof *MembershipProof
poetProof *PoetProof
secondPost *postCommitment
round *Round
}

type NipstBuilder struct {
poet PoetService
post PostService
currentNipst Nipst
activationBuilder ActivationBuilder
stop bool
stopM sync.Mutex
}

func NewNipstBuilder(poet PoetService, post PostService, activationBuilder ActivationBuilder) *NipstBuilder {
return &NipstBuilder{
poet: poet,
post: post,
currentNipst: Nipst{},
activationBuilder: activationBuilder,
stop: false,
}
}

func (n *NipstBuilder) stopped() bool {
n.stopM.Lock()
defer n.stopM.Unlock()
return n.stop
}

func (n *NipstBuilder) Stop() {
n.stopM.Lock()
n.stop = true
defer n.stopM.Unlock()
}

func (n *NipstBuilder) Start() {
n.stopM.Lock()
n.stop = false
go n.loop()
defer n.stopM.Unlock()
}

func (n *NipstBuilder) loop() {
n.loadNipst()
postRoot, challenge := common.Hash{}, common.Hash{}

if n.currentNipst.initialPost == nil {
post := n.waitForPostChallenge(postRoot, challenge)

n.currentNipst.initialPost = post
n.persistNipst()
}
for {
if n.stopped() {
return
}
if n.currentNipst.membershipProof == nil {
membership := n.waitForMembershipProof(n.currentNipst.initialPost)
if !membership.Valid() {
log.Error("invalid membershipProof")
//todo: what to do when error?
continue
}
n.currentNipst.membershipProof = membership
n.persistNipst()
if n.stopped() {
return
}
}
if n.currentNipst.poetProof == nil {
poetProof := n.waitForPoetProof(n.currentNipst.membershipProof)
if !poetProof.Valid() {
log.Error("invalid poet proof")
continue
}
n.currentNipst.poetProof = poetProof
n.persistNipst()
if n.stopped() {
return
}
}
if n.currentNipst.secondPost == nil {
postRoot = n.currentNipst.initialPost.Root
challenge = n.currentNipst.poetProof.Root
post := n.waitForPostChallenge(postRoot, challenge)
if !post.Valid() {
log.Error("invalid second post")
continue
}
n.currentNipst.secondPost = post
n.activationBuilder.BuildActivationTx(n.currentNipst)

n.resetNipst()

if n.stopped() {
return
}
}
}
}

func (n *NipstBuilder) persistNipst() {
//todo: implement
}

func (n *NipstBuilder) loadNipst() {
//todo: implement
}

func (n *NipstBuilder) resetNipst() {
//set up all parameters as preparation for next iteration of creating nipst
n.currentNipst.initialPost = n.currentNipst.secondPost
n.currentNipst.membershipProof = nil
n.currentNipst.poetProof = nil
n.currentNipst.secondPost = nil
n.persistNipst()
}

func (n *NipstBuilder) waitForPostChallenge(root common.Hash, challenge common.Hash) *postCommitment {
for {
post, err := n.post.ChallengeOutput(root, challenge, 1*time.Second)
if n.stopped() {
return nil
}
if err != nil {
time.Sleep(1 * time.Second)
continue
}
return post
}
}

func (n *NipstBuilder) waitForMembershipProof(commitment *postCommitment) *MembershipProof {
log.Info("Sending post commitment %v to POET", commitment.Root)
round, err := n.poet.SendPostProof(commitment.Root, commitment.Proof)
if err != nil {
return nil
}
then := time.Now()
for {
proof, err := n.poet.GetMembershipProof(round, commitment.Root, 1*time.Second)
n.currentNipst.round = &round
if n.stopped() {
return nil
}
if err != nil {
time.Sleep(1 * time.Second)
continue
}
log.Info("Received %v proof from POET after %v ", commitment.Root, time.Since(then))
return proof
}
}

func (n *NipstBuilder) waitForPoetProof(m *MembershipProof) *PoetProof {
for {
proof, err := n.poet.Proof(*n.currentNipst.round, m.Root, 1*time.Second)
if n.stopped() {
return nil
}
if err != nil {
time.Sleep(1 * time.Minute)
continue
}
return proof
}

}
@@ -0,0 +1,70 @@
package nipst

import (
"github.com/spacemeshos/go-spacemesh/common"
"github.com/stretchr/testify/assert"
"testing"
"time"
)

type PoetMock struct {
membership *MembershipProof
poetP *PoetProof
}

type PostMock struct {
firstP *postCommitment
secondP *postCommitment
}

type ActivationMock struct {
nipst chan Nipst
}

func (a *ActivationMock) BuildActivationTx(proof Nipst) {
a.nipst <- proof
}

func (*PoetMock) SendPostProof(root common.Hash, p proof) (Round, error) {
return 0, nil
}
func (p *PoetMock) GetMembershipProof(rnd Round, root common.Hash, timeout time.Duration) (*MembershipProof, error) {
return p.membership, nil
}
func (p *PoetMock) Proof(rnd Round, root common.Hash, timeout time.Duration) (*PoetProof, error) {
return p.poetP, nil
}

func (*PostMock) SendChallenge(root common.Hash, challenge common.Hash) error {
return nil
}

func (p *PostMock) ChallengeOutput(root common.Hash, challenge common.Hash, timeout time.Duration) (*postCommitment, error) {
return p.firstP, nil
}

func TestNipstBuilder_Start(t *testing.T) {

}

func TestMembershipProof_loop(t *testing.T) {
nipst := Nipst{&postCommitment{}, &MembershipProof{}, &PoetProof{}, &postCommitment{}, nil}

poet := PoetMock{nipst.membershipProof, nipst.poetProof}
post := PostMock{nipst.initialPost, nipst.secondPost}
npstChan := make(chan Nipst)
activation := ActivationMock{npstChan}
builder := NewNipstBuilder(&poet, &post, &activation)
builder.Start()

timer := time.NewTimer(1 * time.Second)
select {
case recv := <-npstChan:
recv.round = nipst.round
assert.Equal(t, recv, nipst)
case <-timer.C:
t.Fail()
return
}
builder.Stop()
}

0 comments on commit c70e638

Please sign in to comment.
You can’t perform that action at this time.