/
transaction.go
129 lines (108 loc) · 3.16 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
package virtualeconomyTransaction
import (
"encoding/binary"
"encoding/hex"
"encoding/json"
"errors"
"time"
owcrypt "github.com/nbit99/go-owcrypt"
"github.com/tidwall/gjson"
)
type TxStruct struct {
TxType byte
To string
Amount uint64
Fee uint64
FeeScale uint16
Attachment string
}
type SignaturePubkey struct {
Signature []byte
PublicKey []byte
}
// 创建空交易单
// only transfer for now
func CreateEmptyTransaction(ts TxStruct) (string, error) {
timestamp := make([]byte, 8)
amount := make([]byte, 8)
fee := make([]byte, 8)
feeScale := make([]byte, 2)
attachmentLen := []byte{0x00, 0x00}
txBytes := []byte{}
txBytes = append(txBytes, ts.TxType)
binary.BigEndian.PutUint64(timestamp, uint64((time.Now().UnixNano()/1000)*1000))
txBytes = append(txBytes, timestamp...)
binary.BigEndian.PutUint64(amount, ts.Amount)
txBytes = append(txBytes, amount...)
binary.BigEndian.PutUint64(fee, ts.Fee)
txBytes = append(txBytes, fee...)
binary.BigEndian.PutUint16(feeScale, ts.FeeScale)
txBytes = append(txBytes, feeScale...)
recipient, err := DecodeCheck(ts.To)
if err != nil {
return "", errors.New("Trying to send VSYS to an invalid address!")
}
txBytes = append(txBytes, recipient...)
if ts.Attachment == "" {
txBytes = append(txBytes, attachmentLen...)
}
return hex.EncodeToString(txBytes), nil
}
// 对空交易单进行签名
func SignTransaction(emptyTrans string, prikey []byte) (*SignaturePubkey, error) {
txBytes, err := hex.DecodeString(emptyTrans)
if err != nil {
return nil, errors.New("Invalid empty transaction hex!")
}
sig, _, ret := owcrypt.Signature(prikey, nil, txBytes, owcrypt.ECC_CURVE_X25519)
if ret != owcrypt.SUCCESS {
return nil, errors.New("Failed to sign the transaction!")
}
pub := owcrypt.Point_mulBaseG(prikey, owcrypt.ECC_CURVE_ED25519)
pub, _ = owcrypt.CURVE25519_convert_Ed_to_X(pub)
// cpub, err := owcrypt.CURVE25519_convert_X_to_Ed(pub)
// if err != nil {
// return nil, errors.New("Failed to sign the transaction!")
// }
return &SignaturePubkey{
Signature: sig,
PublicKey: pub,
}, nil
}
// 对签名结果进行验证
func VerifyTransaction(emptyTrans string, sp *SignaturePubkey) bool {
txBytes, err := hex.DecodeString(emptyTrans)
if err != nil {
return false
}
pass := owcrypt.Verify(sp.PublicKey, nil, txBytes, sp.Signature, owcrypt.ECC_CURVE_X25519)
if pass != owcrypt.SUCCESS {
return false
}
return true
}
// 发送交易单
func CreateJSONRawForSendTransaction(emptyTrans string, sp *SignaturePubkey) (*gjson.Result, error) {
var (
body = make(map[string]interface{}, 0)
)
txBytes, err := hex.DecodeString(emptyTrans)
if err != nil {
return nil, errors.New("Invalid transaction hex string!")
}
ts, timestamp, err := TxStructDecode(txBytes)
if err != nil {
return nil, err
}
body["timestamp"] = timestamp
body["amount"] = ts.Amount
body["fee"] = ts.Fee
body["feeScale"] = ts.FeeScale
body["recipient"] = ts.To
body["senderPublicKey"] = Encode(sp.PublicKey, BitcoinAlphabet)
body["attachment"] = ts.Attachment
body["signature"] = Encode(sp.Signature, BitcoinAlphabet)
json, _ := json.Marshal(body)
ret := gjson.ParseBytes(json)
return &ret, nil
}