github.com/0chain/gosdk@v1.17.11/zcncore/mswallet.go (about) 1 //go:build !mobile 2 // +build !mobile 3 4 package zcncore 5 6 import ( 7 "encoding/json" 8 "fmt" 9 10 "github.com/0chain/errors" 11 "github.com/0chain/gosdk/core/encryption" 12 "github.com/0chain/gosdk/core/zcncrypto" 13 ) 14 15 //MSVote -- this should mimic the type Vote defined in MultiSig SC 16 type MSVote struct { 17 ProposalID string `json:"proposal_id"` 18 19 // Client ID in transfer is that of the multi-sig wallet, not the signer. 20 Transfer MSTransfer `json:"transfer"` 21 22 Signature string `json:"signature"` 23 } 24 25 //MSTransfer - a data structure to hold state transfer from one client to another 26 type MSTransfer struct { 27 ClientID string `json:"from"` 28 ToClientID string `json:"to"` 29 Amount uint64 `json:"amount"` 30 } 31 32 // MultisigSCWallet --this should mimic MultisigWallet definition in MultiSig SC 33 type MultisigSCWallet struct { 34 ClientID string `json:"client_id"` 35 SignatureScheme string `json:"signature_scheme"` 36 PublicKey string `json:"public_key"` 37 38 SignerThresholdIDs []string `json:"signer_threshold_ids"` 39 SignerPublicKeys []string `json:"signer_public_keys"` 40 41 NumRequired int `json:"num_required"` 42 } 43 44 // MSWallet Client data necessary for a multi-sig wallet. 45 type MSWallet struct { 46 Id int `json:"id"` 47 SignatureScheme string `json:"signature_scheme"` 48 GroupClientID string `json:"group_client_id"` 49 GroupKey zcncrypto.SignatureScheme `json:"group_key"` 50 SignerClientIDs []string `json:"sig_client_ids"` 51 SignerKeys []zcncrypto.SignatureScheme `json:"signer_keys"` 52 T int `json:"threshold"` 53 N int `json:"num_subkeys"` 54 } 55 56 func (msw *MSWallet) UnmarshalJSON(data []byte) error { 57 m := &struct { 58 Id int `json:"id"` 59 SignatureScheme string `json:"signature_scheme"` 60 GroupClientID string `json:"group_client_id"` 61 SignerClientIDs []string `json:"sig_client_ids"` 62 T int `json:"threshold"` 63 N int `json:"num_subkeys"` 64 GroupKey interface{} `json:"group_key"` 65 SignerKeys interface{} `json:"signer_keys"` 66 }{} 67 68 if err := json.Unmarshal(data, &m); err != nil { 69 return err 70 } 71 72 msw.Id = m.Id 73 msw.SignatureScheme = m.SignatureScheme 74 msw.GroupClientID = m.GroupClientID 75 msw.SignerClientIDs = m.SignerClientIDs 76 msw.T = m.T 77 msw.N = m.N 78 79 if m.GroupKey != nil { 80 groupKeyBuf, err := json.Marshal(m.GroupKey) 81 if err != nil { 82 return err 83 } 84 85 ss := zcncrypto.NewSignatureScheme(m.SignatureScheme) 86 87 if err := json.Unmarshal(groupKeyBuf, &ss); err != nil { 88 return err 89 } 90 91 msw.GroupKey = ss 92 } 93 94 signerKeys, err := zcncrypto.UnmarshalSignatureSchemes(m.SignatureScheme, m.SignerKeys) 95 if err != nil { 96 return err 97 } 98 msw.SignerKeys = signerKeys 99 100 return nil 101 } 102 103 // Marshal returns json string 104 func (msw *MSWallet) Marshal() (string, error) { 105 msws, err := json.Marshal(msw) 106 if err != nil { 107 return "", errors.New("", "Invalid Wallet") 108 } 109 return string(msws), nil 110 } 111 112 //GetMultisigPayload given a multisig wallet as a string, makes a multisig wallet payload to register 113 func GetMultisigPayload(mswstr string) (interface{}, error) { 114 var msw MSWallet 115 err := json.Unmarshal([]byte(mswstr), &msw) 116 117 if err != nil { 118 fmt.Printf("Error while creating multisig wallet from input:\n%v", mswstr) 119 return "", err 120 } 121 var signerThresholdIDs []string 122 var signerPublicKeys []string 123 124 for _, scheme := range msw.SignerKeys { 125 signerThresholdIDs = append(signerThresholdIDs, scheme.GetID()) 126 signerPublicKeys = append(signerPublicKeys, scheme.GetPublicKey()) 127 } 128 129 msscw := MultisigSCWallet{ 130 ClientID: msw.GroupClientID, 131 SignatureScheme: msw.SignatureScheme, 132 PublicKey: msw.GroupKey.GetPublicKey(), 133 134 SignerThresholdIDs: signerThresholdIDs, 135 SignerPublicKeys: signerPublicKeys, 136 137 NumRequired: msw.T, 138 } 139 140 return msscw, nil 141 } 142 143 //GetMultisigVotePayload given a multisig vote as a string, makes a multisig vote payload to register 144 func GetMultisigVotePayload(msvstr string) (interface{}, error) { 145 var msv MSVote 146 err := json.Unmarshal([]byte(msvstr), &msv) 147 148 if err != nil { 149 fmt.Printf("Error while creating multisig wallet from input:\n%v", msvstr) 150 return nil, err 151 } 152 153 //Marshalling and unmarshalling validates the string. Do any additional veirfication here. 154 155 return msv, nil 156 157 } 158 159 // CreateMSVote create a vote for multisig 160 func CreateMSVote(proposal, grpClientID, signerWalletstr, toClientID string, token uint64) (string, error) { 161 if proposal == "" || grpClientID == "" || toClientID == "" || signerWalletstr == "" { 162 return "", errors.New("", "proposal or groupClient or signer wallet or toClientID cannot be empty") 163 } 164 165 if token < 1 { 166 return "", errors.New("", "Token cannot be less than 1") 167 } 168 169 signerWallet, err := getWallet(signerWalletstr) 170 if err != nil { 171 fmt.Printf("Error while parsing the signer wallet. %v", err) 172 return "", err 173 } 174 175 //Note: Is this honored by multisig sc? 176 transfer := MSTransfer{ 177 ClientID: grpClientID, 178 ToClientID: toClientID, 179 Amount: token, 180 } 181 182 buff, _ := json.Marshal(transfer) 183 hash := encryption.Hash(buff) 184 185 sigScheme := zcncrypto.NewSignatureScheme(_config.chain.SignatureScheme) 186 if err := sigScheme.SetPrivateKey(signerWallet.Keys[0].PrivateKey); err != nil { 187 return "", err 188 } 189 190 sig, err := sigScheme.Sign(hash) 191 if err != nil { 192 return "", err 193 } 194 195 vote := MSVote{ 196 Transfer: transfer, 197 ProposalID: proposal, 198 Signature: sig, 199 } 200 201 vbytes, err := json.Marshal(vote) 202 if err != nil { 203 fmt.Printf("error in marshalling vote %v", vote) 204 return "", err 205 } 206 return string(vbytes), nil 207 }