Skip to content

Commit 90d2a6d

Browse files
authored
feat(ledger): Added ToPlutusData() function to gov proposal related types (#1118)
Signed-off-by: Jenita <[email protected]>
1 parent 1aace8d commit 90d2a6d

File tree

2 files changed

+280
-1
lines changed

2 files changed

+280
-1
lines changed

ledger/common/gov.go

Lines changed: 114 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ package common
1616

1717
import (
1818
"fmt"
19+
"math/big"
1920

2021
"github.com/blinklabs-io/gouroboros/cbor"
2122
"github.com/blinklabs-io/plutigo/pkg/data"
@@ -108,12 +109,26 @@ type GovAnchor struct {
108109
DataHash [32]byte
109110
}
110111

112+
func (a *GovAnchor) ToPlutusData() data.PlutusData {
113+
return data.NewConstr(0,
114+
data.NewByteString([]byte(a.Url)),
115+
data.NewByteString(a.DataHash[:]),
116+
)
117+
}
118+
111119
type GovActionId struct {
112120
cbor.StructAsArray
113121
TransactionId [32]byte
114122
GovActionIdx uint32
115123
}
116124

125+
func (id *GovActionId) ToPlutusData() data.PlutusData {
126+
return data.NewConstr(0,
127+
data.NewByteString(id.TransactionId[:]),
128+
data.NewInteger(big.NewInt(int64(id.GovActionIdx))),
129+
)
130+
}
131+
117132
type ProposalProcedure struct {
118133
cbor.StructAsArray
119134
Deposit uint64
@@ -122,6 +137,14 @@ type ProposalProcedure struct {
122137
Anchor GovAnchor
123138
}
124139

140+
func (p *ProposalProcedure) ToPlutusData() data.PlutusData {
141+
return data.NewConstr(0,
142+
data.NewInteger(new(big.Int).SetUint64(p.Deposit)),
143+
p.RewardAccount.ToPlutusData(),
144+
p.GovAction.ToPlutusData(),
145+
)
146+
}
147+
125148
const (
126149
GovActionTypeParameterChange = 0
127150
GovActionTypeHardForkInitiation = 1
@@ -137,6 +160,10 @@ type GovActionWrapper struct {
137160
Action GovAction
138161
}
139162

163+
func (g *GovActionWrapper) ToPlutusData() data.PlutusData {
164+
return g.Action.ToPlutusData()
165+
}
166+
140167
func (g *GovActionWrapper) UnmarshalCBOR(data []byte) error {
141168
// Determine action type
142169
actionType, err := cbor.DecodeIdFromList(data)
@@ -178,6 +205,7 @@ func (g *GovActionWrapper) MarshalCBOR() ([]byte, error) {
178205

179206
type GovAction interface {
180207
isGovAction()
208+
ToPlutusData() data.PlutusData
181209
}
182210

183211
type ParameterChangeGovAction struct {
@@ -188,6 +216,14 @@ type ParameterChangeGovAction struct {
188216
PolicyHash []byte
189217
}
190218

219+
func (a *ParameterChangeGovAction) ToPlutusData() data.PlutusData {
220+
return data.NewConstr(0,
221+
a.ActionId.ToPlutusData(),
222+
data.NewByteString(a.ParamUpdate),
223+
data.NewByteString(a.PolicyHash),
224+
)
225+
}
226+
191227
func (a ParameterChangeGovAction) isGovAction() {}
192228

193229
type HardForkInitiationGovAction struct {
@@ -201,6 +237,16 @@ type HardForkInitiationGovAction struct {
201237
}
202238
}
203239

240+
func (a *HardForkInitiationGovAction) ToPlutusData() data.PlutusData {
241+
return data.NewConstr(1,
242+
a.ActionId.ToPlutusData(),
243+
data.NewConstr(0,
244+
data.NewInteger(new(big.Int).SetUint64(uint64(a.ProtocolVersion.Major))),
245+
data.NewInteger(new(big.Int).SetUint64(uint64(a.ProtocolVersion.Minor))),
246+
),
247+
)
248+
}
249+
204250
func (a HardForkInitiationGovAction) isGovAction() {}
205251

206252
type TreasuryWithdrawalGovAction struct {
@@ -210,6 +256,20 @@ type TreasuryWithdrawalGovAction struct {
210256
PolicyHash []byte
211257
}
212258

259+
func (a *TreasuryWithdrawalGovAction) ToPlutusData() data.PlutusData {
260+
pairs := make([][2]data.PlutusData, 0, len(a.Withdrawals))
261+
for addr, amount := range a.Withdrawals {
262+
pairs = append(pairs, [2]data.PlutusData{
263+
data.NewConstr(0, addr.ToPlutusData()),
264+
data.NewInteger(new(big.Int).SetUint64(amount)),
265+
})
266+
}
267+
return data.NewConstr(2,
268+
data.NewMap(pairs),
269+
data.NewByteString(a.PolicyHash),
270+
)
271+
}
272+
213273
func (a TreasuryWithdrawalGovAction) isGovAction() {}
214274

215275
type NoConfidenceGovAction struct {
@@ -218,6 +278,12 @@ type NoConfidenceGovAction struct {
218278
ActionId *GovActionId
219279
}
220280

281+
func (a *NoConfidenceGovAction) ToPlutusData() data.PlutusData {
282+
return data.NewConstr(3,
283+
a.ActionId.ToPlutusData(),
284+
)
285+
}
286+
221287
func (a NoConfidenceGovAction) isGovAction() {}
222288

223289
type UpdateCommitteeGovAction struct {
@@ -226,7 +292,40 @@ type UpdateCommitteeGovAction struct {
226292
ActionId *GovActionId
227293
Credentials []Credential
228294
CredEpochs map[*Credential]uint
229-
Unknown cbor.Rat
295+
Quorum cbor.Rat
296+
}
297+
298+
func (a *UpdateCommitteeGovAction) ToPlutusData() data.PlutusData {
299+
removedItems := make([]data.PlutusData, 0, len(a.Credentials))
300+
for _, cred := range a.Credentials {
301+
removedItems = append(removedItems, cred.ToPlutusData())
302+
}
303+
304+
addedPairs := make([][2]data.PlutusData, 0, len(a.CredEpochs))
305+
for cred, epoch := range a.CredEpochs {
306+
addedPairs = append(addedPairs, [2]data.PlutusData{
307+
cred.ToPlutusData(),
308+
data.NewInteger(new(big.Int).SetUint64(uint64(epoch))),
309+
})
310+
}
311+
312+
// Get numerator and denominator using Rat methods
313+
var num, den *big.Int
314+
if a.Quorum != (cbor.Rat{}) {
315+
num = a.Quorum.Num()
316+
den = a.Quorum.Denom()
317+
} else {
318+
num = big.NewInt(0)
319+
den = big.NewInt(1)
320+
}
321+
322+
return data.NewConstr(4,
323+
a.ActionId.ToPlutusData(),
324+
data.NewList(removedItems...),
325+
data.NewMap(addedPairs),
326+
data.NewInteger(num),
327+
data.NewInteger(den),
328+
)
230329
}
231330

232331
func (a UpdateCommitteeGovAction) isGovAction() {}
@@ -242,11 +341,25 @@ type NewConstitutionGovAction struct {
242341
}
243342
}
244343

344+
func (a *NewConstitutionGovAction) ToPlutusData() data.PlutusData {
345+
return data.NewConstr(5,
346+
a.ActionId.ToPlutusData(),
347+
data.NewConstr(0,
348+
a.Constitution.Anchor.ToPlutusData(),
349+
data.NewByteString(a.Constitution.ScriptHash),
350+
),
351+
)
352+
}
353+
245354
func (a NewConstitutionGovAction) isGovAction() {}
246355

247356
type InfoGovAction struct {
248357
cbor.StructAsArray
249358
Type uint
250359
}
251360

361+
func (a *InfoGovAction) ToPlutusData() data.PlutusData {
362+
return data.NewConstr(6)
363+
}
364+
252365
func (a InfoGovAction) isGovAction() {}

ledger/common/gov_test.go

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@ import (
1818
"reflect"
1919
"testing"
2020

21+
"github.com/blinklabs-io/gouroboros/cbor"
2122
"github.com/blinklabs-io/plutigo/pkg/data"
23+
"github.com/stretchr/testify/assert"
2224
)
2325

2426
// Ttests the ToPlutusData method for Voter types
@@ -177,3 +179,167 @@ func TestVotingProcedureToPlutusData(t *testing.T) {
177179
})
178180
}
179181
}
182+
183+
func TestProposalProcedureToPlutusData(t *testing.T) {
184+
addr := Address{}
185+
action := &InfoGovAction{}
186+
187+
pp := &ProposalProcedure{
188+
Deposit: 1000000,
189+
RewardAccount: addr,
190+
GovAction: GovActionWrapper{Action: action},
191+
}
192+
193+
pd := pp.ToPlutusData()
194+
constr, ok := pd.(*data.Constr)
195+
assert.True(t, ok)
196+
assert.Equal(t, uint(0), constr.Tag)
197+
assert.Len(t, constr.Fields, 3)
198+
}
199+
200+
func TestGovActionIdToPlutusData(t *testing.T) {
201+
txId := [32]byte{1, 2, 3, 4}
202+
govActionId := &GovActionId{
203+
TransactionId: txId,
204+
GovActionIdx: 42,
205+
}
206+
207+
pd := govActionId.ToPlutusData()
208+
constr, ok := pd.(*data.Constr)
209+
assert.True(t, ok)
210+
assert.Equal(t, uint(0), constr.Tag)
211+
assert.Len(t, constr.Fields, 2)
212+
}
213+
214+
func TestParameterChangeGovActionToPlutusData(t *testing.T) {
215+
action := &ParameterChangeGovAction{
216+
ActionId: &GovActionId{},
217+
ParamUpdate: []byte{1, 2, 3},
218+
PolicyHash: []byte{4, 5, 6},
219+
}
220+
221+
pd := action.ToPlutusData()
222+
constr, ok := pd.(*data.Constr)
223+
assert.True(t, ok)
224+
assert.Equal(t, uint(0), constr.Tag)
225+
assert.Len(t, constr.Fields, 3)
226+
}
227+
228+
func TestHardForkInitiationGovActionToPlutusData(t *testing.T) {
229+
action := &HardForkInitiationGovAction{
230+
ActionId: &GovActionId{},
231+
ProtocolVersion: struct {
232+
cbor.StructAsArray
233+
Major uint
234+
Minor uint
235+
}{
236+
Major: 8,
237+
Minor: 0,
238+
},
239+
}
240+
241+
pd := action.ToPlutusData()
242+
constr, ok := pd.(*data.Constr)
243+
assert.True(t, ok)
244+
assert.Equal(t, uint(1), constr.Tag)
245+
assert.Len(t, constr.Fields, 2)
246+
}
247+
248+
func TestTreasuryWithdrawalGovActionToPlutusData(t *testing.T) {
249+
addr := Address{}
250+
withdrawals := map[*Address]uint64{
251+
&addr: 5000000,
252+
}
253+
254+
action := &TreasuryWithdrawalGovAction{
255+
Withdrawals: withdrawals,
256+
PolicyHash: []byte{1, 2, 3},
257+
}
258+
259+
pd := action.ToPlutusData()
260+
constr, ok := pd.(*data.Constr)
261+
assert.True(t, ok)
262+
assert.Equal(t, uint(2), constr.Tag)
263+
assert.Len(t, constr.Fields, 2)
264+
}
265+
266+
func TestNoConfidenceGovActionToPlutusData(t *testing.T) {
267+
action := &NoConfidenceGovAction{
268+
ActionId: &GovActionId{},
269+
}
270+
271+
pd := action.ToPlutusData()
272+
constr, ok := pd.(*data.Constr)
273+
assert.True(t, ok)
274+
assert.Equal(t, uint(3), constr.Tag)
275+
assert.Len(t, constr.Fields, 1)
276+
}
277+
278+
func TestUpdateCommitteeGovActionToPlutusData(t *testing.T) {
279+
cred := Credential{
280+
CredType: CredentialTypeAddrKeyHash,
281+
Credential: NewBlake2b224([]byte("test")),
282+
}
283+
creds := []Credential{cred}
284+
credEpochs := map[*Credential]uint{
285+
&cred: 42,
286+
}
287+
288+
// Test with zero value Rat
289+
t.Run("ZeroValueRat", func(t *testing.T) {
290+
action := &UpdateCommitteeGovAction{
291+
ActionId: &GovActionId{},
292+
Credentials: creds,
293+
CredEpochs: credEpochs,
294+
Quorum: cbor.Rat{}, // Zero value
295+
}
296+
297+
pd := action.ToPlutusData()
298+
assert.NotNil(t, pd)
299+
300+
constr, ok := pd.(*data.Constr)
301+
assert.True(t, ok)
302+
assert.Equal(t, uint(4), constr.Tag)
303+
304+
// Verify default values were used
305+
num, ok := constr.Fields[3].(*data.Integer)
306+
assert.True(t, ok)
307+
assert.Equal(t, int64(0), num.Inner.Int64())
308+
309+
den, ok := constr.Fields[4].(*data.Integer)
310+
assert.True(t, ok)
311+
assert.Equal(t, int64(1), den.Inner.Int64())
312+
})
313+
314+
t.Run("NilCase", func(t *testing.T) {
315+
})
316+
}
317+
318+
func TestNewConstitutionGovActionToPlutusData(t *testing.T) {
319+
action := &NewConstitutionGovAction{
320+
ActionId: &GovActionId{},
321+
Constitution: struct {
322+
cbor.StructAsArray
323+
Anchor GovAnchor
324+
ScriptHash []byte
325+
}{
326+
ScriptHash: []byte{1, 2, 3},
327+
},
328+
}
329+
330+
pd := action.ToPlutusData()
331+
constr, ok := pd.(*data.Constr)
332+
assert.True(t, ok)
333+
assert.Equal(t, uint(5), constr.Tag)
334+
assert.Len(t, constr.Fields, 2)
335+
}
336+
337+
func TestInfoGovActionToPlutusData(t *testing.T) {
338+
action := &InfoGovAction{}
339+
340+
pd := action.ToPlutusData()
341+
constr, ok := pd.(*data.Constr)
342+
assert.True(t, ok)
343+
assert.Equal(t, uint(6), constr.Tag)
344+
assert.Len(t, constr.Fields, 0)
345+
}

0 commit comments

Comments
 (0)