Merge pull request #1686 from nspcc-dev/update-contract-hash-calculations

Update contract hash calculation scheme
This commit is contained in:
Roman Khimov 2021-01-22 14:20:23 +03:00 committed by GitHub
commit 524c1238e8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 98 additions and 65 deletions

View file

@ -17,6 +17,7 @@ import (
"github.com/nspcc-dev/neo-go/pkg/encoding/address" "github.com/nspcc-dev/neo-go/pkg/encoding/address"
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn" "github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
"github.com/nspcc-dev/neo-go/pkg/rpc/response/result" "github.com/nspcc-dev/neo-go/pkg/rpc/response/result"
"github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest"
"github.com/nspcc-dev/neo-go/pkg/smartcontract/nef" "github.com/nspcc-dev/neo-go/pkg/smartcontract/nef"
"github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neo-go/pkg/vm" "github.com/nspcc-dev/neo-go/pkg/vm"
@ -33,28 +34,37 @@ func TestCalcHash(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
nefF, err := nef.FileFromBytes(src) nefF, err := nef.FileFromBytes(src)
require.NoError(t, err) require.NoError(t, err)
manifestPath := "./testdata/verify.manifest.json"
manifestBytes, err := ioutil.ReadFile(manifestPath)
require.NoError(t, err)
manif := &manifest.Manifest{}
err = json.Unmarshal(manifestBytes, manif)
require.NoError(t, err)
sender := random.Uint160() sender := random.Uint160()
cmd := []string{"neo-go", "contract", "calc-hash"} cmd := []string{"neo-go", "contract", "calc-hash"}
t.Run("no sender", func(t *testing.T) { t.Run("no sender", func(t *testing.T) {
e.RunWithError(t, append(cmd, "--in", nefPath)...) e.RunWithError(t, append(cmd, "--in", nefPath, "--manifest", manifestPath)...)
}) })
t.Run("no nef file", func(t *testing.T) { t.Run("no nef file", func(t *testing.T) {
e.RunWithError(t, append(cmd, "--sender", sender.StringLE())...) e.RunWithError(t, append(cmd, "--sender", sender.StringLE(), "--manifest", manifestPath)...)
})
t.Run("no manifest file", func(t *testing.T) {
e.RunWithError(t, append(cmd, "--sender", sender.StringLE(), "--in", nefPath)...)
}) })
t.Run("invalid path", func(t *testing.T) { t.Run("invalid path", func(t *testing.T) {
e.RunWithError(t, append(cmd, "--sender", sender.StringLE(), e.RunWithError(t, append(cmd, "--sender", sender.StringLE(),
"--in", "./testdata/verify.nef123")...) "--in", "./testdata/verify.nef123", "--manifest", manifestPath)...)
}) })
t.Run("invalid file", func(t *testing.T) { t.Run("invalid file", func(t *testing.T) {
p := path.Join(os.TempDir(), "neogo.calchash.verify.nef") p := path.Join(os.TempDir(), "neogo.calchash.verify.nef")
defer os.Remove(p) defer os.Remove(p)
require.NoError(t, ioutil.WriteFile(p, src[:4], os.ModePerm)) require.NoError(t, ioutil.WriteFile(p, src[:4], os.ModePerm))
e.RunWithError(t, append(cmd, "--sender", sender.StringLE(), "--in", p)...) e.RunWithError(t, append(cmd, "--sender", sender.StringLE(), "--in", p, "--manifest", manifestPath)...)
}) })
cmd = append(cmd, "--in", nefPath) cmd = append(cmd, "--in", nefPath, "--manifest", manifestPath)
expected := state.CreateContractHash(sender, nefF.Script) expected := state.CreateContractHash(sender, nefF.Checksum, manif.Name)
t.Run("valid, uint160", func(t *testing.T) { t.Run("valid, uint160", func(t *testing.T) {
e.Run(t, append(cmd, "--sender", sender.StringLE())...) e.Run(t, append(cmd, "--sender", sender.StringLE())...)
e.checkNextLine(t, expected.StringLE()) e.checkNextLine(t, expected.StringLE())
@ -193,7 +203,8 @@ func TestComlileAndInvokeFunction(t *testing.T) {
t.Run("check calc hash", func(t *testing.T) { t.Run("check calc hash", func(t *testing.T) {
e.Run(t, "neo-go", "contract", "calc-hash", e.Run(t, "neo-go", "contract", "calc-hash",
"--sender", validatorAddr, "--in", nefName) "--sender", validatorAddr, "--in", nefName,
"--manifest", manifestName)
e.checkNextLine(t, h.StringLE()) e.checkNextLine(t, h.StringLE())
}) })

View file

@ -351,6 +351,10 @@ func NewCommands() []cli.Command {
Name: "in", Name: "in",
Usage: "path to NEF file", Usage: "path to NEF file",
}, },
cli.StringFlag{
Name: "manifest, m",
Usage: "path to manifest file",
},
}, },
}, },
}, },
@ -473,6 +477,10 @@ func calcHash(ctx *cli.Context) error {
if p == "" { if p == "" {
return cli.NewExitError(errors.New("no .nef file was provided"), 1) return cli.NewExitError(errors.New("no .nef file was provided"), 1)
} }
mpath := ctx.String("manifest")
if mpath == "" {
return cli.NewExitError(errors.New("no manifest file provided"), 1)
}
f, err := ioutil.ReadFile(p) f, err := ioutil.ReadFile(p)
if err != nil { if err != nil {
return cli.NewExitError(fmt.Errorf("can't read .nef file: %w", err), 1) return cli.NewExitError(fmt.Errorf("can't read .nef file: %w", err), 1)
@ -481,7 +489,16 @@ func calcHash(ctx *cli.Context) error {
if err != nil { if err != nil {
return cli.NewExitError(fmt.Errorf("can't unmarshal .nef file: %w", err), 1) return cli.NewExitError(fmt.Errorf("can't unmarshal .nef file: %w", err), 1)
} }
fmt.Fprintln(ctx.App.Writer, "Contract hash:", state.CreateContractHash(u, nefFile.Script).StringLE()) manifestBytes, err := ioutil.ReadFile(mpath)
if err != nil {
return cli.NewExitError(fmt.Errorf("failed to read manifest file: %w", err), 1)
}
m := &manifest.Manifest{}
err = json.Unmarshal(manifestBytes, m)
if err != nil {
return cli.NewExitError(fmt.Errorf("failed to restore manifest file: %w", err), 1)
}
fmt.Fprintln(ctx.App.Writer, "Contract hash:", state.CreateContractHash(u, nefFile.Checksum, m.Name).StringLE())
return nil return nil
} }
@ -842,7 +859,7 @@ func contractDeploy(ctx *cli.Context) error {
if err != nil { if err != nil {
return cli.NewExitError(fmt.Errorf("failed to push invocation tx: %w", err), 1) return cli.NewExitError(fmt.Errorf("failed to push invocation tx: %w", err), 1)
} }
hash := state.CreateContractHash(sender, nefFile.Script) hash := state.CreateContractHash(sender, nefFile.Checksum, m.Name)
fmt.Fprintf(ctx.App.Writer, "Contract: %s\n", hash.StringLE()) fmt.Fprintf(ctx.App.Writer, "Contract: %s\n", hash.StringLE())
fmt.Fprintln(ctx.App.Writer, txHash.StringLE()) fmt.Fprintln(ctx.App.Writer, txHash.StringLE())
return nil return nil

Binary file not shown.

View file

@ -84,7 +84,7 @@ func NewDeployTx(bc blockchainer.Blockchainer, name string, sender util.Uint160,
tx := transaction.New(Network(), buf.Bytes(), 100*native.GASFactor) tx := transaction.New(Network(), buf.Bytes(), 100*native.GASFactor)
tx.Signers = []transaction.Signer{{Account: sender}} tx.Signers = []transaction.Signer{{Account: sender}}
h := state.CreateContractHash(tx.Sender(), avm) h := state.CreateContractHash(tx.Sender(), ne.Checksum, name)
return tx, h, nil return tx, h, nil
} }

View file

@ -1395,7 +1395,7 @@ func (bc *Blockchain) verifyTxAttributes(tx *transaction.Transaction, isPartialT
if !hasOracle { if !hasOracle {
return fmt.Errorf("%w: oracle tx is not signed by oracle nodes", ErrInvalidAttribute) return fmt.Errorf("%w: oracle tx is not signed by oracle nodes", ErrInvalidAttribute)
} }
if !bytes.Equal(tx.Script, native.GetOracleResponseScript()) { if !bytes.Equal(tx.Script, bc.contracts.Oracle.GetOracleResponseScript()) {
return fmt.Errorf("%w: oracle tx has invalid script", ErrInvalidAttribute) return fmt.Errorf("%w: oracle tx has invalid script", ErrInvalidAttribute)
} }
resp := tx.Attributes[i].Value.(*transaction.OracleResponse) resp := tx.Attributes[i].Value.(*transaction.OracleResponse)

View file

@ -500,7 +500,7 @@ func TestVerifyTx(t *testing.T) {
// We need to create new transaction, // We need to create new transaction,
// because hashes are cached after signing. // because hashes are cached after signing.
getOracleTx := func(t *testing.T) *transaction.Transaction { getOracleTx := func(t *testing.T) *transaction.Transaction {
tx := bc.newTestTx(h, native.GetOracleResponseScript()) tx := bc.newTestTx(h, orc.GetOracleResponseScript())
resp := &transaction.OracleResponse{ resp := &transaction.OracleResponse{
ID: 1, ID: 1,
Code: transaction.Success, Code: transaction.Success,
@ -556,11 +556,11 @@ func TestVerifyTx(t *testing.T) {
}) })
tx.Scripts = append(tx.Scripts, transaction.Witness{}) tx.Scripts = append(tx.Scripts, transaction.Witness{})
t.Run("NonZeroVerification", func(t *testing.T) { t.Run("NonZeroVerification", func(t *testing.T) {
script, _ := state.CreateNativeContractHash(-6) //oracleContractID
w := io.NewBufBinWriter() w := io.NewBufBinWriter()
emit.Opcodes(w.BinWriter, opcode.ABORT) emit.Opcodes(w.BinWriter, opcode.ABORT)
emit.Bytes(w.BinWriter, util.Uint160{}.BytesBE()) emit.Bytes(w.BinWriter, util.Uint160{}.BytesBE())
emit.Bytes(w.BinWriter, script) emit.Int(w.BinWriter, int64(orc.NEF.Checksum))
emit.String(w.BinWriter, orc.Manifest.Name)
tx.Scripts[len(tx.Scripts)-1].VerificationScript = w.Bytes() tx.Scripts[len(tx.Scripts)-1].VerificationScript = w.Bytes()
err := bc.VerifyTx(tx) err := bc.VerifyTx(tx)
require.True(t, errors.Is(err, ErrNativeContractWitness), "got: %v", err) require.True(t, errors.Is(err, ErrNativeContractWitness), "got: %v", err)

View file

@ -119,8 +119,9 @@ func NewContractMD(name string, id int32) *ContractMD {
// Therefore values are taken from C# node. // Therefore values are taken from C# node.
c.NEF.Header.Compiler = "neo-core-v3.0" c.NEF.Header.Compiler = "neo-core-v3.0"
c.NEF.Header.Magic = nef.Magic c.NEF.Header.Magic = nef.Magic
c.NEF.Script, c.Hash = state.CreateNativeContractHash(id) c.NEF.Script = state.CreateNativeContractScript(id)
c.NEF.Checksum = c.NEF.CalculateChecksum() c.NEF.Checksum = c.NEF.CalculateChecksum()
c.Hash = state.CreateContractHash(util.Uint160{}, c.NEF.Checksum, name)
c.Manifest = *manifest.DefaultManifest(name) c.Manifest = *manifest.DefaultManifest(name)
return c return c

View file

@ -8,12 +8,12 @@ import (
// Compatibility test. hashes are taken directly from C# node. // Compatibility test. hashes are taken directly from C# node.
func TestNativeHashes(t *testing.T) { func TestNativeHashes(t *testing.T) {
require.Equal(t, "bee421fdbb3e791265d2104cb34934f53fcc0e45", newManagement().Hash.StringLE()) require.Equal(t, "a501d7d7d10983673b61b7a2d3a813b36f9f0e43", newManagement().Hash.StringLE())
require.Equal(t, "4961bf0ab79370b23dc45cde29f568d0e0fa6e93", newNEO().Hash.StringLE()) require.Equal(t, "f617baca689d1abddedda7c3b80675c4ac21e932", newNEO().Hash.StringLE())
require.Equal(t, "9ac04cf223f646de5f7faccafe34e30e5d4382a2", newGAS().Hash.StringLE()) require.Equal(t, "75844530eb44f4715a42950bb59b4d7ace0b2f3d", newGAS().Hash.StringLE())
require.Equal(t, "c939a4af1c762e5edca36d4b61c06ba82c4c6ff5", newPolicy().Hash.StringLE()) require.Equal(t, "e21a28cfc1e662e152f668c86198141cc17b6c37", newPolicy().Hash.StringLE())
require.Equal(t, "f4bbd95569e8dda2cb84eb609a1488ddd0d9fa91", newDesignate(false).Hash.StringLE()) require.Equal(t, "69b1909aaa14143b0624ba0d61d5cd3b8b67529d", newDesignate(false).Hash.StringLE())
require.Equal(t, "8cd3889136056b3304ec59f6d424b8767710ed79", newOracle().Hash.StringLE()) require.Equal(t, "b82bbf650f963dbf71577d10ea4077e711a13e7b", newOracle().Hash.StringLE())
// Not yet a part of NEO. // Not yet a part of NEO.
//require.Equal(t, "", newNotary().Hash.StringLE()()) //require.Equal(t, "", newNotary().Hash.StringLE()())
} }

View file

@ -239,7 +239,7 @@ func (m *Management) markUpdated(h util.Uint160) {
// Deploy creates contract's hash/ID and saves new contract into the given DAO. // Deploy creates contract's hash/ID and saves new contract into the given DAO.
// It doesn't run _deploy method and doesn't emit notification. // It doesn't run _deploy method and doesn't emit notification.
func (m *Management) Deploy(d dao.DAO, sender util.Uint160, neff *nef.File, manif *manifest.Manifest) (*state.Contract, error) { func (m *Management) Deploy(d dao.DAO, sender util.Uint160, neff *nef.File, manif *manifest.Manifest) (*state.Contract, error) {
h := state.CreateContractHash(sender, neff.Script) h := state.CreateContractHash(sender, neff.Checksum, manif.Name)
key := makeContractKey(h) key := makeContractKey(h)
si := d.GetStorageItem(m.ContractID, key) si := d.GetStorageItem(m.ContractID, key)
if si != nil { if si != nil {

View file

@ -18,13 +18,13 @@ func TestDeployGetUpdateDestroyContract(t *testing.T) {
d := dao.NewSimple(storage.NewMemoryStore(), netmode.UnitTestNet, false) d := dao.NewSimple(storage.NewMemoryStore(), netmode.UnitTestNet, false)
script := []byte{1} script := []byte{1}
sender := util.Uint160{1, 2, 3} sender := util.Uint160{1, 2, 3}
h := state.CreateContractHash(sender, script)
ne, err := nef.NewFile(script) ne, err := nef.NewFile(script)
require.NoError(t, err) require.NoError(t, err)
manif := manifest.NewManifest("Test") manif := manifest.NewManifest("Test")
require.NoError(t, err) require.NoError(t, err)
h := state.CreateContractHash(sender, ne.Checksum, manif.Name)
contract, err := mgmt.Deploy(d, sender, ne, manif) contract, err := mgmt.Deploy(d, sender, ne, manif)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, int32(1), contract.ID) require.Equal(t, int32(1), contract.ID)
@ -43,7 +43,7 @@ func TestDeployGetUpdateDestroyContract(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, int32(2), contract2.ID) require.Equal(t, int32(2), contract2.ID)
require.Equal(t, uint16(0), contract2.UpdateCounter) require.Equal(t, uint16(0), contract2.UpdateCounter)
require.Equal(t, state.CreateContractHash(sender2, script), contract2.Hash) require.Equal(t, state.CreateContractHash(sender2, ne.Checksum, manif.Name), contract2.Hash)
require.Equal(t, ne, &contract2.NEF) require.Equal(t, ne, &contract2.NEF)
require.Equal(t, *manif, contract2.Manifest) require.Equal(t, *manif, contract2.Manifest)

View file

@ -35,6 +35,7 @@ type Oracle struct {
NEO *NEO NEO *NEO
Desig *Designate Desig *Designate
oracleScript []byte
} }
const ( const (
@ -49,20 +50,6 @@ const (
oracleRequestPrice = 5000_0000 oracleRequestPrice = 5000_0000
) )
var oracleScript []byte
func init() {
_, h := state.CreateNativeContractHash(oracleContractID)
w := io.NewBufBinWriter()
emit.Int(w.BinWriter, 0)
emit.Opcodes(w.BinWriter, opcode.NEWARRAY)
emit.Int(w.BinWriter, int64(callflag.All))
emit.String(w.BinWriter, "finish")
emit.Bytes(w.BinWriter, h.BytesBE())
emit.Syscall(w.BinWriter, interopnames.SystemContractCall)
oracleScript = w.Bytes()
}
var ( var (
prefixIDList = []byte{6} prefixIDList = []byte{6}
prefixRequest = []byte{7} prefixRequest = []byte{7}
@ -78,16 +65,18 @@ var (
ErrResponseNotFound = errors.New("oracle response not found") ErrResponseNotFound = errors.New("oracle response not found")
) )
// GetOracleResponseScript returns script for transaction with oracle response.
func GetOracleResponseScript() []byte {
b := make([]byte, len(oracleScript))
copy(b, oracleScript)
return b
}
func newOracle() *Oracle { func newOracle() *Oracle {
o := &Oracle{ContractMD: *interop.NewContractMD(nativenames.Oracle, oracleContractID)} o := &Oracle{ContractMD: *interop.NewContractMD(nativenames.Oracle, oracleContractID)}
w := io.NewBufBinWriter()
emit.Int(w.BinWriter, 0)
emit.Opcodes(w.BinWriter, opcode.NEWARRAY)
emit.Int(w.BinWriter, int64(callflag.All))
emit.String(w.BinWriter, "finish")
emit.Bytes(w.BinWriter, o.Hash.BytesBE())
emit.Syscall(w.BinWriter, interopnames.SystemContractCall)
o.oracleScript = w.Bytes()
desc := newDescriptor("request", smartcontract.VoidType, desc := newDescriptor("request", smartcontract.VoidType,
manifest.NewParameter("url", smartcontract.StringType), manifest.NewParameter("url", smartcontract.StringType),
manifest.NewParameter("filter", smartcontract.StringType), manifest.NewParameter("filter", smartcontract.StringType),
@ -115,6 +104,13 @@ func newOracle() *Oracle {
return o return o
} }
// GetOracleResponseScript returns script for transaction with oracle response.
func (o *Oracle) GetOracleResponseScript() []byte {
b := make([]byte, len(o.oracleScript))
copy(b, o.oracleScript)
return b
}
// OnPersist implements Contract interface. // OnPersist implements Contract interface.
func (o *Oracle) OnPersist(ic *interop.Context) error { func (o *Oracle) OnPersist(ic *interop.Context) error {
return nil return nil

View file

@ -36,7 +36,7 @@ func TestRestoreAfterDeploy(t *testing.T) {
mgmtHash := bc.ManagementContractHash() mgmtHash := bc.ManagementContractHash()
cs1, _ := getTestContractState(bc) cs1, _ := getTestContractState(bc)
cs1.ID = 1 cs1.ID = 1
cs1.Hash = state.CreateContractHash(testchain.MultisigScriptHash(), cs1.NEF.Script) cs1.Hash = state.CreateContractHash(testchain.MultisigScriptHash(), cs1.NEF.Checksum, cs1.Manifest.Name)
manif1, err := json.Marshal(cs1.Manifest) manif1, err := json.Marshal(cs1.Manifest)
require.NoError(t, err) require.NoError(t, err)
nef1, err := nef.NewFile(cs1.NEF.Script) nef1, err := nef.NewFile(cs1.NEF.Script)
@ -80,7 +80,7 @@ func TestContractDeploy(t *testing.T) {
mgmtHash := bc.ManagementContractHash() mgmtHash := bc.ManagementContractHash()
cs1, _ := getTestContractState(bc) cs1, _ := getTestContractState(bc)
cs1.ID = 1 cs1.ID = 1
cs1.Hash = state.CreateContractHash(testchain.MultisigScriptHash(), cs1.NEF.Script) cs1.Hash = state.CreateContractHash(testchain.MultisigScriptHash(), cs1.NEF.Checksum, cs1.Manifest.Name)
manif1, err := json.Marshal(cs1.Manifest) manif1, err := json.Marshal(cs1.Manifest)
require.NoError(t, err) require.NoError(t, err)
nef1b, err := cs1.NEF.Bytes() nef1b, err := cs1.NEF.Bytes()
@ -214,7 +214,7 @@ func TestContractDeploy(t *testing.T) {
checkFAULTState(t, res) checkFAULTState(t, res)
t.Run("get after failed deploy", func(t *testing.T) { t.Run("get after failed deploy", func(t *testing.T) {
h := state.CreateContractHash(neoOwner, deployScript) h := state.CreateContractHash(neoOwner, nefD.Checksum, m.Name)
checkContractState(t, bc, h, nil) checkContractState(t, bc, h, nil)
}) })
}) })
@ -243,7 +243,7 @@ func TestContractDeploy(t *testing.T) {
checkFAULTState(t, res) checkFAULTState(t, res)
t.Run("get after bad _deploy", func(t *testing.T) { t.Run("get after bad _deploy", func(t *testing.T) {
h := state.CreateContractHash(neoOwner, deployScript) h := state.CreateContractHash(neoOwner, nefD.Checksum, m.Name)
checkContractState(t, bc, h, nil) checkContractState(t, bc, h, nil)
}) })
}) })

View file

@ -153,7 +153,7 @@ func TestOracle_Request(t *testing.T) {
err = bc.contracts.Designate.DesignateAsRole(ic, native.RoleOracle, keys.PublicKeys{pub}) err = bc.contracts.Designate.DesignateAsRole(ic, native.RoleOracle, keys.PublicKeys{pub})
require.NoError(t, err) require.NoError(t, err)
tx = transaction.New(netmode.UnitTestNet, native.GetOracleResponseScript(), 0) tx = transaction.New(netmode.UnitTestNet, orc.GetOracleResponseScript(), 0)
ic.Tx = tx ic.Tx = tx
ic.Block = bc.newBlock(tx) ic.Block = bc.newBlock(tx)
@ -203,7 +203,7 @@ func TestOracle_Request(t *testing.T) {
_, err := orc.GetRequestInternal(bc.dao, reqID) // ensure ID is 2 _, err := orc.GetRequestInternal(bc.dao, reqID) // ensure ID is 2
require.NoError(t, err) require.NoError(t, err)
tx = transaction.New(netmode.UnitTestNet, native.GetOracleResponseScript(), 0) tx = transaction.New(netmode.UnitTestNet, orc.GetOracleResponseScript(), 0)
tx.Attributes = []transaction.Attribute{{ tx.Attributes = []transaction.Attribute{{
Type: transaction.OracleResponseT, Type: transaction.OracleResponseT,
Value: &transaction.OracleResponse{ Value: &transaction.OracleResponse{

View file

@ -112,25 +112,25 @@ func (c *Contract) FromStackItem(item stackitem.Item) error {
// CreateContractHash creates deployed contract hash from transaction sender // CreateContractHash creates deployed contract hash from transaction sender
// and contract script. // and contract script.
func CreateContractHash(sender util.Uint160, script []byte) util.Uint160 { func CreateContractHash(sender util.Uint160, checksum uint32, name string) util.Uint160 {
w := io.NewBufBinWriter() w := io.NewBufBinWriter()
emit.Opcodes(w.BinWriter, opcode.ABORT) emit.Opcodes(w.BinWriter, opcode.ABORT)
emit.Bytes(w.BinWriter, sender.BytesBE()) emit.Bytes(w.BinWriter, sender.BytesBE())
emit.Bytes(w.BinWriter, script) emit.Int(w.BinWriter, int64(checksum))
emit.String(w.BinWriter, name)
if w.Err != nil { if w.Err != nil {
panic(w.Err) panic(w.Err)
} }
return hash.Hash160(w.Bytes()) return hash.Hash160(w.Bytes())
} }
// CreateNativeContractHash returns script and hash for the native contract. // CreateNativeContractScript returns script for the native contract.
func CreateNativeContractHash(id int32) ([]byte, util.Uint160) { func CreateNativeContractScript(id int32) []byte {
w := io.NewBufBinWriter() w := io.NewBufBinWriter()
emit.Int(w.BinWriter, int64(id)) emit.Int(w.BinWriter, int64(id))
emit.Syscall(w.BinWriter, interopnames.SystemContractCallNative) emit.Syscall(w.BinWriter, interopnames.SystemContractCallNative)
if w.Err != nil { if w.Err != nil {
panic(w.Err) panic(w.Err)
} }
script := w.Bytes() return w.Bytes()
return script, CreateContractHash(util.Uint160{}, script)
} }

View file

@ -62,14 +62,22 @@ func TestEncodeDecodeContractState(t *testing.T) {
} }
func TestCreateContractHash(t *testing.T) { func TestCreateContractHash(t *testing.T) {
var script = []byte{1, 2, 3} var neff = nef.File{
Header: nef.Header{
Compiler: "test",
Magic: nef.Magic,
},
Tokens: []nef.MethodToken{},
Script: []byte{1, 2, 3},
}
var sender util.Uint160 var sender util.Uint160
var err error var err error
require.Equal(t, "b8e95ff7b11c427c29355e3398722d97bd2ca069", CreateContractHash(sender, script).StringLE()) neff.Checksum = neff.CalculateChecksum()
require.Equal(t, "9b9628e4f1611af90e761eea8cc21372380c74b6", CreateContractHash(sender, neff.Checksum, "").StringLE())
sender, err = util.Uint160DecodeStringLE("a400ff00ff00ff00ff00ff00ff00ff00ff00ff01") sender, err = util.Uint160DecodeStringLE("a400ff00ff00ff00ff00ff00ff00ff00ff00ff01")
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, "435c467b8e15cb9b1474ad7ee817ffdcfededef9", CreateContractHash(sender, script).StringLE()) require.Equal(t, "66eec404d86b918d084e62a29ac9990e3b6f4286", CreateContractHash(sender, neff.Checksum, "").StringLE())
} }
func TestContractFromStackItem(t *testing.T) { func TestContractFromStackItem(t *testing.T) {

View file

@ -56,11 +56,11 @@ type rpcTestCase struct {
check func(t *testing.T, e *executor, result interface{}) check func(t *testing.T, e *executor, result interface{})
} }
const testContractHash = "0b3bc97e94ed99e32dda46c9ecd2d3626979af06" const testContractHash = "c6436aab21ebd15279b85af8d7b5808d38455b0a"
const deploymentTxHash = "e3a67acac29014dc8c24773752ac4535a0f020486749ec5c907234fc9328246c" const deploymentTxHash = "e6ffce4533231c4efdea9a65c7abc0e7073d96a4ebc66f402db3a84b6f8939ef"
const genesisBlockHash = "0542f4350c6e236d0509bcd98188b0034bfbecc1a0c7fcdb8e4295310d468b70" const genesisBlockHash = "0542f4350c6e236d0509bcd98188b0034bfbecc1a0c7fcdb8e4295310d468b70"
const verifyContractHash = "d2da8ee8c0bf6c5bf3dda1ef671dbf5fef7226e9" const verifyContractHash = "03ffc0897543b9b709e0f8cab4a7682dae0ba943"
const verifyContractAVM = "570300412d51083021700c14aa8acf859d4fe402b34e673f2156821796a488ebdb30716813cedb2869db289740" const verifyContractAVM = "570300412d51083021700c14aa8acf859d4fe402b34e673f2156821796a488ebdb30716813cedb2869db289740"
const testVerifyContractAVM = "VwcADBQBDAMOBQYMDQIODw0DDgcJAAAAANswcGgRVUH4J+yMIaonBwAAABFADBQNDwMCCQACAQMHAwQFAgEADgYMCdswcWkRVUH4J+yMIaonBwAAABJAE0A=" const testVerifyContractAVM = "VwcADBQBDAMOBQYMDQIODw0DDgcJAAAAANswcGgRVUH4J+yMIaonBwAAABFADBQNDwMCCQACAQMHAwQFAgEADgYMCdswcWkRVUH4J+yMIaonBwAAABJAE0A="

Binary file not shown.