From 16882441d15bfd1d26947748c9d50d32c428b49d Mon Sep 17 00:00:00 2001 From: lukechampine Date: Thu, 1 Feb 2024 10:48:51 -0400 Subject: [PATCH] coreutils: Add mining helpers --- miner.go | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 miner.go diff --git a/miner.go b/miner.go new file mode 100644 index 0000000..28f1126 --- /dev/null +++ b/miner.go @@ -0,0 +1,73 @@ +package coreutils + +import ( + "encoding/binary" + "time" + + "go.sia.tech/core/consensus" + "go.sia.tech/core/types" + "go.sia.tech/coreutils/chain" +) + +// FindBlockNonce attempts to find a nonce for b that meets the PoW target. +func FindBlockNonce(cs consensus.State, b *types.Block, timeout time.Duration) bool { + b.Nonce = 0 + buf := make([]byte, 32+8+8+32) + binary.LittleEndian.PutUint64(buf[32:], b.Nonce) + binary.LittleEndian.PutUint64(buf[40:], uint64(b.Timestamp.Unix())) + if b.V2 != nil { + copy(buf[:32], "sia/id/block|") + copy(buf[48:], b.V2.Commitment[:]) + } else { + root := b.MerkleRoot() + copy(buf[:32], b.ParentID[:]) + copy(buf[48:], root[:]) + } + factor := cs.NonceFactor() + startBlock := time.Now() + for types.BlockID(types.HashBytes(buf)).CmpWork(cs.ChildTarget) < 0 { + b.Nonce += factor + binary.LittleEndian.PutUint64(buf[32:], b.Nonce) + if time.Since(startBlock) > timeout { + return false + } + } + return true +} + +// MineBlock constructs a block from the provided address and the transactions +// in the txpool, and attempts to find a nonce for it that meets the PoW target. +func MineBlock(cm *chain.Manager, addr types.Address, timeout time.Duration) (types.Block, bool) { + cs := cm.TipState() + b := types.Block{ + ParentID: cs.Index.ID, + Timestamp: types.CurrentTimestamp(), + MinerPayouts: []types.SiacoinOutput{{ + Value: cs.BlockReward(), + Address: addr, + }}, + } + var weight uint64 + for _, txn := range cm.PoolTransactions() { + if weight += cs.TransactionWeight(txn); weight > cs.MaxBlockWeight() { + break + } + b.Transactions = append(b.Transactions, txn) + } + for _, txn := range cm.V2PoolTransactions() { + if weight += cs.V2TransactionWeight(txn); weight > cs.MaxBlockWeight() { + break + } + if b.V2 == nil { + b.V2 = &types.V2BlockData{ + Height: cs.Index.Height + 1, + } + } + b.V2.Transactions = append(b.V2.Transactions, txn) + } + if b.V2 != nil { + b.V2.Commitment = cs.Commitment(cs.TransactionsCommitment(b.Transactions, b.V2Transactions()), addr) + } + found := FindBlockNonce(cs, &b, timeout) + return b, found +}