Skip to content

Commit cc11fcb

Browse files
author
Jason Yellick
committed
[FAB-2033] Proto switch ChainHeader->ChannelHeader
https://jira.hyperledger.org/browse/FAB-2033 The user facing documentation refers to channels, but the vast majority of the fabric code refers to chains. This CR switches the protos to refer to channels as they are generally the interface between the user and fabric code. Change-Id: I869e6d68c1228e638a99e2460274889f18f2543d Signed-off-by: Jason Yellick <[email protected]>
1 parent 0045a79 commit cc11fcb

File tree

42 files changed

+217
-217
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+217
-217
lines changed

common/configtx/manager_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ func makeConfigItem(id, modificationPolicy string, lastModified uint64, data []b
7777

7878
func makeMarshaledConfig(chainID string, configItems ...*cb.ConfigItem) []byte {
7979
config := &cb.Config{
80-
Header: &cb.ChainHeader{ChannelId: chainID},
80+
Header: &cb.ChannelHeader{ChannelId: chainID},
8181
Items: configItems,
8282
}
8383
return utils.MarshalOrPanic(config)

common/configtx/template.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ func (st *simpleTemplate) Envelope(chainID string) (*cb.ConfigEnvelope, error) {
9797
}
9898

9999
marshaledConfig, err := proto.Marshal(&cb.ConfigNext{
100-
Header: &cb.ChainHeader{
100+
Header: &cb.ChannelHeader{
101101
ChannelId: chainID,
102102
Type: int32(cb.HeaderType_CONFIGURATION_ITEM),
103103
},
@@ -172,7 +172,7 @@ func (ct *compositeTemplate) Envelope(chainID string) (*cb.ConfigEnvelope, error
172172
}
173173

174174
marshaledConfig, err := proto.Marshal(&cb.ConfigNext{
175-
Header: &cb.ChainHeader{
175+
Header: &cb.ChannelHeader{
176176
ChannelId: chainID,
177177
Type: int32(cb.HeaderType_CONFIGURATION_ITEM),
178178
},
@@ -239,9 +239,9 @@ func MakeChainCreationTransaction(creationPolicy string, chainID string, signer
239239
return nil, err
240240
}
241241

242-
payloadChainHeader := utils.MakeChainHeader(cb.HeaderType_CONFIGURATION_TRANSACTION, msgVersion, chainID, epoch)
242+
payloadChannelHeader := utils.MakeChannelHeader(cb.HeaderType_CONFIGURATION_TRANSACTION, msgVersion, chainID, epoch)
243243
payloadSignatureHeader := utils.MakeSignatureHeader(sSigner, utils.CreateNonceOrPanic())
244-
payloadHeader := utils.MakePayloadHeader(payloadChainHeader, payloadSignatureHeader)
244+
payloadHeader := utils.MakePayloadHeader(payloadChannelHeader, payloadSignatureHeader)
245245
payload := &cb.Payload{Header: payloadHeader, Data: utils.MarshalOrPanic(newConfigEnv)}
246246
paylBytes := utils.MarshalOrPanic(payload)
247247

common/genesis/genesis.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,9 @@ func (f *factory) Block(chainID string) (*cb.Block, error) {
4848
return nil, err
4949
}
5050

51-
payloadChainHeader := utils.MakeChainHeader(cb.HeaderType_CONFIGURATION_TRANSACTION, msgVersion, chainID, epoch)
51+
payloadChannelHeader := utils.MakeChannelHeader(cb.HeaderType_CONFIGURATION_TRANSACTION, msgVersion, chainID, epoch)
5252
payloadSignatureHeader := utils.MakeSignatureHeader(nil, utils.CreateNonceOrPanic())
53-
payloadHeader := utils.MakePayloadHeader(payloadChainHeader, payloadSignatureHeader)
53+
payloadHeader := utils.MakePayloadHeader(payloadChannelHeader, payloadSignatureHeader)
5454
payload := &cb.Payload{Header: payloadHeader, Data: utils.MarshalOrPanic(configEnv)}
5555
envelope := &cb.Envelope{Payload: utils.MarshalOrPanic(payload), Signature: nil}
5656

common/ledger/blkstorage/fsblkstorage/block_serialization.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -207,5 +207,5 @@ func extractTxID(txEnvelopBytes []byte) (string, error) {
207207
if err != nil {
208208
return "", nil
209209
}
210-
return txPayload.Header.ChainHeader.TxId, nil
210+
return txPayload.Header.ChannelHeader.TxId, nil
211211
}

core/committer/txvalidator/txvalidator_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ func TestNewTxValidator_DuplicateTransactions(t *testing.T) {
7575
// Create simeple endorsement transaction
7676
payload := &common.Payload{
7777
Header: &common.Header{
78-
ChainHeader: &common.ChainHeader{
78+
ChannelHeader: &common.ChannelHeader{
7979
TxId: "simple_txID", // Fake txID
8080
Type: int32(common.HeaderType_ENDORSER_TRANSACTION),
8181
ChannelId: util2.GetTestChainID(),

core/committer/txvalidator/validator.go

+7-7
Original file line numberDiff line numberDiff line change
@@ -118,17 +118,17 @@ func (v *txValidator) Validate(block *common.Block) error {
118118
continue
119119
}
120120

121-
chain := payload.Header.ChainHeader.ChannelId
121+
chain := payload.Header.ChannelHeader.ChannelId
122122
logger.Debug("Transaction is for chain %s", chain)
123123

124124
if !v.chainExists(chain) {
125125
logger.Errorf("Dropping transaction for non-existent chain %s", chain)
126126
continue
127127
}
128128

129-
if common.HeaderType(payload.Header.ChainHeader.Type) == common.HeaderType_ENDORSER_TRANSACTION {
129+
if common.HeaderType(payload.Header.ChannelHeader.Type) == common.HeaderType_ENDORSER_TRANSACTION {
130130
// Check duplicate transactions
131-
txID := payload.Header.ChainHeader.TxId
131+
txID := payload.Header.ChannelHeader.TxId
132132
if _, err := v.support.Ledger().GetTransactionByID(txID); err == nil {
133133
logger.Warning("Duplicate transaction found, ", txID, ", skipping")
134134
continue
@@ -141,7 +141,7 @@ func (v *txValidator) Validate(block *common.Block) error {
141141
logger.Errorf("VSCCValidateTx for transaction txId = %s returned error %s", txID, err)
142142
continue
143143
}
144-
} else if common.HeaderType(payload.Header.ChainHeader.Type) == common.HeaderType_CONFIGURATION_TRANSACTION {
144+
} else if common.HeaderType(payload.Header.ChannelHeader.Type) == common.HeaderType_CONFIGURATION_TRANSACTION {
145145
configEnvelope, err := configtx.UnmarshalConfigEnvelope(payload.Data)
146146
if err != nil {
147147
err := fmt.Errorf("Error unmarshaling config which passed initial validity checks: %s", err)
@@ -179,16 +179,16 @@ func (v *txValidator) Validate(block *common.Block) error {
179179

180180
func (v *vsccValidatorImpl) VSCCValidateTx(payload *common.Payload, envBytes []byte) error {
181181
// Chain ID
182-
chainID := payload.Header.ChainHeader.ChannelId
182+
chainID := payload.Header.ChannelHeader.ChannelId
183183
if chainID == "" {
184184
err := fmt.Errorf("transaction header does not contain an chain ID")
185185
logger.Errorf("%s", err)
186186
return err
187187
}
188188

189189
// Get transaction id
190-
txid := payload.Header.ChainHeader.TxId
191-
logger.Info("[XXX remove me XXX] Transaction type,", common.HeaderType(payload.Header.ChainHeader.Type))
190+
txid := payload.Header.ChannelHeader.TxId
191+
logger.Info("[XXX remove me XXX] Transaction type,", common.HeaderType(payload.Header.ChannelHeader.Type))
192192
if txid == "" {
193193
err := fmt.Errorf("transaction header does not contain transaction ID")
194194
logger.Errorf("%s", err)

core/common/validation/msgvalidation.go

+13-13
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ func ValidateProposalMessage(signedProp *pb.SignedProposal) (*pb.Proposal, *comm
7878
}
7979

8080
// validate the signature
81-
err = checkSignatureFromCreator(hdr.SignatureHeader.Creator, signedProp.Signature, signedProp.ProposalBytes, hdr.ChainHeader.ChannelId)
81+
err = checkSignatureFromCreator(hdr.SignatureHeader.Creator, signedProp.Signature, signedProp.ProposalBytes, hdr.ChannelHeader.ChannelId)
8282
if err != nil {
8383
return nil, nil, nil, err
8484
}
@@ -88,7 +88,7 @@ func ValidateProposalMessage(signedProp *pb.SignedProposal) (*pb.Proposal, *comm
8888
// TODO: perform a check against replay attacks
8989

9090
// continue the validation in a way that depends on the type specified in the header
91-
switch common.HeaderType(hdr.ChainHeader.Type) {
91+
switch common.HeaderType(hdr.ChannelHeader.Type) {
9292
case common.HeaderType_CONFIGURATION_TRANSACTION:
9393
//which the types are different the validation is the same
9494
//viz, validate a proposal to a chaincode. If we need other
@@ -105,7 +105,7 @@ func ValidateProposalMessage(signedProp *pb.SignedProposal) (*pb.Proposal, *comm
105105
return prop, hdr, chaincodeHdrExt, err
106106
default:
107107
//NOTE : we proably need a case
108-
return nil, nil, nil, fmt.Errorf("Unsupported proposal type %d", common.HeaderType(hdr.ChainHeader.Type))
108+
return nil, nil, nil, fmt.Errorf("Unsupported proposal type %d", common.HeaderType(hdr.ChannelHeader.Type))
109109
}
110110
}
111111

@@ -172,11 +172,11 @@ func validateSignatureHeader(sHdr *common.SignatureHeader) error {
172172
return nil
173173
}
174174

175-
// checks for a valid ChainHeader
176-
func validateChainHeader(cHdr *common.ChainHeader) error {
175+
// checks for a valid ChannelHeader
176+
func validateChannelHeader(cHdr *common.ChannelHeader) error {
177177
// check for nil argument
178178
if cHdr == nil {
179-
return fmt.Errorf("Nil ChainHeader provided")
179+
return fmt.Errorf("Nil ChannelHeader provided")
180180
}
181181

182182
// validate the header type
@@ -186,7 +186,7 @@ func validateChainHeader(cHdr *common.ChainHeader) error {
186186
return fmt.Errorf("invalid header type %s", common.HeaderType(cHdr.Type))
187187
}
188188

189-
putilsLogger.Infof("validateChainHeader info: header type %d", common.HeaderType(cHdr.Type))
189+
putilsLogger.Infof("validateChannelHeader info: header type %d", common.HeaderType(cHdr.Type))
190190

191191
// TODO: validate chainID in cHdr.ChainID
192192

@@ -203,7 +203,7 @@ func validateCommonHeader(hdr *common.Header) error {
203203
return fmt.Errorf("Nil header")
204204
}
205205

206-
err := validateChainHeader(hdr.ChainHeader)
206+
err := validateChannelHeader(hdr.ChannelHeader)
207207
if err != nil {
208208
return err
209209
}
@@ -296,8 +296,8 @@ func validateEndorserTransaction(data []byte, hdr *common.Header) error {
296296
}
297297

298298
// build the original header by stitching together
299-
// the common ChainHeader and the per-action SignatureHeader
300-
hdrOrig := &common.Header{ChainHeader: hdr.ChainHeader, SignatureHeader: sHdr}
299+
// the common ChannelHeader and the per-action SignatureHeader
300+
hdrOrig := &common.Header{ChannelHeader: hdr.ChannelHeader, SignatureHeader: sHdr}
301301
hdrBytes, err := utils.GetBytesHeader(hdrOrig) // FIXME: here we hope that hdrBytes will be the same one that the endorser had
302302
if err != nil {
303303
return err
@@ -342,7 +342,7 @@ func ValidateTransaction(e *common.Envelope) (*common.Payload, error) {
342342
}
343343

344344
// validate the signature in the envelope
345-
err = checkSignatureFromCreator(payload.Header.SignatureHeader.Creator, e.Signature, e.Payload, payload.Header.ChainHeader.ChannelId)
345+
err = checkSignatureFromCreator(payload.Header.SignatureHeader.Creator, e.Signature, e.Payload, payload.Header.ChannelHeader.ChannelId)
346346
if err != nil {
347347
return nil, err
348348
}
@@ -352,7 +352,7 @@ func ValidateTransaction(e *common.Envelope) (*common.Payload, error) {
352352
// TODO: perform a check against replay attacks
353353

354354
// continue the validation in a way that depends on the type specified in the header
355-
switch common.HeaderType(payload.Header.ChainHeader.Type) {
355+
switch common.HeaderType(payload.Header.ChannelHeader.Type) {
356356
case common.HeaderType_ENDORSER_TRANSACTION:
357357
err = validateEndorserTransaction(payload.Data, payload.Header)
358358
putilsLogger.Infof("ValidateTransactionEnvelope returns err %s", err)
@@ -362,6 +362,6 @@ func ValidateTransaction(e *common.Envelope) (*common.Payload, error) {
362362
putilsLogger.Infof("ValidateTransactionEnvelope returns err %s", err)
363363
return payload, err
364364
default:
365-
return nil, fmt.Errorf("Unsupported transaction payload type %d", common.HeaderType(payload.Header.ChainHeader.Type))
365+
return nil, fmt.Errorf("Unsupported transaction payload type %d", common.HeaderType(payload.Header.ChannelHeader.Type))
366366
}
367367
}

core/deliverservice/blocksprovider/blocksprovider.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ func (b *blocksProviderImpl) seekOldest() error {
178178
return b.client.Send(&common.Envelope{
179179
Payload: utils.MarshalOrPanic(&common.Payload{
180180
Header: &common.Header{
181-
ChainHeader: &common.ChainHeader{
181+
ChannelHeader: &common.ChannelHeader{
182182
ChannelId: b.chainID,
183183
},
184184
SignatureHeader: &common.SignatureHeader{},
@@ -196,7 +196,7 @@ func (b *blocksProviderImpl) seekLatestFromCommitter(height uint64) error {
196196
return b.client.Send(&common.Envelope{
197197
Payload: utils.MarshalOrPanic(&common.Payload{
198198
Header: &common.Header{
199-
ChainHeader: &common.ChainHeader{
199+
ChannelHeader: &common.ChannelHeader{
200200
ChannelId: b.chainID,
201201
},
202202
SignatureHeader: &common.SignatureHeader{},

core/endorser/endorser.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@ func (e *Endorser) ProcessProposal(ctx context.Context, signedProp *pb.SignedPro
273273
return &pb.ProposalResponse{Response: &pb.Response{Status: 500, Message: err.Error()}}, err
274274
}
275275

276-
chainID := hdr.ChainHeader.ChannelId
276+
chainID := hdr.ChannelHeader.ChannelId
277277

278278
//chainless MSPs have "" chain name
279279
ischainless := syscc.IsChainlessSysCC(hdrExt.ChaincodeId.Name)
@@ -290,7 +290,7 @@ func (e *Endorser) ProcessProposal(ctx context.Context, signedProp *pb.SignedPro
290290

291291
//TODO check for uniqueness of prop.TxID with ledger
292292

293-
txid := hdr.ChainHeader.TxId
293+
txid := hdr.ChannelHeader.TxId
294294
if txid == "" {
295295
err = fmt.Errorf("Invalid txID")
296296
return &pb.ProposalResponse{Response: &pb.Response{Status: 500, Message: err.Error()}}, err

core/ledger/kvledger/history/historydb/historyleveldb/historyleveldb.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ func (historyDB *historyDB) Commit(block *common.Block) error {
106106
return err
107107
}
108108

109-
if common.HeaderType(payload.Header.ChainHeader.Type) == common.HeaderType_ENDORSER_TRANSACTION {
109+
if common.HeaderType(payload.Header.ChannelHeader.Type) == common.HeaderType_ENDORSER_TRANSACTION {
110110

111111
// extract actions from the envelope message
112112
respPayload, err := putils.GetActionFromEnvelope(envBytes)

core/ledger/kvledger/history/historydb/historyleveldb/historyleveldb_query_executer.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ func getTxIDandKeyWriteValueFromTran(
122122
return "", nil, err
123123
}
124124

125-
txID := payload.Header.ChainHeader.TxId
125+
txID := payload.Header.ChannelHeader.TxId
126126

127127
txRWSet := &rwset.TxReadWriteSet{}
128128

core/ledger/kvledger/txmgmt/validator/statebasedval/state_based_validator.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ func (v *Validator) ValidateAndPrepareBatch(block *common.Block, doMVCCValidatio
107107
}
108108

109109
valid := false
110-
if common.HeaderType(payload.Header.ChainHeader.Type) == common.HeaderType_ENDORSER_TRANSACTION {
110+
if common.HeaderType(payload.Header.ChannelHeader.Type) == common.HeaderType_ENDORSER_TRANSACTION {
111111
txRWSet, err := v.validateEndorserTX(envBytes, doMVCCValidation, updates)
112112
if err != nil {
113113
return nil, err
@@ -118,13 +118,13 @@ func (v *Validator) ValidateAndPrepareBatch(block *common.Block, doMVCCValidatio
118118
addWriteSetToBatch(txRWSet, committingTxHeight, updates)
119119
valid = true
120120
}
121-
} else if common.HeaderType(payload.Header.ChainHeader.Type) == common.HeaderType_CONFIGURATION_TRANSACTION {
121+
} else if common.HeaderType(payload.Header.ChannelHeader.Type) == common.HeaderType_CONFIGURATION_TRANSACTION {
122122
valid, err = v.validateConfigTX(env)
123123
if err != nil {
124124
return nil, err
125125
}
126126
} else {
127-
logger.Errorf("Skipping transaction %d that's not an endorsement or configuration %d", txIndex, payload.Header.ChainHeader.Type)
127+
logger.Errorf("Skipping transaction %d that's not an endorsement or configuration %d", txIndex, payload.Header.ChannelHeader.Type)
128128
valid = false
129129
}
130130

core/peer/peer.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ func getCurrConfigBlockFromLedger(ledger ledger.PeerLedger) (*common.Block, erro
143143
currBlockNumber = block.Header.Number - 1
144144
continue
145145
}
146-
if tx.Header.ChainHeader.Type == int32(common.HeaderType_CONFIGURATION_TRANSACTION) {
146+
if tx.Header.ChannelHeader.Type == int32(common.HeaderType_CONFIGURATION_TRANSACTION) {
147147
return block, nil
148148
}
149149
}

core/scc/cscc/configer_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,6 @@ func getChainID(blockBytes []byte) (string, error) {
234234
if err := proto.Unmarshal(envelope.Payload, payload); err != nil {
235235
return "", err
236236
}
237-
fmt.Printf("chain id: %v\n", payload.Header.ChainHeader.ChannelId)
238-
return payload.Header.ChainHeader.ChannelId, nil
237+
fmt.Printf("Channel id: %v\n", payload.Header.ChannelHeader.ChannelId)
238+
return payload.Header.ChannelHeader.ChannelId, nil
239239
}

core/scc/vscc/validator_onevalidsignature.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ func (vscc *ValidatorOneValidSignature) Invoke(stub shim.ChaincodeStubInterface)
8686
}
8787

8888
// get the policy
89-
mgr := mspmgmt.GetManagerForChain(payl.Header.ChainHeader.ChannelId)
89+
mgr := mspmgmt.GetManagerForChain(payl.Header.ChannelHeader.ChannelId)
9090
pProvider := cauthdsl.NewPolicyProvider(mgr)
9191
policy, err := pProvider.NewPolicy(args[2])
9292
if err != nil {
@@ -95,9 +95,9 @@ func (vscc *ValidatorOneValidSignature) Invoke(stub shim.ChaincodeStubInterface)
9595
}
9696

9797
// validate the payload type
98-
if common.HeaderType(payl.Header.ChainHeader.Type) != common.HeaderType_ENDORSER_TRANSACTION {
99-
logger.Errorf("Only Endorser Transactions are supported, provided type %d", payl.Header.ChainHeader.Type)
100-
return shim.Error(fmt.Sprintf("Only Endorser Transactions are supported, provided type %d", payl.Header.ChainHeader.Type))
98+
if common.HeaderType(payl.Header.ChannelHeader.Type) != common.HeaderType_ENDORSER_TRANSACTION {
99+
logger.Errorf("Only Endorser Transactions are supported, provided type %d", payl.Header.ChannelHeader.Type)
100+
return shim.Error(fmt.Sprintf("Only Endorser Transactions are supported, provided type %d", payl.Header.ChannelHeader.Type))
101101
}
102102

103103
// ...and the transaction...

events/events_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -84,15 +84,15 @@ func (a *Adapter) Disconnected(err error) {
8484
}
8585

8686
func createTestBlock(t *testing.T) *common.Block {
87-
chdr := &common.ChainHeader{
87+
chdr := &common.ChannelHeader{
8888
Type: int32(common.HeaderType_ENDORSER_TRANSACTION),
8989
Version: 1,
9090
Timestamp: &timestamp.Timestamp{
9191
Seconds: time.Now().Unix(),
9292
Nanos: 0,
9393
},
9494
ChannelId: "test"}
95-
hdr := &common.Header{ChainHeader: chdr}
95+
hdr := &common.Header{ChannelHeader: chdr}
9696
payload := &common.Payload{Header: hdr}
9797
cea := &ehpb.ChaincodeEndorsedAction{}
9898
ccaPayload := &ehpb.ChaincodeActionPayload{Action: cea}

events/producer/eventhelper.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ func SendProducerBlockEvent(block *common.Block) error {
4949
return fmt.Errorf("Could not extract payload from envelope, err %s", err)
5050
}
5151

52-
if common.HeaderType(payload.Header.ChainHeader.Type) == common.HeaderType_ENDORSER_TRANSACTION {
52+
if common.HeaderType(payload.Header.ChannelHeader.Type) == common.HeaderType_ENDORSER_TRANSACTION {
5353
tx, err := utils.GetTransaction(payload.Data)
5454
if err != nil {
5555
return fmt.Errorf("Error unmarshalling transaction payload for block event: %s", err)

examples/events/block-listener/block-listener.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ func getChainCodeEvents(tdata []byte) (*pb.ChaincodeEvent, error) {
9999
return nil, fmt.Errorf("Could not extract payload from envelope, err %s", err)
100100
}
101101

102-
if common.HeaderType(payload.Header.ChainHeader.Type) == common.HeaderType_ENDORSER_TRANSACTION {
102+
if common.HeaderType(payload.Header.ChannelHeader.Type) == common.HeaderType_ENDORSER_TRANSACTION {
103103
tx, err := utils.GetTransaction(payload.Data)
104104
if err != nil {
105105
return nil, fmt.Errorf("Error unmarshalling transaction payload for block event: %s", err)
@@ -158,7 +158,7 @@ func main() {
158158
fmt.Printf("\n")
159159
fmt.Printf("Received invalid transaction\n")
160160
fmt.Printf("--------------\n")
161-
fmt.Printf("Transaction invalid: TxID: %s\n", tx.Header.ChainHeader.TxId)
161+
fmt.Printf("Transaction invalid: TxID: %s\n", tx.Header.ChannelHeader.TxId)
162162
}
163163
} else {
164164
fmt.Printf("Transaction:\n\t[%v]\n", r)

0 commit comments

Comments
 (0)