diff --git a/dkg/disk.go b/dkg/disk.go index 0a1218280..10615b62a 100644 --- a/dkg/disk.go +++ b/dkg/disk.go @@ -16,7 +16,9 @@ package dkg import ( + "crypto/rand" "encoding/json" + "fmt" "os" "path" @@ -28,7 +30,9 @@ import ( "github.com/obolnetwork/charon/core" "github.com/obolnetwork/charon/eth2util/deposit" "github.com/obolnetwork/charon/eth2util/keystore" + "github.com/obolnetwork/charon/tbls" "github.com/obolnetwork/charon/tbls/tblsconv" + "github.com/obolnetwork/charon/testutil" ) // loadDefinition returns the cluster definition from disk (or the test definition if configured). @@ -112,10 +116,74 @@ func writeDepositData(aggSigs map[core.PubKey]*bls_sig.Signature, withdrawalAddr // Write it to disk depositPath := path.Join(dataDir, "deposit-data.json") - err = os.WriteFile(depositPath, bytes, 0o400) // read-only + err = os.WriteFile(depositPath, bytes, 0o444) // read-only if err != nil { return errors.Wrap(err, "write deposit data") } return nil } + +// checkWrites writes sample files to check disk writes and removes sample files after verification. +func checkWrites(dataDir string, def cluster.Definition) error { + var shares []share + sigs := make(map[core.PubKey]*bls_sig.Signature) + for i := 0; i < def.NumValidators; i++ { + tss, sks, err := tbls.GenerateTSS(def.Threshold, len(def.Operators), rand.Reader) + if err != nil { + return err + } + + shares = append(shares, share{ + PubKey: tss.PublicKey(), + SecretShare: sks[0], + PublicShares: tss.PublicShares(), + }) + + pk, err := tblsconv.KeyToCore(tss.PublicKey()) + if err != nil { + return err + } + + sig, err := testutil.RandomBLSSignature() + if err != nil { + return err + } + + sigs[pk] = sig + } + + if err := writeDepositData(sigs, testutil.RandomETHAddress(), "prater", dataDir); err != nil { + return err + } + + if err := writeKeystores(dataDir, shares); err != nil { + return err + } + + lock := cluster.Lock{Definition: def} + if err := writeLock(dataDir, lock); err != nil { + return err + } + + // Cleanup sample files + if err := os.Remove(path.Join(dataDir, "deposit-data.json")); err != nil { + return errors.Wrap(err, "remove sample deposit-data.json") + } + + for i := 0; i < def.NumValidators; i++ { + if err := os.Remove(path.Join(dataDir, fmt.Sprintf("keystore-%d.json", i))); err != nil { + return errors.Wrap(err, fmt.Sprintf("remove sample keystore-%d.json", i)) + } + + if err := os.Remove(path.Join(dataDir, fmt.Sprintf("keystore-%d.txt", i))); err != nil { + return errors.Wrap(err, fmt.Sprintf("remove sample keystore-%d.txt", i)) + } + } + + if err := os.Remove(path.Join(dataDir, "cluster-lock.json")); err != nil { + return errors.Wrap(err, "remove sample cluster-lock.json") + } + + return nil +} diff --git a/dkg/dkg.go b/dkg/dkg.go index 8f2b979da..9488ab309 100644 --- a/dkg/dkg.go +++ b/dkg/dkg.go @@ -69,6 +69,10 @@ func Run(ctx context.Context, conf Config) (err error) { return err } + if err = checkWrites(conf.DataDir, def); err != nil { + return err + } + network, err := forkVersionToNetwork(def.ForkVersion) if err != nil { return err diff --git a/eth2util/keystore/keystore.go b/eth2util/keystore/keystore.go index a570a2083..607d42778 100644 --- a/eth2util/keystore/keystore.go +++ b/eth2util/keystore/keystore.go @@ -56,7 +56,7 @@ func StoreKeys(secrets []*bls_sig.SecretKey, dir string) error { } filename := path.Join(dir, fmt.Sprintf("keystore-%d.json", i)) - if err := os.WriteFile(filename, b, 0o400); err != nil { + if err := os.WriteFile(filename, b, 0o444); err != nil { return errors.Wrap(err, "write keystore") } diff --git a/testutil/random.go b/testutil/random.go index b20de1964..add97156e 100644 --- a/testutil/random.go +++ b/testutil/random.go @@ -30,6 +30,8 @@ import ( "github.com/attestantio/go-eth2-client/spec/altair" "github.com/attestantio/go-eth2-client/spec/bellatrix" eth2p0 "github.com/attestantio/go-eth2-client/spec/phase0" + "github.com/coinbase/kryptology/pkg/core/curves/native/bls12381" + "github.com/coinbase/kryptology/pkg/signatures/bls/bls_sig" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/p2p/enode" "github.com/ethereum/go-ethereum/p2p/enr" @@ -40,6 +42,7 @@ import ( "github.com/prysmaticlabs/go-bitfield" "github.com/stretchr/testify/require" + "github.com/obolnetwork/charon/app/errors" "github.com/obolnetwork/charon/core" "github.com/obolnetwork/charon/tbls" "github.com/obolnetwork/charon/tbls/tblsconv" @@ -239,6 +242,15 @@ func RandomRoot() eth2p0.Root { return resp } +func RandomBLSSignature() (*bls_sig.Signature, error) { + g2, err := new(bls12381.G2).Random(crand.Reader) + if err != nil { + return nil, errors.Wrap(err, "random point in g2") + } + + return &bls_sig.Signature{Value: *g2}, nil +} + func RandomEth2Signature() eth2p0.BLSSignature { var resp eth2p0.BLSSignature _, _ = rand.Read(resp[:])