generated from TrueCloudLab/basic
Add chain serializers #42
No reviewers
Labels
No labels
Infrastructure
blocked
bug
config
discussion
documentation
duplicate
enhancement
go
help wanted
internal
invalid
kludge
observability
perfomance
question
refactoring
wontfix
No milestone
No project
No assignees
5 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: TrueCloudLab/policy-engine#42
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "dstepanov-yadro/policy-engine:feat/marshal"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes #1
For binary marshalling added simple binary marshaller based on
encoding/binary
package. It could be optimized with unsafe string marshal/unmarshal methods, but it looks error-prone in public package.For json marshalling added json marshaller based on
easyjson
. For enum-types added custom marshal/unmarshal methods to save to json human-readable strings.Also changed
ID
's type from string to bytes (see discussion below).a5818ce3d0
to0191c88935
Add chain marshallersto Add chain serializers0191c88935
to232bed56b8
232bed56b8
to53022608ed
@ -0,0 +11,4 @@
"github.com/stretchr/testify/require"
)
func TestID(t *testing.T) {
Test from #1 (comment)
I think if ID is defined as string, it means that it should have bytes from utf-8 encoding. So as ID is public, so developer has to set valid value to this field.
Probably yes, but we started use chainID as name in policy contract so we have to fit length limitation and have deterministic id.
Looks like then we need to change
ID
type to[]byte
.Replaced
ID
marshalling asbase64
bytes, so now your test passes.String has one advantage: it can't be nil.
53022608ed
to8ec573f89b
8ec573f89b
toa214196c87
@ -0,0 +85,4 @@
{
const prefix string = ",\"ID\":"
out.RawString(prefix[1:])
out.Base64Bytes(in.ID)
The file's header says
I looked at the last commit and I guess you have edited this on your own. Please, could you leave some warning comment like "this line is hand-written". Because anyone who is going to re-generate it, of course, will forget about
Base64
:)Right, this file was edited with easyjson tool ran with
make generate
.I have deleted
ID
'sMarshalEasyJSON
andUnmarshalEasyJSON
methods, so easyjson changed chain marshal/unmarshal implementation.Excellent work! 👍
@ -63,0 +65,4 @@
easyjson-install:
@rm -rf $(EASYJSON_DIR)
@mkdir $(EASYJSON_DIR)
-p
required.Done
@ -0,0 +1,463 @@
// Code generated by easyjson for marshaling/unmarshaling. DO NOT EDIT.
What about adding
/**/*_easyjson.go -diff -merge
in.gitattributes
like we do for.pb.go
in node?What about adding
/**/*_easyjson.go -diff -merge
in.gitattributes
like we do for.pb.go
in node?Done
@ -0,0 +91,4 @@
return offset, nil
}
func SliceUnmarshal[T any](buf []byte, offset int, unmarshalT func(buf []byte, offset int) (T, int, error)) ([]T, int, error) {
Why have you decided to implement this package instead of reusing https://github.com/nspcc-dev/neo-go/tree/master/pkg/io ? Speed?
Counter question: Why did I have to use it? And why not one of the https://github.com/alecthomas/go_serialization_benchmarks#results :)
The real answer is that I don't want to make some additional deps. Also I don't use
any
orreflect
.You didn't have to, it was a question. My argument: because it is common in our ecosystem, has a nice streaming interface and doesn't count as "new" format we all need to learn.
That's perfect, I don't mind leaving it as is. My problems with all marshalers is that they seem to be impossible to write correctly (without panics) from the first try. Maybe add some fuzz tests here? It would be quite simple, we just want to be sure that unmarshal doesn't panic.
I have added tests for
marshal.go
, now test coverage is 93.9%.Tests have been added to the chain marshalling that test a variety of options. Of course, this is not a guarantee, but still.
Fuzzing for a chain looks very complicated: there are too many parameters.
Panics are possible, for example, when allocating memory for a slice, but this panic depends not only on the number of elements, but also on the size of the element, so it is difficult to check.
No-no, we fuzz just unmarshaling -- it is raw bytes, so should be easy. Marshaling is more believable to not panic.
An example with similar test
ef99a7a9e3/pkg/core/transaction/fuzz_test.go (L11)
For example, it seems we do not have any size checks in
SliceUnmarshal()
: what happens if I use9999999
length which is followed by just 3 bytes. It is invalid, but I allocate9999999
bytes (add more nines and it is an easy OOM).Am I missing something?
In neo-go the problem is solved by restricting array size, I think sth similar is applicable here (chains go in contract, so we may restrict them to 64k in size).
Yes, it is. But total slice size depends on item size, so this check is not strict, so OOM may happen even if size limited.
Here is the code:
Every
unmarshal
checks offset and buffer size, soerr
will be returned. Seecorrupted slice size
and other negative unit test.result := make([]T, size)
-- this will panic, right?Yes, but the size of unmarshaled chain is comparable to the size of the slice of bytes (and our slice fits in memory).
We just cannot allow having panic in unmarshal, it works with untrusted data.
Agree. Added fuzz test and slice size check.
19d12b3b27
todc0e63ddbb
dc0e63ddbb
tod56d88c638
d56d88c638
to0a28f0a992