diff --git a/packages/binary/address/address.go b/packages/binary/address/address.go new file mode 100644 index 0000000000000000000000000000000000000000..41a03b74541434f3db9ae4b0b6374125f4a277dc --- /dev/null +++ b/packages/binary/address/address.go @@ -0,0 +1,52 @@ +package address + +import ( + "crypto/rand" + + "github.com/mr-tron/base58" +) + +type Address [Length]byte + +func New(addressBytes []byte) (result Address) { + copy(result[:], addressBytes) + + return +} + +func FromBase58EncodedString(base58EncodedString string) (result Address) { + if addressBytes, err := base58.Decode(base58EncodedString); err != nil { + panic(err) + } else { + copy(result[:], addressBytes) + } + + return +} + +func Random() (result Address) { + addressBytes := make([]byte, Length) + if _, err := rand.Read(addressBytes); err != nil { + panic(err) + } + + return New(addressBytes) +} + +func (address *Address) UnmarshalBinary(data []byte) error { + copy(address[:], data[:Length]) + + return nil +} + +func (address *Address) MarshalBinary() (bytes []byte, err error) { + bytes = append(bytes, address[:]...) + + return +} + +func (address Address) String() string { + return base58.Encode(address[:]) +} + +const Length = 32 diff --git a/packages/binary/approvers/approvers.go b/packages/binary/tangle/approvers/approvers.go similarity index 100% rename from packages/binary/approvers/approvers.go rename to packages/binary/tangle/approvers/approvers.go diff --git a/packages/binary/approvers/types.go b/packages/binary/tangle/approvers/types.go similarity index 100% rename from packages/binary/approvers/types.go rename to packages/binary/tangle/approvers/types.go diff --git a/packages/binary/tangle/tangle.go b/packages/binary/tangle/tangle.go index 1b4bbd418e59964fea96e3012cb38d1ca92400d0..5197c2eb9d18697f8af7be141ab91decc5955734 100644 --- a/packages/binary/tangle/tangle.go +++ b/packages/binary/tangle/tangle.go @@ -1,7 +1,7 @@ package tangle import ( - "github.com/iotaledger/goshimmer/packages/binary/approvers" + "github.com/iotaledger/goshimmer/packages/binary/tangle/approvers" "github.com/iotaledger/goshimmer/packages/binary/transaction" "github.com/iotaledger/hive.go/objectstorage" ) diff --git a/packages/binary/transaction/data_payload.go b/packages/binary/transaction/data_payload.go deleted file mode 100644 index 4b0de177444ea8ddb6344465383203938f520b80..0000000000000000000000000000000000000000 --- a/packages/binary/transaction/data_payload.go +++ /dev/null @@ -1,48 +0,0 @@ -package transaction - -type DataPayload struct { - payloadType PayloadType - data []byte -} - -var DataPayloadType = PayloadType(0) - -func NewDataPayload(data []byte) *DataPayload { - return &DataPayload{ - payloadType: DataPayloadType, - data: data, - } -} - -func (dataPayload *DataPayload) GetType() PayloadType { - return dataPayload.payloadType -} - -func (dataPayload *DataPayload) GetData() []byte { - return dataPayload.data -} - -func (dataPayload *DataPayload) UnmarshalBinary(data []byte) error { - dataPayload.data = make([]byte, len(data)) - copy(dataPayload.data, data) - - return nil -} - -func (dataPayload *DataPayload) MarshalBinary() (data []byte, err error) { - data = make([]byte, len(dataPayload.data)) - copy(data, dataPayload.data) - - return -} - -func createGenericDataPayloadUnmarshaler(payloadType PayloadType) PayloadUnmarshaler { - return func(data []byte) (payload Payload, err error) { - payload = &DataPayload{ - payloadType: payloadType, - } - err = payload.UnmarshalBinary(data) - - return - } -} diff --git a/packages/binary/transaction/id.go b/packages/binary/transaction/id.go index be29a8b8c95e09ad30ed5e0a1f5704ef5cba8dd6..c940bf23ebd2e58e1175731b401b5a0749b1cdca 100644 --- a/packages/binary/transaction/id.go +++ b/packages/binary/transaction/id.go @@ -1,5 +1,7 @@ package transaction -type Id [transactionIdLength]byte +type Id [IdLength]byte -const transactionIdLength = 64 +var EmptyId = Id{} + +const IdLength = 64 diff --git a/packages/binary/transaction/init.go b/packages/binary/transaction/init.go new file mode 100644 index 0000000000000000000000000000000000000000..36b74b8e37d45f8ecf3e1c3bdb0aedbabc84ed7e --- /dev/null +++ b/packages/binary/transaction/init.go @@ -0,0 +1,10 @@ +package transaction + +import ( + "github.com/iotaledger/goshimmer/packages/binary/transaction/payload" + "github.com/iotaledger/goshimmer/packages/binary/transaction/payload/data" +) + +func init() { + payload.SetGenericUnmarshalerFactory(data.GenericPayloadUnmarshalerFactory) +} diff --git a/packages/binary/transaction/payload/data/data.go b/packages/binary/transaction/payload/data/data.go new file mode 100644 index 0000000000000000000000000000000000000000..a701c64122db7d40db2dcf12d2cca9e6057a2708 --- /dev/null +++ b/packages/binary/transaction/payload/data/data.go @@ -0,0 +1,52 @@ +package data + +import ( + "github.com/iotaledger/goshimmer/packages/binary/transaction/payload" +) + +type Data struct { + payloadType payload.Type + data []byte +} + +var Type = payload.Type(0) + +func New(data []byte) *Data { + return &Data{ + payloadType: Type, + data: data, + } +} + +func (dataPayload *Data) GetType() payload.Type { + return dataPayload.payloadType +} + +func (dataPayload *Data) GetData() []byte { + return dataPayload.data +} + +func (dataPayload *Data) UnmarshalBinary(data []byte) error { + dataPayload.data = make([]byte, len(data)) + copy(dataPayload.data, data) + + return nil +} + +func (dataPayload *Data) MarshalBinary() (data []byte, err error) { + data = make([]byte, len(dataPayload.data)) + copy(data, dataPayload.data) + + return +} + +func GenericPayloadUnmarshalerFactory(payloadType payload.Type) payload.Unmarshaler { + return func(data []byte) (payload payload.Payload, err error) { + payload = &Data{ + payloadType: payloadType, + } + err = payload.UnmarshalBinary(data) + + return + } +} diff --git a/packages/binary/transaction/payload/data/init.go b/packages/binary/transaction/payload/data/init.go new file mode 100644 index 0000000000000000000000000000000000000000..4f403d296bbb000478b6605b57cda20124e23807 --- /dev/null +++ b/packages/binary/transaction/payload/data/init.go @@ -0,0 +1,9 @@ +package data + +import ( + "github.com/iotaledger/goshimmer/packages/binary/transaction/payload" +) + +func init() { + payload.RegisterType(Type, GenericPayloadUnmarshalerFactory(Type)) +} diff --git a/packages/binary/transaction/payload/id.go b/packages/binary/transaction/payload/id.go new file mode 100644 index 0000000000000000000000000000000000000000..a20ce75f2b069a4299bf70a633deafd1c41c2f93 --- /dev/null +++ b/packages/binary/transaction/payload/id.go @@ -0,0 +1,5 @@ +package payload + +type Id [IdLength]byte + +const IdLength = 64 diff --git a/packages/binary/transaction/payload.go b/packages/binary/transaction/payload/payload.go similarity index 71% rename from packages/binary/transaction/payload.go rename to packages/binary/transaction/payload/payload.go index be68f2d9487e626f4b6deeacd5357e96a4a032a0..23ff09be788c7dc242b3fd640813e43641a72f76 100644 --- a/packages/binary/transaction/payload.go +++ b/packages/binary/transaction/payload/payload.go @@ -1,4 +1,4 @@ -package transaction +package payload import ( "encoding" @@ -8,5 +8,5 @@ type Payload interface { encoding.BinaryMarshaler encoding.BinaryUnmarshaler - GetType() PayloadType + GetType() Type } diff --git a/packages/binary/transaction/payload/type.go b/packages/binary/transaction/payload/type.go new file mode 100644 index 0000000000000000000000000000000000000000..a1594aa40bd8d8cfe3bd7d7533304b3c778f182b --- /dev/null +++ b/packages/binary/transaction/payload/type.go @@ -0,0 +1,3 @@ +package payload + +type Type = uint32 diff --git a/packages/binary/transaction/payload/type_register.go b/packages/binary/transaction/payload/type_register.go new file mode 100644 index 0000000000000000000000000000000000000000..aac9a9195eae5282e9514790cff2a957e01bafb1 --- /dev/null +++ b/packages/binary/transaction/payload/type_register.go @@ -0,0 +1,36 @@ +package payload + +import ( + "sync" +) + +type Unmarshaler func(data []byte) (Payload, error) + +var ( + typeRegister = make(map[Type]Unmarshaler) + typeRegisterMutex sync.RWMutex + genericUnmarshalerFactory func(payloadType Type) Unmarshaler +) + +func RegisterType(payloadType Type, unmarshaler Unmarshaler) { + typeRegisterMutex.Lock() + typeRegister[payloadType] = unmarshaler + typeRegisterMutex.Unlock() +} + +func GetUnmarshaler(payloadType Type) Unmarshaler { + typeRegisterMutex.RLock() + if unmarshaler, exists := typeRegister[payloadType]; exists { + typeRegisterMutex.RUnlock() + + return unmarshaler + } else { + typeRegisterMutex.RUnlock() + + return genericUnmarshalerFactory(payloadType) + } +} + +func SetGenericUnmarshalerFactory(unmarshalerFactory func(payloadType Type) Unmarshaler) { + genericUnmarshalerFactory = unmarshalerFactory +} diff --git a/packages/binary/transaction/payload/valuetransfer/value.go b/packages/binary/transaction/payload/valuetransfer/value.go new file mode 100644 index 0000000000000000000000000000000000000000..4f395d1d169aad94a283453676e59cb81f5cf1a8 --- /dev/null +++ b/packages/binary/transaction/payload/valuetransfer/value.go @@ -0,0 +1,31 @@ +package valuetransfer + +import ( + "github.com/iotaledger/goshimmer/packages/binary/address" + "github.com/iotaledger/goshimmer/packages/binary/transaction" + "github.com/iotaledger/goshimmer/packages/binary/transaction/payload" +) + +type ValueTransfer struct{} + +var Type = payload.Type(1) + +func New() *ValueTransfer { + return &ValueTransfer{} +} + +func (valueTransfer *ValueTransfer) AddInput(transaction transaction.Id, address address.Address) *ValueTransfer { + return valueTransfer +} + +func (valueTransfer *ValueTransfer) GetType() payload.Type { + return Type +} + +func (valueTransfer *ValueTransfer) MarshalBinary() (bytes []byte, err error) { + return +} + +func (valueTransfer *ValueTransfer) UnmarshalBinary(bytes []byte) (err error) { + return +} diff --git a/packages/binary/transaction/payload_id.go b/packages/binary/transaction/payload_id.go deleted file mode 100644 index ca8edef87c597ee853b9fcb1d304dd94d2c28777..0000000000000000000000000000000000000000 --- a/packages/binary/transaction/payload_id.go +++ /dev/null @@ -1,5 +0,0 @@ -package transaction - -type PayloadId [payloadIdLength]byte - -const payloadIdLength = 64 diff --git a/packages/binary/transaction/payload_type.go b/packages/binary/transaction/payload_type.go deleted file mode 100644 index 23d4ca12ad28a451d6dd7b1ef0a802a606b88da1..0000000000000000000000000000000000000000 --- a/packages/binary/transaction/payload_type.go +++ /dev/null @@ -1,3 +0,0 @@ -package transaction - -type PayloadType = uint32 diff --git a/packages/binary/transaction/payload_type_register.go b/packages/binary/transaction/payload_type_register.go deleted file mode 100644 index 5dcb24ab5565c5514db820f6451328e2bc194e68..0000000000000000000000000000000000000000 --- a/packages/binary/transaction/payload_type_register.go +++ /dev/null @@ -1,31 +0,0 @@ -package transaction - -import ( - "sync" -) - -type PayloadUnmarshaler func(data []byte) (Payload, error) - -var ( - payloadTypeRegister map[PayloadType]PayloadUnmarshaler - payloadTypeRegisterMutex sync.RWMutex -) - -func RegisterPayloadType(payloadType PayloadType, unmarshaler PayloadUnmarshaler) { - payloadTypeRegisterMutex.Lock() - payloadTypeRegister[payloadType] = unmarshaler - payloadTypeRegisterMutex.Unlock() -} - -func GetPayloadUnmarshaler(payloadType PayloadType) PayloadUnmarshaler { - payloadTypeRegisterMutex.RLock() - if unmarshaler, exists := payloadTypeRegister[payloadType]; exists { - payloadTypeRegisterMutex.RUnlock() - - return unmarshaler - } else { - payloadTypeRegisterMutex.RUnlock() - - return createGenericDataPayloadUnmarshaler(payloadType) - } -} diff --git a/packages/binary/transaction/test/transaction_test.go b/packages/binary/transaction/test/transaction_test.go new file mode 100644 index 0000000000000000000000000000000000000000..c01b6c3fc44277c69ac9989771ff06060b55a6bf --- /dev/null +++ b/packages/binary/transaction/test/transaction_test.go @@ -0,0 +1,48 @@ +package test + +import ( + "fmt" + "testing" + + "github.com/iotaledger/goshimmer/packages/binary/transaction" + + "github.com/iotaledger/goshimmer/packages/binary/address" + "github.com/iotaledger/goshimmer/packages/binary/identity" + "github.com/iotaledger/goshimmer/packages/binary/transaction/payload/data" + "github.com/iotaledger/goshimmer/packages/binary/transaction/payload/valuetransfer" + "github.com/stretchr/testify/assert" +) + +func TestNew(t *testing.T) { + newTransaction1 := transaction.New(transaction.EmptyId, transaction.EmptyId, identity.Generate(), data.New([]byte("test"))) + assert.Equal(t, newTransaction1.VerifySignature(), true) + + valueTransfer := valuetransfer.New().AddInput(transaction.EmptyId, address.Random()) + + newValueTransaction1 := transaction.New(transaction.EmptyId, transaction.EmptyId, identity.Generate(), valueTransfer) + assert.Equal(t, newValueTransaction1.VerifySignature(), true) + + newValueTransaction2, _ := transaction.FromBytes(newValueTransaction1.GetBytes()) + assert.Equal(t, newValueTransaction2.VerifySignature(), true) + + if newValueTransaction1.GetPayload().GetType() == valuetransfer.Type { + fmt.Println("VALUE TRANSFER TRANSACTION") + } + + newTransaction2 := transaction.New(newTransaction1.GetId(), transaction.EmptyId, identity.Generate(), data.New([]byte("test1"))) + assert.Equal(t, newTransaction2.VerifySignature(), true) + + if newTransaction1.GetPayload().GetType() == data.Type { + fmt.Println("DATA TRANSACTION") + } + + newTransaction3, _ := transaction.FromBytes(newTransaction2.GetBytes()) + assert.Equal(t, newTransaction3.VerifySignature(), true) + + fmt.Println(newTransaction1) + fmt.Println(newTransaction2) + fmt.Println(newTransaction3) + + //fmt.Println(newValueTransaction1) + //fmt.Println(newValueTransaction2) +} diff --git a/packages/binary/transaction/transaction.go b/packages/binary/transaction/transaction.go index f3e4f4fb7b1f09954bd5ce49622ae5919b255eeb..57ed71539a04311b6c4d383ebc34ec7cb2b41268 100644 --- a/packages/binary/transaction/transaction.go +++ b/packages/binary/transaction/transaction.go @@ -5,6 +5,7 @@ import ( "sync" "github.com/iotaledger/goshimmer/packages/binary/identity" + "github.com/iotaledger/goshimmer/packages/binary/transaction/payload" "github.com/iotaledger/goshimmer/packages/stringify" "github.com/iotaledger/hive.go/objectstorage" @@ -22,7 +23,7 @@ type Transaction struct { trunkTransactionId Id branchTransactionId Id issuer *identity.Identity - payload Payload + payload payload.Payload bytes []byte bytesMutex sync.RWMutex signature [identity.SignatureSize]byte @@ -31,12 +32,12 @@ type Transaction struct { // derived properties id *Id idMutex sync.RWMutex - payloadId *PayloadId + payloadId *payload.Id payloadIdMutex sync.RWMutex } // Allows us to "issue" a transaction. -func New(trunkTransactionId Id, branchTransactionId Id, issuer *identity.Identity, payload Payload) (result *Transaction) { +func New(trunkTransactionId Id, branchTransactionId Id, issuer *identity.Identity, payload payload.Payload) (result *Transaction) { return &Transaction{ trunkTransactionId: trunkTransactionId, branchTransactionId: branchTransactionId, @@ -98,11 +99,11 @@ func (transaction *Transaction) GetId() (result Id) { return } -func (transaction *Transaction) GetPayload() Payload { +func (transaction *Transaction) GetPayload() payload.Payload { return transaction.payload } -func (transaction *Transaction) GetPayloadId() (result PayloadId) { +func (transaction *Transaction) GetPayloadId() (result payload.Id) { transaction.payloadIdMutex.RLock() if transaction.payloadId == nil { transaction.payloadIdMutex.RUnlock() @@ -136,14 +137,14 @@ func (transaction *Transaction) GetBytes() []byte { func (transaction *Transaction) calculateTransactionId() Id { payloadId := transaction.GetPayloadId() - hashBase := make([]byte, transactionIdLength+transactionIdLength+payloadIdLength) + hashBase := make([]byte, IdLength+IdLength+payload.IdLength) offset := 0 copy(hashBase[offset:], transaction.trunkTransactionId[:]) - offset += transactionIdLength + offset += IdLength copy(hashBase[offset:], transaction.branchTransactionId[:]) - offset += transactionIdLength + offset += IdLength copy(hashBase[offset:], payloadId[:]) // offset += payloadIdLength @@ -151,10 +152,10 @@ func (transaction *Transaction) calculateTransactionId() Id { return blake2b.Sum512(hashBase) } -func (transaction *Transaction) calculatePayloadId() PayloadId { +func (transaction *Transaction) calculatePayloadId() payload.Id { bytes := transaction.GetBytes() - return blake2b.Sum512(bytes[2*transactionIdLength:]) + return blake2b.Sum512(bytes[2*IdLength:]) } // Since transactions are immutable and do not get changed after being created, we cache the result of the marshaling. @@ -173,14 +174,14 @@ func (transaction *Transaction) MarshalBinary() (result []byte, err error) { } serializedPayloadLength := len(serializedPayload) - result = make([]byte, transactionIdLength+transactionIdLength+identity.PublicKeySize+4+serializedPayloadLength+identity.SignatureSize) + result = make([]byte, IdLength+IdLength+identity.PublicKeySize+4+serializedPayloadLength+identity.SignatureSize) offset := 0 copy(result[offset:], transaction.trunkTransactionId[:]) - offset += transactionIdLength + offset += IdLength copy(result[offset:], transaction.branchTransactionId[:]) - offset += transactionIdLength + offset += IdLength copy(result[offset:], transaction.issuer.PublicKey) offset += identity.PublicKeySize @@ -217,10 +218,10 @@ func (transaction *Transaction) UnmarshalBinary(data []byte) (err error) { offset := 0 copy(transaction.trunkTransactionId[:], data[offset:]) - offset += transactionIdLength + offset += IdLength copy(transaction.branchTransactionId[:], data[offset:]) - offset += transactionIdLength + offset += IdLength transaction.issuer = identity.New(data[offset : offset+identity.PublicKeySize]) offset += identity.PublicKeySize @@ -228,7 +229,7 @@ func (transaction *Transaction) UnmarshalBinary(data []byte) (err error) { payloadType := binary.LittleEndian.Uint32(data[offset:]) offset += 4 - if transaction.payload, err = GetPayloadUnmarshaler(payloadType)(data[offset : len(data)-identity.SignatureSize]); err != nil { + if transaction.payload, err = payload.GetUnmarshaler(payloadType)(data[offset : len(data)-identity.SignatureSize]); err != nil { return } offset += len(data) - identity.SignatureSize - offset diff --git a/packages/binary/transaction/transaction_test.go b/packages/binary/transaction/transaction_test.go deleted file mode 100644 index 8d930a050c95557315d540cc54088cc783cc99e8..0000000000000000000000000000000000000000 --- a/packages/binary/transaction/transaction_test.go +++ /dev/null @@ -1,25 +0,0 @@ -package transaction - -import ( - "fmt" - "testing" - - "github.com/magiconair/properties/assert" - - "github.com/iotaledger/goshimmer/packages/binary/identity" -) - -func TestNew(t *testing.T) { - newTransaction1 := New(Id{}, Id{}, identity.Generate(), NewDataPayload([]byte("test"))) - assert.Equal(t, newTransaction1.VerifySignature(), true) - - newTransaction2 := New(newTransaction1.GetId(), Id{}, identity.Generate(), NewDataPayload([]byte("test1"))) - assert.Equal(t, newTransaction2.VerifySignature(), true) - - newTransaction3, _ := FromBytes(newTransaction2.GetBytes()) - assert.Equal(t, newTransaction3.VerifySignature(), true) - - fmt.Println(newTransaction1) - fmt.Println(newTransaction2) - fmt.Println(newTransaction3) -} diff --git a/packages/binary/transferoutput/reference.go b/packages/binary/transferoutput/reference.go new file mode 100644 index 0000000000000000000000000000000000000000..6e5658cb084c359928b7f45eb11f533fcd2c3e1a --- /dev/null +++ b/packages/binary/transferoutput/reference.go @@ -0,0 +1 @@ +package transferoutput diff --git a/packages/ledgerstate/address_hash.go b/packages/ledgerstate/address_hash.go deleted file mode 100644 index 146c9c044ddc408aa1f23a30c72854859f8ba069..0000000000000000000000000000000000000000 --- a/packages/ledgerstate/address_hash.go +++ /dev/null @@ -1,31 +0,0 @@ -package ledgerstate - -import ( - "unicode/utf8" - - "github.com/iotaledger/goshimmer/packages/stringify" -) - -type AddressHash [addressHashLength]byte - -func NewAddressHash(addressHash string) (result AddressHash) { - copy(result[:], addressHash) - - return -} - -func (addressHash *AddressHash) UnmarshalBinary(data []byte) error { - copy(addressHash[:], data[:addressHashLength]) - - return nil -} - -func (addressHash AddressHash) String() string { - if utf8.Valid(addressHash[:]) { - return string(addressHash[:]) - } else { - return stringify.SliceOfBytes(addressHash[:]) - } -} - -const addressHashLength = 32 diff --git a/packages/ledgerstate/conflict_id.go b/packages/ledgerstate/conflict_id.go index fce0559c6d5acfd114a7400f31ed252a933352d9..d7f596894be9e771d96aaa9f814d6d8d2e5e1c79 100644 --- a/packages/ledgerstate/conflict_id.go +++ b/packages/ledgerstate/conflict_id.go @@ -3,6 +3,8 @@ package ledgerstate import ( "unicode/utf8" + "github.com/iotaledger/goshimmer/packages/binary/address" + "github.com/iotaledger/goshimmer/packages/stringify" "golang.org/x/crypto/blake2b" ) @@ -22,7 +24,7 @@ func NewConflictId(conflictBytes ...interface{}) (result ConflictId) { panic("expected second parameter of NewConflictId to be a AddressHash") } - fullConflictSetIdentifier := make([]byte, transferHashLength+addressHashLength) + fullConflictSetIdentifier := make([]byte, transferHashLength+address.Length) copy(fullConflictSetIdentifier, transferHash[:]) copy(fullConflictSetIdentifier[transferHashLength:], addressHash[:]) diff --git a/packages/ledgerstate/constants.go b/packages/ledgerstate/constants.go index 14c82ed616bd544456e456b0348304aae405aa7d..8c5d7d7c4ee8ab34ff16833e5d66ae6040a5551d 100644 --- a/packages/ledgerstate/constants.go +++ b/packages/ledgerstate/constants.go @@ -1,5 +1,9 @@ package ledgerstate +import ( + "github.com/iotaledger/goshimmer/packages/binary/address" +) + const ( UNSPENT = SpentIndicator(0) SPENT = SpentIndicator(1) @@ -7,7 +11,7 @@ const ( marshalTransferOutputBookingRealityIdStart = 0 marshalTransferOutputBookingRealityIdEnd = marshalTransferOutputBookingRealityIdStart + realityIdLength marshalTransferOutputBookingAddressHashStart = marshalTransferOutputBookingRealityIdEnd - marshalTransferOutputBookingAddressHashEnd = marshalTransferOutputBookingAddressHashStart + addressHashLength + marshalTransferOutputBookingAddressHashEnd = marshalTransferOutputBookingAddressHashStart + address.Length marshalTransferOutputBookingSpentStart = marshalTransferOutputBookingAddressHashEnd marshalTransferOutputBookingSpentEnd = marshalTransferOutputBookingSpentStart + 1 marshalTransferOutputBookingTransferHashStart = marshalTransferOutputBookingSpentEnd diff --git a/packages/ledgerstate/ledgerstate.go b/packages/ledgerstate/ledgerstate.go index fd824a19c900d9072eeec64b040e69974bcc4393..c482acd9ee94a664677074728beffb0ae25ec4a0 100644 --- a/packages/ledgerstate/ledgerstate.go +++ b/packages/ledgerstate/ledgerstate.go @@ -7,6 +7,8 @@ import ( "strings" "time" + "github.com/iotaledger/goshimmer/packages/binary/address" + "github.com/iotaledger/goshimmer/packages/graphviz" "golang.org/x/crypto/blake2b" @@ -42,7 +44,7 @@ func NewLedgerState(storageId string) *LedgerState { return result } -func (ledgerState *LedgerState) AddTransferOutput(transferHash TransferHash, addressHash AddressHash, balances ...*ColoredBalance) *LedgerState { +func (ledgerState *LedgerState) AddTransferOutput(transferHash TransferHash, addressHash address.Address, balances ...*ColoredBalance) *LedgerState { ledgerState.GetReality(MAIN_REALITY_ID).Consume(func(object objectstorage.StorableObject) { mainReality := object.(*Reality) @@ -401,7 +403,7 @@ func (ledgerState *LedgerState) Prune() *LedgerState { func (ledgerState *LedgerState) generateFilterPrefixes(filters []interface{}) ([][]byte, bool) { filteredRealities := make([]RealityId, 0) - filteredAddresses := make([]AddressHash, 0) + filteredAddresses := make([]address.Address, 0) filteredTransfers := make([]TransferHash, 0) filterSpent := false filterUnspent := false @@ -410,7 +412,7 @@ func (ledgerState *LedgerState) generateFilterPrefixes(filters []interface{}) ([ switch typeCastedValue := filter.(type) { case RealityId: filteredRealities = append(filteredRealities, typeCastedValue) - case AddressHash: + case address.Address: filteredAddresses = append(filteredAddresses, typeCastedValue) case TransferHash: filteredTransfers = append(filteredTransfers, typeCastedValue) diff --git a/packages/ledgerstate/ledgerstate_test.go b/packages/ledgerstate/ledgerstate_test.go index 84dbfd10b923ce21a36cd549436bd1fc0ebb8179..fbe5c0f7b0814eba89f29c5dab0822faa14d1836 100644 --- a/packages/ledgerstate/ledgerstate_test.go +++ b/packages/ledgerstate/ledgerstate_test.go @@ -6,6 +6,8 @@ import ( "testing" "time" + "github.com/iotaledger/goshimmer/packages/binary/address" + "github.com/iotaledger/hive.go/objectstorage" "github.com/iotaledger/hive.go/parameter" ) @@ -19,12 +21,12 @@ var ( transferHash4 = NewTransferHash("TRANSFER4") transferHash5 = NewTransferHash("TRANSFER5") transferHash6 = NewTransferHash("TRANSFER6") - addressHash1 = NewAddressHash("ADDRESS1") - addressHash2 = NewAddressHash("ADDRESS2") - addressHash3 = NewAddressHash("ADDRESS3") - addressHash4 = NewAddressHash("ADDRESS4") - addressHash5 = NewAddressHash("ADDRESS5") - addressHash6 = NewAddressHash("ADDRESS6") + addressHash1 = address.New([]byte("ADDRESS1")) + addressHash2 = address.New([]byte("ADDRESS2")) + addressHash3 = address.New([]byte("ADDRESS3")) + addressHash4 = address.New([]byte("ADDRESS4")) + addressHash5 = address.New([]byte("ADDRESS5")) + addressHash6 = address.New([]byte("ADDRESS6")) pendingReality = NewRealityId("PENDING") ) @@ -60,7 +62,7 @@ func Benchmark(b *testing.B) { func Test(t *testing.T) { ledgerState := NewLedgerState("testLedger").Prune().AddTransferOutput( - transferHash1, addressHash1, NewColoredBalance(eth, 1024), NewColoredBalance(iota_, 1338), + transferHash1, addressHash1, NewColoredBalance(eth, 1337), NewColoredBalance(iota_, 1338), ) ledgerState.CreateReality(pendingReality) @@ -118,10 +120,10 @@ func generateRandomTransferHash() TransferHash { var addressHashCounter = 0 -func generateRandomAddressHash() AddressHash { +func generateRandomAddressHash() address.Address { addressHashCounter++ - return NewAddressHash("ADDRESS" + strconv.Itoa(addressHashCounter)) + return address.New([]byte("ADDRESS" + strconv.Itoa(addressHashCounter))) } func initializeLedgerStateWithBalances(numberOfBalances int) (ledgerState *LedgerState, result []*TransferOutputReference) { diff --git a/packages/ledgerstate/outputs.png b/packages/ledgerstate/outputs.png index b746b5ce8c27e57e55376cd41b8a903a8c5fb5c6..e4b6b842208fe13225b399f6e213b750c101732d 100644 Binary files a/packages/ledgerstate/outputs.png and b/packages/ledgerstate/outputs.png differ diff --git a/packages/ledgerstate/outputs1.png b/packages/ledgerstate/outputs1.png index 3113c75833e458ab2bcf84e6596befc8c8e46a30..57ed6f4633b7a13441ae570e908b6932fe4ff600 100644 Binary files a/packages/ledgerstate/outputs1.png and b/packages/ledgerstate/outputs1.png differ diff --git a/packages/ledgerstate/outputs2.png b/packages/ledgerstate/outputs2.png index 7b2d13e78682f509b9c425714dbee0bc3dc068fc..e795eee536931b189a1bc6f5e6640224ea531472 100644 Binary files a/packages/ledgerstate/outputs2.png and b/packages/ledgerstate/outputs2.png differ diff --git a/packages/ledgerstate/realities.png b/packages/ledgerstate/realities.png index bb6453828ee02fc9679bf7b5ca9488e12feb7cbd..9415fdb9f6fee591eada13e24e86fb98a923a16b 100644 Binary files a/packages/ledgerstate/realities.png and b/packages/ledgerstate/realities.png differ diff --git a/packages/ledgerstate/reality.go b/packages/ledgerstate/reality.go index 8f8e7501c99b1d5826e7c4fa8e5dedc26150404e..6036b96bc5d7a44dd0f0c41f7906dac3ab606a71 100644 --- a/packages/ledgerstate/reality.go +++ b/packages/ledgerstate/reality.go @@ -4,6 +4,8 @@ import ( "sync" "sync/atomic" + "github.com/iotaledger/goshimmer/packages/binary/address" + "github.com/iotaledger/goshimmer/packages/stringify" "github.com/iotaledger/goshimmer/packages/errors" @@ -443,7 +445,7 @@ func (reality *Reality) String() (result string) { } // Books a transfer into this reality (contains the dispatcher for the actual tasks). -func (reality *Reality) bookTransfer(transferHash TransferHash, inputs objectstorage.CachedObjects, outputs map[AddressHash][]*ColoredBalance) (err error) { +func (reality *Reality) bookTransfer(transferHash TransferHash, inputs objectstorage.CachedObjects, outputs map[address.Address][]*ColoredBalance) (err error) { if err = reality.verifyTransfer(inputs, outputs); err != nil { return } @@ -464,7 +466,7 @@ func (reality *Reality) bookTransfer(transferHash TransferHash, inputs objectsto } // Internal utility function that verifies the transfer and checks if it is valid (inputs exist + the net balance is 0). -func (reality *Reality) verifyTransfer(inputs []*objectstorage.CachedObject, outputs map[AddressHash][]*ColoredBalance) error { +func (reality *Reality) verifyTransfer(inputs []*objectstorage.CachedObject, outputs map[address.Address][]*ColoredBalance) error { totalColoredBalances := make(map[Color]uint64) for _, cachedInput := range inputs { @@ -504,7 +506,7 @@ func (reality *Reality) verifyTransfer(inputs []*objectstorage.CachedObject, out // Internal utility function that marks the consumed inputs as spent and returns the corresponding conflicts if the // inputs have been consumed before. -func (reality *Reality) consumeInputs(inputs objectstorage.CachedObjects, transferHash TransferHash, outputs map[AddressHash][]*ColoredBalance) (conflicts objectstorage.CachedObjects, err error) { +func (reality *Reality) consumeInputs(inputs objectstorage.CachedObjects, transferHash TransferHash, outputs map[address.Address][]*ColoredBalance) (conflicts objectstorage.CachedObjects, err error) { conflicts = make(objectstorage.CachedObjects, 0) for _, input := range inputs { @@ -532,7 +534,7 @@ func (reality *Reality) consumeInputs(inputs objectstorage.CachedObjects, transf // // If the inputs have been used before and we consequently have a non-empty list of conflicts, we first create a new // reality for the inputs and then book the transfer outputs into the correct reality. -func (reality *Reality) createTransferOutputs(transferHash TransferHash, outputs map[AddressHash][]*ColoredBalance, conflicts objectstorage.CachedObjects) (err error) { +func (reality *Reality) createTransferOutputs(transferHash TransferHash, outputs map[address.Address][]*ColoredBalance, conflicts objectstorage.CachedObjects) (err error) { if len(conflicts) >= 1 { targetRealityId := transferHash.ToRealityId() @@ -581,7 +583,7 @@ func (reality *Reality) collectParentConflictRealities(parentConflictRealities m // Utility function that processes a conflicting input by retrieving the corresponding conflict. // If there is a non-empty list of consumers to elevate, we elevate them. -func (reality *Reality) processConflictingInput(input *TransferOutput, consumersToElevate map[TransferHash][]AddressHash) (conflict *objectstorage.CachedObject, err error) { +func (reality *Reality) processConflictingInput(input *TransferOutput, consumersToElevate map[TransferHash][]address.Address) (conflict *objectstorage.CachedObject, err error) { conflictId := NewConflictId(input.GetTransferHash(), input.GetAddressHash()) if len(consumersToElevate) >= 1 { @@ -603,7 +605,7 @@ func (reality *Reality) processConflictingInput(input *TransferOutput, consumers } // Creates a Reality for the consumers of the conflicting inputs and registers it as part of the corresponding Conflict. -func (reality *Reality) createRealityForPreviouslyUnconflictingConsumers(consumersOfConflictingInput map[TransferHash][]AddressHash, conflict *Conflict) (err error) { +func (reality *Reality) createRealityForPreviouslyUnconflictingConsumers(consumersOfConflictingInput map[TransferHash][]address.Address, conflict *Conflict) (err error) { for transferHash, addressHashes := range consumersOfConflictingInput { elevatedRealityId := transferHash.ToRealityId() diff --git a/packages/ledgerstate/transfer.go b/packages/ledgerstate/transfer.go index 9b583157265f2cb7475aeb00eba548f08192b946..9398631fcd19bd340c993822d840efc5707fdd90 100644 --- a/packages/ledgerstate/transfer.go +++ b/packages/ledgerstate/transfer.go @@ -1,16 +1,20 @@ package ledgerstate +import ( + "github.com/iotaledger/goshimmer/packages/binary/address" +) + type Transfer struct { hash TransferHash inputs []*TransferOutputReference - outputs map[AddressHash][]*ColoredBalance + outputs map[address.Address][]*ColoredBalance } func NewTransfer(transferHash TransferHash) *Transfer { return &Transfer{ hash: transferHash, inputs: make([]*TransferOutputReference, 0), - outputs: make(map[AddressHash][]*ColoredBalance), + outputs: make(map[address.Address][]*ColoredBalance), } } @@ -28,7 +32,7 @@ func (transfer *Transfer) AddInput(input *TransferOutputReference) *Transfer { return transfer } -func (transfer *Transfer) AddOutput(address AddressHash, balance *ColoredBalance) *Transfer { +func (transfer *Transfer) AddOutput(address address.Address, balance *ColoredBalance) *Transfer { if _, addressExists := transfer.outputs[address]; !addressExists { transfer.outputs[address] = make([]*ColoredBalance, 0) } @@ -38,6 +42,14 @@ func (transfer *Transfer) AddOutput(address AddressHash, balance *ColoredBalance return transfer } -func (transfer *Transfer) GetOutputs() map[AddressHash][]*ColoredBalance { +func (transfer *Transfer) GetOutputs() map[address.Address][]*ColoredBalance { return transfer.outputs } + +func (transfer *Transfer) MarshalBinary() (data []byte, err error) { + return +} + +func (transfer *Transfer) UnmarshalBinary(data []byte) (err error) { + return +} diff --git a/packages/ledgerstate/transfer_output.go b/packages/ledgerstate/transfer_output.go index b0a99c3125ebc9e549bbc2c7bf6689f792bced86..f814da77ea67b4b7a67ebe7b553e53b2dd0d776d 100644 --- a/packages/ledgerstate/transfer_output.go +++ b/packages/ledgerstate/transfer_output.go @@ -4,6 +4,8 @@ import ( "encoding/binary" "sync" + "github.com/iotaledger/goshimmer/packages/binary/address" + "github.com/iotaledger/goshimmer/packages/stringify" "github.com/iotaledger/hive.go/objectstorage" ) @@ -12,10 +14,10 @@ type TransferOutput struct { objectstorage.StorableObjectFlags transferHash TransferHash - addressHash AddressHash + addressHash address.Address balances []*ColoredBalance realityId RealityId - consumers map[TransferHash][]AddressHash + consumers map[TransferHash][]address.Address storageKey []byte ledgerState *LedgerState @@ -25,13 +27,13 @@ type TransferOutput struct { bookingMutex sync.Mutex } -func NewTransferOutput(ledgerState *LedgerState, realityId RealityId, transferHash TransferHash, addressHash AddressHash, balances ...*ColoredBalance) *TransferOutput { +func NewTransferOutput(ledgerState *LedgerState, realityId RealityId, transferHash TransferHash, addressHash address.Address, balances ...*ColoredBalance) *TransferOutput { return &TransferOutput{ transferHash: transferHash, addressHash: addressHash, balances: balances, realityId: realityId, - consumers: make(map[TransferHash][]AddressHash), + consumers: make(map[TransferHash][]address.Address), storageKey: append(transferHash[:], addressHash[:]...), ledgerState: ledgerState, @@ -52,7 +54,7 @@ func (transferOutput *TransferOutput) GetRealityId() (realityId RealityId) { return } -func (transferOutput *TransferOutput) GetAddressHash() (addressHash AddressHash) { +func (transferOutput *TransferOutput) GetAddressHash() (addressHash address.Address) { return transferOutput.addressHash } @@ -77,12 +79,12 @@ func (transferOutput *TransferOutput) GetBalances() []*ColoredBalance { return transferOutput.balances } -func (transferOutput *TransferOutput) GetConsumers() (consumers map[TransferHash][]AddressHash) { - consumers = make(map[TransferHash][]AddressHash) +func (transferOutput *TransferOutput) GetConsumers() (consumers map[TransferHash][]address.Address) { + consumers = make(map[TransferHash][]address.Address) transferOutput.consumersMutex.RLock() for transferHash, addresses := range transferOutput.consumers { - consumers[transferHash] = make([]AddressHash, len(addresses)) + consumers[transferHash] = make([]address.Address, len(addresses)) copy(consumers[transferHash], addresses) } transferOutput.consumersMutex.RUnlock() @@ -90,7 +92,7 @@ func (transferOutput *TransferOutput) GetConsumers() (consumers map[TransferHash return } -func (transferOutput *TransferOutput) addConsumer(consumer TransferHash, outputs map[AddressHash][]*ColoredBalance) (consumersToElevate map[TransferHash][]AddressHash, err error) { +func (transferOutput *TransferOutput) addConsumer(consumer TransferHash, outputs map[address.Address][]*ColoredBalance) (consumersToElevate map[TransferHash][]address.Address, err error) { transferOutput.consumersMutex.RLock() if _, exist := transferOutput.consumers[consumer]; exist { transferOutput.consumersMutex.RUnlock() @@ -103,16 +105,16 @@ func (transferOutput *TransferOutput) addConsumer(consumer TransferHash, outputs consumersToElevate = nil err = transferOutput.markAsSpent() case 1: - consumersToElevate = make(map[TransferHash][]AddressHash, 1) + consumersToElevate = make(map[TransferHash][]address.Address, 1) for transferHash, addresses := range transferOutput.consumers { consumersToElevate[transferHash] = addresses } err = nil default: - consumersToElevate = make(map[TransferHash][]AddressHash) + consumersToElevate = make(map[TransferHash][]address.Address) err = nil } - consumers := make([]AddressHash, len(outputs)) + consumers := make([]address.Address, len(outputs)) i := 0 for addressHash := range outputs { consumers[i] = addressHash @@ -179,7 +181,7 @@ func (transferOutput *TransferOutput) MarshalBinary() ([]byte, error) { for _, addresses := range transferOutput.consumers { serializedLength += 4 for range addresses { - serializedLength += addressHashLength + serializedLength += address.Length } } @@ -204,9 +206,8 @@ func (transferOutput *TransferOutput) MarshalBinary() ([]byte, error) { offset += 4 for _, addressHash := range addresses { - copy(result[offset:], addressHash[:addressHashLength]) - offset += addressHashLength - + copy(result[offset:], addressHash[:address.Length]) + offset += address.Length } } @@ -260,13 +261,13 @@ func (transferOutput *TransferOutput) unmarshalBalances(serializedBalances []byt return balances, nil } -func (transferOutput *TransferOutput) unmarshalConsumers(serializedConsumers []byte) (map[TransferHash][]AddressHash, error) { +func (transferOutput *TransferOutput) unmarshalConsumers(serializedConsumers []byte) (map[TransferHash][]address.Address, error) { offset := 0 consumerCount := int(binary.LittleEndian.Uint32(serializedConsumers[offset:])) offset += 4 - consumers := make(map[TransferHash][]AddressHash, consumerCount) + consumers := make(map[TransferHash][]address.Address, consumerCount) for i := 0; i < consumerCount; i++ { transferHash := TransferHash{} if err := transferHash.UnmarshalBinary(serializedConsumers[offset:]); err != nil { @@ -277,13 +278,13 @@ func (transferOutput *TransferOutput) unmarshalConsumers(serializedConsumers []b addressHashCount := int(binary.LittleEndian.Uint32(serializedConsumers[offset:])) offset += 4 - consumers[transferHash] = make([]AddressHash, addressHashCount) + consumers[transferHash] = make([]address.Address, addressHashCount) for i := 0; i < addressHashCount; i++ { - addressHash := AddressHash{} + addressHash := address.Address{} if err := addressHash.UnmarshalBinary(serializedConsumers[offset:]); err != nil { return nil, err } - offset += addressHashLength + offset += address.Length consumers[transferHash][i] = addressHash } diff --git a/packages/ledgerstate/transfer_output_booking.go b/packages/ledgerstate/transfer_output_booking.go index c60fde9a6816f56d2efd09d2f633dc5885e0c0d1..ef01387400d2615e8cfc6f8ec5abfafe8f43731d 100644 --- a/packages/ledgerstate/transfer_output_booking.go +++ b/packages/ledgerstate/transfer_output_booking.go @@ -1,6 +1,7 @@ package ledgerstate import ( + "github.com/iotaledger/goshimmer/packages/binary/address" "github.com/iotaledger/goshimmer/packages/errors" "github.com/iotaledger/goshimmer/packages/stringify" "github.com/iotaledger/hive.go/objectstorage" @@ -12,14 +13,14 @@ type TransferOutputBooking struct { objectstorage.StorableObjectFlags realityId RealityId - addressHash AddressHash + addressHash address.Address spent bool transferHash TransferHash storageKey []byte } -func newTransferOutputBooking(realityId RealityId, addressHash AddressHash, spent bool, transferHash TransferHash) (result *TransferOutputBooking) { +func newTransferOutputBooking(realityId RealityId, addressHash address.Address, spent bool, transferHash TransferHash) (result *TransferOutputBooking) { result = &TransferOutputBooking{ realityId: realityId, addressHash: addressHash, @@ -36,7 +37,7 @@ func (booking *TransferOutputBooking) GetRealityId() RealityId { return booking.realityId } -func (booking *TransferOutputBooking) GetAddressHash() AddressHash { +func (booking *TransferOutputBooking) GetAddressHash() address.Address { return booking.addressHash } @@ -113,11 +114,11 @@ func (booking *TransferOutputBooking) UnmarshalBinary(data []byte) error { // region private utility methods ////////////////////////////////////////////////////////////////////////////////////// -func generateTransferOutputBookingStorageKey(realityId RealityId, addressHash AddressHash, spent bool, transferHash TransferHash) (storageKey []byte) { - storageKey = make([]byte, realityIdLength+addressHashLength+1+transferHashLength) +func generateTransferOutputBookingStorageKey(realityId RealityId, addressHash address.Address, spent bool, transferHash TransferHash) (storageKey []byte) { + storageKey = make([]byte, realityIdLength+address.Length+1+transferHashLength) copy(storageKey[marshalTransferOutputBookingRealityIdStart:marshalTransferOutputBookingRealityIdEnd], realityId[:realityIdLength]) - copy(storageKey[marshalTransferOutputBookingAddressHashStart:marshalTransferOutputBookingAddressHashEnd], addressHash[:addressHashLength]) + copy(storageKey[marshalTransferOutputBookingAddressHashStart:marshalTransferOutputBookingAddressHashEnd], addressHash[:address.Length]) if spent { storageKey[marshalTransferOutputBookingSpentStart] = byte(SPENT) } else { diff --git a/packages/ledgerstate/transfer_output_reference.go b/packages/ledgerstate/transfer_output_reference.go index ad20e791f01b5e948c5b14b3350d4fc1853927dd..c8fdcd697223b88b7529412b02c997890d76acc7 100644 --- a/packages/ledgerstate/transfer_output_reference.go +++ b/packages/ledgerstate/transfer_output_reference.go @@ -1,16 +1,17 @@ package ledgerstate import ( + "github.com/iotaledger/goshimmer/packages/binary/address" "github.com/iotaledger/goshimmer/packages/stringify" ) type TransferOutputReference struct { storageKey []byte transferHash TransferHash - addressHash AddressHash + addressHash address.Address } -func NewTransferOutputReference(transferHash TransferHash, addressHash AddressHash) *TransferOutputReference { +func NewTransferOutputReference(transferHash TransferHash, addressHash address.Address) *TransferOutputReference { return &TransferOutputReference{ storageKey: append(transferHash[:], addressHash[:]...), transferHash: transferHash, diff --git a/packages/ledgerstate/transfer_output_test.go b/packages/ledgerstate/transfer_output_test.go index 7e35ac72d38bc64132fb6ec3398c5b2ca1a5597a..b733a3ca516762ec452a8b6eb980197f21e154cc 100644 --- a/packages/ledgerstate/transfer_output_test.go +++ b/packages/ledgerstate/transfer_output_test.go @@ -3,17 +3,19 @@ package ledgerstate import ( "testing" + "github.com/iotaledger/goshimmer/packages/binary/address" + "github.com/magiconair/properties/assert" ) func TestTransferOutput_MarshalUnmarshal(t *testing.T) { - transferOutput := NewTransferOutput(nil, NewRealityId("REALITY"), NewTransferHash("RECEIVE"), NewAddressHash("ADDRESS1"), NewColoredBalance(NewColor("IOTA"), 44), NewColoredBalance(NewColor("BTC"), 88)) - transferOutput.consumers = make(map[TransferHash][]AddressHash) + transferOutput := NewTransferOutput(nil, NewRealityId("REALITY"), NewTransferHash("RECEIVE"), address.New([]byte("ADDRESS1")), NewColoredBalance(NewColor("IOTA"), 44), NewColoredBalance(NewColor("BTC"), 88)) + transferOutput.consumers = make(map[TransferHash][]address.Address) spendTransferHash := NewTransferHash("SPEND") - transferOutput.consumers[spendTransferHash] = make([]AddressHash, 2) - transferOutput.consumers[spendTransferHash][0] = NewAddressHash("ADDRESS2") - transferOutput.consumers[spendTransferHash][1] = NewAddressHash("ADDRESS3") + transferOutput.consumers[spendTransferHash] = make([]address.Address, 2) + transferOutput.consumers[spendTransferHash][0] = address.New([]byte("ADDRESS2")) + transferOutput.consumers[spendTransferHash][1] = address.New([]byte("ADDRESS3")) marshaledData, err := transferOutput.MarshalBinary() if err != nil { diff --git a/packages/ledgerstate/visualizer.go b/packages/ledgerstate/visualizer.go index 44552e1dd7c30fc95eb3de38951158198bbe2462..a8f1299dcb38008badf7d2c3ec32730419b50ae4 100644 --- a/packages/ledgerstate/visualizer.go +++ b/packages/ledgerstate/visualizer.go @@ -3,13 +3,15 @@ package ledgerstate import ( "strings" + "github.com/iotaledger/goshimmer/packages/binary/address" + "github.com/iotaledger/goshimmer/packages/graphviz" "github.com/emicklei/dot" "github.com/iotaledger/hive.go/objectstorage" ) -type transferOutputId [transferHashLength + addressHashLength]byte +type transferOutputId [transferHashLength + address.Length]byte type Visualizer struct { ledgerState *LedgerState