github.com/adnan-c/fabric_e2e_couchdb@v0.6.1-preview.0.20170228180935-21ce6b23cf91/common/util/utils.go (about) 1 /* 2 Copyright IBM Corp. 2016 All Rights Reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package util 18 19 import ( 20 "crypto/rand" 21 "fmt" 22 "io" 23 "math/big" 24 "strings" 25 "time" 26 27 "github.com/golang/protobuf/ptypes/timestamp" 28 "github.com/hyperledger/fabric/bccsp" 29 "github.com/hyperledger/fabric/bccsp/factory" 30 "github.com/hyperledger/fabric/common/metadata" 31 ) 32 33 type alg struct { 34 hashFun func([]byte) string 35 } 36 37 const defaultAlg = "sha256" 38 39 var availableIDgenAlgs = map[string]alg{ 40 defaultAlg: {GenerateIDfromTxSHAHash}, 41 } 42 43 // ComputeSHA256 returns SHA2-256 on data 44 func ComputeSHA256(data []byte) (hash []byte) { 45 hash, err := factory.GetDefault().Hash(data, &bccsp.SHA256Opts{}) 46 if err != nil { 47 panic(fmt.Errorf("Failed computing SHA256 on [% x]", data)) 48 } 49 return 50 } 51 52 // ComputeSHA3256 returns SHA3-256 on data 53 func ComputeSHA3256(data []byte) (hash []byte) { 54 hash, err := factory.GetDefault().Hash(data, &bccsp.SHA3_256Opts{}) 55 if err != nil { 56 panic(fmt.Errorf("Failed computing SHA3_256 on [% x]", data)) 57 } 58 return 59 } 60 61 // GenerateBytesUUID returns a UUID based on RFC 4122 returning the generated bytes 62 func GenerateBytesUUID() []byte { 63 uuid := make([]byte, 16) 64 _, err := io.ReadFull(rand.Reader, uuid) 65 if err != nil { 66 panic(fmt.Sprintf("Error generating UUID: %s", err)) 67 } 68 69 // variant bits; see section 4.1.1 70 uuid[8] = uuid[8]&^0xc0 | 0x80 71 72 // version 4 (pseudo-random); see section 4.1.3 73 uuid[6] = uuid[6]&^0xf0 | 0x40 74 75 return uuid 76 } 77 78 // GenerateIntUUID returns a UUID based on RFC 4122 returning a big.Int 79 func GenerateIntUUID() *big.Int { 80 uuid := GenerateBytesUUID() 81 z := big.NewInt(0) 82 return z.SetBytes(uuid) 83 } 84 85 // GenerateUUID returns a UUID based on RFC 4122 86 func GenerateUUID() string { 87 uuid := GenerateBytesUUID() 88 return idBytesToStr(uuid) 89 } 90 91 // CreateUtcTimestamp returns a google/protobuf/Timestamp in UTC 92 func CreateUtcTimestamp() *timestamp.Timestamp { 93 now := time.Now().UTC() 94 secs := now.Unix() 95 nanos := int32(now.UnixNano() - (secs * 1000000000)) 96 return &(timestamp.Timestamp{Seconds: secs, Nanos: nanos}) 97 } 98 99 //GenerateHashFromSignature returns a hash of the combined parameters 100 func GenerateHashFromSignature(path string, args []byte) []byte { 101 return ComputeSHA256(args) 102 } 103 104 // GenerateIDfromTxSHAHash generates SHA256 hash using Tx payload 105 func GenerateIDfromTxSHAHash(payload []byte) string { 106 return fmt.Sprintf("%x", ComputeSHA256(payload)) 107 } 108 109 // GenerateIDWithAlg generates an ID using a custom algorithm 110 func GenerateIDWithAlg(customIDgenAlg string, payload []byte) (string, error) { 111 if customIDgenAlg == "" { 112 customIDgenAlg = defaultAlg 113 } 114 var alg = availableIDgenAlgs[customIDgenAlg] 115 if alg.hashFun != nil { 116 return alg.hashFun(payload), nil 117 } 118 return "", fmt.Errorf("Wrong ID generation algorithm was given: %s", customIDgenAlg) 119 } 120 121 func idBytesToStr(id []byte) string { 122 return fmt.Sprintf("%x-%x-%x-%x-%x", id[0:4], id[4:6], id[6:8], id[8:10], id[10:]) 123 } 124 125 // FindMissingElements identifies the elements of the first slice that are not present in the second 126 // The second slice is expected to be a subset of the first slice 127 func FindMissingElements(all []string, some []string) (delta []string) { 128 all: 129 for _, v1 := range all { 130 for _, v2 := range some { 131 if strings.Compare(v1, v2) == 0 { 132 continue all 133 } 134 } 135 delta = append(delta, v1) 136 } 137 return 138 } 139 140 // ToChaincodeArgs converts string args to []byte args 141 func ToChaincodeArgs(args ...string) [][]byte { 142 bargs := make([][]byte, len(args)) 143 for i, arg := range args { 144 bargs[i] = []byte(arg) 145 } 146 return bargs 147 } 148 149 // ArrayToChaincodeArgs converts array of string args to array of []byte args 150 func ArrayToChaincodeArgs(args []string) [][]byte { 151 bargs := make([][]byte, len(args)) 152 for i, arg := range args { 153 bargs[i] = []byte(arg) 154 } 155 return bargs 156 } 157 158 const testchainid = "testchainid" 159 const testorgid = "**TEST_ORGID**" 160 161 //GetTestChainID returns the CHAINID constant in use by orderer 162 func GetTestChainID() string { 163 return testchainid 164 } 165 166 //GetTestOrgID returns the ORGID constant in use by gossip join message 167 func GetTestOrgID() string { 168 return testorgid 169 } 170 171 //GetSysCCVersion returns the version of all system chaincodes 172 //This needs to be revisited on policies around system chaincode 173 //"upgrades" from user and relationship with "fabric" upgrade. For 174 //now keep it simple and use the fabric's version stamp 175 func GetSysCCVersion() string { 176 return metadata.Version 177 } 178 179 // ConcatenateBytes is useful for combining multiple arrays of bytes, especially for 180 // signatures or digests over multiple fields 181 func ConcatenateBytes(data ...[]byte) []byte { 182 finalLength := 0 183 for _, slice := range data { 184 finalLength += len(slice) 185 } 186 result := make([]byte, finalLength) 187 last := 0 188 for _, slice := range data { 189 for i := range slice { 190 result[i+last] = slice[i] 191 } 192 last += len(slice) 193 } 194 return result 195 }