-
Notifications
You must be signed in to change notification settings - Fork 113
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
258 additions
and
167 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
package ledger |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 /////////////////////////////////////////////////////////////////////////////////////////////////////////// |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | ||
} |
Oops, something went wrong.