Skip to content

Commit

Permalink
Merge pull request #292 from blinklabs-io/feat/ledger-multi-asset
Browse files Browse the repository at this point in the history
feat: better handling of Mary MultiAsset value
  • Loading branch information
agaffney authored Jun 4, 2023
2 parents 8095cee + e96fff1 commit 8d547f9
Show file tree
Hide file tree
Showing 8 changed files with 87 additions and 14 deletions.
14 changes: 13 additions & 1 deletion cmd/block-fetch/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,19 @@ func main() {
for _, output := range tx.Outputs() {
fmt.Printf(" Address: %x\n", output.Address())
fmt.Printf(" Amount: %d\n", output.Amount())
fmt.Printf(" Assets: %#v\n", output.Assets())
assets := output.Assets()
if assets != nil {
fmt.Printf(" Assets:\n")
for _, policyId := range assets.Policies() {
fmt.Printf(" Policy Id: %s\n", policyId)
fmt.Printf(" Policy assets:\n")
for _, assetName := range assets.Assets(policyId) {
fmt.Printf(" Asset name: %s\n", assetName)
fmt.Printf(" Amount: %d\n", assets.Asset(policyId, assetName))
fmt.Println("")
}
}
}
fmt.Println("")
}
}
Expand Down
2 changes: 1 addition & 1 deletion ledger/alonzo.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ func (o AlonzoTransactionOutput) Amount() uint64 {
return o.OutputAmount.Amount
}

func (o AlonzoTransactionOutput) Assets() interface{} {
func (o AlonzoTransactionOutput) Assets() *MultiAsset[uint64] {
return o.OutputAmount.Assets
}

Expand Down
2 changes: 1 addition & 1 deletion ledger/babbage.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ func (o BabbageTransactionOutput) Amount() uint64 {
return o.OutputAmount.Amount
}

func (o BabbageTransactionOutput) Assets() interface{} {
func (o BabbageTransactionOutput) Assets() *MultiAsset[uint64] {
return o.OutputAmount.Assets
}

Expand Down
62 changes: 62 additions & 0 deletions ledger/common.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// Copyright 2023 Blink Labs, LLC.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package ledger

import (
"github.com/blinklabs-io/gouroboros/cbor"
)

// MultiAsset represents a collection of policies, assets, and quantities. It's used for
// TX outputs (uint64) and TX asset minting (int64 to allow for negative values for burning)
type MultiAsset[T int64 | uint64] struct {
data map[Blake2b224]map[cbor.ByteString]T
}

func (m *MultiAsset[T]) UnmarshalCBOR(data []byte) error {
_, err := cbor.Decode(data, &(m.data))
return err
}

func (m *MultiAsset[T]) MarshalCBOR() ([]byte, error) {
return cbor.Encode(&(m.data))
}

func (m *MultiAsset[T]) Policies() []Blake2b224 {
var ret []Blake2b224
for policyId := range m.data {
ret = append(ret, policyId)
}
return ret
}

func (m *MultiAsset[T]) Assets(policyId Blake2b224) [][]byte {
assets, ok := m.data[policyId]
if !ok {
return nil
}
var ret [][]byte
for assetName := range assets {
ret = append(ret, assetName.Bytes())
}
return ret
}

func (m *MultiAsset[T]) Asset(policyId Blake2b224, assetName []byte) T {
policy, ok := m.data[policyId]
if !ok {
return 0
}
return policy[cbor.ByteString(assetName)]
}
8 changes: 4 additions & 4 deletions ledger/mary.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,7 @@ func (h *MaryBlockHeader) Era() Era {
type MaryTransactionBody struct {
AllegraTransactionBody
TxOutputs []MaryTransactionOutput `cbor:"1,keyasint,omitempty"`
// TODO: further parsing of this field
Mint cbor.Value `cbor:"9,keyasint,omitempty"`
Mint MultiAsset[int64] `cbor:"9,keyasint,omitempty"`
}

func (b *MaryTransactionBody) UnmarshalCBOR(cborData []byte) error {
Expand Down Expand Up @@ -117,14 +116,15 @@ func (o MaryTransactionOutput) Amount() uint64 {
return o.OutputAmount.Amount
}

func (o MaryTransactionOutput) Assets() interface{} {
func (o MaryTransactionOutput) Assets() *MultiAsset[uint64] {
return o.OutputAmount.Assets
}

type MaryTransactionOutputValue struct {
cbor.StructAsArray
Amount uint64
Assets map[Blake2b224]map[cbor.ByteString]uint64
// We use a pointer here to allow it to be nil
Assets *MultiAsset[uint64]
}

func (v *MaryTransactionOutputValue) UnmarshalCBOR(data []byte) error {
Expand Down
8 changes: 4 additions & 4 deletions ledger/mary_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,15 @@ import (
"github.com/blinklabs-io/gouroboros/internal/test"
)

func createMaryTransactionOutputValueAssets(policyId []byte, assetName []byte, amount uint64) map[Blake2b224]map[cbor.ByteString]uint64 {
ret := map[Blake2b224]map[cbor.ByteString]uint64{}
func createMaryTransactionOutputValueAssets(policyId []byte, assetName []byte, amount uint64) *MultiAsset[uint64] {
data := map[Blake2b224]map[cbor.ByteString]uint64{}
policyIdKey := Blake2b224{}
copy(policyIdKey[:], policyId)
assetKey := cbor.ByteString(assetName)
ret[policyIdKey] = map[cbor.ByteString]uint64{
data[policyIdKey] = map[cbor.ByteString]uint64{
assetKey: amount,
}
return ret
return &MultiAsset[uint64]{data: data}
}

func TestMaryTransactionOutputValueEncodeDecode(t *testing.T) {
Expand Down
2 changes: 1 addition & 1 deletion ledger/shelley.go
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ func (o ShelleyTransactionOutput) Amount() uint64 {
return o.OutputAmount
}

func (o ShelleyTransactionOutput) Assets() interface{} {
func (o ShelleyTransactionOutput) Assets() *MultiAsset[uint64] {
return nil
}

Expand Down
3 changes: 1 addition & 2 deletions ledger/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,7 @@ type TransactionInput interface {
type TransactionOutput interface {
Address() []byte
Amount() uint64
// TODO: create more specific type/interface for assets
Assets() interface{}
Assets() *MultiAsset[uint64]
}

func NewTransactionFromCbor(txType uint, data []byte) (interface{}, error) {
Expand Down

0 comments on commit 8d547f9

Please sign in to comment.