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

pool: update error types. #245

Merged
merged 18 commits into from
Sep 16, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cmd/miner/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ func loadConfig() (*config, []string, error) {
}

// Create the home directory if it doesn't already exist.
funcName := "loadConfig"
const funcName = "loadConfig"
err = os.MkdirAll(cfg.HomeDir, 0700)
if err != nil {
// Show a nicer error message if it's because a symlink is
Expand Down
2 changes: 1 addition & 1 deletion config.go
Original file line number Diff line number Diff line change
Expand Up @@ -433,7 +433,7 @@ func loadConfig() (*config, []string, error) {
}

// Create the home directory if it doesn't already exist.
funcName := "loadConfig"
const funcName = "loadConfig"
err = os.MkdirAll(cfg.HomeDir, 0700)
if err != nil {
// Show a nicer error message if it's because a symlink is
Expand Down
91 changes: 53 additions & 38 deletions pool/acceptedwork.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,17 +38,11 @@ func heightToBigEndianBytes(height uint32) []byte {
return b
}

// bigEndianBytesToHeight returns the block height of the provided 4-byte big
// endian representation.
func bigEndianBytesToHeight(b []byte) uint32 {
return binary.BigEndian.Uint32(b[0:4])
}

// AcceptedWorkID generates a unique id for work accepted by the network.
func AcceptedWorkID(blockHash string, blockHeight uint32) []byte {
buf := bytes.Buffer{}
buf.WriteString(hex.EncodeToString(heightToBigEndianBytes(blockHeight)))
buf.WriteString(blockHash)
var buf bytes.Buffer
_, _ = buf.WriteString(hex.EncodeToString(heightToBigEndianBytes(blockHeight)))
_, _ = buf.WriteString(blockHash)
return buf.Bytes()
}

Expand All @@ -68,47 +62,55 @@ func NewAcceptedWork(blockHash string, prevHash string, height uint32,

// fetchWorkBucket is a helper function for getting the work bucket.
func fetchWorkBucket(tx *bolt.Tx) (*bolt.Bucket, error) {
const funcName = "fetchWorkBucket"
pbkt := tx.Bucket(poolBkt)
if pbkt == nil {
desc := fmt.Sprintf("bucket %s not found", string(poolBkt))
return nil, MakeError(ErrBucketNotFound, desc, nil)
desc := fmt.Sprintf("%s: bucket %s not found", funcName,
string(poolBkt))
return nil, dbError(ErrBucketNotFound, desc)
}
bkt := pbkt.Bucket(workBkt)
if bkt == nil {
desc := fmt.Sprintf("bucket %s not found", string(workBkt))
return nil, MakeError(ErrBucketNotFound, desc, nil)
desc := fmt.Sprintf("%s: bucket %s not found", funcName,
string(workBkt))
return nil, dbError(ErrBucketNotFound, desc)
}
return bkt, nil
}

// FetchAcceptedWork fetches the accepted work referenced by the provided id.
func FetchAcceptedWork(db *bolt.DB, id []byte) (*AcceptedWork, error) {
const funcName = "FetchAcceptedWork"
var work AcceptedWork
err := db.View(func(tx *bolt.Tx) error {
bkt, err := fetchWorkBucket(tx)
if err != nil {
return err
}

v := bkt.Get(id)
if v == nil {
desc := fmt.Sprintf("no value for key %s", string(id))
return MakeError(ErrValueNotFound, desc, nil)
desc := fmt.Sprintf("%s: no value for key %s",
funcName, string(id))
return dbError(ErrValueNotFound, desc)
}

err = json.Unmarshal(v, &work)
return err
if err != nil {
desc := fmt.Sprintf("%s: unable to unmarshal accepted work: %v",
funcName, err)
return dbError(ErrParse, desc)
}
return nil
})
if err != nil {
return nil, err
}

return &work, err
}

// Create persists the accepted work to the database.
func (work *AcceptedWork) Create(db *bolt.DB) error {
err := db.Update(func(tx *bolt.Tx) error {
const funcName = "AcceptedWork.Create"
return db.Update(func(tx *bolt.Tx) error {
bkt, err := fetchWorkBucket(tx)
if err != nil {
return err
Expand All @@ -118,23 +120,31 @@ func (work *AcceptedWork) Create(db *bolt.DB) error {
id := []byte(work.UUID)
v := bkt.Get(id)
if v != nil {
desc := fmt.Sprintf("work %s already exists", work.UUID)
return MakeError(ErrWorkExists, desc, nil)
desc := fmt.Sprintf("%s: work %s already exists", funcName,
work.UUID)
return dbError(ErrValueFound, desc)
}

workBytes, err := json.Marshal(work)
if err != nil {
return err
desc := fmt.Sprintf("%s: unable to marshal accepted "+
"work bytes: %v", funcName, err)
return dbError(ErrParse, desc)
}

return bkt.Put(id, workBytes)
err = bkt.Put(id, workBytes)
if err != nil {
desc := fmt.Sprintf("%s: unable to persist accepted work: %v",
funcName, err)
return dbError(ErrPersistEntry, desc)
}
return nil
})
return err
}

// Update persists modifications to an existing work.
func (work *AcceptedWork) Update(db *bolt.DB) error {
err := db.Update(func(tx *bolt.Tx) error {
const funcName = "AcceptedWork.Update"
return db.Update(func(tx *bolt.Tx) error {
bkt, err := fetchWorkBucket(tx)
if err != nil {
return err
Expand All @@ -144,18 +154,23 @@ func (work *AcceptedWork) Update(db *bolt.DB) error {
id := []byte(work.UUID)
v := bkt.Get(id)
if v == nil {
desc := fmt.Sprintf("work %s not found", work.UUID)
return MakeError(ErrWorkNotFound, desc, nil)
desc := fmt.Sprintf("%s: work %s not found", funcName, work.UUID)
return dbError(ErrValueNotFound, desc)
}

workBytes, err := json.Marshal(work)
if err != nil {
return err
desc := fmt.Sprintf("%s: unable to marshal accepted "+
"work bytes: %v", funcName, err)
return dbError(ErrPersistEntry, desc)
}

return bkt.Put(id, workBytes)
err = bkt.Put(id, workBytes)
if err != nil {
desc := fmt.Sprintf("%s: unable to persist accepted work: %v",
funcName, err)
return dbError(ErrPersistEntry, desc)
}
return nil
})
return err
}

// Delete removes the associated accepted work from the database.
Expand All @@ -168,6 +183,7 @@ func (work *AcceptedWork) Delete(db *bolt.DB) error {
//
// List is ordered, most recent comes first.
func ListMinedWork(db *bolt.DB) ([]*AcceptedWork, error) {
const funcName = "ListMinedWork"
minedWork := make([]*AcceptedWork, 0)
err := db.View(func(tx *bolt.Tx) error {
bkt, err := fetchWorkBucket(tx)
Expand All @@ -180,17 +196,16 @@ func ListMinedWork(db *bolt.DB) ([]*AcceptedWork, error) {
var work AcceptedWork
err := json.Unmarshal(v, &work)
if err != nil {
return err
desc := fmt.Sprintf("%s: unable to unmarshal accepted "+
"work: %v", funcName, err)
return poolError(ErrParse, desc)
}

minedWork = append(minedWork, &work)
}

return nil
})
if err != nil {
return nil, err
}

return minedWork, nil
}
5 changes: 1 addition & 4 deletions pool/acceptedwork_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package pool

import (
"encoding/json"
"fmt"
"strings"
"testing"

Expand All @@ -14,7 +13,7 @@ func persistAcceptedWork(db *bolt.DB, blockHash string, prevHash string,
acceptedWork := NewAcceptedWork(blockHash, prevHash, height, minedBy, miner)
err := acceptedWork.Create(db)
if err != nil {
return nil, fmt.Errorf("unable to persist accepted work: %v", err)
return nil, err
}
return acceptedWork, nil
}
Expand Down Expand Up @@ -102,15 +101,13 @@ func testAcceptedWork(t *testing.T, db *bolt.DB) {

// Ensure fetching a non existent accepted work returns an error.
id := AcceptedWorkID(workC.BlockHash, workD.Height)

_, err = FetchAcceptedWork(db, id)
if err == nil {
t.Fatalf("FetchAcceptedWork: expected a non-existent accepted work error")
}

// Fetch an accepted work with its id.
id = AcceptedWorkID(workC.BlockHash, workC.Height)

fetchedWork, err := FetchAcceptedWork(db, id)
if err != nil {
t.Fatalf("FetchAcceptedWork error: %v", err)
Expand Down
73 changes: 42 additions & 31 deletions pool/account.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,16 @@ type Account struct {

// AccountID generates a unique id using provided address of the account.
func AccountID(address string, activeNet *chaincfg.Params) (string, error) {
const funcName = "AcccountID"
_, err := dcrutil.DecodeAddress(address, activeNet)
if err != nil {
return "", err
desc := fmt.Sprintf("%s: unable to decode address %s: %v",
funcName, address, err)
return "", poolError(ErrDecode, desc)
}

hasher := blake256.New()
_, err = hasher.Write([]byte(address))
if err != nil {
return "", err
}

id := hex.EncodeToString(hasher.Sum(nil))
return id, nil
_, _ = hasher.Write([]byte(address))
return hex.EncodeToString(hasher.Sum(nil)), nil
}

// NewAccount creates a new account.
Expand All @@ -48,34 +45,35 @@ func NewAccount(address string, activeNet *chaincfg.Params) (*Account, error) {
if err != nil {
return nil, err
}

account := &Account{
UUID: id,
Address: address,
CreatedOn: uint64(time.Now().Unix()),
}

return account, nil
}

// fetchAccountBucket is a helper function for getting the account bucket.
func fetchAccountBucket(tx *bolt.Tx) (*bolt.Bucket, error) {
const funcName = "fetchAccountBucket"
pbkt := tx.Bucket(poolBkt)
if pbkt == nil {
desc := fmt.Sprintf("bucket %s not found", string(poolBkt))
return nil, MakeError(ErrBucketNotFound, desc, nil)
desc := fmt.Sprintf("%s: bucket %s not found", funcName,
string(poolBkt))
return nil, dbError(ErrBucketNotFound, desc)
}
bkt := pbkt.Bucket(accountBkt)
if bkt == nil {
desc := fmt.Sprintf("bucket %s not found", string(accountBkt))
return nil, MakeError(ErrBucketNotFound, desc, nil)
desc := fmt.Sprintf("%s: bucket %s not found", funcName,
string(accountBkt))
return nil, dbError(ErrBucketNotFound, desc)
}

return bkt, nil
}

// FetchAccount fetches the account referenced by the provided id.
func FetchAccount(db *bolt.DB, id []byte) (*Account, error) {
const funcName = "FetchAccount"
var account Account
err := db.View(func(tx *bolt.Tx) error {
bkt, err := fetchAccountBucket(tx)
Expand All @@ -85,42 +83,55 @@ func FetchAccount(db *bolt.DB, id []byte) (*Account, error) {

v := bkt.Get(id)
if v == nil {
desc := fmt.Sprintf("no account found for id %s", string(id))
return MakeError(ErrValueNotFound, desc, nil)
desc := fmt.Sprintf("%s: no account found for id %s", funcName,
string(id))
return dbError(ErrValueNotFound, desc)
}

err = json.Unmarshal(v, &account)
return err
if err != nil {
desc := fmt.Sprintf("%s: unable to unmarshal account: %v",
funcName, err)
return dbError(ErrParse, desc)
}
return nil
})
if err != nil {
return nil, err
}

return &account, err
}

// Create persists the account to the database.
func (acc *Account) Create(db *bolt.DB) error {
err := db.Update(func(tx *bolt.Tx) error {
const funcName = "Account.Create"
return db.Update(func(tx *bolt.Tx) error {
bkt, err := fetchAccountBucket(tx)
if err != nil {
return err
}

// Do not persist already existing account.
id := []byte(acc.UUID)
v := bkt.Get(id)
if v != nil {
desc := fmt.Sprintf("%s: account %s already exists", funcName,
acc.UUID)
return dbError(ErrValueFound, desc)
}
accBytes, err := json.Marshal(acc)
if err != nil {
return err
desc := fmt.Sprintf("%s: unable to marshal account bytes: %v",
funcName, err)
return dbError(ErrParse, desc)
}
err = bkt.Put([]byte(acc.UUID), accBytes)
return err
if err != nil {
desc := fmt.Sprintf("%s: unable to persist account entry: %v",
funcName, err)
return dbError(ErrPersistEntry, desc)
}
return nil
})
return err
}

// Update is not supported for accounts.
func (acc *Account) Update(db *bolt.DB) error {
desc := "account update not supported"
return MakeError(ErrNotSupported, desc, nil)
}

// Delete purges the referenced account from the database.
Expand Down
6 changes: 0 additions & 6 deletions pool/account_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,6 @@ func testAccount(t *testing.T, db *bolt.DB) {
accountA.UUID, fetchedAccount.UUID)
}

// Ensure accounts cannot be updated.
err = accountB.Update(db)
if err == nil {
t.Fatal("expected not supported error")
}

// Delete all accounts.
err = accountA.Delete(db)
if err != nil {
Expand Down
Loading