mirror of https://github.com/poanetwork/gecko.git
88 lines
2.0 KiB
Go
88 lines
2.0 KiB
Go
// (c) 2019-2020, Ava Labs, Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
package avm
|
|
|
|
import (
|
|
"bytes"
|
|
"errors"
|
|
"sort"
|
|
|
|
"github.com/ava-labs/gecko/utils"
|
|
"github.com/ava-labs/gecko/vms/components/ava"
|
|
"github.com/ava-labs/gecko/vms/components/codec"
|
|
"github.com/ava-labs/gecko/vms/components/verify"
|
|
)
|
|
|
|
var (
|
|
errNilOperation = errors.New("nil operation is not valid")
|
|
errEmptyOperation = errors.New("empty operation is not valid")
|
|
)
|
|
|
|
// Operation ...
|
|
type Operation struct {
|
|
ava.Asset `serialize:"true"`
|
|
|
|
Ins []*OperableInput `serialize:"true"`
|
|
Outs []verify.Verifiable `serialize:"true"`
|
|
}
|
|
|
|
// Verify implements the verify.Verifiable interface
|
|
func (op *Operation) Verify(c codec.Codec) error {
|
|
switch {
|
|
case op == nil:
|
|
return errNilOperation
|
|
case len(op.Ins) == 0 && len(op.Outs) == 0:
|
|
return errEmptyOperation
|
|
}
|
|
|
|
for _, in := range op.Ins {
|
|
if err := in.Verify(); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
if !isSortedAndUniqueOperableInputs(op.Ins) {
|
|
return errInputsNotSortedUnique
|
|
}
|
|
|
|
for _, out := range op.Outs {
|
|
if err := out.Verify(); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
if !isSortedVerifiables(op.Outs, c) {
|
|
return errOutputsNotSorted
|
|
}
|
|
|
|
return op.Asset.Verify()
|
|
}
|
|
|
|
type innerSortOperation struct {
|
|
ops []*Operation
|
|
codec codec.Codec
|
|
}
|
|
|
|
func (ops *innerSortOperation) Less(i, j int) bool {
|
|
iOp := ops.ops[i]
|
|
jOp := ops.ops[j]
|
|
|
|
iBytes, err := ops.codec.Marshal(iOp)
|
|
if err != nil {
|
|
return false
|
|
}
|
|
jBytes, err := ops.codec.Marshal(jOp)
|
|
if err != nil {
|
|
return false
|
|
}
|
|
return bytes.Compare(iBytes, jBytes) == -1
|
|
}
|
|
func (ops *innerSortOperation) Len() int { return len(ops.ops) }
|
|
func (ops *innerSortOperation) Swap(i, j int) { o := ops.ops; o[j], o[i] = o[i], o[j] }
|
|
|
|
func sortOperations(ops []*Operation, c codec.Codec) {
|
|
sort.Sort(&innerSortOperation{ops: ops, codec: c})
|
|
}
|
|
func isSortedAndUniqueOperations(ops []*Operation, c codec.Codec) bool {
|
|
return utils.IsSortedAndUnique(&innerSortOperation{ops: ops, codec: c})
|
|
}
|