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

View file

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

View file

@ -2,6 +2,7 @@ package native
import (
"errors"
"fmt"
"github.com/nspcc-dev/neo-go/pkg/core/interop"
"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 {
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
}

View file

@ -45,7 +45,7 @@ func NewGAS() *GAS {
}
// 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)
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 {
data, err := ic.DAO.GetNativeContractState(g.Hash)
if err == nil {
return g.initFromStore(data)
return g.InitFromStore(data)
} else if err != storage.ErrKeyNotFound {
return err
}

View file

@ -76,7 +76,7 @@ func NewNEO() *NEO {
func (n *NEO) Initialize(ic *interop.Context) error {
data, err := ic.DAO.GetNativeContractState(n.Hash)
if err == nil {
return n.initFromStore(data)
return n.InitFromStore(data)
} else if err != storage.ErrKeyNotFound {
return err
}
@ -101,7 +101,7 @@ func (n *NEO) Initialize(ic *interop.Context) error {
}
// 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)
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/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"
)
@ -86,6 +88,7 @@ func createGenesisBlock(cfg config.ProtocolConfiguration) (*block.Block, error)
&governingTokenTX,
&utilityTokenTX,
issueTx,
deployNativeContracts(),
},
}
@ -96,6 +99,22 @@ func createGenesisBlock(cfg config.ProtocolConfiguration) (*block.Block, error)
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() {
admin := hash.Hash160([]byte{byte(opcode.OLDPUSH1)})
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.
// Update expected genesis block hash for better times.
// Old hash is "d42561e3d30e15be6400b6df2f328e02d2bf6354c41dce433bc57687c82144bf"
expect := "931161239581bcd90b73d092483dee6b7bf2162e66df7e15c3a276a22b4c9422"
expect := "094c2c2db5dcb868d85aa4d652aed23bc67e7166f53223a228e382265b1be84b"
assert.Equal(t, expect, block.Hash().StringLE())
}

View file

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

Binary file not shown.