forked from SiaFoundation/coreutils
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathminer.go
85 lines (78 loc) · 2.3 KB
/
miner.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
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) {
retry:
cs := cm.TipState()
txns := cm.PoolTransactions()
v2Txns := cm.V2PoolTransactions()
if cs.Index != cm.Tip() {
goto retry
}
b := types.Block{
ParentID: cs.Index.ID,
Timestamp: types.CurrentTimestamp(),
MinerPayouts: []types.SiacoinOutput{{
Value: cs.BlockReward(),
Address: addr,
}},
}
childHeight := cs.Index.Height + 1
if childHeight >= cs.Network.HardforkV2.AllowHeight {
b.V2 = &types.V2BlockData{
Height: childHeight,
}
}
var weight uint64
for _, txn := range txns {
if weight += cs.TransactionWeight(txn); weight > cs.MaxBlockWeight() {
break
}
b.Transactions = append(b.Transactions, txn)
b.MinerPayouts[0].Value = b.MinerPayouts[0].Value.Add(txn.TotalFees())
}
if b.V2 != nil {
for _, txn := range v2Txns {
if weight += cs.V2TransactionWeight(txn); weight > cs.MaxBlockWeight() {
break
}
b.V2.Transactions = append(b.V2.Transactions, txn)
b.MinerPayouts[0].Value = b.MinerPayouts[0].Value.Add(txn.MinerFee)
}
b.V2.Commitment = cs.Commitment(cs.TransactionsCommitment(b.Transactions, b.V2Transactions()), addr)
}
found := FindBlockNonce(cs, &b, timeout)
return b, found
}