mirror of https://github.com/poanetwork/gecko.git
Implemented Properties
This commit is contained in:
parent
a2c0ad56f7
commit
00332620a6
|
@ -24,6 +24,7 @@ import (
|
|||
"github.com/ava-labs/gecko/vms/evm"
|
||||
"github.com/ava-labs/gecko/vms/nftfx"
|
||||
"github.com/ava-labs/gecko/vms/platformvm"
|
||||
"github.com/ava-labs/gecko/vms/propertyfx"
|
||||
"github.com/ava-labs/gecko/vms/secp256k1fx"
|
||||
"github.com/ava-labs/gecko/vms/spchainvm"
|
||||
"github.com/ava-labs/gecko/vms/spdagvm"
|
||||
|
@ -160,6 +161,7 @@ func Aliases(networkID uint32) (generalAliases map[string][]string, chainAliases
|
|||
timestampvm.ID.Key(): []string{"timestamp"},
|
||||
secp256k1fx.ID.Key(): []string{"secp256k1fx"},
|
||||
nftfx.ID.Key(): []string{"nftfx"},
|
||||
propertyfx.ID.Key(): []string{"propertyfx"},
|
||||
}
|
||||
|
||||
genesisBytes := Genesis(networkID)
|
||||
|
@ -353,6 +355,7 @@ func Genesis(networkID uint32) []byte {
|
|||
FxIDs: []ids.ID{
|
||||
secp256k1fx.ID,
|
||||
nftfx.ID,
|
||||
propertyfx.ID,
|
||||
},
|
||||
Name: "X-Chain",
|
||||
},
|
||||
|
|
|
@ -41,6 +41,7 @@ import (
|
|||
"github.com/ava-labs/gecko/vms/evm"
|
||||
"github.com/ava-labs/gecko/vms/nftfx"
|
||||
"github.com/ava-labs/gecko/vms/platformvm"
|
||||
"github.com/ava-labs/gecko/vms/propertyfx"
|
||||
"github.com/ava-labs/gecko/vms/secp256k1fx"
|
||||
"github.com/ava-labs/gecko/vms/spchainvm"
|
||||
"github.com/ava-labs/gecko/vms/spdagvm"
|
||||
|
@ -337,6 +338,7 @@ func (n *Node) initVMManager() {
|
|||
n.vmManager.RegisterVMFactory(timestampvm.ID, ×tampvm.Factory{})
|
||||
n.vmManager.RegisterVMFactory(secp256k1fx.ID, &secp256k1fx.Factory{})
|
||||
n.vmManager.RegisterVMFactory(nftfx.ID, &nftfx.Factory{})
|
||||
n.vmManager.RegisterVMFactory(propertyfx.ID, &propertyfx.Factory{})
|
||||
}
|
||||
|
||||
// Create the EventDispatcher used for hooking events
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
package propertyfx
|
||||
|
||||
import (
|
||||
"github.com/ava-labs/gecko/vms/components/verify"
|
||||
"github.com/ava-labs/gecko/vms/secp256k1fx"
|
||||
)
|
||||
|
||||
// BurnOperation ...
|
||||
type BurnOperation struct {
|
||||
secp256k1fx.Input `serialize:"true"`
|
||||
}
|
||||
|
||||
// Outs ...
|
||||
func (op *BurnOperation) Outs() []verify.Verifiable { return nil }
|
|
@ -0,0 +1,23 @@
|
|||
package propertyfx
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/ava-labs/gecko/vms/secp256k1fx"
|
||||
)
|
||||
|
||||
func TestBurnOperationInvalid(t *testing.T) {
|
||||
op := BurnOperation{Input: secp256k1fx.Input{
|
||||
SigIndices: []uint32{1, 0},
|
||||
}}
|
||||
if err := op.Verify(); err == nil {
|
||||
t.Fatalf("operation should have failed verification")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBurnOperationNumberOfOutput(t *testing.T) {
|
||||
op := BurnOperation{}
|
||||
if outs := op.Outs(); len(outs) != 0 {
|
||||
t.Fatalf("wrong number of outputs")
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package propertyfx
|
||||
|
||||
import (
|
||||
"github.com/ava-labs/gecko/vms/secp256k1fx"
|
||||
)
|
||||
|
||||
// Credential ...
|
||||
type Credential struct {
|
||||
secp256k1fx.Credential `serialize:"true"`
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package propertyfx
|
||||
|
||||
import (
|
||||
"github.com/ava-labs/gecko/ids"
|
||||
)
|
||||
|
||||
// ID that this Fx uses when labeled
|
||||
var (
|
||||
ID = ids.NewID([32]byte{'p', 'r', 'o', 'p', 'e', 'r', 't', 'y', 'f', 'x'})
|
||||
)
|
||||
|
||||
// Factory ...
|
||||
type Factory struct{}
|
||||
|
||||
// New ...
|
||||
func (f *Factory) New() interface{} { return &Fx{} }
|
|
@ -0,0 +1,12 @@
|
|||
package propertyfx
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestFactory(t *testing.T) {
|
||||
factory := Factory{}
|
||||
if fx := factory.New(); fx == nil {
|
||||
t.Fatalf("Factory.New returned nil")
|
||||
}
|
||||
}
|
|
@ -0,0 +1,109 @@
|
|||
package propertyfx
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/ava-labs/gecko/utils/wrappers"
|
||||
"github.com/ava-labs/gecko/vms/components/verify"
|
||||
"github.com/ava-labs/gecko/vms/secp256k1fx"
|
||||
)
|
||||
|
||||
var (
|
||||
errWrongTxType = errors.New("wrong tx type")
|
||||
errWrongUTXOType = errors.New("wrong utxo type")
|
||||
errWrongOperationType = errors.New("wrong operation type")
|
||||
errWrongCredentialType = errors.New("wrong credential type")
|
||||
|
||||
errNoUTXOs = errors.New("an operation must consume at least one UTXO")
|
||||
errWrongNumberOfUTXOs = errors.New("wrong number of UTXOs for the operation")
|
||||
errWrongNumberOfCreds = errors.New("wrong number of credentials for the operation")
|
||||
|
||||
errWrongMintOutput = errors.New("wrong mint output provided")
|
||||
|
||||
errCantTransfer = errors.New("cant transfer with this fx")
|
||||
)
|
||||
|
||||
// Fx ...
|
||||
type Fx struct{ secp256k1fx.Fx }
|
||||
|
||||
// Initialize ...
|
||||
func (fx *Fx) Initialize(vmIntf interface{}) error {
|
||||
if err := fx.InitializeVM(vmIntf); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log := fx.VM.Logger()
|
||||
log.Debug("Initializing nft fx")
|
||||
|
||||
c := fx.VM.Codec()
|
||||
errs := wrappers.Errs{}
|
||||
errs.Add(
|
||||
c.RegisterType(&MintOutput{}),
|
||||
c.RegisterType(&OwnedOutput{}),
|
||||
c.RegisterType(&MintOperation{}),
|
||||
c.RegisterType(&BurnOperation{}),
|
||||
c.RegisterType(&Credential{}),
|
||||
)
|
||||
return errs.Err
|
||||
}
|
||||
|
||||
// VerifyOperation ...
|
||||
func (fx *Fx) VerifyOperation(txIntf, opIntf, credIntf interface{}, utxosIntf []interface{}) error {
|
||||
tx, ok := txIntf.(secp256k1fx.Tx)
|
||||
switch {
|
||||
case !ok:
|
||||
return errWrongTxType
|
||||
case len(utxosIntf) != 1:
|
||||
return errWrongNumberOfUTXOs
|
||||
}
|
||||
|
||||
cred, ok := credIntf.(*Credential)
|
||||
if !ok {
|
||||
return errWrongCredentialType
|
||||
}
|
||||
|
||||
switch op := opIntf.(type) {
|
||||
case *MintOperation:
|
||||
return fx.VerifyMintOperation(tx, op, cred, utxosIntf[0])
|
||||
case *BurnOperation:
|
||||
return fx.VerifyTransferOperation(tx, op, cred, utxosIntf[0])
|
||||
default:
|
||||
return errWrongOperationType
|
||||
}
|
||||
}
|
||||
|
||||
// VerifyMintOperation ...
|
||||
func (fx *Fx) VerifyMintOperation(tx secp256k1fx.Tx, op *MintOperation, cred *Credential, utxoIntf interface{}) error {
|
||||
out, ok := utxoIntf.(*MintOutput)
|
||||
if !ok {
|
||||
return errWrongUTXOType
|
||||
}
|
||||
|
||||
if err := verify.All(op, cred, out); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch {
|
||||
case !out.OutputOwners.Equals(&op.MintOutput.OutputOwners):
|
||||
return errWrongMintOutput
|
||||
default:
|
||||
return fx.Fx.VerifyCredentials(tx, &op.MintInput, &cred.Credential, &out.OutputOwners)
|
||||
}
|
||||
}
|
||||
|
||||
// VerifyTransferOperation ...
|
||||
func (fx *Fx) VerifyTransferOperation(tx secp256k1fx.Tx, op *BurnOperation, cred *Credential, utxoIntf interface{}) error {
|
||||
out, ok := utxoIntf.(*OwnedOutput)
|
||||
if !ok {
|
||||
return errWrongUTXOType
|
||||
}
|
||||
|
||||
if err := verify.All(op, cred, out); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return fx.VerifyCredentials(tx, &op.Input, &cred.Credential, &out.OutputOwners)
|
||||
}
|
||||
|
||||
// VerifyTransfer ...
|
||||
func (fx *Fx) VerifyTransfer(_, _, _, _ interface{}) error { return errCantTransfer }
|
|
@ -0,0 +1,473 @@
|
|||
package propertyfx
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/ava-labs/gecko/ids"
|
||||
"github.com/ava-labs/gecko/utils/crypto"
|
||||
"github.com/ava-labs/gecko/utils/hashing"
|
||||
"github.com/ava-labs/gecko/utils/logging"
|
||||
"github.com/ava-labs/gecko/utils/timer"
|
||||
"github.com/ava-labs/gecko/vms/components/codec"
|
||||
"github.com/ava-labs/gecko/vms/secp256k1fx"
|
||||
)
|
||||
|
||||
var (
|
||||
txBytes = []byte{0, 1, 2, 3, 4, 5}
|
||||
sigBytes = [crypto.SECP256K1RSigLen]byte{
|
||||
0x0e, 0x33, 0x4e, 0xbc, 0x67, 0xa7, 0x3f, 0xe8,
|
||||
0x24, 0x33, 0xac, 0xa3, 0x47, 0x88, 0xa6, 0x3d,
|
||||
0x58, 0xe5, 0x8e, 0xf0, 0x3a, 0xd5, 0x84, 0xf1,
|
||||
0xbc, 0xa3, 0xb2, 0xd2, 0x5d, 0x51, 0xd6, 0x9b,
|
||||
0x0f, 0x28, 0x5d, 0xcd, 0x3f, 0x71, 0x17, 0x0a,
|
||||
0xf9, 0xbf, 0x2d, 0xb1, 0x10, 0x26, 0x5c, 0xe9,
|
||||
0xdc, 0xc3, 0x9d, 0x7a, 0x01, 0x50, 0x9d, 0xe8,
|
||||
0x35, 0xbd, 0xcb, 0x29, 0x3a, 0xd1, 0x49, 0x32,
|
||||
0x00,
|
||||
}
|
||||
addrBytes = [hashing.AddrLen]byte{
|
||||
0x01, 0x5c, 0xce, 0x6c, 0x55, 0xd6, 0xb5, 0x09,
|
||||
0x84, 0x5c, 0x8c, 0x4e, 0x30, 0xbe, 0xd9, 0x8d,
|
||||
0x39, 0x1a, 0xe7, 0xf0,
|
||||
}
|
||||
)
|
||||
|
||||
func TestFxInitialize(t *testing.T) {
|
||||
vm := secp256k1fx.TestVM{
|
||||
CLK: new(timer.Clock),
|
||||
Code: codec.NewDefault(),
|
||||
Log: logging.NoLog{},
|
||||
}
|
||||
fx := Fx{}
|
||||
err := fx.Initialize(&vm)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFxInitializeInvalid(t *testing.T) {
|
||||
fx := Fx{}
|
||||
err := fx.Initialize(nil)
|
||||
if err == nil {
|
||||
t.Fatalf("Should have returned an error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFxVerifyMintOperation(t *testing.T) {
|
||||
vm := secp256k1fx.TestVM{
|
||||
CLK: new(timer.Clock),
|
||||
Code: codec.NewDefault(),
|
||||
Log: logging.NoLog{},
|
||||
}
|
||||
date := time.Date(2019, time.January, 19, 16, 25, 17, 3, time.UTC)
|
||||
vm.CLK.Set(date)
|
||||
|
||||
fx := Fx{}
|
||||
if err := fx.Initialize(&vm); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
tx := &secp256k1fx.TestTx{
|
||||
Bytes: txBytes,
|
||||
}
|
||||
cred := &Credential{Credential: secp256k1fx.Credential{
|
||||
Sigs: [][crypto.SECP256K1RSigLen]byte{
|
||||
sigBytes,
|
||||
},
|
||||
}}
|
||||
utxo := &MintOutput{OutputOwners: secp256k1fx.OutputOwners{
|
||||
Threshold: 1,
|
||||
Addrs: []ids.ShortID{
|
||||
ids.NewShortID(addrBytes),
|
||||
},
|
||||
}}
|
||||
op := &MintOperation{
|
||||
MintInput: secp256k1fx.Input{
|
||||
SigIndices: []uint32{0},
|
||||
},
|
||||
MintOutput: MintOutput{OutputOwners: secp256k1fx.OutputOwners{
|
||||
Threshold: 1,
|
||||
Addrs: []ids.ShortID{
|
||||
ids.NewShortID(addrBytes),
|
||||
},
|
||||
}},
|
||||
}
|
||||
|
||||
utxos := []interface{}{utxo}
|
||||
if err := fx.VerifyOperation(tx, op, cred, utxos); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFxVerifyMintOperationWrongTx(t *testing.T) {
|
||||
vm := secp256k1fx.TestVM{
|
||||
CLK: new(timer.Clock),
|
||||
Code: codec.NewDefault(),
|
||||
Log: logging.NoLog{},
|
||||
}
|
||||
date := time.Date(2019, time.January, 19, 16, 25, 17, 3, time.UTC)
|
||||
vm.CLK.Set(date)
|
||||
|
||||
fx := Fx{}
|
||||
if err := fx.Initialize(&vm); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
cred := &Credential{Credential: secp256k1fx.Credential{
|
||||
Sigs: [][crypto.SECP256K1RSigLen]byte{
|
||||
sigBytes,
|
||||
},
|
||||
}}
|
||||
utxo := &MintOutput{OutputOwners: secp256k1fx.OutputOwners{
|
||||
Threshold: 1,
|
||||
Addrs: []ids.ShortID{
|
||||
ids.NewShortID(addrBytes),
|
||||
},
|
||||
}}
|
||||
op := &MintOperation{
|
||||
MintInput: secp256k1fx.Input{
|
||||
SigIndices: []uint32{0},
|
||||
},
|
||||
}
|
||||
|
||||
utxos := []interface{}{utxo}
|
||||
if err := fx.VerifyOperation(nil, op, cred, utxos); err == nil {
|
||||
t.Fatalf("VerifyOperation should have errored due to an invalid tx")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFxVerifyMintOperationWrongNumberUTXOs(t *testing.T) {
|
||||
vm := secp256k1fx.TestVM{
|
||||
CLK: new(timer.Clock),
|
||||
Code: codec.NewDefault(),
|
||||
Log: logging.NoLog{},
|
||||
}
|
||||
date := time.Date(2019, time.January, 19, 16, 25, 17, 3, time.UTC)
|
||||
vm.CLK.Set(date)
|
||||
|
||||
fx := Fx{}
|
||||
if err := fx.Initialize(&vm); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
tx := &secp256k1fx.TestTx{
|
||||
Bytes: txBytes,
|
||||
}
|
||||
cred := &Credential{Credential: secp256k1fx.Credential{
|
||||
Sigs: [][crypto.SECP256K1RSigLen]byte{
|
||||
sigBytes,
|
||||
},
|
||||
}}
|
||||
op := &MintOperation{
|
||||
MintInput: secp256k1fx.Input{
|
||||
SigIndices: []uint32{0},
|
||||
},
|
||||
}
|
||||
|
||||
utxos := []interface{}{}
|
||||
if err := fx.VerifyOperation(tx, op, cred, utxos); err == nil {
|
||||
t.Fatalf("VerifyOperation should have errored due to not enough utxos")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFxVerifyMintOperationWrongCredential(t *testing.T) {
|
||||
vm := secp256k1fx.TestVM{
|
||||
CLK: new(timer.Clock),
|
||||
Code: codec.NewDefault(),
|
||||
Log: logging.NoLog{},
|
||||
}
|
||||
date := time.Date(2019, time.January, 19, 16, 25, 17, 3, time.UTC)
|
||||
vm.CLK.Set(date)
|
||||
|
||||
fx := Fx{}
|
||||
if err := fx.Initialize(&vm); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
tx := &secp256k1fx.TestTx{
|
||||
Bytes: txBytes,
|
||||
}
|
||||
utxo := &MintOutput{OutputOwners: secp256k1fx.OutputOwners{
|
||||
Threshold: 1,
|
||||
Addrs: []ids.ShortID{
|
||||
ids.NewShortID(addrBytes),
|
||||
},
|
||||
}}
|
||||
op := &MintOperation{
|
||||
MintInput: secp256k1fx.Input{
|
||||
SigIndices: []uint32{0},
|
||||
},
|
||||
}
|
||||
|
||||
utxos := []interface{}{utxo}
|
||||
if err := fx.VerifyOperation(tx, op, nil, utxos); err == nil {
|
||||
t.Fatalf("VerifyOperation should have errored due to a bad credential")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFxVerifyMintOperationInvalidUTXO(t *testing.T) {
|
||||
vm := secp256k1fx.TestVM{
|
||||
CLK: new(timer.Clock),
|
||||
Code: codec.NewDefault(),
|
||||
Log: logging.NoLog{},
|
||||
}
|
||||
date := time.Date(2019, time.January, 19, 16, 25, 17, 3, time.UTC)
|
||||
vm.CLK.Set(date)
|
||||
|
||||
fx := Fx{}
|
||||
if err := fx.Initialize(&vm); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
tx := &secp256k1fx.TestTx{
|
||||
Bytes: txBytes,
|
||||
}
|
||||
cred := &Credential{Credential: secp256k1fx.Credential{
|
||||
Sigs: [][crypto.SECP256K1RSigLen]byte{
|
||||
sigBytes,
|
||||
},
|
||||
}}
|
||||
op := &MintOperation{
|
||||
MintInput: secp256k1fx.Input{
|
||||
SigIndices: []uint32{0},
|
||||
},
|
||||
}
|
||||
|
||||
utxos := []interface{}{nil}
|
||||
if err := fx.VerifyOperation(tx, op, cred, utxos); err == nil {
|
||||
t.Fatalf("VerifyOperation should have errored due to an invalid utxo")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFxVerifyMintOperationFailingVerification(t *testing.T) {
|
||||
vm := secp256k1fx.TestVM{
|
||||
CLK: new(timer.Clock),
|
||||
Code: codec.NewDefault(),
|
||||
Log: logging.NoLog{},
|
||||
}
|
||||
date := time.Date(2019, time.January, 19, 16, 25, 17, 3, time.UTC)
|
||||
vm.CLK.Set(date)
|
||||
|
||||
fx := Fx{}
|
||||
if err := fx.Initialize(&vm); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
tx := &secp256k1fx.TestTx{
|
||||
Bytes: txBytes,
|
||||
}
|
||||
cred := &Credential{Credential: secp256k1fx.Credential{
|
||||
Sigs: [][crypto.SECP256K1RSigLen]byte{
|
||||
sigBytes,
|
||||
},
|
||||
}}
|
||||
utxo := &MintOutput{OutputOwners: secp256k1fx.OutputOwners{
|
||||
Threshold: 1,
|
||||
Addrs: []ids.ShortID{
|
||||
ids.NewShortID(addrBytes),
|
||||
ids.ShortEmpty,
|
||||
},
|
||||
}}
|
||||
op := &MintOperation{
|
||||
MintInput: secp256k1fx.Input{
|
||||
SigIndices: []uint32{0},
|
||||
},
|
||||
}
|
||||
|
||||
utxos := []interface{}{utxo}
|
||||
if err := fx.VerifyOperation(tx, op, cred, utxos); err == nil {
|
||||
t.Fatalf("VerifyOperation should have errored due to an invalid utxo output")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFxVerifyMintOperationInvalidGroupID(t *testing.T) {
|
||||
vm := secp256k1fx.TestVM{
|
||||
CLK: new(timer.Clock),
|
||||
Code: codec.NewDefault(),
|
||||
Log: logging.NoLog{},
|
||||
}
|
||||
date := time.Date(2019, time.January, 19, 16, 25, 17, 3, time.UTC)
|
||||
vm.CLK.Set(date)
|
||||
|
||||
fx := Fx{}
|
||||
if err := fx.Initialize(&vm); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
tx := &secp256k1fx.TestTx{
|
||||
Bytes: txBytes,
|
||||
}
|
||||
cred := &Credential{Credential: secp256k1fx.Credential{
|
||||
Sigs: [][crypto.SECP256K1RSigLen]byte{
|
||||
sigBytes,
|
||||
},
|
||||
}}
|
||||
utxo := &MintOutput{OutputOwners: secp256k1fx.OutputOwners{
|
||||
Threshold: 1,
|
||||
Addrs: []ids.ShortID{
|
||||
ids.NewShortID(addrBytes),
|
||||
},
|
||||
}}
|
||||
op := &MintOperation{
|
||||
MintInput: secp256k1fx.Input{
|
||||
SigIndices: []uint32{0},
|
||||
},
|
||||
}
|
||||
|
||||
utxos := []interface{}{utxo}
|
||||
if err := fx.VerifyOperation(tx, op, cred, utxos); err == nil {
|
||||
t.Fatalf("VerifyOperation should have errored due to an invalid mint output")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFxVerifyTransferOperation(t *testing.T) {
|
||||
vm := secp256k1fx.TestVM{
|
||||
CLK: new(timer.Clock),
|
||||
Code: codec.NewDefault(),
|
||||
Log: logging.NoLog{},
|
||||
}
|
||||
date := time.Date(2019, time.January, 19, 16, 25, 17, 3, time.UTC)
|
||||
vm.CLK.Set(date)
|
||||
|
||||
fx := Fx{}
|
||||
if err := fx.Initialize(&vm); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
tx := &secp256k1fx.TestTx{
|
||||
Bytes: txBytes,
|
||||
}
|
||||
cred := &Credential{Credential: secp256k1fx.Credential{
|
||||
Sigs: [][crypto.SECP256K1RSigLen]byte{
|
||||
sigBytes,
|
||||
},
|
||||
}}
|
||||
utxo := &OwnedOutput{OutputOwners: secp256k1fx.OutputOwners{
|
||||
Threshold: 1,
|
||||
Addrs: []ids.ShortID{
|
||||
ids.NewShortID(addrBytes),
|
||||
},
|
||||
}}
|
||||
op := &BurnOperation{Input: secp256k1fx.Input{
|
||||
SigIndices: []uint32{0},
|
||||
}}
|
||||
|
||||
utxos := []interface{}{utxo}
|
||||
if err := fx.VerifyOperation(tx, op, cred, utxos); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFxVerifyTransferOperationWrongUTXO(t *testing.T) {
|
||||
vm := secp256k1fx.TestVM{
|
||||
CLK: new(timer.Clock),
|
||||
Code: codec.NewDefault(),
|
||||
Log: logging.NoLog{},
|
||||
}
|
||||
date := time.Date(2019, time.January, 19, 16, 25, 17, 3, time.UTC)
|
||||
vm.CLK.Set(date)
|
||||
|
||||
fx := Fx{}
|
||||
if err := fx.Initialize(&vm); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
tx := &secp256k1fx.TestTx{
|
||||
Bytes: txBytes,
|
||||
}
|
||||
cred := &Credential{Credential: secp256k1fx.Credential{
|
||||
Sigs: [][crypto.SECP256K1RSigLen]byte{
|
||||
sigBytes,
|
||||
},
|
||||
}}
|
||||
op := &BurnOperation{Input: secp256k1fx.Input{
|
||||
SigIndices: []uint32{0},
|
||||
}}
|
||||
|
||||
utxos := []interface{}{nil}
|
||||
if err := fx.VerifyOperation(tx, op, cred, utxos); err == nil {
|
||||
t.Fatalf("VerifyOperation should have errored due to an invalid utxo")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFxVerifyTransferOperationFailedVerify(t *testing.T) {
|
||||
|
||||
vm := secp256k1fx.TestVM{
|
||||
CLK: new(timer.Clock),
|
||||
Code: codec.NewDefault(),
|
||||
Log: logging.NoLog{},
|
||||
}
|
||||
date := time.Date(2019, time.January, 19, 16, 25, 17, 3, time.UTC)
|
||||
vm.CLK.Set(date)
|
||||
|
||||
fx := Fx{}
|
||||
if err := fx.Initialize(&vm); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
tx := &secp256k1fx.TestTx{
|
||||
Bytes: txBytes,
|
||||
}
|
||||
cred := &Credential{Credential: secp256k1fx.Credential{
|
||||
Sigs: [][crypto.SECP256K1RSigLen]byte{
|
||||
sigBytes,
|
||||
},
|
||||
}}
|
||||
utxo := &OwnedOutput{OutputOwners: secp256k1fx.OutputOwners{
|
||||
Threshold: 1,
|
||||
Addrs: []ids.ShortID{
|
||||
ids.NewShortID(addrBytes),
|
||||
},
|
||||
}}
|
||||
op := &BurnOperation{Input: secp256k1fx.Input{
|
||||
SigIndices: []uint32{1, 0},
|
||||
}}
|
||||
|
||||
utxos := []interface{}{utxo}
|
||||
if err := fx.VerifyOperation(tx, op, cred, utxos); err == nil {
|
||||
t.Fatalf("VerifyOperation should have errored due to an invalid utxo output")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFxVerifyOperationUnknownOperation(t *testing.T) {
|
||||
vm := secp256k1fx.TestVM{
|
||||
CLK: new(timer.Clock),
|
||||
Code: codec.NewDefault(),
|
||||
Log: logging.NoLog{},
|
||||
}
|
||||
date := time.Date(2019, time.January, 19, 16, 25, 17, 3, time.UTC)
|
||||
vm.CLK.Set(date)
|
||||
|
||||
fx := Fx{}
|
||||
if err := fx.Initialize(&vm); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
tx := &secp256k1fx.TestTx{
|
||||
Bytes: txBytes,
|
||||
}
|
||||
cred := &Credential{Credential: secp256k1fx.Credential{
|
||||
Sigs: [][crypto.SECP256K1RSigLen]byte{
|
||||
sigBytes,
|
||||
},
|
||||
}}
|
||||
utxo := &OwnedOutput{OutputOwners: secp256k1fx.OutputOwners{
|
||||
Threshold: 1,
|
||||
Addrs: []ids.ShortID{
|
||||
ids.NewShortID(addrBytes),
|
||||
},
|
||||
}}
|
||||
|
||||
utxos := []interface{}{utxo}
|
||||
if err := fx.VerifyOperation(tx, nil, cred, utxos); err == nil {
|
||||
t.Fatalf("VerifyOperation should have errored due to an unknown operation")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFxVerifyTransfer(t *testing.T) {
|
||||
vm := secp256k1fx.TestVM{
|
||||
CLK: new(timer.Clock),
|
||||
Code: codec.NewDefault(),
|
||||
Log: logging.NoLog{},
|
||||
}
|
||||
date := time.Date(2019, time.January, 19, 16, 25, 17, 3, time.UTC)
|
||||
vm.CLK.Set(date)
|
||||
|
||||
fx := Fx{}
|
||||
if err := fx.Initialize(&vm); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := fx.VerifyTransfer(nil, nil, nil, nil); err == nil {
|
||||
t.Fatalf("this Fx doesn't support transfers")
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
package propertyfx
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/ava-labs/gecko/vms/components/verify"
|
||||
"github.com/ava-labs/gecko/vms/secp256k1fx"
|
||||
)
|
||||
|
||||
var (
|
||||
errNilMintOperation = errors.New("nil mint operation")
|
||||
)
|
||||
|
||||
// MintOperation ...
|
||||
type MintOperation struct {
|
||||
MintInput secp256k1fx.Input `serialize:"true"`
|
||||
MintOutput MintOutput `serialize:"true"`
|
||||
OwnedOutput OwnedOutput `serialize:"true"`
|
||||
}
|
||||
|
||||
// Outs ...
|
||||
func (op *MintOperation) Outs() []verify.Verifiable {
|
||||
return []verify.Verifiable{
|
||||
&op.MintOutput,
|
||||
&op.OwnedOutput,
|
||||
}
|
||||
}
|
||||
|
||||
// Verify ...
|
||||
func (op *MintOperation) Verify() error {
|
||||
switch {
|
||||
case op == nil:
|
||||
return errNilMintOperation
|
||||
default:
|
||||
return verify.All(&op.MintInput, &op.MintOutput, &op.OwnedOutput)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package propertyfx
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/ava-labs/gecko/vms/secp256k1fx"
|
||||
)
|
||||
|
||||
func TestMintOperationVerifyNil(t *testing.T) {
|
||||
op := (*MintOperation)(nil)
|
||||
if err := op.Verify(); err == nil {
|
||||
t.Fatalf("nil operation should have failed verification")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMintOperationVerifyInvalidOutput(t *testing.T) {
|
||||
op := MintOperation{
|
||||
OwnedOutput: OwnedOutput{
|
||||
OutputOwners: secp256k1fx.OutputOwners{
|
||||
Threshold: 1,
|
||||
},
|
||||
},
|
||||
}
|
||||
if err := op.Verify(); err == nil {
|
||||
t.Fatalf("operation should have failed verification")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMintOperationOuts(t *testing.T) {
|
||||
op := MintOperation{}
|
||||
if outs := op.Outs(); len(outs) != 2 {
|
||||
t.Fatalf("Wrong number of outputs returned")
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package propertyfx
|
||||
|
||||
import (
|
||||
"github.com/ava-labs/gecko/vms/secp256k1fx"
|
||||
)
|
||||
|
||||
// MintOutput ...
|
||||
type MintOutput struct {
|
||||
secp256k1fx.OutputOwners `serialize:"true"`
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package propertyfx
|
||||
|
||||
import (
|
||||
"github.com/ava-labs/gecko/vms/secp256k1fx"
|
||||
)
|
||||
|
||||
// OwnedOutput ...
|
||||
type OwnedOutput struct {
|
||||
secp256k1fx.OutputOwners `serialize:"true"`
|
||||
}
|
Loading…
Reference in New Issue