Skip to content

Commit 216713a

Browse files
committed
feat: Shelley era 'Utxo' validation rules
This implements the remainder of the Shelley era "Utxo" validation rules, as well as tests for each. It also includes the following changes to support the validation rules: * expose address network ID, type, and Byron attributes * add helpers for ShelleyTransactionInputSet to make use in tests easier * change UtxoState interface to lookup a single UTxO at a time * add NetworkId() to LedgerState interface * add String() to TransactionInput interface Fixes #875 Signed-off-by: Aurora Gaffney <[email protected]>
1 parent 2876b3c commit 216713a

File tree

7 files changed

+1068
-5
lines changed

7 files changed

+1068
-5
lines changed

ledger/common/address.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,26 @@ func (a *Address) MarshalCBOR() ([]byte, error) {
276276
return cbor.Encode(addrBytes)
277277
}
278278

279+
func (a Address) NetworkId() uint {
280+
if a.addressType == AddressTypeByron {
281+
// TODO
282+
if a.byronAddressAttr.Network == nil {
283+
return AddressNetworkMainnet
284+
}
285+
return uint(*a.byronAddressAttr.Network)
286+
} else {
287+
return uint(a.networkId)
288+
}
289+
}
290+
291+
func (a Address) Type() uint8 {
292+
return a.addressType
293+
}
294+
295+
func (a Address) ByronType() uint64 {
296+
return a.byronAddressType
297+
}
298+
279299
// PaymentAddress returns a new Address with only the payment address portion. This will return nil for anything other than payment and script addresses
280300
func (a Address) PaymentAddress() *Address {
281301
var addrType uint8
@@ -337,6 +357,10 @@ func (a *Address) StakeKeyHash() Blake2b224 {
337357
return Blake2b224(a.stakingAddress[:])
338358
}
339359

360+
func (a *Address) ByronAttr() ByronAddressAttributes {
361+
return a.byronAddressAttr
362+
}
363+
340364
func (a Address) generateHRP() string {
341365
var ret string
342366
if a.addressType == AddressTypeNoneKey ||

ledger/common/state.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import (
2020

2121
// UtxoState defines the interface for querying the UTxO state
2222
type UtxoState interface {
23-
UtxosById([]TransactionInput) ([]Utxo, error)
23+
UtxoById(TransactionInput) (Utxo, error)
2424
}
2525

2626
// CertState defines the interface for querying the certificate state
@@ -30,6 +30,7 @@ type CertState interface{}
3030
type LedgerState interface {
3131
UtxoState
3232
CertState
33+
NetworkId() uint
3334
}
3435

3536
// TipState defines the interface for querying the current tip

ledger/common/tx.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ type TransactionBody interface {
5858
type TransactionInput interface {
5959
Id() Blake2b256
6060
Index() uint32
61+
String() string
6162
Utxorpc() *utxorpc.TxInput
6263
}
6364

ledger/shelley/errors.go

Lines changed: 128 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,12 @@
1414

1515
package shelley
1616

17-
import "fmt"
17+
import (
18+
"fmt"
19+
"strings"
20+
21+
"github.com/blinklabs-io/gouroboros/ledger/common"
22+
)
1823

1924
type ExpiredUtxoError struct {
2025
Ttl uint64
@@ -28,3 +33,125 @@ func (e ExpiredUtxoError) Error() string {
2833
e.Slot,
2934
)
3035
}
36+
37+
type InputSetEmptyUtxoError struct{}
38+
39+
func (InputSetEmptyUtxoError) Error() string {
40+
return "input set empty"
41+
}
42+
43+
type FeeTooSmallUtxoError struct {
44+
Provided uint64
45+
Min uint64
46+
}
47+
48+
func (e FeeTooSmallUtxoError) Error() string {
49+
return fmt.Sprintf(
50+
"fee too small: provided %d, minimum %d",
51+
e.Provided,
52+
e.Min,
53+
)
54+
}
55+
56+
type BadInputsUtxoError struct {
57+
Inputs []common.TransactionInput
58+
}
59+
60+
func (e BadInputsUtxoError) Error() string {
61+
tmpInputs := make([]string, 0, len(e.Inputs))
62+
for idx, tmpInput := range e.Inputs {
63+
tmpInputs[idx] = tmpInput.String()
64+
}
65+
return fmt.Sprintf(
66+
"bad input(s): %s",
67+
strings.Join(tmpInputs, ", "),
68+
)
69+
}
70+
71+
type WrongNetworkError struct {
72+
NetId uint
73+
Addrs []common.Address
74+
}
75+
76+
func (e WrongNetworkError) Error() string {
77+
tmpAddrs := make([]string, 0, len(e.Addrs))
78+
for idx, tmpAddr := range e.Addrs {
79+
tmpAddrs[idx] = tmpAddr.String()
80+
}
81+
return fmt.Sprintf(
82+
"wrong network: %s",
83+
strings.Join(tmpAddrs, ", "),
84+
)
85+
}
86+
87+
type WrongNetworkWithdrawalError struct {
88+
NetId uint
89+
Addrs []common.Address
90+
}
91+
92+
func (e WrongNetworkWithdrawalError) Error() string {
93+
tmpAddrs := make([]string, 0, len(e.Addrs))
94+
for idx, tmpAddr := range e.Addrs {
95+
tmpAddrs[idx] = tmpAddr.String()
96+
}
97+
return fmt.Sprintf(
98+
"wrong network withdrawals: %s",
99+
strings.Join(tmpAddrs, ", "),
100+
)
101+
}
102+
103+
type ValueNotConservedUtxoError struct {
104+
Consumed uint64
105+
Produced uint64
106+
}
107+
108+
func (e ValueNotConservedUtxoError) Error() string {
109+
return fmt.Sprintf(
110+
"value not conserved: consumed %d, produced %d",
111+
e.Consumed,
112+
e.Produced,
113+
)
114+
}
115+
116+
type OutputTooSmallUtxoError struct {
117+
Outputs []common.TransactionOutput
118+
}
119+
120+
func (e OutputTooSmallUtxoError) Error() string {
121+
tmpOutputs := make([]string, 0, len(e.Outputs))
122+
for idx, tmpOutput := range e.Outputs {
123+
tmpOutputs[idx] = fmt.Sprintf("%#v", tmpOutput)
124+
}
125+
return fmt.Sprintf(
126+
"output too small: %s",
127+
strings.Join(tmpOutputs, ", "),
128+
)
129+
}
130+
131+
type OutputBootAddrAttrsTooBigError struct {
132+
Outputs []common.TransactionOutput
133+
}
134+
135+
func (e OutputBootAddrAttrsTooBigError) Error() string {
136+
tmpOutputs := make([]string, 0, len(e.Outputs))
137+
for idx, tmpOutput := range e.Outputs {
138+
tmpOutputs[idx] = fmt.Sprintf("%#v", tmpOutput)
139+
}
140+
return fmt.Sprintf(
141+
"output bootstrap address attributes too big: %s",
142+
strings.Join(tmpOutputs, ", "),
143+
)
144+
}
145+
146+
type MaxTxSizeUtxoError struct {
147+
TxSize uint
148+
MaxTxSize uint
149+
}
150+
151+
func (e MaxTxSizeUtxoError) Error() string {
152+
return fmt.Sprintf(
153+
"transaction size too large: size %d, max %d",
154+
e.TxSize,
155+
e.MaxTxSize,
156+
)
157+
}

0 commit comments

Comments
 (0)