Skip to content

Commit 8b87980

Browse files
committed
feat: integrate sds when sending community messages.
1 parent 16fb384 commit 8b87980

File tree

12 files changed

+803
-27
lines changed

12 files changed

+803
-27
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,9 @@ vendor/github.com/waku-org/go-zerokit-rln-arm/
9292
# waku-go-bindings third_party directory
9393
vendor/**/waku-go-bindings/third_party/
9494

95+
# sds-go-bindings third_party directory
96+
vendor/**/sds-go-bindings/third_party/
97+
9598
# status-cli logs
9699
alice.log
97100
bob.log

Makefile

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
.PHONY: statusgo all test clean help
22
.PHONY: statusgo-android statusgo-ios
33
.PHONY: build-libwaku test-libwaku clean-libwaku rebuild-libwaku
4+
.PHONY: build-libsds clean-libsds rebuild-libsds
45

56
# Clear any GOROOT set outside of the Nix shell
67
export GOROOT=
@@ -43,14 +44,17 @@ endif
4344
ifeq ($(detected_OS),Darwin)
4445
GOBIN_SHARED_LIB_EXT := dylib
4546
LIBWAKU_EXT := so
47+
LIBSDS_EXT := so
4648
GOBIN_SHARED_LIB_CFLAGS := CGO_ENABLED=1 GOOS=darwin
4749
else ifeq ($(detected_OS),Windows)
4850
GOBIN_SHARED_LIB_EXT := dll
4951
LIBWAKU_EXT := dll
52+
LIBSDS_EXT := dll
5053
GOBIN_SHARED_LIB_CGO_LDFLAGS := CGO_LDFLAGS=""
5154
else
5255
GOBIN_SHARED_LIB_EXT := so
5356
LIBWAKU_EXT := so
57+
LIBSDS_EXT := so
5458
GOBIN_SHARED_LIB_CGO_LDFLAGS := CGO_LDFLAGS="-Wl,-soname,libstatus.so.0"
5559
endif
5660

@@ -138,7 +142,7 @@ nix-purge: ##@nix Completely remove Nix setup, including /nix directory
138142
all: $(GO_CMD_NAMES)
139143

140144
.PHONY: $(GO_CMD_NAMES) $(GO_CMD_PATHS) $(GO_CMD_BUILDS)
141-
$(GO_CMD_BUILDS): generate
145+
$(GO_CMD_BUILDS): generate-sds generate
142146
$(GO_CMD_BUILDS): ##@build Build any Go project from cmd folder
143147
go build -mod=vendor -v \
144148
-tags '$(BUILD_TAGS)' $(BUILD_FLAGS) \
@@ -153,14 +157,20 @@ ifeq ($(USE_NWAKU),true)
153157
$(MAKE) -C $(CURDIR)/vendor/github.com/waku-org/waku-go-bindings/waku SHELL=/bin/bash
154158
endif
155159

160+
LIBSDS := $(CURDIR)/vendor/github.com/waku-org/sds-go-bindings/third_party/nim-sds/build/libsds.$(LIBSDS_EXT)
161+
$(LIBSDS):
162+
@echo "Building libsds"
163+
$(MAKE) -C $(CURDIR)/vendor/github.com/waku-org/sds-go-bindings/sds SHELL=/bin/bash V=2
164+
156165
statusgo: ##@build Build status-go as status-backend server
166+
statusgo: $(LIBSDS)
157167
statusgo: build/bin/status-backend
158168

159169
status-backend: ##@build Build status-backend to run status-go as HTTP server
160170
status-backend: build/bin/status-backend
161171

162172
run-status-backend: PORT ?= 0
163-
run-status-backend: generate
173+
run-status-backend: generate-sds generate
164174
run-status-backend: ##@run Start status-backend server listening to localhost:PORT
165175
go run ./cmd/status-backend --address localhost:${PORT}
166176

@@ -181,7 +191,7 @@ status-go-deps:
181191
go install github.com/kevinburke/go-bindata/v4/[email protected]
182192
go install google.golang.org/protobuf/cmd/[email protected]
183193

