diff --git a/pkg/core/blockchain.go b/pkg/core/blockchain.go index aab57ddd6..f16d02232 100644 --- a/pkg/core/blockchain.go +++ b/pkg/core/blockchain.go @@ -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) diff --git a/pkg/core/helper_test.go b/pkg/core/helper_test.go index a198fbf71..f54b1ad23 100644 --- a/pkg/core/helper_test.go +++ b/pkg/core/helper_test.go @@ -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, diff --git a/pkg/core/native/interop.go b/pkg/core/native/interop.go index 6b6cec16e..351e226b1 100644 --- a/pkg/core/native/interop.go +++ b/pkg/core/native/interop.go @@ -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 } diff --git a/pkg/core/native/native_gas.go b/pkg/core/native/native_gas.go index 87736f0de..55e1084bf 100644 --- a/pkg/core/native/native_gas.go +++ b/pkg/core/native/native_gas.go @@ -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 } diff --git a/pkg/core/native/native_neo.go b/pkg/core/native/native_neo.go index 71498a187..7624fcb23 100644 --- a/pkg/core/native/native_neo.go +++ b/pkg/core/native/native_neo.go @@ -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 } diff --git a/pkg/core/util.go b/pkg/core/util.go index 2eeb9adea..465e90d11 100644 --- a/pkg/core/util.go +++ b/pkg/core/util.go @@ -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{ diff --git a/pkg/core/util_test.go b/pkg/core/util_test.go index ba870d324..a3b9fc001 100644 --- a/pkg/core/util_test.go +++ b/pkg/core/util_test.go @@ -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()) } diff --git a/pkg/rpc/server/server_test.go b/pkg/rpc/server/server_test.go index 49a494a65..ab5e059de 100644 --- a/pkg/rpc/server/server_test.go +++ b/pkg/rpc/server/server_test.go @@ -408,7 +408,7 @@ var rpcTestCases = map[string][]rpcTestCase{ "getblockheader": { { name: "invalid verbose type", - params: `["614a9085dc55fd0539ad3a9d68d8b8e7c52328da905c87bfe8cfca57a5c3c02f", true]`, + params: `["9673799c5b5a294427401cb07d6cc615ada3a0d5c5bf7ed6f0f54f24abb2e2ac", true]`, fail: true, }, { diff --git a/pkg/rpc/server/testdata/testblocks.acc b/pkg/rpc/server/testdata/testblocks.acc index ab268fe5d..ba7136e26 100644 Binary files a/pkg/rpc/server/testdata/testblocks.acc and b/pkg/rpc/server/testdata/testblocks.acc differ