-
Notifications
You must be signed in to change notification settings - Fork 208
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
Startpost rpc #1312
Startpost rpc #1312
Changes from 5 commits
b2e72dc
67f1716
d0806a1
25b9364
0804d61
77860cf
4408fba
6debcd2
d0274f1
3717cde
ca14381
6f50b1e
359864d
e2c2db5
a5a8b77
152f8da
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,6 +6,7 @@ import ( | |
"github.com/spacemeshos/go-spacemesh/common" | ||
"github.com/spacemeshos/go-spacemesh/log" | ||
"github.com/spacemeshos/go-spacemesh/types" | ||
"sync" | ||
"sync/atomic" | ||
) | ||
|
||
|
@@ -36,7 +37,7 @@ func (provider *PoETNumberOfTickProvider) NumOfTicks() uint64 { | |
type NipstBuilder interface { | ||
BuildNIPST(challenge *common.Hash) (*types.NIPST, error) | ||
IsPostInitialized() bool | ||
InitializePost() (*types.PostProof, error) | ||
InitializePost(logicalDrive string, commitmentSize uint64) (*types.PostProof, error) | ||
} | ||
|
||
type IdStore interface { | ||
|
@@ -60,6 +61,12 @@ type BytesStore interface { | |
Get(key []byte) ([]byte, error) | ||
} | ||
|
||
const ( | ||
Idle = 1 | ||
InProgress = 2 | ||
Done = 3 | ||
) | ||
|
||
type Builder struct { | ||
nodeId types.NodeId | ||
coinbaseAccount address.Address | ||
|
@@ -80,6 +87,9 @@ type Builder struct { | |
started uint32 | ||
store BytesStore | ||
isSynced func() bool | ||
accountLock sync.RWMutex | ||
postInitLock sync.RWMutex | ||
initStatus int | ||
log log.Log | ||
} | ||
|
||
|
@@ -99,6 +109,7 @@ func NewBuilder(nodeId types.NodeId, coinbaseAccount address.Address, db ATXDBPr | |
finished: make(chan struct{}), | ||
isSynced: isSyncedFunc, | ||
store: store, | ||
initStatus: Idle, | ||
log: log, | ||
} | ||
} | ||
|
@@ -119,14 +130,6 @@ func (b *Builder) Stop() { | |
|
||
// loop is the main loop that tries to create an atx per tick received from the global clock | ||
func (b *Builder) loop() { | ||
// post is initialized here, consider moving it to another location. | ||
if !b.nipstBuilder.IsPostInitialized() { | ||
_, err := b.nipstBuilder.InitializePost() // TODO: add proof to first ATX | ||
if err != nil { | ||
b.log.Error("PoST initialization failed: %v", err) | ||
return | ||
} | ||
} | ||
err := b.loadChallenge() | ||
if err != nil { | ||
log.Info("challenge not loaded: %s", err) | ||
|
@@ -140,6 +143,13 @@ func (b *Builder) loop() { | |
b.log.Info("cannot create atx : not synced") | ||
break | ||
} | ||
b.postInitLock.RLock() | ||
initStat := b.initStatus | ||
b.postInitLock.RUnlock() | ||
if initStat != Done || !b.nipstBuilder.IsPostInitialized() { | ||
moshababo marked this conversation as resolved.
Show resolved
Hide resolved
|
||
b.log.Info("nipst is not initialized yet, not building nipst") | ||
moshababo marked this conversation as resolved.
Show resolved
Hide resolved
|
||
break | ||
} | ||
if b.working { | ||
break | ||
} | ||
|
@@ -222,6 +232,44 @@ func (b *Builder) buildNipstChallenge(epoch types.EpochId) error { | |
return nil | ||
} | ||
|
||
func (b *Builder) StartPost(rewardAddress address.Address, logicalDrive string, commitmentSize uint64) error { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Instead of |
||
b.SetCoinbaseAccount(rewardAddress) | ||
|
||
if !b.nipstBuilder.IsPostInitialized() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If post is already initialized, it should return an error. There's no reason for the endpoint to continue swallowing these requests without reporting anything back. |
||
b.postInitLock.Lock() | ||
if b.initStatus != Idle { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It might be worth to check for |
||
b.postInitLock.Unlock() | ||
return fmt.Errorf("attempted to start post when post already inited") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "inited" -> "initiated" ? |
||
} | ||
b.initStatus = InProgress | ||
go func() { | ||
_, err := b.nipstBuilder.InitializePost(logicalDrive, commitmentSize) // TODO: add proof to first ATX | ||
b.postInitLock.Lock() | ||
b.initStatus = Done | ||
b.postInitLock.Unlock() | ||
if err != nil { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You're checking the err after already setting up the status to Also, I don't think we should settle on just logging the error, because the call is intended to be async. |
||
b.log.Error("PoST initialization failed: %v", err) | ||
return | ||
} | ||
}() | ||
b.postInitLock.Unlock() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Any reason for not doing the unlock before launching the goroutine? |
||
} | ||
return nil | ||
} | ||
|
||
func (b *Builder) SetCoinbaseAccount(rewardAddress address.Address) { | ||
b.accountLock.Lock() | ||
b.coinbaseAccount = rewardAddress | ||
b.accountLock.Unlock() | ||
} | ||
|
||
func (b *Builder) getCoinbaseAccount() address.Address { | ||
b.accountLock.RLock() | ||
acc := b.coinbaseAccount | ||
b.accountLock.RUnlock() | ||
return acc | ||
} | ||
|
||
func (b Builder) getNipstKey() []byte { | ||
return []byte("nipst") | ||
} | ||
|
@@ -326,7 +374,7 @@ func (b *Builder) PublishActivationTx(epoch types.EpochId) error { | |
pubEpoch, len(view), view) | ||
} | ||
|
||
atx := types.NewActivationTxWithChallenge(*b.challenge, b.coinbaseAccount, activeSetSize, view, b.nipst) | ||
atx := types.NewActivationTxWithChallenge(*b.challenge, b.getCoinbaseAccount(), activeSetSize, view, b.nipst) | ||
|
||
b.log.With().Info("active ids seen for epoch", log.Uint64("pos_atx_epoch", uint64(posEpoch)), | ||
log.Uint32("view_cnt", activeSetSize)) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,6 +14,7 @@ import ( | |
"github.com/stretchr/testify/require" | ||
"sort" | ||
"testing" | ||
"time" | ||
) | ||
|
||
// ========== Vars / Consts ========== | ||
|
@@ -71,15 +72,20 @@ func (n *NetMock) Broadcast(id string, d []byte) error { | |
} | ||
|
||
type NipstBuilderMock struct { | ||
poetRef []byte | ||
buildNipstFunc func(challenge *common.Hash) (*types.NIPST, error) | ||
poetRef []byte | ||
buildNipstFunc func(challenge *common.Hash) (*types.NIPST, error) | ||
SleepTime int | ||
PostInitialized bool | ||
} | ||
|
||
func (np *NipstBuilderMock) IsPostInitialized() bool { | ||
return true | ||
return np.PostInitialized | ||
} | ||
|
||
func (np *NipstBuilderMock) InitializePost() (*types.PostProof, error) { | ||
func (np *NipstBuilderMock) InitializePost(logicalDrive string, commitmentSize uint64) (*types.PostProof, error) { | ||
if np.SleepTime != 0 { | ||
time.Sleep(time.Duration(np.SleepTime) * time.Millisecond) | ||
} | ||
return nil, nil | ||
} | ||
|
||
|
@@ -97,7 +103,7 @@ func (np *NipstErrBuilderMock) IsPostInitialized() bool { | |
return true | ||
} | ||
|
||
func (np *NipstErrBuilderMock) InitializePost() (*types.PostProof, error) { | ||
func (np *NipstErrBuilderMock) InitializePost(logicalDrive string, commitmentSize uint64) (*types.PostProof, error) { | ||
return nil, nil | ||
} | ||
|
||
|
@@ -432,7 +438,7 @@ func TestBuilder_NipstPublishRecovery(t *testing.T) { | |
coinbase := address.HexToAddress("0xaaa") | ||
net := &NetMock{} | ||
layers := &MeshProviderMock{} | ||
nipstBuilder := &NipstBuilderMock{} | ||
nipstBuilder := &NipstBuilderMock{PostInitialized: true} | ||
layersPerEpoch := uint16(10) | ||
lg := log.NewDefault(id.Key[:5]) | ||
db := NewMockDB() | ||
|
@@ -492,3 +498,28 @@ func TestBuilder_NipstPublishRecovery(t *testing.T) { | |
err = b.PublishActivationTx(3) | ||
assert.True(t, db.hadNone) | ||
} | ||
|
||
func TestStartPost(t *testing.T) { | ||
id := types.NodeId{"aaaaaa", []byte("bbbbb")} | ||
coinbase := address.HexToAddress("0xaaa") | ||
//net := &NetMock{} | ||
layers := &MeshProviderMock{} | ||
nipstBuilder := &NipstBuilderMock{PostInitialized: false} | ||
layersPerEpoch := uint16(10) | ||
lg := log.NewDefault(id.Key[:5]) | ||
|
||
drive := "/tmp/anton" | ||
coinbase2 := address.HexToAddress("0xabb") | ||
db := NewMockDB() | ||
activationDb := NewActivationDb(database.NewMemDatabase(), &MockIdStore{}, mesh.NewMemMeshDB(lg.WithName("meshDB")), layersPerEpoch, &ValidatorMock{}, lg.WithName("atxDB1")) | ||
b := NewBuilder(id, coinbase, activationDb, &FaultyNetMock{}, layers, layersPerEpoch, nipstBuilder, nil, func() bool { return true }, db, lg.WithName("atxBuilder")) | ||
|
||
nipstBuilder.SleepTime = 10000 | ||
err := b.StartPost(coinbase2, drive, 1000) | ||
assert.NoError(t, err) | ||
|
||
// negative test to run | ||
err = b.StartPost(coinbase2, drive, 1000) | ||
assert.Error(t, err) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It worth asserting the err msg, because it's not clear what failure you are testing here - an "InProgress" state or "Done" state. |
||
|
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
1 + iota ?