11 "github.com/davecgh/go-spew/spew"
13 "github.com/vapor/common"
14 "github.com/vapor/consensus"
15 "github.com/vapor/crypto"
16 "github.com/vapor/crypto/csp"
17 edchainkd "github.com/vapor/crypto/ed25519/chainkd"
18 chainjson "github.com/vapor/encoding/json"
19 "github.com/vapor/errors"
20 "github.com/vapor/protocol/bc"
21 "github.com/vapor/protocol/bc/types"
22 "github.com/vapor/protocol/vm/vmutil"
23 "github.com/vapor/testutil"
26 type testAction bc.AssetAmount
28 func (t testAction) Build(ctx context.Context, b *TemplateBuilder) error {
29 in := types.NewSpendInput(nil, bc.NewHash([32]byte{0xff}), *t.AssetId, t.Amount, 0, nil)
30 tplIn := &SigningInstruction{}
32 err := b.AddInput(in, tplIn)
36 return b.AddOutput(types.NewIntraChainOutput(*t.AssetId, t.Amount, []byte("change")))
39 func (t testAction) ActionType() string {
43 func newControlProgramAction(assetAmt bc.AssetAmount, script []byte) *controlProgramAction {
44 return &controlProgramAction{
45 AssetAmount: assetAmt,
50 func TestBuildIntra(t *testing.T) {
51 ctx := context.Background()
53 assetID1 := bc.NewAssetID([32]byte{1})
54 assetID2 := bc.NewAssetID([32]byte{2})
57 newControlProgramAction(bc.AssetAmount{AssetId: &assetID2, Amount: 6}, []byte("dest")),
58 testAction(bc.AssetAmount{AssetId: &assetID1, Amount: 5}),
60 expiryTime := time.Now().Add(time.Minute)
61 got, err := Build(ctx, nil, actions, expiryTime, 0)
63 testutil.FatalErr(t, err)
67 Transaction: types.NewTx(types.TxData{
69 Inputs: []*types.TxInput{
70 types.NewSpendInput(nil, bc.NewHash([32]byte{0xff}), assetID1, 5, 0, nil),
72 Outputs: []*types.TxOutput{
73 types.NewIntraChainOutput(assetID2, 6, []byte("dest")),
74 types.NewIntraChainOutput(assetID1, 5, []byte("change")),
77 SigningInstructions: []*SigningInstruction{{
78 WitnessComponents: []witnessComponent{},
82 if !testutil.DeepEqual(got.Transaction.TxData, want.Transaction.TxData) {
83 t.Errorf("got tx:\n%s\nwant tx:\n%s", spew.Sdump(got.Transaction.TxData), spew.Sdump(want.Transaction.TxData))
86 if !testutil.DeepEqual(got.SigningInstructions, want.SigningInstructions) {
87 t.Errorf("got signing instructions:\n\t%#v\nwant signing instructions:\n\t%#v", got.SigningInstructions, want.SigningInstructions)
91 func newCrossOutAction(assetAmt bc.AssetAmount, redeemContract []byte) *crossOutAction {
92 address, err := common.NewAddressWitnessPubKeyHash(redeemContract, &consensus.MainNetParams)
97 return &crossOutAction{
98 AssetAmount: assetAmt,
99 Address: address.String(),
103 func TestBuildCrossOut(t *testing.T) {
104 ctx := context.Background()
106 assetID1 := bc.NewAssetID([32]byte{1})
107 assetID2 := bc.NewAssetID([32]byte{2})
109 redeemContract := make([]byte, 20)
110 controlProgram := append([]byte{0x00, byte(len(redeemContract))}, redeemContract...)
113 newCrossOutAction(bc.AssetAmount{AssetId: &assetID2, Amount: 6}, redeemContract),
114 testAction(bc.AssetAmount{AssetId: &assetID1, Amount: 5}),
116 expiryTime := time.Now().Add(time.Minute)
117 got, err := Build(ctx, nil, actions, expiryTime, 0)
119 testutil.FatalErr(t, err)
123 Transaction: types.NewTx(types.TxData{
125 Inputs: []*types.TxInput{
126 types.NewSpendInput(nil, bc.NewHash([32]byte{0xff}), assetID1, 5, 0, nil),
128 Outputs: []*types.TxOutput{
129 types.NewCrossChainOutput(assetID2, 6, controlProgram),
130 types.NewIntraChainOutput(assetID1, 5, []byte("change")),
133 SigningInstructions: []*SigningInstruction{{
134 WitnessComponents: []witnessComponent{},
138 if !testutil.DeepEqual(got.Transaction.TxData, want.Transaction.TxData) {
139 t.Errorf("got tx:\n%s\nwant tx:\n%s", spew.Sdump(got.Transaction.TxData), spew.Sdump(want.Transaction.TxData))
142 if !testutil.DeepEqual(got.SigningInstructions, want.SigningInstructions) {
143 t.Errorf("got signing instructions:\n\t%#v\nwant signing instructions:\n\t%#v", got.SigningInstructions, want.SigningInstructions)
147 func mustDecodeHex(str string) []byte {
148 data, err := hex.DecodeString(str)
155 func TestCheckBlankCheck(t *testing.T) {
161 Inputs: []*types.TxInput{types.NewSpendInput(nil, bc.NewHash([32]byte{0xff}), bc.AssetID{}, 5, 0, nil)},
166 Inputs: []*types.TxInput{types.NewSpendInput(nil, bc.NewHash([32]byte{0xff}), bc.AssetID{}, 5, 0, nil)},
167 Outputs: []*types.TxOutput{types.NewIntraChainOutput(bc.AssetID{}, 3, nil)},
172 Inputs: []*types.TxInput{
173 types.NewSpendInput(nil, bc.NewHash([32]byte{0xff}), bc.AssetID{}, 5, 0, nil),
174 types.NewSpendInput(nil, bc.NewHash([32]byte{0xff}), bc.NewAssetID([32]byte{1}), 5, 0, nil),
176 Outputs: []*types.TxOutput{types.NewIntraChainOutput(bc.AssetID{}, 5, nil)},
181 Inputs: []*types.TxInput{types.NewSpendInput(nil, bc.NewHash([32]byte{0xff}), bc.AssetID{}, 5, 0, nil)},
182 Outputs: []*types.TxOutput{
183 types.NewIntraChainOutput(bc.AssetID{}, math.MaxInt64, nil),
184 types.NewIntraChainOutput(bc.AssetID{}, 7, nil),
190 Inputs: []*types.TxInput{
191 types.NewSpendInput(nil, bc.NewHash([32]byte{0xff}), bc.AssetID{}, 5, 0, nil),
192 types.NewSpendInput(nil, bc.NewHash([32]byte{0xff}), bc.AssetID{}, math.MaxInt64, 0, nil),
198 Inputs: []*types.TxInput{types.NewSpendInput(nil, bc.NewHash([32]byte{0xff}), bc.AssetID{}, 5, 0, nil)},
199 Outputs: []*types.TxOutput{types.NewIntraChainOutput(bc.AssetID{}, 5, nil)},
204 Outputs: []*types.TxOutput{types.NewIntraChainOutput(bc.AssetID{}, 5, nil)},
209 Inputs: []*types.TxInput{types.NewSpendInput(nil, bc.NewHash([32]byte{0xff}), bc.AssetID{}, 5, 0, nil)},
210 Outputs: []*types.TxOutput{types.NewIntraChainOutput(bc.NewAssetID([32]byte{1}), 5, nil)},
215 for _, c := range cases {
216 got := checkBlankCheck(c.tx)
217 if errors.Root(got) != c.want {
218 t.Errorf("checkUnsafe(%+v) err = %v want %v", c.tx, errors.Root(got), c.want)
223 func TestCreateTxByUtxo(t *testing.T) {
224 xprv, xpub, err := csp.NewXKeys(nil)
229 pubHash := make([]byte, 0)
230 program := make([]byte, 0)
231 pub := make([]byte, 0)
232 switch xpubkey := xpub.(type) {
234 pub = xpubkey.PublicKey()
235 pubHash = crypto.Ripemd160(pub)
236 program, err = vmutil.P2WPKHProgram([]byte(pubHash))
242 address, err := common.NewAddressWitnessPubKeyHash(pubHash, &consensus.ActiveNetParams)
247 muxID := testutil.MustDecodeHash("1e673900965623ec3305cead5a78dfb68a34599f8bc078460f3f202256c3dfa6")
253 ControlProgram []byte
257 AssetID: *consensus.BTMAssetID,
260 ControlProgram: program,
261 Address: address.EncodeAddress(),
264 recvProg := mustDecodeHex("00145056532ecd3621c9ce8adde5505c058610b287cf")
265 tx := types.NewTx(types.TxData{
267 Inputs: []*types.TxInput{
268 types.NewSpendInput(nil, utxo.SourceID, utxo.AssetID, utxo.Amount, utxo.SourcePos, utxo.ControlProgram),
270 Outputs: []*types.TxOutput{
271 types.NewIntraChainOutput(*consensus.BTMAssetID, 10000000000, recvProg),
277 AllowAdditional: false,
280 h := tpl.Hash(0).Byte32()
281 sig := make([]byte, 0)
282 switch xprvkey := xprv.(type) {
284 sig = xprvkey.Sign(h[:])
288 // Test with more signatures than required, in correct order
289 tpl.SigningInstructions = []*SigningInstruction{{
290 WitnessComponents: []witnessComponent{
293 Sigs: []chainjson.HexBytes{sig},
299 if err = materializeWitnesses(tpl); err != nil {
303 if !testutil.DeepEqual(tx, tpl.Transaction) {
304 t.Errorf("tx:%v result is equal to want:%v", tx, tpl.Transaction)
308 func TestAddContractArgs(t *testing.T) {
309 hexXpub, err := hex.DecodeString("ba76bb52574b3f40315f2c01f1818a9072ced56e9d4b68acbef56a4d0077d08e5e34837963e4cdc54eb251aa34aad01e6ae48b140f6a2743fbb0a0abd9cf8aac")
314 // TODO: it should use map[string]string adapt several algorithm
315 var xpub edchainkd.XPub
316 copy(xpub[:], hexXpub)
318 rawTxSig := RawTxSigArgument{RootXPub: xpub, Path: []chainjson.HexBytes{{1, 1, 0, 0, 0, 0, 0, 0, 0}, {1, 0, 0, 0, 0, 0, 0, 0}}}
319 rawTxSigMsg, err := json.Marshal(rawTxSig)
324 value, err := hex.DecodeString("7468697320697320612074657374")
328 data := DataArgument{value}
329 dataMsg, err := json.Marshal(data)
334 strMsg, err := json.Marshal(StrArgument{"this is a test string"})
339 integerMsg, err := json.Marshal(IntegerArgument{100})
344 boolMsg, err := json.Marshal(BoolArgument{true})
350 arguments []ContractArgument
354 arguments: []ContractArgument{
356 Type: "raw_tx_signature",
357 RawData: rawTxSigMsg,
363 arguments: []ContractArgument{
372 arguments: []ContractArgument{
381 arguments: []ContractArgument{
390 arguments: []ContractArgument{
399 arguments: []ContractArgument{
401 Type: "raw_tx_signature",
402 RawData: rawTxSigMsg,
412 arguments: []ContractArgument{
418 Type: "raw_tx_signature",
419 RawData: rawTxSigMsg,
425 arguments: []ContractArgument{
427 Type: "raw_tx_signature",
428 RawData: rawTxSigMsg,
450 arguments: []ContractArgument{
457 RawData: rawTxSigMsg,
460 wantResult: ErrBadContractArgType,
464 sigInst := &SigningInstruction{}
465 for _, c := range cases {
466 err := AddContractArgs(sigInst, c.arguments)
467 if err != c.wantResult {
468 t.Fatalf("got result=%v, want result=%v", err, c.wantResult)