Skip to content

Commit 2d5aae7

Browse files
Seongjae ChoiSeongjae Choi
authored andcommitted
Implement transferAsset
1 parent 1832a08 commit 2d5aae7

File tree

1 file changed

+277
-0
lines changed

1 file changed

+277
-0
lines changed

core/transaction/transferAsset.go

Lines changed: 277 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,277 @@
1+
package transaction
2+
3+
import (
4+
"encoding/hex"
5+
"errors"
6+
7+
"github.com/CodeChain-io/codechain-sdk-go/core"
8+
"github.com/CodeChain-io/codechain-sdk-go/crypto"
9+
"github.com/CodeChain-io/codechain-sdk-go/key"
10+
"github.com/CodeChain-io/codechain-sdk-go/primitives"
11+
"github.com/ethereum/go-ethereum/rlp"
12+
)
13+
14+
type AssetTransferTransactionJSON struct {
15+
NetworkID string `json:"networkId"`
16+
Burns []core.AssetTransferInputJSON `json:"burns"`
17+
Inputs []core.AssetTransferInputJSON `json:"inputs"`
18+
Outputs []core.AssetTransferOutputJSON `json:"outputs"`
19+
}
20+
21+
type TransferAssetActionJSON struct {
22+
AssetTransferTransactionJSON
23+
Metadata string `json:"metadata"`
24+
Approvals []string `json:"aprovals"`
25+
Expiration int `json:"expiration:omitempty"`
26+
}
27+
28+
type TransferAsset struct {
29+
core.Transaction
30+
Burns []core.AssetTransferInput
31+
Inputs []core.AssetTransferInput
32+
Outputs []core.AssetTransferOutput
33+
Approvals []string
34+
Metadata string
35+
Expiration *int
36+
}
37+
38+
func NewTransferAsset(
39+
burns []core.AssetTransferInput,
40+
inputs []core.AssetTransferInput,
41+
outputs []core.AssetTransferOutput,
42+
networkID string,
43+
metadata string,
44+
approvals []string,
45+
expiration *int) TransferAsset {
46+
47+
tx := core.NewTransaction(networkID)
48+
return TransferAsset{tx, burns, inputs, outputs, approvals, metadata, expiration}
49+
}
50+
51+
func (t TransferAsset) Tracker() primitives.H256 {
52+
hash, _ := crypto.Blake256(t.ActionRlpBytes())
53+
return primitives.NewH256(hash)
54+
}
55+
56+
func (t *TransferAsset) AddApproval(approval string) {
57+
t.Approvals = append(t.Approvals, approval)
58+
}
59+
60+
func (t *TransferAsset) AddBurn(burn core.AssetTransferInput) {
61+
t.Burns = append(t.Burns, burn)
62+
}
63+
64+
func (t *TransferAsset) AddBurns(burns []core.AssetTransferInput) {
65+
t.Burns = append(t.Burns, burns...)
66+
}
67+
68+
func (t *TransferAsset) AddBurnWithAsset(asset core.Asset) {
69+
t.Burns = append(t.Burns, asset.CreateTransferInput())
70+
}
71+
72+
func (t *TransferAsset) AddBurnsWithAsset(assets []core.Asset) {
73+
74+
burns := make([]core.AssetTransferInput, len(assets))
75+
for i, d := range assets {
76+
burns[i] = d.CreateTransferInput()
77+
}
78+
t.Burns = append(t.Burns, burns...)
79+
}
80+
81+
func (t *TransferAsset) AddInput(input core.AssetTransferInput) {
82+
t.Inputs = append(t.Inputs, input)
83+
}
84+
85+
func (t *TransferAsset) AddInputs(inputs []core.AssetTransferInput) {
86+
t.Inputs = append(t.Inputs, inputs...)
87+
}
88+
89+
func (t *TransferAsset) AddInputWithAsset(asset core.Asset) {
90+
t.Inputs = append(t.Inputs, asset.CreateTransferInput())
91+
}
92+
93+
func (t *TransferAsset) AddInputsWithAsset(assets []core.Asset) {
94+
95+
inputs := make([]core.AssetTransferInput, len(assets))
96+
for i, d := range assets {
97+
inputs[i] = d.CreateTransferInput()
98+
}
99+
t.Inputs = append(t.Inputs, inputs...)
100+
}
101+
102+
func (t *TransferAsset) AddOutputs(outputs []core.AssetTransferOutput) TransferAsset {
103+
t.Outputs = append(t.Outputs, outputs...)
104+
return *t
105+
}
106+
107+
func (t TransferAsset) ToEncodeObject() []interface{} {
108+
actionEncode := t.ActionToEncodeObject()
109+
110+
actionEncode = append(actionEncode, t.Metadata)
111+
actionEncode = append(actionEncode, t.Approvals)
112+
if t.Expiration != nil {
113+
actionEncode = append(actionEncode, []interface{}{t.Expiration})
114+
} else {
115+
actionEncode = append(actionEncode, []interface{}{})
116+
}
117+
118+
return []interface{}{t.Seq(), t.Fee().ToEncodeObject(), t.NetworkID(), actionEncode}
119+
120+
}
121+
122+
func (t TransferAsset) ActionToEncodeObject() []interface{} {
123+
burns := make([][]interface{}, len(t.Burns))
124+
for i, d := range t.Burns {
125+
res := d.ToEncodeObject()
126+
burns[i] = res
127+
}
128+
129+
inputs := make([][]interface{}, len(t.Inputs))
130+
for i, d := range t.Inputs {
131+
res := d.ToEncodeObject()
132+
inputs[i] = res
133+
}
134+
135+
outputs := make([][]interface{}, len(t.Outputs))
136+
for i, d := range t.Outputs {
137+
res := d.ToEncodeObject()
138+
outputs[i] = res
139+
}
140+
141+
return []interface{}{
142+
uint(0x14),
143+
t.Transaction.NetworkID(),
144+
burns,
145+
inputs,
146+
outputs,
147+
[]interface{}{}}
148+
}
149+
150+
func (t TransferAsset) GetTransferredAsset(index int) core.Asset {
151+
output := t.Outputs[index]
152+
153+
parameters := make([]string, len(output.Parameters))
154+
for i, d := range output.Parameters {
155+
res := hex.EncodeToString(d)
156+
parameters[i] = res
157+
}
158+
159+
return core.NewAsset(output.AssetType,
160+
output.ShardID,
161+
output.LockScriptHash,
162+
parameters,
163+
output.Quantity,
164+
t.Tracker(),
165+
uint(index))
166+
}
167+
168+
func (t TransferAsset) GetTransferredAssets() []core.Asset {
169+
assets := make([]core.Asset, len(t.Outputs))
170+
for i := range t.Outputs {
171+
assets[i] = t.GetTransferredAsset(i)
172+
}
173+
return assets
174+
}
175+
176+
func (t TransferAsset) HashWithoutScript() primitives.H256 {
177+
inputs := make([]core.AssetTransferInput, len(t.Inputs))
178+
for i, d := range t.Inputs {
179+
inputs[i] = d.WithOutScript()
180+
}
181+
182+
burns := make([]core.AssetTransferInput, len(t.Burns))
183+
for i, d := range t.Burns {
184+
burns[i] = d.WithOutScript()
185+
}
186+
187+
outputs := t.Outputs
188+
189+
t = NewTransferAsset(burns, inputs, outputs, t.NetworkID(), "", []string{}, nil)
190+
hashKey, _ := crypto.Blake128([]byte{3})
191+
192+
blake, _ := crypto.Blake256WithKey(t.ActionRlpBytes(), hashKey)
193+
194+
return primitives.NewH256(blake)
195+
}
196+
197+
func (t TransferAsset) ActionRlpBytes() []byte {
198+
res, _ := rlp.EncodeToBytes(t.ActionToEncodeObject())
199+
return res
200+
}
201+
202+
func (t TransferAsset) ActionToJSON() interface{} {
203+
burns := make([]core.AssetTransferInputJSON, len(t.Burns))
204+
for i, d := range t.Burns {
205+
res := d.ToJSON()
206+
burns[i] = res
207+
}
208+
209+
inputs := make([]core.AssetTransferInputJSON, len(t.Inputs))
210+
for i, d := range t.Inputs {
211+
res := d.ToJSON()
212+
inputs[i] = res
213+
}
214+
215+
outputs := make([]core.AssetTransferOutputJSON, len(t.Outputs))
216+
for i, d := range t.Outputs {
217+
res := d.ToJSON()
218+
outputs[i] = res
219+
}
220+
221+
return AssetTransferTransactionJSON{t.NetworkID(), burns, inputs, outputs}
222+
}
223+
224+
func (t TransferAsset) UnsignedHash() primitives.H256 {
225+
hash, _ := crypto.Blake256(t.RlpBytes())
226+
227+
var value [32]byte
228+
copy(value[:], hash[:32])
229+
return primitives.H256(value)
230+
}
231+
232+
func (t TransferAsset) RlpBytes() []byte {
233+
x, _ := rlp.EncodeToBytes(t.ToEncodeObject())
234+
return x
235+
}
236+
237+
func (t *TransferAsset) Sign(secret primitives.H256, seq uint, fee primitives.U64) core.SignedTransaction {
238+
t.SetSeq(seq)
239+
t.SetFee(fee)
240+
sig := crypto.SignEcdsa(t.UnsignedHash().Bytes(), secret.Bytes())
241+
242+
return core.NewSignedTransaction(t, sig, nil, nil, nil)
243+
}
244+
245+
func (t TransferAsset) GetType() string {
246+
return "transferAsset"
247+
}
248+
249+
func (t *TransferAsset) SignTransactionInput(index int, pubkey []byte, privkey []byte) error {
250+
251+
parameters := t.Inputs[index].PrevOut.Parameters
252+
parameter := hex.EncodeToString(parameters[0])
253+
pubkeyhsh, _ := crypto.Blake160(pubkey)
254+
if parameter != hex.EncodeToString(pubkeyhsh) {
255+
return errors.New("Wrong Publick Key")
256+
}
257+
258+
scriptOpcode := key.GetP2PKHLockScript()
259+
opcode := make([]byte, len(scriptOpcode))
260+
for i, d := range scriptOpcode {
261+
opcode[i] = byte(d)
262+
}
263+
264+
t.Inputs[index].SetLockScript(opcode)
265+
266+
message := t.HashWithoutScript()
267+
268+
script := key.CreateP2PKHUnlockScript(pubkey, privkey, message)
269+
270+
bytescript := make([]byte, len(script))
271+
for i, d := range script {
272+
bytescript[i] = byte(d)
273+
}
274+
t.Inputs[index].SetUnlockScript(bytescript)
275+
276+
return nil
277+
}

0 commit comments

Comments
 (0)