-
Notifications
You must be signed in to change notification settings - Fork 4
Fuzz Network Test Framework #326
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
7a0e4c2
33831c6
f407d8d
06cf6b5
fae084f
7642681
24ab202
e732758
3fe5aa3
0b2410f
167042c
6a69e4a
c2b04a6
93e1792
6274ce3
a968dfc
ee55ad4
1fef374
19f922d
0cde180
316171a
73dcda3
d06c5c7
c98d1ea
7305061
3c24868
474b9b9
3e1dc18
a811c69
20a3842
1b56415
3f3ddad
6fb79ee
9f3784f
cb097aa
d0a73a7
965f081
a944f1b
e0bedfe
9ac9040
16d1f9b
bab8db1
1963835
11b67e3
41f7a94
a46f5e7
daf8058
09391a7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -30,3 +30,7 @@ go.work.sum | |
|
|
||
| .DS_Store | ||
| .idea/ | ||
|
|
||
| # tmp folder | ||
|
|
||
| /tmp | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| package simplex_test | ||
|
|
||
| import ( | ||
| "testing" | ||
|
|
||
| "github.com/ava-labs/simplex/testutil/random_network" | ||
| ) | ||
|
|
||
| func TestNetworkSimpleFuzz(t *testing.T) { | ||
| config := random_network.DefaultFuzzConfig() | ||
| config.RandomSeed = 1770220909588 | ||
| network := random_network.NewNetwork(config, t) | ||
| network.Run() | ||
| network.PrintStatus() | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,143 @@ | ||
| // Copyright (C) 2019-2025, Ava Labs, Inc. All rights reserved. | ||
| // See the file LICENSE for licensing terms. | ||
|
|
||
| package random_network | ||
samliok marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| import ( | ||
| "bytes" | ||
| "context" | ||
| "crypto/sha256" | ||
| "encoding/asn1" | ||
| "fmt" | ||
|
|
||
| "github.com/ava-labs/simplex" | ||
| ) | ||
|
|
||
| var _ simplex.Block = (*Block)(nil) | ||
|
|
||
| type Block struct { | ||
| blacklist simplex.Blacklist | ||
|
|
||
| // contents | ||
| txs []*TX | ||
|
|
||
| // protocol metadata | ||
| metadata simplex.ProtocolMetadata | ||
| digest simplex.Digest | ||
|
|
||
| // mempool access | ||
| mempool *Mempool | ||
| } | ||
|
|
||
| func NewBlock(metadata simplex.ProtocolMetadata, blacklist simplex.Blacklist, mempool *Mempool, txs []*TX) *Block { | ||
| b := &Block{ | ||
| mempool: mempool, | ||
| txs: txs, | ||
| metadata: metadata, | ||
| blacklist: blacklist, | ||
| } | ||
|
|
||
| b.ComputeAndSetDigest() | ||
| return b | ||
| } | ||
|
|
||
| func (b *Block) Verify(ctx context.Context) (simplex.VerifiedBlock, error) { | ||
| return b, b.mempool.VerifyBlock(ctx, b) | ||
| } | ||
|
|
||
| func (b *Block) Blacklist() simplex.Blacklist { | ||
| return b.blacklist | ||
| } | ||
|
|
||
| func (b *Block) BlockHeader() simplex.BlockHeader { | ||
| return simplex.BlockHeader{ | ||
| ProtocolMetadata: b.metadata, | ||
| Digest: b.digest, | ||
| } | ||
| } | ||
|
|
||
| type encodedBlock struct { | ||
| ProtocolMetadata []byte | ||
| TXs []asn1TX | ||
| Blacklist []byte | ||
| } | ||
|
|
||
| func (b *Block) Bytes() ([]byte, error) { | ||
| mdBytes := b.metadata.Bytes() | ||
|
|
||
| var asn1TXs []asn1TX | ||
| for _, tx := range b.txs { | ||
| asn1TXs = append(asn1TXs, asn1TX{ID: tx.ID[:]}) | ||
| } | ||
|
|
||
| blacklistBytes := b.blacklist.Bytes() | ||
|
|
||
| encodedB := encodedBlock{ | ||
| ProtocolMetadata: mdBytes, | ||
| TXs: asn1TXs, | ||
| Blacklist: blacklistBytes, | ||
| } | ||
|
|
||
| return asn1.Marshal(encodedB) | ||
| } | ||
|
|
||
| func (b *Block) containsTX(txID txID) bool { | ||
| for _, tx := range b.txs { | ||
| if tx.ID == txID { | ||
| return true | ||
| } | ||
| } | ||
| return false | ||
| } | ||
|
|
||
| func (b *Block) ComputeAndSetDigest() { | ||
| var bb bytes.Buffer | ||
| tbBytes, err := b.Bytes() | ||
| if err != nil { | ||
| panic(fmt.Sprintf("failed to serialize test block: %v", err)) | ||
| } | ||
|
|
||
| bb.Write(tbBytes) | ||
| b.digest = sha256.Sum256(bb.Bytes()) | ||
| } | ||
|
|
||
| type BlockDeserializer struct { | ||
| mempool *Mempool | ||
| } | ||
|
|
||
| var _ simplex.BlockDeserializer = (*BlockDeserializer)(nil) | ||
|
|
||
| func (bd *BlockDeserializer) DeserializeBlock(ctx context.Context, buff []byte) (simplex.Block, error) { | ||
| var encodedBlock encodedBlock | ||
| _, err := asn1.Unmarshal(buff, &encodedBlock) | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
|
|
||
| md, err := simplex.ProtocolMetadataFromBytes(encodedBlock.ProtocolMetadata) | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
|
|
||
| var blacklist simplex.Blacklist | ||
| if err := blacklist.FromBytes(encodedBlock.Blacklist); err != nil { | ||
| return nil, err | ||
| } | ||
|
|
||
| txs := make([]*TX, len(encodedBlock.TXs)) | ||
| for i, asn1Tx := range encodedBlock.TXs { | ||
| tx := asn1Tx.toTX() | ||
| txs[i] = tx | ||
| } | ||
|
|
||
| b := &Block{ | ||
| metadata: *md, | ||
| txs: txs, | ||
| blacklist: blacklist, | ||
| mempool: bd.mempool, | ||
| } | ||
|
|
||
| b.ComputeAndSetDigest() | ||
|
|
||
| return b, nil | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,54 @@ | ||
| // Copyright (C) 2019-2025, Ava Labs, Inc. All rights reserved. | ||
| // See the file LICENSE for licensing terms. | ||
|
|
||
| package random_network | ||
samliok marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| import "time" | ||
|
|
||
| type FuzzConfig struct { | ||
| // The minimum and maximum number of nodes in the network. Default is between 3 and 10. | ||
| MinNodes int | ||
| MaxNodes int | ||
|
|
||
| // The probability that a transaction verification will fail. Default is .1%. | ||
| TxVerificationFailure float64 | ||
|
|
||
| // The minimum and maximum number of transactions per block. Default is between 5 and 20. | ||
| MinTxsPerBlock int | ||
| MaxTxsPerBlock int | ||
|
|
||
| // The number of blocks that must be finalized before ending the fuzz test. Default is 100. | ||
| NumFinalizedBlocks int | ||
|
|
||
| RandomSeed int64 | ||
|
|
||
| // Chance that a node will be randomly crashed. Default is 10%. | ||
| NodeCrashPercentage float64 | ||
|
|
||
| // Chance that a crashed node will be restarted. Default is 50%. | ||
| NodeRecoverPercentage float64 | ||
|
|
||
| // Amount to advance the time by. Default is 1000ms. | ||
| AdvanceTimeTickAmount time.Duration | ||
|
|
||
| // Creates main.log for network logs and {nodeID-short}.log for each node. | ||
| // NodeID is represented as a 16-character hex string (first 8 bytes). | ||
| // Default is "tmp". | ||
| LogDirectory string | ||
| } | ||
|
|
||
| func DefaultFuzzConfig() *FuzzConfig { | ||
| return &FuzzConfig{ | ||
| MinNodes: 3, | ||
| MaxNodes: 10, | ||
| TxVerificationFailure: .001, | ||
| MinTxsPerBlock: 5, | ||
| MaxTxsPerBlock: 20, | ||
| NumFinalizedBlocks: 100, | ||
| RandomSeed: time.Now().UnixMilli(), | ||
| NodeCrashPercentage: 0.1, | ||
| NodeRecoverPercentage: 0.5, | ||
| AdvanceTimeTickAmount: 1000 * time.Millisecond, | ||
| LogDirectory: "tmp", | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we need to create a temporary folder and if the test succeeds, delete the logs.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This way you don't need to delete the directory at the beginning of the test |
||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the use of adding /tmp?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the logs are written to /tmp, and i would like to save the logs for debugging but not commit them to github