Deterministic JSON Serialization for Tutus Blockchain
Tutus Ordered JSON is a Go library that provides deterministic JSON marshaling with preserved key ordering. In blockchain applications, deterministic serialization is critical for computing consistent hashes—the same data must always produce the same JSON output, byte-for-byte.
Standard Go encoding/json does not guarantee key ordering in marshaled output. This library ensures:
- Deterministic Output: Same input always produces identical JSON bytes
- Preserved Key Order: Object keys appear in the order they were added
- Hash Consistency: Critical for Merkle trees, signatures, and consensus
- API Compatibility: Drop-in replacement for standard
encoding/json
In blockchain systems, JSON is often used for:
| Use Case | Why Order Matters |
|---|---|
| Transaction Signing | Signature must cover exact bytes |
| Block Hashing | Hash must be reproducible across nodes |
| State Proofs | Merkle proofs require deterministic serialization |
| Smart Contract Parameters | ABI encoding must be consistent |
| API Responses | Caching and comparison require stability |
Without deterministic serialization, two nodes could produce different hashes for the same logical data, breaking consensus.
| Feature | Description |
|---|---|
| Preserved Key Order | Keys appear in insertion order |
| Deterministic Output | Byte-for-byte identical output |
| Standard API | Compatible with encoding/json interface |
| Unicode Support | Proper handling of Unicode strings |
| Number Handling | Preserves number precision |
| Streaming Support | Encoder/Decoder for streams |
go get github.com/tutus-one/tutus-ordered-jsonimport (
json "github.com/tutus-one/tutus-ordered-json"
)
// Marshal with preserved order
type Transaction struct {
From string `json:"from"`
To string `json:"to"`
Amount int64 `json:"amount"`
Nonce uint64 `json:"nonce"`
}
tx := Transaction{
From: "0x1234...",
To: "0x5678...",
Amount: 1000000,
Nonce: 42,
}
// Output is deterministic - keys in struct field order
data, err := json.Marshal(tx)
// {"from":"0x1234...","to":"0x5678...","amount":1000000,"nonce":42}
// Works with maps too (using OrderedMap)
om := json.NewOrderedMap()
om.Set("z", 1)
om.Set("a", 2)
om.Set("m", 3)
data, err = json.Marshal(om)
// {"z":1,"a":2,"m":3} - preserves insertion order// Marshal to JSON bytes
func Marshal(v interface{}) ([]byte, error)
// Marshal with indentation
func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error)
// Encoder for io.Writer
func NewEncoder(w io.Writer) *Encoder// Unmarshal from JSON bytes
func Unmarshal(data []byte, v interface{}) error
// Decoder for io.Reader
func NewDecoder(r io.Reader) *DecoderFor map types where key order matters:
// Create new ordered map
om := json.NewOrderedMap()
// Set preserves insertion order
om.Set("first", 1)
om.Set("second", 2)
om.Set("third", 3)
// Get retrieves value
value, exists := om.Get("first")
// Keys returns keys in insertion order
keys := om.Keys() // ["first", "second", "third"]
// Delete removes key
om.Delete("second")
// Marshal produces ordered JSON
data, _ := json.Marshal(om)
// {"first":1,"third":3}// Transaction hash must be deterministic
tx := Transaction{...}
data, _ := json.Marshal(tx)
hash := sha256.Sum256(data)
signature := Sign(privateKey, hash)// All nodes must compute same block hash
header := BlockHeader{
PrevHash: prevHash,
MerkleRoot: merkleRoot,
Timestamp: timestamp,
Height: height,
}
data, _ := json.Marshal(header)
blockHash := sha256.Sum256(data)// Contract parameters must be consistently encoded
params := json.NewOrderedMap()
params.Set("method", "transfer")
params.Set("args", []interface{}{to, amount})
data, _ := json.Marshal(params)| Feature | encoding/json |
tutus-ordered-json |
|---|---|---|
| Map key order | Random | Preserved |
| Deterministic | No | Yes |
| Performance | Faster | Slightly slower |
| Compatibility | Standard | API compatible |
The library adds minimal overhead for ordering preservation:
| Operation | Standard | Ordered | Overhead |
|---|---|---|---|
| Marshal struct | ~500ns | ~520ns | ~4% |
| Marshal map | ~800ns | ~850ns | ~6% |
| Unmarshal | ~600ns | ~600ns | 0% |
# Run all tests
go test ./...
# Run with verbose output
go test -v ./...
# Run benchmarks
go test -bench=. ./...| Project | Purpose |
|---|---|
| tutus-chain | Main blockchain implementation |
| tutus-consensus | dBFT consensus |
| tutus-bolt | Storage backend |
MIT License - see LICENSE
- MarketAlly LLC - Development and maintenance
- David H. Friedel Jr. - Lead Architect
Part of the Tutus Government Blockchain Platform