Commit graph

617 commits

Author SHA1 Message Date
Evgeniy Stratonikov
1dfef4ba26 stackitem: make ByteArray an alias to []byte
Signed-off-by: Evgeniy Stratonikov <evgeniy@nspcc.ru>
2021-08-13 14:41:26 +03:00
Evgeniy Stratonikov
4f98ec2f53 vm: embed reference counter in compound items
```
name              old time/op  new time/op  delta
RefCounter_Add-8  44.8ns ± 4%  11.7ns ± 3%  -73.94%  (p=0.000 n=10+10)
```

Signed-off-by: Evgeniy Stratonikov <evgeniy@nspcc.ru>
2021-08-13 14:41:26 +03:00
Evgeniy Stratonikov
f5d1277bfd vm: do not copy parameter
Signed-off-by: Evgeniy Stratonikov <evgeniy@nspcc.ru>
2021-08-13 11:52:38 +03:00
Evgeniy Stratonikov
a5516e8c96 stackitem: make BigInteger alias to big.Int
Remove one indirection step.
``
name       old time/op    new time/op    delta
MakeInt-8    79.7ns ± 8%    56.2ns ± 8%  -29.44%  (p=0.000 n=10+10)

name       old alloc/op   new alloc/op   delta
MakeInt-8     48.0B ± 0%     40.0B ± 0%  -16.67%  (p=0.000 n=10+10)

