1// SPDX-License-Identifier: ISC
2// Copyright (c) 2014-2020 Bitmark Inc.
3// Use of this source code is governed by an ISC
4// license that can be found in the LICENSE file.
5
6package proof
7
8import (
9	"encoding/binary"
10	"encoding/json"
11
12	zmq "github.com/pebbe/zmq4"
13
14	"github.com/bitmark-inc/bitmarkd/blockrecord"
15	"github.com/bitmark-inc/bitmarkd/fault"
16)
17
18const (
19	internalHasherProtocol = zmq.PAIR
20)
21
22type hashingRequest struct {
23	Job    string
24	Header blockrecord.Header
25}
26
27// InternalHasher - this dummy hasher is for test usage
28type InternalHasher interface {
29	Initialise() error
30	Start()
31}
32
33type internalHasher struct {
34	endpointRequestStr string
35	endpointReplyStr   string
36	requestSocket      *zmq.Socket // receive hash request
37	replySocket        *zmq.Socket // send hash result reply
38}
39
40func (h *internalHasher) Initialise() error {
41	requestSocket, err := zmq.NewSocket(internalHasherProtocol)
42	if nil != err {
43		return err
44	}
45
46	err = requestSocket.Connect(h.endpointRequestStr)
47	if nil != err {
48		return err
49	}
50	h.requestSocket = requestSocket
51
52	replySocket, err := zmq.NewSocket(internalHasherProtocol)
53	if nil != err {
54		return err
55	}
56
57	err = replySocket.Bind(h.endpointReplyStr)
58	if nil != err {
59		return err
60	}
61	h.replySocket = replySocket
62
63	return nil
64}
65
66func (h *internalHasher) Start() {
67	go func() {
68	loop:
69		for i := 1; ; i++ {
70			msg, err := h.requestSocket.Recv(0)
71			if nil != err {
72				continue loop
73			}
74
75			var request hashingRequest
76			_ = json.Unmarshal([]byte(msg), &request)
77			nonce := make([]byte, blockrecord.NonceSize)
78			binary.LittleEndian.PutUint64(nonce, uint64(i))
79
80			reply := struct {
81				Request string
82				Job     string
83				Packed  []byte
84			}{
85				Request: "block.nonce",
86				Job:     request.Job,
87				Packed:  nonce,
88			}
89
90			replyData, _ := json.Marshal(reply)
91
92			_, err = h.replySocket.SendBytes(replyData, 0)
93			if nil != err {
94				continue loop
95			}
96		}
97	}()
98}
99
100func NewInternalHasherForTest(request, reply string) (InternalHasher, error) {
101	if request == reply {
102		return nil, fault.WrongEndpointString
103	}
104
105	return &internalHasher{
106		endpointRequestStr: request,
107		endpointReplyStr:   reply,
108	}, nil
109}
110