Created
October 23, 2019 16:05
-
-
Save KireinaHoro/7f88944bdb4e70d96b1e9b71c934ee02 to your computer and use it in GitHub Desktop.
Revisions
-
KireinaHoro created this gist
Oct 23, 2019 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,117 @@ package main import ( "crypto/sha256" "encoding/binary" "encoding/hex" "encoding/json" "fmt" "math/big" "os" "strconv" ) const Id = "1700012980" type Input struct { Block int Version string HashPrevBlock string `json:"hashPrevBlock"` HashMerkleRoot string `json:"hashMerkleRoot"` Time string Bits string } type Output struct { Block int Nonce string Id string } func reverse(a []byte) { for i, j := 0, len(a)-1; i < j; i, j = i+1, j-1 { a[i], a[j] = a[j], a[i] } } func reverseString(a string) string { runes := []rune(a) for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 { runes[i], runes[j] = runes[j], runes[i] } return string(runes) } func decodeToLittleEndian(str string) []byte { ret, err := hex.DecodeString(str[2:]) if err != nil { panic(err) } reverse(ret) return ret } func constructHeader(input Input) []byte { var ret []byte ret = append(ret, decodeToLittleEndian(input.Version)...) ret = append(ret, decodeToLittleEndian(input.HashPrevBlock)...) ret = append(ret, decodeToLittleEndian(input.HashMerkleRoot)...) ret = append(ret, decodeToLittleEndian(input.Time)...) ret = append(ret, decodeToLittleEndian(input.Bits)...) return ret } func hashOnce(headerWithoutNonce []byte, nonce uint32) []byte { bs := make([]byte, 4) binary.LittleEndian.PutUint32(bs, nonce) fullBlock := append(headerWithoutNonce, bs...) firstPass := sha256.Sum256(fullBlock) secondPass := sha256.Sum256(firstPass[:]) return secondPass[:] } func findNonceWithHint(headerWithoutNonce []byte, hint uint32, input Input) *Output { bits, _ := strconv.ParseUint(input.Bits[2:], 16, 32) mantissa := bits & 0x00ffffff exponent := (bits & 0xff000000) >> 24 target := big.NewInt(int64(mantissa)) target.Mul(target, new(big.Int).Exp(big.NewInt(256), big.NewInt(int64(exponent)-3), nil)) targetStr := fmt.Sprintf("%064x", target) fmt.Printf("Target: 0x%s\n", targetStr) for nonce, i := hint, 0; nonce > 0; nonce, i = nonce+1, i+1 { if i%1000 == 0 { fmt.Printf("%d...", i) if i%10000 == 0 { fmt.Print("\n") } } hashStr := reverseString(hex.EncodeToString(hashOnce(headerWithoutNonce, nonce))) if hashStr < targetStr { fmt.Println("===== We have a block now =====") return &Output{ Block: input.Block, Nonce: fmt.Sprintf("0x%08x", nonce), Id: Id, } } } return nil } func runRequest() string { var input Input err := json.NewDecoder(os.Stdin).Decode(&input) if err != nil { panic(err) } ret, err := json.Marshal(findNonceWithHint(constructHeader(input), 0, input)) if err != nil { panic(err) } return string(ret) } func main() { fmt.Println(runRequest()) }