This repository has been archived by the owner on Jan 25, 2021. It is now read-only.
/
deployment.go
135 lines (110 loc) · 3.67 KB
/
deployment.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
package neoutils
import (
"bytes"
"encoding/binary"
"io"
"log"
"github.com/o3labs/neo-utils/neoutils/smartcontract"
)
func WriteVarUint(w io.Writer, val uint64) error {
if val < 0xfd {
binary.Write(w, binary.LittleEndian, uint8(val))
return nil
}
if val < 0xFFFF {
binary.Write(w, binary.LittleEndian, byte(0xfd))
binary.Write(w, binary.LittleEndian, uint16(val))
return nil
}
if val < 0xFFFFFFFF {
binary.Write(w, binary.LittleEndian, byte(0xfe))
binary.Write(w, binary.LittleEndian, uint32(val))
return nil
}
binary.Write(w, binary.LittleEndian, byte(0xff))
binary.Write(w, binary.LittleEndian, val)
return nil
}
type SmartContractInfo struct {
AVMHEX string
Name string
Version string
Author string
Email string
Description string
Properties smartcontract.Properties
InputTypes []smartcontract.ParameterType
ReturnType smartcontract.ParameterType
}
func (s *SmartContractInfo) GetScriptHash() string {
address := VMCodeToNEOAddress(hex2bytes(s.AVMHEX))
scripthash := NEOAddressToScriptHashWithEndian(address, binary.BigEndian)
return scripthash
}
func (s *SmartContractInfo) Serialize() []byte {
params := []byte{}
for _, p := range s.InputTypes {
params = append(params, p.Byte())
}
scriptBuilder := smartcontract.NewScriptBuilder()
scriptBuilder.Push([]byte(s.Description))
scriptBuilder.Push([]byte(s.Email))
scriptBuilder.Push([]byte(s.Author))
scriptBuilder.Push([]byte(s.Version))
scriptBuilder.Push([]byte(s.Name))
scriptBuilder.Push(int(s.Properties))
scriptBuilder.Push([]byte{s.ReturnType.Byte()})
scriptBuilder.Push(params)
scriptBuilder.PushVarData(hex2bytes(s.AVMHEX))
scriptBuilder.PushSysCall("Neo.Contract.Create")
b := scriptBuilder.ToBytes()
buff := new(bytes.Buffer)
WriteVarUint(buff, uint64(len(b)))
endPayload := []byte{}
endPayload = append(endPayload, buff.Bytes()...)
endPayload = append(endPayload, b...)
return endPayload
}
func DeploySmartContractScript(contractInfo SmartContractInfo, wallet Wallet, asset smartcontract.NativeAsset, amount float64, unspent smartcontract.Unspent, attributes map[smartcontract.TransactionAttribute][]byte) ([]byte, error) {
tx := smartcontract.NewInvocationTransactionPayable()
tx.Data = contractInfo.Serialize()
tx.GAS = uint64(490)
amountToSend := amount
assetToSend := asset
networkFee := smartcontract.NetworkFeeAmount(0)
txInputs, err := smartcontract.NewScriptBuilder().GenerateTransactionInput(unspent, assetToSend, amountToSend, networkFee)
if err != nil {
return nil, err
}
tx.Inputs = txInputs
txAttributes, err := smartcontract.NewScriptBuilder().GenerateTransactionAttributes(attributes)
if err != nil {
return nil, err
}
tx.Attributes = txAttributes
//when deploy smart contract, you don't actually send asset to another address
//so the receiver is the same address
sender := smartcontract.ParseNEOAddress(wallet.Address)
receiver := smartcontract.ParseNEOAddress(wallet.Address)
txOutputs, err := smartcontract.NewScriptBuilder().GenerateTransactionOutputPayableGAS(sender, receiver, unspent, assetToSend, amount, networkFee, float64(tx.GAS))
if err != nil {
return nil, err
}
tx.Outputs = txOutputs
//begin signing process and invocation script
privateKeyInHex := bytesToHex(wallet.PrivateKey)
signedData, err := Sign(tx.ToBytes(), privateKeyInHex)
if err != nil {
return nil, err
}
signature := smartcontract.TransactionSignature{
SignedData: signedData,
PublicKey: wallet.PublicKey,
}
scripts := []interface{}{signature}
txScripts := smartcontract.NewScriptBuilder().GenerateVerificationScripts(scripts)
tx.Script = txScripts
//end signing process
log.Printf("txid = %v", tx.ToTXID())
return tx.ToBytes(), nil
}