package intermediate import ( "crypto/ecdsa" apiClient "github.com/nspcc-dev/neofs-api-go/pkg/client" reputationapi "github.com/nspcc-dev/neofs-api-go/pkg/reputation" "github.com/nspcc-dev/neofs-node/cmd/neofs-node/reputation/common" "github.com/nspcc-dev/neofs-node/pkg/services/reputation" reputationcommon "github.com/nspcc-dev/neofs-node/pkg/services/reputation/common" eigentrustcalc "github.com/nspcc-dev/neofs-node/pkg/services/reputation/eigentrust/calculator" ) // RemoteProviderPrm groups the required parameters of the RemoteProvider's constructor. // // All values must comply with the requirements imposed on them. // Passing incorrect parameter values will result in constructor // failure (error or panic depending on the implementation). type RemoteProviderPrm struct { Key *ecdsa.PrivateKey } // NewRemoteProvider creates a new instance of the RemoteProvider. // // Panics if at least one value of the parameters is invalid. // // The created RemoteProvider does not require additional // initialization and is completely ready for work. func NewRemoteProvider(prm RemoteProviderPrm) *RemoteProvider { switch { case prm.Key == nil: common.PanicOnPrmValue("NetMapSource", prm.Key) } return &RemoteProvider{ key: prm.Key, } } // RemoteProvider is an implementation of the clientKeyRemoteProvider interface. type RemoteProvider struct { key *ecdsa.PrivateKey } func (rp RemoteProvider) WithClient(c apiClient.Client) reputationcommon.WriterProvider { return &TrustWriterProvider{ client: c, key: rp.key, } } type TrustWriterProvider struct { client apiClient.Client key *ecdsa.PrivateKey } func (twp *TrustWriterProvider) InitWriter(ctx reputationcommon.Context) (reputationcommon.Writer, error) { eiContext, ok := ctx.(eigentrustcalc.Context) if !ok { // TODO: think if this can be done without such limitation panic(ErrIncorrectContextPanicMsg) } return &RemoteTrustWriter{ eiCtx: eiContext, client: twp.client, key: twp.key, }, nil } type RemoteTrustWriter struct { eiCtx eigentrustcalc.Context client apiClient.Client key *ecdsa.PrivateKey buf []*apiClient.AnnounceIntermediateTrustPrm } // Write check if passed context contains required // data(returns ErrIncorrectContext if not) and // caches passed trusts(as SendIntermediateTrustPrm structs). func (rtp *RemoteTrustWriter) Write(t reputation.Trust) error { apiTrustingPeer := reputationapi.NewPeerID() apiTrustingPeer.SetPublicKey(t.TrustingPeer()) apiTrustedPeer := reputationapi.NewPeerID() apiTrustedPeer.SetPublicKey(t.Peer()) apiTrust := reputationapi.NewTrust() apiTrust.SetValue(t.Value().Float64()) apiTrust.SetPeer(apiTrustedPeer) apiPeerToPeerTrust := reputationapi.NewPeerToPeerTrust() apiPeerToPeerTrust.SetTrustingPeer(apiTrustingPeer) apiPeerToPeerTrust.SetTrust(apiTrust) p := &apiClient.AnnounceIntermediateTrustPrm{} p.SetEpoch(rtp.eiCtx.Epoch()) p.SetIteration(rtp.eiCtx.I()) p.SetTrust(apiPeerToPeerTrust) rtp.buf = append(rtp.buf, p) return nil } // Close sends all cached intermediate trusts. // If error occurs, returns in immediately and stops iteration. func (rtp *RemoteTrustWriter) Close() (err error) { for _, prm := range rtp.buf { _, err = rtp.client.AnnounceIntermediateTrust( rtp.eiCtx, *prm, apiClient.WithKey(rtp.key), ) if err != nil { return } } return }