From 52843fc1bf5a8227481c1e0e960a521dc054d8ab Mon Sep 17 00:00:00 2001 From: Evgeniy Stratonikov Date: Mon, 18 Jan 2021 17:05:11 +0300 Subject: [PATCH] nef: add Tokens field --- cli/testdata/verify.manifest.json | 2 +- cli/testdata/verify.nef | Bin 82 -> 83 bytes pkg/core/state/contract_test.go | 1 + pkg/rpc/client/rpc_test.go | 6 +-- pkg/rpc/server/server_test.go | 4 +- pkg/rpc/server/testdata/testblocks.acc | Bin 7665 -> 7667 bytes pkg/smartcontract/nef/method_token.go | 57 +++++++++++++++++++++ pkg/smartcontract/nef/method_token_test.go | 50 ++++++++++++++++++ pkg/smartcontract/nef/nef.go | 13 +++-- pkg/smartcontract/nef/nef_test.go | 41 +++++++++++++++ 10 files changed, 164 insertions(+), 10 deletions(-) create mode 100644 pkg/smartcontract/nef/method_token.go create mode 100644 pkg/smartcontract/nef/method_token_test.go diff --git a/cli/testdata/verify.manifest.json b/cli/testdata/verify.manifest.json index 518bcd896..627b44167 100755 --- a/cli/testdata/verify.manifest.json +++ b/cli/testdata/verify.manifest.json @@ -1 +1 @@ -{"name":"verify","abi":{"hash":"0xbf214a7551e50d6fbe0bef05271719325d9fc1ef","methods":[{"name":"verify","offset":0,"parameters":[],"returntype":"Boolean"},{"name":"onPayment","offset":5,"parameters":[{"name":"from","type":"ByteArray"},{"name":"amount","type":"Integer"},{"name":"data","type":"Any"}],"returntype":"Void"}],"events":[]},"groups":[],"permissions":[{"contract":"*","methods":"*"}],"supportedstandards":[],"trusts":[],"safemethods":[],"extra":null} \ No newline at end of file +{"name":"verify","abi":{"methods":[{"name":"onPayment","offset":5,"parameters":[{"name":"from","type":"ByteArray"},{"name":"amount","type":"Integer"},{"name":"data","type":"Any"}],"returntype":"Void","safe":false},{"name":"verify","offset":0,"parameters":[],"returntype":"Boolean","safe":false}],"events":[{"name":"Hello world!","parameters":[{"name":"args","type":"Array"}]}]},"groups":[],"permissions":[{"contract":"*","methods":"*"}],"supportedstandards":[],"trusts":[],"extra":null} \ No newline at end of file diff --git a/cli/testdata/verify.nef b/cli/testdata/verify.nef index 5bb3c8bbe40518db36efb14d911e84b0a574ee9e..3de780aee21a23f0914246ef4aa0425972083f83 100755 GIT binary patch delta 49 wcmWFvo}jK{tY@HGP?V}`Vy>H>Vw`AUV32IY00*4mj0}Pf;S9_UI+A5Y01lf8SO5S3 delta 48 ycmWFznxL+2q-UU8lx(PLXl$vQZenhbYG`U{!~g}H;fxG|4&e;U4l|PW%?1GbxC$8n diff --git a/pkg/core/state/contract_test.go b/pkg/core/state/contract_test.go index 9ea4c627a..634cca9a4 100644 --- a/pkg/core/state/contract_test.go +++ b/pkg/core/state/contract_test.go @@ -44,6 +44,7 @@ func TestEncodeDecodeContractState(t *testing.T) { Compiler: "neo-go.test", Version: "test", }, + Tokens: []nef.MethodToken{}, Script: script, Checksum: 0, }, diff --git a/pkg/rpc/client/rpc_test.go b/pkg/rpc/client/rpc_test.go index aa2b4bca4..087ead720 100644 --- a/pkg/rpc/client/rpc_test.go +++ b/pkg/rpc/client/rpc_test.go @@ -330,7 +330,7 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ } return c.GetContractStateByHash(hash) }, - serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"id":0,"nef":{"magic":860243278,"compiler":"neo-go","version":"3.0","script":"VgJXHwIMDWNvbnRyYWN0IGNhbGx4eVMTwEEFB5IWIXhKDANQdXSXJyQAAAAQVUGEGNYNIXJqeRDOeRHOU0FSoUH1IUURQCOPAgAASgwLdG90YWxTdXBwbHmXJxEAAABFAkBCDwBAI28CAABKDAhkZWNpbWFsc5cnDQAAAEUSQCNWAgAASgwEbmFtZZcnEgAAAEUMBFJ1YmxAIzwCAABKDAZzeW1ib2yXJxEAAABFDANSVUJAIyECAABKDAliYWxhbmNlT2aXJ2IAAAAQVUGEGNYNIXN5EM50bMoAFLQnIwAAAAwPaW52YWxpZCBhZGRyZXNzEVVBNtNSBiFFENsgQGtsUEEfLnsHIXUMCWJhbGFuY2VPZmxtUxPAQQUHkhYhRW1AI7IBAABKDAh0cmFuc2ZlcpcnKwEAABBVQYQY1g0hdnkQzncHbwfKABS0JyoAAAAMFmludmFsaWQgJ2Zyb20nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRHOdwhvCMoAFLQnKAAAAAwUaW52YWxpZCAndG8nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRLOdwlvCRC1JyIAAAAMDmludmFsaWQgYW1vdW50EVVBNtNSBiFFENsgQG5vB1BBHy57ByF3Cm8Kbwm1JyYAAAAMEmluc3VmZmljaWVudCBmdW5kcxFVQTbTUgYhRRDbIEBvCm8Jn3cKbm8HbwpTQVKhQfUhbm8IUEEfLnsHIXcLbwtvCZ53C25vCG8LU0FSoUH1IQwIdHJhbnNmZXJvB28IbwlUFMBBBQeSFiFFEUAjewAAAEoMBGluaXSXJ1AAAAAQVUGEGNYNIXcMEFVBh8PSZCF3DQJAQg8Adw5vDG8Nbw5TQVKhQfUhDAh0cmFuc2ZlcgwA2zBvDW8OVBTAQQUHkhYhRRFAIyMAAAAMEWludmFsaWQgb3BlcmF0aW9uQTbTUgY6IwUAAABFQA==","checksum":749050685},"manifest":{"name":"Test","abi":{"methods":[],"events":[]},"groups":[],"permissions":null,"trusts":[],"supportedstandards":[],"safemethods":[],"extra":null},"hash":"0x1b4357bff5a01bdf2a6581247cf9ed1e24629176"}}`, + serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"id":0,"nef":{"magic":860243278,"compiler":"neo-go","version":"3.0","script":"VgJXHwIMDWNvbnRyYWN0IGNhbGx4eVMTwEEFB5IWIXhKDANQdXSXJyQAAAAQVUGEGNYNIXJqeRDOeRHOU0FSoUH1IUURQCOPAgAASgwLdG90YWxTdXBwbHmXJxEAAABFAkBCDwBAI28CAABKDAhkZWNpbWFsc5cnDQAAAEUSQCNWAgAASgwEbmFtZZcnEgAAAEUMBFJ1YmxAIzwCAABKDAZzeW1ib2yXJxEAAABFDANSVUJAIyECAABKDAliYWxhbmNlT2aXJ2IAAAAQVUGEGNYNIXN5EM50bMoAFLQnIwAAAAwPaW52YWxpZCBhZGRyZXNzEVVBNtNSBiFFENsgQGtsUEEfLnsHIXUMCWJhbGFuY2VPZmxtUxPAQQUHkhYhRW1AI7IBAABKDAh0cmFuc2ZlcpcnKwEAABBVQYQY1g0hdnkQzncHbwfKABS0JyoAAAAMFmludmFsaWQgJ2Zyb20nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRHOdwhvCMoAFLQnKAAAAAwUaW52YWxpZCAndG8nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRLOdwlvCRC1JyIAAAAMDmludmFsaWQgYW1vdW50EVVBNtNSBiFFENsgQG5vB1BBHy57ByF3Cm8Kbwm1JyYAAAAMEmluc3VmZmljaWVudCBmdW5kcxFVQTbTUgYhRRDbIEBvCm8Jn3cKbm8HbwpTQVKhQfUhbm8IUEEfLnsHIXcLbwtvCZ53C25vCG8LU0FSoUH1IQwIdHJhbnNmZXJvB28IbwlUFMBBBQeSFiFFEUAjewAAAEoMBGluaXSXJ1AAAAAQVUGEGNYNIXcMEFVBh8PSZCF3DQJAQg8Adw5vDG8Nbw5TQVKhQfUhDAh0cmFuc2ZlcgwA2zBvDW8OVBTAQQUHkhYhRRFAIyMAAAAMEWludmFsaWQgb3BlcmF0aW9uQTbTUgY6IwUAAABFQA==","checksum":2354924458},"manifest":{"name":"Test","abi":{"methods":[],"events":[]},"groups":[],"permissions":null,"trusts":[],"supportedstandards":[],"safemethods":[],"extra":null},"hash":"0x1b4357bff5a01bdf2a6581247cf9ed1e24629176"}}`, result: func(c *Client) interface{} { script, err := base64.StdEncoding.DecodeString("VgJXHwIMDWNvbnRyYWN0IGNhbGx4eVMTwEEFB5IWIXhKDANQdXSXJyQAAAAQVUGEGNYNIXJqeRDOeRHOU0FSoUH1IUURQCOPAgAASgwLdG90YWxTdXBwbHmXJxEAAABFAkBCDwBAI28CAABKDAhkZWNpbWFsc5cnDQAAAEUSQCNWAgAASgwEbmFtZZcnEgAAAEUMBFJ1YmxAIzwCAABKDAZzeW1ib2yXJxEAAABFDANSVUJAIyECAABKDAliYWxhbmNlT2aXJ2IAAAAQVUGEGNYNIXN5EM50bMoAFLQnIwAAAAwPaW52YWxpZCBhZGRyZXNzEVVBNtNSBiFFENsgQGtsUEEfLnsHIXUMCWJhbGFuY2VPZmxtUxPAQQUHkhYhRW1AI7IBAABKDAh0cmFuc2ZlcpcnKwEAABBVQYQY1g0hdnkQzncHbwfKABS0JyoAAAAMFmludmFsaWQgJ2Zyb20nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRHOdwhvCMoAFLQnKAAAAAwUaW52YWxpZCAndG8nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRLOdwlvCRC1JyIAAAAMDmludmFsaWQgYW1vdW50EVVBNtNSBiFFENsgQG5vB1BBHy57ByF3Cm8Kbwm1JyYAAAAMEmluc3VmZmljaWVudCBmdW5kcxFVQTbTUgYhRRDbIEBvCm8Jn3cKbm8HbwpTQVKhQfUhbm8IUEEfLnsHIXcLbwtvCZ53C25vCG8LU0FSoUH1IQwIdHJhbnNmZXJvB28IbwlUFMBBBQeSFiFFEUAjewAAAEoMBGluaXSXJ1AAAAAQVUGEGNYNIXcMEFVBh8PSZCF3DQJAQg8Adw5vDG8Nbw5TQVKhQfUhDAh0cmFuc2ZlcgwA2zBvDW8OVBTAQQUHkhYhRRFAIyMAAAAMEWludmFsaWQgb3BlcmF0aW9uQTbTUgY6IwUAAABFQA==") if err != nil { @@ -351,7 +351,7 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ invoke: func(c *Client) (interface{}, error) { return c.GetContractStateByAddressOrName("NWiu5oejTu925aeL9Hc1LX8SvaJhE23h15") }, - serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"id":0,"nef":{"magic":860243278,"compiler":"neo-go","version":"3.0","script":"VgJXHwIMDWNvbnRyYWN0IGNhbGx4eVMTwEEFB5IWIXhKDANQdXSXJyQAAAAQVUGEGNYNIXJqeRDOeRHOU0FSoUH1IUURQCOPAgAASgwLdG90YWxTdXBwbHmXJxEAAABFAkBCDwBAI28CAABKDAhkZWNpbWFsc5cnDQAAAEUSQCNWAgAASgwEbmFtZZcnEgAAAEUMBFJ1YmxAIzwCAABKDAZzeW1ib2yXJxEAAABFDANSVUJAIyECAABKDAliYWxhbmNlT2aXJ2IAAAAQVUGEGNYNIXN5EM50bMoAFLQnIwAAAAwPaW52YWxpZCBhZGRyZXNzEVVBNtNSBiFFENsgQGtsUEEfLnsHIXUMCWJhbGFuY2VPZmxtUxPAQQUHkhYhRW1AI7IBAABKDAh0cmFuc2ZlcpcnKwEAABBVQYQY1g0hdnkQzncHbwfKABS0JyoAAAAMFmludmFsaWQgJ2Zyb20nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRHOdwhvCMoAFLQnKAAAAAwUaW52YWxpZCAndG8nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRLOdwlvCRC1JyIAAAAMDmludmFsaWQgYW1vdW50EVVBNtNSBiFFENsgQG5vB1BBHy57ByF3Cm8Kbwm1JyYAAAAMEmluc3VmZmljaWVudCBmdW5kcxFVQTbTUgYhRRDbIEBvCm8Jn3cKbm8HbwpTQVKhQfUhbm8IUEEfLnsHIXcLbwtvCZ53C25vCG8LU0FSoUH1IQwIdHJhbnNmZXJvB28IbwlUFMBBBQeSFiFFEUAjewAAAEoMBGluaXSXJ1AAAAAQVUGEGNYNIXcMEFVBh8PSZCF3DQJAQg8Adw5vDG8Nbw5TQVKhQfUhDAh0cmFuc2ZlcgwA2zBvDW8OVBTAQQUHkhYhRRFAIyMAAAAMEWludmFsaWQgb3BlcmF0aW9uQTbTUgY6IwUAAABFQA==","checksum":749050685},"manifest":{"name":"Test","abi":{"methods":[],"events":[]},"groups":[],"permissions":null,"trusts":[],"supportedstandards":[],"safemethods":[],"extra":null},"hash":"0x1b4357bff5a01bdf2a6581247cf9ed1e24629176"}}`, + serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"id":0,"nef":{"magic":860243278,"compiler":"neo-go","version":"3.0","script":"VgJXHwIMDWNvbnRyYWN0IGNhbGx4eVMTwEEFB5IWIXhKDANQdXSXJyQAAAAQVUGEGNYNIXJqeRDOeRHOU0FSoUH1IUURQCOPAgAASgwLdG90YWxTdXBwbHmXJxEAAABFAkBCDwBAI28CAABKDAhkZWNpbWFsc5cnDQAAAEUSQCNWAgAASgwEbmFtZZcnEgAAAEUMBFJ1YmxAIzwCAABKDAZzeW1ib2yXJxEAAABFDANSVUJAIyECAABKDAliYWxhbmNlT2aXJ2IAAAAQVUGEGNYNIXN5EM50bMoAFLQnIwAAAAwPaW52YWxpZCBhZGRyZXNzEVVBNtNSBiFFENsgQGtsUEEfLnsHIXUMCWJhbGFuY2VPZmxtUxPAQQUHkhYhRW1AI7IBAABKDAh0cmFuc2ZlcpcnKwEAABBVQYQY1g0hdnkQzncHbwfKABS0JyoAAAAMFmludmFsaWQgJ2Zyb20nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRHOdwhvCMoAFLQnKAAAAAwUaW52YWxpZCAndG8nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRLOdwlvCRC1JyIAAAAMDmludmFsaWQgYW1vdW50EVVBNtNSBiFFENsgQG5vB1BBHy57ByF3Cm8Kbwm1JyYAAAAMEmluc3VmZmljaWVudCBmdW5kcxFVQTbTUgYhRRDbIEBvCm8Jn3cKbm8HbwpTQVKhQfUhbm8IUEEfLnsHIXcLbwtvCZ53C25vCG8LU0FSoUH1IQwIdHJhbnNmZXJvB28IbwlUFMBBBQeSFiFFEUAjewAAAEoMBGluaXSXJ1AAAAAQVUGEGNYNIXcMEFVBh8PSZCF3DQJAQg8Adw5vDG8Nbw5TQVKhQfUhDAh0cmFuc2ZlcgwA2zBvDW8OVBTAQQUHkhYhRRFAIyMAAAAMEWludmFsaWQgb3BlcmF0aW9uQTbTUgY6IwUAAABFQA==","checksum":2354924458},"manifest":{"name":"Test","abi":{"methods":[],"events":[]},"groups":[],"permissions":null,"trusts":[],"supportedstandards":[],"safemethods":[],"extra":null},"hash":"0x1b4357bff5a01bdf2a6581247cf9ed1e24629176"}}`, result: func(c *Client) interface{} { script, err := base64.StdEncoding.DecodeString("VgJXHwIMDWNvbnRyYWN0IGNhbGx4eVMTwEEFB5IWIXhKDANQdXSXJyQAAAAQVUGEGNYNIXJqeRDOeRHOU0FSoUH1IUURQCOPAgAASgwLdG90YWxTdXBwbHmXJxEAAABFAkBCDwBAI28CAABKDAhkZWNpbWFsc5cnDQAAAEUSQCNWAgAASgwEbmFtZZcnEgAAAEUMBFJ1YmxAIzwCAABKDAZzeW1ib2yXJxEAAABFDANSVUJAIyECAABKDAliYWxhbmNlT2aXJ2IAAAAQVUGEGNYNIXN5EM50bMoAFLQnIwAAAAwPaW52YWxpZCBhZGRyZXNzEVVBNtNSBiFFENsgQGtsUEEfLnsHIXUMCWJhbGFuY2VPZmxtUxPAQQUHkhYhRW1AI7IBAABKDAh0cmFuc2ZlcpcnKwEAABBVQYQY1g0hdnkQzncHbwfKABS0JyoAAAAMFmludmFsaWQgJ2Zyb20nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRHOdwhvCMoAFLQnKAAAAAwUaW52YWxpZCAndG8nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRLOdwlvCRC1JyIAAAAMDmludmFsaWQgYW1vdW50EVVBNtNSBiFFENsgQG5vB1BBHy57ByF3Cm8Kbwm1JyYAAAAMEmluc3VmZmljaWVudCBmdW5kcxFVQTbTUgYhRRDbIEBvCm8Jn3cKbm8HbwpTQVKhQfUhbm8IUEEfLnsHIXcLbwtvCZ53C25vCG8LU0FSoUH1IQwIdHJhbnNmZXJvB28IbwlUFMBBBQeSFiFFEUAjewAAAEoMBGluaXSXJ1AAAAAQVUGEGNYNIXcMEFVBh8PSZCF3DQJAQg8Adw5vDG8Nbw5TQVKhQfUhDAh0cmFuc2ZlcgwA2zBvDW8OVBTAQQUHkhYhRRFAIyMAAAAMEWludmFsaWQgb3BlcmF0aW9uQTbTUgY6IwUAAABFQA==") if err != nil { @@ -372,7 +372,7 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ invoke: func(c *Client) (interface{}, error) { return c.GetContractStateByID(0) }, - serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"id":0,"nef":{"magic":860243278,"compiler":"neo-go","version":"3.0","script":"VgJXHwIMDWNvbnRyYWN0IGNhbGx4eVMTwEEFB5IWIXhKDANQdXSXJyQAAAAQVUGEGNYNIXJqeRDOeRHOU0FSoUH1IUURQCOPAgAASgwLdG90YWxTdXBwbHmXJxEAAABFAkBCDwBAI28CAABKDAhkZWNpbWFsc5cnDQAAAEUSQCNWAgAASgwEbmFtZZcnEgAAAEUMBFJ1YmxAIzwCAABKDAZzeW1ib2yXJxEAAABFDANSVUJAIyECAABKDAliYWxhbmNlT2aXJ2IAAAAQVUGEGNYNIXN5EM50bMoAFLQnIwAAAAwPaW52YWxpZCBhZGRyZXNzEVVBNtNSBiFFENsgQGtsUEEfLnsHIXUMCWJhbGFuY2VPZmxtUxPAQQUHkhYhRW1AI7IBAABKDAh0cmFuc2ZlcpcnKwEAABBVQYQY1g0hdnkQzncHbwfKABS0JyoAAAAMFmludmFsaWQgJ2Zyb20nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRHOdwhvCMoAFLQnKAAAAAwUaW52YWxpZCAndG8nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRLOdwlvCRC1JyIAAAAMDmludmFsaWQgYW1vdW50EVVBNtNSBiFFENsgQG5vB1BBHy57ByF3Cm8Kbwm1JyYAAAAMEmluc3VmZmljaWVudCBmdW5kcxFVQTbTUgYhRRDbIEBvCm8Jn3cKbm8HbwpTQVKhQfUhbm8IUEEfLnsHIXcLbwtvCZ53C25vCG8LU0FSoUH1IQwIdHJhbnNmZXJvB28IbwlUFMBBBQeSFiFFEUAjewAAAEoMBGluaXSXJ1AAAAAQVUGEGNYNIXcMEFVBh8PSZCF3DQJAQg8Adw5vDG8Nbw5TQVKhQfUhDAh0cmFuc2ZlcgwA2zBvDW8OVBTAQQUHkhYhRRFAIyMAAAAMEWludmFsaWQgb3BlcmF0aW9uQTbTUgY6IwUAAABFQA==","checksum":749050685},"manifest":{"name":"Test","abi":{"methods":[],"events":[]},"groups":[],"permissions":null,"trusts":[],"supportedstandards":[],"safemethods":[],"extra":null},"hash":"0x1b4357bff5a01bdf2a6581247cf9ed1e24629176"}}`, + serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"id":0,"nef":{"magic":860243278,"compiler":"neo-go","version":"3.0","script":"VgJXHwIMDWNvbnRyYWN0IGNhbGx4eVMTwEEFB5IWIXhKDANQdXSXJyQAAAAQVUGEGNYNIXJqeRDOeRHOU0FSoUH1IUURQCOPAgAASgwLdG90YWxTdXBwbHmXJxEAAABFAkBCDwBAI28CAABKDAhkZWNpbWFsc5cnDQAAAEUSQCNWAgAASgwEbmFtZZcnEgAAAEUMBFJ1YmxAIzwCAABKDAZzeW1ib2yXJxEAAABFDANSVUJAIyECAABKDAliYWxhbmNlT2aXJ2IAAAAQVUGEGNYNIXN5EM50bMoAFLQnIwAAAAwPaW52YWxpZCBhZGRyZXNzEVVBNtNSBiFFENsgQGtsUEEfLnsHIXUMCWJhbGFuY2VPZmxtUxPAQQUHkhYhRW1AI7IBAABKDAh0cmFuc2ZlcpcnKwEAABBVQYQY1g0hdnkQzncHbwfKABS0JyoAAAAMFmludmFsaWQgJ2Zyb20nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRHOdwhvCMoAFLQnKAAAAAwUaW52YWxpZCAndG8nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRLOdwlvCRC1JyIAAAAMDmludmFsaWQgYW1vdW50EVVBNtNSBiFFENsgQG5vB1BBHy57ByF3Cm8Kbwm1JyYAAAAMEmluc3VmZmljaWVudCBmdW5kcxFVQTbTUgYhRRDbIEBvCm8Jn3cKbm8HbwpTQVKhQfUhbm8IUEEfLnsHIXcLbwtvCZ53C25vCG8LU0FSoUH1IQwIdHJhbnNmZXJvB28IbwlUFMBBBQeSFiFFEUAjewAAAEoMBGluaXSXJ1AAAAAQVUGEGNYNIXcMEFVBh8PSZCF3DQJAQg8Adw5vDG8Nbw5TQVKhQfUhDAh0cmFuc2ZlcgwA2zBvDW8OVBTAQQUHkhYhRRFAIyMAAAAMEWludmFsaWQgb3BlcmF0aW9uQTbTUgY6IwUAAABFQA==","checksum":2354924458},"manifest":{"name":"Test","abi":{"methods":[],"events":[]},"groups":[],"permissions":null,"trusts":[],"supportedstandards":[],"safemethods":[],"extra":null},"hash":"0x1b4357bff5a01bdf2a6581247cf9ed1e24629176"}}`, result: func(c *Client) interface{} { script, err := base64.StdEncoding.DecodeString("VgJXHwIMDWNvbnRyYWN0IGNhbGx4eVMTwEEFB5IWIXhKDANQdXSXJyQAAAAQVUGEGNYNIXJqeRDOeRHOU0FSoUH1IUURQCOPAgAASgwLdG90YWxTdXBwbHmXJxEAAABFAkBCDwBAI28CAABKDAhkZWNpbWFsc5cnDQAAAEUSQCNWAgAASgwEbmFtZZcnEgAAAEUMBFJ1YmxAIzwCAABKDAZzeW1ib2yXJxEAAABFDANSVUJAIyECAABKDAliYWxhbmNlT2aXJ2IAAAAQVUGEGNYNIXN5EM50bMoAFLQnIwAAAAwPaW52YWxpZCBhZGRyZXNzEVVBNtNSBiFFENsgQGtsUEEfLnsHIXUMCWJhbGFuY2VPZmxtUxPAQQUHkhYhRW1AI7IBAABKDAh0cmFuc2ZlcpcnKwEAABBVQYQY1g0hdnkQzncHbwfKABS0JyoAAAAMFmludmFsaWQgJ2Zyb20nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRHOdwhvCMoAFLQnKAAAAAwUaW52YWxpZCAndG8nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRLOdwlvCRC1JyIAAAAMDmludmFsaWQgYW1vdW50EVVBNtNSBiFFENsgQG5vB1BBHy57ByF3Cm8Kbwm1JyYAAAAMEmluc3VmZmljaWVudCBmdW5kcxFVQTbTUgYhRRDbIEBvCm8Jn3cKbm8HbwpTQVKhQfUhbm8IUEEfLnsHIXcLbwtvCZ53C25vCG8LU0FSoUH1IQwIdHJhbnNmZXJvB28IbwlUFMBBBQeSFiFFEUAjewAAAEoMBGluaXSXJ1AAAAAQVUGEGNYNIXcMEFVBh8PSZCF3DQJAQg8Adw5vDG8Nbw5TQVKhQfUhDAh0cmFuc2ZlcgwA2zBvDW8OVBTAQQUHkhYhRRFAIyMAAAAMEWludmFsaWQgb3BlcmF0aW9uQTbTUgY6IwUAAABFQA==") if err != nil { diff --git a/pkg/rpc/server/server_test.go b/pkg/rpc/server/server_test.go index 41fc7282a..99c8dc3e5 100644 --- a/pkg/rpc/server/server_test.go +++ b/pkg/rpc/server/server_test.go @@ -57,7 +57,7 @@ type rpcTestCase struct { } const testContractHash = "0b3bc97e94ed99e32dda46c9ecd2d3626979af06" -const deploymentTxHash = "4288bb6ad12426a9e34f6af4c050bc291798a46958443d614f457a9a12f087c2" +const deploymentTxHash = "fe9e91388ba9be39f771fddaf07d3719c490eb179788a3d193f248c7ed4cff61" const genesisBlockHash = "0542f4350c6e236d0509bcd98188b0034bfbecc1a0c7fcdb8e4295310d468b70" const verifyContractHash = "d2da8ee8c0bf6c5bf3dda1ef671dbf5fef7226e9" @@ -1408,7 +1408,7 @@ func checkNep17Balances(t *testing.T, e *executor, acc interface{}) { }, { Asset: e.chain.UtilityTokenHash(), - Amount: "80006675650", + Amount: "80006673650", LastUpdated: 7, }}, Address: testchain.PrivateKeyByID(0).GetScriptHash().StringLE(), diff --git a/pkg/rpc/server/testdata/testblocks.acc b/pkg/rpc/server/testdata/testblocks.acc index f98ff66b7d996af67ccb71c84765cfe80f251b46..501ed5fe66f009c369ec4f6978e82c6d45cc45fd 100644 GIT binary patch delta 2088 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 diff --git a/pkg/smartcontract/nef/method_token.go b/pkg/smartcontract/nef/method_token.go new file mode 100644 index 000000000..48aeacd89 --- /dev/null +++ b/pkg/smartcontract/nef/method_token.go @@ -0,0 +1,57 @@ +package nef + +import ( + "errors" + "strings" + + "github.com/nspcc-dev/neo-go/pkg/io" + "github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag" + "github.com/nspcc-dev/neo-go/pkg/util" +) + +// maxMethodLength is the maximum length of method. +const maxMethodLength = 32 + +var ( + errInvalidMethodName = errors.New("method name should't start with '_'") + errInvalidCallFlag = errors.New("invalid call flag") +) + +// MethodToken is contract method description. +type MethodToken struct { + // Hash is contract hash. + Hash util.Uint160 `json:"hash"` + // Method is method name. + Method string `json:"method"` + // ParamCount is method parameter count. + ParamCount uint16 `json:"paramcount"` + // HasReturn is true if method returns value. + HasReturn bool `json:"hasreturnvalue"` + // CallFlag is a set of call flags the method will be called with. + CallFlag callflag.CallFlag `json:"callflags"` +} + +// EncodeBinary implements io.Serializable. +func (t *MethodToken) EncodeBinary(w *io.BinWriter) { + w.WriteBytes(t.Hash[:]) + w.WriteString(t.Method) + w.WriteU16LE(t.ParamCount) + w.WriteBool(t.HasReturn) + w.WriteB(byte(t.CallFlag)) +} + +// DecodeBinary implements io.Serializable. +func (t *MethodToken) DecodeBinary(r *io.BinReader) { + r.ReadBytes(t.Hash[:]) + t.Method = r.ReadString(maxMethodLength) + if r.Err == nil && strings.HasPrefix(t.Method, "_") { + r.Err = errInvalidMethodName + return + } + t.ParamCount = r.ReadU16LE() + t.HasReturn = r.ReadBool() + t.CallFlag = callflag.CallFlag(r.ReadB()) + if r.Err == nil && t.CallFlag&^callflag.All != 0 { + r.Err = errInvalidCallFlag + } +} diff --git a/pkg/smartcontract/nef/method_token_test.go b/pkg/smartcontract/nef/method_token_test.go new file mode 100644 index 000000000..05072723d --- /dev/null +++ b/pkg/smartcontract/nef/method_token_test.go @@ -0,0 +1,50 @@ +package nef + +import ( + "errors" + "strings" + "testing" + + "github.com/nspcc-dev/neo-go/internal/random" + "github.com/nspcc-dev/neo-go/internal/testserdes" + "github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag" + "github.com/stretchr/testify/require" +) + +func TestMethodToken_Serializable(t *testing.T) { + getToken := func() *MethodToken { + return &MethodToken{ + Hash: random.Uint160(), + Method: "MethodName", + ParamCount: 2, + HasReturn: true, + CallFlag: callflag.ReadStates, + } + } + t.Run("good", func(t *testing.T) { + testserdes.EncodeDecodeBinary(t, getToken(), new(MethodToken)) + }) + t.Run("too long name", func(t *testing.T) { + tok := getToken() + tok.Method = strings.Repeat("s", maxMethodLength+1) + data, err := testserdes.EncodeBinary(tok) + require.NoError(t, err) + require.Error(t, testserdes.DecodeBinary(data, new(MethodToken))) + }) + t.Run("start with '_'", func(t *testing.T) { + tok := getToken() + tok.Method = "_method" + data, err := testserdes.EncodeBinary(tok) + require.NoError(t, err) + err = testserdes.DecodeBinary(data, new(MethodToken)) + require.True(t, errors.Is(err, errInvalidMethodName)) + }) + t.Run("invalid call flag", func(t *testing.T) { + tok := getToken() + tok.CallFlag = ^callflag.All + data, err := testserdes.EncodeBinary(tok) + require.NoError(t, err) + err = testserdes.DecodeBinary(data, new(MethodToken)) + require.True(t, errors.Is(err, errInvalidCallFlag)) + }) +} diff --git a/pkg/smartcontract/nef/nef.go b/pkg/smartcontract/nef/nef.go index 74476d0ab..cbf14c3d6 100644 --- a/pkg/smartcontract/nef/nef.go +++ b/pkg/smartcontract/nef/nef.go @@ -20,6 +20,7 @@ import ( // | Compiler | 32 bytes | Compiler used | // | Version | 32 bytes | Compiler version | // +------------+-----------+------------------------------------------------------------+ +// | Tokens | Var array | List of method tokens | // | Script | Var bytes | Var bytes for the payload | // +------------+-----------+------------------------------------------------------------+ // | Checksum | 4 bytes | First four bytes of double SHA256 hash of the header | @@ -37,8 +38,9 @@ const ( // File represents compiled contract file structure according to the NEF3 standard. type File struct { Header - Script []byte `json:"script"` - Checksum uint32 `json:"checksum"` + Tokens []MethodToken `json:"tokens"` + Script []byte `json:"script"` + Checksum uint32 `json:"checksum"` } // Header represents File header. @@ -56,6 +58,7 @@ func NewFile(script []byte) (*File, error) { Compiler: "neo-go", Version: config.Version, }, + Tokens: []MethodToken{}, Script: script, } if len(config.Version) > compilerFieldSize { @@ -115,6 +118,7 @@ func (n *File) CalculateChecksum() uint32 { // EncodeBinary implements io.Serializable interface. func (n *File) EncodeBinary(w *io.BinWriter) { n.Header.EncodeBinary(w) + w.WriteArray(n.Tokens) w.WriteVarBytes(n.Script) w.WriteU32LE(n.Checksum) } @@ -122,14 +126,15 @@ func (n *File) EncodeBinary(w *io.BinWriter) { // DecodeBinary implements io.Serializable interface. func (n *File) DecodeBinary(r *io.BinReader) { n.Header.DecodeBinary(r) + r.ReadArray(&n.Tokens) n.Script = r.ReadVarBytes(MaxScriptLength) - if len(n.Script) == 0 { + if r.Err == nil && len(n.Script) == 0 { r.Err = errors.New("empty script") return } n.Checksum = r.ReadU32LE() checksum := n.CalculateChecksum() - if checksum != n.Checksum { + if r.Err == nil && checksum != n.Checksum { r.Err = errors.New("checksum verification failure") return } diff --git a/pkg/smartcontract/nef/nef_test.go b/pkg/smartcontract/nef/nef_test.go index c0054e461..e96dd259f 100644 --- a/pkg/smartcontract/nef/nef_test.go +++ b/pkg/smartcontract/nef/nef_test.go @@ -6,7 +6,10 @@ import ( "strconv" "testing" + "github.com/nspcc-dev/neo-go/internal/random" "github.com/nspcc-dev/neo-go/internal/testserdes" + "github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag" + "github.com/nspcc-dev/neo-go/pkg/util" "github.com/stretchr/testify/require" ) @@ -18,6 +21,13 @@ func TestEncodeDecodeBinary(t *testing.T) { Compiler: "the best compiler ever", Version: "1.2.3.4", }, + Tokens: []MethodToken{{ + Hash: random.Uint160(), + Method: "method", + ParamCount: 3, + HasReturn: true, + CallFlag: callflag.WriteStates, + }}, Script: script, } @@ -45,8 +55,16 @@ func TestEncodeDecodeBinary(t *testing.T) { checkDecodeError(t, expected) }) + t.Run("invalid tokens list", func(t *testing.T) { + expected.Script = script + expected.Tokens[0].Method = "_reserved" + expected.Checksum = expected.CalculateChecksum() + checkDecodeError(t, expected) + }) + t.Run("positive", func(t *testing.T) { expected.Script = script + expected.Tokens[0].Method = "method" expected.Checksum = expected.CalculateChecksum() expected.Header.Magic = Magic testserdes.EncodeDecodeBinary(t, expected, &File{}) @@ -67,6 +85,13 @@ func TestBytesFromBytes(t *testing.T) { Compiler: "the best compiler ever", Version: "1.2.3.4", }, + Tokens: []MethodToken{{ + Hash: random.Uint160(), + Method: "someMethod", + ParamCount: 3, + HasReturn: true, + CallFlag: callflag.WriteStates, + }}, Script: script, } expected.Checksum = expected.CalculateChecksum() @@ -85,6 +110,13 @@ func TestMarshalUnmarshalJSON(t *testing.T) { Compiler: "test.compiler", Version: "test.ver", }, + Tokens: []MethodToken{{ + Hash: util.Uint160{0x12, 0x34, 0x56, 0x78, 0x91, 0x00}, + Method: "someMethod", + ParamCount: 3, + HasReturn: true, + CallFlag: callflag.WriteStates, + }}, Script: []byte{1, 2, 3, 4}, } expected.Checksum = expected.CalculateChecksum() @@ -95,6 +127,15 @@ func TestMarshalUnmarshalJSON(t *testing.T) { "magic":`+strconv.FormatUint(uint64(Magic), 10)+`, "compiler": "test.compiler", "version": "test.ver", + "tokens": [ + { + "hash": "0x`+expected.Tokens[0].Hash.StringLE()+`", + "method": "someMethod", + "paramcount": 3, + "hasreturnvalue": true, + "callflags": `+strconv.FormatInt(int64(expected.Tokens[0].CallFlag), 10)+` + } + ], "script": "`+base64.StdEncoding.EncodeToString(expected.Script)+`", "checksum":`+strconv.FormatUint(uint64(expected.Checksum), 10)+`}`, string(data))