Skip to content

Commit

Permalink
Merge pull request #93 from spacemeshos/intialize-initializer-on-new
Browse files Browse the repository at this point in the history
Initializer has correct state on New
  • Loading branch information
fasmat authored Dec 11, 2022
2 parents 7b87ae7 + 8b67b9b commit f3ec621
Show file tree
Hide file tree
Showing 7 changed files with 124 additions and 73 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@ require (
github.com/klauspost/cpuid/v2 v2.1.1 // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
golang.org/x/sys v0.2.0 // indirect
golang.org/x/sys v0.3.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A=
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ=
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
Expand Down
38 changes: 20 additions & 18 deletions initialization/initialization.go
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ func NewInitializer(opts ...OptionFunc) (*Initializer, error) {
return nil, err
}

return &Initializer{
init := &Initializer{
cfg: *options.cfg,
opts: *options.initOpts,
nodeId: options.nodeId,
Expand All @@ -200,34 +200,39 @@ func NewInitializer(opts ...OptionFunc) (*Initializer, error) {
diskState: NewDiskState(options.initOpts.DataDir, uint(options.cfg.BitsPerLabel)),
logger: options.logger,
powDifficultyFunc: options.powDifficultyFunc,
}, nil
}
}

// Initialize is the process in which the prover commits to store some data, by having its storage filled with
// pseudo-random data with respect to a specific id. This data is the result of a computationally-expensive operation.
func (init *Initializer) Initialize(ctx context.Context) error {
if !init.mtx.TryLock() {
return ErrAlreadyInitializing
numLabelsWritten, err := init.diskState.NumLabelsWritten()
if err != nil {
return nil, err
}
defer init.mtx.Unlock()

if numLabelsWritten, err := init.diskState.NumLabelsWritten(); err != nil {
return err
} else if numLabelsWritten > 0 {
if numLabelsWritten > 0 {
m, err := init.loadMetadata()
if err != nil {
return err
return nil, err
}
if err := init.verifyMetadata(m); err != nil {
return err
return nil, err
}
init.nonce.Store(m.Nonce)
init.lastPosition.Store(m.LastPosition)
}

if err := init.saveMetadata(); err != nil {
return err
return nil, err
}

return init, nil
}

// Initialize is the process in which the prover commits to store some data, by having its storage filled with
// pseudo-random data with respect to a specific id. This data is the result of a computationally-expensive operation.
func (init *Initializer) Initialize(ctx context.Context) error {
if !init.mtx.TryLock() {
return ErrAlreadyInitializing
}
defer init.mtx.Unlock()

numLabels := uint64(init.opts.NumUnits) * uint64(init.cfg.LabelsPerUnit)
fileNumLabels := numLabels / uint64(init.opts.NumFiles)
Expand All @@ -254,9 +259,6 @@ func (init *Initializer) Initialize(ctx context.Context) error {
}

// continue searching for a nonce
// TODO(mafa): PM-195 depending on the difficulty function this can take a VERY long time, with the current difficulty function
// ~ 37% of all smeshers won't find a nonce while computing leaves
// ~ 2% of all smeshers won't find a nonce even after checking 4x numLabels
defer init.saveMetadata()
for i := *init.lastPosition.Load(); i < math.MaxUint64; i += batchSize {
lastPos := i
Expand Down
123 changes: 78 additions & 45 deletions initialization/initialization_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,14 @@ func TestInitialize(t *testing.T) {
}
r.Equal(uint64(cfg.MinNumUnits)*cfg.LabelsPerUnit, init.NumLabelsWritten())

m, err := LoadMetadata(opts.DataDir)
r.NoError(err)
r.NoError(verifying.VerifyPow(m))
m := &shared.VRFNonceMetadata{
NodeId: nodeId,
CommitmentAtxId: commitmentAtxId,
NumUnits: opts.NumUnits,
BitsPerLabel: cfg.BitsPerLabel,
LabelsPerUnit: uint64(opts.NumUnits) * cfg.LabelsPerUnit,
}
r.NoError(verifying.VerifyVRFNonce(init.Nonce(), m))
}

func TestInitialize_PowOutOfRange(t *testing.T) {
Expand Down Expand Up @@ -108,12 +113,17 @@ func TestInitialize_PowOutOfRange(t *testing.T) {
r.NoError(init.Initialize(context.Background()))
r.Equal(uint64(cfg.MinNumUnits)*cfg.LabelsPerUnit, init.NumLabelsWritten())

m, err := LoadMetadata(opts.DataDir)
r.NoError(err)
r.NoError(verifying.VerifyPow(m))
m := &shared.VRFNonceMetadata{
NodeId: nodeId,
CommitmentAtxId: commitmentAtxId,
NumUnits: opts.NumUnits,
BitsPerLabel: cfg.BitsPerLabel,
LabelsPerUnit: uint64(opts.NumUnits) * cfg.LabelsPerUnit,
}
r.NoError(verifying.VerifyVRFNonce(init.Nonce(), m))

// check that the found nonce is outside of the range for calculating labels
r.Less(uint64(cfg.MinNumUnits)*cfg.LabelsPerUnit, *m.Nonce)
r.Less(uint64(cfg.MinNumUnits)*cfg.LabelsPerUnit, *init.Nonce())
}

func TestInitialize_ContinueWithLastPos(t *testing.T) {
Expand All @@ -140,12 +150,17 @@ func TestInitialize_ContinueWithLastPos(t *testing.T) {
r.NoError(init.Initialize(context.Background()))
r.Equal(uint64(cfg.MinNumUnits)*cfg.LabelsPerUnit, init.NumLabelsWritten())

m, err := LoadMetadata(opts.DataDir)
r.NoError(err)
r.NoError(verifying.VerifyPow(m))
meta := &shared.VRFNonceMetadata{
NodeId: nodeId,
CommitmentAtxId: commitmentAtxId,
NumUnits: opts.NumUnits,
BitsPerLabel: cfg.BitsPerLabel,
LabelsPerUnit: uint64(opts.NumUnits) * cfg.LabelsPerUnit,
}
r.NoError(verifying.VerifyVRFNonce(init.Nonce(), meta))

// trying again returns same nonce
origNonce := *m.Nonce
origNonce := *init.Nonce()
init, err = NewInitializer(
WithNodeId(nodeId),
WithCommitmentAtxId(commitmentAtxId),
Expand All @@ -158,7 +173,7 @@ func TestInitialize_ContinueWithLastPos(t *testing.T) {
r.NoError(init.Initialize(context.Background()))
r.Equal(uint64(cfg.MinNumUnits)*cfg.LabelsPerUnit, init.NumLabelsWritten())

m, err = LoadMetadata(opts.DataDir)
m, err := LoadMetadata(opts.DataDir)
r.NoError(err)
r.Equal(origNonce, *m.Nonce)
r.Nil(m.LastPosition)
Expand Down Expand Up @@ -205,9 +220,16 @@ func TestInitialize_ContinueWithLastPos(t *testing.T) {
r.NotNil(m.Nonce)
r.NotNil(m.LastPosition)
r.LessOrEqual(uint64(cfg.MinNumUnits)*cfg.LabelsPerUnit, *m.LastPosition)

r.LessOrEqual(uint64(cfg.MinNumUnits)*cfg.LabelsPerUnit, *m.Nonce)
r.NoError(verifying.VerifyPow(m))

meta = &shared.VRFNonceMetadata{
NodeId: nodeId,
CommitmentAtxId: commitmentAtxId,
NumUnits: opts.NumUnits,
BitsPerLabel: cfg.BitsPerLabel,
LabelsPerUnit: uint64(opts.NumUnits) * cfg.LabelsPerUnit,
}
r.NoError(verifying.VerifyVRFNonce(init.Nonce(), meta))

// lastPos sets lower bound for searching for nonce if none was found
lastPos := *m.Nonce + 10
Expand All @@ -234,7 +256,15 @@ func TestInitialize_ContinueWithLastPos(t *testing.T) {
r.LessOrEqual(lastPos, *m.LastPosition)

r.Less(lastPos, *m.Nonce)
r.NoError(verifying.VerifyPow(m))

meta = &shared.VRFNonceMetadata{
NodeId: nodeId,
CommitmentAtxId: commitmentAtxId,
NumUnits: opts.NumUnits,
BitsPerLabel: cfg.BitsPerLabel,
LabelsPerUnit: uint64(opts.NumUnits) * cfg.LabelsPerUnit,
}
r.NoError(verifying.VerifyVRFNonce(init.Nonce(), meta))
}

func TestReset_WhileInitializing(t *testing.T) {
Expand Down Expand Up @@ -472,29 +502,27 @@ func TestInitialize_NumUnits_MultipleFiles(t *testing.T) {

// Increase `opts.NumUnits` while `opts.NumFiles` > 1.
opts.NumUnits = prevNumUnits + 1
init, err = NewInitializer(
_, err = NewInitializer(
WithNodeId(nodeId),
WithCommitmentAtxId(commitmentAtxId),
WithConfig(cfg),
WithInitOpts(opts),
WithLogger(testLogger{t: t}),
)
r.NoError(err)
cfgMissErr := &shared.ConfigMismatchError{}
r.ErrorAs(init.Initialize(context.Background()), cfgMissErr)
var cfgMissErr shared.ConfigMismatchError
r.ErrorAs(err, &cfgMissErr)
r.Equal("NumUnits", cfgMissErr.Param)

// Decrease `opts.NumUnits` while `opts.NumFiles` > 1.
opts.NumUnits = prevNumUnits - 1
init, err = NewInitializer(
_, err = NewInitializer(
WithNodeId(nodeId),
WithCommitmentAtxId(commitmentAtxId),
WithConfig(cfg),
WithInitOpts(opts),
WithLogger(testLogger{t: t}),
)
r.NoError(err)
r.ErrorAs(init.Initialize(context.Background()), cfgMissErr)
r.ErrorAs(err, &cfgMissErr)
r.Equal("NumUnits", cfgMissErr.Param)
}

Expand Down Expand Up @@ -523,9 +551,14 @@ func TestInitialize_MultipleFiles(t *testing.T) {
oneFileData, err := initData(opts.DataDir, uint(cfg.BitsPerLabel))
r.NoError(err)

m, err := LoadMetadata(opts.DataDir)
r.NoError(err)
r.NoError(verifying.VerifyPow(m))
m := &shared.VRFNonceMetadata{
NodeId: nodeId,
CommitmentAtxId: commitmentAtxId,
NumUnits: opts.NumUnits,
BitsPerLabel: cfg.BitsPerLabel,
LabelsPerUnit: uint64(opts.NumUnits) * cfg.LabelsPerUnit,
}
r.NoError(verifying.VerifyVRFNonce(init.Nonce(), m))

// TODO(mafa): since we are not looking for the absolute lowest nonce, we can't guarantee that the nonce will be the same.
// see also https://github.com/spacemeshos/post/issues/90
Expand Down Expand Up @@ -553,9 +586,14 @@ func TestInitialize_MultipleFiles(t *testing.T) {

r.Equal(multipleFilesData, oneFileData)

m, err := LoadMetadata(opts.DataDir)
r.NoError(err)
r.NoError(verifying.VerifyPow(m))
m := &shared.VRFNonceMetadata{
NodeId: nodeId,
CommitmentAtxId: commitmentAtxId,
NumUnits: opts.NumUnits,
BitsPerLabel: cfg.BitsPerLabel,
LabelsPerUnit: uint64(opts.NumUnits) * cfg.LabelsPerUnit,
}
r.NoError(verifying.VerifyVRFNonce(init.Nonce(), m))

// TODO(mafa): see above
// r.Equal(oneFileNonce, *init.Nonce())
Expand Down Expand Up @@ -641,8 +679,8 @@ func TestValidateMetadata(t *testing.T) {
r.NoError(err)

m, err := init.loadMetadata()
r.Equal(ErrStateMetadataFileMissing, err)
r.Nil(m)
r.NoError(err)
r.NoError(init.verifyMetadata(m))

r.NoError(init.Initialize(context.Background()))
m, err = init.loadMetadata()
Expand All @@ -652,72 +690,67 @@ func TestValidateMetadata(t *testing.T) {
// Attempt to initialize with different `NodeId`.
newNodeId := make([]byte, 32)
newNodeId[0] = newNodeId[0] + 1
init, err = NewInitializer(
_, err = NewInitializer(
WithNodeId(newNodeId),
WithCommitmentAtxId(commitmentAtxId),
WithConfig(cfg),
WithInitOpts(opts),
WithLogger(testLogger{t: t}),
)
r.NoError(err)
var errConfigMismatch ConfigMismatchError
r.ErrorAs(init.Initialize(context.Background()), &errConfigMismatch)
r.ErrorAs(err, &errConfigMismatch)
r.Equal("NodeId", errConfigMismatch.Param)

// Attempt to initialize with different `AtxId`.
newAtxId := make([]byte, 32)
newAtxId[0] = newAtxId[0] + 1
init, err = NewInitializer(
_, err = NewInitializer(
WithNodeId(nodeId),
WithCommitmentAtxId(newAtxId),
WithConfig(cfg),
WithInitOpts(opts),
WithLogger(testLogger{t: t}),
)
r.NoError(err)
r.ErrorAs(init.Initialize(context.Background()), &errConfigMismatch)
r.ErrorAs(err, &errConfigMismatch)
r.Equal("CommitmentAtxId", errConfigMismatch.Param)

// Attempt to initialize with different `cfg.BitsPerLabel`.
newCfg := cfg
newCfg.BitsPerLabel = cfg.BitsPerLabel + 1
init, err = NewInitializer(
_, err = NewInitializer(
WithNodeId(nodeId),
WithCommitmentAtxId(commitmentAtxId),
WithConfig(newCfg),
WithInitOpts(opts),
WithLogger(testLogger{t: t}),
)
r.NoError(err)
r.ErrorAs(init.Initialize(context.Background()), &errConfigMismatch)
r.ErrorAs(err, &errConfigMismatch)
r.Equal("BitsPerLabel", errConfigMismatch.Param)

// Attempt to initialize with different `opts.NumFiles`.
newOpts := opts
newOpts.NumFiles = 4
init, err = NewInitializer(
_, err = NewInitializer(
WithNodeId(nodeId),
WithCommitmentAtxId(commitmentAtxId),
WithConfig(cfg),
WithInitOpts(newOpts),
WithLogger(testLogger{t: t}),
)
r.NoError(err)
r.ErrorAs(init.Initialize(context.Background()), &errConfigMismatch)
r.ErrorAs(err, &errConfigMismatch)
r.Equal("NumFiles", errConfigMismatch.Param)

// Attempt to initialize with different `opts.NumUnits` while `opts.NumFiles` > 1.
newOpts = opts
newOpts.NumUnits++
init, err = NewInitializer(
_, err = NewInitializer(
WithNodeId(nodeId),
WithCommitmentAtxId(commitmentAtxId),
WithConfig(cfg),
WithInitOpts(newOpts),
WithLogger(testLogger{t: t}),
)
r.NoError(err)
r.ErrorAs(init.Initialize(context.Background()), &errConfigMismatch)
r.ErrorAs(err, &errConfigMismatch)
r.Equal("NumUnits", errConfigMismatch.Param)
}

Expand Down
11 changes: 11 additions & 0 deletions shared/proof.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,14 @@ type ProofMetadata struct {
K1 uint32
K2 uint32
}

type VRFNonce uint64

type VRFNonceMetadata struct {
NodeId []byte
CommitmentAtxId []byte

NumUnits uint32
BitsPerLabel uint8
LabelsPerUnit uint64
}
Loading

0 comments on commit f3ec621

Please sign in to comment.