-
Notifications
You must be signed in to change notification settings - Fork 29
/
txn.go
140 lines (119 loc) · 4.82 KB
/
txn.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
package transaction
import (
"context"
"encoding/json"
"fmt"
"github.com/0chain/gosdk/core/util"
"github.com/0chain/gosdk/zcncore"
"github.com/0chain/gosdk/zmagmacore/chain"
"github.com/0chain/gosdk/zmagmacore/errors"
"github.com/0chain/gosdk/zmagmacore/node"
ctime "github.com/0chain/gosdk/zmagmacore/time"
)
type (
// Transaction entity that encapsulates the transaction related data and metadata.
Transaction struct {
Hash string `json:"hash,omitempty"`
Version string `json:"version,omitempty"`
ClientID string `json:"client_id,omitempty"`
PublicKey string `json:"public_key,omitempty"`
ToClientID string `json:"to_client_id,omitempty"`
ChainID string `json:"chain_id,omitempty"`
TransactionData string `json:"transaction_data,omitempty"`
Value int64 `json:"transaction_value,omitempty"`
Signature string `json:"signature,omitempty"`
CreationDate ctime.Timestamp `json:"creation_date,omitempty"`
TransactionType int `json:"transaction_type,omitempty"`
TransactionOutput string `json:"transaction_output,omitempty"`
OutputHash string `json:"txn_output_hash"`
scheme zcncore.TransactionScheme
callBack *callback
}
)
// NewTransactionEntity creates Transaction with initialized fields.
// Sets version, client ID, creation date, public key and creates internal zcncore.TransactionScheme.
func NewTransactionEntity() (*Transaction, error) {
txn := &Transaction{
Version: "1.0",
ClientID: node.ID(),
CreationDate: ctime.Now(),
ChainID: chain.GetServerChain().ID,
PublicKey: node.PublicKey(),
callBack: newCallBack(),
}
zcntxn, err := zcncore.NewTransaction(txn.callBack, 0, 0)
if err != nil {
return nil, err
}
txn.scheme = zcntxn
return txn, nil
}
// ExecuteSmartContract executes function of smart contract with provided address.
//
// Returns hash of executed transaction.
func (t *Transaction) ExecuteSmartContract(ctx context.Context, address, funcName, input string,
val uint64) (string, error) {
const errCode = "transaction_send"
_, err := t.scheme.ExecuteSmartContract(address, funcName, input, val)
if err != nil {
msg := fmt.Sprintf("error while sending txn: %v", err)
return "", errors.New(errCode, msg)
}
if err := t.callBack.waitCompleteCall(ctx); err != nil {
msg := fmt.Sprintf("error while sending txn: %v", err)
return "", errors.New(errCode, msg)
}
t.Hash = t.scheme.GetTransactionHash()
if len(t.scheme.GetTransactionError()) > 0 {
return "", errors.New(errCode, t.scheme.GetTransactionError())
}
return t.Hash, nil
}
type (
verifyOutput struct {
Confirmation confirmation `json:"confirmation"`
}
// confirmation represents the acceptance that a transaction is included into the blockchain.
confirmation struct {
Version string `json:"version"`
Hash string `json:"hash"`
BlockHash string `json:"block_hash"`
PreviousBlockHash string `json:"previous_block_hash"`
Transaction *Transaction `json:"txn,omitempty"`
CreationDate ctime.Timestamp `json:"creation_date"`
MinerID string `json:"miner_id"`
Round int64 `json:"round"`
Status int `json:"transaction_status"`
RoundRandomSeed int64 `json:"round_random_seed"`
MerkleTreeRoot string `json:"merkle_tree_root"`
MerkleTreePath *util.MTPath `json:"merkle_tree_path"`
ReceiptMerkleTreeRoot string `json:"receipt_merkle_tree_root"`
ReceiptMerkleTreePath *util.MTPath `json:"receipt_merkle_tree_path"`
}
)
// Verify checks including of transaction in the blockchain.
func (t *Transaction) Verify(ctx context.Context) error {
const errCode = "transaction_verify"
if err := t.scheme.SetTransactionHash(t.Hash); err != nil {
return err
}
err := t.scheme.Verify()
if err != nil {
msg := fmt.Sprintf("error while verifying txn: %v; txn hash: %s", err, t.scheme.GetTransactionHash())
return errors.New(errCode, msg)
}
if err := t.callBack.waitVerifyCall(ctx); err != nil {
msg := fmt.Sprintf("error while verifying txn: %v; txn hash: %s", err, t.scheme.GetTransactionHash())
return errors.New(errCode, msg)
}
vo := new(verifyOutput)
if err := json.Unmarshal([]byte(t.scheme.GetVerifyOutput()), vo); err != nil {
return errors.New(errCode, "error while unmarshalling confirmation: "+err.Error()+", json: "+t.scheme.GetVerifyOutput())
}
if vo.Confirmation.Transaction != nil {
t.TransactionOutput = vo.Confirmation.Transaction.TransactionOutput
} else {
return errors.New(errCode, "got invalid confirmation (missing transaction)")
}
return nil
}