First attempt to have some fuzz tests exported for the fuzzing framework
This commit is contained in:
parent
a1198e5532
commit
3b3a2b10f1
12
Makefile
12
Makefile
|
@ -90,3 +90,15 @@ testnet1-no-clean: | build deps
|
|||
|
||||
clean: | clean-common
|
||||
rm -rf build/{$(TOOLS_CSV),all_tests,*_node}
|
||||
|
||||
libnfuzz.so: | build deps-common beacon_chain.nims
|
||||
echo -e $(BUILD_MSG) "build/$@" && \
|
||||
$(ENV_SCRIPT) nim c -d:release --debugger:native --app:lib --noMain --nimcache:nimcache/libnfuzz $(NIM_PARAMS) -o:build/$@.0 nfuzz/libnfuzz.nim && \
|
||||
rm -f build/$@ && \
|
||||
ln -s $@.0 build/$@
|
||||
|
||||
libnfuzz.a: | build deps-common beacon_chain.nims
|
||||
echo -e $(BUILD_MSG) "build/$@" && \
|
||||
rm -f build/$@ && \
|
||||
$(ENV_SCRIPT) nim c -d:release --debugger:native --app:staticlib --noMain --nimcache:nimcache/libnfuzz_static $(NIM_PARAMS) -o:build/$@ nfuzz/libnfuzz.nim && \
|
||||
[[ -e "$@" ]] && mv "$@" build/ # workaround for https://github.com/nim-lang/Nim/issues/12745
|
||||
|
|
|
@ -13,7 +13,7 @@ import
|
|||
# TODO: Proceed to renaming and signature changes
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.9.2/specs/core/0_beacon-chain.md#compute_shuffled_index
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.9.2/specs/core/0_beacon-chain.md#compute_committee
|
||||
func get_shuffled_seq(seed: Eth2Digest,
|
||||
func get_shuffled_seq*(seed: Eth2Digest,
|
||||
list_size: uint64,
|
||||
): seq[ValidatorIndex] =
|
||||
## Via https://github.com/protolambda/eth2-shuffle/blob/master/shuffle.go
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
#ifndef __LIBNFUZZ_H__
|
||||
#define __LIBNFUZZ_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void NimMain();
|
||||
|
||||
bool nfuzz_block(uint8_t* input_ptr, size_t input_size,
|
||||
uint8_t* output_ptr, size_t* output_size);
|
||||
bool nfuzz_attestation(uint8_t* input_ptr, size_t input_size,
|
||||
uint8_t* output_ptr, size_t* output_size);
|
||||
void nfuzz_shuffle(uint8_t* seed_ptr, uint64_t* output_ptr, size_t output_size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //__LIBNFUZZ_H__
|
|
@ -0,0 +1,86 @@
|
|||
import
|
||||
endians, stew/ptrops, stew/ranges/ptr_arith,
|
||||
../beacon_chain/[ssz, state_transition],
|
||||
../beacon_chain/spec/[datatypes, helpers, digest, validator, beaconstate],
|
||||
# Required for deserialisation of ValidatorSig in Attestation due to
|
||||
# https://github.com/nim-lang/Nim/issues/11225
|
||||
../beacon_chain/spec/crypto
|
||||
|
||||
type
|
||||
BlockInput = object
|
||||
state: BeaconState
|
||||
beaconBlock: BeaconBlock
|
||||
AttestationInput = object
|
||||
state: BeaconState
|
||||
attestation: Attestation
|
||||
|
||||
proc copyState(state: BeaconState, output: ptr byte,
|
||||
output_size: ptr csize): bool {.raises:[IOError, Defect].} =
|
||||
# Not catching any errors as it is assumed that a state object will always be
|
||||
# in a shape that it is serializable. Can raise IOError and Defects though.
|
||||
let resultState = SSZ.encode(state)
|
||||
if resultState.len <= output_size[]:
|
||||
output_size[] = resultState.len
|
||||
# Note: improvement might be to write directly to buffer with OutputStream
|
||||
# and SszWriter
|
||||
copyMem(output, unsafeAddr resultState[0], output_size[])
|
||||
result = true
|
||||
|
||||
proc nfuzz_block(input: openArray[byte], output: ptr byte,
|
||||
output_size: ptr csize): bool {.exportc.} =
|
||||
var data: BlockInput
|
||||
|
||||
try:
|
||||
data = SSZ.decode(input, BlockInput)
|
||||
except MalformedSszError, SszSizeMismatchError, RangeError:
|
||||
return false
|
||||
|
||||
try:
|
||||
result = state_transition(data.state, data.beaconBlock, flags = {})
|
||||
except ValueError: # Not catching Defect, IOError and ... Exception! :(
|
||||
discard
|
||||
|
||||
if result:
|
||||
result = copyState(data.state, output, output_size)
|
||||
|
||||
proc nfuzz_attestation(input: openArray[byte], output: ptr byte,
|
||||
output_size: ptr csize): bool {.exportc.} =
|
||||
var
|
||||
data: AttestationInput
|
||||
cache = get_empty_per_epoch_cache()
|
||||
|
||||
try:
|
||||
data = SSZ.decode(input, AttestationInput)
|
||||
except MalformedSszError, SszSizeMismatchError, RangeError:
|
||||
return false
|
||||
|
||||
try:
|
||||
result = process_attestation(data.state, data.attestation,
|
||||
flags = {}, cache)
|
||||
except ValueError: # Not catching Defect and IOError
|
||||
discard
|
||||
|
||||
if result:
|
||||
result = copyState(data.state, output, output_size)
|
||||
|
||||
# Note: Could also accept raw input pointer and access list_size + seed here.
|
||||
# However, list_size needs to be known also outside this proc to allocate output.
|
||||
# TODO: rework to copy immediatly in an uint8 openArray, considering we have to
|
||||
# go over the list anyhow?
|
||||
proc nfuzz_shuffle(input_seed: ptr byte, output: var openArray[uint64])
|
||||
{.exportc.} =
|
||||
var seed: Eth2Digest
|
||||
let list_size = output.len.uint64 # should be OK as max 2 bytes are passed.
|
||||
|
||||
copyMem(addr(seed.data), input_seed, 32)
|
||||
|
||||
# TODO: is RangeError a valid error here that needs to be catched?
|
||||
let shuffled_seq = get_shuffled_seq(seed, list_size)
|
||||
|
||||
doAssert(list_size == shuffled_seq.len.uint64)
|
||||
|
||||
for i in 0..<list_size:
|
||||
# ValidatorIndex is currently wrongly uint32 so we copy this 1 by 1,
|
||||
# assumes passed output is zeroed.
|
||||
copyMem(offset(addr output, i.int), shuffled_seq[i.int].unsafeAddr,
|
||||
sizeof(ValidatorIndex))
|
Loading…
Reference in New Issue