65
vendor/github.com/status-im/status-go/protocol/datasync/datasync.go
generated
vendored
Normal file
65
vendor/github.com/status-im/status-go/protocol/datasync/datasync.go
generated
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
package datasync
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"errors"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
datasyncnode "github.com/status-im/mvds/node"
|
||||
"github.com/status-im/mvds/protobuf"
|
||||
datasyncproto "github.com/status-im/mvds/protobuf"
|
||||
datasynctransport "github.com/status-im/mvds/transport"
|
||||
"go.uber.org/zap"
|
||||
|
||||
datasyncpeer "github.com/status-im/status-go/protocol/datasync/peer"
|
||||
)
|
||||
|
||||
type DataSync struct {
|
||||
*datasyncnode.Node
|
||||
// NodeTransport is the implementation of the datasync transport interface.
|
||||
*NodeTransport
|
||||
logger *zap.Logger
|
||||
sendingEnabled bool
|
||||
}
|
||||
|
||||
func New(node *datasyncnode.Node, transport *NodeTransport, sendingEnabled bool, logger *zap.Logger) *DataSync {
|
||||
return &DataSync{Node: node, NodeTransport: transport, sendingEnabled: sendingEnabled, logger: logger}
|
||||
}
|
||||
|
||||
// Unwrap tries to unwrap datasync message and passes back the message to datasync in order to acknowledge any potential message and mark messages as acknowledged
|
||||
func (d *DataSync) Unwrap(sender *ecdsa.PublicKey, payload []byte) (*protobuf.Payload, error) {
|
||||
logger := d.logger.With(zap.String("site", "Handle"))
|
||||
|
||||
datasyncMessage, err := unwrap(payload)
|
||||
// If it failed to decode is not a protobuf message, if it successfully decoded but body is empty, is likedly a protobuf wrapped message
|
||||
if err != nil {
|
||||
logger.Debug("Unwrapping datasync message failed", zap.Error(err))
|
||||
return nil, err
|
||||
} else if !datasyncMessage.IsValid() {
|
||||
return nil, errors.New("handling non-datasync message")
|
||||
} else {
|
||||
logger.Debug("handling datasync message")
|
||||
if d.sendingEnabled {
|
||||
d.add(sender, &datasyncMessage)
|
||||
}
|
||||
}
|
||||
|
||||
return &datasyncMessage, nil
|
||||
}
|
||||
|
||||
func (d *DataSync) Stop() {
|
||||
d.Node.Stop()
|
||||
}
|
||||
|
||||
func (d *DataSync) add(publicKey *ecdsa.PublicKey, datasyncMessage *datasyncproto.Payload) {
|
||||
packet := datasynctransport.Packet{
|
||||
Sender: datasyncpeer.PublicKeyToPeerID(*publicKey),
|
||||
Payload: datasyncMessage,
|
||||
}
|
||||
d.NodeTransport.AddPacket(packet)
|
||||
}
|
||||
|
||||
func unwrap(payload []byte) (datasyncPayload datasyncproto.Payload, err error) {
|
||||
err = proto.Unmarshal(payload, &datasyncPayload)
|
||||
return
|
||||
}
|
||||
19
vendor/github.com/status-im/status-go/protocol/datasync/peer/utils.go
generated
vendored
Normal file
19
vendor/github.com/status-im/status-go/protocol/datasync/peer/utils.go
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
package peer
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
|
||||
"github.com/status-im/mvds/state"
|
||||
|
||||
"github.com/status-im/status-go/eth-node/crypto"
|
||||
)
|
||||
|
||||
func PublicKeyToPeerID(k ecdsa.PublicKey) state.PeerID {
|
||||
var p state.PeerID
|
||||
copy(p[:], crypto.FromECDSAPub(&k))
|
||||
return p
|
||||
}
|
||||
|
||||
func IDToPublicKey(p state.PeerID) (*ecdsa.PublicKey, error) {
|
||||
return crypto.UnmarshalPubkey(p[:])
|
||||
}
|
||||
70
vendor/github.com/status-im/status-go/protocol/datasync/transport.go
generated
vendored
Normal file
70
vendor/github.com/status-im/status-go/protocol/datasync/transport.go
generated
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
package datasync
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"math"
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
"github.com/status-im/mvds/protobuf"
|
||||
"github.com/status-im/mvds/state"
|
||||
"github.com/status-im/mvds/transport"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
const backoffInterval = 30
|
||||
|
||||
var errNotInitialized = errors.New("datasync transport not initialized")
|
||||
var DatasyncTicker = 300 * time.Millisecond
|
||||
|
||||
// It's easier to calculate nextEpoch if we consider seconds as a unit rather than
|
||||
// 300 ms, so we multiply the result by the ratio
|
||||
var offsetToSecond = uint64(time.Second / DatasyncTicker)
|
||||
|
||||
type NodeTransport struct {
|
||||
packets chan transport.Packet
|
||||
logger *zap.Logger
|
||||
dispatch func(state.PeerID, *protobuf.Payload) error
|
||||
}
|
||||
|
||||
func NewNodeTransport() *NodeTransport {
|
||||
return &NodeTransport{
|
||||
packets: make(chan transport.Packet),
|
||||
}
|
||||
}
|
||||
|
||||
func (t *NodeTransport) Init(dispatch func(state.PeerID, *protobuf.Payload) error, logger *zap.Logger) {
|
||||
t.dispatch = dispatch
|
||||
t.logger = logger
|
||||
}
|
||||
|
||||
func (t *NodeTransport) AddPacket(p transport.Packet) {
|
||||
t.packets <- p
|
||||
}
|
||||
|
||||
func (t *NodeTransport) Watch() transport.Packet {
|
||||
return <-t.packets
|
||||
}
|
||||
|
||||
func (t *NodeTransport) Send(_ state.PeerID, peer state.PeerID, payload *protobuf.Payload) error {
|
||||
if t.dispatch == nil {
|
||||
return errNotInitialized
|
||||
}
|
||||
|
||||
// We don't return an error otherwise datasync will keep
|
||||
// re-trying sending at each epoch
|
||||
err := t.dispatch(peer, payload)
|
||||
if err != nil {
|
||||
t.logger.Error("failed to send message", zap.Error(err))
|
||||
return nil
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// CalculateSendTime calculates the next epoch
|
||||
// at which a message should be sent.
|
||||
// We randomize it a bit so that not all messages are sent on the same epoch
|
||||
func CalculateSendTime(count uint64, time int64) int64 {
|
||||
return time + int64(uint64(math.Exp2(float64(count-1)))*backoffInterval*offsetToSecond) + int64(rand.Intn(30)) // nolint: gosec
|
||||
}
|
||||
30
vendor/github.com/status-im/status-go/protocol/datasync/utils.go
generated
vendored
Normal file
30
vendor/github.com/status-im/status-go/protocol/datasync/utils.go
generated
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
package datasync
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
|
||||
"github.com/status-im/mvds/state"
|
||||
|
||||
"github.com/status-im/status-go/eth-node/crypto"
|
||||
)
|
||||
|
||||
func ToGroupID(data []byte) state.GroupID {
|
||||
g := state.GroupID{}
|
||||
copy(g[:], data[:])
|
||||
return g
|
||||
}
|
||||
|
||||
// ToOneToOneGroupID returns a groupID for a onetoonechat, which is taken by
|
||||
// concatenating the bytes of the compressed keys, in ascending order by X
|
||||
func ToOneToOneGroupID(key1 *ecdsa.PublicKey, key2 *ecdsa.PublicKey) state.GroupID {
|
||||
pk1 := crypto.CompressPubkey(key1)
|
||||
pk2 := crypto.CompressPubkey(key2)
|
||||
var groupID []byte
|
||||
if key1.X.Cmp(key2.X) == -1 {
|
||||
groupID = append(pk1, pk2...)
|
||||
} else {
|
||||
groupID = append(pk2, pk1...)
|
||||
}
|
||||
|
||||
return ToGroupID(crypto.Keccak256(groupID))
|
||||
}
|
||||
Reference in New Issue
Block a user