/
parseTx.go
123 lines (115 loc) · 3.58 KB
/
parseTx.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
package mandosjsonparse
import (
"errors"
"fmt"
mj "github.com/ElrondNetwork/arwen-wasm-vm/mandos-go/json/model"
oj "github.com/ElrondNetwork/arwen-wasm-vm/mandos-go/orderedjson"
)
func (p *Parser) processTx(txType mj.TransactionType, blrRaw oj.OJsonObject) (*mj.Transaction, error) {
bltMap, isMap := blrRaw.(*oj.OJsonMap)
if !isMap {
return nil, errors.New("unmarshalled transaction is not a map")
}
blt := mj.Transaction{
Type: txType,
Value: mj.JSONBigIntZero(),
ESDTValue: nil,
}
var err error
for _, kvp := range bltMap.OrderedKV {
switch kvp.Key {
case "nonce":
blt.Nonce, err = p.processUint64(kvp.Value)
if err != nil {
return nil, fmt.Errorf("invalid transaction nonce: %w", err)
}
case "from":
if !txType.HasSender() {
return nil, errors.New("`from` not allowed in transaction, it is always the zero address")
}
fromStr, err := p.parseString(kvp.Value)
if err != nil {
return nil, fmt.Errorf("invalid transaction from: %w", err)
}
var fromErr error
blt.From, fromErr = p.parseAccountAddress(fromStr)
if fromErr != nil {
return nil, fromErr
}
case "to":
toStr, err := p.parseString(kvp.Value)
if err != nil {
return nil, fmt.Errorf("invalid transaction to: %w", err)
}
if txType == mj.ScDeploy {
if len(toStr) > 0 {
return nil, errors.New("transaction to field not allowed for scDeploy transactions")
}
} else {
blt.To, err = p.parseAccountAddress(toStr)
if err != nil {
return nil, err
}
}
case "function":
blt.Function, err = p.parseString(kvp.Value)
if err != nil {
return nil, fmt.Errorf("invalid transaction function: %w", err)
}
if !txType.HasFunction() && len(blt.Function) > 0 {
return nil, errors.New("transaction function field not allowed in this context")
}
case "value":
if !txType.HasValue() {
return nil, errors.New("`value` not allowed in this context")
}
blt.Value, err = p.processBigInt(kvp.Value, bigIntUnsignedBytes)
if err != nil {
return nil, fmt.Errorf("invalid transaction value: %w", err)
}
case "esdt":
if !txType.HasESDT() {
return nil, errors.New("`esdt` not allowed in this context")
}
blt.ESDTValue, err = p.processTxESDT(kvp.Value)
if err != nil {
return nil, fmt.Errorf("invalid transaction ESDT value: %w", err)
}
case "arguments":
blt.Arguments, err = p.parseSubTreeList(kvp.Value)
if err != nil {
return nil, fmt.Errorf("invalid transaction arguments: %w", err)
}
if txType == mj.Transfer && len(blt.Arguments) > 0 {
return nil, errors.New("function arguments not allowed for transfer transactions")
}
case "contractCode":
blt.Code, err = p.processStringAsByteArray(kvp.Value)
if err != nil {
return nil, fmt.Errorf("invalid transaction contract code: %w", err)
}
if txType != mj.ScDeploy && len(blt.Code.Value) > 0 {
return nil, errors.New("transaction contractCode field only allowed int scDeploy transactions")
}
case "gasPrice":
if !txType.HasGas() {
return nil, errors.New("`gasPrice` not allowed in this context")
}
blt.GasPrice, err = p.processUint64(kvp.Value)
if err != nil {
return nil, fmt.Errorf("invalid transaction gasPrice: %w", err)
}
case "gasLimit":
if !txType.HasGas() {
return nil, errors.New("`gasLimit` not allowed in this context")
}
blt.GasLimit, err = p.processUint64(kvp.Value)
if err != nil {
return nil, fmt.Errorf("invalid transaction gasLimit: %w", err)
}
default:
return nil, fmt.Errorf("unknown field in transaction: %s", kvp.Key)
}
}
return &blt, nil
}