core: init native interops in the genesis block

closes #836
This commit is contained in:
Anna Shaleva 2020-04-20 20:38:47 +03:00 committed by Roman Khimov
parent aa8d4d2f57
commit 869c7d6afa
9 changed files with 56 additions and 17 deletions

View file

@ -197,9 +197,6 @@ func (bc *Blockchain) init() error {
if err != nil { if err != nil {
return err return err
} }
if err := bc.initNative(); err != nil {
return err
}
return bc.storeBlock(genesisBlock) return bc.storeBlock(genesisBlock)
} }
if ver != version { if ver != version {
@ -211,6 +208,10 @@ func (bc *Blockchain) init() error {
// and the genesis block as first block. // and the genesis block as first block.
bc.log.Info("restoring blockchain", zap.String("version", version)) bc.log.Info("restoring blockchain", zap.String("version", version))
if err = bc.registerNative(); err != nil {
return err
}
bHeight, err := bc.dao.GetCurrentBlockHeight() bHeight, err := bc.dao.GetCurrentBlockHeight()
if err != nil { if err != nil {
return err return err
@ -272,19 +273,26 @@ func (bc *Blockchain) init() error {
return nil return nil
} }
func (bc *Blockchain) initNative() error { func (bc *Blockchain) registerNative() error {
ic := bc.newInteropContext(trigger.Application, bc.dao, nil, nil)
gas := native.NewGAS() gas := native.NewGAS()
neo := native.NewNEO() neo := native.NewNEO()
neo.GAS = gas neo.GAS = gas
gas.NEO = neo gas.NEO = neo
if err := gas.Initialize(ic); err != nil { data, err := bc.dao.GetNativeContractState(gas.Hash)
return fmt.Errorf("can't initialize GAS native contract: %v", err) if err != nil {
return err
} }
if err := neo.Initialize(ic); err != nil { if err = gas.InitFromStore(data); err != nil {
return fmt.Errorf("can't initialize NEO native contract: %v", err) return err
}
data, err = bc.dao.GetNativeContractState(neo.Hash)
if err != nil {
return err
}
if err = neo.InitFromStore(data); err != nil {
return err
} }
bc.contracts.SetGAS(gas) bc.contracts.SetGAS(gas)

View file

@ -195,7 +195,7 @@ func TestCreateBasicChain(t *testing.T) {
// use output of issue tx from genesis block as an input // use output of issue tx from genesis block as an input
genesisBlock, err := bc.GetBlock(bc.GetHeaderHash(0)) genesisBlock, err := bc.GetBlock(bc.GetHeaderHash(0))
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 4, len(genesisBlock.Transactions)) require.Equal(t, 5, len(genesisBlock.Transactions))
h := genesisBlock.Transactions[3].Hash() h := genesisBlock.Transactions[3].Hash()
txMoveNeo.AddInput(&transaction.Input{ txMoveNeo.AddInput(&transaction.Input{
PrevHash: h, PrevHash: h,

View file

@ -2,6 +2,7 @@ package native
import ( import (
"errors" "errors"
"fmt"
"github.com/nspcc-dev/neo-go/pkg/core/interop" "github.com/nspcc-dev/neo-go/pkg/core/interop"
"github.com/nspcc-dev/neo-go/pkg/vm" "github.com/nspcc-dev/neo-go/pkg/vm"
@ -12,5 +13,16 @@ func Deploy(ic *interop.Context, _ *vm.VM) error {
if ic.Block.Index != 0 { if ic.Block.Index != 0 {
return errors.New("native contracts can be deployed only at 0 block") return errors.New("native contracts can be deployed only at 0 block")
} }
gas := NewGAS()
neo := NewNEO()
neo.GAS = gas
gas.NEO = neo
if err := gas.Initialize(ic); err != nil {
return fmt.Errorf("can't initialize GAS native contract: %v", err)
}
if err := neo.Initialize(ic); err != nil {
return fmt.Errorf("can't initialize NEO native contract: %v", err)
}
return nil return nil
} }

View file

@ -45,7 +45,7 @@ func NewGAS() *GAS {
} }
// initFromStore initializes variable contract parameters from the store. // initFromStore initializes variable contract parameters from the store.
func (g *GAS) initFromStore(data []byte) error { func (g *GAS) InitFromStore(data []byte) error {
g.totalSupply = *emit.BytesToInt(data) g.totalSupply = *emit.BytesToInt(data)
return nil return nil
} }
@ -68,7 +68,7 @@ func (g *GAS) increaseBalance(_ *interop.Context, acc *state.Account, amount *bi
func (g *GAS) Initialize(ic *interop.Context) error { func (g *GAS) Initialize(ic *interop.Context) error {
data, err := ic.DAO.GetNativeContractState(g.Hash) data, err := ic.DAO.GetNativeContractState(g.Hash)
if err == nil { if err == nil {
return g.initFromStore(data) return g.InitFromStore(data)
} else if err != storage.ErrKeyNotFound { } else if err != storage.ErrKeyNotFound {
return err return err
} }

View file

@ -76,7 +76,7 @@ func NewNEO() *NEO {
func (n *NEO) Initialize(ic *interop.Context) error { func (n *NEO) Initialize(ic *interop.Context) error {
data, err := ic.DAO.GetNativeContractState(n.Hash) data, err := ic.DAO.GetNativeContractState(n.Hash)
if err == nil { if err == nil {
return n.initFromStore(data) return n.InitFromStore(data)
} else if err != storage.ErrKeyNotFound { } else if err != storage.ErrKeyNotFound {
return err return err
} }
@ -101,7 +101,7 @@ func (n *NEO) Initialize(ic *interop.Context) error {
} }
// initFromStore initializes variable contract parameters from the store. // initFromStore initializes variable contract parameters from the store.
func (n *NEO) initFromStore(data []byte) error { func (n *NEO) InitFromStore(data []byte) error {
n.totalSupply = *emit.BytesToInt(data) n.totalSupply = *emit.BytesToInt(data)
return nil return nil
} }

View file

@ -8,8 +8,10 @@ import (
"github.com/nspcc-dev/neo-go/pkg/core/transaction" "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/hash"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys" "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/smartcontract"
"github.com/nspcc-dev/neo-go/pkg/util" "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" "github.com/nspcc-dev/neo-go/pkg/vm/opcode"
) )
@ -86,6 +88,7 @@ func createGenesisBlock(cfg config.ProtocolConfiguration) (*block.Block, error)
&governingTokenTX, &governingTokenTX,
&utilityTokenTX, &utilityTokenTX,
issueTx, issueTx,
deployNativeContracts(),
}, },
} }
@ -96,6 +99,22 @@ func createGenesisBlock(cfg config.ProtocolConfiguration) (*block.Block, error)
return b, nil return b, nil
} }
func deployNativeContracts() *transaction.Transaction {
buf := io.NewBufBinWriter()
emit.Syscall(buf.BinWriter, "Neo.Native.Deploy")
script := buf.Bytes()
tx := transaction.NewInvocationTX(script, 0)
tx.Nonce = 0
tx.Sender = hash.Hash160([]byte{byte(opcode.PUSH1)})
tx.Scripts = []transaction.Witness{
{
InvocationScript: []byte{},
VerificationScript: []byte{byte(opcode.PUSH1)},
},
}
return tx
}
func init() { func init() {
admin := hash.Hash160([]byte{byte(opcode.OLDPUSH1)}) admin := hash.Hash160([]byte{byte(opcode.OLDPUSH1)})
registerTX := &transaction.RegisterTX{ registerTX := &transaction.RegisterTX{

View file

@ -20,7 +20,7 @@ func TestGenesisBlockMainNet(t *testing.T) {
// have been changed. Consequently, hash of the genesis block has been changed. // have been changed. Consequently, hash of the genesis block has been changed.
// Update expected genesis block hash for better times. // Update expected genesis block hash for better times.
// Old hash is "d42561e3d30e15be6400b6df2f328e02d2bf6354c41dce433bc57687c82144bf" // Old hash is "d42561e3d30e15be6400b6df2f328e02d2bf6354c41dce433bc57687c82144bf"
expect := "931161239581bcd90b73d092483dee6b7bf2162e66df7e15c3a276a22b4c9422" expect := "094c2c2db5dcb868d85aa4d652aed23bc67e7166f53223a228e382265b1be84b"
assert.Equal(t, expect, block.Hash().StringLE()) assert.Equal(t, expect, block.Hash().StringLE())
} }

View file

@ -408,7 +408,7 @@ var rpcTestCases = map[string][]rpcTestCase{
"getblockheader": { "getblockheader": {
{ {
name: "invalid verbose type", name: "invalid verbose type",
params: `["614a9085dc55fd0539ad3a9d68d8b8e7c52328da905c87bfe8cfca57a5c3c02f", true]`, params: `["9673799c5b5a294427401cb07d6cc615ada3a0d5c5bf7ed6f0f54f24abb2e2ac", true]`,
fail: true, fail: true,
}, },
{ {

Binary file not shown.