rossihwang (OP)
Newbie
Offline
Activity: 14
Merit: 0
|
![](https://bitcointalk.org/Themes/custom1/images/post/xx.gif) |
April 30, 2014, 01:37:17 AM |
|
with extranonce2 coinb1 coinb2 extranonce1, i can get the coinbase. and then the coinbase operate with merkle branch somehow, i can get the merkle root. and then combine the version hash1...etc together, i can get the block header. so for example the extranonce2_size is 4 so the extranonce2 is from 0 to 2^32 - 1. is it means that when i get a notify from server, i can generate 2^32 block header from it? is my understanding all right? thx guys!
|
|
|
|
rossihwang (OP)
Newbie
Offline
Activity: 14
Merit: 0
|
![](https://bitcointalk.org/Themes/custom1/images/post/xx.gif) |
May 04, 2014, 01:24:16 AM |
|
anyone helpsssss!
|
|
|
|
colinrgodsey
Newbie
Offline
Activity: 39
Merit: 0
|
![](https://bitcointalk.org/Themes/custom1/images/post/xx.gif) |
May 04, 2014, 04:24:31 AM |
|
As far as I've seen, the extranonce2 info is always 4 bytes.... here's a snippet from ScalaMiner ( https://github.com/colinrgodsey/scalaminer) for generating the header from stratum info (extraNonceInt is a randomly generated 32b int): def getWork(hashType: ScalaMiner.HashType, extraNonceInt: Int, job: MiningJob, extraNonceInfo: ExtraNonce, targetBytes: Seq[Byte], needsMidstate: Boolean) = { val bytes = intToBytes(extraNonceInt) val enBytes = Seq.fill[Byte](extraNonceInfo.extranonce2Size - bytes.length)(0) ++ bytes
val extraNonce = extraNonceInfo.extranonce1 ++ enBytes
val sha256 = new ScalaSha256
val coinbase = ScalaMiner.BufferType.empty ++ job.coinbase1 ++ extraNonce ++ job.coinbase2
val coinbaseHash = doubleHash(coinbase, sha256)
val merkleRoot = reverseEndian(job.merkleBranches.foldLeft(coinbaseHash) { (a, b) => doubleHash(a ++ b, sha256) })
val ntime = (System.currentTimeMillis / 1000) + job.dTime
val serializedHeader = ScalaMiner.BufferType.empty ++ job.protoVersion ++ job.previousHash ++ merkleRoot ++ intToBytes(ntime.toInt) ++ job.nBits ++ intToBytes(0) ++ //enBytes ++ workBasePad
//require(serializedHeader.length == 128, "bad length " + serializedHeader.length)
//TODO: this is the 'old' target? val target = ScalaMiner.BufferType.empty ++ (if(targetBytes.isEmpty) "ffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000".fromHex.toSeq else targetBytes)
val midstate = if(needsMidstate) calculateMidstate(serializedHeader.take(64)) else Nil
Stratum.Job(Work(hashType, serializedHeader, midstate, target), job.id, merkleRoot, enBytes) }
|
|
|
|
rossihwang (OP)
Newbie
Offline
Activity: 14
Merit: 0
|
![](https://bitcointalk.org/Themes/custom1/images/post/xx.gif) |
May 04, 2014, 08:25:02 AM |
|
As far as I've seen, the extranonce2 info is always 4 bytes.... here's a snippet from ScalaMiner ( https://github.com/colinrgodsey/scalaminer) for generating the header from stratum info (extraNonceInt is a randomly generated 32b int): def getWork(hashType: ScalaMiner.HashType, extraNonceInt: Int, job: MiningJob, extraNonceInfo: ExtraNonce, targetBytes: Seq[Byte], needsMidstate: Boolean) = { val bytes = intToBytes(extraNonceInt) val enBytes = Seq.fill[Byte](extraNonceInfo.extranonce2Size - bytes.length)(0) ++ bytes
val extraNonce = extraNonceInfo.extranonce1 ++ enBytes
val sha256 = new ScalaSha256
val coinbase = ScalaMiner.BufferType.empty ++ job.coinbase1 ++ extraNonce ++ job.coinbase2
val coinbaseHash = doubleHash(coinbase, sha256)
val merkleRoot = reverseEndian(job.merkleBranches.foldLeft(coinbaseHash) { (a, b) => doubleHash(a ++ b, sha256) })
val ntime = (System.currentTimeMillis / 1000) + job.dTime
val serializedHeader = ScalaMiner.BufferType.empty ++ job.protoVersion ++ job.previousHash ++ merkleRoot ++ intToBytes(ntime.toInt) ++ job.nBits ++ intToBytes(0) ++ //enBytes ++ workBasePad
//require(serializedHeader.length == 128, "bad length " + serializedHeader.length)
//TODO: this is the 'old' target? val target = ScalaMiner.BufferType.empty ++ (if(targetBytes.isEmpty) "ffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000".fromHex.toSeq else targetBytes)
val midstate = if(needsMidstate) calculateMidstate(serializedHeader.take(64)) else Nil
Stratum.Job(Work(hashType, serializedHeader, midstate, target), job.id, merkleRoot, enBytes) }
to colinrgodsey first of all, thank u for replying me and my new confusion comes: 1) the extraNonceInt in your post is the so-called extranonce2? 2) how can it randomly generated? 3) where does it come from?
|
|
|
|
colinrgodsey
Newbie
Offline
Activity: 39
Merit: 0
|
![](https://bitcointalk.org/Themes/custom1/images/post/xx.gif) |
May 04, 2014, 03:17:31 PM Last edit: May 04, 2014, 03:40:16 PM by colinrgodsey |
|
good question. im not totally sure what the justification is for this part of the hashing process, but ill try to explain what ive gathered...
theres 3 different nonce components in the header:
extranonce1 - used for merkle hash, provided by stratum host extranonce2 - generated by the client! the stratum host will tell you the desired size in bytes (extranonce2_size, >= 4 i think). This number will also have to be submitted with the stratum results as well as the work nonce below. the work nonce - the work guessing portion. these final 4 bytes must be 'guessed' by the mining device
initially, none of this made any damn sense to me, but it cleared up a bit
extranonce1 - still not sure why exactly its here, but ultimately its a source of entropy the pool picks extranonce2 - source of entropy (randomness) from the mining client. with ScalaMiner, i wasnt doing this right initially and mining devices would have lots of 'collisions' (devices scanning the same work range). but technically if 2 different devices have a different extranonce2 value for each of them, they cant mine the same range, because the devices are only guessing 4 bytes of the header. the work nonce - the final 4 bytes of the header, guessed by the mining device! each different extranonce2 and extranonce1 value will give us a completely new set of 2^32 4 bytes values to try for our work nonce range. most mining devices start at 0 for this value and just increment for each guess internally. if you give 2 devices the same extranonce1 and extranonce2, you'll often get identical nonce results, and ultimately duplicate shares.
some mining devices will also happily chew through the nonce range quickly and return no results. 2^32 = 4294967296 hashes, so at 10GH/s, it can chew through all possibilities in about half a second. the mining software at this point should know to submit new work to the device after this long (with a new extranonce2 value, giving it a brand new 2^32 possibilities to try). devices like the BFL BitForce SC line will let you queue up multiple jobs at once because otherwise you'd waste lots of time transferring new nonce ranges to the device.
So ultimately, for each device I start a counter at a random value and increment it randomly each time work is sent. thats the value I end up using for extraNonceInt in the code sample, which is then used to generate the extranonce2 value. giving two devices the same extranonce values can be detrimental, as you might not know they're mining duplicate shares until they finish
|
|
|
|
rossihwang (OP)
Newbie
Offline
Activity: 14
Merit: 0
|
![](https://bitcointalk.org/Themes/custom1/images/post/xx.gif) |
May 05, 2014, 02:01:58 AM |
|
many thanks again!
so as you posted above, i can get a work from stratum server. and disconnect the network. then the miner software increase extranonce2 (randomly?!) to build different header. for each header, in the worest condition, I should guess the nonce for 2^32 -1 times. until I find a nonce whose result hash can meet the target. I reconnect to the stratum server, and submit the extranonce2, nonce and ...in the predefined format. is it correct?
|
|
|
|
colinrgodsey
Newbie
Offline
Activity: 39
Merit: 0
|
![](https://bitcointalk.org/Themes/custom1/images/post/xx.gif) |
May 05, 2014, 12:55:48 PM |
|
correct except for the stratum connection part: stratum is a streaming protocol, so your connection to the server stays open the entire time. Reconnecting may actually give you a new extranonce1 and new job id which would invalidate your results, so you want to keep the connection open for any results you may submit. but yea, extranonce1 is decided by the pool, and they tell you what size extranonce2 to randomly generate (usually 4 bytes), the device then cycles through all the 2^32 nonce possibilities. many thanks again!
so as you posted above, i can get a work from stratum server. and disconnect the network. then the miner software increase extranonce2 (randomly?!) to build different header. for each header, in the worest condition, I should guess the nonce for 2^32 -1 times. until I find a nonce whose result hash can meet the target. I reconnect to the stratum server, and submit the extranonce2, nonce and ...in the predefined format. is it correct?
|
|
|
|
rossihwang (OP)
Newbie
Offline
Activity: 14
Merit: 0
|
![](https://bitcointalk.org/Themes/custom1/images/post/xx.gif) |
May 06, 2014, 01:29:56 AM |
|
get it!thank u very much!
|
|
|
|
|