mirror of https://github.com/poanetwork/gecko.git
331 lines
6.8 KiB
Go
331 lines
6.8 KiB
Go
// (c) 2019-2020, Ava Labs, Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
package platformvm
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/ava-labs/gecko/ids"
|
|
"github.com/ava-labs/gecko/utils/crypto"
|
|
"github.com/ava-labs/gecko/vms/avm"
|
|
)
|
|
|
|
// test method SyntacticVerify
|
|
func TestCreateChainTxSyntacticVerify(t *testing.T) {
|
|
vm := defaultVM()
|
|
vm.Ctx.Lock.Lock()
|
|
defer func() {
|
|
vm.Shutdown()
|
|
vm.Ctx.Lock.Unlock()
|
|
}()
|
|
|
|
// Case 1: tx is nil
|
|
var tx *CreateChainTx
|
|
if err := tx.SyntacticVerify(); err == nil {
|
|
t.Fatal("should have failed because tx is nil")
|
|
}
|
|
|
|
// Case 2: network ID is wrong
|
|
tx, err := vm.newCreateChainTx(
|
|
defaultNonce+1,
|
|
testSubnet1.id,
|
|
nil,
|
|
avm.ID,
|
|
nil,
|
|
"chain name",
|
|
testNetworkID+1,
|
|
[]*crypto.PrivateKeySECP256K1R{testSubnet1ControlKeys[0], testSubnet1ControlKeys[1]},
|
|
defaultKey,
|
|
)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
err = tx.SyntacticVerify()
|
|
if err == nil {
|
|
t.Fatal("should've errored because network ID is wrong")
|
|
}
|
|
|
|
// case 3: tx ID is empty
|
|
tx, err = vm.newCreateChainTx(
|
|
defaultNonce+1,
|
|
testSubnet1.id,
|
|
nil,
|
|
avm.ID,
|
|
nil,
|
|
"chain name",
|
|
testNetworkID,
|
|
[]*crypto.PrivateKeySECP256K1R{testSubnet1ControlKeys[0], testSubnet1ControlKeys[1]},
|
|
defaultKey,
|
|
)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
tx.id = ids.ID{}
|
|
if err := tx.SyntacticVerify(); err == nil {
|
|
t.Fatal("should've errored because tx ID is empty")
|
|
}
|
|
|
|
// Case 4: vm ID is empty
|
|
tx, err = vm.newCreateChainTx(
|
|
defaultNonce+1,
|
|
testSubnet1.id,
|
|
nil,
|
|
avm.ID,
|
|
nil,
|
|
"chain name",
|
|
testNetworkID,
|
|
[]*crypto.PrivateKeySECP256K1R{testSubnet1ControlKeys[0], testSubnet1ControlKeys[1]},
|
|
defaultKey,
|
|
)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
tx.VMID = ids.ID{}
|
|
if err := tx.SyntacticVerify(); err == nil {
|
|
t.Fatal("should've errored because tx ID is empty")
|
|
}
|
|
|
|
// Case 5: Control sigs not sorted
|
|
tx, err = vm.newCreateChainTx(
|
|
defaultNonce+1,
|
|
testSubnet1.id,
|
|
nil,
|
|
avm.ID,
|
|
nil,
|
|
"chain name",
|
|
testNetworkID,
|
|
[]*crypto.PrivateKeySECP256K1R{testSubnet1ControlKeys[0], testSubnet1ControlKeys[1]},
|
|
defaultKey,
|
|
)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
// Reverse signature order
|
|
tx.ControlSigs[0], tx.ControlSigs[1] = tx.ControlSigs[1], tx.ControlSigs[0]
|
|
if err := tx.SyntacticVerify(); err == nil {
|
|
t.Fatal("should've errored because control sigs not sorted")
|
|
}
|
|
|
|
// Case 6: Control sigs not unique
|
|
tx, err = vm.newCreateChainTx(
|
|
defaultNonce+1,
|
|
testSubnet1.id,
|
|
nil,
|
|
avm.ID,
|
|
nil,
|
|
"chain name",
|
|
testNetworkID,
|
|
[]*crypto.PrivateKeySECP256K1R{testSubnet1ControlKeys[0], testSubnet1ControlKeys[1]},
|
|
defaultKey,
|
|
)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
tx.ControlSigs[0] = tx.ControlSigs[1]
|
|
if err := tx.SyntacticVerify(); err == nil {
|
|
t.Fatal("should've errored because control sigs not unique")
|
|
}
|
|
|
|
// Case 7: Valid tx passes syntactic verification
|
|
tx, err = vm.newCreateChainTx(
|
|
defaultNonce+1,
|
|
testSubnet1.id,
|
|
nil,
|
|
avm.ID,
|
|
nil,
|
|
"chain name",
|
|
testNetworkID,
|
|
[]*crypto.PrivateKeySECP256K1R{testSubnet1ControlKeys[0], testSubnet1ControlKeys[1]},
|
|
defaultKey,
|
|
)
|
|
if err != nil {
|
|
t.Fatalf("should have passed verification but got %v", err)
|
|
}
|
|
}
|
|
|
|
// Ensure SemanticVerify fails when there are not enough control sigs
|
|
func TestCreateChainTxInsufficientControlSigs(t *testing.T) {
|
|
vm := defaultVM()
|
|
vm.Ctx.Lock.Lock()
|
|
defer func() {
|
|
vm.Shutdown()
|
|
vm.Ctx.Lock.Unlock()
|
|
}()
|
|
|
|
// Case 1: No control sigs (2 are needed)
|
|
tx, err := vm.newCreateChainTx(
|
|
defaultNonce+1,
|
|
testSubnet1.id,
|
|
nil,
|
|
avm.ID,
|
|
nil,
|
|
"chain name",
|
|
testNetworkID,
|
|
nil,
|
|
defaultKey,
|
|
)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
_, err = tx.SemanticVerify(vm.DB)
|
|
if err == nil {
|
|
t.Fatal("should have errored because there are no control sigs")
|
|
}
|
|
|
|
// Case 2: 1 control sig (2 are needed)
|
|
tx, err = vm.newCreateChainTx(
|
|
defaultNonce+1,
|
|
testSubnet1.id,
|
|
nil,
|
|
avm.ID,
|
|
nil,
|
|
"chain name",
|
|
testNetworkID,
|
|
[]*crypto.PrivateKeySECP256K1R{testSubnet1ControlKeys[0]},
|
|
defaultKey,
|
|
)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
_, err = tx.SemanticVerify(vm.DB)
|
|
if err == nil {
|
|
t.Fatal("should have errored because there are no control sigs")
|
|
}
|
|
}
|
|
|
|
// Ensure SemanticVerify fails when an incorrect control signature is given
|
|
func TestCreateChainTxWrongControlSig(t *testing.T) {
|
|
vm := defaultVM()
|
|
vm.Ctx.Lock.Lock()
|
|
defer func() {
|
|
vm.Shutdown()
|
|
vm.Ctx.Lock.Unlock()
|
|
}()
|
|
|
|
// Generate new, random key to sign tx with
|
|
factory := crypto.FactorySECP256K1R{}
|
|
key, err := factory.NewPrivateKey()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
tx, err := vm.newCreateChainTx(
|
|
defaultNonce+1,
|
|
testSubnet1.id,
|
|
nil,
|
|
avm.ID,
|
|
nil,
|
|
"chain name",
|
|
testNetworkID,
|
|
[]*crypto.PrivateKeySECP256K1R{testSubnet1ControlKeys[0], key.(*crypto.PrivateKeySECP256K1R)},
|
|
defaultKey,
|
|
)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
_, err = tx.SemanticVerify(vm.DB)
|
|
if err == nil {
|
|
t.Fatal("should have errored because incorrect control sig given")
|
|
}
|
|
}
|
|
|
|
// Ensure SemanticVerify fails when the Subnet the blockchain specifies as
|
|
// its validator set doesn't exist
|
|
func TestCreateChainTxNoSuchSubnet(t *testing.T) {
|
|
vm := defaultVM()
|
|
vm.Ctx.Lock.Lock()
|
|
defer func() {
|
|
vm.Shutdown()
|
|
vm.Ctx.Lock.Unlock()
|
|
}()
|
|
|
|
tx, err := vm.newCreateChainTx(
|
|
defaultNonce+1,
|
|
ids.NewID([32]byte{1, 9, 124, 11, 20}), // pick some random ID for subnet
|
|
nil,
|
|
avm.ID,
|
|
nil,
|
|
"chain name",
|
|
testNetworkID,
|
|
[]*crypto.PrivateKeySECP256K1R{testSubnet1ControlKeys[0], testSubnet1ControlKeys[1]},
|
|
defaultKey,
|
|
)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
_, err = tx.SemanticVerify(vm.DB)
|
|
if err == nil {
|
|
t.Fatal("should have errored because Subnet doesn't exist")
|
|
}
|
|
}
|
|
|
|
func TestCreateChainTxAlreadyExists(t *testing.T) {
|
|
vm := defaultVM()
|
|
vm.Ctx.Lock.Lock()
|
|
defer func() {
|
|
vm.Shutdown()
|
|
vm.Ctx.Lock.Unlock()
|
|
}()
|
|
|
|
// create a tx
|
|
tx, err := vm.newCreateChainTx(
|
|
defaultNonce+1,
|
|
testSubnet1.id,
|
|
nil,
|
|
avm.ID,
|
|
nil,
|
|
"chain name",
|
|
testNetworkID,
|
|
[]*crypto.PrivateKeySECP256K1R{testSubnet1ControlKeys[0], testSubnet1ControlKeys[1]},
|
|
defaultKey,
|
|
)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
// put the chain in existing chain list
|
|
if err := vm.putChains(vm.DB, []*CreateChainTx{tx}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
_, err = tx.SemanticVerify(vm.DB)
|
|
if err == nil {
|
|
t.Fatalf("should have failed because there is already a chain with ID %s", tx.id)
|
|
}
|
|
}
|
|
|
|
// Ensure valid tx passes semanticVerify
|
|
func TestCreateChainTxValid(t *testing.T) {
|
|
vm := defaultVM()
|
|
vm.Ctx.Lock.Lock()
|
|
defer func() {
|
|
vm.Shutdown()
|
|
vm.Ctx.Lock.Unlock()
|
|
}()
|
|
|
|
// create a valid tx
|
|
tx, err := vm.newCreateChainTx(
|
|
defaultNonce+1,
|
|
testSubnet1.id,
|
|
nil,
|
|
avm.ID,
|
|
nil,
|
|
"chain name",
|
|
testNetworkID,
|
|
[]*crypto.PrivateKeySECP256K1R{testSubnet1ControlKeys[0], testSubnet1ControlKeys[1]},
|
|
defaultKey,
|
|
)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
_, err = tx.SemanticVerify(vm.DB)
|
|
if err != nil {
|
|
t.Fatalf("expected tx to pass verification but got error: %v", err)
|
|
}
|
|
}
|