name       old allocs/op  new allocs/op  delta
MakeInt-8      3.00 ± 0%      2.00 ± 0%  -33.33%  (p=0.000 n=10+10)
```

Signed-off-by: Evgeniy Stratonikov <evgeniy@nspcc.ru>
2021-08-12 17:53:36 +03:00
Evgeniy Stratonikov
cff8b1c24e stackitem: use Bool item directly
It is always copied.

Signed-off-by: Evgeniy Stratonikov <evgeniy@nspcc.ru>
2021-08-12 17:53:36 +03:00
Roman Khimov
bdb2d24a5a vm: remove istack redirection in VM
VM always has istack and it doesn't even change, so doing this microallocation
makes no sense. Notice that estack is a bit harder to change we do replace it
in some cases and we compare pointers to it as well.
2021-08-11 14:42:01 +03:00
Roman Khimov
ff7d594bef vm: store refcounter directly in VM
VM always has it, so allocating yet another object makes no sense.
2021-08-11 13:25:58 +03:00
Evgeniy Stratonikov
f02d8b4ec4 stackitem: serialize integers to the pre-allocated slice
Signed-off-by: Evgeniy Stratonikov <evgeniy@nspcc.ru>
2021-08-06 11:59:24 +03:00
Roman Khimov
85936de254 vm: don't create reference counter when it's not needed
* invocation stack doesn't need refcounting
 * exception stack doesn't need refcounting
 * evaluation stack always has VM-level refcounter
2021-08-02 22:38:41 +03:00
Roman Khimov
2c2ccdca74 opcode: optimize IsValid
Map access costs much more than array access.

name       old time/op  new time/op  delta
IsValid-8  17.6ns ± 2%   1.1ns ± 2%  -93.68%  (p=0.008 n=5+5)
2021-08-02 21:46:19 +03:00
Evgeniy Stratonikov
bdb9748c1b native/std: restrict amount of items in JSON deserialization
Signed-off-by: Evgeniy Stratonikov <evgeniy@nspcc.ru>
2021-08-02 18:57:47 +03:00
Roman Khimov
ad35db66b5
Merge pull request #2091 from nspcc-dev/tune-error-messages
*: simplify some error messages
2021-07-23 10:40:26 +03:00
Roman Khimov
1d8ad5b84a *: simplify some error messages
Log:
2021-07-23T09:59:18.948+0300    WARN    contract invocation failed      {"tx": "de3e3c1f1d37e4528990f894dea5583fd320485ad3862a95eb0e8823eecf4a5f", "block": 9643, "error": "error encountered at instruction 1 (SYSCALL): error during call from native: error encountered at instruction 745 (CAT): invalid conversion: Map/ByteString"}

The word "error" appears 4 times here.
2021-07-23 10:08:09 +03:00
Roman Khimov
6b852fc7b6
Merge pull request #2089 from nspcc-dev/fix-emit
vm/emit: improve error message
2021-07-22 15:17:59 +03:00
Evgeniy Stratonikov
808c30e7d7 vm/emit: improve error message
Show unsupported type instead of value.

Signed-off-by: Evgeniy Stratonikov <evgeniy@nspcc.ru>
2021-07-22 14:23:32 +03:00
Roman Khimov
ede410a4a7 go.mod: update ishell package
It only adds go.mod and changes import path, that's it.
2021-07-21 23:28:26 +03:00
Roman Khimov
0583f252ab *: create real temporary dirs and files in tests
Improve reliability.
2021-07-20 12:51:11 +03:00
Roman Khimov
19717dd9a8 slice: introduce common Copy helper
It's a bit more convenient to use.
2021-07-19 22:57:55 +03:00
Roman Khimov
a54e3516d1 slice: add Reverse function, deduplicate code a bit 2021-07-19 22:57:55 +03:00
Roman Khimov
100e97d772 util: move ArrayReverse into package of its own
Leave just uint160 and uint256 types in util.
2021-07-19 22:57:55 +03:00
Roman Khimov
1568ebc513 stackitem: rework struct cloning protection
Count everything, fail early, make it more compatible with
neo-project/neo-vm#423.
2021-07-19 15:42:42 +03:00
Roman Khimov
5f13de3a76 *: simplify some integer checks with IsUint64()
If we need a positive number we can do `IsUint64()` instead of checking that
`Int64()` is `> 0`.
2021-07-19 15:42:42 +03:00
Roman Khimov
233307aca5 stackitem: completely drop MaxArraySize
Turns out C# VM doesn't have it since preview2, so our limiting of
MaxArraySize in incompatible with it. Removing this limit shouldn't be a
problem with the reference counter we have, both APPEND and SETITEM add things
to reference counter and we can't exceed MaxStackSize. PACK on the other hand
can't get more than MaxStackSize-1 of input elements.

Unify NEWSTRUCT with NEWARRAY* and use better integer checks at the same time.

Multisig limit is still 1024.
2021-07-19 15:42:42 +03:00
Roman Khimov
ee4a647934 stackitem: limit EQUAL for deeply nested structs
See neo-project/neo-vm#428.
2021-07-19 15:42:42 +03:00
Roman Khimov
f89f0300f6 stackitem: improve test coverage a bit 2021-07-19 15:42:42 +03:00
Roman Khimov
df2430d5e4 stackitem: limit deserialization to MaxDeserialized items
Follow neo-project/neo#2531. Even though it's not strictly required (our node
handles problematic script just fine) we better be compliant wrt
deserialization behavior. MaxDeserialized is introduced to avoid moving
MaxStackSize which is a VM parameter.
2021-07-19 15:42:42 +03:00
Roman Khimov
aab18c3083 stackitem: introduce Convertible interface
We have a lot of native contract types that are converted to stack items
before serialization, then deserialized as stack items and converted back to
regular structures. stackitem.Convertible allows to remove a lot of repetitive
io.Serializable code.

This also introduces to/from converter in testserdes which unfortunately
required to change util tests to avoid circular references.
2021-07-19 15:42:42 +03:00
Roman Khimov
fbe8bd2d9c stackitem: limit deserialized arrays/maps
See neo-project/neo#2531, even though they use MaxStackSize there resulting
element is not valid unless it has <=MaxArraySize elements.
2021-07-19 15:42:42 +03:00
Roman Khimov
654c4a6589 stackitem: properly pass allowInvalid on binary deserialization
Otherwise DecodeBinaryProtected() is broken for arrays/maps.
2021-07-19 15:42:41 +03:00
Roman Khimov
15be763bb3 vm: limit POW, fix #2060
Calculating pow(pow(2, 255), 0xffffffff) takes unknown amount of time. See
also neo-project/neo-vm#422.
2021-07-19 15:42:41 +03:00
Roman Khimov
d638aee7a1
Merge pull request #2053 from nspcc-dev/stackitem-json
Speedup stackitem json serialization
2021-07-13 11:27:33 +03:00
Evgeniy Stratonikov
0611031fd4 stackitem/test: improve coverage for serialization
Signed-off-by: Evgeniy Stratonikov <evgeniy@nspcc.ru>
2021-07-13 11:06:19 +03:00
Evgeniy Stratonikov
8fdc7e32f5 stackitem: cache serialized results in EncodeBinary
```
name            old time/op    new time/op    delta
EncodeBinary-8    8.39ms ± 1%    0.05ms ±21%  -99.44%  (p=0.000 n=10+9)

