github.com/nspcc-dev/neo-go@v0.105.2-0.20240517133400-6be757af3eba/pkg/services/oracle/broadcaster/oracle.go (about)

     1  package broadcaster
     2  
     3  import (
     4  	"encoding/base64"
     5  	"encoding/binary"
     6  	"time"
     7  
     8  	"github.com/nspcc-dev/neo-go/pkg/config"
     9  	"github.com/nspcc-dev/neo-go/pkg/core/transaction"
    10  	"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
    11  	"github.com/nspcc-dev/neo-go/pkg/rpcclient"
    12  	"github.com/nspcc-dev/neo-go/pkg/services/helpers/rpcbroadcaster"
    13  	"go.uber.org/zap"
    14  )
    15  
    16  const (
    17  	defaultSendTimeout = time.Second * 4
    18  
    19  	defaultChanCapacity = 16
    20  )
    21  
    22  // OracleBroadcaster is an oracle broadcaster implementation.
    23  type OracleBroadcaster struct {
    24  	rpcbroadcaster.RPCBroadcaster
    25  }
    26  
    27  // New returns a new struct capable of broadcasting oracle responses.
    28  func New(cfg config.OracleConfiguration, log *zap.Logger) *OracleBroadcaster {
    29  	if cfg.ResponseTimeout == 0 {
    30  		cfg.ResponseTimeout = defaultSendTimeout
    31  	}
    32  	r := &OracleBroadcaster{
    33  		RPCBroadcaster: *rpcbroadcaster.NewRPCBroadcaster(log, cfg.ResponseTimeout),
    34  	}
    35  	for i := range cfg.Nodes {
    36  		r.Clients[cfg.Nodes[i]] = r.NewRPCClient(cfg.Nodes[i], (*rpcclient.Client).SubmitRawOracleResponse,
    37  			cfg.ResponseTimeout, make(chan []any, defaultChanCapacity))
    38  	}
    39  	return r
    40  }
    41  
    42  // SendResponse implements interfaces.Broadcaster.
    43  func (r *OracleBroadcaster) SendResponse(priv *keys.PrivateKey, resp *transaction.OracleResponse, txSig []byte) {
    44  	pub := priv.PublicKey()
    45  	data := GetMessage(pub.Bytes(), resp.ID, txSig)
    46  	msgSig := priv.Sign(data)
    47  	params := []any{
    48  		base64.StdEncoding.EncodeToString(pub.Bytes()),
    49  		resp.ID,
    50  		base64.StdEncoding.EncodeToString(txSig),
    51  		base64.StdEncoding.EncodeToString(msgSig),
    52  	}
    53  	r.SendParams(params)
    54  }
    55  
    56  // GetMessage returns data which is signed upon sending response by RPC.
    57  func GetMessage(pubBytes []byte, reqID uint64, txSig []byte) []byte {
    58  	data := make([]byte, len(pubBytes)+8+len(txSig))
    59  	copy(data, pubBytes)
    60  	binary.LittleEndian.PutUint64(data[len(pubBytes):], uint64(reqID))
    61  	copy(data[len(pubBytes)+8:], txSig)
    62  	return data
    63  }