Skip to content

Commit

Permalink
native: drop Neo.Native.Deploy, move contract init to management cont…
Browse files Browse the repository at this point in the history
…ract

The contract is almost a stub at the moment, though it does deploy other
contracts.
  • Loading branch information
roman-khimov committed Dec 13, 2020
1 parent 090bee8 commit ff789f6
Show file tree
Hide file tree
Showing 15 changed files with 127 additions and 98 deletions.
Binary file modified cli/testdata/chain50x2.acc
Binary file not shown.
22 changes: 10 additions & 12 deletions pkg/core/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -600,18 +600,16 @@ func (bc *Blockchain) storeBlock(block *block.Block, txpool *mempool.Pool) error
}
writeBuf.Reset()

if block.Index > 0 {
aer, err := bc.runPersist(bc.contracts.GetPersistScript(), block, cache, trigger.OnPersist)
if err != nil {
return fmt.Errorf("onPersist failed: %w", err)
}
appExecResults = append(appExecResults, aer)
err = cache.PutAppExecResult(aer, writeBuf)
if err != nil {
return fmt.Errorf("failed to store onPersist exec result: %w", err)
}
writeBuf.Reset()
aer, err := bc.runPersist(bc.contracts.GetPersistScript(), block, cache, trigger.OnPersist)
if err != nil {
return fmt.Errorf("onPersist failed: %w", err)
}
appExecResults = append(appExecResults, aer)
err = cache.PutAppExecResult(aer, writeBuf)
if err != nil {
return fmt.Errorf("failed to store onPersist exec result: %w", err)
}
writeBuf.Reset()

for _, tx := range block.Transactions {
if err := cache.StoreAsTransaction(tx, block.Index, writeBuf); err != nil {
Expand Down Expand Up @@ -673,7 +671,7 @@ func (bc *Blockchain) storeBlock(block *block.Block, txpool *mempool.Pool) error
}
}

aer, err := bc.runPersist(bc.contracts.GetPostPersistScript(), block, cache, trigger.PostPersist)
aer, err = bc.runPersist(bc.contracts.GetPostPersistScript(), block, cache, trigger.PostPersist)
if err != nil {
return fmt.Errorf("postPersist failed: %w", err)
}
Expand Down
17 changes: 12 additions & 5 deletions pkg/core/blockchain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -713,11 +713,18 @@ func TestVerifyTx(t *testing.T) {
require.True(t, errors.Is(bc.VerifyTx(tx), ErrHasConflicts))
})
t.Run("attribute on-chain conflict", func(t *testing.T) {
b, err := bc.GetBlock(bc.GetHeaderHash(0))
require.NoError(t, err)
conflictsHash := b.Transactions[0].Hash()
tx := getConflictsTx(conflictsHash)
require.Error(t, bc.VerifyTx(tx))
tx := transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0)
tx.ValidUntilBlock = 4242
tx.Signers = []transaction.Signer{{
Account: testchain.MultisigScriptHash(),
Scopes: transaction.None,
}}
require.NoError(t, testchain.SignTx(bc, tx))
b := bc.newBlock(tx)

require.NoError(t, bc.AddBlock(b))
txConflict := getConflictsTx(tx.Hash())
require.Error(t, bc.VerifyTx(txConflict))
})
t.Run("positive", func(t *testing.T) {
tx := getConflictsTx(random.Uint256())
Expand Down
2 changes: 1 addition & 1 deletion pkg/core/dao/dao.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ func (dao *Simple) DeleteContractState(hash util.Uint160) error {

// GetAndUpdateNextContractID returns id for the next contract and increases stored ID.
func (dao *Simple) GetAndUpdateNextContractID() (int32, error) {
var id int32
var id = int32(1)
key := storage.SYSContractID.Bytes()
data, err := dao.Store.Get(key)
if err == nil {
Expand Down
6 changes: 3 additions & 3 deletions pkg/core/dao/dao_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,13 +73,13 @@ func TestSimple_GetAndUpdateNextContractID(t *testing.T) {
dao := NewSimple(storage.NewMemoryStore(), netmode.UnitTestNet, false)
id, err := dao.GetAndUpdateNextContractID()
require.NoError(t, err)
require.EqualValues(t, 0, id)
id, err = dao.GetAndUpdateNextContractID()
require.NoError(t, err)
require.EqualValues(t, 1, id)
id, err = dao.GetAndUpdateNextContractID()
require.NoError(t, err)
require.EqualValues(t, 2, id)
id, err = dao.GetAndUpdateNextContractID()
require.NoError(t, err)
require.EqualValues(t, 3, id)
}

func TestPutGetAppExecResult(t *testing.T) {
Expand Down
2 changes: 0 additions & 2 deletions pkg/core/interop/interopnames/names.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@ const (
NeoCryptoSHA256 = "Neo.Crypto.SHA256"
NeoCryptoRIPEMD160 = "Neo.Crypto.RIPEMD160"
NeoNativeCall = "Neo.Native.Call"
NeoNativeDeploy = "Neo.Native.Deploy"
)

var names = []string{
Expand Down Expand Up @@ -140,5 +139,4 @@ var names = []string{
NeoCryptoSHA256,
NeoCryptoRIPEMD160,
NeoNativeCall,
NeoNativeDeploy,
}
2 changes: 1 addition & 1 deletion pkg/core/interop_system_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -718,7 +718,7 @@ func TestContractCreate(t *testing.T) {

ic.Tx = transaction.New(netmode.UnitTestNet, []byte{1}, 0)
ic.Tx.Signers = append(ic.Tx.Signers, transaction.Signer{Account: sender})
cs.ID = 0
cs.ID = 1
cs.Hash = state.CreateContractHash(sender, cs.Script)

t.Run("missing NEF", func(t *testing.T) {
Expand Down
1 change: 0 additions & 1 deletion pkg/core/interops.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,6 @@ var neoInterops = []interop.Function{
{Name: interopnames.NeoCryptoSHA256, Func: crypto.Sha256, Price: 1000000, ParamCount: 1},
{Name: interopnames.NeoCryptoRIPEMD160, Func: crypto.RipeMD160, Price: 1000000, ParamCount: 1},
{Name: interopnames.NeoNativeCall, Func: native.Call, Price: 0, RequiredFlags: smartcontract.AllowCall, ParamCount: 1, DisallowCallback: true},
{Name: interopnames.NeoNativeDeploy, Func: native.Deploy, Price: 0, RequiredFlags: smartcontract.WriteStates, DisallowCallback: true},
}

// initIDinInteropsSlice initializes IDs from names in one given
Expand Down
19 changes: 12 additions & 7 deletions pkg/core/native/contract.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,14 @@ const reservedContractID = -100

// Contracts is a set of registered native contracts.
type Contracts struct {
NEO *NEO
GAS *GAS
Policy *Policy
Oracle *Oracle
Designate *Designate
Notary *Notary
Contracts []interop.Contract
Management *Management
NEO *NEO
GAS *GAS
Policy *Policy
Oracle *Oracle
Designate *Designate
Notary *Notary
Contracts []interop.Contract
// persistScript is vm script which executes "onPersist" method of every native contract.
persistScript []byte
// postPersistScript is vm script which executes "postPersist" method of every native contract.
Expand Down Expand Up @@ -54,6 +55,10 @@ func (cs *Contracts) ByName(name string) interop.Contract {
func NewContracts(p2pSigExtensionsEnabled bool) *Contracts {
cs := new(Contracts)

mgmt := newManagement()
cs.Management = mgmt
cs.Contracts = append(cs.Contracts, mgmt)

gas := newGAS()
neo := newNEO()
neo.GAS = gas
Expand Down
26 changes: 0 additions & 26 deletions pkg/core/native/interop.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,36 +5,10 @@ import (
"fmt"

"github.com/nspcc-dev/neo-go/pkg/core/interop"
"github.com/nspcc-dev/neo-go/pkg/core/state"
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
"github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger"
)

// Deploy deploys native contract.
func Deploy(ic *interop.Context) error {
if ic.Block == nil || ic.Block.Index != 0 {
return errors.New("native contracts can be deployed only at 0 block")
}

for _, native := range ic.Natives {
md := native.Metadata()

cs := &state.Contract{
ID: md.ContractID,
Hash: md.Hash,
Script: md.Script,
Manifest: md.Manifest,
}
if err := ic.DAO.PutContractState(cs); err != nil {
return err
}
if err := native.Initialize(ic); err != nil {
return fmt.Errorf("initializing %s native contract: %w", md.Name, err)
}
}
return nil
}

// Call calls specified native contract method.
func Call(ic *interop.Context) error {
name := ic.VM.Estack().Pop().String()
Expand Down
72 changes: 72 additions & 0 deletions pkg/core/native/management.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package native

import (
"fmt"
"sync"

"github.com/nspcc-dev/neo-go/pkg/core/interop"
"github.com/nspcc-dev/neo-go/pkg/core/state"
)

// Management is contract-managing native contract.
type Management struct {
interop.ContractMD

lock sync.RWMutex
isValid bool
nextID int32
}

const (
managementName = "Neo Contract Management"
prefixContract = 8
prefixNextAvailableId = 15
)

// newManagement creates new Management native contract.
func newManagement() *Management {
var m = &Management{ContractMD: *interop.NewContractMD(managementName)}

return m
}

// Metadata implements Contract interface.
func (m *Management) Metadata() *interop.ContractMD {
return &m.ContractMD
}

// OnPersist implements Contract interface.
func (m *Management) OnPersist(ic *interop.Context) error {
if ic.Block.Index != 0 { // We're only deploying at 0 at the moment.
return nil
}

for _, native := range ic.Natives {
md := native.Metadata()

cs := &state.Contract{
ID: md.ContractID,
Hash: md.Hash,
Script: md.Script,
Manifest: md.Manifest,
}
if err := ic.DAO.PutContractState(cs); err != nil {
return err
}
if err := native.Initialize(ic); err != nil {
return fmt.Errorf("initializing %s native contract: %w", md.Name, err)
}
}

return nil
}

// PostPersist implements Contract interface.
func (m *Management) PostPersist(_ *interop.Context) error {
return nil
}

// Initialize implements Contract interface.
func (m *Management) Initialize(_ *interop.Context) error {
return nil
}
31 changes: 2 additions & 29 deletions pkg/core/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,12 @@ import (
"time"

"github.com/nspcc-dev/neo-go/pkg/config"
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
"github.com/nspcc-dev/neo-go/pkg/core/block"
"github.com/nspcc-dev/neo-go/pkg/core/interop/interopnames"
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neo-go/pkg/io"
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
"github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neo-go/pkg/vm/emit"
"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
)

Expand Down Expand Up @@ -56,10 +52,8 @@ func createGenesisBlock(cfg config.ProtocolConfiguration) (*block.Block, error)
}

b := &block.Block{
Base: base,
Transactions: []*transaction.Transaction{
deployNativeContracts(cfg.Magic),
},
Base: base,
Transactions: []*transaction.Transaction{},
ConsensusData: block.ConsensusData{
PrimaryIndex: 0,
Nonce: 2083236893,
Expand All @@ -70,27 +64,6 @@ func createGenesisBlock(cfg config.ProtocolConfiguration) (*block.Block, error)
return b, nil
}

func deployNativeContracts(magic netmode.Magic) *transaction.Transaction {
buf := io.NewBufBinWriter()
emit.Syscall(buf.BinWriter, interopnames.NeoNativeDeploy)
script := buf.Bytes()
tx := transaction.New(magic, script, 0)
tx.Nonce = 0
tx.Signers = []transaction.Signer{
{
Account: hash.Hash160([]byte{byte(opcode.PUSH1)}),
Scopes: transaction.None,
},
}
tx.Scripts = []transaction.Witness{
{
InvocationScript: []byte{},
VerificationScript: []byte{byte(opcode.PUSH1)},
},
}
return tx
}

func validatorsFromConfig(cfg config.ProtocolConfiguration) ([]*keys.PublicKey, error) {
vs, err := committeeFromConfig(cfg)
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion pkg/core/util_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ func TestGenesisBlockMainNet(t *testing.T) {
block, err := createGenesisBlock(cfg.ProtocolConfiguration)
require.NoError(t, err)

expect := "ecaee33262f1bc7c7c28f2b25b54a5d61d50670871f45c0c6fe755a40cbde4a8"
expect := "00c6803707b564153d444bfcdf3a13325fc96dda55cc8a740bbd543a1d752fda"
assert.Equal(t, expect, block.Hash().StringLE())
}

Expand Down
Loading

0 comments on commit ff789f6

Please sign in to comment.