Skip to content

Commit 5ae7245

Browse files
refactor: require router requests to include a persona tag (#642)
1 parent 22ce242 commit 5ae7245

File tree

21 files changed

+237
-140
lines changed

21 files changed

+237
-140
lines changed

cardinal/go.mod

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ require (
4141
gotest.tools/v3 v3.5.1
4242
pkg.world.dev/world-engine/assert v1.0.0
4343
pkg.world.dev/world-engine/evm v1.0.4-0.20240227035346-26b21454bb27
44-
pkg.world.dev/world-engine/rift v1.0.0-beta.0.20240228200800-1b976869f98c
44+
pkg.world.dev/world-engine/rift v1.0.0-beta.0.20240229194424-80acab903631
4545
pkg.world.dev/world-engine/sign v1.0.1-beta
4646
)
4747

cardinal/go.sum

+4-2
Original file line numberDiff line numberDiff line change
@@ -1022,10 +1022,12 @@ pkg.world.dev/world-engine/assert v1.0.0 h1:vD6+QLT1pvQa86FPFi+wGcVA7PEwTGndXr+P
10221022
pkg.world.dev/world-engine/assert v1.0.0/go.mod h1:bwA9YZ40+Tte6GUKibfqByxBLLt+54zjjFako8cpSuU=
10231023
pkg.world.dev/world-engine/evm v1.0.4-0.20240227035346-26b21454bb27 h1:KBp8rJCqqqRbGs5PuFvPsQ1EoI24vRFGhyCezMrNJ60=
10241024
pkg.world.dev/world-engine/evm v1.0.4-0.20240227035346-26b21454bb27/go.mod h1:GEAeoxsr7DVTC/uIMe03UMdQmIlTghGT7TiouGRkuv4=
1025-
pkg.world.dev/world-engine/rift v1.0.0-beta.0.20240227034741-42bcc7370398 h1:TIo6GpegYuOwcUt7HMSdxau5qEscuJCtkh3v/LWX5jY=
1026-
pkg.world.dev/world-engine/rift v1.0.0-beta.0.20240227034741-42bcc7370398/go.mod h1:CIqUi3eVvHyglcXEmvvVhPeFR2OfEhykrpufXGAnxGk=
10271025
pkg.world.dev/world-engine/rift v1.0.0-beta.0.20240228200800-1b976869f98c h1:B9Jml627mvbBZEZSA2eSvbFPdnHzYoaNq0eH6GX7MEA=
10281026
pkg.world.dev/world-engine/rift v1.0.0-beta.0.20240228200800-1b976869f98c/go.mod h1:CIqUi3eVvHyglcXEmvvVhPeFR2OfEhykrpufXGAnxGk=
1027+
pkg.world.dev/world-engine/rift v1.0.0-beta.0.20240229190150-770ff015ead0 h1:s5eBwlSbnBvKEj6BgfeJ2PJuwBc2R72wBqTcNiS+rd0=
1028+
pkg.world.dev/world-engine/rift v1.0.0-beta.0.20240229190150-770ff015ead0/go.mod h1:CIqUi3eVvHyglcXEmvvVhPeFR2OfEhykrpufXGAnxGk=
1029+
pkg.world.dev/world-engine/rift v1.0.0-beta.0.20240229194424-80acab903631 h1:7M05p5W9nUMz+JbMasS3rdECcyC6Hp7z1eeIzxw2MKI=
1030+
pkg.world.dev/world-engine/rift v1.0.0-beta.0.20240229194424-80acab903631/go.mod h1:CIqUi3eVvHyglcXEmvvVhPeFR2OfEhykrpufXGAnxGk=
10291031
pkg.world.dev/world-engine/sign v1.0.1-beta h1:ZwVeJYdf88t6qIHPurbdKJKVxUN0dfp0gSF7OCA9xt8=
10301032
pkg.world.dev/world-engine/sign v1.0.1-beta/go.mod h1:U6XdRfjzoodAScJ/bH4qzxY7gbqbgGV2Od+k3tSTekE=
10311033
sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo=

cardinal/router/mocks/provider.go

+8-7
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cardinal/router/provider.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package router
22

33
import (
4+
"pkg.world.dev/world-engine/cardinal/persona/component"
45
"pkg.world.dev/world-engine/cardinal/types"
56
"pkg.world.dev/world-engine/sign"
67
)
@@ -13,7 +14,7 @@ type Provider interface {
1314
GetMessageByName(string) (types.Message, bool)
1415
GetMessageByID(id types.MessageID) (types.Message, bool)
1516
HandleEVMQuery(name string, abiRequest []byte) ([]byte, error)
16-
GetPersonaForEVMAddress(string) (string, error)
17+
GetSignerComponentForPersona(string) (*component.SignerComponent, error)
1718
WaitForNextTick() bool
1819

1920
AddEVMTransaction(id types.MessageID, msgValue any, tx *sign.Transaction, evmTxHash string) (

cardinal/router/router_evm_server.go

+14-4
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"google.golang.org/grpc"
99
routerv1 "pkg.world.dev/world-engine/rift/router/v1"
1010
"pkg.world.dev/world-engine/sign"
11+
"slices"
1112
)
1213

1314
const (
@@ -64,11 +65,20 @@ func (e *evmServer) SendMessage(_ context.Context, req *routerv1.SendMessageRequ
6465
}, nil
6566
}
6667

67-
// check if the sender has a linked persona address. if not don't process the transaction.
68-
personaTag, err := e.provider.GetPersonaForEVMAddress(req.Sender)
68+
// get the signer component for the persona tag the request wants to use, and check if the evm address in the
69+
// sender is present in the signer component's authorized address list.
70+
signer, err := e.provider.GetSignerComponentForPersona(req.PersonaTag)
6971
if err != nil {
7072
return &routerv1.SendMessageResponse{
71-
Errs: fmt.Errorf("unable to find persona tag associated with the EVM address %q: %w", req.Sender, err).
73+
Errs: fmt.Errorf("unable to find persona tag %q: %w", req.PersonaTag, err).
74+
Error(),
75+
EvmTxHash: req.EvmTxHash,
76+
Code: CodeUnauthorized,
77+
}, nil
78+
}
79+
if !slices.Contains(signer.AuthorizedAddresses, req.Sender) {
80+
return &routerv1.SendMessageResponse{
81+
Errs: fmt.Errorf("persona tag %q has not authorized address %q", req.PersonaTag, req.Sender).
7282
Error(),
7383
EvmTxHash: req.EvmTxHash,
7484
Code: CodeUnauthorized,
@@ -77,7 +87,7 @@ func (e *evmServer) SendMessage(_ context.Context, req *routerv1.SendMessageRequ
7787

7888
// since we are injecting the msgValue directly, all we need is the persona tag in the signed payload.
7989
// the sig checking happens in the grpcServer's Handler, not in ecs.Engine.
80-
sig := &sign.Transaction{PersonaTag: personaTag}
90+
sig := &sign.Transaction{PersonaTag: req.PersonaTag}
8191
e.provider.AddEVMTransaction(msgType.ID(), msgValue, sig, req.EvmTxHash)
8292

8393
// wait for the next tick so the msgValue gets processed

cardinal/router/router_test.go

+59-14
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"github.com/golang/mock/gomock"
99
"google.golang.org/grpc"
1010
"pkg.world.dev/world-engine/assert"
11+
"pkg.world.dev/world-engine/cardinal/persona/component"
1112
"pkg.world.dev/world-engine/cardinal/router/mocks"
1213
"pkg.world.dev/world-engine/cardinal/types"
1314
routerv1 "pkg.world.dev/world-engine/rift/router/v1"
@@ -104,13 +105,14 @@ func TestRouter_SendMessage_PersonaNotFound(t *testing.T) {
104105
}
105106
name := "foo"
106107
sender := "0xtyler"
108+
persona := "tyler"
107109

108110
provider.EXPECT().GetMessageByName(name).Return(msg, true).Times(1)
109-
provider.EXPECT().GetPersonaForEVMAddress(sender).Return("", fmt.Errorf("not found")).Times(1)
111+
provider.EXPECT().GetSignerComponentForPersona(persona).Return(nil, fmt.Errorf("not found")).Times(1)
110112

111113
res, err := router.server.SendMessage(
112114
context.Background(),
113-
&routerv1.SendMessageRequest{MessageId: name, Sender: sender},
115+
&routerv1.SendMessageRequest{MessageId: name, PersonaTag: persona, Sender: sender},
114116
)
115117
assert.NilError(t, err)
116118
assert.Equal(t, res.Code, CodeUnauthorized)
@@ -130,13 +132,17 @@ func TestRouter_SendMessage_ResultDoesNotExist(t *testing.T) {
130132
evmTxHash := "0xFooBarBaz"
131133

132134
req := &routerv1.SendMessageRequest{
133-
Sender: sender,
134-
MessageId: msgName,
135-
EvmTxHash: evmTxHash,
135+
Sender: sender,
136+
MessageId: msgName,
137+
PersonaTag: persona,
138+
EvmTxHash: evmTxHash,
136139
}
137140

138141
provider.EXPECT().GetMessageByName(msgName).Return(msg, true).Times(1)
139-
provider.EXPECT().GetPersonaForEVMAddress(sender).Return(persona, nil).Times(1)
142+
provider.EXPECT().
143+
GetSignerComponentForPersona(persona).
144+
Return(&component.SignerComponent{AuthorizedAddresses: []string{sender}}, nil).
145+
Times(1)
140146
provider.EXPECT().AddEVMTransaction(msg.id, msgValue, &sign.Transaction{PersonaTag: persona}, evmTxHash).Times(1)
141147
provider.EXPECT().WaitForNextTick().Return(true).Times(1)
142148
provider.EXPECT().ConsumeEVMMsgResult(evmTxHash).Return(nil, nil, "", false).Times(1)
@@ -160,13 +166,17 @@ func TestRouter_SendMessage_TxSuccess(t *testing.T) {
160166
evmTxHash := "0xFooBarBaz"
161167

162168
req := &routerv1.SendMessageRequest{
163-
Sender: sender,
164-
MessageId: msgName,
165-
EvmTxHash: evmTxHash,
169+
Sender: sender,
170+
PersonaTag: persona,
171+
MessageId: msgName,
172+
EvmTxHash: evmTxHash,
166173
}
167174

168175
provider.EXPECT().GetMessageByName(msgName).Return(msg, true).Times(1)
169-
provider.EXPECT().GetPersonaForEVMAddress(sender).Return(persona, nil).Times(1)
176+
provider.EXPECT().
177+
GetSignerComponentForPersona(persona).
178+
Return(&component.SignerComponent{AuthorizedAddresses: []string{sender}}, nil).
179+
Times(1)
170180
provider.EXPECT().AddEVMTransaction(msg.id, msgValue, &sign.Transaction{PersonaTag: persona}, evmTxHash).Times(1)
171181
provider.EXPECT().WaitForNextTick().Return(true).Times(1)
172182
provider.EXPECT().ConsumeEVMMsgResult(evmTxHash).Return([]byte("response"), nil, evmTxHash, true).Times(1)
@@ -176,6 +186,37 @@ func TestRouter_SendMessage_TxSuccess(t *testing.T) {
176186
assert.Equal(t, res.Code, CodeSuccess)
177187
}
178188

189+
func TestRouter_SendMessage_NoAuthorizedAddress(t *testing.T) {
190+
router, provider := getTestRouterAndProvider(t)
191+
msgValue := []byte("hello")
192+
msg := &mockMsg{
193+
id: 5, evmCompat: true, decodeEVMBytes: func() ([]byte, error) {
194+
return msgValue, nil
195+
},
196+
}
197+
msgName := "foo"
198+
sender := "0xtyler"
199+
persona := "tyler"
200+
evmTxHash := "0xFooBarBaz"
201+
202+
req := &routerv1.SendMessageRequest{
203+
Sender: sender,
204+
MessageId: msgName,
205+
PersonaTag: persona,
206+
EvmTxHash: evmTxHash,
207+
}
208+
209+
provider.EXPECT().GetMessageByName(msgName).Return(msg, true).Times(1)
210+
provider.EXPECT().
211+
GetSignerComponentForPersona(persona).
212+
Return(&component.SignerComponent{AuthorizedAddresses: []string{"bogus"}}, nil).
213+
Times(1)
214+
215+
res, err := router.server.SendMessage(context.Background(), req)
216+
assert.NilError(t, err)
217+
assert.Equal(t, res.Code, CodeUnauthorized)
218+
}
219+
179220
func TestRouter_SendMessage_TxFailed(t *testing.T) {
180221
router, provider := getTestRouterAndProvider(t)
181222
msgValue := []byte("hello")
@@ -190,13 +231,17 @@ func TestRouter_SendMessage_TxFailed(t *testing.T) {
190231
evmTxHash := "0xFooBarBaz"
191232

192233
req := &routerv1.SendMessageRequest{
193-
Sender: sender,
194-
MessageId: msgName,
195-
EvmTxHash: evmTxHash,
234+
Sender: sender,
235+
MessageId: msgName,
236+
PersonaTag: persona,
237+
EvmTxHash: evmTxHash,
196238
}
197239

198240
provider.EXPECT().GetMessageByName(msgName).Return(msg, true).Times(1)
199-
provider.EXPECT().GetPersonaForEVMAddress(sender).Return(persona, nil).Times(1)
241+
provider.EXPECT().
242+
GetSignerComponentForPersona(persona).
243+
Return(&component.SignerComponent{AuthorizedAddresses: []string{sender}}, nil).
244+
Times(1)
200245
provider.EXPECT().AddEVMTransaction(msg.id, msgValue, &sign.Transaction{PersonaTag: persona}, evmTxHash).Times(1)
201246
provider.EXPECT().WaitForNextTick().Return(true).Times(1)
202247
provider.EXPECT().

cardinal/world_persona.go

+8-11
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ func (w *World) GetSignerForPersonaTag(personaTag string, tick uint64) (addr str
3939
return addr, errors.Join(errs...)
4040
}
4141

42-
func (w *World) GetPersonaForEVMAddress(addr string) (string, error) {
42+
func (w *World) GetSignerComponentForPersona(personaTag string) (*component.SignerComponent, error) {
4343
var sc *component.SignerComponent
4444
wCtx := NewReadOnlyWorldContext(w)
4545
q := NewSearch(wCtx, filter.Exact(component.SignerComponent{}))
@@ -49,28 +49,25 @@ func (w *World) GetPersonaForEVMAddress(addr string) (string, error) {
4949
func(id types.EntityID) bool {
5050
var signerComp *component.SignerComponent
5151
signerComp, getComponentErr = GetComponent[component.SignerComponent](wCtx, id)
52-
getComponentErr = eris.Wrap(getComponentErr, "")
5352
if getComponentErr != nil {
5453
return false
5554
}
56-
for _, authAddr := range signerComp.AuthorizedAddresses {
57-
if authAddr == addr {
58-
sc = signerComp
59-
return false
60-
}
55+
if signerComp.PersonaTag == personaTag {
56+
sc = signerComp
57+
return false
6158
}
6259
return true
6360
},
6461
), "",
6562
)
6663
if getComponentErr != nil {
67-
return "", getComponentErr
64+
return nil, getComponentErr
6865
}
6966
if searchIterationErr != nil {
70-
return "", searchIterationErr
67+
return nil, searchIterationErr
7168
}
7269
if sc == nil {
73-
return "", eris.Errorf("address %s does not have a linked persona tag", addr)
70+
return nil, eris.Errorf("persona tag %q not found", personaTag)
7471
}
75-
return sc.PersonaTag, nil
72+
return sc, nil
7673
}

cardinal/world_persona_test.go

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package cardinal_test
2+
3+
import (
4+
"fmt"
5+
"pkg.world.dev/world-engine/assert"
6+
msg2 "pkg.world.dev/world-engine/cardinal/persona/msg"
7+
"pkg.world.dev/world-engine/cardinal/testutils"
8+
"pkg.world.dev/world-engine/sign"
9+
"testing"
10+
)
11+
12+
func TestGetSignerComponentForPersona(t *testing.T) {
13+
tf := testutils.NewTestFixture(t, nil)
14+
world := tf.World
15+
msg, exists := world.GetMessageByName("create-persona")
16+
assert.True(t, exists)
17+
personaTag := "tyler"
18+
signer := "foobar"
19+
createPersonaMsg := msg2.CreatePersona{
20+
PersonaTag: personaTag,
21+
SignerAddress: signer,
22+
}
23+
world.AddTransaction(msg.ID(), createPersonaMsg, &sign.Transaction{})
24+
tf.DoTick()
25+
26+
sc, err := world.GetSignerComponentForPersona(personaTag)
27+
assert.NilError(t, err)
28+
assert.Equal(t, sc.PersonaTag, personaTag)
29+
assert.Equal(t, sc.SignerAddress, signer)
30+
31+
notRealPersona := "nobody_important"
32+
sc, err = world.GetSignerComponentForPersona(notRealPersona)
33+
assert.ErrorContains(t, err, fmt.Sprintf("persona tag %q not found", notRealPersona))
34+
assert.Nil(t, sc)
35+
}

e2e/chain/go.mod

+2
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ require (
1919
google.golang.org/grpc v1.59.0
2020
gotest.tools/v3 v3.5.1
2121
pkg.world.dev/world-engine/evm v1.0.2-beta
22+
pkg.world.dev/world-engine/rift v1.0.0-beta.0.20240229190150-770ff015ead0
2223
)
2324

2425
require (
@@ -35,6 +36,7 @@ require (
3536
github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect
3637
github.com/99designs/keyring v1.2.1 // indirect
3738
github.com/DataDog/zstd v1.5.5 // indirect
39+
github.com/JeremyLoy/config v1.5.0 // indirect
3840
github.com/beorn7/perks v1.0.1 // indirect
3941
github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 // indirect
4042
github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect

e2e/chain/go.sum

+6
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym
6565
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
6666
github.com/DataDog/zstd v1.5.5 h1:oWf5W7GtOLgp6bciQYDmhHHjdhYkALu6S/5Ni9ZgSvQ=
6767
github.com/DataDog/zstd v1.5.5/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw=
68+
github.com/JeremyLoy/config v1.5.0 h1:CEKqDuZIvb9r2sUZpMk8oLZOMODWMxC+Hs5bD+bN+hc=
69+
github.com/JeremyLoy/config v1.5.0/go.mod h1:Q89XwS4S1w+hjmGVcWwb6yZjNWH3QfussGr/+y0u6Fg=
6870
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
6971
github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE=
7072
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
@@ -106,6 +108,8 @@ github.com/btcsuite/btcd/btcutil v1.1.3 h1:xfbtw8lwpp0G6NwSHb+UE67ryTFHJAiNuipus
106108
github.com/btcsuite/btcd/btcutil v1.1.3/go.mod h1:UR7dsSJzJUfMmFiiLlIrMq1lS9jh9EdCV7FStZSnpi0=
107109
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2 h1:KdUfX2zKommPRa+PD0sWZUyXe9w277ABlgELO7H04IM=
108110
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc=
111+
github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce h1:YtWJF7RHm2pYCvA5t0RPmAaLUhREsKuKd+SLhxFbFeQ=
112+
github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce/go.mod h1:0DVlHczLPewLcPGEIeUEzfOJhqGPQ0mJJRDBtD307+o=
109113
github.com/bufbuild/protocompile v0.6.0 h1:Uu7WiSQ6Yj9DbkdnOe7U4mNKp58y9WDMKDn28/ZlunY=
110114
github.com/bufbuild/protocompile v0.6.0/go.mod h1:YNP35qEYoYGme7QMtz5SBCoN4kL4g12jTtjuzRNdjpE=
111115
github.com/bytedance/sonic v1.10.0 h1:qtNZduETEIWJVIyDl01BeNxur2rW9OwTQ/yBqFRkKEk=
@@ -1444,6 +1448,8 @@ nhooyr.io/websocket v1.8.7 h1:usjR2uOr/zjjkVMy0lW+PPohFok7PCow5sDjLgX4P4g=
14441448
nhooyr.io/websocket v1.8.7/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0=
14451449
pgregory.net/rapid v1.1.0 h1:CMa0sjHSru3puNx+J0MIAuiiEV4N0qj8/cMWGBBCsjw=
14461450
pgregory.net/rapid v1.1.0/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04=
1451+
pkg.world.dev/world-engine/rift v1.0.0-beta.0.20240229190150-770ff015ead0 h1:s5eBwlSbnBvKEj6BgfeJ2PJuwBc2R72wBqTcNiS+rd0=
1452+
pkg.world.dev/world-engine/rift v1.0.0-beta.0.20240229190150-770ff015ead0/go.mod h1:CIqUi3eVvHyglcXEmvvVhPeFR2OfEhykrpufXGAnxGk=
14471453
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
14481454
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
14491455
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=

evm/go.mod

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ require (
5252
pkg.berachain.dev/polaris/eth v0.0.0-20231106013048-594360df8f05
5353
pkg.berachain.dev/polaris/lib v0.0.0-20231104204753-faadca38b64d
5454
pkg.world.dev/world-engine/assert v1.0.0
55-
pkg.world.dev/world-engine/rift v1.0.0-beta.0.20240227034741-42bcc7370398
55+
pkg.world.dev/world-engine/rift v1.0.0-beta.0.20240229194424-80acab903631
5656
)
5757

5858
require (

evm/go.sum

+6-2
Original file line numberDiff line numberDiff line change
@@ -3108,8 +3108,12 @@ pkg.berachain.dev/polaris/lib v0.0.0-20231104204753-faadca38b64d h1:LMuJ+fYqzSbz
31083108
pkg.berachain.dev/polaris/lib v0.0.0-20231104204753-faadca38b64d/go.mod h1:6w+5Axb6GV66PLllrYf7h1G3x8Pwu5nvd7ZiibiI3HM=
31093109
pkg.world.dev/world-engine/assert v1.0.0 h1:vD6+QLT1pvQa86FPFi+wGcVA7PEwTGndXr+PkTY/Fpw=
31103110
pkg.world.dev/world-engine/assert v1.0.0/go.mod h1:bwA9YZ40+Tte6GUKibfqByxBLLt+54zjjFako8cpSuU=
3111-
pkg.world.dev/world-engine/rift v1.0.0-beta.0.20240227034741-42bcc7370398 h1:TIo6GpegYuOwcUt7HMSdxau5qEscuJCtkh3v/LWX5jY=
3112-
pkg.world.dev/world-engine/rift v1.0.0-beta.0.20240227034741-42bcc7370398/go.mod h1:CIqUi3eVvHyglcXEmvvVhPeFR2OfEhykrpufXGAnxGk=
3111+
pkg.world.dev/world-engine/rift v1.0.0-beta.0.20240228200800-1b976869f98c h1:B9Jml627mvbBZEZSA2eSvbFPdnHzYoaNq0eH6GX7MEA=
3112+
pkg.world.dev/world-engine/rift v1.0.0-beta.0.20240228200800-1b976869f98c/go.mod h1:CIqUi3eVvHyglcXEmvvVhPeFR2OfEhykrpufXGAnxGk=
3113+
pkg.world.dev/world-engine/rift v1.0.0-beta.0.20240229190150-770ff015ead0 h1:s5eBwlSbnBvKEj6BgfeJ2PJuwBc2R72wBqTcNiS+rd0=
3114+
pkg.world.dev/world-engine/rift v1.0.0-beta.0.20240229190150-770ff015ead0/go.mod h1:CIqUi3eVvHyglcXEmvvVhPeFR2OfEhykrpufXGAnxGk=
3115+
pkg.world.dev/world-engine/rift v1.0.0-beta.0.20240229194424-80acab903631 h1:7M05p5W9nUMz+JbMasS3rdECcyC6Hp7z1eeIzxw2MKI=
3116+
pkg.world.dev/world-engine/rift v1.0.0-beta.0.20240229194424-80acab903631/go.mod h1:CIqUi3eVvHyglcXEmvvVhPeFR2OfEhykrpufXGAnxGk=
31133117
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
31143118
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
31153119
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=

0 commit comments

Comments
 (0)