github.com/0chain/gosdk@v1.17.11/zcncore/transactionauth_base.go (about) 1 package zcncore 2 3 import ( 4 "encoding/json" 5 6 "github.com/0chain/errors" 7 "github.com/0chain/gosdk/core/node" 8 "github.com/0chain/gosdk/core/sys" 9 "github.com/0chain/gosdk/core/transaction" 10 "github.com/0chain/gosdk/core/zcncrypto" 11 "github.com/0chain/gosdk/zboxcore/client" 12 ) 13 14 type TransactionWithAuth struct { 15 t *Transaction 16 } 17 18 func (ta *TransactionWithAuth) Hash() string { 19 return ta.t.txnHash 20 } 21 22 func (ta *TransactionWithAuth) SetTransactionNonce(txnNonce int64) error { 23 return ta.t.SetTransactionNonce(txnNonce) 24 } 25 26 func (ta *TransactionWithAuth) getAuthorize() (*transaction.Transaction, error) { 27 ta.t.txn.PublicKey = _config.wallet.ClientKey 28 err := ta.t.txn.ComputeHashAndSign(SignFn) 29 if err != nil { 30 return nil, errors.Wrap(err, "signing error.") 31 } 32 33 jsonByte, err := json.Marshal(ta.t.txn) 34 if err != nil { 35 return nil, err 36 } 37 38 if sys.Authorize == nil { 39 return nil, errors.New("not_initialized", "no authorize func is set, define it in native code and set in sys") 40 } 41 authorize, err := sys.Authorize(string(jsonByte)) 42 if err != nil { 43 return nil, err 44 } 45 46 var txnResp transaction.Transaction 47 err = json.Unmarshal([]byte(authorize), &txnResp) 48 if err != nil { 49 return nil, errors.Wrap(err, "invalid json on auth response.") 50 } 51 // Verify the split key signed signature 52 ok, err := txnResp.VerifySigWith(client.GetClientPublicKey(), sys.VerifyWith) 53 if err != nil { 54 logging.Error("verification failed for txn from auth", err.Error()) 55 return nil, errAuthVerifyFailed 56 } 57 if !ok { 58 return nil, errAuthVerifyFailed 59 } 60 return &txnResp, nil 61 } 62 63 func (ta *TransactionWithAuth) completeTxn(status int, out string, err error) { 64 // do error code translation 65 if status != StatusSuccess { 66 switch err { 67 case errNetwork: 68 status = StatusNetworkError 69 case errUserRejected: 70 status = StatusRejectedByUser 71 case errAuthVerifyFailed: 72 status = StatusAuthVerifyFailed 73 case errAuthTimeout: 74 status = StatusAuthTimeout 75 } 76 } 77 ta.t.completeTxn(status, out, err) //nolint 78 } 79 80 func verifyFn(signature, msgHash, publicKey string) (bool, error) { 81 v := zcncrypto.NewSignatureScheme(_config.chain.SignatureScheme) 82 err := v.SetPublicKey(publicKey) 83 if err != nil { 84 return false, err 85 } 86 87 ok, err := v.Verify(signature, msgHash) 88 if err != nil || !ok { 89 return false, errors.New("", `{"error": "signature_mismatch"}`) 90 } 91 return true, nil 92 } 93 94 func (ta *TransactionWithAuth) sign(otherSig string) error { 95 ta.t.txn.ComputeHashData() 96 97 sig, err := AddSignature(_config.wallet.Keys[0].PrivateKey, otherSig, ta.t.txn.Hash) 98 if err != nil { 99 return err 100 } 101 ta.t.txn.Signature = sig 102 return nil 103 } 104 105 func (ta *TransactionWithAuth) submitTxn() { 106 nonce := ta.t.txn.TransactionNonce 107 if nonce < 1 { 108 nonce = node.Cache.GetNextNonce(ta.t.txn.ClientID) 109 } else { 110 node.Cache.Set(ta.t.txn.ClientID, nonce) 111 } 112 ta.t.txn.TransactionNonce = nonce 113 authTxn, err := ta.getAuthorize() 114 if err != nil { 115 logging.Error("get auth error for send, err: ", err.Error()) 116 ta.completeTxn(StatusAuthError, "", err) 117 return 118 } 119 120 // Use the timestamp from auth and sign 121 ta.t.txn.CreationDate = authTxn.CreationDate 122 ta.t.txn.Signature = authTxn.Signature 123 ta.t.submitTxn() 124 } 125 126 func (ta *TransactionWithAuth) StoreData(data string) error { 127 go func() { 128 ta.t.txn.TransactionType = transaction.TxnTypeData 129 ta.t.txn.TransactionData = data 130 ta.submitTxn() 131 }() 132 return nil 133 } 134 135 // ExecuteFaucetSCWallet impements the Faucet Smart contract for a given wallet 136 func (ta *TransactionWithAuth) ExecuteFaucetSCWallet(walletStr string, methodName string, input []byte) error { 137 w, err := ta.t.createFaucetSCWallet(walletStr, methodName, input) 138 if err != nil { 139 return err 140 } 141 go func() { 142 nonce := ta.t.txn.TransactionNonce 143 if nonce < 1 { 144 nonce = node.Cache.GetNextNonce(ta.t.txn.ClientID) 145 } else { 146 node.Cache.Set(ta.t.txn.ClientID, nonce) 147 } 148 ta.t.txn.TransactionNonce = nonce 149 err = ta.t.txn.ComputeHashAndSignWithWallet(signWithWallet, w) 150 if err != nil { 151 return 152 } 153 ta.submitTxn() 154 }() 155 return nil 156 } 157 158 func (ta *TransactionWithAuth) SetTransactionCallback(cb TransactionCallback) error { 159 return ta.t.SetTransactionCallback(cb) 160 } 161 162 func (ta *TransactionWithAuth) SetTransactionHash(hash string) error { 163 return ta.t.SetTransactionHash(hash) 164 } 165 166 func (ta *TransactionWithAuth) GetTransactionHash() string { 167 return ta.t.GetTransactionHash() 168 } 169 170 func (ta *TransactionWithAuth) Verify() error { 171 return ta.t.Verify() 172 } 173 174 func (ta *TransactionWithAuth) GetVerifyOutput() string { 175 return ta.t.GetVerifyOutput() 176 } 177 178 func (ta *TransactionWithAuth) GetTransactionError() string { 179 return ta.t.GetTransactionError() 180 } 181 182 func (ta *TransactionWithAuth) GetVerifyError() string { 183 return ta.t.GetVerifyError() 184 } 185 186 func (ta *TransactionWithAuth) Output() []byte { 187 return []byte(ta.t.txnOut) 188 } 189 190 // GetTransactionNonce returns nonce 191 func (ta *TransactionWithAuth) GetTransactionNonce() int64 { 192 return ta.t.txn.TransactionNonce 193 } 194 195 // 196 // miner sc 197 // 198 199 // RegisterMultiSig register a multisig wallet with the SC. 200 func (ta *TransactionWithAuth) RegisterMultiSig(walletstr string, mswallet string) error { 201 return errors.New("", "not implemented") 202 } 203 204 // 205 // Storage SC 206 //