2020-09-28 11:58:04 +00:00
|
|
|
package broadcaster
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/base64"
|
|
|
|
"encoding/binary"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/nspcc-dev/neo-go/pkg/config"
|
|
|
|
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
|
|
|
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
2022-07-21 19:39:53 +00:00
|
|
|
"github.com/nspcc-dev/neo-go/pkg/rpcclient"
|
2021-02-02 07:45:02 +00:00
|
|
|
"github.com/nspcc-dev/neo-go/pkg/services/helpers/rpcbroadcaster"
|
2020-09-28 11:58:04 +00:00
|
|
|
"github.com/nspcc-dev/neo-go/pkg/services/oracle"
|
|
|
|
"go.uber.org/zap"
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
defaultSendTimeout = time.Second * 4
|
2020-10-08 11:50:10 +00:00
|
|
|
|
|
|
|
defaultChanCapacity = 16
|
2020-09-28 11:58:04 +00:00
|
|
|
)
|
|
|
|
|
2021-02-02 07:45:02 +00:00
|
|
|
type oracleBroadcaster struct {
|
|
|
|
rpcbroadcaster.RPCBroadcaster
|
|
|
|
}
|
|
|
|
|
2022-04-20 18:30:09 +00:00
|
|
|
// New returns a new struct capable of broadcasting oracle responses.
|
2020-09-28 11:58:04 +00:00
|
|
|
func New(cfg config.OracleConfiguration, log *zap.Logger) oracle.Broadcaster {
|
|
|
|
if cfg.ResponseTimeout == 0 {
|
|
|
|
cfg.ResponseTimeout = defaultSendTimeout
|
|
|
|
}
|
2021-02-02 07:45:02 +00:00
|
|
|
r := &oracleBroadcaster{
|
|
|
|
RPCBroadcaster: *rpcbroadcaster.NewRPCBroadcaster(log, cfg.ResponseTimeout),
|
2020-09-28 11:58:04 +00:00
|
|
|
}
|
|
|
|
for i := range cfg.Nodes {
|
2022-07-21 19:39:53 +00:00
|
|
|
r.Clients[cfg.Nodes[i]] = r.NewRPCClient(cfg.Nodes[i], (*rpcclient.Client).SubmitRawOracleResponse,
|
2022-07-07 17:03:10 +00:00
|
|
|
cfg.ResponseTimeout, make(chan []interface{}, defaultChanCapacity))
|
2020-09-28 11:58:04 +00:00
|
|
|
}
|
|
|
|
return r
|
|
|
|
}
|
|
|
|
|
|
|
|
// SendResponse implements interfaces.Broadcaster.
|
2021-02-02 07:45:02 +00:00
|
|
|
func (r *oracleBroadcaster) SendResponse(priv *keys.PrivateKey, resp *transaction.OracleResponse, txSig []byte) {
|
2020-09-28 11:58:04 +00:00
|
|
|
pub := priv.PublicKey()
|
|
|
|
data := GetMessage(pub.Bytes(), resp.ID, txSig)
|
|
|
|
msgSig := priv.Sign(data)
|
2022-07-07 17:03:10 +00:00
|
|
|
params := []interface{}{
|
2020-09-28 11:58:04 +00:00
|
|
|
base64.StdEncoding.EncodeToString(pub.Bytes()),
|
|
|
|
resp.ID,
|
|
|
|
base64.StdEncoding.EncodeToString(txSig),
|
|
|
|
base64.StdEncoding.EncodeToString(msgSig),
|
2022-07-07 17:03:10 +00:00
|
|
|
}
|
2022-07-01 20:04:54 +00:00
|
|
|
r.SendParams(params)
|
2020-09-28 11:58:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// GetMessage returns data which is signed upon sending response by RPC.
|
|
|
|
func GetMessage(pubBytes []byte, reqID uint64, txSig []byte) []byte {
|
|
|
|
data := make([]byte, len(pubBytes)+8+len(txSig))
|
|
|
|
copy(data, pubBytes)
|
|
|
|
binary.LittleEndian.PutUint64(data[len(pubBytes):], uint64(reqID))
|
|
|
|
copy(data[len(pubBytes)+8:], txSig)
|
|
|
|
return data
|
|
|
|
}
|