github.com/Finschia/finschia-sdk@v0.48.1/types/address/hash.go (about) 1 package address 2 3 import ( 4 "bytes" 5 "crypto/sha256" 6 "fmt" 7 "sort" 8 9 "github.com/Finschia/finschia-sdk/internal/conv" 10 "github.com/Finschia/finschia-sdk/types/errors" 11 ) 12 13 // Len is the length of base addresses 14 const Len = sha256.Size 15 16 // Addressable represents any type from which we can derive an address. 17 type Addressable interface { 18 Address() []byte 19 } 20 21 // Hash creates a new address from address type and key 22 func Hash(typ string, key []byte) []byte { 23 hasher := sha256.New() 24 _, err := hasher.Write(conv.UnsafeStrToBytes(typ)) 25 // the error always nil, it's here only to satisfy the io.Writer interface 26 errors.AssertNil(err) 27 th := hasher.Sum(nil) 28 29 hasher.Reset() 30 _, err = hasher.Write(th) 31 errors.AssertNil(err) 32 _, err = hasher.Write(key) 33 errors.AssertNil(err) 34 return hasher.Sum(nil) 35 } 36 37 // Compose creates a new address based on sub addresses. 38 func Compose(typ string, subAddresses []Addressable) ([]byte, error) { 39 as := make([][]byte, len(subAddresses)) 40 totalLen := 0 41 var err error 42 for i := range subAddresses { 43 a := subAddresses[i].Address() 44 as[i], err = LengthPrefix(a) 45 if err != nil { 46 return nil, fmt.Errorf("not compatible sub-adddress=%v at index=%d [%w]", a, i, err) 47 } 48 totalLen += len(as[i]) 49 } 50 51 sort.Slice(as, func(i, j int) bool { return bytes.Compare(as[i], as[j]) <= 0 }) 52 key := make([]byte, totalLen) 53 offset := 0 54 for i := range as { 55 copy(key[offset:], as[i]) 56 offset += len(as[i]) 57 } 58 return Hash(typ, key), nil 59 } 60 61 // Module is a specialized version of a composed address for modules. Each module account 62 // is constructed from a module name and module account key. 63 func Module(moduleName string, key []byte) []byte { 64 mKey := append([]byte(moduleName), 0) 65 return Hash("module", append(mKey, key...)) 66 } 67 68 // Derive derives a new address from the main `address` and a derivation `key`. 69 func Derive(address []byte, key []byte) []byte { 70 return Hash(conv.UnsafeBytesToStr(address), key) 71 }