Skip to content

Commit 4ff4d89

Browse files
avalonchejtragliametachris
authored
Add Deneb Types and Flow (#553)
* add deneb path * remove redirectives * Check deneb blobs * Make attestantio import names consistent (#560) * update payload fields * Compute block root to calculate block hash * remove computing deneb hash * clean up and add tests * updated builder specs * update mev-boost to updated builder-specs * fix tests * Apply suggestions from code review Co-authored-by: Justin Traglia <[email protected]> * rebase * update go-boost-utils * address pr comments --------- Co-authored-by: Justin Traglia <[email protected]> Co-authored-by: Chris Hager <[email protected]>
1 parent bcfd1db commit 4ff4d89

File tree

12 files changed

+790
-205
lines changed

12 files changed

+790
-205
lines changed

.golangci.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ linters:
1919
- wrapcheck
2020
- wsl
2121
- musttag
22+
- depguard
2223

2324
#
2425
# Maybe fix later:

cmd/test-cli/main.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ import (
88
"os"
99
"strconv"
1010

11-
"github.com/attestantio/go-builder-client/api"
12-
"github.com/attestantio/go-builder-client/spec"
13-
"github.com/attestantio/go-eth2-client/api/v1/capella"
11+
builderApi "github.com/attestantio/go-builder-client/api"
12+
builderSpec "github.com/attestantio/go-builder-client/spec"
13+
eth2ApiV1Capella "github.com/attestantio/go-eth2-client/api/v1/capella"
1414
"github.com/attestantio/go-eth2-client/spec/altair"
1515
"github.com/attestantio/go-eth2-client/spec/phase0"
1616
"github.com/ethereum/go-ethereum/common"
@@ -44,7 +44,7 @@ func doRegisterValidator(v validatorPrivateData, boostEndpoint string, builderSi
4444
log.WithError(err).Info("Registered validator")
4545
}
4646

47-
func doGetHeader(v validatorPrivateData, boostEndpoint string, beaconNode Beacon, engineEndpoint string, builderSigningDomain phase0.Domain) spec.VersionedSignedBuilderBid {
47+
func doGetHeader(v validatorPrivateData, boostEndpoint string, beaconNode Beacon, engineEndpoint string, builderSigningDomain phase0.Domain) builderSpec.VersionedSignedBuilderBid {
4848
// Mergemock needs to call forkchoice update before getHeader, for non-mergemock beacon node this is a no-op
4949
err := beaconNode.onGetHeader()
5050
if err != nil {
@@ -71,7 +71,7 @@ func doGetHeader(v validatorPrivateData, boostEndpoint string, beaconNode Beacon
7171

7272
uri := fmt.Sprintf("%s/eth/v1/builder/header/%d/%s/%s", boostEndpoint, currentBlock.Slot+1, currentBlockHash, v.Pk.String())
7373

74-
var getHeaderResp spec.VersionedSignedBuilderBid
74+
var getHeaderResp builderSpec.VersionedSignedBuilderBid
7575
if _, err := server.SendHTTPRequest(context.TODO(), *http.DefaultClient, http.MethodGet, uri, "test-cli", nil, nil, &getHeaderResp); err != nil {
7676
log.WithError(err).WithField("currentBlockHash", currentBlockHash).Fatal("Could not get header")
7777
}
@@ -95,12 +95,12 @@ func doGetHeader(v validatorPrivateData, boostEndpoint string, beaconNode Beacon
9595
func doGetPayload(v validatorPrivateData, boostEndpoint string, beaconNode Beacon, engineEndpoint string, builderSigningDomain, proposerSigningDomain phase0.Domain) {
9696
header := doGetHeader(v, boostEndpoint, beaconNode, engineEndpoint, builderSigningDomain)
9797

98-
blindedBeaconBlock := capella.BlindedBeaconBlock{
98+
blindedBeaconBlock := eth2ApiV1Capella.BlindedBeaconBlock{
9999
Slot: 0,
100100
ProposerIndex: 0,
101101
ParentRoot: phase0.Root{},
102102
StateRoot: phase0.Root{},
103-
Body: &capella.BlindedBeaconBlockBody{
103+
Body: &eth2ApiV1Capella.BlindedBeaconBlockBody{
104104
RANDAOReveal: phase0.BLSSignature{},
105105
ETH1Data: &phase0.ETH1Data{},
106106
Graffiti: phase0.Hash32{},
@@ -119,11 +119,11 @@ func doGetPayload(v validatorPrivateData, boostEndpoint string, beaconNode Beaco
119119
log.WithError(err).Fatal("could not sign blinded beacon block")
120120
}
121121

122-
payload := capella.SignedBlindedBeaconBlock{
122+
payload := eth2ApiV1Capella.SignedBlindedBeaconBlock{
123123
Message: &blindedBeaconBlock,
124124
Signature: signature,
125125
}
126-
var respPayload api.VersionedExecutionPayload
126+
var respPayload builderApi.VersionedExecutionPayload
127127
if _, err := server.SendHTTPRequest(context.TODO(), *http.DefaultClient, http.MethodPost, boostEndpoint+"/eth/v1/builder/blinded_blocks", "test-cli", nil, payload, &respPayload); err != nil {
128128
log.WithError(err).Fatal("could not get payload")
129129
}

cmd/test-cli/validator.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import (
66
"os"
77
"time"
88

9-
apiv1 "github.com/attestantio/go-builder-client/api/v1"
9+
builderApiV1 "github.com/attestantio/go-builder-client/api/v1"
1010
"github.com/attestantio/go-eth2-client/spec/phase0"
1111
"github.com/ethereum/go-ethereum/common/hexutil"
1212
"github.com/flashbots/go-boost-utils/bls"
@@ -52,29 +52,29 @@ func newRandomValidator(gasLimit uint64, feeRecipient string) validatorPrivateDa
5252
return validatorPrivateData{bls.SecretKeyToBytes(sk), bls.PublicKeyToBytes(pk), hexutil.Uint64(gasLimit), feeRecipient}
5353
}
5454

55-
func (v *validatorPrivateData) PrepareRegistrationMessage(builderSigningDomain phase0.Domain) ([]apiv1.SignedValidatorRegistration, error) {
55+
func (v *validatorPrivateData) PrepareRegistrationMessage(builderSigningDomain phase0.Domain) ([]builderApiV1.SignedValidatorRegistration, error) {
5656
pk := phase0.BLSPubKey{}
5757
if len(v.Pk) != len(pk) {
58-
return []apiv1.SignedValidatorRegistration{}, errInvalidLength
58+
return []builderApiV1.SignedValidatorRegistration{}, errInvalidLength
5959
}
6060
copy(pk[:], v.Pk)
6161

6262
addr, err := utils.HexToAddress(v.FeeRecipientHex)
6363
if err != nil {
64-
return []apiv1.SignedValidatorRegistration{}, err
64+
return []builderApiV1.SignedValidatorRegistration{}, err
6565
}
66-
msg := apiv1.ValidatorRegistration{
66+
msg := builderApiV1.ValidatorRegistration{
6767
FeeRecipient: addr,
6868
Timestamp: time.Now(),
6969
Pubkey: pk,
7070
GasLimit: uint64(v.GasLimit),
7171
}
7272
signature, err := v.Sign(&msg, builderSigningDomain)
7373
if err != nil {
74-
return []apiv1.SignedValidatorRegistration{}, err
74+
return []builderApiV1.SignedValidatorRegistration{}, err
7575
}
7676

77-
return []apiv1.SignedValidatorRegistration{{
77+
return []builderApiV1.SignedValidatorRegistration{{
7878
Message: &msg,
7979
Signature: signature,
8080
}}, nil

go.mod

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@ module github.com/flashbots/mev-boost
33
go 1.20
44

55
require (
6-
github.com/ethereum/go-ethereum v1.13.9
7-
github.com/flashbots/go-boost-utils v1.7.1
6+
github.com/ethereum/go-ethereum v1.13.10
7+
github.com/flashbots/go-boost-utils v1.8.0
88
github.com/flashbots/go-utils v0.5.0
99
github.com/google/uuid v1.5.0
10-
github.com/gorilla/mux v1.8.1
10+
github.com/gorilla/mux v1.8.0
1111
github.com/holiman/uint256 v1.2.4
1212
github.com/prysmaticlabs/go-bitfield v0.0.0-20210809151128-385d8c5e3fb7
1313
github.com/sirupsen/logrus v1.9.3

go.sum

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -92,16 +92,16 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7
9292
github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw=
9393
github.com/ethereum/c-kzg-4844 v0.4.0 h1:3MS1s4JtA868KpJxroZoepdV0ZKBp3u/O5HcZ7R3nlY=
9494
github.com/ethereum/c-kzg-4844 v0.4.0/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0=
95-
github.com/ethereum/go-ethereum v1.13.9 h1:ed4e4c7NWPrO2VX2wsMhWs5+6Lf2D591DmdE8RgmtcU=
96-
github.com/ethereum/go-ethereum v1.13.9/go.mod h1:sc48XYQxCzH3fG9BcrXCOOgQk2JfZzNAmIKnceogzsA=
95+
github.com/ethereum/go-ethereum v1.13.10 h1:Ppdil79nN+Vc+mXfge0AuUgmKWuVv4eMqzoIVSdqZek=
96+
github.com/ethereum/go-ethereum v1.13.10/go.mod h1:sc48XYQxCzH3fG9BcrXCOOgQk2JfZzNAmIKnceogzsA=
9797
github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8=
9898
github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs=
9999
github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw=
100100
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
101101
github.com/ferranbt/fastssz v0.1.3 h1:ZI+z3JH05h4kgmFXdHuR1aWYsgrg7o+Fw7/NCzM16Mo=
102102
github.com/ferranbt/fastssz v0.1.3/go.mod h1:0Y9TEd/9XuFlh7mskMPfXiI2Dkw4Ddg9EyXt1W7MRvE=
103-
github.com/flashbots/go-boost-utils v1.7.1 h1:JN0JFOCuuQoPhyZEaFxFHC2dWVScixItJ2nijzfE6IQ=
104-
github.com/flashbots/go-boost-utils v1.7.1/go.mod h1:O2LUD1QAqi1oMzU1mtj7f1NMunNySJizQGrw7xujSe8=
103+
github.com/flashbots/go-boost-utils v1.8.0 h1:z3K1hw+Fbl9AGMNQKnK7Bvf0M/rKgjfruAEvra+Z8Mg=
104+
github.com/flashbots/go-boost-utils v1.8.0/go.mod h1:Ry1Rw8Lx5v1rpAR0+IvR4sV10jYAeQaGVM3vRD8mYdM=
105105
github.com/flashbots/go-utils v0.5.0 h1:ldjWta9B9//DJU2QcwRbErez3+1aKhSn6EoFc6d5kPY=
106106
github.com/flashbots/go-utils v0.5.0/go.mod h1:LauDwifaRdSK0mS5X34GR59pJtUu1T/lOFNdff1BqtI=
107107
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
@@ -174,8 +174,8 @@ github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+
174174
github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU=
175175
github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
176176
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
177-
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
178-
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
177+
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
178+
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
179179
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
180180
github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
181181
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=

server/mock_relay.go

Lines changed: 37 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,14 @@ import (
1010
"testing"
1111
"time"
1212

13-
"github.com/attestantio/go-builder-client/api"
14-
apibellatrix "github.com/attestantio/go-builder-client/api/bellatrix"
15-
apicapella "github.com/attestantio/go-builder-client/api/capella"
16-
apiv1 "github.com/attestantio/go-builder-client/api/v1"
17-
"github.com/attestantio/go-builder-client/spec"
18-
consensusspec "github.com/attestantio/go-eth2-client/spec"
19-
"github.com/attestantio/go-eth2-client/spec/bellatrix"
13+
builderApi "github.com/attestantio/go-builder-client/api"
14+
builderApiCapella "github.com/attestantio/go-builder-client/api/capella"
15+
builderApiDeneb "github.com/attestantio/go-builder-client/api/deneb"
16+
builderApiV1 "github.com/attestantio/go-builder-client/api/v1"
17+
builderSpec "github.com/attestantio/go-builder-client/spec"
18+
"github.com/attestantio/go-eth2-client/spec"
2019
"github.com/attestantio/go-eth2-client/spec/capella"
20+
"github.com/attestantio/go-eth2-client/spec/deneb"
2121
"github.com/attestantio/go-eth2-client/spec/phase0"
2222
"github.com/ethereum/go-ethereum/common/hexutil"
2323
"github.com/flashbots/go-boost-utils/bls"
@@ -59,8 +59,8 @@ type mockRelay struct {
5959
handlerOverrideGetPayload func(w http.ResponseWriter, req *http.Request)
6060

6161
// Default responses placeholders, used if overrider does not exist
62-
GetHeaderResponse *spec.VersionedSignedBuilderBid
63-
GetPayloadResponse *api.VersionedExecutionPayload
62+
GetHeaderResponse *builderSpec.VersionedSignedBuilderBid
63+
GetPayloadResponse *builderApi.VersionedSubmitBlindedBlockResponse
6464

6565
// Server section
6666
Server *httptest.Server
@@ -141,7 +141,7 @@ func (m *mockRelay) handleStatus(w http.ResponseWriter, _ *http.Request) {
141141
fmt.Fprintf(w, `{}`)
142142
}
143143

144-
// By default, handleRegisterValidator returns a default apiv1.SignedValidatorRegistration
144+
// By default, handleRegisterValidator returns a default builderApiV1.SignedValidatorRegistration
145145
func (m *mockRelay) handleRegisterValidator(w http.ResponseWriter, req *http.Request) {
146146
m.mu.Lock()
147147
defer m.mu.Unlock()
@@ -154,7 +154,7 @@ func (m *mockRelay) handleRegisterValidator(w http.ResponseWriter, req *http.Req
154154

155155
// defaultHandleRegisterValidator returns the default handler for handleRegisterValidator
156156
func (m *mockRelay) defaultHandleRegisterValidator(w http.ResponseWriter, req *http.Request) {
157-
payload := []apiv1.SignedValidatorRegistration{}
157+
payload := []builderApiV1.SignedValidatorRegistration{}
158158
if err := DecodeJSON(req.Body, &payload); err != nil {
159159
http.Error(w, err.Error(), http.StatusBadRequest)
160160
return
@@ -166,14 +166,15 @@ func (m *mockRelay) defaultHandleRegisterValidator(w http.ResponseWriter, req *h
166166

167167
// MakeGetHeaderResponse is used to create the default or can be used to create a custom response to the getHeader
168168
// method
169-
func (m *mockRelay) MakeGetHeaderResponse(value uint64, blockHash, parentHash, publicKey string, version consensusspec.DataVersion) *spec.VersionedSignedBuilderBid {
169+
func (m *mockRelay) MakeGetHeaderResponse(value uint64, blockHash, parentHash, publicKey string, version spec.DataVersion) *builderSpec.VersionedSignedBuilderBid {
170170
switch version {
171-
case consensusspec.DataVersionBellatrix:
171+
case spec.DataVersionCapella:
172172
// Fill the payload with custom values.
173-
message := &apibellatrix.BuilderBid{
174-
Header: &bellatrix.ExecutionPayloadHeader{
175-
BlockHash: _HexToHash(blockHash),
176-
ParentHash: _HexToHash(parentHash),
173+
message := &builderApiCapella.BuilderBid{
174+
Header: &capella.ExecutionPayloadHeader{
175+
BlockHash: _HexToHash(blockHash),
176+
ParentHash: _HexToHash(parentHash),
177+
WithdrawalsRoot: phase0.Root{},
177178
},
178179
Value: uint256.NewInt(value),
179180
Pubkey: _HexToPubkey(publicKey),
@@ -183,37 +184,38 @@ func (m *mockRelay) MakeGetHeaderResponse(value uint64, blockHash, parentHash, p
183184
signature, err := ssz.SignMessage(message, ssz.DomainBuilder, m.secretKey)
184185
require.NoError(m.t, err)
185186

186-
return &spec.VersionedSignedBuilderBid{
187-
Version: consensusspec.DataVersionCapella,
188-
Bellatrix: &apibellatrix.SignedBuilderBid{
187+
return &builderSpec.VersionedSignedBuilderBid{
188+
Version: spec.DataVersionCapella,
189+
Capella: &builderApiCapella.SignedBuilderBid{
189190
Message: message,
190191
Signature: signature,
191192
},
192193
}
193-
case consensusspec.DataVersionCapella:
194-
// Fill the payload with custom values.
195-
message := &apicapella.BuilderBid{
196-
Header: &capella.ExecutionPayloadHeader{
194+
case spec.DataVersionDeneb:
195+
message := &builderApiDeneb.BuilderBid{
196+
Header: &deneb.ExecutionPayloadHeader{
197197
BlockHash: _HexToHash(blockHash),
198198
ParentHash: _HexToHash(parentHash),
199199
WithdrawalsRoot: phase0.Root{},
200+
BaseFeePerGas: uint256.NewInt(0),
200201
},
201-
Value: uint256.NewInt(value),
202-
Pubkey: _HexToPubkey(publicKey),
202+
BlobKZGCommitments: make([]deneb.KZGCommitment, 0),
203+
Value: uint256.NewInt(value),
204+
Pubkey: _HexToPubkey(publicKey),
203205
}
204206

205207
// Sign the message.
206208
signature, err := ssz.SignMessage(message, ssz.DomainBuilder, m.secretKey)
207209
require.NoError(m.t, err)
208210

209-
return &spec.VersionedSignedBuilderBid{
210-
Version: consensusspec.DataVersionCapella,
211-
Capella: &apicapella.SignedBuilderBid{
211+
return &builderSpec.VersionedSignedBuilderBid{
212+
Version: spec.DataVersionDeneb,
213+
Deneb: &builderApiDeneb.SignedBuilderBid{
212214
Message: message,
213215
Signature: signature,
214216
},
215217
}
216-
case consensusspec.DataVersionUnknown, consensusspec.DataVersionPhase0, consensusspec.DataVersionAltair, consensusspec.DataVersionDeneb:
218+
case spec.DataVersionUnknown, spec.DataVersionPhase0, spec.DataVersionAltair, spec.DataVersionBellatrix:
217219
return nil
218220
}
219221
return nil
@@ -243,7 +245,7 @@ func (m *mockRelay) defaultHandleGetHeader(w http.ResponseWriter) {
243245
"0xe28385e7bd68df656cd0042b74b69c3104b5356ed1f20eb69f1f925df47a3ab7",
244246
"0xe28385e7bd68df656cd0042b74b69c3104b5356ed1f20eb69f1f925df47a3ab7",
245247
"0x8a1d7b8dd64e0aafe7ea7b6c95065c9364cf99d38470c12ee807d55f7de1529ad29ce2c422e0b65e3d5a05c02caca249",
246-
consensusspec.DataVersionCapella,
248+
spec.DataVersionCapella,
247249
)
248250
if m.GetHeaderResponse != nil {
249251
response = m.GetHeaderResponse
@@ -257,9 +259,9 @@ func (m *mockRelay) defaultHandleGetHeader(w http.ResponseWriter) {
257259

258260
// MakeGetPayloadResponse is used to create the default or can be used to create a custom response to the getPayload
259261
// method
260-
func (m *mockRelay) MakeGetPayloadResponse(parentHash, blockHash, feeRecipient string, blockNumber uint64) *api.VersionedExecutionPayload {
261-
return &api.VersionedExecutionPayload{
262-
Version: consensusspec.DataVersionCapella,
262+
func (m *mockRelay) MakeGetPayloadResponse(parentHash, blockHash, feeRecipient string, blockNumber uint64, version spec.DataVersion) *builderApi.VersionedSubmitBlindedBlockResponse {
263+
return &builderApi.VersionedSubmitBlindedBlockResponse{
264+
Version: version,
263265
Capella: &capella.ExecutionPayload{
264266
ParentHash: _HexToHash(parentHash),
265267
BlockHash: _HexToHash(blockHash),
@@ -294,6 +296,7 @@ func (m *mockRelay) defaultHandleGetPayload(w http.ResponseWriter) {
294296
"0x534809bd2b6832edff8d8ce4cb0e50068804fd1ef432c8362ad708a74fdc0e46",
295297
"0xdb65fEd33dc262Fe09D9a2Ba8F80b329BA25f941",
296298
12345,
299+
spec.DataVersionCapella,
297300
)
298301

299302
if m.GetPayloadResponse != nil {

server/mock_types_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package server
33
import (
44
"testing"
55

6-
capellaapi "github.com/attestantio/go-builder-client/api/capella"
6+
builderApiCapella "github.com/attestantio/go-builder-client/api/capella"
77
"github.com/attestantio/go-eth2-client/spec/bellatrix"
88
"github.com/attestantio/go-eth2-client/spec/capella"
99
"github.com/attestantio/go-eth2-client/spec/phase0"
@@ -202,7 +202,7 @@ func TestHexToSignature(t *testing.T) {
202202

203203
publicKey := hexutil.Encode(bls.PublicKeyToBytes(blsPublicKey))
204204

205-
message := &capellaapi.BuilderBid{
205+
message := &builderApiCapella.BuilderBid{
206206
Header: &capella.ExecutionPayloadHeader{
207207
BlockHash: _HexToHash("0xe28385e7bd68df656cd0042b74b69c3104b5356ed1f20eb69f1f925df47a3ab7"),
208208
},

0 commit comments

Comments
 (0)