Files
benchmarks/bench-blockchain/warp_test.go
zeekayandHanzo Dev 0cd2c897d6 Go 1.27.1, and the code it can say more simply
Modules declare go 1.27.1. go fix applied the modernizers; omitzero is
not applied, since it changes what the JSON says.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-16 19:16:58 -07:00

429 lines
11 KiB
Go

package blockchain
import (
"crypto/sha256"
"encoding/binary"
"encoding/json"
"testing"
)
// Warp Message structures for cross-chain communication
// Based on Lux Network's AWM (Avalanche Warp Messaging) patterns
// JSONWarpMessage - traditional JSON encoding
type JSONWarpMessage struct {
SourceChainID string `json:"source_chain_id"`
DestinationChainID string `json:"destination_chain_id"`
Nonce uint64 `json:"nonce"`
Timestamp int64 `json:"timestamp"`
Payload []byte `json:"payload"`
Signatures []string `json:"signatures"`
}
// JSONValidatorSet - for consensus updates
type JSONValidatorSet struct {
Epoch uint64 `json:"epoch"`
Validators []JSONValidator `json:"validators"`
TotalStake uint64 `json:"total_stake"`
}
type JSONValidator struct {
NodeID string `json:"node_id"`
PublicKey string `json:"public_key"`
Stake uint64 `json:"stake"`
StartTime int64 `json:"start_time"`
EndTime int64 `json:"end_time"`
}
// JSONConsensusVote
type JSONConsensusVote struct {
BlockHash string `json:"block_hash"`
Height uint64 `json:"height"`
Round uint32 `json:"round"`
ValidatorID string `json:"validator_id"`
Signature string `json:"signature"`
Timestamp int64 `json:"timestamp"`
}
// ZAP versions - zero-copy binary format
// ZAPWarpMessage header (48 bytes fixed)
type ZAPWarpMessage struct {
SourceChainID [32]byte // Fixed chain ID
DestinationChainID [32]byte
Nonce uint64
Timestamp int64
PayloadPtr uint32 // offset to payload
PayloadLen uint32
SigsPtr uint32 // offset to signatures
SigsCount uint32
// Variable data follows
}
const warpHeaderSize = 32 + 32 + 8 + 8 + 4 + 4 + 4 + 4 // 96 bytes
func zapEncodeWarpMessage(buf []byte, srcChain, dstChain [32]byte, nonce uint64, ts int64, payload []byte, sigs [][]byte) int {
offset := 0
// Fixed header
copy(buf[offset:], srcChain[:])
offset += 32
copy(buf[offset:], dstChain[:])
offset += 32
binary.LittleEndian.PutUint64(buf[offset:], nonce)
offset += 8
binary.LittleEndian.PutUint64(buf[offset:], uint64(ts))
offset += 8
// Payload pointer/length
payloadOffset := warpHeaderSize
binary.LittleEndian.PutUint32(buf[offset:], uint32(payloadOffset))
offset += 4
binary.LittleEndian.PutUint32(buf[offset:], uint32(len(payload)))
offset += 4
// Signatures pointer/count
sigsOffset := payloadOffset + len(payload)
binary.LittleEndian.PutUint32(buf[offset:], uint32(sigsOffset))
offset += 4
binary.LittleEndian.PutUint32(buf[offset:], uint32(len(sigs)))
offset += 4
// Write payload
copy(buf[payloadOffset:], payload)
// Write signatures (fixed 64 bytes each for Ed25519)
sigOffset := sigsOffset
for _, sig := range sigs {
copy(buf[sigOffset:], sig)
sigOffset += 64
}
return sigOffset
}
func zapDecodeWarpMessage(buf []byte) (srcChain, dstChain [32]byte, nonce uint64, ts int64, payload []byte, sigs [][]byte) {
copy(srcChain[:], buf[0:32])
copy(dstChain[:], buf[32:64])
nonce = binary.LittleEndian.Uint64(buf[64:])
ts = int64(binary.LittleEndian.Uint64(buf[72:]))
payloadPtr := binary.LittleEndian.Uint32(buf[80:])
payloadLen := binary.LittleEndian.Uint32(buf[84:])
sigsPtr := binary.LittleEndian.Uint32(buf[88:])
sigsCount := binary.LittleEndian.Uint32(buf[92:])
payload = buf[payloadPtr : payloadPtr+payloadLen]
sigs = make([][]byte, sigsCount)
for i := range sigsCount {
sigs[i] = buf[sigsPtr+i*64 : sigsPtr+(i+1)*64]
}
return
}
// Test data generators
func generateWarpPayload(size int) []byte {
payload := make([]byte, size)
for i := range payload {
payload[i] = byte(i % 256)
}
return payload
}
func generateSignatures(count int) [][]byte {
sigs := make([][]byte, count)
for i := range sigs {
sigs[i] = make([]byte, 64)
for j := range sigs[i] {
sigs[i][j] = byte((i + j) % 256)
}
}
return sigs
}
func generateSignatureStrings(count int) []string {
sigs := make([]string, count)
for i := range sigs {
sig := make([]byte, 64)
for j := range sig {
sig[j] = byte((i + j) % 256)
}
sigs[i] = string(sig)
}
return sigs
}
// Warp message encoding benchmarks
func BenchmarkZAPWarpMessage(b *testing.B) {
srcChain := sha256.Sum256([]byte("source-chain"))
dstChain := sha256.Sum256([]byte("dest-chain"))
payload := generateWarpPayload(1024)
sigs := generateSignatures(10) // 10 validator signatures
buf := make([]byte, 8192)
b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
zapEncodeWarpMessage(buf, srcChain, dstChain, uint64(i), 1706000000000, payload, sigs)
}
}
func BenchmarkJSONWarpMessage(b *testing.B) {
msg := JSONWarpMessage{
SourceChainID: "2JVSBoinj9C2J33VntvzYtVJNZdN2NKiwwKjcumHUWEb5DbBrm",
DestinationChainID: "yH8D7ThNJkxmtkuv2jgBa4P1Rn3Qpr4pPr7QYNfcdoS6k6HWp",
Nonce: 12345,
Timestamp: 1706000000000,
Payload: generateWarpPayload(1024),
Signatures: generateSignatureStrings(10),
}
b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
json.Marshal(msg)
}
}
func BenchmarkZAPWarpDecode(b *testing.B) {
srcChain := sha256.Sum256([]byte("source-chain"))
dstChain := sha256.Sum256([]byte("dest-chain"))
payload := generateWarpPayload(1024)
sigs := generateSignatures(10)
buf := make([]byte, 8192)
zapEncodeWarpMessage(buf, srcChain, dstChain, 12345, 1706000000000, payload, sigs)
b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
zapDecodeWarpMessage(buf)
}
}
func BenchmarkJSONWarpDecode(b *testing.B) {
msg := JSONWarpMessage{
SourceChainID: "2JVSBoinj9C2J33VntvzYtVJNZdN2NKiwwKjcumHUWEb5DbBrm",
DestinationChainID: "yH8D7ThNJkxmtkuv2jgBa4P1Rn3Qpr4pPr7QYNfcdoS6k6HWp",
Nonce: 12345,
Timestamp: 1706000000000,
Payload: generateWarpPayload(1024),
Signatures: generateSignatureStrings(10),
}
data, _ := json.Marshal(msg)
b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
var decoded JSONWarpMessage
json.Unmarshal(data, &decoded)
}
}
// Validator set update benchmarks (consensus critical path)
func BenchmarkZAPValidatorSet100(b *testing.B) {
// 100 validators, typical network size
buf := make([]byte, 100*1024) // 100KB
b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
offset := 0
// Header: epoch + count + total_stake
binary.LittleEndian.PutUint64(buf[offset:], 12345) // epoch
offset += 8
binary.LittleEndian.PutUint32(buf[offset:], 100) // count
offset += 4
binary.LittleEndian.PutUint64(buf[offset:], 10000000) // total stake
offset += 8
// Each validator: 32-byte nodeID + 48-byte pubkey + 8-byte stake + 8+8 times
for j := range 100 {
// NodeID (32 bytes)
binary.LittleEndian.PutUint64(buf[offset:], uint64(j))
offset += 32
// PubKey (48 bytes BLS)
offset += 48
// Stake
binary.LittleEndian.PutUint64(buf[offset:], 100000)
offset += 8
// Start/End times
binary.LittleEndian.PutUint64(buf[offset:], 1706000000000)
offset += 8
binary.LittleEndian.PutUint64(buf[offset:], 1706000000000+86400*365)
offset += 8
}
}
}
func BenchmarkJSONValidatorSet100(b *testing.B) {
validators := make([]JSONValidator, 100)
for i := range validators {
validators[i] = JSONValidator{
NodeID: "NodeID-7Xhw2mDxuDS44j42TCB6U5579esbSt3Lg",
PublicKey: "0x8a2fc8c01c7a2f8b6c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7b",
Stake: 100000,
StartTime: 1706000000000,
EndTime: 1706000000000 + 86400*365,
}
}
set := JSONValidatorSet{
Epoch: 12345,
Validators: validators,
TotalStake: 10000000,
}
b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
json.Marshal(set)
}
}
// Consensus vote benchmarks (latency critical)
func BenchmarkZAPConsensusVote(b *testing.B) {
buf := make([]byte, 256)
b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
offset := 0
// BlockHash (32 bytes)
offset += 32
// Height
binary.LittleEndian.PutUint64(buf[offset:], 1000000)
offset += 8
// Round
binary.LittleEndian.PutUint32(buf[offset:], 1)
offset += 4
// ValidatorID (32 bytes)
offset += 32
// Signature (64 bytes)
offset += 64
// Timestamp
binary.LittleEndian.PutUint64(buf[offset:], 1706000000000)
}
}
func BenchmarkJSONConsensusVote(b *testing.B) {
vote := JSONConsensusVote{
BlockHash: "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
Height: 1000000,
Round: 1,
ValidatorID: "NodeID-7Xhw2mDxuDS44j42TCB6U5579esbSt3Lg",
Signature: "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef12345678",
Timestamp: 1706000000000,
}
b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
json.Marshal(vote)
}
}
// Batch consensus votes (1000 votes, typical block attestation)
func BenchmarkZAPConsensusVoteBatch1000(b *testing.B) {
buf := make([]byte, 256*1000)
b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
for j := range 1000 {
offset := j * 144 // Fixed vote size
// BlockHash (32 bytes)
binary.LittleEndian.PutUint64(buf[offset:], uint64(j))
offset += 32
// Height
binary.LittleEndian.PutUint64(buf[offset:], 1000000)
offset += 8
// Round
binary.LittleEndian.PutUint32(buf[offset:], 1)
offset += 4
// ValidatorID (32 bytes)
offset += 32
// Signature (64 bytes)
offset += 64
// Timestamp
binary.LittleEndian.PutUint64(buf[offset:], 1706000000000)
}
}
}
func BenchmarkJSONConsensusVoteBatch1000(b *testing.B) {
votes := make([]JSONConsensusVote, 1000)
for i := range votes {
votes[i] = JSONConsensusVote{
BlockHash: "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
Height: 1000000,
Round: 1,
ValidatorID: "NodeID-7Xhw2mDxuDS44j42TCB6U5579esbSt3Lg",
Signature: "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef12345678",
Timestamp: 1706000000000,
}
}
b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
json.Marshal(votes)
}
}
// State sync benchmark (memory-mapped access simulation)
func BenchmarkZAPStateAccess(b *testing.B) {
// Simulate accessing random state in a 1MB buffer
state := make([]byte, 1024*1024)
for i := range state {
state[i] = byte(i % 256)
}
b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
// Direct access to specific offset (simulating mmap)
offset := (i * 1024) % (1024 * 1024)
_ = binary.LittleEndian.Uint64(state[offset:])
}
}
func BenchmarkJSONStateAccess(b *testing.B) {
// Must parse entire state to access any field
state := map[string]any{
"accounts": make([]map[string]any, 1000),
}
for i := range 1000 {
state["accounts"].([]map[string]any)[i] = map[string]any{
"address": "0x1234567890abcdef",
"balance": 100000,
"nonce": i,
}
}
data, _ := json.Marshal(state)
b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
var parsed map[string]any
json.Unmarshal(data, &parsed)
// Access one account
_ = parsed["accounts"].([]any)[i%1000]
}
}