mirror of
https://github.com/luxfi/mpc.git
synced 2026-09-24 00:26:24 +00:00
kms/release: wire cc/attest chain verifier into Release path
Red Final N1 fix. Release() previously called only Attestation.Verify(nonce) and ReleasePolicy.Permits() before sealing the session key. Neither step performs the actual SEV-SNP / TDX / NRAS chain verification — AMD KDS lookup, ARK→ASK→VCEK chain, NRAS JWT — leaving the #222 go-sev-guest verifier as dead code on the release path. A worker that fabricates a CompositeAttestation envelope whose Verify(nonce) returns true and whose RIM/HW/issuer membership matches policy could harvest a session key without ever presenting AMD-signed evidence. Wire-in: - kms.CompositeAttestation gains VerifyEvidence(ctx, opts...) returning []*attest.VerifiedReport. *attestation.CompositeAttestation already implements this method (composite.go:320 → attest.Dispatch per blob). - ReleaseRequest gains optional Ctx + AttestOptions for context plumbing + per-call policy (e.g. attest.WithExpectedReportData(nonce[:])). - Release() calls VerifyEvidence between the cheap nonce check and the policy permit step. Any chain failure → ErrAttestationChain joined with ErrPolicyRefused via errors.Join. No silent acceptance. - New sentinel ErrAttestationChain. Tests (go test -v -short -race -count=1 -timeout 60s ./pkg/kms/...): - all 14 existing TestRelease_/TestNonce_/TestAAD_ remain green - NEW TestRelease_RefusesOnChainFailure: Verify(nonce)=true but VerifyEvidence returns ErrChainInvalid → MUST surface ErrAttestationChain wrapped under ErrPolicyRefused - NEW TestRelease_AcceptsOnChainPass: paired happy-path so the chain-step is the only difference, not a wiring regression Also pulled in cherry-pick of canonical go-sev-guest sums (c4f1e22) so cc/attest builds reproducibly outside the dirty local cache.
This commit is contained in:
@@ -111,6 +111,7 @@ require (
|
||||
github.com/golang/mock v1.6.0 // indirect
|
||||
github.com/google/flatbuffers v25.12.19+incompatible // indirect
|
||||
github.com/google/go-cmp v0.7.0 // indirect
|
||||
github.com/google/go-sev-guest v0.14.1 // indirect
|
||||
github.com/google/s2a-go v0.1.9 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.14 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.21.0 // indirect
|
||||
|
||||
@@ -55,6 +55,8 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
|
||||
github.com/ansel1/merry v1.8.1/go.mod h1:wJVu1mHEtEUWq5zTTX9RiWjcE+xL8y7BGYl2VTYdP7M=
|
||||
github.com/ansel1/merry/v2 v2.2.2/go.mod h1:sludwzkWfhZHOF4jSOViv+t2nnu2HNmtsMKzAfwmVB8=
|
||||
github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA=
|
||||
github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4=
|
||||
github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg=
|
||||
|
||||
+3
-62
@@ -159,11 +159,8 @@ github.com/chelnak/ysmrr v0.6.0/go.mod h1:56JSrmQgb7/7xoMvuD87h3PE/qW6K1+BQcrgWt
|
||||
github.com/chengxilo/virtualterm v1.0.4/go.mod h1:DyxxBZz/x1iqJjFxTFcr6/x+jSpqN0iwWCOK1q10rlY=
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d/go.mod h1:8EPpVsBuRksnlj1mLy4AWzRNQYxauNi62uWcE3to6eA=
|
||||
github.com/chenzhuoyu/iasm v0.9.0/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObkaSkeBlk=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/clipperhouse/stringish v0.1.1/go.mod h1:v/WhFtE1q0ovMta2+m+UbpZ+2/HEXNWYXQgCt4hdOzA=
|
||||
@@ -313,9 +310,6 @@ github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71
|
||||
github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8=
|
||||
github.com/golang/mock v1.7.0-rc.1 h1:YojYx61/OLFsiv6Rw1Z96LpldJIy31o+UHmwAUMJ6/U=
|
||||
github.com/golang/mock v1.7.0-rc.1/go.mod h1:s42URUywIqd+OcERslBJvOjepvNymP31m3q8d/GkuRs=
|
||||
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
|
||||
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM=
|
||||
@@ -335,11 +329,11 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
||||
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-querystring v1.2.0/go.mod h1:8IFJqpSRITyJ8QhQ13bmbeMBDfmeEJZD5A0egEOmkqU=
|
||||
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/logger v1.1.1 h1:+6Z2geNxc9G+4D4oDO9njjjn2d0wN5d7uOo0vOIW1NQ=
|
||||
github.com/google/logger v1.1.1/go.mod h1:BkeJZ+1FhQ+/d087r4dzojEg1u2ZX+ZqG1jTUrLM+zQ=
|
||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||
github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||
@@ -472,14 +466,10 @@ github.com/luxfi/address v1.0.1/go.mod h1:5j3Eh66v9zvv1GbNdZwt+23krV8JlSDaRzmWZU
|
||||
github.com/luxfi/ai v0.0.0-20251225021023-3f15131f2bd1/go.mod h1:4+FVvnCo1QqM3NaVUte0da4zgH2IblVLmUxKQi0BwE0=
|
||||
github.com/luxfi/api v1.0.1/go.mod h1:N2Ymyqo3SoB6/DmPXRV6W377k2qNqZujSP/B8fbIB9U=
|
||||
github.com/luxfi/atomic v0.0.1/go.mod h1:UzFk1K7VXjJhjm2c4Yiu5HydKbWi36kFtrlDKbm8MG8=
|
||||
github.com/luxfi/atomic v1.0.0 h1:xUV60MuzRvXngaQ1sM0yVC2v4TRoLlUGkkH7M9PS4yw=
|
||||
github.com/luxfi/atomic v1.0.0/go.mod h1:0G2mTlQ6TXWHICUHrUUPu1/qAiIyR4gSZ2tva9ci/bI=
|
||||
github.com/luxfi/bft v0.1.0/go.mod h1:IUT167Erk2h8z36197Yrmu/3CBIsZku5WlEG8O2NMp4=
|
||||
github.com/luxfi/cache v1.1.0/go.mod h1:9GvlEEE9rFPaaWxvVpSPwW8ZMo2+8VMNNcuPa4AwzPg=
|
||||
github.com/luxfi/cache v1.2.0/go.mod h1:Esn48WMB3JL/+UOdCEV2Chyjr1MG3SSckXWLhB/P080=
|
||||
github.com/luxfi/codec v1.1.2/go.mod h1:T+DV0Jau5bi+8wMcaoj51zS1rgt80VovQKzaN2CV5Mg=
|
||||
github.com/luxfi/codec v1.1.4 h1:Yl8ZalMNkqo7cD6R9AjczAajkLOmsjyZ9+DASVYHrvg=
|
||||
github.com/luxfi/codec v1.1.4/go.mod h1:oGQ3j6E8c2P0pL0irYtWkrB1hmDUFIE0puXHK4gV5KI=
|
||||
github.com/luxfi/compress v0.0.2/go.mod h1:cfa7L3STdZdsMwJc9faZML1modLNh1n2u72n/DOfuNU=
|
||||
github.com/luxfi/compress v0.0.4/go.mod h1:/eN0eca98igoE6DDsLv/4w7n1gsQKwa+HUTxmWz/iWw=
|
||||
github.com/luxfi/concurrent v0.0.2/go.mod h1:SwEDrQXVAXgBiObXVg0pfmLzU1xsa9ZeBRptkBdyNUU=
|
||||
@@ -492,8 +482,6 @@ github.com/luxfi/consensus v1.22.62/go.mod h1:sEAGM6n/tGXx7Sd5d7F22862rqT8n2y+Z1
|
||||
github.com/luxfi/consensus v1.22.67/go.mod h1:mUffRVhwE3zz8bHwAIXT0xSroqOceszepHl8Tp6GwrI=
|
||||
github.com/luxfi/const v1.4.1/go.mod h1:qWfecjdImPY3kXsy3UAe4ZVpMcsp2/iUlHwUMPVREoI=
|
||||
github.com/luxfi/constants v1.4.2/go.mod h1:xk+0eA7UY1GkHrmI7yqR+9LDe4TUe3p1VfRvs6cJbNM=
|
||||
github.com/luxfi/constants v1.4.7 h1:e/Qs+DQP3pugle3Zncq6fZCxKgqqtbyD/z7Gm4ZjsYg=
|
||||
github.com/luxfi/constants v1.4.7/go.mod h1:hOszZ2NDQ8gMZKncfcZ67PXkb5OIbnwAzXC3oFbQwW0=
|
||||
github.com/luxfi/container v0.0.2/go.mod h1:nnK+TxHmGry0mGnfun4jx0tLqWJgV/GbZXTETMuFJn4=
|
||||
github.com/luxfi/coreth v0.15.71/go.mod h1:Z/OTRrw+q+uSNrCh1Fg0hkMf1fRquzbTQelx7wR0HOM=
|
||||
github.com/luxfi/crypto v1.17.28/go.mod h1:v6eaW5ejuzW2gecChWKQqx4CtVhoM1b+e40ro/6WVPg=
|
||||
@@ -501,28 +489,20 @@ github.com/luxfi/crypto v1.17.36/go.mod h1:UHzltsXPDF/tGcmTiL/DbkClAflr3YmvOaXlw
|
||||
github.com/luxfi/crypto v1.17.37/go.mod h1:vu+pCHdyPQZULzrA+K+lTFYrg8vOtNdu+/5Vko8RzZ0=
|
||||
github.com/luxfi/crypto v1.17.38/go.mod h1:G2t1GQvPsrwnzwyVEj0LQDuX2AWZVI5kEAPyVeicc5o=
|
||||
github.com/luxfi/crypto v1.17.39/go.mod h1:mChLWmW4CLR1wAN6CeJTveCzUv0DTzGQnYgq01x3W0U=
|
||||
github.com/luxfi/crypto v1.17.45 h1:uGK0y4+aLipE/M0YIQ5hcsWv0ZG0E4cPv03a94K/eLE=
|
||||
github.com/luxfi/crypto v1.17.45/go.mod h1:GnAkhQ7HNs3X0Tzx5nOONS3kl0yRmWHbDcRO5ffILsg=
|
||||
github.com/luxfi/czmq/v4 v4.2.2/go.mod h1:WFY9ldUbeU900P8bcIRr7Jim23veOhJL5A5zSpTogdU=
|
||||
github.com/luxfi/database v1.17.35/go.mod h1:dYxaF30KGJQzuxA3VH7+WGU5/dhwRyzLgzSk9F3wje0=
|
||||
github.com/luxfi/database v1.17.38/go.mod h1:q6BJNN+47VtkmkGrswQmC0ikERYAdlmZCYhGTXkF4mM=
|
||||
github.com/luxfi/database v1.17.39/go.mod h1:iHE5evTMxltmYGe3QkewrZv1xgGrDBbqcv0y4NkDJcI=
|
||||
github.com/luxfi/database v1.17.40/go.mod h1:du1q0PemBc0gZcdtHhsARs6mIsZM3a5R/C040DVYLCM=
|
||||
github.com/luxfi/database v1.17.42/go.mod h1:0nArLBm0r42J103oHR2xkAe8+mftuz5jtFgNylU1hgg=
|
||||
github.com/luxfi/database v1.17.44 h1:hfiTls7sqbweW+o4iaZqB8P997paC+vpgWmhN6v5MJ0=
|
||||
github.com/luxfi/database v1.17.44/go.mod h1:6Ey5y3I0WNLHbxIlIdFqUuKfBg+b0fAgTA8FgRgQ8zg=
|
||||
github.com/luxfi/evm v0.8.30/go.mod h1:S0fChMeuWV4XqY4OB6RozqvyHcm+imJCKyqsMY713hY=
|
||||
github.com/luxfi/fhe v1.7.6-0.20260106060801-28e308e4c2f8/go.mod h1:SVO5KV3GKMW5U0XeQSV4x7fryNWHsCjyhhhAoIPCpG8=
|
||||
github.com/luxfi/fhe v1.7.7 h1:RP26i3CxvNy2y/3LKiJPgd9uR5MrlG/MvQnv5rkQFhk=
|
||||
github.com/luxfi/fhe v1.7.7/go.mod h1:FHfGNgKL5ZLcnKVKFVNLDJOBbQyQm5DGpVrMnY8ASJo=
|
||||
github.com/luxfi/filesystem v0.0.1/go.mod h1:OQVSU6XNwqrr1AI+MqkID2taHUclx7NYmmr3svgttec=
|
||||
github.com/luxfi/formatting v1.0.0/go.mod h1:lswh6dPQ4E9Q+nZLwispV+Jdthr5R1PkYTBA/LhuSgE=
|
||||
github.com/luxfi/formatting v1.0.1/go.mod h1:mYzNf5DJOiqSSKUPzNj5dKy4tstFbN3pZlkI5716eKc=
|
||||
github.com/luxfi/genesis v1.5.21/go.mod h1:XI1T2oMh/VS/f+LWMWPDQIEhEneCNVHodhn2Qr3rFMU=
|
||||
github.com/luxfi/genesis v1.5.22/go.mod h1:ernOqYxKPEZnwu/QvgJ9y4Lb+IUpfoOtZ3/DubzExv0=
|
||||
github.com/luxfi/geth v1.16.73/go.mod h1:CPzps7Zp3I7Og3KT3m+Qs41WW8z+YPGx1TOJQnHdBHY=
|
||||
github.com/luxfi/geth v1.16.79 h1:MtP8ZUuSVZDjmZDa1kTJCl0PpG8+wGbQft652GO6a3A=
|
||||
github.com/luxfi/geth v1.16.79/go.mod h1:6xNi4sHoh0v1kBf0TOjmFhBg5+4umbSqrwiFZsDanZ0=
|
||||
github.com/luxfi/go-bip32 v1.0.2/go.mod h1:bc7/LXDKAJQZ/F0Xjf5yXaTZxY9/ssLb4FC+Hxn/cDk=
|
||||
github.com/luxfi/go-bip39 v1.1.2/go.mod h1:96de9VkR2kY/ASAnhMtvt3TSh+PZkAFAngNj0GjRGDo=
|
||||
github.com/luxfi/gpu v0.30.0/go.mod h1:7pFsHqra1Vrmy2aGXVEPKeKsPR+Bn+QmBXuByK3fdPA=
|
||||
@@ -541,17 +521,11 @@ github.com/luxfi/log v1.2.1/go.mod h1:0vJzb4Hl9fvgwWDMKcbCD/SYH3bO0iSmgZMcYdfdl1
|
||||
github.com/luxfi/log v1.4.0/go.mod h1:64IE3xRMJcpkQwnPUfJw3pDj7wU0kRS7BZ9wM7R72jk=
|
||||
github.com/luxfi/lpm v1.0.5/go.mod h1:dS/NS6muB9zlHWbO/VeCMYCe53YwIjXDHg/jif7TejI=
|
||||
github.com/luxfi/math v1.2.2/go.mod h1:C8STnF2H+D6rqBPt248CiWY2TGuJgdtv/+4UqrT15iM=
|
||||
github.com/luxfi/math v1.2.4 h1:iVz7s0gToCNUU/2cLT8gUa8MLzc0YRp4jBmeXBeKdXk=
|
||||
github.com/luxfi/math v1.2.4/go.mod h1:i+Am9YvFsqDE75ZW8MPE62XCXGukXNiN/7mD9SKxxZY=
|
||||
github.com/luxfi/math/safe v0.0.1/go.mod h1:EejrmOJHh03YAD8+Zww8cPcMR1K3Q2I7w1dX4sMloeo=
|
||||
github.com/luxfi/mdns v0.1.0 h1:VB3mQcETc9j5SY1S6lAgFtuGr/rjWuDgPYnxS+OKWMQ=
|
||||
github.com/luxfi/mdns v0.1.0/go.mod h1:/3dheKVjUk2yiS/ocH1IDzeLXOIe+kpVsErIGDOZdiQ=
|
||||
github.com/luxfi/metric v1.4.9/go.mod h1:JlAAc4Jm5apoU2DHEgt57UHD7+8AjMdpP2rQJ/zaACY=
|
||||
github.com/luxfi/metric v1.4.10/go.mod h1:3OIQ+e6mciesm3cik3Q4CSOAvTlBy4JA0ZoKzCB9APo=
|
||||
github.com/luxfi/metric v1.4.11/go.mod h1:EAFmkzd5EX654G48HXKIsyJufOUa4sxmOJKvwSRbjng=
|
||||
github.com/luxfi/metric v1.4.12/go.mod h1:EAFmkzd5EX654G48HXKIsyJufOUa4sxmOJKvwSRbjng=
|
||||
github.com/luxfi/metric v1.5.1 h1:6tVarXMnNR3Xzud8FYUHjtXabTll3HI/OEqG0tgLAcI=
|
||||
github.com/luxfi/metric v1.5.1/go.mod h1:PkD4D4JoGuyKtfUkqPNYkrg9xKrJeNVZFdW/5XvAe/A=
|
||||
github.com/luxfi/mock v0.1.0/go.mod h1:izF+9K0gGzFC9zERn6Po37v46eLdPB+EIsDjL3GLk+U=
|
||||
github.com/luxfi/net v0.0.1/go.mod h1:JTPsJHaUcpF0HruczW14FlUTjPk78xF73XGSMQa86NA=
|
||||
github.com/luxfi/netrunner v1.14.35/go.mod h1:vfeCr7L49R9yoSjZCpZe2+xtoNdPt4fstEtbKt7Jtls=
|
||||
@@ -585,8 +559,6 @@ github.com/luxfi/staking v1.0.0/go.mod h1:E+fm3upfQTOu0fLCr3Uo4xYgAm7r/vEzgcUpNA
|
||||
github.com/luxfi/staking v1.1.0/go.mod h1:xwYacmreoKoy31ELT6QPno6b5M8q7bg4zJrmmt524X4=
|
||||
github.com/luxfi/sys v0.0.0-20260110090042-50187ec5ffd8/go.mod h1:Y0UwjnEJYSbGM7IvJbKYLf8BWNVLfT8Oz00bEiDITHw=
|
||||
github.com/luxfi/threshold v1.5.1/go.mod h1:OsWmH2foqB2K4vVpHTjSHrVM4oveSzqOZb/k+fqNsYY=
|
||||
github.com/luxfi/threshold v1.6.0 h1:pq/n1iYowws+CXe/+slJodjPlJ152hFF94luHp2E82c=
|
||||
github.com/luxfi/threshold v1.6.0/go.mod h1:XWSfWM3n/tVggluh/LH7is4vYL85zmyMHCqfz2qrYVU=
|
||||
github.com/luxfi/timer v1.0.1/go.mod h1:PQ15H3AEUfvWVf0kv5WhIGPWmhr9BxBv/VKLyyekpk4=
|
||||
github.com/luxfi/tls v1.0.0/go.mod h1:QZXWuYFZPfGA9AyRIBXgIuXPrmvWWHtQkJtplZnTlWc=
|
||||
github.com/luxfi/tls v1.0.2/go.mod h1:t6Fr+KYKDZEz1KxciGHzRrj/KsQIx8V3iG/8YiSqpvU=
|
||||
@@ -596,8 +568,6 @@ github.com/luxfi/units v1.0.0/go.mod h1:tma28v4ed1tupdS0kpSeyO+u1wWK/g1NqODPbN1Y
|
||||
github.com/luxfi/upgrade v1.0.0/go.mod h1:DZF7dO4erhUEKf907B2e65k4/vGkCPkUngpvIEUS3eI=
|
||||
github.com/luxfi/utils v1.1.0/go.mod h1:ABqhBdGNig0CaDcnNYldv1byS0BTNi5IKPbJSPF1p98=
|
||||
github.com/luxfi/utils v1.1.1/go.mod h1:DL7634uXEcCu2tCBll0bmX0SVnMJeABbmhm5NkLMu78=
|
||||
github.com/luxfi/utils v1.1.4 h1:8OY0jXCkpp6OotN1Y++6DATJkvtEwzq2k0p56imJlAk=
|
||||
github.com/luxfi/utils v1.1.4/go.mod h1:c3yz1RjzrB+cs5GZm+q1T3/2cCKElO9vxm9yRRtgSEM=
|
||||
github.com/luxfi/utxo v0.0.1/go.mod h1:cwkUv/J6zNohRI7+xrj03wi39bm6CYkek+6XRhQrPTU=
|
||||
github.com/luxfi/utxo v0.2.3/go.mod h1:I23ZJND7kU6NUklD2nY24mU93jQXBPGu1c9Y1hjX9Vk=
|
||||
github.com/luxfi/validators v1.0.0/go.mod h1:QGppjtI/gqprbplWc10J+4OIK8UYWpv+53mfH2aKhy4=
|
||||
@@ -615,13 +585,9 @@ github.com/luxfi/warp v1.18.2/go.mod h1:qu3TZv98repNhIDf04I6pzXePSgHjzP+JoSfWmF4
|
||||
github.com/luxfi/warp v1.18.4/go.mod h1:5kXaZGYBBzOFyzPoDukVynvTTPskElrA8EQ5TVgovqc=
|
||||
github.com/luxfi/warp v1.18.5/go.mod h1:SFyC529HDvbP/TWRAdYQSyJUliMa5JKFRtBrTLEElp4=
|
||||
github.com/luxfi/zap v0.0.0-20260126200933-22a2a4c72dfb/go.mod h1:uvmQO9kVvOfBcqPhY52wx5Z1O6L/4Mv2tBrJDc3gVgM=
|
||||
github.com/luxfi/zap v0.2.0 h1:RzvOkp3EoN5UCkpnqfObHLM1sEHy7YcxXKuermhE/VA=
|
||||
github.com/luxfi/zap v0.2.0/go.mod h1:2hydPSa/XMCMtfW6/DC9M5Bt03N5h75QwCV5Vypsqr4=
|
||||
github.com/luxfi/zapdb v1.0.0 h1:u8TF4g/bWew5mQwiR/Mcu+QIFYTT6BP5Ty8oBaDgalA=
|
||||
github.com/luxfi/zapdb v1.0.0/go.mod h1:tT2WF2iSabQHrAYe9l7LHscaIBfN2YtCbdgOrCyCI2A=
|
||||
github.com/luxfi/zapdb/v4 v4.9.1/go.mod h1:gYJjLcFCxmUATZ6Zg7iZHwAbgBMxGVP1g8UOWomK70Y=
|
||||
github.com/luxfi/zapdb/v4 v4.9.3 h1:KV1DrbZqtZsZvrWyPw5D8WHR0DxzqW2jHjqx6obxgoM=
|
||||
github.com/luxfi/zapdb/v4 v4.9.3/go.mod h1:BrpLaDeYy+smON4ASDPCFKWrQ58CXhy3WNEPGna7vuU=
|
||||
github.com/luxfi/zmq/v4 v4.2.2/go.mod h1:omy8ymZAhx60lx/nPsWT6uOV11uNFVnjtls+Hi5KqaU=
|
||||
github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
|
||||
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
|
||||
@@ -796,8 +762,6 @@ github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpE
|
||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||
github.com/stretchr/testify v0.0.0-20161117074351-18a02ba4a312/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.1.4/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
@@ -839,7 +803,6 @@ github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJu
|
||||
github.com/xrash/smetrics v0.0.0-20250705151800-55b8f293f342/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM=
|
||||
github.com/yosssi/ace v0.0.5/go.mod h1:ALfIzm2vT7t5ZE7uoIZqF3TQ7SAOyupFZnkrF5id+K0=
|
||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||
@@ -880,6 +843,7 @@ go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
|
||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8=
|
||||
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
|
||||
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||
go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
|
||||
go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
||||
@@ -944,8 +908,6 @@ golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCc
|
||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
|
||||
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
@@ -967,8 +929,6 @@ golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73r
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
@@ -1026,9 +986,6 @@ golang.org/x/oauth2 v0.34.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwE
|
||||
golang.org/x/oauth2 v0.35.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
|
||||
golang.org/x/perf v0.0.0-20230113213139-801c7ef9e5c5/go.mod h1:UBKtEnL8aqnd+0JHqZ+2qoMDwtuy6cYhhKNoHLBiTQc=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
@@ -1057,9 +1014,6 @@ golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@@ -1080,13 +1034,10 @@ golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211117180635-dee7805ff2e1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
@@ -1124,7 +1075,6 @@ golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
|
||||
golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254=
|
||||
golang.org/x/term v0.38.0/go.mod h1:bSEAKrOT1W+VSu9TSCMtoGEOUcKxOKgl3LE5QEF/xVg=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
@@ -1187,15 +1137,7 @@ golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roY
|
||||
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
|
||||
golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
||||
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
@@ -1335,7 +1277,6 @@ gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22/go.mod h1:yeKp02qBN3iKW1OzL3M
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/vmihailenco/msgpack.v2 v2.9.2/go.mod h1:/3Dn1Npt9+MYyLpYYXjInO/5jvMLamn+AEGwNEOatn8=
|
||||
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
|
||||
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
|
||||
+91
-10
@@ -18,6 +18,9 @@
|
||||
// (challenge-response binding — a stolen nonce cannot be replayed
|
||||
// under a different jobID, and a forged nonce cannot trick the gate
|
||||
// into accepting a worker-chosen challenge).
|
||||
// 6. Every CPU TEE / GPU evidence blob in the envelope cryptographically
|
||||
// chains to its pinned vendor root via cc/attest.Dispatch (AMD KDS +
|
||||
// VCEK for SEV-SNP, Intel quote chain for TDX, NRAS JWT for NVIDIA).
|
||||
//
|
||||
// On success the gate returns the session key sealed (HPKE-style: ECDH
|
||||
// over X25519, ChaCha20-Poly1305 AEAD) to the worker's GPU TEE public
|
||||
@@ -35,6 +38,7 @@
|
||||
package kms
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/hmac"
|
||||
"crypto/rand"
|
||||
"crypto/sha256"
|
||||
@@ -46,22 +50,44 @@ import (
|
||||
|
||||
"golang.org/x/crypto/chacha20poly1305"
|
||||
"golang.org/x/crypto/curve25519"
|
||||
|
||||
"github.com/luxfi/mpc/cc/attest"
|
||||
)
|
||||
|
||||
// CompositeAttestation is the contract surface the release gate consumes
|
||||
// from pkg/attestation (LP-127, v0.62). We declare the interface here so
|
||||
// pkg/kms does not depend on pkg/attestation; the v0.62 concrete type
|
||||
// satisfies via method-set match.
|
||||
// pkg/kms does not depend on pkg/attestation directly; the v0.62
|
||||
// concrete type satisfies via method-set match.
|
||||
//
|
||||
// The attestation MUST bind a freshly-generated nonce supplied by the
|
||||
// gate (challenge-response) and the worker's TEE public key. Either
|
||||
// failure mode collapses release to "refused".
|
||||
//
|
||||
// VerifyEvidence is the wire-in for the canonical cc/attest chain
|
||||
// verifier. The gate calls VerifyEvidence after the cheap nonce check
|
||||
// and BEFORE policy / seal so that a forged report whose Verify(nonce)
|
||||
// returns true but whose chain does not validate cannot harvest a
|
||||
// session key.
|
||||
type CompositeAttestation interface {
|
||||
// Verify checks NVTrust + TPM + nonce. Returns false on any
|
||||
// cryptographic mismatch. Errors only on unrecoverable failure
|
||||
// (parsing, root-of-trust load) — a forged attestation is (false, nil).
|
||||
Verify(expectedNonce [32]byte) (bool, error)
|
||||
|
||||
// VerifyEvidence cryptographically validates every CPU TEE / GPU
|
||||
// evidence blob in the envelope using cc/attest:
|
||||
//
|
||||
// - SEV-SNP → AMD KDS lookup, ARK→ASK→VCEK chain, report-signature
|
||||
// - TDX → Intel quote chain
|
||||
// - NRAS → NVIDIA NRAS JWT verify against pinned issuer key
|
||||
//
|
||||
// Returns the per-evidence verified reports on success; any
|
||||
// chain-verify failure → (nil, err) and the gate MUST refuse
|
||||
// release. Wire-in for #222 go-sev-guest: without this step a
|
||||
// worker can craft an envelope whose Verify(nonce) returns true
|
||||
// while the actual blobs are unsigned or signed by a non-AMD key.
|
||||
VerifyEvidence(ctx context.Context, opts ...attest.Option) ([]*attest.VerifiedReport, error)
|
||||
|
||||
// RIMDigest returns the Reference Integrity Manifest digest the
|
||||
// worker measured. Compared to ReleasePolicy.RequiredRIM.
|
||||
RIMDigest() [32]byte
|
||||
@@ -157,11 +183,24 @@ func (s SealedSessionKey) AAD(teePub [32]byte) []byte {
|
||||
|
||||
// ReleaseRequest carries everything the gate needs in one shot. JobID
|
||||
// is opaque to the gate (used only for AAD binding).
|
||||
//
|
||||
// Ctx, when non-nil, is threaded into the cc/attest chain verifier so
|
||||
// AMD KDS / NRAS network calls cannot stall the gate. When nil the
|
||||
// gate uses context.Background().
|
||||
//
|
||||
// AttestOptions are forwarded to VerifyEvidence; production callers
|
||||
// MUST include attest.WithExpectedReportData(rec.Nonce[:]) (or an
|
||||
// equivalent measurement pin) so the chain verifier refuses any quote
|
||||
// whose REPORT_DATA does not equal the gate-issued nonce. The gate
|
||||
// does not auto-bind here because the REPORT_DATA framing is
|
||||
// kind-specific (64-byte field on SEV-SNP/TDX, JWT claim on NRAS).
|
||||
type ReleaseRequest struct {
|
||||
JobID [32]byte
|
||||
Epoch uint64
|
||||
Nonce [32]byte // gate-issued, attested-over by the worker
|
||||
Attestation CompositeAttestation
|
||||
JobID [32]byte
|
||||
Epoch uint64
|
||||
Nonce [32]byte // gate-issued, attested-over by the worker
|
||||
Attestation CompositeAttestation
|
||||
Ctx context.Context
|
||||
AttestOptions []attest.Option
|
||||
}
|
||||
|
||||
// ReleaseGate verifies attestation + releases a session key sealed to
|
||||
@@ -180,6 +219,7 @@ type ReleaseGate interface {
|
||||
// - hardware not in allowlist
|
||||
// - epoch mismatch (replay)
|
||||
// - jobID re-use within the current epoch (replay)
|
||||
// - cc/attest chain verify failure on any evidence blob
|
||||
Release(req ReleaseRequest) (SealedSessionKey, error)
|
||||
|
||||
// Rotate advances the epoch — invalidates all in-flight nonces.
|
||||
@@ -191,6 +231,16 @@ type ReleaseGate interface {
|
||||
// Callers MUST treat this as a hard refusal — never as "approved by default".
|
||||
var ErrPolicyRefused = errors.New("kms/release: refused")
|
||||
|
||||
// ErrAttestationChain is returned when the cc/attest chain verifier
|
||||
// (AMD KDS + VCEK validation, NVIDIA NRAS JWT, Intel TDX quote)
|
||||
// refuses any evidence blob in the envelope. Wrapped by
|
||||
// ErrPolicyRefused via errors.Join so callers can switch on either
|
||||
// sentinel; the gate releases NO key when this fires. Red Final N1
|
||||
// wire-in: a forged envelope whose Verify(nonce) returns true but
|
||||
// whose evidence does not chain to the pinned vendor root must
|
||||
// produce ErrAttestationChain, not silent acceptance.
|
||||
var ErrAttestationChain = errors.New("kms/release: attestation chain verify failed")
|
||||
|
||||
// DefaultReplayWindow is how long a consumed jobID stays in the replay
|
||||
// set after Release(). 1 hour absorbs clock skew + worker retries
|
||||
// without growing the consumed-set unbounded.
|
||||
@@ -318,10 +368,20 @@ func (g *LocalReleaseGate) Issue(jobID [32]byte) ([32]byte, uint64, error) {
|
||||
// 1. epoch match (cheap)
|
||||
// 2. lookup pending record (storage hit)
|
||||
// 3. constant-time nonce equality (no timing leak on jobID enumeration)
|
||||
// 4. attestation verify (expensive crypto)
|
||||
// 5. policy permits (membership check)
|
||||
// 6. seal session key (key derivation + AEAD)
|
||||
// 7. consume (atomic — only after all checks pass)
|
||||
// 4. attestation nonce verify (cheap, in-memory)
|
||||
// 5. cc/attest chain verify — VCEK / KDS / SEV-SNP / TDX / NRAS
|
||||
// (network + signature, the actual root-of-trust step). Without
|
||||
// this step the audit-bypass exists: a worker crafts an envelope
|
||||
// whose Verify(nonce) returns true but whose evidence blobs do not
|
||||
// chain to the pinned vendor root.
|
||||
// 6. policy permits (RIM + hardware membership)
|
||||
// 7. seal session key (ECDH + AEAD)
|
||||
// 8. consume (atomic — only after all checks pass)
|
||||
//
|
||||
// Any failure at step 4 → ErrPolicyRefused. Any failure at step 5 →
|
||||
// ErrPolicyRefused joined with ErrAttestationChain. No silent
|
||||
// acceptance; a cryptographically valid nonce binding is NOT
|
||||
// sufficient on its own.
|
||||
func (g *LocalReleaseGate) Release(req ReleaseRequest) (SealedSessionKey, error) {
|
||||
g.mu.Lock()
|
||||
defer g.mu.Unlock()
|
||||
@@ -368,6 +428,27 @@ func (g *LocalReleaseGate) Release(req ReleaseRequest) (SealedSessionKey, error)
|
||||
if !ok {
|
||||
return SealedSessionKey{}, fmt.Errorf("%w: attestation invalid", ErrPolicyRefused)
|
||||
}
|
||||
|
||||
// Step 5 — the canonical chain verifier. Dispatches every
|
||||
// supported CPU TEE / GPU evidence blob to cc/attest:
|
||||
//
|
||||
// - SEV-SNP → AMD KDS lookup, ARK→ASK→VCEK chain, signature
|
||||
// - TDX → Intel quote chain
|
||||
// - NRAS → NVIDIA NRAS JWT verify against pinned issuer key
|
||||
//
|
||||
// Red Final N1: without this step the #222 go-sev-guest wins are
|
||||
// dead code — Verify(nonce) is trivially satisfied by a worker
|
||||
// that fabricates the envelope. VerifyEvidence forces the actual
|
||||
// cryptographic chain check; any failure → ErrAttestationChain
|
||||
// wrapped under ErrPolicyRefused.
|
||||
ctx := req.Ctx
|
||||
if ctx == nil {
|
||||
ctx = context.Background()
|
||||
}
|
||||
if _, err := req.Attestation.VerifyEvidence(ctx, req.AttestOptions...); err != nil {
|
||||
return SealedSessionKey{}, errors.Join(ErrPolicyRefused, fmt.Errorf("%w: %v", ErrAttestationChain, err))
|
||||
}
|
||||
|
||||
if !g.policy.Permits(req.Attestation) {
|
||||
return SealedSessionKey{}, fmt.Errorf("%w: policy denied (RIM or hardware)", ErrPolicyRefused)
|
||||
}
|
||||
|
||||
+87
-23
@@ -1,12 +1,15 @@
|
||||
package kms
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"errors"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"golang.org/x/crypto/curve25519"
|
||||
|
||||
"github.com/luxfi/mpc/cc/attest"
|
||||
)
|
||||
|
||||
// x25519Basepoint multiplies priv by the curve25519 basepoint.
|
||||
@@ -17,12 +20,17 @@ func x25519Basepoint(priv []byte) ([]byte, error) {
|
||||
// fakeAttestation is a deterministic stub. Verify() succeeds iff
|
||||
// expectedNonce equals the nonce captured at construction. RIM and
|
||||
// hardware are caller-supplied so the test exercises Permits().
|
||||
//
|
||||
// VerifyEvidence simulates the cc/attest chain dispatch. Default is
|
||||
// success. Set failChain=true to force a chain-verify failure — used
|
||||
// by TestRelease_RefusesOnChainFailure.
|
||||
type fakeAttestation struct {
|
||||
expectNonce [32]byte
|
||||
rim [32]byte
|
||||
hw [32]byte
|
||||
teePub [32]byte
|
||||
failVerify bool
|
||||
failChain bool
|
||||
}
|
||||
|
||||
func (f *fakeAttestation) Verify(expectedNonce [32]byte) (bool, error) {
|
||||
@@ -31,6 +39,13 @@ func (f *fakeAttestation) Verify(expectedNonce [32]byte) (bool, error) {
|
||||
}
|
||||
return f.expectNonce == expectedNonce, nil
|
||||
}
|
||||
|
||||
func (f *fakeAttestation) VerifyEvidence(ctx context.Context, opts ...attest.Option) ([]*attest.VerifiedReport, error) {
|
||||
if f.failChain {
|
||||
return nil, attest.ErrChainInvalid
|
||||
}
|
||||
return []*attest.VerifiedReport{{Kind: attest.KindSEVSNP, Vendor: "amd.sev.snp"}}, nil
|
||||
}
|
||||
func (f *fakeAttestation) RIMDigest() [32]byte { return f.rim }
|
||||
func (f *fakeAttestation) HardwareFingerprint() [32]byte { return f.hw }
|
||||
func (f *fakeAttestation) TEEPublicKey() [32]byte { return f.teePub }
|
||||
@@ -59,7 +74,6 @@ func newTestGate(t *testing.T) (*LocalReleaseGate, *MemoryNonceStore, [32]byte,
|
||||
t.Fatalf("NewLocalReleaseGate: %v", err)
|
||||
}
|
||||
var teePub [32]byte
|
||||
// Use a real curve25519 pubkey so ECDH succeeds in seal.
|
||||
priv := mustRand(t, 32)
|
||||
priv[0] &= 248
|
||||
priv[31] &= 127
|
||||
@@ -72,9 +86,6 @@ func newTestGate(t *testing.T) (*LocalReleaseGate, *MemoryNonceStore, [32]byte,
|
||||
return gate, store, rim, hw, teePub
|
||||
}
|
||||
|
||||
// curve25519X25519Basepoint wraps the basepoint multiplication so the
|
||||
// test file does not import curve25519 directly (avoid duplicate import
|
||||
// surfaces; release.go already pulls it).
|
||||
func curve25519X25519Basepoint(priv []byte) ([]byte, error) {
|
||||
return x25519Basepoint(priv)
|
||||
}
|
||||
@@ -119,8 +130,6 @@ func TestRelease_WrongNonce(t *testing.T) {
|
||||
t.Fatalf("Issue: %v", err)
|
||||
}
|
||||
|
||||
// Worker presents a forged nonce (e.g. the worker chose its own
|
||||
// random challenge instead of using the gate-issued one).
|
||||
var forged [32]byte
|
||||
copy(forged[:], mustRand(t, 32))
|
||||
if forged == nonce {
|
||||
@@ -141,8 +150,7 @@ func TestRelease_WrongNonce(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// Test 3: Issue → KMS restart (re-construct gate from store) → Release
|
||||
// still works (no replay-window reset).
|
||||
// Test 3: Issue → KMS restart → Release still works.
|
||||
func TestRelease_SurvivesRestart(t *testing.T) {
|
||||
policy := NewReleasePolicy(
|
||||
[][32]byte{[32]byte(mustRand(t, 32))},
|
||||
@@ -151,12 +159,10 @@ func TestRelease_SurvivesRestart(t *testing.T) {
|
||||
for k := range policy.RequiredRIM {
|
||||
_ = k
|
||||
}
|
||||
// Reuse the same store across two gate constructions.
|
||||
var rootKey [32]byte
|
||||
copy(rootKey[:], mustRand(t, 32))
|
||||
store := NewMemoryNonceStore()
|
||||
|
||||
// First gate: Issue.
|
||||
g1, err := NewLocalReleaseGate(policy, store, rootKey)
|
||||
if err != nil {
|
||||
t.Fatalf("NewLocalReleaseGate: %v", err)
|
||||
@@ -168,14 +174,11 @@ func TestRelease_SurvivesRestart(t *testing.T) {
|
||||
t.Fatalf("Issue: %v", err)
|
||||
}
|
||||
|
||||
// "Restart": construct a second gate over the same store. The
|
||||
// pending nonce + epoch must round-trip.
|
||||
g2, err := NewLocalReleaseGate(policy, store, rootKey)
|
||||
if err != nil {
|
||||
t.Fatalf("NewLocalReleaseGate (restart): %v", err)
|
||||
}
|
||||
|
||||
// Pull the policy's RIM/HW so the attestation matches.
|
||||
var rim, hw [32]byte
|
||||
for k := range policy.RequiredRIM {
|
||||
rim = k
|
||||
@@ -222,7 +225,6 @@ func TestRelease_AlreadyConsumed(t *testing.T) {
|
||||
t.Fatalf("Release #1: %v", err)
|
||||
}
|
||||
|
||||
// Replay: same jobID + nonce. Must refuse.
|
||||
_, err = gate.Release(ReleaseRequest{
|
||||
JobID: jobID, Epoch: epoch, Nonce: nonce, Attestation: att,
|
||||
})
|
||||
@@ -249,7 +251,6 @@ func TestRelease_Expired(t *testing.T) {
|
||||
t.Fatalf("Issue: %v", err)
|
||||
}
|
||||
|
||||
// Wait past the TTL.
|
||||
time.Sleep(50 * time.Millisecond)
|
||||
|
||||
att := &fakeAttestation{expectNonce: nonce, rim: rim, hw: hw, teePub: teePub}
|
||||
@@ -266,12 +267,9 @@ func TestRelease_Expired(t *testing.T) {
|
||||
t.Fatalf("Release: expected ErrExpired wrapped, got %v", err)
|
||||
}
|
||||
|
||||
// GC should reclaim the pending entry.
|
||||
if err := gate.GC(); err != nil {
|
||||
t.Fatalf("GC: %v", err)
|
||||
}
|
||||
// After GC the jobID is "unknown" rather than "expired"; either is
|
||||
// a valid hard refusal.
|
||||
_, err = gate.Release(ReleaseRequest{
|
||||
JobID: jobID, Epoch: epoch, Nonce: nonce, Attestation: att,
|
||||
})
|
||||
@@ -280,9 +278,6 @@ func TestRelease_Expired(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// Bonus: nonce binding — nonce derived for jobID A must NOT match
|
||||
// jobID B even with identical fresh entropy. The HMAC binding is what
|
||||
// the audit calls out; this asserts it directly.
|
||||
func TestNonce_BoundToJobID(t *testing.T) {
|
||||
gate, _, _, _, _ := newTestGate(t)
|
||||
|
||||
@@ -303,8 +298,6 @@ func TestNonce_BoundToJobID(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// Bonus: AAD includes the issued nonce. Re-deriving AAD with a
|
||||
// different IssuedNonce must produce different bytes.
|
||||
func TestAAD_BindsIssuedNonce(t *testing.T) {
|
||||
var jobID, n1, n2, teePub [32]byte
|
||||
copy(jobID[:], mustRand(t, 32))
|
||||
@@ -320,3 +313,74 @@ func TestAAD_BindsIssuedNonce(t *testing.T) {
|
||||
t.Fatalf("AAD did not bind IssuedNonce (collision)")
|
||||
}
|
||||
}
|
||||
|
||||
// Test (Red Final N1): an attestation that passes the cheap nonce
|
||||
// Verify() but FAILS the cc/attest chain verifier (AMD KDS / VCEK,
|
||||
// NRAS, TDX) MUST be refused. Without the chain step a worker can
|
||||
// craft a forged envelope whose Verify(nonce) returns true but whose
|
||||
// evidence blobs do not chain to the pinned vendor root, harvesting a
|
||||
// session key.
|
||||
func TestRelease_RefusesOnChainFailure(t *testing.T) {
|
||||
gate, _, rim, hw, teePub := newTestGate(t)
|
||||
var jobID [32]byte
|
||||
copy(jobID[:], mustRand(t, 32))
|
||||
|
||||
nonce, epoch, err := gate.Issue(jobID)
|
||||
if err != nil {
|
||||
t.Fatalf("Issue: %v", err)
|
||||
}
|
||||
|
||||
// nonce binding passes (failVerify=false) but the chain check
|
||||
// fails — the forged-evidence path the audit flagged.
|
||||
att := &fakeAttestation{
|
||||
expectNonce: nonce,
|
||||
rim: rim,
|
||||
hw: hw,
|
||||
teePub: teePub,
|
||||
failVerify: false,
|
||||
failChain: true,
|
||||
}
|
||||
_, err = gate.Release(ReleaseRequest{
|
||||
JobID: jobID,
|
||||
Epoch: epoch,
|
||||
Nonce: nonce,
|
||||
Attestation: att,
|
||||
})
|
||||
if err == nil {
|
||||
t.Fatalf("Release: expected chain-verify refusal, got nil")
|
||||
}
|
||||
if !errors.Is(err, ErrPolicyRefused) {
|
||||
t.Fatalf("Release: expected ErrPolicyRefused wrapped, got %v", err)
|
||||
}
|
||||
if !errors.Is(err, ErrAttestationChain) {
|
||||
t.Fatalf("Release: expected ErrAttestationChain wrapped, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Test (Red Final N1, paired): the SAME attestation with chain check
|
||||
// passing must succeed.
|
||||
func TestRelease_AcceptsOnChainPass(t *testing.T) {
|
||||
gate, _, rim, hw, teePub := newTestGate(t)
|
||||
var jobID [32]byte
|
||||
copy(jobID[:], mustRand(t, 32))
|
||||
|
||||
nonce, epoch, err := gate.Issue(jobID)
|
||||
if err != nil {
|
||||
t.Fatalf("Issue: %v", err)
|
||||
}
|
||||
att := &fakeAttestation{
|
||||
expectNonce: nonce,
|
||||
rim: rim,
|
||||
hw: hw,
|
||||
teePub: teePub,
|
||||
failChain: false,
|
||||
}
|
||||
if _, err := gate.Release(ReleaseRequest{
|
||||
JobID: jobID,
|
||||
Epoch: epoch,
|
||||
Nonce: nonce,
|
||||
Attestation: att,
|
||||
}); err != nil {
|
||||
t.Fatalf("Release: expected success, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user