184-
statusgo-android: generate
194+
statusgo-android: generate-sds-android generate
185195
statusgo-android: ##@cross-compile Build status-go for Android
186196
@echo "Building status-go for Android..."
187197
mkdir -p build/bin \
@@ -211,8 +221,8 @@ statusgo-ios: ##@cross-compile Build status-go for iOS
211221
github.com/status-im/status-go/mobile
212222
@echo "iOS framework cross compilation done in build/bin/Statusgo.xcframework"
213223

214-
statusgo-library: generate
215-
statusgo-library: $(LIBWAKU) ##@cross-compile Build status-go as static library for current platform
224+
statusgo-library: generate-sds generate
225+
statusgo-library: $(LIBWAKU) $(LIBSDS) ##@cross-compile Build status-go as static library for current platform
216226
## cmd/library/README.md explains the magic incantation behind this
217227
mkdir -p build/bin/statusgo-lib
218228
go run cmd/library/*.go > build/bin/statusgo-lib/main.go
@@ -227,9 +237,10 @@ statusgo-library: $(LIBWAKU) ##@cross-compile Build status-go as static library
227237
@ls -la build/bin/libstatus.*
228238

229239
build-libwaku: $(LIBWAKU)
240+
build-libsds: $(LIBSDS)
230241

231-
statusgo-shared-library: generate
232-
statusgo-shared-library: $(LIBWAKU) ##@cross-compile Build status-go as shared library for current platform
242+
statusgo-shared-library: generate-sds generate
243+
statusgo-shared-library: $(LIBWAKU) $(LIBSDS) ##@cross-compile Build status-go as shared library for current platform
233244
## cmd/library/README.md explains the magic incantation behind this
234245
mkdir -p build/bin/statusgo-lib
235246
go run cmd/library/*.go > build/bin/statusgo-lib/main.go
@@ -274,12 +285,18 @@ setup-dev: ##@setup Install all necessary tools for development
274285
setup-dev:
275286
echo "Replaced by Nix shell. Use 'make shell' or just any target as-is."
276287

288+
generate-sds: ##@ Build libsds third_party
289+
cd vendor/github.com/waku-org/sds-go-bindings/sds/ && make build
290+
291+
generate-sds-android: ##@ Build libsds third_party for Android
292+
cd vendor/github.com/waku-org/sds-go-bindings/sds/ && make build-android
293+
277294
generate: PACKAGES ?= $$(go list -e ./... | grep -v "/contracts/")
278295
generate: GO_GENERATE_CMD ?= $$(which go-generate-fast || echo 'go generate')
279296
generate: export GO_GENERATE_FAST_DEBUG ?= false
280297
generate: export GO_GENERATE_FAST_RECACHE ?= false
281298
generate: ##@ Run generate for all given packages using go-generate-fast, fallback to `go generate` (e.g. for docker)
282-
@GOROOT=$$(go env GOROOT) $(GO_GENERATE_CMD) $(PACKAGES)
299+
@GOOS=$$(go env GOHOSTOS) GOARCH=$$(go env GOHOSTARCH) GOROOT=$$(go env GOROOT) $(GO_GENERATE_CMD) $(PACKAGES)
283300

284301
generate-contracts:
285302
go generate ./contracts
@@ -326,9 +343,15 @@ clean-libwaku:
326343

327344
rebuild-libwaku: | clean-libwaku $(LIBWAKU)
328345

346+
clean-libsds:
347+
@echo "Removing libsds"
348+
rm $(LIBSDS)
349+
350+
rebuild-libsds: | clean-libsds $(LIBSDS)
351+
329352
test: test-unit ##@tests Run basic, short tests during development
330353

331-
test-unit-prep: generate
354+
test-unit-prep: generate-sds generate
332355
test-unit-prep: export BUILD_TAGS ?=
333356
test-unit-prep: export UNIT_TEST_DRY_RUN ?= false
334357
test-unit-prep: export UNIT_TEST_COUNT ?= 1
@@ -356,7 +379,7 @@ test-unit-network: ##@tests Run unit and integration tests with network access
356379
test-unit-race: export GOTEST_EXTRAFLAGS=-race
357380
test-unit-race: test-unit ##@tests Run unit and integration tests with -race flag
358381

359-
test-functional: generate
382+
test-functional: generate-sds generate
360383
test-functional: export FUNCTIONAL_TESTS_DOCKER_UID ?= $(call sh, id -u)
361384
test-functional: export FUNCTIONAL_TESTS_REPORT_CODECOV ?= false
362385
test-functional:
@@ -367,10 +390,10 @@ benchmark:
367390
@./_assets/scripts/run_benchmark.sh
368391

369392
lint-panics: export GOFLAGS ?= -tags='$(BUILD_TAGS)'
370-
lint-panics: generate
393+
lint-panics: generate-sds generate
371394
go run ./cmd/lint-panics -root="$(PWD)" -skip=./cmd -test=false ./...
372395

373-
lint: generate lint-panics
396+
lint: generate-sds generate lint-panics
374397
golangci-lint --build-tags '$(BUILD_TAGS)' run ./...
375398

376399
clean: ##@other Cleanup

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ require (
9595
github.com/status-im/extkeys v1.3.0
9696
github.com/status-im/go-wallet-sdk v0.0.0-20250902115318-6340846c26ec
9797
github.com/waku-org/go-waku v0.8.1-0.20250825172353-0c3d6dc0a8cc
98+
github.com/waku-org/sds-go-bindings v0.0.0-20250821114619-48e2341b175e
9899
github.com/waku-org/waku-go-bindings v0.0.0-20250714110306-6feba5b0df4d
99100
github.com/wk8/go-ordered-map/v2 v2.1.7
100101
github.com/yeqown/go-qrcode/v2 v2.2.1

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2185,6 +2185,8 @@ github.com/waku-org/go-zerokit-rln-arm v0.0.0-20230916171929-1dd9494ff065 h1:Sd7
21852185
github.com/waku-org/go-zerokit-rln-arm v0.0.0-20230916171929-1dd9494ff065/go.mod h1:7cSGUoGVIla1IpnChrLbkVjkYgdOcr7rcifEfh4ReR4=
21862186
github.com/waku-org/go-zerokit-rln-x86_64 v0.0.0-20230916171518-2a77c3734dd1 h1:4HSdWMFMufpRo3ECTX6BrvA+VzKhXZf7mS0rTa5cCWU=
21872187
github.com/waku-org/go-zerokit-rln-x86_64 v0.0.0-20230916171518-2a77c3734dd1/go.mod h1:+LeEYoW5/uBUTVjtBGLEVCUe9mOYAlu5ZPkIxLOSr5Y=
2188+
github.com/waku-org/sds-go-bindings v0.0.0-20250821114619-48e2341b175e h1:jgqa6QfY/H+xbzx5fASxLjxSP419T0k1KcPflubYMfk=
2189+
github.com/waku-org/sds-go-bindings v0.0.0-20250821114619-48e2341b175e/go.mod h1:UXU/th81Xb7JQASEQS+bmApkoLarPrJDJY6Y+XT0efc=
21882190
github.com/waku-org/waku-go-bindings v0.0.0-20250714110306-6feba5b0df4d h1:k22pZ7dnQ5vTplQ7ZwTfkaZgEUl9IwO9NlbwzRsg73M=
21892191
github.com/waku-org/waku-go-bindings v0.0.0-20250714110306-6feba5b0df4d/go.mod h1:v6ogkMCyQRUTazRyQR5LIouukY4/2bkjjHpnBKBxcAY=
21902192
github.com/wealdtech/go-ens/v3 v3.5.0 h1:Huc9GxBgiGweCOGTYomvsg07K2QggAqZpZ5SuiZdC8o=

messaging/common/message_sender.go

Lines changed: 93 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import (
3232
"github.com/status-im/status-go/protocol/common"
3333
"github.com/status-im/status-go/protocol/protobuf"
3434
v1protocol "github.com/status-im/status-go/protocol/v1"
35+
sds "github.com/waku-org/sds-go-bindings/sds"
3536
)
3637

3738
// Whisper message properties.
@@ -65,6 +66,8 @@ type MessageSender struct {
6566

6667
// handleSharedSecrets is a callback that is called every time a new shared secret is negotiated
6768
handleSharedSecrets func([]*sharedsecret.Secret) error
69+
70+
reliabilityManager *sds.ReliabilityManager
6871
}
6972

7073
func NewMessageSender(
@@ -75,16 +78,40 @@ func NewMessageSender(
7578
enc *encryption.Protocol,
7679
logger *zap.Logger,
7780
) (*MessageSender, error) {
81+
sds.SetLogger(logger)
82+
reliabilityManager, err := sds.NewReliabilityManager()
83+
if err != nil {
84+
return nil, errors.Wrap(err, "SDS: failed to create reliability manager")
85+
}
86+
callbacks := sds.EventCallbacks{
87+
OnMessageSent: func(messageId sds.MessageID, channelId string) {
88+
logger.Debug("SDS: message sent", zap.String("messageId", string(messageId)), zap.String("channelId", channelId))
89+
},
90+
OnMissingDependencies: func(messageId sds.MessageID, missingDeps []sds.MessageID, channelId string) {
91+
logger.Debug("SDS: missing dependencies",
92+
zap.String("messageId", string(messageId)),
93+
zap.String("channelId", channelId),
94+
zap.Any("missingDeps", missingDeps))
95+
},
96+
OnMessageReady: func(messageId sds.MessageID, channelId string) {
97+
logger.Debug("SDS: message ready",
98+
zap.String("messageId", string(messageId)),
99+
zap.String("channelId", channelId))
100+
},
101+
}
102+
reliabilityManager.RegisterCallbacks(callbacks)
103+
78104
p := &MessageSender{
79-
identity: identity,
80-
database: database,
81-
datasyncEnabled: true, // FIXME
82-
protocol: enc,
83-
persistence: persistence,
84-
publisher: pubsub.NewPublisher(),
85-
transport: transport,
86-
logger: logger,
87-
ephemeralKeys: make(map[string]*ecdsa.PrivateKey),
105+
identity: identity,
106+
database: database,
107+
datasyncEnabled: true, // FIXME
108+
protocol: enc,
109+
persistence: persistence,
110+
publisher: pubsub.NewPublisher(),
111+
transport: transport,
112+
logger: logger,
113+
ephemeralKeys: make(map[string]*ecdsa.PrivateKey),
114+
reliabilityManager: reliabilityManager,
88115
}
89116

90117
return p, nil
@@ -311,6 +338,15 @@ func (s *MessageSender) sendCommunity(
311338
rawMessage.Sender = s.identity
312339
}
313340

341+
if rawMessage.CommunityID != nil && len(rawMessage.CommunityID) > 0 && rawMessage.MessageType != protobuf.ApplicationMetadataMessage_COMMUNITY_DESCRIPTION {
342+
s.logger.Debug("SDS: dispatchCommunityChatMessage with communityID", zap.String("communityID", types.EncodeHex(rawMessage.CommunityID)))
343+
sdsWrappedPayload, err := s.wrapPayloadForSDS(rawMessage.Payload, rawMessage.CommunityID)
344+
if err != nil {
345+
return nil, errors.Wrap(err, "failed to wrap payload for SDS")
346+
}
347+
rawMessage.Payload = sdsWrappedPayload
348+
}
349+
314350
messageID, err := s.getMessageID(rawMessage)
315351
if err != nil {
316352
return nil, err
@@ -676,6 +712,15 @@ func (s *MessageSender) SendPublic(
676712
rawMessage.Sender = s.identity
677713
}
678714

715+
if rawMessage.CommunityID != nil && len(rawMessage.CommunityID) > 0 && rawMessage.MessageType != protobuf.ApplicationMetadataMessage_COMMUNITY_DESCRIPTION {
716+
s.logger.Debug("SDS: SendPublic with communityID", zap.String("communityID", types.EncodeHex(rawMessage.CommunityID)))
717+
sdsWrappedPayload, err := s.wrapPayloadForSDS(rawMessage.Payload, rawMessage.CommunityID)
718+
if err != nil {
719+
return nil, errors.Wrap(err, "failed to wrap payload for SDS")
720+
}
721+
rawMessage.Payload = sdsWrappedPayload
722+
}
723+
679724
var wrappedMessage []byte
680725
var err error
681726
if rawMessage.SkipApplicationWrap {
@@ -932,6 +977,7 @@ func (s *MessageSender) handleMessage(receivedMsg *messagingtypes.ReceivedMessag
932977
}
933978

934979
// Not a critical error; message wasn't segmented, proceed with next layers.
980+
hlogger.Error("failed to handle segmentation layer message", zap.Error(err))
935981
}
936982

937983
err = s.handleEncryptionLayer(context.Background(), message)
@@ -960,6 +1006,11 @@ func (s *MessageSender) handleMessage(receivedMsg *messagingtypes.ReceivedMessag
9601006
zap.String("envelopeHash", hexutil.Encode(msg.TransportLayer.Hash)),
9611007
zap.String("messageId", hexutil.Encode(msg.ApplicationLayer.ID)),
9621008
)
1009+
1010+
err = s.unwrapPayloadForSDS(msg)
1011+
if err != nil {
1012+
hlogger.Error("failed to unwrap payload for SDS", zap.Error(err))
1013+
}
9631014
}
9641015

9651016
return response, nil
@@ -1386,3 +1437,36 @@ func populateMessageApplicationLayer(m *messagingtypes.Message) error {
13861437
m.ApplicationLayer.Type = message.Type
13871438
return nil
13881439
}
1440+
1441+
// Wrap message with SDS protocol https://github.com/vacp2p/rfc-index/blob/main/vac/raw/sds.md
1442+
func (s *MessageSender) wrapPayloadForSDS(payload []byte, communityID []byte) ([]byte, error) {
1443+
sdsMessageID := crypto.Keccak256(payload)
1444+
1445+
s.logger.Debug("SDS: original payload",
1446+
zap.String("channelId", types.EncodeHex(communityID)),
1447+
zap.Int("payload-length", len(payload)),
1448+
zap.String("messageId", types.EncodeHex(sdsMessageID)),
1449+
)
1450+
sdsWrappedPayload, err := s.reliabilityManager.WrapOutgoingMessage(payload, sds.MessageID(types.EncodeHex(sdsMessageID)), types.EncodeHex(communityID))
1451+
if err != nil {
1452+
return nil, errors.Wrap(err, "SDS: failed to wrap a community message")
1453+
}
1454+
1455+
return sdsWrappedPayload, nil
1456+
}
1457+
1458+
func (s *MessageSender) unwrapPayloadForSDS(msg *messagingtypes.Message) error {
1459+
if len(msg.EncryptionLayer.Payload) > 0 {
1460+
unwrappedMessage, err := s.reliabilityManager.UnwrapReceivedMessage(msg.ApplicationLayer.Payload)
1461+
if err != nil {
1462+
s.logger.Error("SDS: failed to unwrap received message", zap.Error(err))
1463+
} else {
1464+
msg.ApplicationLayer.Payload = *unwrappedMessage.Message
1465+
s.logger.Debug("SDS: missing deps",
1466+
zap.Any("missing-deps", *unwrappedMessage.MissingDeps),
1467+
)
1468+
}
1469+
}
1470+
1471+
return nil
1472+
}

nix/pkgs/status-go/mobile/build.nix

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
platform ? "android",
66
platformVersion ? "23",
77
targets ? [ "android/arm64" ],
8-
goBuildFlags ? [ ], # Use -v or -x for debugging.
8+
goBuildFlags ? [ -v ], # Use -v or -x for debugging.
99
goBuildLdFlags ? [ ],
1010
outputFileName,
1111
}:

protocol/messenger.go

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1818,18 +1818,17 @@ func (m *Messenger) dispatchMessage(ctx context.Context, rawMessage messagingtyp
18181818
if err != nil {
18191819
return rawMessage, err
18201820
}
1821+
rawMessage.CommunityID, err = types.DecodeHex(chat.CommunityID)
1822+
if err != nil {
1823+
return rawMessage, err
1824+
}
18211825
isEncrypted := isCommunityEncrypted || isChannelEncrypted
18221826
if !isEncrypted {
18231827
id, err = m.messaging.SendPublic(ctx, rawMessage.ContentTopic, rawMessage)
18241828
if err != nil {
18251829
return rawMessage, err
18261830
}
18271831
} else {
1828-
rawMessage.CommunityID, err = types.DecodeHex(chat.CommunityID)
1829-
if err != nil {
1830-
return rawMessage, err
1831-
}
1832-
18331832
if isChannelEncrypted {
18341833
rawMessage.HashRatchetGroupID = []byte(chat.ID)
18351834
} else {

0 commit comments

Comments
 (0)