name            old alloc/op   new alloc/op   delta
EncodeBinary-8    2.24MB ± 0%    0.33MB ± 0%  -85.29%  (p=0.000 n=9+10)

name            old allocs/op  new allocs/op  delta
EncodeBinary-8     65.6k ± 0%      0.0k ± 0%  -99.95%  (p=0.000 n=10+10)
```

Signed-off-by: Evgeniy Stratonikov <evgeniy@nspcc.ru>
2021-07-13 11:06:19 +03:00
Evgeniy Stratonikov
17a3f17c74 stackitem: use byte-slice directly during encoding
```
name            old time/op    new time/op    delta
EncodeBinary-8    10.6ms ± 1%     8.4ms ± 1%  -20.94%  (p=0.000 n=9+10)

name            old alloc/op   new alloc/op   delta
EncodeBinary-8    1.64MB ± 0%    2.24MB ± 0%  +36.18%  (p=0.000 n=8+9)

name            old allocs/op  new allocs/op  delta
EncodeBinary-8      131k ± 0%       66k ± 0%  -49.98%  (p=0.000 n=10+10)
```

Signed-off-by: Evgeniy Stratonikov <evgeniy@nspcc.ru>
2021-07-13 11:06:18 +03:00
Evgeniy Stratonikov
c4eb7db8a5 stackitem: access value of Array/Struct directly
```
name      old time/op    new time/op    delta
ToJSON-8    50.3µs ±34%    47.8µs ± 9%     ~     (p=0.971 n=10+10)

name      old alloc/op   new alloc/op   delta
ToJSON-8     396kB ± 0%     396kB ± 0%   -0.10%  (p=0.000 n=6+10)

name      old allocs/op  new allocs/op  delta
ToJSON-8      34.0 ± 0%      18.0 ± 0%  -47.06%  (p=0.000 n=10+10)
```

Signed-off-by: Evgeniy Stratonikov <evgeniy@nspcc.ru>
2021-07-12 14:40:21 +03:00
Evgeniy Stratonikov
dc0a17dd0e stackitem: cache visited items while marshaling json
```
name      old time/op    new time/op    delta
ToJSON-8    4.52ms ± 4%    0.05ms ±34%  -98.89%  (p=0.000 n=8+10)

name      old alloc/op   new alloc/op   delta
ToJSON-8    2.13MB ± 0%    0.40MB ± 0%  -81.44%  (p=0.000 n=9+6)

