-
Notifications
You must be signed in to change notification settings - Fork 7
/
transaction.go
185 lines (159 loc) · 3.77 KB
/
transaction.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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
package near
import (
"crypto"
"crypto/ed25519"
"crypto/rand"
"crypto/sha256"
"math/big"
"github.com/aurora-is-near/near-api-go/utils"
"github.com/near/borsh-go"
)
// AccessKey encodes a NEAR access key.
type AccessKey struct {
Nonce uint64
Permission AccessKeyPermission
}
// AccessKeyPermission encodes a NEAR access key permission.
type AccessKeyPermission struct {
Enum borsh.Enum `borsh_enum:"true"` // treat struct as complex enum when serializing/deserializing
FunctionCall FunctionCallPermission
FullAccess borsh.Enum
}
// FunctionCallPermission encodes a NEAR function call permission (an access
// key permission).
type FunctionCallPermission struct {
Allowance *big.Int
ReceiverId string
MethodNames []string
}
func fullAccessKey() AccessKey {
return AccessKey{
Nonce: 0,
Permission: AccessKeyPermission{
Enum: 1,
FullAccess: 1,
},
}
}
// A Transaction encodes a NEAR transaction.
type Transaction struct {
SignerID string
PublicKey utils.PublicKey
Nonce uint64
ReceiverID string
BlockHash [32]byte
Actions []Action
}
// Action simulates an enum for Borsh encoding.
type Action struct {
Enum borsh.Enum `borsh_enum:"true"` // treat struct as complex enum when serializing/deserializing
CreateAccount borsh.Enum
DeployContract DeployContract
FunctionCall FunctionCall
Transfer Transfer
Stake Stake
AddKey AddKey
DeleteKey DeleteKey
DeleteAccount DeleteAccount
}
// The DeployContract action.
type DeployContract struct {
Code []byte
}
// The FunctionCall action.
type FunctionCall struct {
MethodName string
Args []byte
Gas uint64
Deposit big.Int // u128
}
// The Transfer action.
type Transfer struct {
Deposit big.Int // u128
}
// The Stake action.
type Stake struct {
Stake big.Int // u128
PublicKey utils.PublicKey
}
// The AddKey action.
type AddKey struct {
PublicKey utils.PublicKey
AccessKey AccessKey
}
// The DeleteKey action.
type DeleteKey struct {
PublicKey utils.PublicKey
}
// The DeleteAccount action.
type DeleteAccount struct {
BeneficiaryID string
}
// A Signature used for signing transaction.
type Signature struct {
KeyType uint8
Data [64]byte
}
// SignedTransaction encodes signed transactions for NEAR.
type SignedTransaction struct {
Transaction Transaction
Signature Signature
}
func createTransaction(
signerID string,
publicKey utils.PublicKey,
receiverID string,
nonce uint64,
blockHash []byte,
actions []Action,
) *Transaction {
var tx Transaction
tx.SignerID = signerID
tx.PublicKey = publicKey
tx.ReceiverID = receiverID
tx.Nonce = nonce
copy(tx.BlockHash[:], blockHash)
tx.Actions = actions
return &tx
}
func signTransactionObject(
tx *Transaction,
privKey ed25519.PrivateKey,
accountID string,
) (txHash []byte, signedTx *SignedTransaction, err error) {
buf, err := borsh.Serialize(*tx)
if err != nil {
return nil, nil, err
}
hash := sha256.Sum256(buf)
sig, err := privKey.Sign(rand.Reader, hash[:], crypto.Hash(0))
if err != nil {
return nil, nil, err
}
var signature Signature
signature.KeyType = utils.ED25519
copy(signature.Data[:], sig)
var stx SignedTransaction
stx.Transaction = *tx
stx.Signature = signature
return hash[:], &stx, nil
}
func signTransaction(
receiverID string,
nonce uint64,
actions []Action,
blockHash []byte,
publicKey ed25519.PublicKey,
privKey ed25519.PrivateKey,
accountID string,
) (txHash []byte, signedTx *SignedTransaction, err error) {
// create transaction
tx := createTransaction(accountID, utils.PublicKeyFromEd25519(publicKey),
receiverID, nonce, blockHash, actions)
// sign transaction object
txHash, signedTx, err = signTransactionObject(tx, privKey, accountID)
if err != nil {
return nil, nil, err
}
return txHash, signedTx, nil
}