forked from TrueCloudLab/neoneo-go
Merge pull request #2191 from nspcc-dev/port-nef-source
nef: add Source field
This commit is contained in:
commit
63c939b9fa
20 changed files with 54 additions and 10 deletions
|
@ -601,9 +601,9 @@ func TestCompileExamples(t *testing.T) {
|
|||
})
|
||||
}
|
||||
|
||||
t.Run("invalid events in manifest", func(t *testing.T) {
|
||||
t.Run("invalid manifest", func(t *testing.T) {
|
||||
const dir = "./testdata/"
|
||||
for _, name := range []string{"invalid1", "invalid2", "invalid3"} {
|
||||
for _, name := range []string{"invalid1", "invalid2", "invalid3", "invalid4"} {
|
||||
outF := path.Join(tmpDir, name+".nef")
|
||||
manifestF := path.Join(tmpDir, name+".manifest.json")
|
||||
e.RunWithError(t, "neo-go", "contract", "compile",
|
||||
|
|
|
@ -427,6 +427,7 @@ func initSmartContract(ctx *cli.Context) error {
|
|||
|
||||
m := ProjectConfig{
|
||||
Name: contractName,
|
||||
SourceURL: "http://example.com/",
|
||||
SupportedStandards: []string{},
|
||||
SafeMethods: []string{},
|
||||
Events: []manifest.Event{
|
||||
|
@ -489,6 +490,7 @@ func contractCompile(ctx *cli.Context) error {
|
|||
return err
|
||||
}
|
||||
o.Name = conf.Name
|
||||
o.SourceURL = conf.SourceURL
|
||||
o.ContractEvents = conf.Events
|
||||
o.ContractSupportedStandards = conf.SupportedStandards
|
||||
o.Permissions = make([]manifest.Permission, len(conf.Permissions))
|
||||
|
@ -733,6 +735,7 @@ func testInvokeScript(ctx *cli.Context) error {
|
|||
// ProjectConfig contains project metadata.
|
||||
type ProjectConfig struct {
|
||||
Name string
|
||||
SourceURL string
|
||||
SafeMethods []string
|
||||
SupportedStandards []string
|
||||
Events []manifest.Event
|
||||
|
|
|
@ -59,6 +59,7 @@ func RuntimeNotify(args []interface{}) {
|
|||
require.NoError(t, err)
|
||||
require.Equal(t,
|
||||
`name: testContract
|
||||
sourceurl: http://example.com/
|
||||
safemethods: []
|
||||
supportedstandards: []
|
||||
events:
|
||||
|
|
5
cli/testdata/invalid4/invalid.go
vendored
Normal file
5
cli/testdata/invalid4/invalid.go
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
package invalid4
|
||||
|
||||
func Verify() bool {
|
||||
return true
|
||||
}
|
2
cli/testdata/invalid4/invalid.yml
vendored
Normal file
2
cli/testdata/invalid4/invalid.yml
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
name: Test bad source url
|
||||
sourceurl: http://example.com/with/some/huge/path/that/cant/be/ever/normally/reached/but/we/need/to/test/for/it/anyway/because/there/is/some/path/in/the/code/that/does/this/check/and/it/should/be/triggered/to/ensure/proper/coverage/in/this/particular/component/of/our/perfect/compiler
|
|
@ -1,4 +1,5 @@
|
|||
name: "Engine example"
|
||||
sourceurl: https://github.com/nspcc-dev/neo-go/
|
||||
supportedstandards: []
|
||||
events:
|
||||
- name: Tx
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
name: "Event types example"
|
||||
sourceurl: https://github.com/nspcc-dev/neo-go/
|
||||
supportedstandards: []
|
||||
events:
|
||||
- name: SomeBytes
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
name: "Iterator example"
|
||||
sourceurl: https://github.com/nspcc-dev/neo-go/
|
||||
supportedstandards: []
|
||||
events:
|
||||
- name: found storage key-value pair
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
name: "NameService"
|
||||
sourceurl: https://github.com/nspcc-dev/neo-go/
|
||||
supportedstandards: ["NEP-11"]
|
||||
safemethods: ["balanceOf", "decimals", "symbol", "totalSupply", "tokensOf", "ownerOf",
|
||||
"tokens", "properties", "roots", "getPrice", "isAvailable", "getRecord",
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
name: "HASHY NFT"
|
||||
sourceurl: https://github.com/nspcc-dev/neo-go/
|
||||
supportedstandards: ["NEP-11"]
|
||||
safemethods: ["balanceOf", "decimals", "symbol", "totalSupply", "tokensOf", "ownerOf", "tokens", "properties"]
|
||||
events:
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
name: "Oracle example"
|
||||
sourceurl: https://github.com/nspcc-dev/neo-go/
|
||||
supportedstandards: []
|
||||
events:
|
||||
permissions:
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
name: "Runtime example"
|
||||
sourceurl: https://github.com/nspcc-dev/neo-go/
|
||||
supportedstandards: []
|
||||
events:
|
||||
- name: Event
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
name: "Storage example"
|
||||
sourceurl: https://github.com/nspcc-dev/neo-go/
|
||||
supportedstandards: []
|
||||
events: []
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
name: "Timer example"
|
||||
sourceurl: https://github.com/nspcc-dev/neo-go/
|
||||
supportedstandards: []
|
||||
events: []
|
||||
permissions:
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
name: "My awesome token"
|
||||
sourceurl: https://github.com/nspcc-dev/neo-go/
|
||||
supportedstandards: ["NEP-17"]
|
||||
safemethods: ["balanceOf", "decimals", "symbol", "totalSupply"]
|
||||
events:
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
name: "Awesome NEO Token"
|
||||
sourceurl: https://github.com/nspcc-dev/neo-go/
|
||||
supportedstandards: ["NEP-17"]
|
||||
safemethods: ["balanceOf", "decimals", "symbol", "totalSupply"]
|
||||
events:
|
||||
|
|
|
@ -52,6 +52,9 @@ type Options struct {
|
|||
// Name is contract's name to be written to manifest.
|
||||
Name string
|
||||
|
||||
// SourceURL is contract's source URL to be written to manifest.
|
||||
SourceURL string
|
||||
|
||||
// Runtime notifications.
|
||||
ContractEvents []manifest.Event
|
||||
|
||||
|
@ -199,6 +202,13 @@ func CompileAndSave(src string, o *Options) ([]byte, error) {
|
|||
if err != nil {
|
||||
return nil, fmt.Errorf("error while trying to create .nef file: %w", err)
|
||||
}
|
||||
if o.SourceURL != "" {
|
||||
if len(o.SourceURL) > nef.MaxSourceURLLength {
|
||||
return nil, errors.New("too long source URL")
|
||||
}
|
||||
f.Source = o.SourceURL
|
||||
f.Checksum = f.CalculateChecksum()
|
||||
}
|
||||
bytes, err := f.Bytes()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error while serializing .nef file: %w", err)
|
||||
|
|
1
pkg/rpc/server/testdata/test_contract.yml
vendored
1
pkg/rpc/server/testdata/test_contract.yml
vendored
|
@ -1,4 +1,5 @@
|
|||
name: "Rubl"
|
||||
sourceurl: https://github.com/nspcc-dev/neo-go/
|
||||
supportedstandards: ["NEP-17"]
|
||||
safemethods: ["balanceOf", "decimals", "symbol", "totalSupply"]
|
||||
events:
|
||||
|
|
|
@ -18,8 +18,9 @@ import (
|
|||
// +------------+-----------+------------------------------------------------------------+
|
||||
// | Magic | 4 bytes | Magic header |
|
||||
// | Compiler | 64 bytes | Compiler used and it's version |
|
||||
// | Source | Var bytes | Source file URL. |
|
||||
// +------------+-----------+------------------------------------------------------------+
|
||||
// | Reserved | 2-bytes | Reserved for extensions. Must be 0. |
|
||||
// | Reserved | 1 byte | Reserved for extensions. Must be 0. |
|
||||
// | Tokens | Var array | List of method tokens |
|
||||
// | Reserved | 2-bytes | Reserved for extensions. Must be 0. |
|
||||
// | Script | Var bytes | Var bytes for the payload |
|
||||
|
@ -32,6 +33,8 @@ const (
|
|||
Magic uint32 = 0x3346454E
|
||||
// MaxScriptLength is the maximum allowed contract script length.
|
||||
MaxScriptLength = 512 * 1024
|
||||
// MaxSourceURLLength is the maximum allowed source URL length.
|
||||
MaxSourceURLLength = 256
|
||||
// compilerFieldSize is the length of `Compiler` File header field in bytes.
|
||||
compilerFieldSize = 64
|
||||
)
|
||||
|
@ -39,6 +42,7 @@ const (
|
|||
// File represents compiled contract file structure according to the NEF3 standard.
|
||||
type File struct {
|
||||
Header
|
||||
Source string `json:"source"`
|
||||
Tokens []MethodToken `json:"tokens"`
|
||||
Script []byte `json:"script"`
|
||||
Checksum uint32 `json:"checksum"`
|
||||
|
@ -106,7 +110,12 @@ func (n *File) CalculateChecksum() uint32 {
|
|||
// EncodeBinary implements io.Serializable interface.
|
||||
func (n *File) EncodeBinary(w *io.BinWriter) {
|
||||
n.Header.EncodeBinary(w)
|
||||
w.WriteU16LE(0)
|
||||
if len(n.Source) > MaxSourceURLLength {
|
||||
w.Err = errors.New("source url too long")
|
||||
return
|
||||
}
|
||||
w.WriteString(n.Source)
|
||||
w.WriteB(0)
|
||||
w.WriteArray(n.Tokens)
|
||||
w.WriteU16LE(0)
|
||||
w.WriteVarBytes(n.Script)
|
||||
|
@ -118,13 +127,14 @@ var errInvalidReserved = errors.New("reserved bytes must be 0")
|
|||
// DecodeBinary implements io.Serializable interface.
|
||||
func (n *File) DecodeBinary(r *io.BinReader) {
|
||||
n.Header.DecodeBinary(r)
|
||||
reserved := r.ReadU16LE()
|
||||
if r.Err == nil && reserved != 0 {
|
||||
n.Source = r.ReadString(MaxSourceURLLength)
|
||||
reservedB := r.ReadB()
|
||||
if r.Err == nil && reservedB != 0 {
|
||||
r.Err = errInvalidReserved
|
||||
return
|
||||
}
|
||||
r.ReadArray(&n.Tokens)
|
||||
reserved = r.ReadU16LE()
|
||||
reserved := r.ReadU16LE()
|
||||
if r.Err == nil && reserved != 0 {
|
||||
r.Err = errInvalidReserved
|
||||
return
|
||||
|
|
|
@ -149,6 +149,7 @@ func TestMarshalUnmarshalJSON(t *testing.T) {
|
|||
require.JSONEq(t, `{
|
||||
"magic":`+strconv.FormatUint(uint64(Magic), 10)+`,
|
||||
"compiler": "test.compiler-test.ver",
|
||||
"source": "",
|
||||
"tokens": [
|
||||
{
|
||||
"hash": "0x`+expected.Tokens[0].Hash.StringLE()+`",
|
||||
|
|
Loading…
Reference in a new issue