mirror of
https://github.com/hyperledger/fabric-samples.git
synced 2026-06-23 01:55:10 +00:00
Tests on PDCs ongoing
This commit is contained in:
parent
4d42997eb8
commit
2d940bcdc6
5 changed files with 890 additions and 643 deletions
|
|
@ -43,10 +43,10 @@ type Data struct {
|
||||||
JsonFileContent map[string]interface{}
|
JsonFileContent map[string]interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
type PrivateDataContent struct {
|
type PrivateSchemaContent struct {
|
||||||
Id string `json:"Id"`
|
JsonSchemaContent map[string]interface{} `json:"JsonSchemaContent"`
|
||||||
AnonymousFunder string `json:"AnonymousFunder"`
|
SchemaId string `json:"SchemaId"`
|
||||||
AssetValue string `json:"AssetValue"`
|
Project string `json:"Project`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Schema struct {
|
type Schema struct {
|
||||||
|
|
@ -232,6 +232,7 @@ func (s *SmartContract) SchemaExists(ctx contractapi.TransactionContextInterface
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SmartContract) CreateNewSchema(ctx contractapi.TransactionContextInterface, newSchemaContent string) error {
|
func (s *SmartContract) CreateNewSchema(ctx contractapi.TransactionContextInterface, newSchemaContent string) error {
|
||||||
|
|
||||||
jsonFileContent, err := s.JsonReader(ctx, newSchemaContent)
|
jsonFileContent, err := s.JsonReader(ctx, newSchemaContent)
|
||||||
|
|
@ -416,107 +417,6 @@ func (s *SmartContract) CreateDataSample(ctx contractapi.TransactionContextInter
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SmartContract) WriteToPDC(ctx contractapi.TransactionContextInterface) error {
|
|
||||||
// Get new asset from transient map
|
|
||||||
transientMap, err := ctx.GetStub().GetTransient()
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("error getting transient: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Asset properties are private, therefore they get passed in transient field, instead of func args
|
|
||||||
transientAssetJSON, ok := transientMap["asset_properties"]
|
|
||||||
if !ok {
|
|
||||||
//log error to stdout
|
|
||||||
return fmt.Errorf("asset not found in the transient map input")
|
|
||||||
}
|
|
||||||
type assetTransientInput struct {
|
|
||||||
Contributor string `json:"Contributor"`
|
|
||||||
ContributorId string `json:"ContributorId"`
|
|
||||||
ContentHash string `json:"ContentHash"`
|
|
||||||
Id string `json:"Id"`
|
|
||||||
Owner string `json:"Owners"`
|
|
||||||
JsonFileContent map[string]interface{}
|
|
||||||
}
|
|
||||||
|
|
||||||
var assetInput assetTransientInput
|
|
||||||
err = json.Unmarshal(transientAssetJSON, &assetInput)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to unmarshal JSON: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if asset already exists
|
|
||||||
assetAsBytes, err := ctx.GetStub().GetPrivateData(PDC1, assetInput.Id)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to get asset: %v", err)
|
|
||||||
} else if assetAsBytes != nil {
|
|
||||||
fmt.Println("Asset already exists: " + assetInput.Id)
|
|
||||||
return fmt.Errorf("this asset already exists: " + assetInput.Id)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get ID of submitting client identity
|
|
||||||
clientID, err := submittingClientIdentity(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify that the client is submitting request to peer in their organization
|
|
||||||
// This is to ensure that a client from another org doesn't attempt to read or
|
|
||||||
// write private data from this peer.
|
|
||||||
err = verifyClientOrgMatchesPeerOrg(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("CreateAsset cannot be performed: Error %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make submitting client the owner
|
|
||||||
asset := Data{
|
|
||||||
Contributor: assetInput.Contributor,
|
|
||||||
ContributorId: assetInput.ContributorId,
|
|
||||||
ContentHash: assetInput.ContentHash,
|
|
||||||
Id: assetInput.Id,
|
|
||||||
Owner: clientID,
|
|
||||||
JsonFileContent: assetInput.JsonFileContent,
|
|
||||||
}
|
|
||||||
assetJSONasBytes, err := json.Marshal(asset)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to marshal asset into JSON: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save asset to private data collection
|
|
||||||
// Typical logger, logs to stdout/file in the fabric managed docker container, running this chaincode
|
|
||||||
// Look for container name like dev-peer0.org1.example.com-{chaincodename_version}-xyz
|
|
||||||
log.Printf("CreateAsset Put: collection %v, ID %v, owner %v", assetCollection, assetInput.ID, clientID)
|
|
||||||
|
|
||||||
err = ctx.GetStub().PutPrivateData(assetCollection, assetInput.ID, assetJSONasBytes)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to put asset into private data collection: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save asset details to collection visible to owning organization
|
|
||||||
assetPrivateDetails := AssetPrivateDetails{
|
|
||||||
ID: assetInput.ID,
|
|
||||||
AppraisedValue: assetInput.AppraisedValue,
|
|
||||||
}
|
|
||||||
|
|
||||||
assetPrivateDetailsAsBytes, err := json.Marshal(assetPrivateDetails) // marshal asset details to JSON
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to marshal into JSON: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get collection name for this organization.
|
|
||||||
orgCollection, err := getCollectionName(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to infer private collection name for the org: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Put asset appraised value into owners org specific private data collection
|
|
||||||
log.Printf("Put: collection %v, ID %v", orgCollection, assetInput.ID)
|
|
||||||
err = ctx.GetStub().PutPrivateData(orgCollection, assetInput.ID, assetPrivateDetailsAsBytes)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to put asset private details: %v", err)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdateAsset updates an existing asset in the world state with provided parameters.
|
// UpdateAsset updates an existing asset in the world state with provided parameters.
|
||||||
/*func (s *SmartContract) UpdateAsset(ctx contractapi.TransactionContextInterface,
|
/*func (s *SmartContract) UpdateAsset(ctx contractapi.TransactionContextInterface,
|
||||||
Contributor string, ContributorId string, Id string, Owner string) error {
|
Contributor string, ContributorId string, Id string, Owner string) error {
|
||||||
|
|
@ -933,63 +833,78 @@ func verifyClientOrgMatchesPeerOrg(ctx contractapi.TransactionContextInterface)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// WriteSchemaToPDC submits a schema to an Org's priva data collection so validations of incoming data can be done.
|
||||||
// ReadAsset returns the asset stored in the world state with given id.
|
|
||||||
func (s *SmartContract) ReadAsset(ctx contractapi.TransactionContextInterface, id string) (*Asset, error) {
|
func (s *SmartContract) WriteSchemaToPDC(ctx contractapi.TransactionContextInterface) error {
|
||||||
assetJSON, err := ctx.GetStub().GetState(id)
|
// Get new asset from transient map
|
||||||
|
transientMap, err := ctx.GetStub().GetTransient()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to read from world state: %v", err)
|
return fmt.Errorf("error getting transient: %v", err)
|
||||||
}
|
}
|
||||||
if assetJSON == nil {
|
|
||||||
return nil, fmt.Errorf("the asset %s does not exist", id)
|
// Asset properties are private, therefore they get passed in transient field, instead of func args
|
||||||
|
transientAssetJSON, ok := transientMap["asset_properties"]
|
||||||
|
if !ok {
|
||||||
|
//log error to stdout
|
||||||
|
return fmt.Errorf("asset not found in the transient map input")
|
||||||
}
|
}
|
||||||
var asset Asset
|
|
||||||
err = json.Unmarshal(assetJSON, &asset)
|
type transientInput struct {
|
||||||
|
JsonSchemaContent map[string]interface{} `json:"JsonSchemaContent"`
|
||||||
|
SchemaId string `json:"SchemaId"`
|
||||||
|
Project string `json:"Project`
|
||||||
|
}
|
||||||
|
|
||||||
|
// So far, we've taken what's on the transient dictionary and unmarshal it into the transientInput Struct
|
||||||
|
var assetInput transientInput
|
||||||
|
err = json.Unmarshal(transientAssetJSON, &assetInput)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return fmt.Errorf("failed to unmarshal JSON: %v", err)
|
||||||
}
|
}
|
||||||
return &asset, nil
|
|
||||||
}
|
// Check if Schema already exists
|
||||||
// TransferAsset updates the owner field of asset with given id in world state, and returns the old owner.
|
assetAsBytes, err := ctx.GetStub().GetPrivateData(PDC1, assetInput.SchemaId)
|
||||||
func (s *SmartContract) TransferAsset(ctx contractapi.TransactionContextInterface, id string, newOwner string) (string, error) {
|
|
||||||
asset, err := s.ReadAsset(ctx, id)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return fmt.Errorf("failed to get Schema: %v", err)
|
||||||
|
} else if assetAsBytes != nil {
|
||||||
|
fmt.Println("Schema already exists: " + assetInput.SchemaId)
|
||||||
|
return fmt.Errorf("this Schema already exists: " + assetInput.SchemaId)
|
||||||
}
|
}
|
||||||
oldOwner := asset.Owner
|
|
||||||
asset.Owner = newOwner
|
// Get ID of submitting client identity
|
||||||
assetJSON, err := json.Marshal(asset)
|
clientID, err := submittingClientIdentity(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return err
|
||||||
}
|
}
|
||||||
err = ctx.GetStub().PutState(id, assetJSON)
|
|
||||||
|
// Verify that the client is submitting request to peer in their organization
|
||||||
|
// This is to ensure that a client from another org doesn't attempt to read or
|
||||||
|
// write private data from this peer.
|
||||||
|
err = verifyClientOrgMatchesPeerOrg(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return fmt.Errorf("CreateSchema cannot be performed: Error %v", err)
|
||||||
}
|
}
|
||||||
return oldOwner, nil
|
|
||||||
|
// Make submitting client the owner
|
||||||
|
Schema := PrivateSchemaContent{
|
||||||
|
JsonSchemaContent: assetInput.JsonSchemaContent,
|
||||||
|
SchemaId: assetInput.SchemaId,
|
||||||
|
Project: assetInput.Project,
|
||||||
}
|
}
|
||||||
// GetAllAssets returns all assets found in world state
|
assetJSONasBytes, err := json.Marshal(Schema)
|
||||||
func (s *SmartContract) GetAllAssets(ctx contractapi.TransactionContextInterface) ([]*Asset, error) {
|
|
||||||
// range query with empty string for startKey and endKey does an
|
|
||||||
// open-ended query of all assets in the chaincode namespace.
|
|
||||||
resultsIterator, err := ctx.GetStub().GetStateByRange("", "")
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return fmt.Errorf("failed to marshal Schema into JSON: %v", err)
|
||||||
}
|
}
|
||||||
defer resultsIterator.Close()
|
|
||||||
var assets []*Asset
|
// Save asset to private data collection
|
||||||
for resultsIterator.HasNext() {
|
// Typical logger, logs to stdout/file in the fabric managed docker container, running this chaincode
|
||||||
queryResponse, err := resultsIterator.Next()
|
// Look for container name like dev-peer0.org1.example.com-{chaincodename_version}-xyz
|
||||||
|
log.Printf("WriteSchemaToPDC Put: collection %v, ID %v, owner %v", PDC1, assetInput.SchemaId, clientID)
|
||||||
|
|
||||||
|
err = ctx.GetStub().PutPrivateData(PDC1, assetInput.SchemaId, assetJSONasBytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return fmt.Errorf("failed to put asset into private data collection: %v", err)
|
||||||
}
|
}
|
||||||
var asset Asset
|
|
||||||
err = json.Unmarshal(queryResponse.Value, &asset)
|
return nil
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
assets = append(assets, &asset)
|
|
||||||
}
|
|
||||||
return assets, nil
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,6 +1,6 @@
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"name": "assetCollection",
|
"name": "PDC1",
|
||||||
"policy": "OR('Org1MSP.member', 'Org2MSP.member')",
|
"policy": "OR('Org1MSP.member', 'Org2MSP.member')",
|
||||||
"requiredPeerCount": 1,
|
"requiredPeerCount": 1,
|
||||||
"maxPeerCount": 1,
|
"maxPeerCount": 1,
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,13 @@ module github.com/hyperledger/fabric-samples/asset-transfer-private-data/chainco
|
||||||
go 1.14
|
go 1.14
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/google/uuid v1.3.0
|
||||||
github.com/hyperledger/fabric-chaincode-go v0.0.0-20200511190512-bcfeb58dd83a
|
github.com/hyperledger/fabric-chaincode-go v0.0.0-20200511190512-bcfeb58dd83a
|
||||||
github.com/hyperledger/fabric-contract-api-go v1.1.0
|
github.com/hyperledger/fabric-contract-api-go v1.1.0
|
||||||
github.com/hyperledger/fabric-protos-go v0.0.0-20200707132912-fee30f3ccd23
|
github.com/hyperledger/fabric-protos-go v0.0.0-20200707132912-fee30f3ccd23
|
||||||
github.com/stretchr/testify v1.5.1
|
github.com/stretchr/testify v1.5.1
|
||||||
|
github.com/xeipuuv/gojsonschema v1.2.0
|
||||||
|
golang.org/x/net v0.0.0-20220906165146-f3363e06e74c // indirect
|
||||||
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab // indirect
|
||||||
google.golang.org/protobuf v1.25.0
|
google.golang.org/protobuf v1.25.0
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,8 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
|
||||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w=
|
github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w=
|
||||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||||
|
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||||
github.com/hyperledger/fabric-chaincode-go v0.0.0-20200424173110-d7076418f212/go.mod h1:N7H3sA7Tx4k/YzFq7U0EPdqJtqvM4Kild0JoCc7C0Dc=
|
github.com/hyperledger/fabric-chaincode-go v0.0.0-20200424173110-d7076418f212/go.mod h1:N7H3sA7Tx4k/YzFq7U0EPdqJtqvM4Kild0JoCc7C0Dc=
|
||||||
github.com/hyperledger/fabric-chaincode-go v0.0.0-20200511190512-bcfeb58dd83a h1:KoFw2HnRfW+EItMP0zvUUl1FGzDb/7O0ov7uXZffQok=
|
github.com/hyperledger/fabric-chaincode-go v0.0.0-20200511190512-bcfeb58dd83a h1:KoFw2HnRfW+EItMP0zvUUl1FGzDb/7O0ov7uXZffQok=
|
||||||
|
|
@ -131,8 +133,9 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||||
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297 h1:k7pJ2yAPLPgbskkFdhRCsA77k2fySZ1zf2zCjvQCiIM=
|
|
||||||
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20220906165146-f3363e06e74c h1:yKufUcDwucU5urd+50/Opbt4AYpqthk7wHpHok8f1lo=
|
||||||
|
golang.org/x/net v0.0.0-20220906165146-f3363e06e74c/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
|
@ -144,11 +147,16 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190515120540-06a5c4944438/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190515120540-06a5c4944438/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190710143415-6ec70d6a5542 h1:6ZQFf1D2YYDDI7eSwW8adlkkavTB9sw5I24FVtEvNUQ=
|
|
||||||
golang.org/x/sys v0.0.0-20190710143415-6ec70d6a5542/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190710143415-6ec70d6a5542/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-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab h1:2QkjZIsXupsJbJIdSjjUOgWK3aEtzyuh2mPt3l/CkeU=
|
||||||
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
|
||||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
|
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
|
||||||
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue