Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 14 additions & 9 deletions fsm/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,9 @@ type genesisState struct {
Supply *Supply `json:"supply"`
OrderBooks *lib.OrderBooks `protobuf:"bytes,7,opt,name=order_books,json=orderBooks,proto3" json:"orderBooks,omitempty"`
DoubleSigners []*lib.DoubleSigner `protobuf:"bytes,6,rep,name=double_signers,json=doubleSigners,proto3" json:"doubleSigners,omitempty"` // only used for export
// RetiredCommittees must be serialized so that retired (non-subsidized) committees survive a
// genesis export/import round trip; otherwise they silently become live again on restart.
RetiredCommittees []uint64 `json:"retiredCommittees,omitempty"`
}

// MarshalJSON() is the json.Marshaller implementation for the GenesisState object
Expand All @@ -240,15 +243,16 @@ func (x *GenesisState) MarshalJSON() ([]byte, error) {
t = time.UnixMicro(int64(x.Time)).Format(time.DateTime)
}
return json.Marshal(genesisState{
Time: t,
Pools: x.Pools,
Accounts: x.Accounts,
NonSigners: x.NonSigners,
Validators: x.Validators,
Params: x.Params,
Supply: x.Supply,
OrderBooks: x.OrderBooks,
DoubleSigners: x.DoubleSigners,
Time: t,
Pools: x.Pools,
Accounts: x.Accounts,
NonSigners: x.NonSigners,
Validators: x.Validators,
Params: x.Params,
Supply: x.Supply,
OrderBooks: x.OrderBooks,
DoubleSigners: x.DoubleSigners,
RetiredCommittees: x.RetiredCommittees,
})
}

Expand All @@ -268,5 +272,6 @@ func (x *GenesisState) UnmarshalJSON(bz []byte) (err error) {
x.Params, x.Pools, x.Supply = ptr.Params, ptr.Pools, ptr.Supply
x.Accounts, x.Validators, x.NonSigners = ptr.Accounts, ptr.Validators, ptr.NonSigners
x.OrderBooks, x.DoubleSigners = ptr.OrderBooks, ptr.DoubleSigners
x.RetiredCommittees = ptr.RetiredCommittees
return
}
21 changes: 21 additions & 0 deletions fsm/genesis_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -816,3 +816,24 @@ func validateWithExportedState(t *testing.T, sm StateMachine, expected *GenesisS
// compare got vs expected
require.EqualExportedValues(t, expected, got, fmt.Sprintf("EXPECTED:\n%s\nGOT:\n%s", expectedJson, gotJson))
}

// TestGenesisJSONRoundTripPreservesRetiredCommittees ensures that retired committees survive a
// GenesisState -> JSON -> GenesisState round trip. Retired committees are non-subsidized "for
// eternity"; if the JSON codec drops them, an export/import upgrade silently makes them live
// again and they resume receiving minted rewards.
func TestGenesisJSONRoundTripPreservesRetiredCommittees(t *testing.T) {
// a genesis state carrying two retired committees
expected := &GenesisState{
Params: DefaultParams(),
RetiredCommittees: []uint64{7, 21},
}
// marshal to JSON via the custom GenesisState codec
bz, err := json.Marshal(expected)
require.NoError(t, err)
// unmarshal back into a fresh GenesisState
got := new(GenesisState)
require.NoError(t, json.Unmarshal(bz, got))
// the retired committees must survive the round trip
require.Equal(t, expected.RetiredCommittees, got.RetiredCommittees,
"retired committees must survive a genesis export/import round trip; json=%s", string(bz))
}