Skip to content

Commit

Permalink
Feat: started commenting code
Browse files Browse the repository at this point in the history
  • Loading branch information
hmoog committed Mar 24, 2022
1 parent fbd8293 commit 308cfd5
Show file tree
Hide file tree
Showing 10 changed files with 258 additions and 167 deletions.
1 change: 1 addition & 0 deletions packages/refactored/ledger/ledger_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package ledger
4 changes: 2 additions & 2 deletions packages/refactored/ledger/storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ func NewStorage(ledger *Ledger) (newStorage *Storage) {
}

// CachedTransaction retrieves the Transaction with the given TransactionID from the object storage.
func (s *Storage) CachedTransaction(transactionID utxo.TransactionID) (cachedTransaction *objectstorage.CachedObject[utxo.Transaction]) {
func (s *Storage) CachedTransaction(transactionID utxo.TransactionID) (cachedTransaction CachedTransaction) {
return s.transactionStorage.Load(transactionID.Bytes())
}

Expand All @@ -42,7 +42,7 @@ func (s *Storage) CachedTransactionMetadata(transactionID utxo.TransactionID, co
}

// CachedOutput retrieves the Output with the given OutputID from the object storage.
func (s *Storage) CachedOutput(outputID utxo.OutputID) (cachedOutput *objectstorage.CachedObject[utxo.Output]) {
func (s *Storage) CachedOutput(outputID utxo.OutputID) (cachedOutput CachedOutput) {
return s.outputStorage.Load(outputID.Bytes())
}

Expand Down
197 changes: 197 additions & 0 deletions packages/refactored/ledger/testutils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
package ledger

import (
"sync"

"github.com/iotaledger/hive.go/generics/objectstorage"
"github.com/iotaledger/hive.go/marshalutil"
"github.com/iotaledger/hive.go/stringify"

"github.com/iotaledger/goshimmer/packages/refactored/utxo"
)

// region MockedInput //////////////////////////////////////////////////////////////////////////////////////////////////

type MockedInput struct {
outputID utxo.OutputID
}

func (m *MockedInput) FromMarshalUtil(marshalUtil *marshalutil.MarshalUtil) (input *MockedInput, err error) {
if input = m; input == nil {
input = new(MockedInput)
}

if m.outputID, err = utxo.OutputIDFromMarshalUtil(marshalUtil); err != nil {
return nil, err
}

return m, nil
}

func (m *MockedInput) Bytes() (serializedInput []byte) {
return m.outputID.Bytes()
}

func (m *MockedInput) String() (humanReadableInput string) {
return stringify.Struct("MockedInput",
stringify.StructField("outputID", m.outputID),
)
}

var _ utxo.Input = new(MockedInput)

// endregion ///////////////////////////////////////////////////////////////////////////////////////////////////////////

// region MockedOutput /////////////////////////////////////////////////////////////////////////////////////////////////

type MockedOutput struct {
id utxo.OutputID
idMutex sync.RWMutex

objectstorage.StorableObjectFlags
}

func (m *MockedOutput) ID() (id utxo.OutputID) {
m.idMutex.RLock()
defer m.idMutex.RUnlock()

return m.id
}

func (m *MockedOutput) SetID(id utxo.OutputID) {
m.idMutex.Lock()
defer m.idMutex.Unlock()

m.id = id
}

func (m *MockedOutput) Bytes() (serializedOutput []byte) {
return m.ID().Bytes()
}

func (m *MockedOutput) String() (humanReadableOutput string) {
return stringify.Struct("MockedOutput",
stringify.StructField("id", m.ID()),
)
}

func (m *MockedOutput) FromObjectStorage(key, _ []byte) (object objectstorage.StorableObject, err error) {
id, _, err := utxo.OutputIDFromBytes(key)
if err != nil {
return nil, err
}

output := new(MockedOutput)
output.SetID(id)

return output, nil
}

func (m *MockedOutput) ObjectStorageKey() []byte {
return m.ID().Bytes()
}

func (m *MockedOutput) ObjectStorageValue() []byte {
return nil
}

var _ utxo.Output = new(MockedOutput)

// endregion ///////////////////////////////////////////////////////////////////////////////////////////////////////////

// region mockedTransaction ////////////////////////////////////////////////////////////////////////////////////////////

type mockedTransaction struct {
id utxo.TransactionID
inputs []utxo.Input
outputsCount int

objectstorage.StorableObjectFlags
}

func (m *mockedTransaction) ID() utxo.TransactionID {
return m.id
}

func (m *mockedTransaction) Inputs() []utxo.Input {
return m.inputs
}

func (m *mockedTransaction) Bytes() []byte {
return m.ObjectStorageValue()
}

func (m *mockedTransaction) FromObjectStorage(_, data []byte) (result objectstorage.StorableObject, err error) {
marshalUtil := marshalutil.New(data)

if m.id, err = utxo.TransactionIDFromMarshalUtil(marshalUtil); err != nil {
return
}

inputsCount, err := marshalUtil.ReadUint64()
if err != nil {
return
}
inputs := make([]utxo.Input, int(inputsCount))
for i := uint64(0); i < inputsCount; i++ {
if inputs[i], err = new(MockedInput).FromMarshalUtil(marshalUtil); err != nil {
return
}
}
outputsCount, err := marshalUtil.ReadUint64()
if err != nil {
return
}
m.outputsCount = int(outputsCount)

return m, nil
}

func (m *mockedTransaction) ObjectStorageKey() []byte {
return m.id.Bytes()
}

func (m *mockedTransaction) ObjectStorageValue() []byte {
marshalUtil := marshalutil.New()

marshalUtil.Write(m.ID())
marshalUtil.WriteUint64(uint64(len(m.Inputs())))
for _, input := range m.Inputs() {
marshalUtil.Write(input)
}
marshalUtil.WriteUint64(uint64(m.outputsCount))

return marshalUtil.Bytes()
}

var _ utxo.Transaction = new(mockedTransaction)

// endregion ///////////////////////////////////////////////////////////////////////////////////////////////////////////

// region mockedVM /////////////////////////////////////////////////////////////////////////////////////////////////////

type mockedVM struct{}

func (m *mockedVM) ParseTransaction(transactionBytes []byte) (transaction utxo.Transaction, err error) {
mockedTx, err := new(mockedTransaction).FromObjectStorage(nil, transactionBytes)

return mockedTx.(*mockedTransaction), err
}

func (m *mockedVM) ParseOutput(outputBytes []byte) (output utxo.Output, err error) {
// TODO implement me
panic("implement me")
}

func (m *mockedVM) ResolveInput(input utxo.Input) (outputID utxo.OutputID) {
return input.(*MockedInput).outputID
}

func (m *mockedVM) ExecuteTransaction(transaction utxo.Transaction, inputs []utxo.Output, executionLimit ...uint64) (outputs []utxo.Output, err error) {
// TODO implement me
panic("implement me")
}

var _ utxo.VM = new(mockedVM)

// endregion ///////////////////////////////////////////////////////////////////////////////////////////////////////////
2 changes: 2 additions & 0 deletions packages/refactored/ledger/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,5 @@ type CachedOutputsMetadata = objectstorage.CachedObjects[*OutputMetadata]
type CachedConsumer = *objectstorage.CachedObject[*Consumer]

type CachedConsumers = objectstorage.CachedObjects[*Consumer]

type CachedTransaction = *objectstorage.CachedObject[utxo.Transaction]
7 changes: 6 additions & 1 deletion packages/refactored/utxo/input.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
package utxo

// Input is an entity that allows to encode information about which Outputs are supposed to be used by a Transaction.
type Input interface {
String() (humanReadableInput string)
// Bytes returns a serialized version of the Input.
Bytes() (serialized []byte)

// String returns a human-readable version of the Input.
String() (humanReadable string)
}
25 changes: 18 additions & 7 deletions packages/refactored/utxo/output.go
Original file line number Diff line number Diff line change
@@ -1,17 +1,28 @@
package utxo

import (
"github.com/iotaledger/hive.go/generics/objectstorage"
)

// Output is the container for the data produced by executing a Transaction.
type Output interface {
// ID returns the identifier of the Output.
ID() (id OutputID)

// SetID sets the identifier of the Output.
//
// Note: Since determining the identifier of an Output is an operation that requires at least a few hashing
// operations, we allow the ID to be set externally.
//
// This allows us to potentially skip the ID calculation in cases where the ID is known upfront (e.g. when loading
// Outputs from the object storage).
SetID(id OutputID)

Bytes() (serializedOutput []byte)
// TransactionID returns the identifier of the Transaction that created this Output.
TransactionID() (txID TransactionID)

// Index returns the unique Index of the Output in respect to its TransactionID.
Index() (index uint16)

String() (humanReadableOutput string)
// Bytes returns a serialized version of the Output.
Bytes() (serialized []byte)

objectstorage.StorableObject
// String returns a human-readable version of the Output.
String() (humanReadable string)
}
77 changes: 8 additions & 69 deletions packages/refactored/utxo/outputid.go
Original file line number Diff line number Diff line change
@@ -1,74 +1,13 @@
package utxo

import (
"encoding/binary"
// OutputID is the type that is used for identifiers of Outputs.
type OutputID interface {
// MapKey returns an array version of the OutputID which can be used as a key in maps.
MapKey() [32]byte

"github.com/cockroachdb/errors"
"github.com/iotaledger/hive.go/byteutils"
"github.com/iotaledger/hive.go/cerrors"
"github.com/iotaledger/hive.go/marshalutil"
"github.com/mr-tron/base58"
"golang.org/x/crypto/blake2b"
)
// Bytes returns a serialized version of the OutputID.
Bytes() (serialized []byte)

const OutputIDLength = 32

type OutputID [OutputIDLength]byte

// NewOutputID returns a new OutputID from the given details.
func NewOutputID(transactionID TransactionID, outputIndex uint16, outputMetadata []byte) (outputID OutputID) {
serializedOutputIndex := make([]byte, 2)
binary.LittleEndian.PutUint16(serializedOutputIndex, outputIndex)

return blake2b.Sum256(byteutils.ConcatBytes(transactionID.Bytes(), serializedOutputIndex, outputMetadata))
}

// OutputIDFromBytes unmarshals an OutputID from a sequence of bytes.
func OutputIDFromBytes(bytes []byte) (outputID OutputID, consumedBytes int, err error) {
marshalUtil := marshalutil.New(bytes)
if outputID, err = OutputIDFromMarshalUtil(marshalUtil); err != nil {
err = errors.Errorf("failed to parse OutputID from MarshalUtil: %w", err)
return
}
consumedBytes = marshalUtil.ReadOffset()

return
}

// OutputIDFromBase58 creates an OutputID from a base58 encoded string.
func OutputIDFromBase58(base58String string) (outputID OutputID, err error) {
decodedBytes, err := base58.Decode(base58String)
if err != nil {
err = errors.Errorf("error while decoding base58 encoded OutputID (%v): %w", err, cerrors.ErrBase58DecodeFailed)
return
}

if outputID, _, err = OutputIDFromBytes(decodedBytes); err != nil {
err = errors.Errorf("failed to parse OutputID from bytes: %w", err)
return
}

return
}

// OutputIDFromMarshalUtil unmarshals an OutputID using a MarshalUtil (for easier unmarshaling).
func OutputIDFromMarshalUtil(marshalUtil *marshalutil.MarshalUtil) (outputID OutputID, err error) {
outputIDBytes, err := marshalUtil.ReadBytes(OutputIDLength)
if err != nil {
err = errors.Errorf("failed to parse OutputID (%v): %w", err, cerrors.ErrParseBytesFailed)
return
}
copy(outputID[:], outputIDBytes)

return
}

// Bytes returns a marshaled version of the OutputID.
func (o OutputID) Bytes() (serializedTransaction []byte) {
return o[:]
}

// String creates a human-readable version of the OutputID.
func (o OutputID) String() (humanReadableOutputID string) {
return "OutputID(" + base58.Encode(o[:]) + ")"
// String returns a human-readable version of the OutputID.
String() (humanReadable string)
}
17 changes: 9 additions & 8 deletions packages/refactored/utxo/transaction.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
package utxo

import (
"github.com/iotaledger/hive.go/generics/objectstorage"
)

// Transaction is the type that is used to describe instructions how to modify the ledger state.
type Transaction interface {
ID() TransactionID
// ID returns the identifier of the Transaction.
ID() (id TransactionID)

Inputs() []Input
// Inputs returns the inputs of the Transaction.
Inputs() (inputs []Input)

Bytes() []byte
// Bytes returns a serialized version of the Transaction.
Bytes() (serialized []byte)

objectstorage.StorableObject
// String returns a human-readable version of the Transaction.
String() (humanReadable string)
}
Loading

0 comments on commit 308cfd5

Please sign in to comment.