job.go raw
1 package job
2
3 //
4 // import (
5 // "errors"
6 // "github.com/p9c/p9/pkg/chaincfg"
7 // "time"
8 //
9 // "github.com/niubaoshu/gotiny"
10 //
11 // "github.com/p9c/p9/pkg/blockchain"
12 // "github.com/p9c/p9/pkg/chainhash"
13 // "github.com/p9c/p9/pkg/blockchain/fork"
14 // "github.com/p9c/p9/pkg/wire"
15 // "github.com/p9c/p9/pkg/util"
16 // )
17 //
18
19 var Magic = []byte{'j', 'o', 'b', 1}
20
21 //
22 // type Job struct {
23 // // IPs map[string]struct{}
24 // // P2PListenerPort uint16
25 // // RPCListenerPort uint16
26 // ControllerNonce uint64
27 // Height int32
28 // PrevBlockHash *chainhash.Hash
29 // MinTimestamp time.Time
30 // Diffs blockchain.Diffs
31 // Merkles blockchain.Merkles
32 // // CoinBases map[int32]*util.Tx
33 // }
34 //
35 // // Get returns a message broadcast by a node and each field is decoded where
36 // // possible avoiding memory allocation (slicing the data). Yes, this is not
37 // // concurrent safe, put a mutex in to share it. Using the same principles as
38 // // used in FlatBuffers, we define a message type that instead of using a reflect
39 // // based encoder, there is a creation function, and a set of methods that
40 // // extracts the individual requested field without copying memory, or
41 // // deserialize their contents which will be concurrent safe The varying coinbase
42 // // payment values are in transaction 0 last output, the individual varying
43 // // transactions are stored separately and will be reassembled at the end
44 // func Get(
45 // node *blockchain.BlockChain,
46 // activeNet *chaincfg.Params,
47 // uuid uint64,
48 // mB *util.Block,
49 // ) (cbs *map[int32]*util.Tx, out []byte, txr []*util.Tx,) {
50 // _temp := make(map[int32]*util.Tx)
51 // cbs = &_temp
52 // bH := node.BestSnapshot().Height + 1
53 // tip := node.BestChain.Tip()
54 // bitsMap := make(blockchain.Diffs)
55 // var e error
56 // df, ok := tip.Diffs.Load().(blockchain.Diffs)
57 // if df == nil || !ok ||
58 // len(df) != len(fork.List[1].AlgoVers) {
59 // if bitsMap, e = node.CalcNextRequiredDifficultyPlan9Controller(tip); E.Chk(e) {
60 // return
61 // }
62 // tip.Diffs.Store(bitsMap)
63 // } else {
64 // bitsMap = tip.Diffs.Load().(blockchain.Diffs)
65 // }
66 // // Now we need to get the values for coinbase for each algorithm then regenerate
67 // // the merkle roots To mine this block a miner only needs the matching merkle
68 // // roots for the version number but to get them first get the values
69 // var val int64
70 // mTS := make(map[int32]*chainhash.Hash)
71 // mBtx := mB.Transactions()
72 // root := len(mBtx) - 1
73 // coinbase := mBtx[root]
74 // transactions := mB.Transactions()[:root]
75 // txr = make([]*util.Tx, len(transactions))
76 // for i, v := range transactions {
77 // txr[i] = v
78 // }
79 // nbH := bH
80 // if (activeNet.Net == wire.MainNet &&
81 // nbH == fork.List[1].ActivationHeight) ||
82 // (activeNet.Net == wire.TestNet3 &&
83 // nbH == fork.List[1].TestnetStart) {
84 // nbH++
85 // }
86 //
87 // for i := range bitsMap {
88 // // set value according to version and block height
89 // val = blockchain.CalcBlockSubsidy(nbH, activeNet, i)
90 // txc := coinbase.MsgTx().Copy()
91 // txc.TxOut[len(txc.TxOut)-1].Value = val
92 // txx := util.NewTx(txc.Copy())
93 // // D.S(coinbase)
94 // (*cbs)[i] = txx
95 // // D.Ln("coinbase for version", i, txx.MsgTx().TxOut[len(txx.MsgTx().TxOut)-1].Value)
96 // mTree := blockchain.BuildMerkleTreeStore(
97 // append(txr, txx), false,
98 // )
99 // // D.S(mTree)
100 // mr := mTree.GetRoot()
101 // if mr == nil {
102 // e = errors.New("got a nil merkle root")
103 // panic(e)
104 // return
105 // }
106 // mTS[i] = mr
107 // }
108 // jrb := Job{
109 // ControllerNonce: uuid,
110 // Height: bH,
111 // PrevBlockHash: &mB.WireBlock().Header.PrevBlock,
112 // Diffs: bitsMap,
113 // Merkles: mTS,
114 // MinTimestamp: tip.Header().Timestamp.Truncate(time.Second).Add(time.Second),
115 // }
116 // // jrb.CoinBases= make(map[int32]*util.Tx)
117 // // for i := range *cbs {
118 // // jrb.CoinBases[i] = (*cbs)[i]
119 // // }
120 // out = gotiny.Marshal(&jrb)
121 // // D.S(jrb)
122 // // D.S(out)
123 // // var testy []byte
124 // // for i := range out {
125 // // testy = append(testy, out[i])
126 // // }
127 // // var jr Job
128 // // D.Ln(gotiny.Unmarshal(testy, &jr))
129 // // D.S(jr)
130 // // D.Ln("job size", len(jobber))
131 // // return Container{*msg.CreateContainer(Magic)}, txr
132 // return cbs, out, txr
133 // }
134 //
135 // //
136 // // // LoadContainer takes a message byte slice payload and loads it into a
137 // // // container ready to be decoded
138 // // func LoadContainer(b []byte) (out Container) {
139 // // out.Data = b
140 // // return
141 // // }
142 // //
143 // // func (j *Container) GetIPs() []*net.IP {
144 // // return IPs.New().DecodeOne(j.Get(0)).Get()
145 // // }
146 // //
147 // // func (j *Container) GetP2PListenersPort() uint16 {
148 // // return Uint16.New().DecodeOne(j.Get(1)).Get()
149 // // }
150 // //
151 // // func (j *Container) GetRPCListenersPort() uint16 {
152 // // return Uint16.New().DecodeOne(j.Get(2)).Get()
153 // // }
154 // //
155 // // func (j *Container) GetControllerListenerPort() uint16 {
156 // // return Uint16.New().DecodeOne(j.Get(3)).Get()
157 // // }
158 // //
159 // // func (j *Container) GetNewHeight() (out int32) {
160 // // return Int32.New().DecodeOne(j.Get(4)).Get()
161 // // }
162 // //
163 // // func (j *Container) GetPrevBlockHash() (out *chainhash.Hash) {
164 // // return Hash.New().DecodeOne(j.Get(5)).Get()
165 // // }
166 // //
167 // // func (j *Container) GetBitses() blockchain.Bits {
168 // // return Bits.NewBitses().DecodeOne(j.Get(6)).Get()
169 // // }
170 // //
171 // // // GetHashes returns the merkle roots per version
172 // // func (j *Container) GetHashes() (out map[int32]*chainhash.Hash) {
173 // // return Merkles.NewHashes().DecodeOne(j.Get(7)).Get()
174 // // }
175 // //
176 // // func (j *Container) String() (s string) {
177 // // s += fmt.Sprint("\ntype '"+string(Magic)+"' elements:", j.Count())
178 // // s += "\n"
179 // // ips := j.GetIPs()
180 // // s += "1 IPs:"
181 // // for i := range ips {
182 // // s += fmt.Sprint(" ", ips[i].String())
183 // // }
184 // // s += "\n"
185 // // s += fmt.Sprint("2 P2PListenersPort: ", j.GetP2PListenersPort())
186 // // s += "\n"
187 // // s += fmt.Sprint("3 RPCListenersPort: ", j.GetRPCListenersPort())
188 // // s += "\n"
189 // // s += fmt.Sprint(
190 // // "4 ControllerListenerPort: ",
191 // // j.GetControllerListenerPort(),
192 // // )
193 // // s += "\n"
194 // // h := j.GetNewHeight()
195 // // s += fmt.Sprint("5 Block height: ", h)
196 // // s += "\n"
197 // // s += fmt.Sprintf(
198 // // "6 Previous Block Hash (sha256d): %064x",
199 // // j.GetPrevBlockHash().CloneBytes(),
200 // // )
201 // // s += "\n"
202 // // bitses := j.GetBitses()
203 // // s += fmt.Sprint("7 Difficulty targets:\n")
204 // // var sortedBitses []int
205 // // for i := range bitses {
206 // // sortedBitses = append(sortedBitses, int(i))
207 // // }
208 // // txsort.Ints(sortedBitses)
209 // // for i := range sortedBitses {
210 // // s += fmt.Sprintf(
211 // // " %2d %-10v %d %064x",
212 // // sortedBitses[i],
213 // // fork.List[fork.GetCurrent(h)].AlgoVers[int32(sortedBitses[i])],
214 // // bitses[int32(sortedBitses[i])],
215 // // fork.CompactToBig(bitses[int32(sortedBitses[i])]).Bytes(),
216 // // )
217 // // s += "\n"
218 // // }
219 // // s += "8 Merkles:\n"
220 // // hashes := j.GetHashes()
221 // // for i := range sortedBitses {
222 // // s += fmt.Sprintf(
223 // // " %2d %s\n", sortedBitses[i],
224 // // hashes[int32(sortedBitses[i])].String(),
225 // // )
226 // // }
227 // //
228 // // // s += spew.Sdump(j.GetHashes())
229 // // return
230 // // }
231 // //
232 // // //
233 // // // // Struct returns a handy Go struct version This can be used at the start of a
234 // // // // new block to get a handy struct, the first work received triggers startup and
235 // // // // locks the worker into sending solutions there, until there is a new
236 // // // // PrevBlockHash, the work controller (kopach) only responds to updates from
237 // // // // this first one (or if it stops sending) - the controller keeps track of
238 // // // // individual controller servers multicasting and when it deletes a newly gone
239 // // // // dark controller when it comes to send if it isn't found it falls back to the
240 // // // // next available to submit
241 // // // func (j *Container) Struct() (out Job) {
242 // // // out = Job{
243 // // // IPs: j.GetIPs(),
244 // // // P2PListenerPort: j.GetP2PListenersPort(),
245 // // // RPCListenerPort: j.GetRPCListenersPort(),
246 // // // ControllerPort: j.GetControllerListenerPort(),
247 // // // Height: j.GetNewHeight(),
248 // // // PrevBlockHash: j.GetPrevBlockHash(),
249 // // // Bits: j.GetBitses(),
250 // // // Merkles: j.GetHashes(),
251 // // // }
252 // // // return
253 // // // }
254 //
255 // // GetMsgBlock takes the handy go struct version and returns a wire.WireBlock
256 // // ready for giving nonce extranonce and computing the merkel root based on the
257 // // extranonce in the coinbase as needs to be done when mining, so this would be
258 // // called for each round for each algorithm to start.
259 // func (j *Job) GetMsgBlock(version int32) (out *wire.WireBlock) {
260 // found := false
261 // for i := range j.Diffs {
262 // if i == version {
263 // found = true
264 // }
265 // }
266 // if found {
267 // tn := time.Now().Truncate(time.Second)
268 // if tn.Sub(j.MinTimestamp) < time.Second {
269 // tn = j.MinTimestamp
270 // }
271 // out = &wire.WireBlock{
272 // Header: wire.BlockHeader{
273 // Version: version,
274 // PrevBlock: *j.PrevBlockHash,
275 // MerkleRoot: *j.Merkles[version],
276 // Timestamp: tn,
277 // },
278 // // Transactions: j.Txs,
279 // }
280 // }
281 // return
282 // }
283