name      old allocs/op  new allocs/op  delta
ToJSON-8     65.6k ± 0%      0.0k ± 0%  -99.95%  (p=0.000 n=10+10)
```

Signed-off-by: Evgeniy Stratonikov <evgeniy@nspcc.ru>
2021-07-12 14:40:21 +03:00
Evgeniy Stratonikov
69cdd5252a stackitem: add benchmark for serialization routines
Signed-off-by: Evgeniy Stratonikov <evgeniy@nspcc.ru>
2021-07-12 14:40:17 +03:00
Roman Khimov
fe3c68b92d vm: panic in cloneIfStruct
It's internal, so we can deduplicate code a bit.
2021-07-12 11:52:24 +03:00
Roman Khimov
4000dd692c vm: make cloning limits a bit more effective
Take actual reference counter value into account.
2021-07-11 19:37:06 +03:00
Roman Khimov
cfe41abd35 vm: fix OOM during nested structure cloning
Resulting item can't have more than MaxStackSize elements. Technically this
limits to MaxStackSize cloned elements but it's considered to be enough to
mitigate the issue (the next size check is going to happen during push to the
stack). See neo-project/neo#2534, thanks @vang1ong7ang.
2021-07-11 18:47:50 +03:00
Evgeniy Stratonikov
1863023e27 vm: copy argument in unary opcodes, fix #2051
We already do this in binary opcodes, let's be consistent.

This fixes state difference at height 275663
for tx 3c498317684d63849b03e4c58ad57ce4b19bb206b7b01bcc64233de3b3e207f4

Signed-off-by: Evgeniy Stratonikov <evgeniy@nspcc.ru>
2021-07-08 17:09:04 +03:00
Roman Khimov
e62a766058 state: move nil check down to stackitem JSON processing
We want to return real errors, not some generic thing for any kind of thing
happening.
2021-07-07 00:38:19 +03:00
Roman Khimov
5a9efcc654 stackitem: rework error handling
Return good named errors everywhere, export appropriate constants, make
errors.Is() work.
2021-07-07 00:18:00 +03:00
Roman Khimov
0de949b575 stackitem: remove Item/StackItem from function names
They're useless in a package named 'stackitem', make this package a bit more
user-friendly.
2021-07-06 19:56:23 +03:00
Roman Khimov
b9ff07f32c stackitem: add limit to serialized items
Standard binary serialization/deserialization is mostly used in VM to put/get
elements into/from storage, so they never should exceed MaxSize (otherwise one
won't be able to deserialize these items).

This patch leaves EncodeBinaryStackItem unprotected, but that's a streaming
interface, so it's up to the user of it to ensure its appropriate use (and our
uses are mostly for native contract's data, so they're fine).
2021-07-06 19:34:02 +03:00
Roman Khimov
8472064bbc stackitem: refactor serialization code, add explicit context 2021-07-06 19:32:52 +03:00
Roman Khimov
1b7b7e4bec stackitem: don't overwrite error when serializing Item
We must get out as quickly as possible.
2021-07-06 17:51:46 +03:00
Roman Khimov
e34fa2e915 stackitem: limit JSONization nesting level
We can have very deep reference types and attempt to JSONize them can easily
lead to OOM (even though there are no recursive references inside). Therefore
we have to limit them. While regular ToJSON() is buffer size limited to
MaxSize, ToJSONWithTypes is not and limiting it to MaxSize output will require
substantial rewriting effort while not really providing fair result, MaxSize
is more about stack item size while its JSON representation can be much bigger
because of various overheads.

Initial thought was to limit it by element count based on
MaxIteratorResultItems, but the problem here is that we don't always have this
limit in contexts using ToJSONWithTypes (like notification event
marshaling). Thus we need some generic limit which would be fine for all
users.

We at the same time have maxJSONDepth used when deserializing from JSON, so
it can be used for marshaling as well, it's not often that we have deeper
structures in real results.

Inspired by neo-project/neo#2521.
2021-07-06 17:33:16 +03:00
Roman Khimov
6879cbcdcc stackitem: properly detect recursive references during serialization
If we're done with element it no longer can lead to recursion error, so fix
cases like `[arr, arr]` where we have two copies of `arr` trigger this error
for no good reason (there is no recursion there).
2021-07-06 17:10:31 +03:00
Evgeniy Stratonikov
8d67a03aec stackitem: fix Buffer deserialization
Fix incorrect application log for transaction in N3 testnet
8eb4076f1f1c07e693eda7e810779488a2d2b50aba9b727fd237cbc3adbec9e9

Signed-off-by: Evgeniy Stratonikov <evgeniy@nspcc.ru>
2021-06-29 11:39:55 +03:00