Skip to content

Commit b767b9a

Browse files
committed
test(event): governance actions
Signed-off-by: Chris Gianelloni <wolf31o2@blinklabs.io>
1 parent 14ce1d9 commit b767b9a

File tree

1 file changed

+327
-0
lines changed

1 file changed

+327
-0
lines changed

event/governance_test.go

Lines changed: 327 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121

2222
"github.com/blinklabs-io/gouroboros/cbor"
2323
"github.com/blinklabs-io/gouroboros/ledger/common"
24+
"github.com/blinklabs-io/gouroboros/ledger/conway"
2425
"github.com/stretchr/testify/assert"
2526
)
2627

@@ -109,6 +110,332 @@ func TestExtractGovActionId(t *testing.T) {
109110
})
110111
}
111112

113+
func TestExtractTreasuryWithdrawalAction(t *testing.T) {
114+
t.Run("extracts withdrawals with multiple destinations", func(t *testing.T) {
115+
addr1 := common.Address{}
116+
addr2 := common.Address{}
117+
118+
action := &common.TreasuryWithdrawalGovAction{
119+
Type: 2,
120+
Withdrawals: map[*common.Address]uint64{
121+
&addr1: 1000000,
122+
&addr2: 2000000,
123+
},
124+
PolicyHash: []byte{0xab, 0xcd, 0xef},
125+
}
126+
127+
result := extractGovActionData(action)
128+
129+
assert.NotNil(t, result.TreasuryWithdrawal)
130+
assert.Len(t, result.TreasuryWithdrawal.Withdrawals, 2)
131+
assert.Equal(t, "abcdef", result.TreasuryWithdrawal.PolicyHash)
132+
133+
// Verify total amount matches (order may vary due to map iteration)
134+
var total uint64
135+
for _, w := range result.TreasuryWithdrawal.Withdrawals {
136+
total += w.Amount
137+
}
138+
assert.Equal(t, uint64(3000000), total)
139+
})
140+
141+
t.Run("extracts withdrawals without policy hash", func(t *testing.T) {
142+
addr := common.Address{}
143+
144+
action := &common.TreasuryWithdrawalGovAction{
145+
Type: 2,
146+
Withdrawals: map[*common.Address]uint64{
147+
&addr: 5000000,
148+
},
149+
}
150+
151+
result := extractGovActionData(action)
152+
153+
assert.NotNil(t, result.TreasuryWithdrawal)
154+
assert.Len(t, result.TreasuryWithdrawal.Withdrawals, 1)
155+
assert.Equal(t, "", result.TreasuryWithdrawal.PolicyHash)
156+
})
157+
}
158+
159+
func TestExtractUpdateCommitteeAction(t *testing.T) {
160+
t.Run("extracts committee members to add and remove", func(t *testing.T) {
161+
// Create credentials with proper Blake2b224 hashes
162+
var credHash1, credHash2, credHash3 common.Blake2b224
163+
copy(credHash1[:], []byte("credential1hash12345678"))
164+
copy(credHash2[:], []byte("credential2hash12345678"))
165+
copy(credHash3[:], []byte("credential3hash12345678"))
166+
167+
cred1 := common.Credential{
168+
CredType: common.CredentialTypeAddrKeyHash,
169+
Credential: credHash1,
170+
}
171+
cred2 := &common.Credential{
172+
CredType: common.CredentialTypeAddrKeyHash,
173+
Credential: credHash2,
174+
}
175+
cred3 := &common.Credential{
176+
CredType: common.CredentialTypeAddrKeyHash,
177+
Credential: credHash3,
178+
}
179+
180+
action := &common.UpdateCommitteeGovAction{
181+
Type: 4,
182+
Credentials: []common.Credential{
183+
cred1,
184+
},
185+
CredEpochs: map[*common.Credential]uint{
186+
cred2: 500,
187+
cred3: 600,
188+
},
189+
Quorum: cbor.Rat{Rat: big.NewRat(2, 3)},
190+
}
191+
192+
result := extractGovActionData(action)
193+
194+
assert.NotNil(t, result.UpdateCommittee)
195+
assert.Len(t, result.UpdateCommittee.MembersToRemove, 1)
196+
assert.Len(t, result.UpdateCommittee.MembersToAdd, 2)
197+
assert.Equal(t, uint64(2), result.UpdateCommittee.QuorumNumerator)
198+
assert.Equal(t, uint64(3), result.UpdateCommittee.QuorumDenominator)
199+
})
200+
201+
t.Run("extracts with previous action ID", func(t *testing.T) {
202+
txId := [32]byte{}
203+
copy(txId[:], []byte("committeeactiontxhash12345678"))
204+
205+
action := &common.UpdateCommitteeGovAction{
206+
Type: 4,
207+
ActionId: &common.GovActionId{
208+
TransactionId: txId,
209+
GovActionIdx: 3,
210+
},
211+
Quorum: cbor.Rat{Rat: big.NewRat(1, 2)},
212+
}
213+
214+
result := extractGovActionData(action)
215+
216+
assert.NotNil(t, result.UpdateCommittee)
217+
assert.NotNil(t, result.UpdateCommittee.PrevActionId)
218+
assert.Equal(t, hex.EncodeToString(txId[:]), result.UpdateCommittee.PrevActionId.TransactionId)
219+
assert.Equal(t, uint32(3), result.UpdateCommittee.PrevActionId.GovActionIdx)
220+
})
221+
}
222+
223+
func TestExtractNewConstitutionAction(t *testing.T) {
224+
t.Run("extracts constitution with anchor", func(t *testing.T) {
225+
dataHash := [32]byte{}
226+
copy(dataHash[:], []byte("constitutionhash123456789012"))
227+
228+
action := &common.NewConstitutionGovAction{
229+
Type: 5,
230+
Constitution: struct {
231+
cbor.StructAsArray
232+
Anchor common.GovAnchor
233+
ScriptHash []byte
234+
}{
235+
Anchor: common.GovAnchor{
236+
Url: "https://example.com/constitution.json",
237+
DataHash: dataHash,
238+
},
239+
},
240+
}
241+
242+
result := extractGovActionData(action)
243+
244+
assert.NotNil(t, result.NewConstitution)
245+
assert.Equal(t, "https://example.com/constitution.json", result.NewConstitution.Anchor.Url)
246+
assert.Equal(t, hex.EncodeToString(dataHash[:]), result.NewConstitution.Anchor.DataHash)
247+
assert.Equal(t, "", result.NewConstitution.ScriptHash)
248+
})
249+
250+
t.Run("extracts constitution with script hash", func(t *testing.T) {
251+
dataHash := [32]byte{}
252+
copy(dataHash[:], []byte("constitutionhash123456789012"))
253+
254+
action := &common.NewConstitutionGovAction{
255+
Type: 5,
256+
Constitution: struct {
257+
cbor.StructAsArray
258+
Anchor common.GovAnchor
259+
ScriptHash []byte
260+
}{
261+
Anchor: common.GovAnchor{
262+
Url: "https://example.com/constitution.json",
263+
DataHash: dataHash,
264+
},
265+
ScriptHash: []byte{0xde, 0xad, 0xbe, 0xef},
266+
},
267+
}
268+
269+
result := extractGovActionData(action)
270+
271+
assert.NotNil(t, result.NewConstitution)
272+
assert.Equal(t, "deadbeef", result.NewConstitution.ScriptHash)
273+
})
274+
275+
t.Run("extracts constitution with previous action ID", func(t *testing.T) {
276+
txId := [32]byte{}
277+
copy(txId[:], []byte("prevconstitutionactiontx12345"))
278+
dataHash := [32]byte{}
279+
280+
action := &common.NewConstitutionGovAction{
281+
Type: 5,
282+
ActionId: &common.GovActionId{
283+
TransactionId: txId,
284+
GovActionIdx: 7,
285+
},
286+
Constitution: struct {
287+
cbor.StructAsArray
288+
Anchor common.GovAnchor
289+
ScriptHash []byte
290+
}{
291+
Anchor: common.GovAnchor{
292+
Url: "https://example.com/new-constitution.json",
293+
DataHash: dataHash,
294+
},
295+
},
296+
}
297+
298+
result := extractGovActionData(action)
299+
300+
assert.NotNil(t, result.NewConstitution)
301+
assert.NotNil(t, result.NewConstitution.PrevActionId)
302+
assert.Equal(t, uint32(7), result.NewConstitution.PrevActionId.GovActionIdx)
303+
})
304+
}
305+
306+
func TestExtractParameterChangeAction(t *testing.T) {
307+
t.Run("extracts parameter change with basic params", func(t *testing.T) {
308+
minFeeA := uint(44)
309+
minFeeB := uint(155381)
310+
maxTxSize := uint(16384)
311+
312+
action := &conway.ConwayParameterChangeGovAction{
313+
Type: 0,
314+
ParamUpdate: conway.ConwayProtocolParameterUpdate{
315+
MinFeeA: &minFeeA,
316+
MinFeeB: &minFeeB,
317+
MaxTxSize: &maxTxSize,
318+
},
319+
PolicyHash: []byte{0xca, 0xfe, 0xba, 0xbe},
320+
}
321+
322+
result := extractGovActionData(action)
323+
324+
assert.NotNil(t, result.ParameterChange)
325+
assert.Equal(t, "cafebabe", result.ParameterChange.PolicyHash)
326+
assert.NotNil(t, result.ParameterChange.ParamUpdate)
327+
assert.NotNil(t, result.ParameterChange.ParamUpdate.MinFeeA)
328+
assert.Equal(t, uint(44), *result.ParameterChange.ParamUpdate.MinFeeA)
329+
assert.NotNil(t, result.ParameterChange.ParamUpdate.MinFeeB)
330+
assert.Equal(t, uint(155381), *result.ParameterChange.ParamUpdate.MinFeeB)
331+
assert.NotNil(t, result.ParameterChange.ParamUpdate.MaxTxSize)
332+
assert.Equal(t, uint(16384), *result.ParameterChange.ParamUpdate.MaxTxSize)
333+
})
334+
335+
t.Run("extracts parameter change with previous action ID", func(t *testing.T) {
336+
txId := [32]byte{}
337+
copy(txId[:], []byte("paramchangeactiontxhash12345"))
338+
minFeeA := uint(50)
339+
340+
action := &conway.ConwayParameterChangeGovAction{
341+
Type: 0,
342+
ActionId: &common.GovActionId{
343+
TransactionId: txId,
344+
GovActionIdx: 2,
345+
},
346+
ParamUpdate: conway.ConwayProtocolParameterUpdate{
347+
MinFeeA: &minFeeA,
348+
},
349+
}
350+
351+
result := extractGovActionData(action)
352+
353+
assert.NotNil(t, result.ParameterChange)
354+
assert.NotNil(t, result.ParameterChange.PrevActionId)
355+
assert.Equal(t, hex.EncodeToString(txId[:]), result.ParameterChange.PrevActionId.TransactionId)
356+
assert.Equal(t, uint32(2), result.ParameterChange.PrevActionId.GovActionIdx)
357+
})
358+
359+
t.Run("extracts parameter change with execution units", func(t *testing.T) {
360+
action := &conway.ConwayParameterChangeGovAction{
361+
Type: 0,
362+
ParamUpdate: conway.ConwayProtocolParameterUpdate{
363+
MaxTxExUnits: &common.ExUnits{
364+
Memory: 10000000,
365+
Steps: 10000000000,
366+
},
367+
MaxBlockExUnits: &common.ExUnits{
368+
Memory: 50000000,
369+
Steps: 40000000000,
370+
},
371+
},
372+
}
373+
374+
result := extractGovActionData(action)
375+
376+
assert.NotNil(t, result.ParameterChange)
377+
assert.NotNil(t, result.ParameterChange.ParamUpdate)
378+
assert.NotNil(t, result.ParameterChange.ParamUpdate.MaxTxExUnits)
379+
assert.Equal(t, int64(10000000), result.ParameterChange.ParamUpdate.MaxTxExUnits.Mem)
380+
assert.Equal(t, int64(10000000000), result.ParameterChange.ParamUpdate.MaxTxExUnits.Steps)
381+
assert.NotNil(t, result.ParameterChange.ParamUpdate.MaxBlockExUnits)
382+
assert.Equal(t, int64(50000000), result.ParameterChange.ParamUpdate.MaxBlockExUnits.Mem)
383+
assert.Equal(t, int64(40000000000), result.ParameterChange.ParamUpdate.MaxBlockExUnits.Steps)
384+
})
385+
386+
t.Run("extracts parameter change with rational values", func(t *testing.T) {
387+
action := &conway.ConwayParameterChangeGovAction{
388+
Type: 0,
389+
ParamUpdate: conway.ConwayProtocolParameterUpdate{
390+
A0: &cbor.Rat{Rat: big.NewRat(1, 10)}, // 0.1
391+
Rho: &cbor.Rat{Rat: big.NewRat(3, 1000)}, // 0.003
392+
Tau: &cbor.Rat{Rat: big.NewRat(2, 10)}, // 0.2
393+
},
394+
}
395+
396+
result := extractGovActionData(action)
397+
398+
assert.NotNil(t, result.ParameterChange)
399+
assert.NotNil(t, result.ParameterChange.ParamUpdate)
400+
assert.NotNil(t, result.ParameterChange.ParamUpdate.A0)
401+
assert.InDelta(t, 0.1, *result.ParameterChange.ParamUpdate.A0, 0.0001)
402+
assert.NotNil(t, result.ParameterChange.ParamUpdate.Rho)
403+
assert.InDelta(t, 0.003, *result.ParameterChange.ParamUpdate.Rho, 0.0001)
404+
assert.NotNil(t, result.ParameterChange.ParamUpdate.Tau)
405+
assert.InDelta(t, 0.2, *result.ParameterChange.ParamUpdate.Tau, 0.0001)
406+
})
407+
408+
t.Run("extracts parameter change with governance parameters", func(t *testing.T) {
409+
minCommitteeSize := uint(5)
410+
committeeTermLimit := uint64(146)
411+
govActionDeposit := uint64(100000000000)
412+
drepDeposit := uint64(500000000)
413+
414+
action := &conway.ConwayParameterChangeGovAction{
415+
Type: 0,
416+
ParamUpdate: conway.ConwayProtocolParameterUpdate{
417+
MinCommitteeSize: &minCommitteeSize,
418+
CommitteeTermLimit: &committeeTermLimit,
419+
GovActionDeposit: &govActionDeposit,
420+
DRepDeposit: &drepDeposit,
421+
},
422+
}
423+
424+
result := extractGovActionData(action)
425+
426+
assert.NotNil(t, result.ParameterChange)
427+
assert.NotNil(t, result.ParameterChange.ParamUpdate)
428+
assert.NotNil(t, result.ParameterChange.ParamUpdate.MinCommitteeSize)
429+
assert.Equal(t, uint(5), *result.ParameterChange.ParamUpdate.MinCommitteeSize)
430+
assert.NotNil(t, result.ParameterChange.ParamUpdate.CommitteeTermLimit)
431+
assert.Equal(t, uint64(146), *result.ParameterChange.ParamUpdate.CommitteeTermLimit)
432+
assert.NotNil(t, result.ParameterChange.ParamUpdate.GovActionDeposit)
433+
assert.Equal(t, uint64(100000000000), *result.ParameterChange.ParamUpdate.GovActionDeposit)
434+
assert.NotNil(t, result.ParameterChange.ParamUpdate.DRepDeposit)
435+
assert.Equal(t, uint64(500000000), *result.ParameterChange.ParamUpdate.DRepDeposit)
436+
})
437+
}
438+
112439
func TestRationalToFloat(t *testing.T) {
113440
t.Run("converts rational to float", func(t *testing.T) {
114441
// 1/2 = 0.5

0 commit comments

Comments
 (0)