fix: determine if a enr contains a UDP port (#2864)

This commit is contained in:
Richard Ramos 2022-09-16 09:09:13 -04:00 committed by GitHub
parent 6f93913be5
commit 824bb17ba9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 285 additions and 88 deletions

View File

@ -1 +1 @@
0.109.4
0.110.0

4
go.mod
View File

@ -54,7 +54,7 @@ require (
github.com/prometheus/client_golang v1.12.1
github.com/russolsen/transit v0.0.0-20180705123435-0794b4c4505a
github.com/status-im/doubleratchet v3.0.0+incompatible
github.com/status-im/go-waku v0.1.1-0.20220819160153-b0761ad70648
github.com/status-im/go-waku v0.2.3-0.20220915230805-448f5a2e0ef6
github.com/status-im/go-waku-rendezvous v0.0.0-20220817210730-9b9b02b1e880
github.com/status-im/markdown v0.0.0-20220622180305-7ee4aa8bbc3f
github.com/status-im/migrate/v4 v4.6.2-status.2
@ -241,7 +241,7 @@ require (
github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/status-im/go-discover v0.0.0-20220406135310-85a2ce36f63e // indirect
github.com/status-im/go-multiaddr-ethv4 v1.2.3 // indirect
github.com/status-im/go-rln v0.0.9 // indirect
github.com/status-im/go-rln v0.1.1 // indirect
github.com/status-im/keycard-go v0.0.0-20200402102358-957c09536969 // indirect
github.com/tklauser/go-sysconf v0.3.6 // indirect
github.com/tklauser/numcpus v0.2.2 // indirect

8
go.sum
View File

@ -2107,10 +2107,10 @@ github.com/status-im/go-ethereum v1.10.4-status.4 h1:Cs0MoHEhF0LEwii2R8U8jMSEW/g
github.com/status-im/go-ethereum v1.10.4-status.4/go.mod h1:GvIhpdCOgMHI6i5xVPEZOrv/qSMeOFHbZh77AoyZUoE=
github.com/status-im/go-multiaddr-ethv4 v1.2.3 h1:EdMt0rCVcue9zQ3TZoUVrKel0HG+RfbuqY94PXd3AWk=
github.com/status-im/go-multiaddr-ethv4 v1.2.3/go.mod h1:xgjMcsI3pNezwNVlUnUmaDLVmtT871/OOqnEUublHKQ=
github.com/status-im/go-rln v0.0.9 h1:qDmFJoFS/1PGNDB0pEjlRDRNZUpIFBAde2f3fIixCbA=
github.com/status-im/go-rln v0.0.9/go.mod h1:t8Bf4nNAuQh9VlEiz/rgFVtEz7sjEfcd62MIuEnZn8U=
github.com/status-im/go-waku v0.1.1-0.20220819160153-b0761ad70648 h1:WxLTpw+waqh21ykspOQAK688MbfpRrWO6wbJeljstgg=
github.com/status-im/go-waku v0.1.1-0.20220819160153-b0761ad70648/go.mod h1:Z4K27xrsvQvOI23hX92wDJDPtaEHeiTLn7cSNOHzq44=
github.com/status-im/go-rln v0.1.1 h1:Evbma0GZ0dgzbKcm92SWzHMZ4pOlVBxH1+z9eQAd1i4=
github.com/status-im/go-rln v0.1.1/go.mod h1:t8Bf4nNAuQh9VlEiz/rgFVtEz7sjEfcd62MIuEnZn8U=
github.com/status-im/go-waku v0.2.3-0.20220915230805-448f5a2e0ef6 h1:9BB5PtaKOJJbpj+GKc/2ixRXHLdc0MCRbj2ZszP0+tU=
github.com/status-im/go-waku v0.2.3-0.20220915230805-448f5a2e0ef6/go.mod h1:yHFOjS30GLuCiS+UqblYd46McaorFlwMQ3tM32aofSU=
github.com/status-im/go-waku-rendezvous v0.0.0-20220817210730-9b9b02b1e880 h1:Ggyf88sYbHV3q/qVNMNsq+JMiar1WRkiDTr+VdTPyVk=
github.com/status-im/go-waku-rendezvous v0.0.0-20220817210730-9b9b02b1e880/go.mod h1:lYUCd41Gzh6bw8RYlbADWe+LQCvhxnq2e19QWxdDM0k=
github.com/status-im/go-watchdog v1.2.0-ios-nolibproc h1:BJwZEF7OVKaXc2zErBUAolFSGzwrTBbWnN8e/6MER5E=

View File

@ -11,10 +11,6 @@ package rln
#cgo linux,amd64,musl,!android LDFLAGS:-L${SRCDIR}/../libs/x86_64-unknown-linux-musl
#cgo linux,amd64,!musl,!android LDFLAGS:-L${SRCDIR}/../libs/x86_64-unknown-linux-gnu
#cgo linux,386 LDFLAGS:-L${SRCDIR}/../libs/i686-unknown-linux-gnu
#cgo linux,mips LDFLAGS:-L${SRCDIR}/../libs/mips-unknown-linux-gnu
#cgo linux,mips64 LDFLAGS:-L${SRCDIR}/../libs/mips64-unknown-linux-gnuabi64
#cgo linux,mips64le LDFLAGS:-L${SRCDIR}/../libs/mips64el-unknown-linux-gnuabi64
#cgo linux,mipsle LDFLAGS:-L${SRCDIR}/../libs/mipsel-unknown-linux-gnu
#cgo windows,386 LDFLAGS:-L${SRCDIR}/../libs/i686-pc-windows-gnu -lrln -lm -lws2_32 -luserenv
#cgo windows,amd64 LDFLAGS:-L${SRCDIR}/../libs/x86_64-pc-windows-gnu -lrln -lm -lws2_32 -luserenv
#cgo darwin,386,!ios LDFLAGS:-L${SRCDIR}/../libs/i686-apple-darwin

View File

@ -236,7 +236,7 @@ func (d *DBStore) Put(env *protocol.Envelope) error {
}
// Query retrieves messages from the DB
func (d *DBStore) Query(query *pb.HistoryQuery) ([]StoredMessage, error) {
func (d *DBStore) Query(query *pb.HistoryQuery) (*pb.Index, []StoredMessage, error) {
start := time.Now()
defer func() {
elapsed := time.Since(start)
@ -290,7 +290,7 @@ func (d *DBStore) Query(query *pb.HistoryQuery) ([]StoredMessage, error) {
).Scan(&exists)
if err != nil {
return nil, err
return nil, nil, err
}
if exists {
@ -302,7 +302,7 @@ func (d *DBStore) Query(query *pb.HistoryQuery) ([]StoredMessage, error) {
parameters = append(parameters, cursorDBKey.Bytes())
} else {
return nil, ErrInvalidCursor
return nil, nil, ErrInvalidCursor
}
}
@ -320,28 +320,41 @@ func (d *DBStore) Query(query *pb.HistoryQuery) ([]StoredMessage, error) {
stmt, err := d.db.Prepare(sqlQuery)
if err != nil {
return nil, err
return nil, nil, err
}
defer stmt.Close()
parameters = append(parameters, query.PagingInfo.PageSize)
rows, err := stmt.Query(parameters...)
if err != nil {
return nil, err
return nil, nil, err
}
var result []StoredMessage
for rows.Next() {
record, err := d.GetStoredMessage(rows)
if err != nil {
return nil, err
return nil, nil, err
}
result = append(result, record)
}
defer rows.Close()
return result, nil
cursor := &pb.Index{}
if len(result) != 0 {
lastMsgIdx := len(result) - 1
cursor = protocol.NewEnvelope(result[lastMsgIdx].Message, result[lastMsgIdx].ReceiverTime, result[lastMsgIdx].PubsubTopic).Index()
}
// The retrieved messages list should always be in chronological order
if query.PagingInfo.Direction == pb.PagingInfo_BACKWARD {
for i, j := 0, len(result)-1; i < j; i, j = i+1, j-1 {
result[i], result[j] = result[j], result[i]
}
}
return cursor, result, nil
}
// MostRecentTimestamp returns an unix timestamp with the most recent senderTimestamp

View File

@ -67,7 +67,7 @@ func RetrieveNodes(ctx context.Context, url string, opts ...DnsDiscoveryOption)
func hasUDP(node *enode.Node) bool {
enrUDP := new(enr.UDP)
if err := node.Record().Load(enr.WithEntry(enrUDP.ENRKey(), enrUDP)); err != nil {
return err == nil
return false
}
return false
return true
}

View File

@ -57,6 +57,7 @@ type RLNRelay interface {
MembershipKeyPair() MembershipKeyPair
MembershipIndex() uint
AppendRLNProof(msg *pb.WakuMessage, senderEpochTime time.Time) error
Stop()
}
type WakuNode struct {
@ -363,6 +364,7 @@ func (w *WakuNode) Stop() {
w.relay.Stop()
w.lightPush.Stop()
w.store.Stop()
_ = w.stopRlnRelay()
w.host.Close()

View File

@ -3,7 +3,6 @@
package node
// RLNRelay is used to access any operation related to Waku RLN protocol
func (w *WakuNode) RLNRelay() RLNRelay {
return nil
}
@ -11,3 +10,7 @@ func (w *WakuNode) RLNRelay() RLNRelay {
func (w *WakuNode) mountRlnRelay() error {
return nil
}
func (w *WakuNode) stopRlnRelay() error {
return nil
}

View File

@ -54,9 +54,6 @@ func (w *WakuNode) mountRlnRelay() error {
w.rlnRelay = rlnRelay
w.log.Info("membership id key", zap.String("IDKey", hex.EncodeToString(memKeyPair.IDKey[:])))
w.log.Info("membership id commitment key", zap.String("IDCommitment", hex.EncodeToString(memKeyPair.IDCommitment[:])))
// check the correct construction of the tree by comparing the calculated root against the expected root
// no error should happen as it is already captured in the unit tests
root, err := rlnRelay.RLN.GetMerkleRoot()
@ -84,7 +81,7 @@ func (w *WakuNode) mountRlnRelay() error {
// mount the rln relay protocol in the on-chain/dynamic mode
var err error
w.rlnRelay, err = rln.RlnRelayDynamic(context.Background(), w.relay, w.opts.rlnETHClientAddress, w.opts.rlnETHPrivateKey, w.opts.rlnMembershipContractAddress, memKeyPair, w.opts.rlnRelayMemIndex, w.opts.rlnRelayPubsubTopic, w.opts.rlnRelayContentTopic, w.opts.rlnSpamHandler, w.log)
w.rlnRelay, err = rln.RlnRelayDynamic(context.Background(), w.relay, w.opts.rlnETHClientAddress, w.opts.rlnETHPrivateKey, w.opts.rlnMembershipContractAddress, memKeyPair, w.opts.rlnRelayMemIndex, w.opts.rlnRelayPubsubTopic, w.opts.rlnRelayContentTopic, w.opts.rlnSpamHandler, w.opts.rlnRegistrationHandler, w.log)
if err != nil {
return err
}
@ -94,3 +91,10 @@ func (w *WakuNode) mountRlnRelay() error {
return nil
}
func (w *WakuNode) stopRlnRelay() error {
if w.rlnRelay != nil {
w.rlnRelay.Stop()
}
return nil
}

View File

@ -9,6 +9,7 @@ import (
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/p2p/enode"
"github.com/libp2p/go-libp2p"
"github.com/libp2p/go-libp2p-core/crypto"
@ -93,6 +94,7 @@ type WakuNodeParameters struct {
rlnETHPrivateKey *ecdsa.PrivateKey
rlnETHClientAddress string
rlnMembershipContractAddress common.Address
rlnRegistrationHandler func(tx *types.Transaction)
keepAliveInterval time.Duration
@ -121,6 +123,11 @@ func (w WakuNodeParameters) Identity() config.Option {
return libp2p.Identity(*w.GetPrivKey())
}
// TLSConfig returns the TLS config used for setting up secure websockets
func (w WakuNodeParameters) TLSConfig() *tls.Config {
return w.tlsConfig
}
// AddressFactory returns the address factory used by the node's host
func (w WakuNodeParameters) AddressFactory() basichost.AddrsFactory {
return w.addressFactory

View File

@ -11,6 +11,8 @@ import (
"github.com/status-im/go-waku/waku/v2/protocol/rln"
)
// WithStaticRLNRelay enables the Waku V2 RLN protocol in offchain mode
// Requires the `gowaku_rln` build constrain (or the env variable RLN=true if building go-waku)
func WithStaticRLNRelay(pubsubTopic string, contentTopic string, memberIndex r.MembershipIndex, spamHandler rln.SpamHandler) WakuNodeOption {
return func(params *WakuNodeParameters) error {
params.enableRLN = true
@ -23,7 +25,9 @@ func WithStaticRLNRelay(pubsubTopic string, contentTopic string, memberIndex r.M
}
}
func WithDynamicRLNRelay(pubsubTopic string, contentTopic string, memberIndex r.MembershipIndex, idKey *r.IDKey, idCommitment *r.IDCommitment, spamHandler rln.SpamHandler, ethClientAddress string, ethPrivateKey *ecdsa.PrivateKey, membershipContractAddress common.Address) WakuNodeOption {
// WithStaticRLNRelay enables the Waku V2 RLN protocol in onchain mode.
// Requires the `gowaku_rln` build constrain (or the env variable RLN=true if building go-waku)
func WithDynamicRLNRelay(pubsubTopic string, contentTopic string, memberIndex r.MembershipIndex, idKey *r.IDKey, idCommitment *r.IDCommitment, spamHandler rln.SpamHandler, ethClientAddress string, ethPrivateKey *ecdsa.PrivateKey, membershipContractAddress common.Address, registrationHandler rln.RegistrationHandler) WakuNodeOption {
return func(params *WakuNodeParameters) error {
params.enableRLN = true
params.rlnRelayDynamic = true
@ -36,6 +40,7 @@ func WithDynamicRLNRelay(pubsubTopic string, contentTopic string, memberIndex r.
params.rlnETHClientAddress = ethClientAddress
params.rlnETHPrivateKey = ethPrivateKey
params.rlnMembershipContractAddress = membershipContractAddress
params.rlnRegistrationHandler = registrationHandler
return nil
}
}

View File

@ -19,6 +19,8 @@ var (
ChaChaPoly = WakuNoiseProtocolID(30)
)
const NoisePaddingBlockSize = 248
var ErrorHandshakeComplete = errors.New("handshake complete")
// All protocols share same cipher suite
@ -121,8 +123,13 @@ func (hs *Handshake) Step(readPayloadV2 *PayloadV2, transportMessage []byte) (*H
// We initialize a payload v2 and we set proper protocol ID (if supported)
result.Payload2.ProtocolId = hs.protocolID
payload, err := PKCS7_Pad(transportMessage, NoisePaddingBlockSize)
if err != nil {
return nil, err
}
var noisePubKeys [][]byte
msg, cs1, cs2, err = hs.state.WriteMessageAndGetPK(hs.hsBuff, &noisePubKeys, transportMessage)
msg, cs1, cs2, err = hs.state.WriteMessageAndGetPK(hs.hsBuff, &noisePubKeys, payload)
if err != nil {
return nil, err
}
@ -149,8 +156,14 @@ func (hs *Handshake) Step(readPayloadV2 *PayloadV2, transportMessage []byte) (*H
hs.shouldWrite = true
// We retrieve and store the (decrypted) received transport message
result.TransportMessage = msg
// We retrieve, and store the (unpadded decrypted) received transport message
payload, err := PKCS7_Unpad(msg, NoisePaddingBlockSize)
if err != nil {
return nil, err
}
result.TransportMessage = payload
}
if cs1 != nil && cs2 != nil {
@ -186,9 +199,12 @@ func (hs *Handshake) Encrypt(plaintext []byte) (*PayloadV2, error) {
return nil, errors.New("tried to encrypt empty plaintext")
}
// TODO: add padding (?)
paddedTransportMessage, err := PKCS7_Pad(plaintext, NoisePaddingBlockSize)
if err != nil {
return nil, err
}
cyphertext, err := hs.enc.Encrypt(nil, nil, plaintext)
cyphertext, err := hs.enc.Encrypt(nil, nil, paddedTransportMessage)
if err != nil {
return nil, err
}
@ -215,7 +231,12 @@ func (hs *Handshake) Decrypt(payload *PayloadV2) ([]byte, error) {
return nil, errors.New("tried to decrypt empty ciphertext")
}
return hs.dec.Decrypt(nil, nil, payload.TransportMessage)
paddedMessage, err := hs.dec.Decrypt(nil, nil, payload.TransportMessage)
if err != nil {
return nil, err
}
return PKCS7_Unpad(paddedMessage, NoisePaddingBlockSize)
}
// NewHandshake_XX_25519_ChaChaPoly_SHA256 creates a handshake where the initiator and receiver are not aware of each other static keys

View File

@ -0,0 +1,48 @@
package noise
import (
"errors"
)
// PKCS7_Pad pads a payload according to PKCS#7 as per
// RFC 5652 https://datatracker.ietf.org/doc/html/rfc5652#section-6.3
func PKCS7_Pad(payload []byte, paddingSize int) ([]byte, error) {
if paddingSize >= 256 {
return nil, errors.New("invalid padding size")
}
k := paddingSize - (len(payload) % paddingSize)
var padVal int
if k != 0 {
padVal = k
} else {
padVal = paddingSize
}
padding := make([]byte, padVal)
for i := range padding {
padding[i] = byte(padVal)
}
return append(payload, padding...), nil
}
// PKCS7_Unpad unpads a payload according to PKCS#7 as per
// RFC 5652 https://datatracker.ietf.org/doc/html/rfc5652#section-6.3
func PKCS7_Unpad(payload []byte, paddingSize int) ([]byte, error) {
if paddingSize >= 256 {
return nil, errors.New("invalid padding size")
}
if len(payload) == 0 {
return nil, nil // empty payload
}
high := len(payload) - 1
k := payload[high]
unpadded := payload[0:(high + 1 - int(k))]
return unpadded, nil
}

View File

@ -115,6 +115,7 @@ type WakuMessage struct {
Version uint32 `protobuf:"varint,3,opt,name=version,proto3" json:"version,omitempty"`
Timestamp int64 `protobuf:"zigzag64,10,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
RateLimitProof *RateLimitProof `protobuf:"bytes,21,opt,name=rate_limit_proof,json=rateLimitProof,proto3" json:"rate_limit_proof,omitempty"`
Ephemeral bool `protobuf:"varint,31,opt,name=ephemeral,proto3" json:"ephemeral,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
@ -188,6 +189,13 @@ func (m *WakuMessage) GetRateLimitProof() *RateLimitProof {
return nil
}
func (m *WakuMessage) GetEphemeral() bool {
if m != nil {
return m.Ephemeral
}
return false
}
func init() {
proto.RegisterType((*RateLimitProof)(nil), "pb.RateLimitProof")
proto.RegisterType((*WakuMessage)(nil), "pb.WakuMessage")
@ -196,26 +204,27 @@ func init() {
func init() { proto.RegisterFile("waku_message.proto", fileDescriptor_6f0a20862b3bf714) }
var fileDescriptor_6f0a20862b3bf714 = []byte{
// 299 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x54, 0x91, 0xbf, 0x4e, 0xf3, 0x30,
0x14, 0xc5, 0x3f, 0xf7, 0xa3, 0xad, 0x7a, 0x5b, 0xaa, 0xca, 0x02, 0xe1, 0x01, 0x85, 0xaa, 0x53,
0xa7, 0x0e, 0xb0, 0x32, 0x31, 0x83, 0x84, 0x2c, 0x24, 0x60, 0x8a, 0x9c, 0x70, 0x4b, 0xad, 0xfc,
0xb9, 0x96, 0xe3, 0x00, 0x7d, 0x13, 0x5e, 0x82, 0x87, 0x60, 0x63, 0xe4, 0x11, 0x50, 0x78, 0x11,
0x14, 0x87, 0x2a, 0x64, 0xf3, 0xef, 0x1c, 0x1d, 0xe9, 0xf8, 0x5c, 0xe0, 0xcf, 0x2a, 0x29, 0xc3,
0x0c, 0x8b, 0x42, 0x3d, 0xe2, 0xca, 0x58, 0x72, 0xc4, 0x7b, 0x26, 0x5a, 0xbc, 0x31, 0x98, 0x4a,
0xe5, 0xf0, 0x52, 0x67, 0xda, 0x5d, 0x5b, 0xa2, 0x35, 0x3f, 0x80, 0xbe, 0xa9, 0x1f, 0x82, 0xcd,
0xd9, 0x72, 0x22, 0x1b, 0xe0, 0x27, 0x30, 0xce, 0xd0, 0x26, 0x29, 0x86, 0x96, 0xc8, 0x89, 0x9e,
0xf7, 0xa0, 0x91, 0x24, 0x91, 0xab, 0x63, 0x68, 0x28, 0xde, 0x88, 0xff, 0x4d, 0xcc, 0x03, 0x3f,
0x82, 0x61, 0xb1, 0x51, 0x16, 0xc3, 0x17, 0xb1, 0xe7, 0xf5, 0x81, 0xc7, 0xbb, 0xd6, 0xd8, 0x8a,
0xfe, 0x1f, 0xe3, 0x9e, 0x1f, 0xc3, 0x28, 0x2f, 0xd3, 0x54, 0xaf, 0x35, 0x5a, 0x31, 0xf0, 0x56,
0x2b, 0x2c, 0xde, 0x19, 0x8c, 0x6f, 0x55, 0x52, 0x5e, 0x35, 0x3f, 0xe1, 0x02, 0x86, 0x46, 0x6d,
0x53, 0x52, 0x0f, 0xbf, 0x75, 0x77, 0xc8, 0x17, 0x30, 0x89, 0x29, 0x77, 0x98, 0xbb, 0x1b, 0x32,
0x3a, 0xf6, 0x8d, 0x47, 0xb2, 0xa3, 0xd5, 0xe9, 0x27, 0xb4, 0x85, 0xa6, 0xdc, 0xb7, 0xde, 0x97,
0x3b, 0xac, 0x5b, 0x38, 0x9d, 0x61, 0xe1, 0x54, 0x66, 0x04, 0xcc, 0xd9, 0x92, 0xcb, 0x56, 0xe0,
0xe7, 0x30, 0xb3, 0xca, 0x61, 0x98, 0xd6, 0xab, 0x85, 0xcd, 0x5a, 0x87, 0x73, 0xb6, 0x1c, 0x9f,
0xf2, 0x95, 0x89, 0x56, 0xdd, 0x41, 0xe5, 0xd4, 0x76, 0xf8, 0x62, 0xf6, 0x51, 0x05, 0xec, 0xb3,
0x0a, 0xd8, 0x57, 0x15, 0xb0, 0xd7, 0xef, 0xe0, 0x5f, 0x34, 0xf0, 0x07, 0x39, 0xfb, 0x09, 0x00,
0x00, 0xff, 0xff, 0x4a, 0x19, 0x2a, 0x86, 0xa6, 0x01, 0x00, 0x00,
// 313 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x54, 0x91, 0x41, 0x4e, 0x02, 0x31,
0x18, 0x85, 0x2d, 0x0a, 0xc8, 0x0f, 0x12, 0xd2, 0x68, 0xec, 0x82, 0x0c, 0x13, 0x56, 0xb3, 0x62,
0xa1, 0x5b, 0x57, 0xae, 0x35, 0x31, 0x8d, 0x89, 0xba, 0x9a, 0x14, 0xfc, 0x91, 0x86, 0xe9, 0xfc,
0x4d, 0xa7, 0xa8, 0xdc, 0xc4, 0x4b, 0x78, 0x0f, 0x97, 0xde, 0x40, 0x83, 0x17, 0x31, 0xd3, 0x91,
0x8c, 0xec, 0xfa, 0xbe, 0x97, 0x97, 0xbc, 0xbe, 0x1f, 0xf8, 0x8b, 0x5a, 0xae, 0x52, 0x83, 0x45,
0xa1, 0x9e, 0x70, 0x62, 0x1d, 0x79, 0xe2, 0x0d, 0x3b, 0x1d, 0xbf, 0x33, 0xe8, 0x4b, 0xe5, 0xf1,
0x4a, 0x1b, 0xed, 0x6f, 0x1c, 0xd1, 0x9c, 0x1f, 0x43, 0xd3, 0x96, 0x0f, 0xc1, 0x62, 0x96, 0xf4,
0x64, 0x25, 0xf8, 0x08, 0xba, 0x06, 0xdd, 0x32, 0xc3, 0xd4, 0x11, 0x79, 0xd1, 0x08, 0x1e, 0x54,
0x48, 0x12, 0xf9, 0x32, 0x86, 0x96, 0x66, 0x0b, 0xb1, 0x5f, 0xc5, 0x82, 0xe0, 0xa7, 0xd0, 0x2e,
0x16, 0xca, 0x61, 0xfa, 0x2a, 0x0e, 0x02, 0x6f, 0x05, 0x79, 0x5f, 0x1b, 0x6b, 0xd1, 0xfc, 0x67,
0x3c, 0xf0, 0x21, 0x74, 0xf2, 0x55, 0x96, 0xe9, 0xb9, 0x46, 0x27, 0x5a, 0xc1, 0xaa, 0xc1, 0xf8,
0x8b, 0x41, 0xf7, 0x4e, 0x2d, 0x57, 0xd7, 0xd5, 0x4f, 0xb8, 0x80, 0xb6, 0x55, 0xeb, 0x8c, 0xd4,
0xe3, 0x5f, 0xdd, 0xad, 0xe4, 0x63, 0xe8, 0xcd, 0x28, 0xf7, 0x98, 0xfb, 0x5b, 0xb2, 0x7a, 0x16,
0x1a, 0x77, 0xe4, 0x0e, 0x2b, 0xd3, 0xcf, 0xe8, 0x0a, 0x4d, 0x79, 0x68, 0x7d, 0x24, 0xb7, 0xb2,
0x6c, 0xe1, 0xb5, 0xc1, 0xc2, 0x2b, 0x63, 0x05, 0xc4, 0x2c, 0xe1, 0xb2, 0x06, 0xfc, 0x02, 0x06,
0x4e, 0x79, 0x4c, 0xb3, 0x72, 0xb5, 0xb4, 0x5a, 0xeb, 0x24, 0x66, 0x49, 0xf7, 0x8c, 0x4f, 0xec,
0x74, 0xb2, 0x3b, 0xa8, 0xec, 0xbb, 0xdd, 0x81, 0x87, 0xd0, 0x41, 0xbb, 0x40, 0x83, 0x4e, 0x65,
0x62, 0x14, 0xb3, 0xe4, 0x50, 0xd6, 0xe0, 0x72, 0xf0, 0xb1, 0x89, 0xd8, 0xe7, 0x26, 0x62, 0xdf,
0x9b, 0x88, 0xbd, 0xfd, 0x44, 0x7b, 0xd3, 0x56, 0x38, 0xd7, 0xf9, 0x6f, 0x00, 0x00, 0x00, 0xff,
0xff, 0xe6, 0x01, 0x38, 0xc8, 0xc4, 0x01, 0x00, 0x00,
}
func (m *RateLimitProof) Marshal() (dAtA []byte, err error) {
@ -311,6 +320,18 @@ func (m *WakuMessage) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i -= len(m.XXX_unrecognized)
copy(dAtA[i:], m.XXX_unrecognized)
}
if m.Ephemeral {
i--
if m.Ephemeral {
dAtA[i] = 1
} else {
dAtA[i] = 0
}
i--
dAtA[i] = 0x1
i--
dAtA[i] = 0xf8
}
if m.RateLimitProof != nil {
{
size, err := m.RateLimitProof.MarshalToSizedBuffer(dAtA[:i])
@ -423,6 +444,9 @@ func (m *WakuMessage) Size() (n int) {
l = m.RateLimitProof.Size()
n += 2 + l + sovWakuMessage(uint64(l))
}
if m.Ephemeral {
n += 3
}
if m.XXX_unrecognized != nil {
n += len(m.XXX_unrecognized)
}
@ -861,6 +885,26 @@ func (m *WakuMessage) Unmarshal(dAtA []byte) error {
return err
}
iNdEx = postIndex
case 31:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Ephemeral", wireType)
}
var v int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowWakuMessage
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
v |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
m.Ephemeral = bool(v != 0)
default:
iNdEx = preIndex
skippy, err := skipWakuMessage(dAtA[iNdEx:])

View File

@ -17,4 +17,5 @@ message WakuMessage {
uint32 version = 3;
sint64 timestamp = 10;
RateLimitProof rate_limit_proof = 21;
bool ephemeral = 31;
}

View File

@ -85,6 +85,7 @@ func RlnRelayDynamic(
pubsubTopic string,
contentTopic string,
spamHandler SpamHandler,
registrationHandler RegistrationHandler,
log *zap.Logger,
) (*WakuRLNRelay, error) {
log = log.Named("rln-dynamic")
@ -114,6 +115,7 @@ func RlnRelayDynamic(
contentTopic: contentTopic,
log: log,
nullifierLog: make(map[r.Epoch][]r.ProofMetadata),
registrationHandler: registrationHandler,
}
// prepare rln membership key pair

View File

@ -4,18 +4,20 @@ import (
"bytes"
"context"
"crypto/ecdsa"
"encoding/hex"
"errors"
"math"
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethclient"
proto "github.com/golang/protobuf/proto"
"github.com/libp2p/go-libp2p-core/peer"
pubsub "github.com/libp2p/go-libp2p-pubsub"
r "github.com/status-im/go-rln/rln"
"github.com/status-im/go-waku/waku/v2/protocol/pb"
"github.com/status-im/go-waku/waku/v2/protocol/relay"
"github.com/status-im/go-waku/waku/v2/utils"
"go.uber.org/zap"
)
@ -25,6 +27,8 @@ const MAX_CLOCK_GAP_SECONDS = 20
// maximum allowed gap between the epochs of messages' RateLimitProofs
const MAX_EPOCH_GAP = int64(MAX_CLOCK_GAP_SECONDS / r.EPOCH_UNIT_SECONDS)
type RegistrationHandler = func(tx *types.Transaction)
type WakuRLNRelay struct {
ctx context.Context
@ -40,14 +44,23 @@ type WakuRLNRelay struct {
// TODO may need to erase this ethAccountPrivateKey when is not used
// TODO may need to make ethAccountPrivateKey mandatory
ethAccountPrivateKey *ecdsa.PrivateKey
RLN *r.RLN
ethClient *ethclient.Client
RLN *r.RLN
// pubsubTopic is the topic for which rln relay is mounted
pubsubTopic string
contentTopic string
// the log of nullifiers and Shamir shares of the past messages grouped per epoch
nullifierLog map[r.Epoch][]r.ProofMetadata
log *zap.Logger
registrationHandler RegistrationHandler
log *zap.Logger
}
func (rln *WakuRLNRelay) Stop() {
if rln.ethClient != nil {
rln.ethClient.Close()
}
}
func StaticSetup(rlnRelayMemIndex r.MembershipIndex) ([]r.IDCommitment, r.MembershipKeyPair, r.MembershipIndex, error) {
@ -352,11 +365,11 @@ func toMembershipKeyPairs(groupKeys [][]string) ([]r.MembershipKeyPair, error) {
groupKeyPairs := []r.MembershipKeyPair{}
for _, pair := range groupKeys {
idKey, err := hex.DecodeString(pair[0])
idKey, err := utils.DecodeHexString(pair[0])
if err != nil {
return nil, err
}
idCommitment, err := hex.DecodeString(pair[1])
idCommitment, err := utils.DecodeHexString(pair[1])
if err != nil {
return nil, err
}

View File

@ -10,6 +10,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/rpc"
r "github.com/status-im/go-rln/rln"
"github.com/status-im/go-waku/waku/v2/protocol/rln/contracts"
"go.uber.org/zap"
@ -23,7 +24,7 @@ func toBigInt(i []byte) *big.Int {
return result
}
func register(ctx context.Context, idComm r.IDCommitment, ethAccountPrivateKey *ecdsa.PrivateKey, ethClientAddress string, membershipContractAddress common.Address, log *zap.Logger) (*r.MembershipIndex, error) {
func register(ctx context.Context, idComm r.IDCommitment, ethAccountPrivateKey *ecdsa.PrivateKey, ethClientAddress string, membershipContractAddress common.Address, registrationHandler RegistrationHandler, log *zap.Logger) (*r.MembershipIndex, error) {
backend, err := ethclient.Dial(ethClientAddress)
if err != nil {
return nil, err
@ -57,6 +58,10 @@ func register(ctx context.Context, idComm r.IDCommitment, ethAccountPrivateKey *
log.Info("transaction broadcasted", zap.String("transactionHash", tx.Hash().Hex()))
if registrationHandler != nil {
registrationHandler(tx)
}
txReceipt, err := bind.WaitMined(ctx, backend, tx)
if err != nil {
return nil, err
@ -95,7 +100,7 @@ func register(ctx context.Context, idComm r.IDCommitment, ethAccountPrivateKey *
// into the membership contract whose address is in rlnPeer.membershipContractAddress
func (rln *WakuRLNRelay) Register(ctx context.Context) (*r.MembershipIndex, error) {
pk := rln.membershipKeyPair.IDCommitment
return register(ctx, pk, rln.ethAccountPrivateKey, rln.ethClientAddress, rln.membershipContractAddress, rln.log)
return register(ctx, pk, rln.ethAccountPrivateKey, rln.ethClientAddress, rln.membershipContractAddress, rln.registrationHandler, rln.log)
}
// the types of inputs to this handler matches the MemberRegistered event/proc defined in the MembershipContract interface
@ -125,7 +130,7 @@ func (rln *WakuRLNRelay) HandleGroupUpdates(handler RegistrationEventHandler, er
errChan <- err
return
}
defer backend.Close()
rln.ethClient = backend
rlnContract, err := contracts.NewRLN(rln.membershipContractAddress, backend)
if err != nil {
@ -146,7 +151,7 @@ func (rln *WakuRLNRelay) HandleGroupUpdates(handler RegistrationEventHandler, er
select {
case <-doneCh:
return
case <-errCh:
case err := <-errCh:
errChan <- err
return
}
@ -179,8 +184,13 @@ func (rln *WakuRLNRelay) watchNewEvents(rlnContract *contracts.RLN, handler Regi
logSink := make(chan *contracts.RLNMemberRegistered)
subs, err := rlnContract.WatchMemberRegistered(&bind.WatchOpts{Context: rln.ctx, Start: nil}, logSink)
if err != nil {
if err == rpc.ErrNotificationsUnsupported {
err = errors.New("notifications not supported. The node must support websockets")
}
errCh <- err
return
}
defer subs.Unsubscribe()
close(doneCh)
@ -189,7 +199,6 @@ func (rln *WakuRLNRelay) watchNewEvents(rlnContract *contracts.RLN, handler Regi
case evt := <-logSink:
err = processLogs(evt, handler)
if err != nil {
// TODO: should this stop the chat app?
rln.log.Error("processing rln log", zap.Error(err))
}
case <-rln.ctx.Done():
@ -197,8 +206,11 @@ func (rln *WakuRLNRelay) watchNewEvents(rlnContract *contracts.RLN, handler Regi
close(logSink)
return
case err := <-subs.Err():
rln.log.Error("watching new events", zap.Error(err))
close(logSink)
if err != nil {
rln.log.Error("watching new events", zap.Error(err))
errCh <- err
}
return
}
}

View File

@ -62,7 +62,7 @@ func findMessages(query *pb.HistoryQuery, msgProvider MessageProvider) ([]*pb.Wa
query.PagingInfo.PageSize = MaxPageSize
}
queryResult, err := msgProvider.Query(query)
cursor, queryResult, err := msgProvider.Query(query)
if err != nil {
return nil, nil, err
}
@ -72,10 +72,7 @@ func findMessages(query *pb.HistoryQuery, msgProvider MessageProvider) ([]*pb.Wa
return nil, newPagingInfo, nil
}
lastMsgIdx := len(queryResult) - 1
newCursor := protocol.NewEnvelope(queryResult[lastMsgIdx].Message, queryResult[lastMsgIdx].ReceiverTime, queryResult[lastMsgIdx].PubsubTopic).Index()
newPagingInfo := &pb.PagingInfo{PageSize: query.PagingInfo.PageSize, Cursor: newCursor, Direction: query.PagingInfo.Direction}
newPagingInfo := &pb.PagingInfo{PageSize: query.PagingInfo.PageSize, Cursor: cursor, Direction: query.PagingInfo.Direction}
if newPagingInfo.PageSize > uint64(len(queryResult)) {
newPagingInfo.PageSize = uint64(len(queryResult))
}
@ -108,7 +105,7 @@ func (store *WakuStore) FindMessages(query *pb.HistoryQuery) *pb.HistoryResponse
type MessageProvider interface {
GetAll() ([]persistence.StoredMessage, error)
Query(query *pb.HistoryQuery) ([]persistence.StoredMessage, error)
Query(query *pb.HistoryQuery) (*pb.Index, []persistence.StoredMessage, error)
Put(env *protocol.Envelope) error
MostRecentTimestamp() (int64, error)
Stop()
@ -214,6 +211,10 @@ func (store *WakuStore) storeMessage(env *protocol.Envelope) error {
return ErrFutureMessage
}
if env.Message().Ephemeral {
return nil
}
err := store.msgProvider.Put(env)
if err != nil {
store.log.Error("storing message", zap.Error(err))

View File

@ -0,0 +1,11 @@
package utils
import (
"encoding/hex"
"strings"
)
func DecodeHexString(input string) ([]byte, error) {
input = strings.TrimPrefix(input, "0x")
return hex.DecodeString(input)
}

4
vendor/modules.txt vendored
View File

@ -932,10 +932,10 @@ github.com/status-im/go-discover/discover/v5wire
# github.com/status-im/go-multiaddr-ethv4 v1.2.3
## explicit; go 1.11
github.com/status-im/go-multiaddr-ethv4
# github.com/status-im/go-rln v0.0.9
# github.com/status-im/go-rln v0.1.1
## explicit; go 1.17
github.com/status-im/go-rln/rln
# github.com/status-im/go-waku v0.1.1-0.20220819160153-b0761ad70648
# github.com/status-im/go-waku v0.2.3-0.20220915230805-448f5a2e0ef6
## explicit; go 1.17
github.com/status-im/go-waku/logging
github.com/status-im/go-waku/waku/persistence

View File

@ -156,7 +156,7 @@ func (d *DBStore) Put(env *protocol.Envelope) error {
}
// Query retrieves messages from the DB
func (d *DBStore) Query(query *pb.HistoryQuery) ([]gowakuPersistence.StoredMessage, error) {
func (d *DBStore) Query(query *pb.HistoryQuery) (*pb.Index, []gowakuPersistence.StoredMessage, error) {
start := time.Now()
defer func() {
elapsed := time.Since(start)
@ -210,7 +210,7 @@ func (d *DBStore) Query(query *pb.HistoryQuery) ([]gowakuPersistence.StoredMessa
).Scan(&exists)
if err != nil {
return nil, err
return nil, nil, err
}
if exists {
@ -222,7 +222,7 @@ func (d *DBStore) Query(query *pb.HistoryQuery) ([]gowakuPersistence.StoredMessa
parameters = append(parameters, cursorDBKey.Bytes())
} else {
return nil, ErrInvalidCursor
return nil, nil, ErrInvalidCursor
}
}
@ -240,28 +240,41 @@ func (d *DBStore) Query(query *pb.HistoryQuery) ([]gowakuPersistence.StoredMessa
stmt, err := d.db.Prepare(sqlQuery)
if err != nil {
return nil, err
return nil, nil, err
}
defer stmt.Close()
parameters = append(parameters, query.PagingInfo.PageSize)
rows, err := stmt.Query(parameters...)
if err != nil {
return nil, err
return nil, nil, err
}
var result []gowakuPersistence.StoredMessage
for rows.Next() {
record, err := d.GetStoredMessage(rows)
if err != nil {
return nil, err
return nil, nil, err
}
result = append(result, record)
}
defer rows.Close()
return result, nil
cursor := &pb.Index{}
if len(result) != 0 {
lastMsgIdx := len(result) - 1
cursor = protocol.NewEnvelope(result[lastMsgIdx].Message, result[lastMsgIdx].ReceiverTime, result[lastMsgIdx].PubsubTopic).Index()
}
// The retrieved messages list should always be in chronological order
if query.PagingInfo.Direction == pb.PagingInfo_BACKWARD {
for i, j := 0, len(result)-1; i < j; i, j = i+1, j-1 {
result[i], result[j] = result[j], result[i]
}
}
return cursor, result, nil
}
// MostRecentTimestamp returns an unix timestamp with the most recent senderTimestamp

View File

@ -77,7 +77,7 @@ import (
)
const messageQueueLimit = 1024
const requestTimeout = 5 * time.Second
const requestTimeout = 10 * time.Second
const PeerStoreTable = "peerstore"
@ -344,7 +344,9 @@ func (w *Waku) getDiscV5BootstrapNodes(addresses []string) ([]*enode.Node, error
retrieveENR := func(d dnsdisc.DiscoveredNode, protocol libp2pproto.ID) {
mu.Lock()
defer mu.Unlock()
result = append(result, d.ENR)
if d.ENR != nil {
result = append(result, d.ENR)
}
}
for _, addrString := range addresses {
@ -373,23 +375,22 @@ func (w *Waku) getDiscV5BootstrapNodes(addresses []string) ([]*enode.Node, error
}
func (w *Waku) dnsDiscover(enrtreeAddress string, protocol libp2pproto.ID, apply fnApplyToEachPeer) {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
ctx, cancel := context.WithTimeout(context.Background(), requestTimeout)
defer cancel()
w.dnsAddressCacheLock.RLock()
discNodes, ok := w.dnsAddressCache[enrtreeAddress]
w.dnsAddressCacheLock.RUnlock()
w.dnsAddressCacheLock.Lock()
defer w.dnsAddressCacheLock.Unlock()
discNodes, ok := w.dnsAddressCache[enrtreeAddress]
if !ok {
w.dnsAddressCacheLock.Lock()
var err error
discoveredNodes, err := dnsdisc.RetrieveNodes(ctx, enrtreeAddress)
w.dnsAddressCache[enrtreeAddress] = append(w.dnsAddressCache[enrtreeAddress], discoveredNodes...)
w.dnsAddressCacheLock.Unlock()
if err != nil {
log.Warn("dns discovery error ", err)
return
}
w.dnsAddressCache[enrtreeAddress] = append(w.dnsAddressCache[enrtreeAddress], discoveredNodes...)
discNodes = w.dnsAddressCache[enrtreeAddress]
}
for _, d := range discNodes {