Skip to content

Commit 697c3b5

Browse files
authored
Absgrafx/main (#724)
2 parents beeb09c + be75e79 commit 697c3b5

30 files changed

Lines changed: 2965 additions & 121 deletions

proxy-router/internal/attestation/golden.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,11 @@ func (g *GoldenSource) verifyAndExtract(ctx context.Context, version string) (*G
217217
return nil, fmt.Errorf("failed to read referrer index manifest: %w", err)
218218
}
219219

220-
trustedRoot, err := root.FetchTrustedRoot()
220+
// Use a sandbox-safe TUF cache directory when the mobile embedder has
221+
// configured one via [SetSigstoreCacheDir]; falls back to the library
222+
// default ($HOME/.sigstore/root) on desktop/server builds. See
223+
// sigstore_cache.go for why this override exists.
224+
trustedRoot, err := root.FetchTrustedRootWithOptions(tufOptions())
221225
if err != nil {
222226
return nil, fmt.Errorf("failed to fetch Sigstore trusted root: %w", err)
223227
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package attestation
2+
3+
import (
4+
"path/filepath"
5+
"sync"
6+
7+
"github.com/sigstore/sigstore-go/pkg/tuf"
8+
)
9+
10+
// sigstoreCacheDir, when non-empty, overrides the default TUF cache location
11+
// (`$HOME/.sigstore/root`) used by [sigstore-go] when fetching the trusted
12+
// root. The default path blows up inside the iOS app sandbox — the home
13+
// directory returned by `os.UserHomeDir()` maps to
14+
// `/private/var/mobile/Containers/Data/Application/<UUID>/` which is
15+
// read-only at the top level; only `Documents/` and `Library/` are
16+
// writable. Mobile embedders call [SetSigstoreCacheDir] during SDK init to
17+
// point TUF at the app's writable data directory instead.
18+
var (
19+
sigstoreCacheMu sync.RWMutex
20+
sigstoreCacheDir string
21+
)
22+
23+
// SetSigstoreCacheDir configures a writable directory to be used as the
24+
// Sigstore TUF metadata cache. Pass an empty string to fall back to the
25+
// library default ($HOME/.sigstore/root), which is the right choice on
26+
// desktop and server builds.
27+
//
28+
// Safe to call from any goroutine; takes effect on the next trusted-root
29+
// fetch. The supplied path is joined with a `sigstore` subdirectory so
30+
// mobile apps can share a single data-dir across multiple Go caches
31+
// without them colliding.
32+
func SetSigstoreCacheDir(dir string) {
33+
sigstoreCacheMu.Lock()
34+
defer sigstoreCacheMu.Unlock()
35+
if dir == "" {
36+
sigstoreCacheDir = ""
37+
return
38+
}
39+
sigstoreCacheDir = filepath.Join(dir, "sigstore")
40+
}
41+
42+
// tufOptions returns a fresh [tuf.Options] with the sandbox-safe cache path
43+
// applied if one has been configured. Callers should treat the result as
44+
// ephemeral and not cache it between fetches — the underlying options hold
45+
// a mutable CachePath.
46+
func tufOptions() *tuf.Options {
47+
opts := tuf.DefaultOptions()
48+
sigstoreCacheMu.RLock()
49+
dir := sigstoreCacheDir
50+
sigstoreCacheMu.RUnlock()
51+
if dir != "" {
52+
opts = opts.WithCachePath(dir)
53+
}
54+
return opts
55+
}
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
package blockchainapi
2+
3+
import (
4+
"math/big"
5+
"testing"
6+
7+
"github.com/MorpheusAIs/Morpheus-Lumerin-Node/proxy-router/internal/blockchainapi/structs"
8+
"github.com/MorpheusAIs/Morpheus-Lumerin-Node/proxy-router/internal/lib"
9+
)
10+
11+
func TestComputeSessionTokenAmount(t *testing.T) {
12+
makeBid := func(pricePerSecond int64) *structs.Bid {
13+
return &structs.Bid{
14+
PricePerSecond: &lib.BigInt{Int: *big.NewInt(pricePerSecond)},
15+
}
16+
}
17+
18+
tests := []struct {
19+
name string
20+
bid *structs.Bid
21+
duration *big.Int
22+
supply *big.Int
23+
budget *big.Int
24+
directPayment bool
25+
want *big.Int
26+
wantErr bool
27+
}{
28+
{
29+
name: "direct payment",
30+
bid: makeBid(100),
31+
duration: big.NewInt(3600),
32+
supply: big.NewInt(1_000_000),
33+
budget: big.NewInt(50_000),
34+
directPayment: true,
35+
want: big.NewInt(360_000),
36+
},
37+
{
38+
name: "staked",
39+
bid: makeBid(100),
40+
duration: big.NewInt(3600),
41+
supply: big.NewInt(1_000_000),
42+
budget: big.NewInt(50_000),
43+
directPayment: false,
44+
want: big.NewInt(7_200_000),
45+
},
46+
{
47+
name: "nil bid",
48+
bid: nil,
49+
duration: big.NewInt(3600),
50+
supply: big.NewInt(1_000_000),
51+
budget: big.NewInt(50_000),
52+
directPayment: false,
53+
wantErr: true,
54+
},
55+
{
56+
name: "zero budget",
57+
bid: makeBid(100),
58+
duration: big.NewInt(3600),
59+
supply: big.NewInt(1_000_000),
60+
budget: big.NewInt(0),
61+
directPayment: false,
62+
wantErr: true,
63+
},
64+
{
65+
name: "nil budget",
66+
bid: makeBid(100),
67+
duration: big.NewInt(3600),
68+
supply: big.NewInt(1_000_000),
69+
budget: nil,
70+
directPayment: false,
71+
wantErr: true,
72+
},
73+
}
74+
75+
for _, tt := range tests {
76+
t.Run(tt.name, func(t *testing.T) {
77+
got, err := computeSessionTokenAmount(tt.bid, tt.duration, tt.supply, tt.budget, tt.directPayment)
78+
if tt.wantErr {
79+
if err == nil {
80+
t.Fatalf("expected error, got result %s", got)
81+
}
82+
return
83+
}
84+
if err != nil {
85+
t.Fatalf("unexpected error: %v", err)
86+
}
87+
if got.Cmp(tt.want) != 0 {
88+
t.Errorf("got %s, want %s", got, tt.want)
89+
}
90+
})
91+
}
92+
}

0 commit comments

Comments
 (0)