-
Notifications
You must be signed in to change notification settings - Fork 78
/
txBuilder.go
132 lines (127 loc) · 3.18 KB
/
txBuilder.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
package request
import (
"errors"
"fmt"
"strconv"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neo-go/pkg/io"
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
"github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neo-go/pkg/vm/emit"
"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
)
// expandArrayIntoScript pushes all FuncParam parameters from the given array
// into the given buffer in reverse order.
func expandArrayIntoScript(script *io.BinWriter, slice []Param) error {
for j := len(slice) - 1; j >= 0; j-- {
fp, err := slice[j].GetFuncParam()
if err != nil {
return err
}
switch fp.Type {
case smartcontract.ByteArrayType:
str, err := fp.Value.GetBytesBase64()
if err != nil {
return err
}
emit.Bytes(script, str)
case smartcontract.SignatureType:
str, err := fp.Value.GetBytesHex()
if err != nil {
return err
}
emit.Bytes(script, str)
case smartcontract.StringType:
str, err := fp.Value.GetString()
if err != nil {
return err
}
emit.String(script, str)
case smartcontract.Hash160Type:
hash, err := fp.Value.GetUint160FromHex()
if err != nil {
return err
}
emit.Bytes(script, hash.BytesBE())
case smartcontract.Hash256Type:
hash, err := fp.Value.GetUint256()
if err != nil {
return err
}
emit.Bytes(script, hash.BytesBE())
case smartcontract.PublicKeyType:
str, err := fp.Value.GetString()
if err != nil {
return err
}
key, err := keys.NewPublicKeyFromString(string(str))
if err != nil {
return err
}
emit.Bytes(script, key.Bytes())
case smartcontract.IntegerType:
val, err := fp.Value.GetInt()
if err != nil {
return err
}
emit.Int(script, int64(val))
case smartcontract.BoolType:
str, err := fp.Value.GetString()
if err != nil {
return err
}
switch str {
case "true":
emit.Int(script, 1)
case "false":
emit.Int(script, 0)
default:
return errors.New("wrong boolean value")
}
case smartcontract.ArrayType:
val, err := fp.Value.GetArray()
if err != nil {
return err
}
err = expandArrayIntoScript(script, val)
if err != nil {
return err
}
emit.Int(script, int64(len(val)))
emit.Opcodes(script, opcode.PACK)
default:
return fmt.Errorf("parameter type %v is not supported", fp.Type)
}
}
return nil
}
// CreateFunctionInvocationScript creates a script to invoke given contract with
// given parameters.
func CreateFunctionInvocationScript(contract util.Uint160, params Params) ([]byte, error) {
script := io.NewBufBinWriter()
for i := len(params) - 1; i >= 0; i-- {
switch params[i].Type {
case StringT:
emit.String(script.BinWriter, params[i].String())
case NumberT:
num, err := params[i].GetInt()
if err != nil {
return nil, err
}
emit.String(script.BinWriter, strconv.Itoa(num))
case ArrayT:
slice, err := params[i].GetArray()
if err != nil {
return nil, err
}
err = expandArrayIntoScript(script.BinWriter, slice)
if err != nil {
return nil, err
}
emit.Int(script.BinWriter, int64(len(slice)))
emit.Opcodes(script.BinWriter, opcode.PACK)
}
}
emit.AppCall(script.BinWriter, contract)
return script.Bytes(), nil
}