commit
e456451a89
|
@ -1,7 +1,6 @@
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/ethereum/go-ethereum",
|
"ImportPath": "github.com/ethereum/go-ethereum",
|
||||||
"GoVersion": "go1.5.2",
|
"GoVersion": "go1.5.2",
|
||||||
"GodepVersion": "v60",
|
|
||||||
"Packages": [
|
"Packages": [
|
||||||
"./..."
|
"./..."
|
||||||
],
|
],
|
||||||
|
@ -21,8 +20,8 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/ethereum/ethash",
|
"ImportPath": "github.com/ethereum/ethash",
|
||||||
"Comment": "v23.1-242-gbc9ba4d",
|
"Comment": "v23.1-245-g25b32de",
|
||||||
"Rev": "bc9ba4d6a83a0fe308fefd8c6001b8ed1607137f"
|
"Rev": "25b32de0c0271065c28c3719c2bfe86959d72f0c"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/fatih/color",
|
"ImportPath": "github.com/fatih/color",
|
||||||
|
|
|
@ -105,6 +105,15 @@ func freeCache(cache *cache) {
|
||||||
cache.ptr = nil
|
cache.ptr = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (cache *cache) compute(dagSize uint64, hash common.Hash, nonce uint64) (ok bool, mixDigest, result common.Hash) {
|
||||||
|
ret := C.ethash_light_compute_internal(cache.ptr, C.uint64_t(dagSize), hashToH256(hash), C.uint64_t(nonce))
|
||||||
|
// Make sure cache is live until after the C call.
|
||||||
|
// This is important because a GC might happen and execute
|
||||||
|
// the finalizer before the call completes.
|
||||||
|
_ = cache
|
||||||
|
return bool(ret.success), h256ToHash(ret.mix_hash), h256ToHash(ret.result)
|
||||||
|
}
|
||||||
|
|
||||||
// Light implements the Verify half of the proof of work. It uses a few small
|
// Light implements the Verify half of the proof of work. It uses a few small
|
||||||
// in-memory caches to verify the nonces found by Full.
|
// in-memory caches to verify the nonces found by Full.
|
||||||
type Light struct {
|
type Light struct {
|
||||||
|
@ -140,29 +149,23 @@ func (l *Light) Verify(block pow.Block) bool {
|
||||||
|
|
||||||
cache := l.getCache(blockNum)
|
cache := l.getCache(blockNum)
|
||||||
dagSize := C.ethash_get_datasize(C.uint64_t(blockNum))
|
dagSize := C.ethash_get_datasize(C.uint64_t(blockNum))
|
||||||
|
|
||||||
if l.test {
|
if l.test {
|
||||||
dagSize = dagSizeForTesting
|
dagSize = dagSizeForTesting
|
||||||
}
|
}
|
||||||
// Recompute the hash using the cache.
|
// Recompute the hash using the cache.
|
||||||
hash := hashToH256(block.HashNoNonce())
|
ok, mixDigest, result := cache.compute(uint64(dagSize), block.HashNoNonce(), block.Nonce())
|
||||||
ret := C.ethash_light_compute_internal(cache.ptr, dagSize, hash, C.uint64_t(block.Nonce()))
|
if !ok {
|
||||||
if !ret.success {
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// avoid mixdigest malleability as it's not included in a block's "hashNononce"
|
// avoid mixdigest malleability as it's not included in a block's "hashNononce"
|
||||||
if block.MixDigest() != h256ToHash(ret.mix_hash) {
|
if block.MixDigest() != mixDigest {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure cache is live until after the C call.
|
|
||||||
// This is important because a GC might happen and execute
|
|
||||||
// the finalizer before the call completes.
|
|
||||||
_ = cache
|
|
||||||
// The actual check.
|
// The actual check.
|
||||||
target := new(big.Int).Div(maxUint256, difficulty)
|
target := new(big.Int).Div(maxUint256, difficulty)
|
||||||
return h256ToHash(ret.result).Big().Cmp(target) <= 0
|
return result.Big().Cmp(target) <= 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func h256ToHash(in C.ethash_h256_t) common.Hash {
|
func h256ToHash(in C.ethash_h256_t) common.Hash {
|
||||||
|
|
|
@ -138,7 +138,7 @@ func PrintDevices() {
|
||||||
|
|
||||||
platforms, err := cl.GetPlatforms()
|
platforms, err := cl.GetPlatforms()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("Plaform error (check your OpenCL installation): %v", err)
|
fmt.Println("Plaform error (check your OpenCL installation):", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -267,13 +267,13 @@ func initCLDevice(deviceId int, device *cl.Device, c *OpenCLMiner) error {
|
||||||
|
|
||||||
context, err := cl.CreateContext([]*cl.Device{device})
|
context, err := cl.CreateContext([]*cl.Device{device})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed creating context:", err)
|
return fmt.Errorf("failed creating context: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: test running with CL_QUEUE_PROFILING_ENABLE for profiling?
|
// TODO: test running with CL_QUEUE_PROFILING_ENABLE for profiling?
|
||||||
queue, err := context.CreateCommandQueue(device, 0)
|
queue, err := context.CreateCommandQueue(device, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("command queue err:", err)
|
return fmt.Errorf("command queue err: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// See [4] section 3.2 and [3] "clBuildProgram".
|
// See [4] section 3.2 and [3] "clBuildProgram".
|
||||||
|
@ -287,7 +287,7 @@ func initCLDevice(deviceId int, device *cl.Device, c *OpenCLMiner) error {
|
||||||
|
|
||||||
program, err := context.CreateProgramWithSource([]string{kernelCode})
|
program, err := context.CreateProgramWithSource([]string{kernelCode})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("program err:", err)
|
return fmt.Errorf("program err: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if using AMD OpenCL impl, you can set this to debug on x86 CPU device.
|
/* if using AMD OpenCL impl, you can set this to debug on x86 CPU device.
|
||||||
|
@ -303,7 +303,7 @@ func initCLDevice(deviceId int, device *cl.Device, c *OpenCLMiner) error {
|
||||||
buildOpts := ""
|
buildOpts := ""
|
||||||
err = program.BuildProgram([]*cl.Device{device}, buildOpts)
|
err = program.BuildProgram([]*cl.Device{device}, buildOpts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("program build err:", err)
|
return fmt.Errorf("program build err: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var searchKernelName, hashKernelName string
|
var searchKernelName, hashKernelName string
|
||||||
|
@ -313,7 +313,7 @@ func initCLDevice(deviceId int, device *cl.Device, c *OpenCLMiner) error {
|
||||||
searchKernel, err := program.CreateKernel(searchKernelName)
|
searchKernel, err := program.CreateKernel(searchKernelName)
|
||||||
hashKernel, err := program.CreateKernel(hashKernelName)
|
hashKernel, err := program.CreateKernel(hashKernelName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("kernel err:", err)
|
return fmt.Errorf("kernel err: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: when this DAG size appears, patch the Go bindings
|
// TODO: when this DAG size appears, patch the Go bindings
|
||||||
|
@ -328,28 +328,28 @@ func initCLDevice(deviceId int, device *cl.Device, c *OpenCLMiner) error {
|
||||||
dagBuf := *(new(*cl.MemObject))
|
dagBuf := *(new(*cl.MemObject))
|
||||||
dagBuf, err = context.CreateEmptyBuffer(cl.MemReadOnly, int(c.dagSize))
|
dagBuf, err = context.CreateEmptyBuffer(cl.MemReadOnly, int(c.dagSize))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("allocating dag buf failed: ", err)
|
return fmt.Errorf("allocating dag buf failed: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// write DAG to device mem
|
// write DAG to device mem
|
||||||
dagPtr := unsafe.Pointer(c.ethash.Full.current.ptr.data)
|
dagPtr := unsafe.Pointer(c.ethash.Full.current.ptr.data)
|
||||||
_, err = queue.EnqueueWriteBuffer(dagBuf, true, 0, int(c.dagSize), dagPtr, nil)
|
_, err = queue.EnqueueWriteBuffer(dagBuf, true, 0, int(c.dagSize), dagPtr, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("writing to dag buf failed: ", err)
|
return fmt.Errorf("writing to dag buf failed: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
searchBuffers := make([]*cl.MemObject, searchBufSize)
|
searchBuffers := make([]*cl.MemObject, searchBufSize)
|
||||||
for i := 0; i < searchBufSize; i++ {
|
for i := 0; i < searchBufSize; i++ {
|
||||||
searchBuff, err := context.CreateEmptyBuffer(cl.MemWriteOnly, (1+maxSearchResults)*SIZEOF_UINT32)
|
searchBuff, err := context.CreateEmptyBuffer(cl.MemWriteOnly, (1+maxSearchResults)*SIZEOF_UINT32)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("search buffer err:", err)
|
return fmt.Errorf("search buffer err: %v", err)
|
||||||
}
|
}
|
||||||
searchBuffers[i] = searchBuff
|
searchBuffers[i] = searchBuff
|
||||||
}
|
}
|
||||||
|
|
||||||
headerBuf, err := context.CreateEmptyBuffer(cl.MemReadOnly, 32)
|
headerBuf, err := context.CreateEmptyBuffer(cl.MemReadOnly, 32)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("header buffer err:", err)
|
return fmt.Errorf("header buffer err: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unique, random nonces are crucial for mining efficieny.
|
// Unique, random nonces are crucial for mining efficieny.
|
||||||
|
@ -556,13 +556,13 @@ func (c *OpenCLMiner) Search(block pow.Block, stop <-chan struct{}, index int) (
|
||||||
upperNonce := uint64(binary.LittleEndian.Uint32(results[lo:hi]))
|
upperNonce := uint64(binary.LittleEndian.Uint32(results[lo:hi]))
|
||||||
checkNonce = p.startNonce + upperNonce
|
checkNonce = p.startNonce + upperNonce
|
||||||
if checkNonce != 0 {
|
if checkNonce != 0 {
|
||||||
cn := C.uint64_t(checkNonce)
|
|
||||||
ds := C.uint64_t(c.dagSize)
|
|
||||||
// We verify that the nonce is indeed a solution by
|
// We verify that the nonce is indeed a solution by
|
||||||
// executing the Ethash verification function (on the CPU).
|
// executing the Ethash verification function (on the CPU).
|
||||||
ret := C.ethash_light_compute_internal(c.ethash.Light.current.ptr, ds, hashToH256(headerHash), cn)
|
cache := c.ethash.Light.getCache(block.NumberU64())
|
||||||
|
ok, mixDigest, result := cache.compute(c.dagSize, headerHash, checkNonce)
|
||||||
|
|
||||||
// TODO: return result first
|
// TODO: return result first
|
||||||
if ret.success && h256ToHash(ret.result).Big().Cmp(target256) <= 0 {
|
if ok && result.Big().Cmp(target256) <= 0 {
|
||||||
_, err = d.queue.EnqueueUnmapMemObject(d.searchBuffers[p.bufIndex], cres, nil)
|
_, err = d.queue.EnqueueUnmapMemObject(d.searchBuffers[p.bufIndex], cres, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("Error in Search clEnqueueUnmapMemObject: ", err)
|
fmt.Println("Error in Search clEnqueueUnmapMemObject: ", err)
|
||||||
|
@ -573,9 +573,8 @@ func (c *OpenCLMiner) Search(block pow.Block, stop <-chan struct{}, index int) (
|
||||||
fmt.Println("Error in Search WaitForEvents: ", err)
|
fmt.Println("Error in Search WaitForEvents: ", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return checkNonce, C.GoBytes(unsafe.Pointer(&ret.mix_hash), C.int(32))
|
return checkNonce, mixDigest.Bytes()
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := d.queue.EnqueueWriteBuffer(d.searchBuffers[p.bufIndex], false, 0, 4, unsafe.Pointer(&zero), nil)
|
_, err := d.queue.EnqueueWriteBuffer(d.searchBuffers[p.bufIndex], false, 0, 4, unsafe.Pointer(&zero), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("Error in Search cl: EnqueueWriteBuffer", err)
|
fmt.Println("Error in Search cl: EnqueueWriteBuffer", err)
|
||||||
|
|
|
@ -3,7 +3,7 @@ package xhandler
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/Godeps/_workspace/src/golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Chain is an helper to chain middleware handlers together for an easier
|
// Chain is an helper to chain middleware handlers together for an easier
|
||||||
|
|
|
@ -4,7 +4,7 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/Godeps/_workspace/src/golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CloseHandler returns a Handler cancelling the context when the client
|
// CloseHandler returns a Handler cancelling the context when the client
|
||||||
|
|
|
@ -14,7 +14,7 @@ package xhandler
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/Godeps/_workspace/src/golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
)
|
)
|
||||||
|
|
||||||
// HandlerC is a net/context aware http.Handler
|
// HandlerC is a net/context aware http.Handler
|
||||||
|
|
|
@ -56,8 +56,7 @@ func (s *Ethereum) StartMining(threads int, gpus string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: re-creating miner is a bit ugly
|
// TODO: re-creating miner is a bit ugly
|
||||||
cl := ethash.NewCL(ids)
|
s.miner = miner.New(s, s.chainConfig, s.EventMux(), ethash.NewCL(ids))
|
||||||
s.miner = miner.New(s, s.EventMux(), cl)
|
|
||||||
go s.miner.Start(eb, len(ids))
|
go s.miner.Start(eb, len(ids))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue