forked from TrueCloudLab/neoneo-go
Merge pull request #540 from nspcc-dev/feature/triggerType_509
core: add trigger types as constants. Closes #509
This commit is contained in:
commit
e251889f7b
5 changed files with 57 additions and 17 deletions
|
@ -16,6 +16,7 @@ import (
|
||||||
"github.com/CityOfZion/neo-go/pkg/crypto/keys"
|
"github.com/CityOfZion/neo-go/pkg/crypto/keys"
|
||||||
"github.com/CityOfZion/neo-go/pkg/io"
|
"github.com/CityOfZion/neo-go/pkg/io"
|
||||||
"github.com/CityOfZion/neo-go/pkg/smartcontract"
|
"github.com/CityOfZion/neo-go/pkg/smartcontract"
|
||||||
|
"github.com/CityOfZion/neo-go/pkg/smartcontract/trigger"
|
||||||
"github.com/CityOfZion/neo-go/pkg/util"
|
"github.com/CityOfZion/neo-go/pkg/util"
|
||||||
"github.com/CityOfZion/neo-go/pkg/vm"
|
"github.com/CityOfZion/neo-go/pkg/vm"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
@ -487,7 +488,7 @@ func (bc *Blockchain) storeBlock(block *Block) error {
|
||||||
}
|
}
|
||||||
chainState.contracts[contract.ScriptHash()] = contract
|
chainState.contracts[contract.ScriptHash()] = contract
|
||||||
case *transaction.InvocationTX:
|
case *transaction.InvocationTX:
|
||||||
systemInterop := newInteropContext(0x10, bc, chainState.store, block, tx)
|
systemInterop := newInteropContext(trigger.Application, bc, chainState.store, block, tx)
|
||||||
v := bc.spawnVMWithInterops(systemInterop)
|
v := bc.spawnVMWithInterops(systemInterop)
|
||||||
v.SetCheckedHash(tx.VerificationHash().Bytes())
|
v.SetCheckedHash(tx.VerificationHash().Bytes())
|
||||||
v.LoadScript(t.Script)
|
v.LoadScript(t.Script)
|
||||||
|
@ -530,7 +531,7 @@ func (bc *Blockchain) storeBlock(block *Block) error {
|
||||||
}
|
}
|
||||||
aer := &AppExecResult{
|
aer := &AppExecResult{
|
||||||
TxHash: tx.Hash(),
|
TxHash: tx.Hash(),
|
||||||
Trigger: 0x10,
|
Trigger: trigger.Application,
|
||||||
VMState: v.State(),
|
VMState: v.State(),
|
||||||
GasConsumed: util.Fixed8(0),
|
GasConsumed: util.Fixed8(0),
|
||||||
Stack: v.Stack("estack"),
|
Stack: v.Stack("estack"),
|
||||||
|
@ -1418,7 +1419,7 @@ func (bc *Blockchain) spawnVMWithInterops(interopCtx *interopContext) *vm.VM {
|
||||||
// GetTestVM returns a VM and a Store setup for a test run of some sort of code.
|
// GetTestVM returns a VM and a Store setup for a test run of some sort of code.
|
||||||
func (bc *Blockchain) GetTestVM() (*vm.VM, storage.Store) {
|
func (bc *Blockchain) GetTestVM() (*vm.VM, storage.Store) {
|
||||||
tmpStore := storage.NewMemCachedStore(bc.store)
|
tmpStore := storage.NewMemCachedStore(bc.store)
|
||||||
systemInterop := newInteropContext(0x10, bc, tmpStore, nil, nil)
|
systemInterop := newInteropContext(trigger.Application, bc, tmpStore, nil, nil)
|
||||||
vm := bc.spawnVMWithInterops(systemInterop)
|
vm := bc.spawnVMWithInterops(systemInterop)
|
||||||
return vm, tmpStore
|
return vm, tmpStore
|
||||||
}
|
}
|
||||||
|
@ -1482,7 +1483,7 @@ func (bc *Blockchain) verifyTxWitnesses(t *transaction.Transaction, block *Block
|
||||||
}
|
}
|
||||||
sort.Slice(hashes, func(i, j int) bool { return hashes[i].Less(hashes[j]) })
|
sort.Slice(hashes, func(i, j int) bool { return hashes[i].Less(hashes[j]) })
|
||||||
sort.Slice(witnesses, func(i, j int) bool { return witnesses[i].ScriptHash().Less(witnesses[j].ScriptHash()) })
|
sort.Slice(witnesses, func(i, j int) bool { return witnesses[i].ScriptHash().Less(witnesses[j].ScriptHash()) })
|
||||||
interopCtx := newInteropContext(0, bc, bc.store, block, t)
|
interopCtx := newInteropContext(trigger.Verification, bc, bc.store, block, t)
|
||||||
for i := 0; i < len(hashes); i++ {
|
for i := 0; i < len(hashes); i++ {
|
||||||
err := bc.verifyHashAgainstScript(hashes[i], witnesses[i], t.VerificationHash(), interopCtx)
|
err := bc.verifyHashAgainstScript(hashes[i], witnesses[i], t.VerificationHash(), interopCtx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -1502,7 +1503,7 @@ func (bc *Blockchain) verifyBlockWitnesses(block *Block, prevHeader *Header) err
|
||||||
} else {
|
} else {
|
||||||
hash = prevHeader.NextConsensus
|
hash = prevHeader.NextConsensus
|
||||||
}
|
}
|
||||||
interopCtx := newInteropContext(0, bc, bc.store, nil, nil)
|
interopCtx := newInteropContext(trigger.Verification, bc, bc.store, nil, nil)
|
||||||
return bc.verifyHashAgainstScript(hash, block.Script, block.VerificationHash(), interopCtx)
|
return bc.verifyHashAgainstScript(hash, block.Script, block.VerificationHash(), interopCtx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"github.com/CityOfZion/neo-go/pkg/core/transaction"
|
"github.com/CityOfZion/neo-go/pkg/core/transaction"
|
||||||
"github.com/CityOfZion/neo-go/pkg/crypto/keys"
|
"github.com/CityOfZion/neo-go/pkg/crypto/keys"
|
||||||
"github.com/CityOfZion/neo-go/pkg/smartcontract"
|
"github.com/CityOfZion/neo-go/pkg/smartcontract"
|
||||||
|
"github.com/CityOfZion/neo-go/pkg/smartcontract/trigger"
|
||||||
"github.com/CityOfZion/neo-go/pkg/util"
|
"github.com/CityOfZion/neo-go/pkg/util"
|
||||||
"github.com/CityOfZion/neo-go/pkg/vm"
|
"github.com/CityOfZion/neo-go/pkg/vm"
|
||||||
gherr "github.com/pkg/errors"
|
gherr "github.com/pkg/errors"
|
||||||
|
@ -429,7 +430,7 @@ func (ic *interopContext) storageFind(v *vm.VM) error {
|
||||||
// evaluation stack, does a lot of checks and returns ContractState if it
|
// evaluation stack, does a lot of checks and returns ContractState if it
|
||||||
// succeeds.
|
// succeeds.
|
||||||
func (ic *interopContext) createContractStateFromVM(v *vm.VM) (*ContractState, error) {
|
func (ic *interopContext) createContractStateFromVM(v *vm.VM) (*ContractState, error) {
|
||||||
if ic.trigger != 0x10 {
|
if ic.trigger != trigger.Application {
|
||||||
return nil, errors.New("can't create contract when not triggered by an application")
|
return nil, errors.New("can't create contract when not triggered by an application")
|
||||||
}
|
}
|
||||||
script := v.Estack().Pop().Bytes()
|
script := v.Estack().Pop().Bytes()
|
||||||
|
@ -551,7 +552,7 @@ func (ic *interopContext) contractMigrate(v *vm.VM) error {
|
||||||
|
|
||||||
// assetCreate creates an asset.
|
// assetCreate creates an asset.
|
||||||
func (ic *interopContext) assetCreate(v *vm.VM) error {
|
func (ic *interopContext) assetCreate(v *vm.VM) error {
|
||||||
if ic.trigger != 0x10 {
|
if ic.trigger != trigger.Application {
|
||||||
return errors.New("can't create asset when not triggered by an application")
|
return errors.New("can't create asset when not triggered by an application")
|
||||||
}
|
}
|
||||||
atype := transaction.AssetType(v.Estack().Pop().BigInt().Int64())
|
atype := transaction.AssetType(v.Estack().Pop().BigInt().Int64())
|
||||||
|
@ -717,7 +718,7 @@ func (ic *interopContext) assetGetPrecision(v *vm.VM) error {
|
||||||
|
|
||||||
// assetRenew updates asset expiration date.
|
// assetRenew updates asset expiration date.
|
||||||
func (ic *interopContext) assetRenew(v *vm.VM) error {
|
func (ic *interopContext) assetRenew(v *vm.VM) error {
|
||||||
if ic.trigger != 0x10 {
|
if ic.trigger != trigger.Application {
|
||||||
return errors.New("can't create asset when not triggered by an application")
|
return errors.New("can't create asset when not triggered by an application")
|
||||||
}
|
}
|
||||||
asInterface := v.Estack().Pop().Value()
|
asInterface := v.Estack().Pop().Value()
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"github.com/CityOfZion/neo-go/pkg/core/transaction"
|
"github.com/CityOfZion/neo-go/pkg/core/transaction"
|
||||||
"github.com/CityOfZion/neo-go/pkg/crypto/keys"
|
"github.com/CityOfZion/neo-go/pkg/crypto/keys"
|
||||||
"github.com/CityOfZion/neo-go/pkg/smartcontract"
|
"github.com/CityOfZion/neo-go/pkg/smartcontract"
|
||||||
|
"github.com/CityOfZion/neo-go/pkg/smartcontract/trigger"
|
||||||
"github.com/CityOfZion/neo-go/pkg/util"
|
"github.com/CityOfZion/neo-go/pkg/util"
|
||||||
"github.com/CityOfZion/neo-go/pkg/vm"
|
"github.com/CityOfZion/neo-go/pkg/vm"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
@ -42,7 +43,7 @@ func TestHeaderGetVersion(t *testing.T) {
|
||||||
func TestHeaderGetVersion_Negative(t *testing.T) {
|
func TestHeaderGetVersion_Negative(t *testing.T) {
|
||||||
v := vm.New()
|
v := vm.New()
|
||||||
block := newDumbBlock()
|
block := newDumbBlock()
|
||||||
context := newInteropContext(0x10, newTestChain(t), storage.NewMemoryStore(), block, nil)
|
context := newInteropContext(trigger.Application, newTestChain(t), storage.NewMemoryStore(), block, nil)
|
||||||
v.Estack().PushVal(vm.NewBoolItem(false))
|
v.Estack().PushVal(vm.NewBoolItem(false))
|
||||||
|
|
||||||
err := context.headerGetVersion(v)
|
err := context.headerGetVersion(v)
|
||||||
|
@ -325,7 +326,7 @@ func TestAssetGetPrecision(t *testing.T) {
|
||||||
func createVMAndPushBlock(t *testing.T) (*vm.VM, *Block, *interopContext) {
|
func createVMAndPushBlock(t *testing.T) (*vm.VM, *Block, *interopContext) {
|
||||||
v := vm.New()
|
v := vm.New()
|
||||||
block := newDumbBlock()
|
block := newDumbBlock()
|
||||||
context := newInteropContext(0x10, newTestChain(t), storage.NewMemoryStore(), block, nil)
|
context := newInteropContext(trigger.Application, newTestChain(t), storage.NewMemoryStore(), block, nil)
|
||||||
v.Estack().PushVal(vm.NewInteropItem(block))
|
v.Estack().PushVal(vm.NewInteropItem(block))
|
||||||
return v, block, context
|
return v, block, context
|
||||||
}
|
}
|
||||||
|
@ -354,7 +355,7 @@ func createVMAndAssetState(t *testing.T) (*vm.VM, *AssetState, *interopContext)
|
||||||
IsFrozen: false,
|
IsFrozen: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
context := newInteropContext(0x10, newTestChain(t), storage.NewMemoryStore(), nil, nil)
|
context := newInteropContext(trigger.Application, newTestChain(t), storage.NewMemoryStore(), nil, nil)
|
||||||
return v, assetState, context
|
return v, assetState, context
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -373,7 +374,7 @@ func createVMAndContractState(t *testing.T) (*vm.VM, *ContractState, *interopCon
|
||||||
scriptHash: randomUint160(),
|
scriptHash: randomUint160(),
|
||||||
}
|
}
|
||||||
|
|
||||||
context := newInteropContext(0x10, newTestChain(t), storage.NewMemoryStore(), nil, nil)
|
context := newInteropContext(trigger.Application, newTestChain(t), storage.NewMemoryStore(), nil, nil)
|
||||||
return v, contractState, context
|
return v, contractState, context
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -387,7 +388,7 @@ func createVMAndAccState(t *testing.T) (*vm.VM, *AccountState, *interopContext)
|
||||||
accountState.Votes = []*keys.PublicKey{key}
|
accountState.Votes = []*keys.PublicKey{key}
|
||||||
|
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
context := newInteropContext(0x10, newTestChain(t), storage.NewMemoryStore(), nil, nil)
|
context := newInteropContext(trigger.Application, newTestChain(t), storage.NewMemoryStore(), nil, nil)
|
||||||
return v, accountState, context
|
return v, accountState, context
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -416,6 +417,6 @@ func createVMAndTX(t *testing.T) (*vm.VM, *transaction.Transaction, *interopCont
|
||||||
tx.Attributes = attributes
|
tx.Attributes = attributes
|
||||||
tx.Inputs = inputs
|
tx.Inputs = inputs
|
||||||
tx.Outputs = outputs
|
tx.Outputs = outputs
|
||||||
context := newInteropContext(0x10, newTestChain(t), storage.NewMemoryStore(), nil, tx)
|
context := newInteropContext(trigger.Application, newTestChain(t), storage.NewMemoryStore(), nil, tx)
|
||||||
return v, tx, context
|
return v, tx, context
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"github.com/CityOfZion/neo-go/pkg/core/transaction"
|
"github.com/CityOfZion/neo-go/pkg/core/transaction"
|
||||||
"github.com/CityOfZion/neo-go/pkg/crypto/hash"
|
"github.com/CityOfZion/neo-go/pkg/crypto/hash"
|
||||||
"github.com/CityOfZion/neo-go/pkg/crypto/keys"
|
"github.com/CityOfZion/neo-go/pkg/crypto/keys"
|
||||||
|
"github.com/CityOfZion/neo-go/pkg/smartcontract/trigger"
|
||||||
"github.com/CityOfZion/neo-go/pkg/util"
|
"github.com/CityOfZion/neo-go/pkg/util"
|
||||||
"github.com/CityOfZion/neo-go/pkg/vm"
|
"github.com/CityOfZion/neo-go/pkg/vm"
|
||||||
gherr "github.com/pkg/errors"
|
gherr "github.com/pkg/errors"
|
||||||
|
@ -393,7 +394,7 @@ func (ic *interopContext) checkStorageContext(stc *StorageContext) error {
|
||||||
|
|
||||||
// storageDelete deletes stored key-value pair.
|
// storageDelete deletes stored key-value pair.
|
||||||
func (ic *interopContext) storageDelete(v *vm.VM) error {
|
func (ic *interopContext) storageDelete(v *vm.VM) error {
|
||||||
if ic.trigger != 0x10 && ic.trigger != 0x11 {
|
if ic.trigger != trigger.Application && ic.trigger != trigger.ApplicationR {
|
||||||
return errors.New("can't delete when the trigger is not application")
|
return errors.New("can't delete when the trigger is not application")
|
||||||
}
|
}
|
||||||
stcInterface := v.Estack().Pop().Value()
|
stcInterface := v.Estack().Pop().Value()
|
||||||
|
@ -464,7 +465,7 @@ func (ic *interopContext) storageGetReadOnlyContext(v *vm.VM) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ic *interopContext) putWithContextAndFlags(stc *StorageContext, key []byte, value []byte, isConst bool) error {
|
func (ic *interopContext) putWithContextAndFlags(stc *StorageContext, key []byte, value []byte, isConst bool) error {
|
||||||
if ic.trigger != 0x10 && ic.trigger != 0x11 {
|
if ic.trigger != trigger.Application && ic.trigger != trigger.ApplicationR {
|
||||||
return errors.New("can't delete when the trigger is not application")
|
return errors.New("can't delete when the trigger is not application")
|
||||||
}
|
}
|
||||||
if len(key) > MaxStorageKeyLen {
|
if len(key) > MaxStorageKeyLen {
|
||||||
|
@ -538,7 +539,7 @@ func (ic *interopContext) storageContextAsReadOnly(v *vm.VM) error {
|
||||||
|
|
||||||
// contractDestroy destroys a contract.
|
// contractDestroy destroys a contract.
|
||||||
func (ic *interopContext) contractDestroy(v *vm.VM) error {
|
func (ic *interopContext) contractDestroy(v *vm.VM) error {
|
||||||
if ic.trigger != 0x10 {
|
if ic.trigger != trigger.Application {
|
||||||
return errors.New("can't destroy contract when not triggered by application")
|
return errors.New("can't destroy contract when not triggered by application")
|
||||||
}
|
}
|
||||||
hash := getContextScriptHash(v, 0)
|
hash := getContextScriptHash(v, 0)
|
||||||
|
|
36
pkg/smartcontract/trigger/trigger_type.go
Normal file
36
pkg/smartcontract/trigger/trigger_type.go
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
package trigger
|
||||||
|
|
||||||
|
// Trigger typed used in C# reference node: https://github.com/neo-project/neo/blob/c64748ecbac3baeb8045b16af0d518398a6ced24/neo/SmartContract/TriggerType.cs#L3
|
||||||
|
const (
|
||||||
|
// The verification trigger indicates that the contract is being invoked as a verification function.
|
||||||
|
// The verification function can accept multiple parameters, and should return a boolean value that indicates the validity of the transaction or block.
|
||||||
|
// The entry point of the contract will be invoked if the contract is triggered by Verification:
|
||||||
|
// main(...);
|
||||||
|
// The entry point of the contract must be able to handle this type of invocation.
|
||||||
|
Verification = 0x00
|
||||||
|
|
||||||
|
// The verificationR trigger indicates that the contract is being invoked as a verification function because it is specified as a target of an output of the transaction.
|
||||||
|
// The verification function accepts no parameter, and should return a boolean value that indicates the validity of the transaction.
|
||||||
|
// The entry point of the contract will be invoked if the contract is triggered by VerificationR:
|
||||||
|
// main("receiving", new object[0]);
|
||||||
|
// The receiving function should have the following signature:
|
||||||
|
// public bool receiving()
|
||||||
|
// The receiving function will be invoked automatically when a contract is receiving assets from a transfer.
|
||||||
|
VerificationR = 0x01
|
||||||
|
|
||||||
|
// The application trigger indicates that the contract is being invoked as an application function.
|
||||||
|
// The application function can accept multiple parameters, change the states of the blockchain, and return any type of value.
|
||||||
|
// The contract can have any form of entry point, but we recommend that all contracts should have the following entry point:
|
||||||
|
// public byte[] main(string operation, params object[] args)
|
||||||
|
// The functions can be invoked by creating an InvocationTransaction.
|
||||||
|
Application = 0x10
|
||||||
|
|
||||||
|
// The ApplicationR trigger indicates that the default function received of the contract is being invoked because it is specified as a target of an output of the transaction.
|
||||||
|
// The received function accepts no parameter, changes the states of the blockchain, and returns any type of value.
|
||||||
|
// The entry point of the contract will be invoked if the contract is triggered by ApplicationR:
|
||||||
|
// main("received", new object[0]);
|
||||||
|
// The received function should have the following signature:
|
||||||
|
// public byte[] received()
|
||||||
|
// The received function will be invoked automatically when a contract is receiving assets from a transfer.
|
||||||
|
ApplicationR = 0x11
|
||||||
|
)
|
Loading…
Reference in a new issue