From afea62eb8a22b3e41891a198c714ce579a89fe3a Mon Sep 17 00:00:00 2001 From: jonastheis <4181434+jonastheis@users.noreply.github.com> Date: Wed, 4 Oct 2023 12:38:16 +0200 Subject: [PATCH 01/15] Add framework for code generation --- gen/cmd/cmd.go | 64 ++++++++++++++++++++++++++++++++++++++++ gen/cmd/configuration.go | 31 +++++++++++++++++++ 2 files changed, 95 insertions(+) create mode 100644 gen/cmd/cmd.go create mode 100644 gen/cmd/configuration.go diff --git a/gen/cmd/cmd.go b/gen/cmd/cmd.go new file mode 100644 index 000000000..9b11161e6 --- /dev/null +++ b/gen/cmd/cmd.go @@ -0,0 +1,64 @@ +// Package gen/cmd allows to generate .go source files using the go:generate command. +// Use with "cmd [templateFile] [outputFile] [typeName] [typeReceiver] [Features separated by space]". +// +// In the template the following are available: +// - typeName as {{.Name}} +// - typeReceiver as {{.Receiver}} +// - Features are available via map and can be evaluated as {{if index .Features "extended"}} +package main + +import ( + "bytes" + "fmt" + "go/format" + "os" + "strings" + "text/template" + + "github.com/iotaledger/hive.go/lo" +) + +func main() { + if len(os.Args) < 6 { + printUsage("not enough parameters") + } + + templateFilePath := os.Args[1] + conf := newConfiguration(os.Args[2], os.Args[3], os.Args[4], os.Args[5]) + + funcs := template.FuncMap{ + "firstLower": func(s string) string { + return strings.ToLower(s[0:]) + s[:1] + }, + } + + tmplFile := lo.PanicOnErr(os.ReadFile(templateFilePath)) + + tmpl := template.Must( + template.New("gen"). + Funcs(funcs). + Parse(string(tmplFile)), + ) + + buffer := new(bytes.Buffer) + panicOnError(tmpl.Execute(buffer, conf)) + + formattedOutput := lo.PanicOnErr(format.Source(buffer.Bytes())) + + panicOnError(os.WriteFile(conf.FileName, formattedOutput, 0600)) +} + +// printUsage prints the usage of the variadic code generator in case of an error. +func printUsage(errorMsg string) { + _, _ = fmt.Fprintf(os.Stderr, "Error:\t%s\n\n", errorMsg) + _, _ = fmt.Fprintf(os.Stderr, "Usage of gen/cmd:\n") + _, _ = fmt.Fprintf(os.Stderr, "\tcmd [templateFile] [outputFile] [typeName] [typeReceiver] [features separated by space]\n") + + os.Exit(2) +} + +func panicOnError(err error) { + if err != nil { + panic(err) + } +} diff --git a/gen/cmd/configuration.go b/gen/cmd/configuration.go new file mode 100644 index 000000000..510079bf6 --- /dev/null +++ b/gen/cmd/configuration.go @@ -0,0 +1,31 @@ +package main + +import ( + "fmt" + "strings" +) + +type configuration struct { + FileName string + Name string + Receiver string + Features map[string]bool +} + +func newConfiguration(fileName, name, receiver, featuresStr string) *configuration { + features := make(map[string]bool) + for _, feature := range strings.Split(featuresStr, " ") { + features[feature] = true + } + + return &configuration{ + FileName: fileName, + Name: name, + Receiver: strings.ToLower(receiver), + Features: features, + } +} + +func (c *configuration) String() string { + return fmt.Sprintf("configuration{\n\tFileName:%s,\n\tName:%s,\n\tReceiver:%s,\n\tFeatures:%v,\n}\n", c.FileName, c.Name, c.Receiver, c.Features) +} From a1f6ac8b696db5779a7b157ed90039d6c6f63418 Mon Sep 17 00:00:00 2001 From: jonastheis <4181434+jonastheis@users.noreply.github.com> Date: Thu, 5 Oct 2023 05:35:42 +0200 Subject: [PATCH 02/15] Add template and generation for Identifier --- gen/gen_identifier.go | 6 ++ gen/identifier.tmpl | 142 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 148 insertions(+) create mode 100644 gen/gen_identifier.go create mode 100644 gen/identifier.tmpl diff --git a/gen/gen_identifier.go b/gen/gen_identifier.go new file mode 100644 index 000000000..291ffd0cd --- /dev/null +++ b/gen/gen_identifier.go @@ -0,0 +1,6 @@ +//go:build ignore + +package gen + +//go:generate go run ./cmd identifier.tmpl ../identifier.gen.go Identifier i "" +//go:generate go run ./cmd identifier.tmpl ../identifier_account.gen.go AccountID a "output" diff --git a/gen/identifier.tmpl b/gen/identifier.tmpl new file mode 100644 index 000000000..7ced5d5e2 --- /dev/null +++ b/gen/identifier.tmpl @@ -0,0 +1,142 @@ +package iotago + +// Code generated by go generate; DO NOT EDIT. Check gen/ directory instead. + +import ( + "encoding/hex" + "sync" + + "golang.org/x/crypto/blake2b" + + "github.com/iotaledger/hive.go/ierrors" + "github.com/iotaledger/iota.go/v4/hexutil" +) + +const ( + // {{.Name}}Length defines the length of an {{.Name}}. + {{.Name}}Length = blake2b.Size256 +) + +var ( + Empty{{.Name}} = {{.Name}}{} + + ErrInvalid{{.Name}}Length = ierrors.New("invalid {{.Name}} length") +) + +// {{.Name}} is a 32 byte hash value. +type {{.Name}} [{{.Name}}Length]byte + +type {{.Name}}s []{{.Name}} + +// {{.Name}}FromData returns a new {{.Name}} for the given data by hashing it with blake2b. +func {{.Name}}FromData(data []byte) {{.Name}} { + return blake2b.Sum256(data) +} + +// {{.Name}}FromHexString converts the hex to an {{.Name}} representation. +func {{.Name}}FromHexString(hex string) ({{.Name}}, error) { + bytes, err := hexutil.DecodeHex(hex) + if err != nil { + return {{.Name}}{}, err + } + + {{.Receiver}}, _, err := {{.Name}}FromBytes(bytes) + + return {{.Receiver}}, err +} + +// Must{{.Name}}FromHexString converts the hex to an {{.Name}} representation. +func Must{{.Name}}FromHexString(hex string) {{.Name}} { + {{.Receiver}}, err := {{.Name}}FromHexString(hex) + if err != nil { + panic(err) + } + + return {{.Receiver}} +} + +func {{.Name}}FromBytes(bytes []byte) ({{.Name}}, int, error) { + var {{.Receiver}} {{.Name}} + if len(bytes) < {{.Name}}Length { + return {{.Receiver}}, 0, ErrInvalid{{.Name}}Length + } + copy({{.Receiver}}[:], bytes) + + return {{.Receiver}}, len(bytes), nil +} + +func ({{.Receiver}} {{.Name}}) Bytes() ([]byte, error) { + return {{.Receiver}}[:], nil +} + +func ({{.Receiver}} {{.Name}}) MarshalText() (text []byte, err error) { + dst := make([]byte, hex.EncodedLen(len({{.Name}}{}))) + hex.Encode(dst, {{.Receiver}}[:]) + + return dst, nil +} + +func ({{.Receiver}} *{{.Name}}) UnmarshalText(text []byte) error { + _, err := hex.Decode({{.Receiver}}[:], text) + + return err +} + +// Empty tells whether the {{.Name}} is empty. +func ({{.Receiver}} {{.Name}}) Empty() bool { + return {{.Receiver}} == Empty{{.Name}} +} + +// ToHex converts the {{.Name}} to its hex representation. +func ({{.Receiver}} {{.Name}}) ToHex() string { + return hexutil.EncodeHex({{.Receiver}}[:]) +} + +func ({{.Receiver}} {{.Name}}) String() string { + return {{.Receiver}}.Alias() +} + +var ( + // {{firstLower .Name}}Aliases contains a dictionary of {{.Name}}s associated to their human-readable alias. + {{firstLower .Name}}Aliases = make(map[{{.Name}}]string) + + // {{firstLower .Name}}AliasesMutex is the mutex that is used to synchronize access to the previous map. + {{firstLower .Name}}AliasesMutex = sync.RWMutex{} +) + +// RegisterAlias allows to register a human-readable alias for the {{.Name}} which will be used as a replacement for +// the String method. +func ({{.Receiver}} {{.Name}}) RegisterAlias(alias string) { + {{firstLower .Name}}AliasesMutex.Lock() + defer {{firstLower .Name}}AliasesMutex.Unlock() + + {{firstLower .Name}}Aliases[{{.Receiver}}] = alias +} + +// Alias returns the human-readable alias of the {{.Name}} (or the hex encoded bytes if no alias was set). +func ({{.Receiver}} {{.Name}}) Alias() (alias string) { + {{firstLower .Name}}AliasesMutex.RLock() + defer {{firstLower .Name}}AliasesMutex.RUnlock() + + if existingAlias, exists := {{firstLower .Name}}Aliases[{{.Receiver}}]; exists { + return existingAlias + } + + return {{.Receiver}}.ToHex() +} + +// UnregisterAlias allows to unregister a previously registered alias. +func ({{.Receiver}} {{.Name}}) UnregisterAlias() { + {{firstLower .Name}}AliasesMutex.Lock() + defer {{firstLower .Name}}AliasesMutex.Unlock() + + delete({{firstLower .Name}}Aliases, {{.Receiver}}) +} + +// Unregister{{.Name}}Aliases allows to unregister all previously registered aliases. +func Unregister{{.Name}}Aliases() { + {{firstLower .Name}}AliasesMutex.Lock() + defer {{firstLower .Name}}AliasesMutex.Unlock() + + {{firstLower .Name}}Aliases = make(map[{{.Name}}]string) +} From 92fd272b2baaf6fd5d7ececd7ec18d9ac92261e9 Mon Sep 17 00:00:00 2001 From: jonastheis <4181434+jonastheis@users.noreply.github.com> Date: Thu, 5 Oct 2023 05:40:22 +0200 Subject: [PATCH 03/15] Generate Identifier and AccountID from template and fix all problems --- builder/output_builder_account.go | 2 +- builder/transaction_builder.go | 6 +- identifier.gen.go | 142 ++++++++++++++++++++++++++++++ identifier.go | 138 ----------------------------- identifier_account.gen.go | 142 ++++++++++++++++++++++++++++++ identifier_account.go | 36 ++++++++ output_account.go | 55 +----------- output_test.go | 2 +- rent.go | 2 +- transaction_id.go | 1 - vm/types.go | 2 +- 11 files changed, 328 insertions(+), 200 deletions(-) create mode 100644 identifier.gen.go delete mode 100644 identifier.go create mode 100644 identifier_account.gen.go create mode 100644 identifier_account.go diff --git a/builder/output_builder_account.go b/builder/output_builder_account.go index 93d45928f..6f6ffbc39 100644 --- a/builder/output_builder_account.go +++ b/builder/output_builder_account.go @@ -10,7 +10,7 @@ func NewAccountOutputBuilder(stateCtrl iotago.Address, govAddr iotago.Address, a return &AccountOutputBuilder{output: &iotago.AccountOutput{ Amount: amount, Mana: 0, - AccountID: iotago.EmptyAccountID(), + AccountID: iotago.EmptyAccountID, StateIndex: 0, StateMetadata: []byte{}, FoundryCounter: 0, diff --git a/builder/transaction_builder.go b/builder/transaction_builder.go index a61ad1b0f..3878b9cd5 100644 --- a/builder/transaction_builder.go +++ b/builder/transaction_builder.go @@ -147,16 +147,16 @@ func (b *TransactionBuilder) AllotRequiredManaAndStoreRemainingManaInOutput(targ // check if the output is locked for a certain time to an account. hasManalockCondition := func(output iotago.Output) (iotago.AccountID, bool) { if !output.UnlockConditionSet().HasTimelockUntil(minManalockedSlot) { - return iotago.EmptyAccountID(), false + return iotago.EmptyAccountID, false } unlockAddress := output.UnlockConditionSet().Address() if unlockAddress == nil { - return iotago.EmptyAccountID(), false + return iotago.EmptyAccountID, false } if unlockAddress.Address.Type() != iotago.AddressAccount { - return iotago.EmptyAccountID(), false + return iotago.EmptyAccountID, false } //nolint:forcetypeassert // we can safely assume that this is an AccountAddress accountAddress := unlockAddress.Address.(*iotago.AccountAddress) diff --git a/identifier.gen.go b/identifier.gen.go new file mode 100644 index 000000000..d86cec063 --- /dev/null +++ b/identifier.gen.go @@ -0,0 +1,142 @@ +package iotago + +// Code generated by go generate; DO NOT EDIT. Check gen/ directory instead. + +import ( + "encoding/hex" + "sync" + + "golang.org/x/crypto/blake2b" + + "github.com/iotaledger/hive.go/ierrors" + "github.com/iotaledger/iota.go/v4/hexutil" +) + +const ( + // IdentifierLength defines the length of an Identifier. + IdentifierLength = blake2b.Size256 +) + +var ( + EmptyIdentifier = Identifier{} + + ErrInvalidIdentifierLength = ierrors.New("invalid Identifier length") +) + +// Identifier is a 32 byte hash value. +type Identifier [IdentifierLength]byte + +type Identifiers []Identifier + +// IdentifierFromData returns a new Identifier for the given data by hashing it with blake2b. +func IdentifierFromData(data []byte) Identifier { + return blake2b.Sum256(data) +} + +// IdentifierFromHexString converts the hex to an Identifier representation. +func IdentifierFromHexString(hex string) (Identifier, error) { + bytes, err := hexutil.DecodeHex(hex) + if err != nil { + return Identifier{}, err + } + + i, _, err := IdentifierFromBytes(bytes) + + return i, err +} + +// MustIdentifierFromHexString converts the hex to an Identifier representation. +func MustIdentifierFromHexString(hex string) Identifier { + i, err := IdentifierFromHexString(hex) + if err != nil { + panic(err) + } + + return i +} + +func IdentifierFromBytes(bytes []byte) (Identifier, int, error) { + var i Identifier + if len(bytes) < IdentifierLength { + return i, 0, ErrInvalidIdentifierLength + } + copy(i[:], bytes) + + return i, len(bytes), nil +} + +func (i Identifier) Bytes() ([]byte, error) { + return i[:], nil +} + +func (i Identifier) MarshalText() (text []byte, err error) { + dst := make([]byte, hex.EncodedLen(len(Identifier{}))) + hex.Encode(dst, i[:]) + + return dst, nil +} + +func (i *Identifier) UnmarshalText(text []byte) error { + _, err := hex.Decode(i[:], text) + + return err +} + +// Empty tells whether the Identifier is empty. +func (i Identifier) Empty() bool { + return i == EmptyIdentifier +} + +// ToHex converts the Identifier to its hex representation. +func (i Identifier) ToHex() string { + return hexutil.EncodeHex(i[:]) +} + +func (i Identifier) String() string { + return i.Alias() +} + +var ( + // identifierIAliases contains a dictionary of Identifiers associated to their human-readable alias. + identifierIAliases = make(map[Identifier]string) + + // identifierIAliasesMutex is the mutex that is used to synchronize access to the previous map. + identifierIAliasesMutex = sync.RWMutex{} +) + +// RegisterAlias allows to register a human-readable alias for the Identifier which will be used as a replacement for +// the String method. +func (i Identifier) RegisterAlias(alias string) { + identifierIAliasesMutex.Lock() + defer identifierIAliasesMutex.Unlock() + + identifierIAliases[i] = alias +} + +// Alias returns the human-readable alias of the Identifier (or the hex encoded bytes if no alias was set). +func (i Identifier) Alias() (alias string) { + identifierIAliasesMutex.RLock() + defer identifierIAliasesMutex.RUnlock() + + if existingAlias, exists := identifierIAliases[i]; exists { + return existingAlias + } + + return i.ToHex() +} + +// UnregisterAlias allows to unregister a previously registered alias. +func (i Identifier) UnregisterAlias() { + identifierIAliasesMutex.Lock() + defer identifierIAliasesMutex.Unlock() + + delete(identifierIAliases, i) +} + +// UnregisterIdentifierAliases allows to unregister all previously registered aliases. +func UnregisterIdentifierAliases() { + identifierIAliasesMutex.Lock() + defer identifierIAliasesMutex.Unlock() + + identifierIAliases = make(map[Identifier]string) +} diff --git a/identifier.go b/identifier.go deleted file mode 100644 index 8915791f0..000000000 --- a/identifier.go +++ /dev/null @@ -1,138 +0,0 @@ -package iotago - -import ( - "encoding/hex" - "sync" - - "golang.org/x/crypto/blake2b" - - "github.com/iotaledger/hive.go/ierrors" - "github.com/iotaledger/iota.go/v4/hexutil" -) - -const ( - // IdentifierLength defines the length of an Identifier. - IdentifierLength = blake2b.Size256 -) - -var ( - EmptyIdentifier = Identifier{} - - ErrInvalidIdentifierLength = ierrors.New("Invalid identifier length") -) - -// Identifier is a 32 byte hash value that can be used to uniquely identify some blob of data. -type Identifier [IdentifierLength]byte - -// IdentifierFromData returns a new Identifier for the given data by hashing it with blake2b. -func IdentifierFromData(data []byte) Identifier { - return blake2b.Sum256(data) -} - -// IdentifierFromHexString converts the hex to an Identifier representation. -func IdentifierFromHexString(hex string) (Identifier, error) { - bytes, err := hexutil.DecodeHex(hex) - if err != nil { - return Identifier{}, err - } - - id, _, err := IdentifierFromBytes(bytes) - - return id, err -} - -// MustIdentifierFromHexString converts the hex to an Identifier representation. -func MustIdentifierFromHexString(hex string) Identifier { - id, err := IdentifierFromHexString(hex) - if err != nil { - panic(err) - } - - return id -} - -func IdentifierFromBytes(bytes []byte) (Identifier, int, error) { - var id Identifier - if len(bytes) < IdentifierLength { - return id, 0, ErrInvalidIdentifierLength - } - copy(id[:], bytes) - - return id, len(bytes), nil -} - -func (id Identifier) Bytes() ([]byte, error) { - return id[:], nil -} - -func (id Identifier) MarshalText() (text []byte, err error) { - dst := make([]byte, hex.EncodedLen(len(Identifier{}))) - hex.Encode(dst, id[:]) - - return dst, nil -} - -func (id *Identifier) UnmarshalText(text []byte) error { - _, err := hex.Decode(id[:], text) - - return err -} - -// Empty tells whether the Identifier is empty. -func (id Identifier) Empty() bool { - return id == EmptyIdentifier -} - -// ToHex converts the Identifier to its hex representation. -func (id Identifier) ToHex() string { - return hexutil.EncodeHex(id[:]) -} - -func (id Identifier) String() string { - return id.Alias() -} - -var ( - // identifierAliases contains a dictionary of identifiers associated to their human-readable alias. - identifierAliases = make(map[Identifier]string) - - // identifierAliasesMutex is the mutex that is used to synchronize access to the previous map. - identifierAliasesMutex = sync.RWMutex{} -) - -// RegisterAlias allows to register a human-readable alias for the Identifier which will be used as a replacement for -// the String method. -func (id Identifier) RegisterAlias(alias string) { - identifierAliasesMutex.Lock() - defer identifierAliasesMutex.Unlock() - - identifierAliases[id] = alias -} - -// Alias returns the human-readable alias of the Identifier (or the base58 encoded bytes of no alias was set). -func (id Identifier) Alias() (alias string) { - identifierAliasesMutex.RLock() - defer identifierAliasesMutex.RUnlock() - - if existingAlias, exists := identifierAliases[id]; exists { - return existingAlias - } - - return id.ToHex() -} - -// UnregisterAlias allows to unregister a previously registered alias. -func (id Identifier) UnregisterAlias() { - identifierAliasesMutex.Lock() - defer identifierAliasesMutex.Unlock() - - delete(identifierAliases, id) -} - -// UnregisterIdentifierAliases allows to unregister all previously registered aliases. -func UnregisterIdentifierAliases() { - identifierAliasesMutex.Lock() - defer identifierAliasesMutex.Unlock() - - identifierAliases = make(map[Identifier]string) -} diff --git a/identifier_account.gen.go b/identifier_account.gen.go new file mode 100644 index 000000000..34eb5a7a5 --- /dev/null +++ b/identifier_account.gen.go @@ -0,0 +1,142 @@ +package iotago + +// Code generated by go generate; DO NOT EDIT. Check gen/ directory instead. + +import ( + "encoding/hex" + "sync" + + "golang.org/x/crypto/blake2b" + + "github.com/iotaledger/hive.go/ierrors" + "github.com/iotaledger/iota.go/v4/hexutil" +) + +const ( + // AccountIDLength defines the length of an AccountID. + AccountIDLength = blake2b.Size256 +) + +var ( + EmptyAccountID = AccountID{} + + ErrInvalidAccountIDLength = ierrors.New("invalid AccountID length") +) + +// AccountID is a 32 byte hash value. +type AccountID [AccountIDLength]byte + +type AccountIDs []AccountID + +// AccountIDFromData returns a new AccountID for the given data by hashing it with blake2b. +func AccountIDFromData(data []byte) AccountID { + return blake2b.Sum256(data) +} + +// AccountIDFromHexString converts the hex to an AccountID representation. +func AccountIDFromHexString(hex string) (AccountID, error) { + bytes, err := hexutil.DecodeHex(hex) + if err != nil { + return AccountID{}, err + } + + a, _, err := AccountIDFromBytes(bytes) + + return a, err +} + +// MustAccountIDFromHexString converts the hex to an AccountID representation. +func MustAccountIDFromHexString(hex string) AccountID { + a, err := AccountIDFromHexString(hex) + if err != nil { + panic(err) + } + + return a +} + +func AccountIDFromBytes(bytes []byte) (AccountID, int, error) { + var a AccountID + if len(bytes) < AccountIDLength { + return a, 0, ErrInvalidAccountIDLength + } + copy(a[:], bytes) + + return a, len(bytes), nil +} + +func (a AccountID) Bytes() ([]byte, error) { + return a[:], nil +} + +func (a AccountID) MarshalText() (text []byte, err error) { + dst := make([]byte, hex.EncodedLen(len(AccountID{}))) + hex.Encode(dst, a[:]) + + return dst, nil +} + +func (a *AccountID) UnmarshalText(text []byte) error { + _, err := hex.Decode(a[:], text) + + return err +} + +// Empty tells whether the AccountID is empty. +func (a AccountID) Empty() bool { + return a == EmptyAccountID +} + +// ToHex converts the AccountID to its hex representation. +func (a AccountID) ToHex() string { + return hexutil.EncodeHex(a[:]) +} + +func (a AccountID) String() string { + return a.Alias() +} + +var ( + // accountidAAliases contains a dictionary of AccountIDs associated to their human-readable alias. + accountidAAliases = make(map[AccountID]string) + + // accountidAAliasesMutex is the mutex that is used to synchronize access to the previous map. + accountidAAliasesMutex = sync.RWMutex{} +) + +// RegisterAlias allows to register a human-readable alias for the AccountID which will be used as a replacement for +// the String method. +func (a AccountID) RegisterAlias(alias string) { + accountidAAliasesMutex.Lock() + defer accountidAAliasesMutex.Unlock() + + accountidAAliases[a] = alias +} + +// Alias returns the human-readable alias of the AccountID (or the hex encoded bytes if no alias was set). +func (a AccountID) Alias() (alias string) { + accountidAAliasesMutex.RLock() + defer accountidAAliasesMutex.RUnlock() + + if existingAlias, exists := accountidAAliases[a]; exists { + return existingAlias + } + + return a.ToHex() +} + +// UnregisterAlias allows to unregister a previously registered alias. +func (a AccountID) UnregisterAlias() { + accountidAAliasesMutex.Lock() + defer accountidAAliasesMutex.Unlock() + + delete(accountidAAliases, a) +} + +// UnregisterAccountIDAliases allows to unregister all previously registered aliases. +func UnregisterAccountIDAliases() { + accountidAAliasesMutex.Lock() + defer accountidAAliasesMutex.Unlock() + + accountidAAliases = make(map[AccountID]string) +} diff --git a/identifier_account.go b/identifier_account.go new file mode 100644 index 000000000..ebf6b20e4 --- /dev/null +++ b/identifier_account.go @@ -0,0 +1,36 @@ +package iotago + +import "golang.org/x/crypto/blake2b" + +func (id AccountID) Addressable() bool { + return true +} + +func (id AccountID) Key() interface{} { + return id.String() +} + +func (id AccountID) FromOutputID(in OutputID) ChainID { + return AccountIDFromOutputID(in) +} + +func (id AccountID) Matches(other ChainID) bool { + otherAccountID, isAccountID := other.(AccountID) + if !isAccountID { + return false + } + + return id == otherAccountID +} + +func (id AccountID) ToAddress() ChainAddress { + var addr AccountAddress + copy(addr[:], id[:]) + + return &addr +} + +// AccountIDFromOutputID returns the AccountID computed from a given OutputID. +func AccountIDFromOutputID(outputID OutputID) AccountID { + return blake2b.Sum256(outputID[:]) +} diff --git a/output_account.go b/output_account.go index a80568e3e..6b1d5a0cb 100644 --- a/output_account.go +++ b/output_account.go @@ -3,17 +3,10 @@ package iotago import ( "bytes" - "golang.org/x/crypto/blake2b" - "github.com/iotaledger/hive.go/ierrors" "github.com/iotaledger/hive.go/serializer/v2" ) -const ( - // AccountIDLength is the byte length of an AccountID. - AccountIDLength = IdentifierLength -) - var ( // ErrNonUniqueAccountOutputs gets returned when multiple AccountOutputs(s) with the same AccountID exist within sets. ErrNonUniqueAccountOutputs = ierrors.New("non unique accounts within outputs") @@ -37,54 +30,8 @@ var ( // ErrMultipleImplicitAccountCreationAddresses gets return when there is more than one // Implicit Account Creation Address on the input side of a transaction. ErrMultipleImplicitAccountCreationAddresses = ierrors.New("multiple implicit account creation addresses on the input side") - - emptyAccountID = [AccountIDLength]byte{} ) -func EmptyAccountID() AccountID { - return emptyAccountID -} - -// AccountID is the identifier for an account. -// It is computed as the Blake2b-256 hash of the OutputID of the output which created the account. -type AccountID = Identifier - -// AccountIDs are IDs of accounts. -type AccountIDs []AccountID - -func (id AccountID) Addressable() bool { - return true -} - -func (id AccountID) Key() interface{} { - return id.String() -} - -func (id AccountID) FromOutputID(in OutputID) ChainID { - return AccountIDFromOutputID(in) -} - -func (id AccountID) Matches(other ChainID) bool { - otherAccountID, isAccountID := other.(AccountID) - if !isAccountID { - return false - } - - return id == otherAccountID -} - -func (id AccountID) ToAddress() ChainAddress { - var addr AccountAddress - copy(addr[:], id[:]) - - return &addr -} - -// AccountIDFromOutputID returns the AccountID computed from a given OutputID. -func AccountIDFromOutputID(outputID OutputID) AccountID { - return blake2b.Sum256(outputID[:]) -} - // AccountOutputs is a slice of AccountOutput(s). type AccountOutputs []*AccountOutput @@ -311,7 +258,7 @@ func (a *AccountOutput) ChainID() ChainID { } func (a *AccountOutput) AccountEmpty() bool { - return a.AccountID == emptyAccountID + return a.AccountID == EmptyAccountID } func (a *AccountOutput) FeatureSet() FeatureSet { diff --git a/output_test.go b/output_test.go index 4aa73f5f5..c9addcd03 100644 --- a/output_test.go +++ b/output_test.go @@ -75,7 +75,7 @@ func TestOutputIDString(t *testing.T) { } func TestOutputsDeSerialize(t *testing.T) { - emptyAccountAddress := iotago.AccountAddress(iotago.EmptyAccountID()) + emptyAccountAddress := iotago.AccountAddress(iotago.EmptyAccountID) tests := []deSerializeTest{ { diff --git a/rent.go b/rent.go index e53d556bc..d1d522723 100644 --- a/rent.go +++ b/rent.go @@ -94,7 +94,7 @@ func NewRentStructure(rentParameters *RentParameters) *RentStructure { dummyAccountOutput := &AccountOutput{ Amount: 0, Mana: 0, - AccountID: EmptyAccountID(), + AccountID: EmptyAccountID, StateIndex: 0, StateMetadata: []byte{}, FoundryCounter: 0, diff --git a/transaction_id.go b/transaction_id.go index 405f4b123..2f95d1ee2 100644 --- a/transaction_id.go +++ b/transaction_id.go @@ -1,4 +1,3 @@ -//nolint:dupl package iotago import ( diff --git a/vm/types.go b/vm/types.go index 3d5608330..d58d20330 100644 --- a/vm/types.go +++ b/vm/types.go @@ -77,5 +77,5 @@ type ImplicitAccountOutput struct { } func (o *ImplicitAccountOutput) ChainID() iotago.ChainID { - return iotago.EmptyAccountID() + return iotago.EmptyAccountID } From 4625179ab11b847c5faa9c88d79c63bc948bee11 Mon Sep 17 00:00:00 2001 From: jonastheis <4181434+jonastheis@users.noreply.github.com> Date: Thu, 5 Oct 2023 06:07:49 +0200 Subject: [PATCH 04/15] Add template and generation for SlotIdentifier --- gen/{gen_identifier.go => identifier_gen.go} | 2 +- gen/slot_identifier.tmpl | 202 +++++++++++++++++++ gen/slot_identifier_gen.go | 5 + 3 files changed, 208 insertions(+), 1 deletion(-) rename gen/{gen_identifier.go => identifier_gen.go} (85%) create mode 100644 gen/slot_identifier.tmpl create mode 100644 gen/slot_identifier_gen.go diff --git a/gen/gen_identifier.go b/gen/identifier_gen.go similarity index 85% rename from gen/gen_identifier.go rename to gen/identifier_gen.go index 291ffd0cd..89716ccdc 100644 --- a/gen/gen_identifier.go +++ b/gen/identifier_gen.go @@ -3,4 +3,4 @@ package gen //go:generate go run ./cmd identifier.tmpl ../identifier.gen.go Identifier i "" -//go:generate go run ./cmd identifier.tmpl ../identifier_account.gen.go AccountID a "output" +//go:generate go run ./cmd identifier.tmpl ../identifier_account.gen.go AccountID a "" diff --git a/gen/slot_identifier.tmpl b/gen/slot_identifier.tmpl new file mode 100644 index 000000000..cbfd5475e --- /dev/null +++ b/gen/slot_identifier.tmpl @@ -0,0 +1,202 @@ +package iotago + +// Code generated by go generate; DO NOT EDIT. Check gen/ directory instead. + +import ( +{{if index .Features "ids"}} "bytes" {{end}} + "encoding/binary" + "encoding/hex" + "fmt" + {{if index .Features "ids"}} "sort" {{end}} + "sync" + + "golang.org/x/crypto/blake2b" + + "github.com/iotaledger/iota.go/v4/hexutil" +) + +const ( + {{.Name}}Length = IdentifierLength + SlotIndexLength +) + +var ( + Empty{{.Name}} = {{.Name}}{} +) + +// {{.Name}} is a 32 byte hash value together with an 4 byte slot index. +type {{.Name}} [{{.Name}}Length]byte + +// {{.Name}}RepresentingData returns a new {{.Name}} for the given data by hashing it with blake2b and associating it with the given slot index. +func {{.Name}}RepresentingData(slot SlotIndex, data []byte) {{.Name}} { + return New{{.Name}}(slot, blake2b.Sum256(data)) +} + +func New{{.Name}}(slot SlotIndex, idBytes Identifier) {{.Name}} { + {{.Receiver}} := {{.Name}}{} + copy({{.Receiver}}[:], idBytes[:]) + binary.LittleEndian.PutUint32({{.Receiver}}[IdentifierLength:], uint32(slot)) + + return {{.Receiver}} +} + +// {{.Name}}FromHexString converts the hex to a {{.Name}} representation. +func {{.Name}}FromHexString(hex string) ({{.Name}}, error) { + bytes, err := hexutil.DecodeHex(hex) + if err != nil { + return {{.Name}}{}, err + } + + s, _, err := {{.Name}}FromBytes(bytes) + + return s, err +} + +// {{.Name}}FromBytes returns a new {{.Name}} represented by the passed bytes. +func {{.Name}}FromBytes(bytes []byte) ({{.Name}}, int, error) { + if len(bytes) < {{.Name}}Length { + return {{.Name}}{}, 0, ErrInvalidIdentifierLength + } + + return {{.Name}}(bytes), {{.Name}}Length, nil +} + +// Must{{.Name}}FromHexString converts the hex to a {{.Name}} representation. +func Must{{.Name}}FromHexString(hex string) {{.Name}} { + {{.Receiver}}, err := {{.Name}}FromHexString(hex) + if err != nil { + panic(err) + } + + return {{.Receiver}} +} + +func ({{.Receiver}} {{.Name}}) Bytes() ([]byte, error) { + return {{.Receiver}}[:], nil +} + +func ({{.Receiver}} {{.Name}}) MarshalText() (text []byte, err error) { + dst := make([]byte, hex.EncodedLen(len({{.Name}}{}))) + hex.Encode(dst, {{.Receiver}}[:]) + + return dst, nil +} + +func ({{.Receiver}} *{{.Name}}) UnmarshalText(text []byte) error { + _, err := hex.Decode({{.Receiver}}[:], text) + + return err +} + +// Empty tells whether the {{.Name}} is empty. +func ({{.Receiver}} {{.Name}}) Empty() bool { + return {{.Receiver}} == Empty{{.Name}} +} + +// ToHex converts the Identifier to its hex representation. +func ({{.Receiver}} {{.Name}}) ToHex() string { + return hexutil.EncodeHex({{.Receiver}}[:]) +} + +func ({{.Receiver}} {{.Name}}) String() string { + return fmt.Sprintf("%s:%d", {{.Receiver}}.Alias(), {{.Receiver}}.Slot()) +} + +func ({{.Receiver}} {{.Name}}) Slot() SlotIndex { + return SlotIndex(binary.LittleEndian.Uint32({{.Receiver}}[IdentifierLength:])) +} + +// Index returns a slot index to conform with hive's IndexedID interface. +func ({{.Receiver}} {{.Name}}) Index() SlotIndex { + return {{.Receiver}}.Slot() +} + +func ({{.Receiver}} {{.Name}}) Identifier() Identifier { + return Identifier({{.Receiver}}[:IdentifierLength]) +} + +var ( + // {{.Name}}Aliases contains a dictionary of identifiers associated to their human-readable alias. + {{.Name}}Aliases = make(map[{{.Name}}]string) + + // {{.Name}}AliasesMutex is the mutex that is used to synchronize access to the previous map. + {{.Name}}AliasesMutex = sync.RWMutex{} +) + +// RegisterAlias allows to register a human-readable alias for the Identifier which will be used as a replacement for +// the String method. +func ({{.Receiver}} {{.Name}}) RegisterAlias(alias string) { + {{.Name}}AliasesMutex.Lock() + defer {{.Name}}AliasesMutex.Unlock() + + {{.Name}}Aliases[{{.Receiver}}] = alias +} + +// Alias returns the human-readable alias of the Identifier (or the base58 encoded bytes of no alias was set). +func ({{.Receiver}} {{.Name}}) Alias() (alias string) { + {{.Name}}AliasesMutex.RLock() + defer {{.Name}}AliasesMutex.RUnlock() + + if existingAlias, exists := {{.Name}}Aliases[{{.Receiver}}]; exists { + return existingAlias + } + + return {{.Receiver}}.ToHex() +} + +// UnregisterAlias allows to unregister a previously registered alias. +func ({{.Receiver}} {{.Name}}) UnregisterAlias() { + {{.Name}}AliasesMutex.Lock() + defer {{.Name}}AliasesMutex.Unlock() + + delete({{.Name}}Aliases, {{.Receiver}}) +} + + +{{if index .Features "ids"}} + +type {{.Name}}s []{{.Name}} + +// ToHex converts the {{.Name}}s to their hex representation. +func (ids {{.Name}}s) ToHex() []string { + hexIDs := make([]string, len(ids)) + for i, {{.Receiver}} := range ids { + hexIDs[i] = hexutil.EncodeHex({{.Receiver}}[:]) + } + + return hexIDs +} + +// RemoveDupsAndSort removes duplicated {{.Name}}s and sorts the slice by the lexical ordering. +func (ids {{.Name}}s) RemoveDupsAndSort() {{.Name}}s { + sorted := append({{.Name}}s{}, ids...) + sort.Slice(sorted, func(i, j int) bool { + return bytes.Compare(sorted[i][:], sorted[j][:]) == -1 + }) + + var result {{.Name}}s + var prev {{.Name}} + for i, {{.Receiver}} := range sorted { + if i == 0 || !bytes.Equal(prev[:], {{.Receiver}}[:]) { + result = append(result, {{.Receiver}}) + } + prev = {{.Receiver}} + } + + return result +} + +// {{.Name}}sFromHexString converts the given block IDs from their hex to {{.Name}} representation. +func {{.Name}}sFromHexString({{.Name}}sHex []string) ({{.Name}}s, error) { + result := make({{.Name}}s, len({{.Name}}sHex)) + + for i, hexString := range {{.Name}}sHex { + {{.Name}}, err := {{.Name}}FromHexString(hexString) + if err != nil { + return nil, err + } + result[i] = {{.Name}} + } + + return result, nil +} +{{end}} diff --git a/gen/slot_identifier_gen.go b/gen/slot_identifier_gen.go new file mode 100644 index 000000000..b33322568 --- /dev/null +++ b/gen/slot_identifier_gen.go @@ -0,0 +1,5 @@ +//go:build ignore + +package gen + +//go:generate go run ./cmd slot_identifier.tmpl ../block_id.gen.go BlockID b "ids" From 808d42c7a991b9af6019bb87a7841cad3a28350d Mon Sep 17 00:00:00 2001 From: jonastheis <4181434+jonastheis@users.noreply.github.com> Date: Thu, 5 Oct 2023 06:08:25 +0200 Subject: [PATCH 05/15] Generate BlockID from template and fix all incompatibilities --- attestation.go | 6 +- block.go | 62 +-------- block_id.gen.go | 198 +++++++++++++++++++++++++++++ merklehasher/merkle_hasher_test.go | 14 +- nodeclient/http_api_client.go | 10 +- slot_identifier.go | 10 +- 6 files changed, 219 insertions(+), 81 deletions(-) create mode 100644 block_id.gen.go diff --git a/attestation.go b/attestation.go index ae620b799..3fd611144 100644 --- a/attestation.go +++ b/attestation.go @@ -74,18 +74,18 @@ func (a *Attestation) Compare(other *Attestation) int { func (a *Attestation) BlockID() (BlockID, error) { signatureBytes, err := a.API.Encode(a.Signature) if err != nil { - return EmptyBlockID(), ierrors.Errorf("failed to create blockID: %w", err) + return EmptyBlockID, ierrors.Errorf("failed to create blockID: %w", err) } headerHash, err := a.BlockHeader.Hash(a.API) if err != nil { - return EmptyBlockID(), ierrors.Errorf("failed to create blockID: %w", err) + return EmptyBlockID, ierrors.Errorf("failed to create blockID: %w", err) } id := blockIdentifier(headerHash, a.BlockHash, signatureBytes) slot := a.API.TimeProvider().SlotFromTime(a.IssuingTime) - return NewSlotIdentifier(slot, id), nil + return NewBlockID(slot, id), nil } func (a *Attestation) signingMessage() ([]byte, error) { diff --git a/block.go b/block.go index b10c030bb..b9fab4d33 100644 --- a/block.go +++ b/block.go @@ -1,11 +1,9 @@ package iotago import ( - "bytes" "context" "crypto/ed25519" "fmt" - "sort" "time" "golang.org/x/crypto/blake2b" @@ -16,12 +14,9 @@ import ( "github.com/iotaledger/hive.go/serializer/v2" "github.com/iotaledger/hive.go/serializer/v2/byteutils" "github.com/iotaledger/hive.go/serializer/v2/serix" - "github.com/iotaledger/iota.go/v4/hexutil" ) const ( - // BlockIDLength defines the length of a block ID. - BlockIDLength = SlotIdentifierLength // MaxBlockSize defines the maximum size of a block. MaxBlockSize = 32768 // BlockMaxParents defines the maximum amount of parents in a block. @@ -52,61 +47,6 @@ const ( BlockTypeValidation BlockType = 1 ) -// EmptyBlockID returns an empty BlockID. -func EmptyBlockID() BlockID { - return emptySlotIdentifier -} - -// BlockID is the ID of a Block. -type BlockID = SlotIdentifier - -// BlockIDs are IDs of blocks. -type BlockIDs []BlockID - -// ToHex converts the BlockIDs to their hex representation. -func (ids BlockIDs) ToHex() []string { - hexIDs := make([]string, len(ids)) - for i, id := range ids { - hexIDs[i] = hexutil.EncodeHex(id[:]) - } - - return hexIDs -} - -// RemoveDupsAndSort removes duplicated BlockIDs and sorts the slice by the lexical ordering. -func (ids BlockIDs) RemoveDupsAndSort() BlockIDs { - sorted := append(BlockIDs{}, ids...) - sort.Slice(sorted, func(i, j int) bool { - return bytes.Compare(sorted[i][:], sorted[j][:]) == -1 - }) - - var result BlockIDs - var prev BlockID - for i, id := range sorted { - if i == 0 || !bytes.Equal(prev[:], id[:]) { - result = append(result, id) - } - prev = id - } - - return result -} - -// BlockIDsFromHexString converts the given block IDs from their hex to BlockID representation. -func BlockIDsFromHexString(blockIDsHex []string) (BlockIDs, error) { - result := make(BlockIDs, len(blockIDsHex)) - - for i, hexString := range blockIDsHex { - blockID, err := SlotIdentifierFromHexString(hexString) - if err != nil { - return nil, err - } - result[i] = blockID - } - - return result, nil -} - type BlockPayload interface { Payload } @@ -255,7 +195,7 @@ func (b *ProtocolBlock) ID() (BlockID, error) { slot := b.API.TimeProvider().SlotFromTime(b.IssuingTime) - return NewSlotIdentifier(slot, id), nil + return NewBlockID(slot, id), nil } // MustID works like ID but panics if the BlockID can't be computed. diff --git a/block_id.gen.go b/block_id.gen.go new file mode 100644 index 000000000..ba5b3741f --- /dev/null +++ b/block_id.gen.go @@ -0,0 +1,198 @@ +package iotago + +// Code generated by go generate; DO NOT EDIT. Check gen/ directory instead. + +import ( + "bytes" + "encoding/binary" + "encoding/hex" + "fmt" + "sort" + "sync" + + "golang.org/x/crypto/blake2b" + + "github.com/iotaledger/iota.go/v4/hexutil" +) + +const ( + BlockIDLength = IdentifierLength + SlotIndexLength +) + +var ( + EmptyBlockID = BlockID{} +) + +// BlockID is a 32 byte hash value together with an 4 byte slot index. +type BlockID [BlockIDLength]byte + +// BlockIDRepresentingData returns a new BlockID for the given data by hashing it with blake2b and associating it with the given slot index. +func BlockIDRepresentingData(slot SlotIndex, data []byte) BlockID { + return NewBlockID(slot, blake2b.Sum256(data)) +} + +func NewBlockID(slot SlotIndex, idBytes Identifier) BlockID { + b := BlockID{} + copy(b[:], idBytes[:]) + binary.LittleEndian.PutUint32(b[IdentifierLength:], uint32(slot)) + + return b +} + +// BlockIDFromHexString converts the hex to a BlockID representation. +func BlockIDFromHexString(hex string) (BlockID, error) { + bytes, err := hexutil.DecodeHex(hex) + if err != nil { + return BlockID{}, err + } + + s, _, err := BlockIDFromBytes(bytes) + + return s, err +} + +// BlockIDFromBytes returns a new BlockID represented by the passed bytes. +func BlockIDFromBytes(bytes []byte) (BlockID, int, error) { + if len(bytes) < BlockIDLength { + return BlockID{}, 0, ErrInvalidIdentifierLength + } + + return BlockID(bytes), BlockIDLength, nil +} + +// MustBlockIDFromHexString converts the hex to a BlockID representation. +func MustBlockIDFromHexString(hex string) BlockID { + b, err := BlockIDFromHexString(hex) + if err != nil { + panic(err) + } + + return b +} + +func (b BlockID) Bytes() ([]byte, error) { + return b[:], nil +} + +func (b BlockID) MarshalText() (text []byte, err error) { + dst := make([]byte, hex.EncodedLen(len(BlockID{}))) + hex.Encode(dst, b[:]) + + return dst, nil +} + +func (b *BlockID) UnmarshalText(text []byte) error { + _, err := hex.Decode(b[:], text) + + return err +} + +// Empty tells whether the BlockID is empty. +func (b BlockID) Empty() bool { + return b == EmptyBlockID +} + +// ToHex converts the Identifier to its hex representation. +func (b BlockID) ToHex() string { + return hexutil.EncodeHex(b[:]) +} + +func (b BlockID) String() string { + return fmt.Sprintf("%s:%d", b.Alias(), b.Slot()) +} + +func (b BlockID) Slot() SlotIndex { + return SlotIndex(binary.LittleEndian.Uint32(b[IdentifierLength:])) +} + +// Index returns a slot index to conform with hive's IndexedID interface. +func (b BlockID) Index() SlotIndex { + return b.Slot() +} + +func (b BlockID) Identifier() Identifier { + return Identifier(b[:IdentifierLength]) +} + +var ( + // BlockIDAliases contains a dictionary of identifiers associated to their human-readable alias. + BlockIDAliases = make(map[BlockID]string) + + // BlockIDAliasesMutex is the mutex that is used to synchronize access to the previous map. + BlockIDAliasesMutex = sync.RWMutex{} +) + +// RegisterAlias allows to register a human-readable alias for the Identifier which will be used as a replacement for +// the String method. +func (b BlockID) RegisterAlias(alias string) { + BlockIDAliasesMutex.Lock() + defer BlockIDAliasesMutex.Unlock() + + BlockIDAliases[b] = alias +} + +// Alias returns the human-readable alias of the Identifier (or the base58 encoded bytes of no alias was set). +func (b BlockID) Alias() (alias string) { + BlockIDAliasesMutex.RLock() + defer BlockIDAliasesMutex.RUnlock() + + if existingAlias, exists := BlockIDAliases[b]; exists { + return existingAlias + } + + return b.ToHex() +} + +// UnregisterAlias allows to unregister a previously registered alias. +func (b BlockID) UnregisterAlias() { + BlockIDAliasesMutex.Lock() + defer BlockIDAliasesMutex.Unlock() + + delete(BlockIDAliases, b) +} + +type BlockIDs []BlockID + +// ToHex converts the BlockIDs to their hex representation. +func (ids BlockIDs) ToHex() []string { + hexIDs := make([]string, len(ids)) + for i, b := range ids { + hexIDs[i] = hexutil.EncodeHex(b[:]) + } + + return hexIDs +} + +// RemoveDupsAndSort removes duplicated BlockIDs and sorts the slice by the lexical ordering. +func (ids BlockIDs) RemoveDupsAndSort() BlockIDs { + sorted := append(BlockIDs{}, ids...) + sort.Slice(sorted, func(i, j int) bool { + return bytes.Compare(sorted[i][:], sorted[j][:]) == -1 + }) + + var result BlockIDs + var prev BlockID + for i, b := range sorted { + if i == 0 || !bytes.Equal(prev[:], b[:]) { + result = append(result, b) + } + prev = b + } + + return result +} + +// BlockIDsFromHexString converts the given block IDs from their hex to BlockID representation. +func BlockIDsFromHexString(BlockIDsHex []string) (BlockIDs, error) { + result := make(BlockIDs, len(BlockIDsHex)) + + for i, hexString := range BlockIDsHex { + BlockID, err := BlockIDFromHexString(hexString) + if err != nil { + return nil, err + } + result[i] = BlockID + } + + return result, nil +} diff --git a/merklehasher/merkle_hasher_test.go b/merklehasher/merkle_hasher_test.go index 76a5316d7..450b6fbc4 100644 --- a/merklehasher/merkle_hasher_test.go +++ b/merklehasher/merkle_hasher_test.go @@ -21,13 +21,13 @@ func TestMerkleHasher(t *testing.T) { // https://github.com/Wollac/iota-crypto-demo/tree/master/examples/merkle - includedBlocks = append(includedBlocks, iotago.MustSlotIdentifierFromHexString("0x52fdfc072182654f163f5f0f9a621d729566c74d10037c4d7bbb0407d1e2c64900000000")) - includedBlocks = append(includedBlocks, iotago.MustSlotIdentifierFromHexString("0x81855ad8681d0d86d1e91e00167939cb6694d2c422acd208a0072939487f699900000000")) - includedBlocks = append(includedBlocks, iotago.MustSlotIdentifierFromHexString("0xeb9d18a44784045d87f3c67cf22746e995af5a25367951baa2ff6cd471c483f100000000")) - includedBlocks = append(includedBlocks, iotago.MustSlotIdentifierFromHexString("0x5fb90badb37c5821b6d95526a41a9504680b4e7c8b763a1b1d49d4955c84862100000000")) - includedBlocks = append(includedBlocks, iotago.MustSlotIdentifierFromHexString("0x6325253fec738dd7a9e28bf921119c160f0702448615bbda08313f6a8eb668d200000000")) - includedBlocks = append(includedBlocks, iotago.MustSlotIdentifierFromHexString("0x0bf5059875921e668a5bdf2c7fc4844592d2572bcd0668d2d6c52f5054e2d08300000000")) - includedBlocks = append(includedBlocks, iotago.MustSlotIdentifierFromHexString("0x6bf84c7174cb7476364cc3dbd968b0f7172ed85794bb358b0c3b525da1786f9f00000000")) + includedBlocks = append(includedBlocks, iotago.MustBlockIDFromHexString("0x52fdfc072182654f163f5f0f9a621d729566c74d10037c4d7bbb0407d1e2c64900000000")) + includedBlocks = append(includedBlocks, iotago.MustBlockIDFromHexString("0x81855ad8681d0d86d1e91e00167939cb6694d2c422acd208a0072939487f699900000000")) + includedBlocks = append(includedBlocks, iotago.MustBlockIDFromHexString("0xeb9d18a44784045d87f3c67cf22746e995af5a25367951baa2ff6cd471c483f100000000")) + includedBlocks = append(includedBlocks, iotago.MustBlockIDFromHexString("0x5fb90badb37c5821b6d95526a41a9504680b4e7c8b763a1b1d49d4955c84862100000000")) + includedBlocks = append(includedBlocks, iotago.MustBlockIDFromHexString("0x6325253fec738dd7a9e28bf921119c160f0702448615bbda08313f6a8eb668d200000000")) + includedBlocks = append(includedBlocks, iotago.MustBlockIDFromHexString("0x0bf5059875921e668a5bdf2c7fc4844592d2572bcd0668d2d6c52f5054e2d08300000000")) + includedBlocks = append(includedBlocks, iotago.MustBlockIDFromHexString("0x6bf84c7174cb7476364cc3dbd968b0f7172ed85794bb358b0c3b525da1786f9f00000000")) hasher := merklehasher.NewHasher[iotago.BlockID](crypto.BLAKE2b_256) hash, err := hasher.HashValues(includedBlocks) diff --git a/nodeclient/http_api_client.go b/nodeclient/http_api_client.go index bb4841718..df52f4b00 100644 --- a/nodeclient/http_api_client.go +++ b/nodeclient/http_api_client.go @@ -443,24 +443,24 @@ func (client *Client) SubmitBlock(ctx context.Context, m *iotago.ProtocolBlock) apiForVersion, err := client.APIForVersion(m.ProtocolVersion) if err != nil { - return iotago.EmptyBlockID(), err + return iotago.EmptyBlockID, err } data, err := apiForVersion.Encode(m) if err != nil { - return iotago.EmptyBlockID(), err + return iotago.EmptyBlockID, err } req := &RawDataEnvelope{Data: data} //nolint:bodyclose res, err := client.Do(ctx, http.MethodPost, RouteBlocks, req, nil) if err != nil { - return iotago.EmptyBlockID(), err + return iotago.EmptyBlockID, err } - blockID, err := iotago.SlotIdentifierFromHexString(res.Header.Get(locationHeader)) + blockID, err := iotago.BlockIDFromHexString(res.Header.Get(locationHeader)) if err != nil { - return iotago.EmptyBlockID(), err + return iotago.EmptyBlockID, err } return blockID, nil diff --git a/slot_identifier.go b/slot_identifier.go index 9094eb7dd..5e9ee3b46 100644 --- a/slot_identifier.go +++ b/slot_identifier.go @@ -111,8 +111,8 @@ func (id SlotIdentifier) Identifier() Identifier { } var ( - // slotIidentifierAliases contains a dictionary of identifiers associated to their human-readable alias. - slotIidentifierAliases = make(map[SlotIdentifier]string) + // slotIdentifierAliases contains a dictionary of identifiers associated to their human-readable alias. + slotIdentifierAliases = make(map[SlotIdentifier]string) // slotIdentifierAliasesMutex is the mutex that is used to synchronize access to the previous map. slotIdentifierAliasesMutex = sync.RWMutex{} @@ -124,7 +124,7 @@ func (id SlotIdentifier) RegisterAlias(alias string) { slotIdentifierAliasesMutex.Lock() defer slotIdentifierAliasesMutex.Unlock() - slotIidentifierAliases[id] = alias + slotIdentifierAliases[id] = alias } // Alias returns the human-readable alias of the Identifier (or the base58 encoded bytes of no alias was set). @@ -132,7 +132,7 @@ func (id SlotIdentifier) Alias() (alias string) { slotIdentifierAliasesMutex.RLock() defer slotIdentifierAliasesMutex.RUnlock() - if existingAlias, exists := slotIidentifierAliases[id]; exists { + if existingAlias, exists := slotIdentifierAliases[id]; exists { return existingAlias } @@ -144,5 +144,5 @@ func (id SlotIdentifier) UnregisterAlias() { slotIdentifierAliasesMutex.Lock() defer slotIdentifierAliasesMutex.Unlock() - delete(slotIidentifierAliases, id) + delete(slotIdentifierAliases, id) } From 119d89c52fb0b54c43ede09ab16fde802eaf5040 Mon Sep 17 00:00:00 2001 From: jonastheis <4181434+jonastheis@users.noreply.github.com> Date: Thu, 5 Oct 2023 06:14:06 +0200 Subject: [PATCH 06/15] Generate CommitmentID from template and fix all incompatibilities --- block_test.go | 16 +-- commitment.go | 10 +- commitment_id.gen.go | 151 +++++++++++++++++++++++++++++ gen/slot_identifier_gen.go | 1 + nodeclient/http_api_client_test.go | 10 +- signed_transaction_test.go | 2 +- workscore_test.go | 2 +- 7 files changed, 168 insertions(+), 24 deletions(-) create mode 100644 commitment_id.gen.go diff --git a/block_test.go b/block_test.go index 74cc3eba8..d4b4fb20a 100644 --- a/block_test.go +++ b/block_test.go @@ -216,7 +216,7 @@ func TestProtocolBlock_TransactionCreationTime(t *testing.T) { }). AddOutput(output). SetCreationSlot(101). - AddContextInput(&iotago.CommitmentInput{CommitmentID: iotago.NewSlotIdentifier(78, tpkg.Rand32ByteArray())}). + AddContextInput(&iotago.CommitmentInput{CommitmentID: iotago.NewCommitmentID(78, tpkg.Rand32ByteArray())}). Build(iotago.NewInMemoryAddressSigner(iotago.AddressKeys{Address: addr, Keys: ed25519.PrivateKey(keyPair.PrivateKey[:])})) require.NoError(t, err) @@ -341,7 +341,7 @@ func TestProtocolBlock_TransactionCommitmentInput(t *testing.T) { Input: output, }). AddOutput(output). - AddContextInput(&iotago.CommitmentInput{CommitmentID: iotago.NewSlotIdentifier(78, tpkg.Rand32ByteArray())}). + AddContextInput(&iotago.CommitmentInput{CommitmentID: iotago.NewCommitmentID(78, tpkg.Rand32ByteArray())}). Build(iotago.NewInMemoryAddressSigner(iotago.AddressKeys{Address: addr, Keys: ed25519.PrivateKey(keyPair.PrivateKey[:])})) require.NoError(t, err) @@ -355,7 +355,7 @@ func TestProtocolBlock_TransactionCommitmentInput(t *testing.T) { Input: output, }). AddOutput(output). - AddContextInput(&iotago.CommitmentInput{CommitmentID: iotago.NewSlotIdentifier(90, tpkg.Rand32ByteArray())}). + AddContextInput(&iotago.CommitmentInput{CommitmentID: iotago.NewCommitmentID(90, tpkg.Rand32ByteArray())}). Build(iotago.NewInMemoryAddressSigner(iotago.AddressKeys{Address: addr, Keys: ed25519.PrivateKey(keyPair.PrivateKey[:])})) require.NoError(t, err) @@ -369,7 +369,7 @@ func TestProtocolBlock_TransactionCommitmentInput(t *testing.T) { Input: output, }). AddOutput(output). - AddContextInput(&iotago.CommitmentInput{CommitmentID: iotago.NewSlotIdentifier(85, tpkg.Rand32ByteArray())}). + AddContextInput(&iotago.CommitmentInput{CommitmentID: iotago.NewCommitmentID(85, tpkg.Rand32ByteArray())}). Build(iotago.NewInMemoryAddressSigner(iotago.AddressKeys{Address: addr, Keys: ed25519.PrivateKey(keyPair.PrivateKey[:])})) require.NoError(t, err) @@ -383,7 +383,7 @@ func TestProtocolBlock_TransactionCommitmentInput(t *testing.T) { Input: output, }). AddOutput(output). - AddContextInput(&iotago.CommitmentInput{CommitmentID: iotago.NewSlotIdentifier(79, tpkg.Rand32ByteArray())}). + AddContextInput(&iotago.CommitmentInput{CommitmentID: iotago.NewCommitmentID(79, tpkg.Rand32ByteArray())}). Build(iotago.NewInMemoryAddressSigner(iotago.AddressKeys{Address: addr, Keys: ed25519.PrivateKey(keyPair.PrivateKey[:])})) require.NoError(t, err) @@ -397,7 +397,7 @@ func TestProtocolBlock_TransactionCommitmentInput(t *testing.T) { Input: output, }). AddOutput(output). - AddContextInput(&iotago.CommitmentInput{CommitmentID: iotago.NewSlotIdentifier(79, tpkg.Rand32ByteArray())}). + AddContextInput(&iotago.CommitmentInput{CommitmentID: iotago.NewCommitmentID(79, tpkg.Rand32ByteArray())}). Build(iotago.NewInMemoryAddressSigner(iotago.AddressKeys{Address: addr, Keys: ed25519.PrivateKey(keyPair.PrivateKey[:])})) require.NoError(t, err) @@ -411,7 +411,7 @@ func TestProtocolBlock_TransactionCommitmentInput(t *testing.T) { Input: output, }). AddOutput(output). - AddContextInput(&iotago.CommitmentInput{CommitmentID: iotago.NewSlotIdentifier(89, tpkg.Rand32ByteArray())}). + AddContextInput(&iotago.CommitmentInput{CommitmentID: iotago.NewCommitmentID(89, tpkg.Rand32ByteArray())}). Build(iotago.NewInMemoryAddressSigner(iotago.AddressKeys{Address: addr, Keys: ed25519.PrivateKey(keyPair.PrivateKey[:])})) require.NoError(t, err) @@ -425,7 +425,7 @@ func TestProtocolBlock_TransactionCommitmentInput(t *testing.T) { Input: output, }). AddOutput(output). - AddContextInput(&iotago.CommitmentInput{CommitmentID: iotago.NewSlotIdentifier(85, tpkg.Rand32ByteArray())}). + AddContextInput(&iotago.CommitmentInput{CommitmentID: iotago.NewCommitmentID(85, tpkg.Rand32ByteArray())}). Build(iotago.NewInMemoryAddressSigner(iotago.AddressKeys{Address: addr, Keys: ed25519.PrivateKey(keyPair.PrivateKey[:])})) require.NoError(t, err) diff --git a/commitment.go b/commitment.go index 7091908d1..536ba6e95 100644 --- a/commitment.go +++ b/commitment.go @@ -9,14 +9,6 @@ import ( "github.com/iotaledger/hive.go/serializer/v2" ) -const ( - CommitmentIDLength = SlotIdentifierLength -) - -type CommitmentID = SlotIdentifier - -var EmptyCommitmentID = CommitmentID{} - type Commitment struct { ProtocolVersion Version `serix:"0,mapKey=protocolVersion"` Slot SlotIndex `serix:"1,mapKey=slot"` @@ -49,7 +41,7 @@ func (c *Commitment) ID() (CommitmentID, error) { return CommitmentID{}, ierrors.Errorf("failed to serialize commitment: %w", err) } - return SlotIdentifierRepresentingData(c.Slot, data), nil + return CommitmentIDRepresentingData(c.Slot, data), nil } func (c *Commitment) StateID() Identifier { diff --git a/commitment_id.gen.go b/commitment_id.gen.go new file mode 100644 index 000000000..03fe1cb7c --- /dev/null +++ b/commitment_id.gen.go @@ -0,0 +1,151 @@ +package iotago + +// Code generated by go generate; DO NOT EDIT. Check gen/ directory instead. + +import ( + "encoding/binary" + "encoding/hex" + "fmt" + + "sync" + + "golang.org/x/crypto/blake2b" + + "github.com/iotaledger/iota.go/v4/hexutil" +) + +const ( + CommitmentIDLength = IdentifierLength + SlotIndexLength +) + +var ( + EmptyCommitmentID = CommitmentID{} +) + +// CommitmentID is a 32 byte hash value together with an 4 byte slot index. +type CommitmentID [CommitmentIDLength]byte + +// CommitmentIDRepresentingData returns a new CommitmentID for the given data by hashing it with blake2b and associating it with the given slot index. +func CommitmentIDRepresentingData(slot SlotIndex, data []byte) CommitmentID { + return NewCommitmentID(slot, blake2b.Sum256(data)) +} + +func NewCommitmentID(slot SlotIndex, idBytes Identifier) CommitmentID { + c := CommitmentID{} + copy(c[:], idBytes[:]) + binary.LittleEndian.PutUint32(c[IdentifierLength:], uint32(slot)) + + return c +} + +// CommitmentIDFromHexString converts the hex to a CommitmentID representation. +func CommitmentIDFromHexString(hex string) (CommitmentID, error) { + bytes, err := hexutil.DecodeHex(hex) + if err != nil { + return CommitmentID{}, err + } + + s, _, err := CommitmentIDFromBytes(bytes) + + return s, err +} + +// CommitmentIDFromBytes returns a new CommitmentID represented by the passed bytes. +func CommitmentIDFromBytes(bytes []byte) (CommitmentID, int, error) { + if len(bytes) < CommitmentIDLength { + return CommitmentID{}, 0, ErrInvalidIdentifierLength + } + + return CommitmentID(bytes), CommitmentIDLength, nil +} + +// MustCommitmentIDFromHexString converts the hex to a CommitmentID representation. +func MustCommitmentIDFromHexString(hex string) CommitmentID { + c, err := CommitmentIDFromHexString(hex) + if err != nil { + panic(err) + } + + return c +} + +func (c CommitmentID) Bytes() ([]byte, error) { + return c[:], nil +} + +func (c CommitmentID) MarshalText() (text []byte, err error) { + dst := make([]byte, hex.EncodedLen(len(CommitmentID{}))) + hex.Encode(dst, c[:]) + + return dst, nil +} + +func (c *CommitmentID) UnmarshalText(text []byte) error { + _, err := hex.Decode(c[:], text) + + return err +} + +// Empty tells whether the CommitmentID is empty. +func (c CommitmentID) Empty() bool { + return c == EmptyCommitmentID +} + +// ToHex converts the Identifier to its hex representation. +func (c CommitmentID) ToHex() string { + return hexutil.EncodeHex(c[:]) +} + +func (c CommitmentID) String() string { + return fmt.Sprintf("%s:%d", c.Alias(), c.Slot()) +} + +func (c CommitmentID) Slot() SlotIndex { + return SlotIndex(binary.LittleEndian.Uint32(c[IdentifierLength:])) +} + +// Index returns a slot index to conform with hive's IndexedID interface. +func (c CommitmentID) Index() SlotIndex { + return c.Slot() +} + +func (c CommitmentID) Identifier() Identifier { + return Identifier(c[:IdentifierLength]) +} + +var ( + // CommitmentIDAliases contains a dictionary of identifiers associated to their human-readable alias. + CommitmentIDAliases = make(map[CommitmentID]string) + + // CommitmentIDAliasesMutex is the mutex that is used to synchronize access to the previous map. + CommitmentIDAliasesMutex = sync.RWMutex{} +) + +// RegisterAlias allows to register a human-readable alias for the Identifier which will be used as a replacement for +// the String method. +func (c CommitmentID) RegisterAlias(alias string) { + CommitmentIDAliasesMutex.Lock() + defer CommitmentIDAliasesMutex.Unlock() + + CommitmentIDAliases[c] = alias +} + +// Alias returns the human-readable alias of the Identifier (or the base58 encoded bytes of no alias was set). +func (c CommitmentID) Alias() (alias string) { + CommitmentIDAliasesMutex.RLock() + defer CommitmentIDAliasesMutex.RUnlock() + + if existingAlias, exists := CommitmentIDAliases[c]; exists { + return existingAlias + } + + return c.ToHex() +} + +// UnregisterAlias allows to unregister a previously registered alias. +func (c CommitmentID) UnregisterAlias() { + CommitmentIDAliasesMutex.Lock() + defer CommitmentIDAliasesMutex.Unlock() + + delete(CommitmentIDAliases, c) +} diff --git a/gen/slot_identifier_gen.go b/gen/slot_identifier_gen.go index b33322568..aca64eedb 100644 --- a/gen/slot_identifier_gen.go +++ b/gen/slot_identifier_gen.go @@ -3,3 +3,4 @@ package gen //go:generate go run ./cmd slot_identifier.tmpl ../block_id.gen.go BlockID b "ids" +//go:generate go run ./cmd slot_identifier.tmpl ../commitment_id.gen.go CommitmentID c "" diff --git a/nodeclient/http_api_client_test.go b/nodeclient/http_api_client_test.go index dc20b7687..5e2e98e37 100644 --- a/nodeclient/http_api_client_test.go +++ b/nodeclient/http_api_client_test.go @@ -176,7 +176,7 @@ func TestClient_BlockIssuance(t *testing.T) { LatestFinalizedSlot: iotago.SlotIndex(20), } - prevID, err := iotago.SlotIdentifierFromHexString(hexutil.EncodeHex(tpkg.RandBytes(40))) + prevID, err := iotago.CommitmentIDFromHexString(hexutil.EncodeHex(tpkg.RandBytes(40))) require.NoError(t, err) rootsID, err := iotago.IdentifierFromHexString(hexutil.EncodeHex(tpkg.RandBytes(32))) require.NoError(t, err) @@ -484,8 +484,8 @@ func TestClient_CommitmentByID(t *testing.T) { var slot iotago.SlotIndex = 5 - commitmentID := iotago.NewSlotIdentifier(slot, tpkg.Rand32ByteArray()) - commitment := iotago.NewCommitment(mockAPI.Version(), slot, iotago.NewSlotIdentifier(slot-1, tpkg.Rand32ByteArray()), tpkg.Rand32ByteArray(), tpkg.RandUint64(math.MaxUint64), tpkg.RandMana(iotago.MaxMana)) + commitmentID := iotago.NewCommitmentID(slot, tpkg.Rand32ByteArray()) + commitment := iotago.NewCommitment(mockAPI.Version(), slot, iotago.NewCommitmentID(slot-1, tpkg.Rand32ByteArray()), tpkg.Rand32ByteArray(), tpkg.RandUint64(math.MaxUint64), tpkg.RandMana(iotago.MaxMana)) originRes := &iotago.Commitment{ Slot: commitment.Slot, @@ -505,7 +505,7 @@ func TestClient_CommitmentByID(t *testing.T) { func TestClient_CommitmentUTXOChangesByID(t *testing.T) { defer gock.Off() - commitmentID := iotago.NewSlotIdentifier(5, tpkg.Rand32ByteArray()) + commitmentID := iotago.NewCommitmentID(5, tpkg.Rand32ByteArray()) randCreatedOutput := tpkg.RandUTXOInput() randConsumedOutput := tpkg.RandUTXOInput() @@ -533,7 +533,7 @@ func TestClient_CommitmentByIndex(t *testing.T) { var slot iotago.SlotIndex = 1337 - commitment := iotago.NewCommitment(mockAPI.Version(), slot, iotago.NewSlotIdentifier(slot-1, tpkg.Rand32ByteArray()), tpkg.Rand32ByteArray(), tpkg.RandUint64(math.MaxUint64), tpkg.RandMana(iotago.MaxMana)) + commitment := iotago.NewCommitment(mockAPI.Version(), slot, iotago.NewCommitmentID(slot-1, tpkg.Rand32ByteArray()), tpkg.Rand32ByteArray(), tpkg.RandUint64(math.MaxUint64), tpkg.RandMana(iotago.MaxMana)) originRes := &iotago.Commitment{ Slot: commitment.Slot, diff --git a/signed_transaction_test.go b/signed_transaction_test.go index 18197ebea..0d1e996dd 100644 --- a/signed_transaction_test.go +++ b/signed_transaction_test.go @@ -207,7 +207,7 @@ func TestTransaction_InputTypes(t *testing.T) { } commitmentInput1 := &iotago.CommitmentInput{ - CommitmentID: iotago.SlotIdentifierRepresentingData(10, tpkg.RandBytes(32)), + CommitmentID: iotago.CommitmentIDRepresentingData(10, tpkg.RandBytes(32)), } bicInput1 := &iotago.BlockIssuanceCreditInput{ diff --git a/workscore_test.go b/workscore_test.go index 173a89eb8..697d9eee3 100644 --- a/workscore_test.go +++ b/workscore_test.go @@ -76,7 +76,7 @@ func TestTransactionEssenceWorkScore(t *testing.T) { }). AddOutput(output1). AddOutput(output2). - AddContextInput(&iotago.CommitmentInput{CommitmentID: iotago.NewSlotIdentifier(85, tpkg.Rand32ByteArray())}). + AddContextInput(&iotago.CommitmentInput{CommitmentID: iotago.NewCommitmentID(85, tpkg.Rand32ByteArray())}). AddContextInput(&iotago.BlockIssuanceCreditInput{AccountID: tpkg.RandAccountID()}). AddContextInput(&iotago.RewardInput{Index: 0}). IncreaseAllotment(tpkg.RandAccountID(), tpkg.RandMana(10000)+1). From f2d561de5a2fb0d8af71e9b567ed7643bb4a71c3 Mon Sep 17 00:00:00 2001 From: jonastheis <4181434+jonastheis@users.noreply.github.com> Date: Thu, 5 Oct 2023 13:20:17 +0200 Subject: [PATCH 07/15] Update template to include error --- block_id.gen.go | 17 ++++++++++------- commitment_id.gen.go | 17 ++++++++++------- gen/cmd/cmd.go | 2 +- gen/slot_identifier.tmpl | 17 ++++++++++------- 4 files changed, 31 insertions(+), 22 deletions(-) diff --git a/block_id.gen.go b/block_id.gen.go index ba5b3741f..df704787a 100644 --- a/block_id.gen.go +++ b/block_id.gen.go @@ -12,6 +12,7 @@ import ( "golang.org/x/crypto/blake2b" + "github.com/iotaledger/hive.go/ierrors" "github.com/iotaledger/iota.go/v4/hexutil" ) @@ -20,6 +21,8 @@ const ( ) var ( + ErrInvalidBlockIDLength = ierrors.New("invalid blockID length") + EmptyBlockID = BlockID{} ) @@ -41,23 +44,23 @@ func NewBlockID(slot SlotIndex, idBytes Identifier) BlockID { // BlockIDFromHexString converts the hex to a BlockID representation. func BlockIDFromHexString(hex string) (BlockID, error) { - bytes, err := hexutil.DecodeHex(hex) + b, err := hexutil.DecodeHex(hex) if err != nil { return BlockID{}, err } - s, _, err := BlockIDFromBytes(bytes) + s, _, err := BlockIDFromBytes(b) return s, err } // BlockIDFromBytes returns a new BlockID represented by the passed bytes. -func BlockIDFromBytes(bytes []byte) (BlockID, int, error) { - if len(bytes) < BlockIDLength { - return BlockID{}, 0, ErrInvalidIdentifierLength +func BlockIDFromBytes(b []byte) (BlockID, int, error) { + if len(b) < BlockIDLength { + return BlockID{}, 0, ErrInvalidBlockIDLength } - return BlockID(bytes), BlockIDLength, nil + return BlockID(b), BlockIDLength, nil } // MustBlockIDFromHexString converts the hex to a BlockID representation. @@ -98,7 +101,7 @@ func (b BlockID) ToHex() string { } func (b BlockID) String() string { - return fmt.Sprintf("%s:%d", b.Alias(), b.Slot()) + return fmt.Sprintf("BlockID(%s:%d)", b.Alias(), b.Slot()) } func (b BlockID) Slot() SlotIndex { diff --git a/commitment_id.gen.go b/commitment_id.gen.go index 03fe1cb7c..bdd3150fe 100644 --- a/commitment_id.gen.go +++ b/commitment_id.gen.go @@ -11,6 +11,7 @@ import ( "golang.org/x/crypto/blake2b" + "github.com/iotaledger/hive.go/ierrors" "github.com/iotaledger/iota.go/v4/hexutil" ) @@ -19,6 +20,8 @@ const ( ) var ( + ErrInvalidCommitmentIDLength = ierrors.New("invalid commitmentID length") + EmptyCommitmentID = CommitmentID{} ) @@ -40,23 +43,23 @@ func NewCommitmentID(slot SlotIndex, idBytes Identifier) CommitmentID { // CommitmentIDFromHexString converts the hex to a CommitmentID representation. func CommitmentIDFromHexString(hex string) (CommitmentID, error) { - bytes, err := hexutil.DecodeHex(hex) + b, err := hexutil.DecodeHex(hex) if err != nil { return CommitmentID{}, err } - s, _, err := CommitmentIDFromBytes(bytes) + s, _, err := CommitmentIDFromBytes(b) return s, err } // CommitmentIDFromBytes returns a new CommitmentID represented by the passed bytes. -func CommitmentIDFromBytes(bytes []byte) (CommitmentID, int, error) { - if len(bytes) < CommitmentIDLength { - return CommitmentID{}, 0, ErrInvalidIdentifierLength +func CommitmentIDFromBytes(b []byte) (CommitmentID, int, error) { + if len(b) < CommitmentIDLength { + return CommitmentID{}, 0, ErrInvalidCommitmentIDLength } - return CommitmentID(bytes), CommitmentIDLength, nil + return CommitmentID(b), CommitmentIDLength, nil } // MustCommitmentIDFromHexString converts the hex to a CommitmentID representation. @@ -97,7 +100,7 @@ func (c CommitmentID) ToHex() string { } func (c CommitmentID) String() string { - return fmt.Sprintf("%s:%d", c.Alias(), c.Slot()) + return fmt.Sprintf("CommitmentID(%s:%d)", c.Alias(), c.Slot()) } func (c CommitmentID) Slot() SlotIndex { diff --git a/gen/cmd/cmd.go b/gen/cmd/cmd.go index 9b11161e6..5f5f7d007 100644 --- a/gen/cmd/cmd.go +++ b/gen/cmd/cmd.go @@ -28,7 +28,7 @@ func main() { funcs := template.FuncMap{ "firstLower": func(s string) string { - return strings.ToLower(s[0:]) + s[:1] + return strings.ToLower(s[0:1]) + s[1:] }, } diff --git a/gen/slot_identifier.tmpl b/gen/slot_identifier.tmpl index cbfd5475e..40246518f 100644 --- a/gen/slot_identifier.tmpl +++ b/gen/slot_identifier.tmpl @@ -12,6 +12,7 @@ import ( "golang.org/x/crypto/blake2b" + "github.com/iotaledger/hive.go/ierrors" "github.com/iotaledger/iota.go/v4/hexutil" ) @@ -20,6 +21,8 @@ const ( ) var ( + ErrInvalid{{.Name}}Length = ierrors.New("invalid {{firstLower .Name}} length") + Empty{{.Name}} = {{.Name}}{} ) @@ -41,23 +44,23 @@ func New{{.Name}}(slot SlotIndex, idBytes Identifier) {{.Name}} { // {{.Name}}FromHexString converts the hex to a {{.Name}} representation. func {{.Name}}FromHexString(hex string) ({{.Name}}, error) { - bytes, err := hexutil.DecodeHex(hex) + b, err := hexutil.DecodeHex(hex) if err != nil { return {{.Name}}{}, err } - s, _, err := {{.Name}}FromBytes(bytes) + s, _, err := {{.Name}}FromBytes(b) return s, err } // {{.Name}}FromBytes returns a new {{.Name}} represented by the passed bytes. -func {{.Name}}FromBytes(bytes []byte) ({{.Name}}, int, error) { - if len(bytes) < {{.Name}}Length { - return {{.Name}}{}, 0, ErrInvalidIdentifierLength +func {{.Name}}FromBytes(b []byte) ({{.Name}}, int, error) { + if len(b) < {{.Name}}Length { + return {{.Name}}{}, 0, ErrInvalid{{.Name}}Length } - return {{.Name}}(bytes), {{.Name}}Length, nil + return {{.Name}}(b), {{.Name}}Length, nil } // Must{{.Name}}FromHexString converts the hex to a {{.Name}} representation. @@ -98,7 +101,7 @@ func ({{.Receiver}} {{.Name}}) ToHex() string { } func ({{.Receiver}} {{.Name}}) String() string { - return fmt.Sprintf("%s:%d", {{.Receiver}}.Alias(), {{.Receiver}}.Slot()) + return fmt.Sprintf("{{.Name}}(%s:%d)", {{.Receiver}}.Alias(), {{.Receiver}}.Slot()) } func ({{.Receiver}} {{.Name}}) Slot() SlotIndex { From 2f6977a17709fa553cefeb209ee18cc2c3bf6a03 Mon Sep 17 00:00:00 2001 From: jonastheis <4181434+jonastheis@users.noreply.github.com> Date: Thu, 5 Oct 2023 13:26:12 +0200 Subject: [PATCH 08/15] Generate TransactionID from template and fix all incompatibilities --- gen/slot_identifier_gen.go | 1 + output_test.go | 2 +- transaction_id.gen.go | 201 +++++++++++++++++++++++++++++++++++++ transaction_id.go | 153 ---------------------------- 4 files changed, 203 insertions(+), 154 deletions(-) create mode 100644 transaction_id.gen.go delete mode 100644 transaction_id.go diff --git a/gen/slot_identifier_gen.go b/gen/slot_identifier_gen.go index aca64eedb..14328dd23 100644 --- a/gen/slot_identifier_gen.go +++ b/gen/slot_identifier_gen.go @@ -4,3 +4,4 @@ package gen //go:generate go run ./cmd slot_identifier.tmpl ../block_id.gen.go BlockID b "ids" //go:generate go run ./cmd slot_identifier.tmpl ../commitment_id.gen.go CommitmentID c "" +//go:generate go run ./cmd slot_identifier.tmpl ../transaction_id.gen.go TransactionID t "ids" diff --git a/output_test.go b/output_test.go index c9addcd03..2d3bb5aca 100644 --- a/output_test.go +++ b/output_test.go @@ -67,7 +67,7 @@ func TestOutputIDString(t *testing.T) { outputID iotago.OutputID outputTypeString string }{ - {outputID: iotago.OutputIDFromTransactionIDAndIndex(lo.PanicOnErr(iotago.TransactionIDFromHexString("0xbaadf00ddeadbeefc8ed3cbe4acb99aeb94515ad89a6228f3f5d8f82dec429df135adafc")), 1), outputTypeString: "OutputID(0xbaadf00ddeadbeefc8ed3cbe4acb99aeb94515ad89a6228f3f5d8f82dec429df135adafc:4242168339:1)"}, + {outputID: iotago.OutputIDFromTransactionIDAndIndex(lo.PanicOnErr(iotago.TransactionIDFromHexString("0xbaadf00ddeadbeefc8ed3cbe4acb99aeb94515ad89a6228f3f5d8f82dec429df135adafc")), 1), outputTypeString: "OutputID(TransactionID(0xbaadf00ddeadbeefc8ed3cbe4acb99aeb94515ad89a6228f3f5d8f82dec429df135adafc:4242168339):1)"}, } for _, tt := range tests { require.Equal(t, tt.outputID.String(), tt.outputTypeString) diff --git a/transaction_id.gen.go b/transaction_id.gen.go new file mode 100644 index 000000000..ed8eadadd --- /dev/null +++ b/transaction_id.gen.go @@ -0,0 +1,201 @@ +package iotago + +// Code generated by go generate; DO NOT EDIT. Check gen/ directory instead. + +import ( + "bytes" + "encoding/binary" + "encoding/hex" + "fmt" + "sort" + "sync" + + "golang.org/x/crypto/blake2b" + + "github.com/iotaledger/hive.go/ierrors" + "github.com/iotaledger/iota.go/v4/hexutil" +) + +const ( + TransactionIDLength = IdentifierLength + SlotIndexLength +) + +var ( + ErrInvalidTransactionIDLength = ierrors.New("invalid transactionID length") + + EmptyTransactionID = TransactionID{} +) + +// TransactionID is a 32 byte hash value together with an 4 byte slot index. +type TransactionID [TransactionIDLength]byte + +// TransactionIDRepresentingData returns a new TransactionID for the given data by hashing it with blake2b and associating it with the given slot index. +func TransactionIDRepresentingData(slot SlotIndex, data []byte) TransactionID { + return NewTransactionID(slot, blake2b.Sum256(data)) +} + +func NewTransactionID(slot SlotIndex, idBytes Identifier) TransactionID { + t := TransactionID{} + copy(t[:], idBytes[:]) + binary.LittleEndian.PutUint32(t[IdentifierLength:], uint32(slot)) + + return t +} + +// TransactionIDFromHexString converts the hex to a TransactionID representation. +func TransactionIDFromHexString(hex string) (TransactionID, error) { + b, err := hexutil.DecodeHex(hex) + if err != nil { + return TransactionID{}, err + } + + s, _, err := TransactionIDFromBytes(b) + + return s, err +} + +// TransactionIDFromBytes returns a new TransactionID represented by the passed bytes. +func TransactionIDFromBytes(b []byte) (TransactionID, int, error) { + if len(b) < TransactionIDLength { + return TransactionID{}, 0, ErrInvalidTransactionIDLength + } + + return TransactionID(b), TransactionIDLength, nil +} + +// MustTransactionIDFromHexString converts the hex to a TransactionID representation. +func MustTransactionIDFromHexString(hex string) TransactionID { + t, err := TransactionIDFromHexString(hex) + if err != nil { + panic(err) + } + + return t +} + +func (t TransactionID) Bytes() ([]byte, error) { + return t[:], nil +} + +func (t TransactionID) MarshalText() (text []byte, err error) { + dst := make([]byte, hex.EncodedLen(len(TransactionID{}))) + hex.Encode(dst, t[:]) + + return dst, nil +} + +func (t *TransactionID) UnmarshalText(text []byte) error { + _, err := hex.Decode(t[:], text) + + return err +} + +// Empty tells whether the TransactionID is empty. +func (t TransactionID) Empty() bool { + return t == EmptyTransactionID +} + +// ToHex converts the Identifier to its hex representation. +func (t TransactionID) ToHex() string { + return hexutil.EncodeHex(t[:]) +} + +func (t TransactionID) String() string { + return fmt.Sprintf("TransactionID(%s:%d)", t.Alias(), t.Slot()) +} + +func (t TransactionID) Slot() SlotIndex { + return SlotIndex(binary.LittleEndian.Uint32(t[IdentifierLength:])) +} + +// Index returns a slot index to conform with hive's IndexedID interface. +func (t TransactionID) Index() SlotIndex { + return t.Slot() +} + +func (t TransactionID) Identifier() Identifier { + return Identifier(t[:IdentifierLength]) +} + +var ( + // TransactionIDAliases contains a dictionary of identifiers associated to their human-readable alias. + TransactionIDAliases = make(map[TransactionID]string) + + // TransactionIDAliasesMutex is the mutex that is used to synchronize access to the previous map. + TransactionIDAliasesMutex = sync.RWMutex{} +) + +// RegisterAlias allows to register a human-readable alias for the Identifier which will be used as a replacement for +// the String method. +func (t TransactionID) RegisterAlias(alias string) { + TransactionIDAliasesMutex.Lock() + defer TransactionIDAliasesMutex.Unlock() + + TransactionIDAliases[t] = alias +} + +// Alias returns the human-readable alias of the Identifier (or the base58 encoded bytes of no alias was set). +func (t TransactionID) Alias() (alias string) { + TransactionIDAliasesMutex.RLock() + defer TransactionIDAliasesMutex.RUnlock() + + if existingAlias, exists := TransactionIDAliases[t]; exists { + return existingAlias + } + + return t.ToHex() +} + +// UnregisterAlias allows to unregister a previously registered alias. +func (t TransactionID) UnregisterAlias() { + TransactionIDAliasesMutex.Lock() + defer TransactionIDAliasesMutex.Unlock() + + delete(TransactionIDAliases, t) +} + +type TransactionIDs []TransactionID + +// ToHex converts the TransactionIDs to their hex representation. +func (ids TransactionIDs) ToHex() []string { + hexIDs := make([]string, len(ids)) + for i, t := range ids { + hexIDs[i] = hexutil.EncodeHex(t[:]) + } + + return hexIDs +} + +// RemoveDupsAndSort removes duplicated TransactionIDs and sorts the slice by the lexical ordering. +func (ids TransactionIDs) RemoveDupsAndSort() TransactionIDs { + sorted := append(TransactionIDs{}, ids...) + sort.Slice(sorted, func(i, j int) bool { + return bytes.Compare(sorted[i][:], sorted[j][:]) == -1 + }) + + var result TransactionIDs + var prev TransactionID + for i, t := range sorted { + if i == 0 || !bytes.Equal(prev[:], t[:]) { + result = append(result, t) + } + prev = t + } + + return result +} + +// TransactionIDsFromHexString converts the given block IDs from their hex to TransactionID representation. +func TransactionIDsFromHexString(TransactionIDsHex []string) (TransactionIDs, error) { + result := make(TransactionIDs, len(TransactionIDsHex)) + + for i, hexString := range TransactionIDsHex { + TransactionID, err := TransactionIDFromHexString(hexString) + if err != nil { + return nil, err + } + result[i] = TransactionID + } + + return result, nil +} diff --git a/transaction_id.go b/transaction_id.go deleted file mode 100644 index 2f95d1ee2..000000000 --- a/transaction_id.go +++ /dev/null @@ -1,153 +0,0 @@ -package iotago - -import ( - "encoding/binary" - "encoding/hex" - "fmt" - "sync" - - "golang.org/x/crypto/blake2b" - - "github.com/iotaledger/iota.go/v4/hexutil" -) - -const ( - TransactionIDLength = IdentifierLength + SlotIndexLength -) - -var ( - emptyTransactionID = TransactionID{} -) - -// TransactionID is a 32 byte hash value that can be used to uniquely identify some blob of data together with an 4 byte slot index. -type TransactionID [TransactionIDLength]byte - -// TransactionIDRepresentingData returns a new TransactionID for the given data by hashing it with blake2b and associating it with the given slot index. -func TransactionIDRepresentingData(slot SlotIndex, data []byte) TransactionID { - return NewTransactionID(slot, blake2b.Sum256(data)) -} - -func NewTransactionID(slot SlotIndex, idBytes Identifier) TransactionID { - id := TransactionID{} - copy(id[:], idBytes[:]) - binary.LittleEndian.PutUint32(id[IdentifierLength:], uint32(slot)) - - return id -} - -// TransactionIDFromHexString converts the hex to a TransactionID representation. -func TransactionIDFromHexString(hex string) (TransactionID, error) { - bytes, err := hexutil.DecodeHex(hex) - if err != nil { - return TransactionID{}, err - } - - s, _, err := TransactionIDFromBytes(bytes) - - return s, err -} - -// TransactionIDFromBytes returns a new TransactionID represented by the passed bytes. -func TransactionIDFromBytes(bytes []byte) (TransactionID, int, error) { - if len(bytes) < TransactionIDLength { - return TransactionID{}, 0, ErrInvalidIdentifierLength - } - - return TransactionID(bytes), TransactionIDLength, nil -} - -// MustTransactionIDFromHexString converts the hex to a TransactionID representation. -func MustTransactionIDFromHexString(hex string) TransactionID { - id, err := TransactionIDFromHexString(hex) - if err != nil { - panic(err) - } - - return id -} - -func (id TransactionID) Bytes() ([]byte, error) { - return id[:], nil -} - -func (id TransactionID) MarshalText() (text []byte, err error) { - dst := make([]byte, hex.EncodedLen(len(TransactionID{}))) - hex.Encode(dst, id[:]) - - return dst, nil -} - -func (id *TransactionID) UnmarshalText(text []byte) error { - _, err := hex.Decode(id[:], text) - - return err -} - -// Empty tells whether the Identifier is empty. -func (id TransactionID) Empty() bool { - return id == emptyTransactionID -} - -// ToHex converts the Identifier to its hex representation. -func (id TransactionID) ToHex() string { - return hexutil.EncodeHex(id[:]) -} - -func (id TransactionID) String() string { - return fmt.Sprintf("%s:%d", id.Alias(), id.Slot()) -} - -func (id TransactionID) Slot() SlotIndex { - return SlotIndex(binary.LittleEndian.Uint32(id[IdentifierLength:])) -} - -// Index returns a slot index to conform with hive's IndexedID interface. -func (id TransactionID) Index() SlotIndex { - return id.Slot() -} - -func (id TransactionID) Identifier() Identifier { - return Identifier(id[:IdentifierLength]) -} - -var ( - // transactionIDAliases contains a dictionary of identifiers associated to their human-readable alias. - transactionIDAliases = make(map[TransactionID]string) - - // transactionIDAliasesMutex is the mutex that is used to synchronize access to the previous map. - transactionIDAliasesMutex = sync.RWMutex{} -) - -// RegisterAlias allows to register a human-readable alias for the Identifier which will be used as a replacement for -// the String method. -func (id TransactionID) RegisterAlias(alias string) { - transactionIDAliasesMutex.Lock() - defer transactionIDAliasesMutex.Unlock() - - transactionIDAliases[id] = alias -} - -// Alias returns the human-readable alias of the Identifier (or the base58 encoded bytes of no alias was set). -func (id TransactionID) Alias() (alias string) { - transactionIDAliasesMutex.RLock() - defer transactionIDAliasesMutex.RUnlock() - - if existingAlias, exists := transactionIDAliases[id]; exists { - return existingAlias - } - - return id.ToHex() -} - -// UnregisterAlias allows to unregister a previously registered alias. -func (id TransactionID) UnregisterAlias() { - transactionIDAliasesMutex.Lock() - defer transactionIDAliasesMutex.Unlock() - - delete(transactionIDAliases, id) -} - -var EmptyTransactionID = TransactionID{} - -// TransactionIDs are IDs of transactions. -type TransactionIDs []TransactionID From bcf1805224144fb1ca97061e0b425d2076936bd4 Mon Sep 17 00:00:00 2001 From: jonastheis <4181434+jonastheis@users.noreply.github.com> Date: Thu, 5 Oct 2023 13:28:00 +0200 Subject: [PATCH 09/15] Generate SignedTransactionID from template and fix all incompatibilities --- gen/slot_identifier_gen.go | 1 + signed_transaction_id.gen.go | 201 +++++++++++++++++++++++++++++++++++ signed_transaction_id.go | 154 --------------------------- 3 files changed, 202 insertions(+), 154 deletions(-) create mode 100644 signed_transaction_id.gen.go delete mode 100644 signed_transaction_id.go diff --git a/gen/slot_identifier_gen.go b/gen/slot_identifier_gen.go index 14328dd23..5478ac697 100644 --- a/gen/slot_identifier_gen.go +++ b/gen/slot_identifier_gen.go @@ -5,3 +5,4 @@ package gen //go:generate go run ./cmd slot_identifier.tmpl ../block_id.gen.go BlockID b "ids" //go:generate go run ./cmd slot_identifier.tmpl ../commitment_id.gen.go CommitmentID c "" //go:generate go run ./cmd slot_identifier.tmpl ../transaction_id.gen.go TransactionID t "ids" +//go:generate go run ./cmd slot_identifier.tmpl ../signed_transaction_id.gen.go SignedTransactionID t "ids" diff --git a/signed_transaction_id.gen.go b/signed_transaction_id.gen.go new file mode 100644 index 000000000..35973505a --- /dev/null +++ b/signed_transaction_id.gen.go @@ -0,0 +1,201 @@ +package iotago + +// Code generated by go generate; DO NOT EDIT. Check gen/ directory instead. + +import ( + "bytes" + "encoding/binary" + "encoding/hex" + "fmt" + "sort" + "sync" + + "golang.org/x/crypto/blake2b" + + "github.com/iotaledger/hive.go/ierrors" + "github.com/iotaledger/iota.go/v4/hexutil" +) + +const ( + SignedTransactionIDLength = IdentifierLength + SlotIndexLength +) + +var ( + ErrInvalidSignedTransactionIDLength = ierrors.New("invalid signedTransactionID length") + + EmptySignedTransactionID = SignedTransactionID{} +) + +// SignedTransactionID is a 32 byte hash value together with an 4 byte slot index. +type SignedTransactionID [SignedTransactionIDLength]byte + +// SignedTransactionIDRepresentingData returns a new SignedTransactionID for the given data by hashing it with blake2b and associating it with the given slot index. +func SignedTransactionIDRepresentingData(slot SlotIndex, data []byte) SignedTransactionID { + return NewSignedTransactionID(slot, blake2b.Sum256(data)) +} + +func NewSignedTransactionID(slot SlotIndex, idBytes Identifier) SignedTransactionID { + t := SignedTransactionID{} + copy(t[:], idBytes[:]) + binary.LittleEndian.PutUint32(t[IdentifierLength:], uint32(slot)) + + return t +} + +// SignedTransactionIDFromHexString converts the hex to a SignedTransactionID representation. +func SignedTransactionIDFromHexString(hex string) (SignedTransactionID, error) { + b, err := hexutil.DecodeHex(hex) + if err != nil { + return SignedTransactionID{}, err + } + + s, _, err := SignedTransactionIDFromBytes(b) + + return s, err +} + +// SignedTransactionIDFromBytes returns a new SignedTransactionID represented by the passed bytes. +func SignedTransactionIDFromBytes(b []byte) (SignedTransactionID, int, error) { + if len(b) < SignedTransactionIDLength { + return SignedTransactionID{}, 0, ErrInvalidSignedTransactionIDLength + } + + return SignedTransactionID(b), SignedTransactionIDLength, nil +} + +// MustSignedTransactionIDFromHexString converts the hex to a SignedTransactionID representation. +func MustSignedTransactionIDFromHexString(hex string) SignedTransactionID { + t, err := SignedTransactionIDFromHexString(hex) + if err != nil { + panic(err) + } + + return t +} + +func (t SignedTransactionID) Bytes() ([]byte, error) { + return t[:], nil +} + +func (t SignedTransactionID) MarshalText() (text []byte, err error) { + dst := make([]byte, hex.EncodedLen(len(SignedTransactionID{}))) + hex.Encode(dst, t[:]) + + return dst, nil +} + +func (t *SignedTransactionID) UnmarshalText(text []byte) error { + _, err := hex.Decode(t[:], text) + + return err +} + +// Empty tells whether the SignedTransactionID is empty. +func (t SignedTransactionID) Empty() bool { + return t == EmptySignedTransactionID +} + +// ToHex converts the Identifier to its hex representation. +func (t SignedTransactionID) ToHex() string { + return hexutil.EncodeHex(t[:]) +} + +func (t SignedTransactionID) String() string { + return fmt.Sprintf("SignedTransactionID(%s:%d)", t.Alias(), t.Slot()) +} + +func (t SignedTransactionID) Slot() SlotIndex { + return SlotIndex(binary.LittleEndian.Uint32(t[IdentifierLength:])) +} + +// Index returns a slot index to conform with hive's IndexedID interface. +func (t SignedTransactionID) Index() SlotIndex { + return t.Slot() +} + +func (t SignedTransactionID) Identifier() Identifier { + return Identifier(t[:IdentifierLength]) +} + +var ( + // SignedTransactionIDAliases contains a dictionary of identifiers associated to their human-readable alias. + SignedTransactionIDAliases = make(map[SignedTransactionID]string) + + // SignedTransactionIDAliasesMutex is the mutex that is used to synchronize access to the previous map. + SignedTransactionIDAliasesMutex = sync.RWMutex{} +) + +// RegisterAlias allows to register a human-readable alias for the Identifier which will be used as a replacement for +// the String method. +func (t SignedTransactionID) RegisterAlias(alias string) { + SignedTransactionIDAliasesMutex.Lock() + defer SignedTransactionIDAliasesMutex.Unlock() + + SignedTransactionIDAliases[t] = alias +} + +// Alias returns the human-readable alias of the Identifier (or the base58 encoded bytes of no alias was set). +func (t SignedTransactionID) Alias() (alias string) { + SignedTransactionIDAliasesMutex.RLock() + defer SignedTransactionIDAliasesMutex.RUnlock() + + if existingAlias, exists := SignedTransactionIDAliases[t]; exists { + return existingAlias + } + + return t.ToHex() +} + +// UnregisterAlias allows to unregister a previously registered alias. +func (t SignedTransactionID) UnregisterAlias() { + SignedTransactionIDAliasesMutex.Lock() + defer SignedTransactionIDAliasesMutex.Unlock() + + delete(SignedTransactionIDAliases, t) +} + +type SignedTransactionIDs []SignedTransactionID + +// ToHex converts the SignedTransactionIDs to their hex representation. +func (ids SignedTransactionIDs) ToHex() []string { + hexIDs := make([]string, len(ids)) + for i, t := range ids { + hexIDs[i] = hexutil.EncodeHex(t[:]) + } + + return hexIDs +} + +// RemoveDupsAndSort removes duplicated SignedTransactionIDs and sorts the slice by the lexical ordering. +func (ids SignedTransactionIDs) RemoveDupsAndSort() SignedTransactionIDs { + sorted := append(SignedTransactionIDs{}, ids...) + sort.Slice(sorted, func(i, j int) bool { + return bytes.Compare(sorted[i][:], sorted[j][:]) == -1 + }) + + var result SignedTransactionIDs + var prev SignedTransactionID + for i, t := range sorted { + if i == 0 || !bytes.Equal(prev[:], t[:]) { + result = append(result, t) + } + prev = t + } + + return result +} + +// SignedTransactionIDsFromHexString converts the given block IDs from their hex to SignedTransactionID representation. +func SignedTransactionIDsFromHexString(SignedTransactionIDsHex []string) (SignedTransactionIDs, error) { + result := make(SignedTransactionIDs, len(SignedTransactionIDsHex)) + + for i, hexString := range SignedTransactionIDsHex { + SignedTransactionID, err := SignedTransactionIDFromHexString(hexString) + if err != nil { + return nil, err + } + result[i] = SignedTransactionID + } + + return result, nil +} diff --git a/signed_transaction_id.go b/signed_transaction_id.go deleted file mode 100644 index c57152a68..000000000 --- a/signed_transaction_id.go +++ /dev/null @@ -1,154 +0,0 @@ -//nolint:dupl -package iotago - -import ( - "encoding/binary" - "encoding/hex" - "fmt" - "sync" - - "golang.org/x/crypto/blake2b" - - "github.com/iotaledger/iota.go/v4/hexutil" -) - -const ( - SignedTransactionIDLength = IdentifierLength + SlotIndexLength -) - -var ( - emptySignedTransactionID = SignedTransactionID{} -) - -// SignedTransactionID is a 32 byte hash value that can be used to uniquely identify some blob of data together with an 4 byte slot index. -type SignedTransactionID [SignedTransactionIDLength]byte - -// SignedTransactionIDRepresentingData returns a new SignedTransactionID for the given data by hashing it with blake2b and associating it with the given slot index. -func SignedTransactionIDRepresentingData(slot SlotIndex, data []byte) SignedTransactionID { - return NewSignedTransactionID(slot, blake2b.Sum256(data)) -} - -func NewSignedTransactionID(slot SlotIndex, idBytes Identifier) SignedTransactionID { - id := SignedTransactionID{} - copy(id[:], idBytes[:]) - binary.LittleEndian.PutUint32(id[IdentifierLength:], uint32(slot)) - - return id -} - -// SignedTransactionIDFromHexString converts the hex to a SignedTransactionID representation. -func SignedTransactionIDFromHexString(hex string) (SignedTransactionID, error) { - bytes, err := hexutil.DecodeHex(hex) - if err != nil { - return SignedTransactionID{}, err - } - - s, _, err := SignedTransactionIDFromBytes(bytes) - - return s, err -} - -// SignedTransactionIDFromBytes returns a new SignedTransactionID represented by the passed bytes. -func SignedTransactionIDFromBytes(bytes []byte) (SignedTransactionID, int, error) { - if len(bytes) < SignedTransactionIDLength { - return SignedTransactionID{}, 0, ErrInvalidIdentifierLength - } - - return SignedTransactionID(bytes), SignedTransactionIDLength, nil -} - -// MustSignedTransactionIDFromHexString converts the hex to a SignedTransactionID representation. -func MustSignedTransactionIDFromHexString(hex string) SignedTransactionID { - id, err := SignedTransactionIDFromHexString(hex) - if err != nil { - panic(err) - } - - return id -} - -func (id SignedTransactionID) Bytes() ([]byte, error) { - return id[:], nil -} - -func (id SignedTransactionID) MarshalText() (text []byte, err error) { - dst := make([]byte, hex.EncodedLen(len(SignedTransactionID{}))) - hex.Encode(dst, id[:]) - - return dst, nil -} - -func (id *SignedTransactionID) UnmarshalText(text []byte) error { - _, err := hex.Decode(id[:], text) - - return err -} - -// Empty tells whether the Identifier is empty. -func (id SignedTransactionID) Empty() bool { - return id == emptySignedTransactionID -} - -// ToHex converts the Identifier to its hex representation. -func (id SignedTransactionID) ToHex() string { - return hexutil.EncodeHex(id[:]) -} - -func (id SignedTransactionID) String() string { - return fmt.Sprintf("%s:%d", id.Alias(), id.Slot()) -} - -func (id SignedTransactionID) Slot() SlotIndex { - return SlotIndex(binary.LittleEndian.Uint32(id[IdentifierLength:])) -} - -// Index returns a slot index to conform with hive's IndexedID interface. -func (id SignedTransactionID) Index() SlotIndex { - return id.Slot() -} - -func (id SignedTransactionID) Identifier() Identifier { - return Identifier(id[:IdentifierLength]) -} - -var ( - // signedTransactionIDAliases contains a dictionary of identifiers associated to their human-readable alias. - signedTransactionIDAliases = make(map[SignedTransactionID]string) - - // signedTransactionIDAliasesMutex is the mutex that is used to synchronize access to the previous map. - signedTransactionIDAliasesMutex = sync.RWMutex{} -) - -// RegisterAlias allows to register a human-readable alias for the Identifier which will be used as a replacement for -// the String method. -func (id SignedTransactionID) RegisterAlias(alias string) { - signedTransactionIDAliasesMutex.Lock() - defer signedTransactionIDAliasesMutex.Unlock() - - signedTransactionIDAliases[id] = alias -} - -// Alias returns the human-readable alias of the Identifier (or the base58 encoded bytes of no alias was set). -func (id SignedTransactionID) Alias() (alias string) { - signedTransactionIDAliasesMutex.RLock() - defer signedTransactionIDAliasesMutex.RUnlock() - - if existingAlias, exists := signedTransactionIDAliases[id]; exists { - return existingAlias - } - - return id.ToHex() -} - -// UnregisterAlias allows to unregister a previously registered alias. -func (id SignedTransactionID) UnregisterAlias() { - signedTransactionIDAliasesMutex.Lock() - defer signedTransactionIDAliasesMutex.Unlock() - - delete(signedTransactionIDAliases, id) -} - -var EmptySignedTransactionID = SignedTransactionID{} - -// SignedTransactionIDs are IDs of signed transactions. -type SignedTransactionIDs []SignedTransactionID From 511c99ea2ee1daf994e2d33a5c36cc970bc979f0 Mon Sep 17 00:00:00 2001 From: jonastheis <4181434+jonastheis@users.noreply.github.com> Date: Thu, 5 Oct 2023 13:35:13 +0200 Subject: [PATCH 10/15] Remove SlotIdentifier type and replace usages with correct types --- block.go | 12 ++-- input_utxo.go | 4 +- input_utxo_test.go | 8 +-- output.go | 12 ++-- payload.go | 2 +- slot_identifier.go | 148 --------------------------------------------- tpkg/util.go | 14 ++--- 7 files changed, 26 insertions(+), 174 deletions(-) delete mode 100644 slot_identifier.go diff --git a/block.go b/block.go index b9fab4d33..c5d83c2a3 100644 --- a/block.go +++ b/block.go @@ -401,9 +401,9 @@ func (b *BasicBlock) Size() int { } return BasicBlockSizeEmptyParentsAndEmptyPayload + - len(b.StrongParents)*SlotIdentifierLength + - len(b.WeakParents)*SlotIdentifierLength + - len(b.ShallowLikeParents)*SlotIdentifierLength + + len(b.StrongParents)*BlockIDLength + + len(b.WeakParents)*BlockIDLength + + len(b.ShallowLikeParents)*BlockIDLength + payloadSize } @@ -496,9 +496,9 @@ func (b *ValidationBlock) WorkScore(_ *WorkScoreStructure) (WorkScore, error) { func (b *ValidationBlock) Size() int { return serializer.OneByte + // block type - serializer.OneByte + len(b.StrongParents)*SlotIdentifierLength + // StrongParents count - serializer.OneByte + len(b.WeakParents)*SlotIdentifierLength + // WeakParents count - serializer.OneByte + len(b.ShallowLikeParents)*SlotIdentifierLength + // ShallowLikeParents count + serializer.OneByte + len(b.StrongParents)*BlockIDLength + // StrongParents count + serializer.OneByte + len(b.WeakParents)*BlockIDLength + // WeakParents count + serializer.OneByte + len(b.ShallowLikeParents)*BlockIDLength + // ShallowLikeParents count serializer.OneByte + // highest supported version IdentifierLength // protocol parameters hash } diff --git a/input_utxo.go b/input_utxo.go index 7d74e539e..12ce5141d 100644 --- a/input_utxo.go +++ b/input_utxo.go @@ -43,8 +43,8 @@ func (u *UTXOInput) IsReadOnly() bool { func (u *UTXOInput) OutputID() OutputID { var id OutputID - copy(id[:SlotIdentifierLength], u.TransactionID[:]) - binary.LittleEndian.PutUint16(id[SlotIdentifierLength:], u.TransactionOutputIndex) + copy(id[:TransactionIDLength], u.TransactionID[:]) + binary.LittleEndian.PutUint16(id[TransactionIDLength:], u.TransactionOutputIndex) return id } diff --git a/input_utxo_test.go b/input_utxo_test.go index 7f6c6721d..dd4d6b3e4 100644 --- a/input_utxo_test.go +++ b/input_utxo_test.go @@ -23,10 +23,10 @@ func TestUTXOInput_DeSerialize(t *testing.T) { } func TestUTXOInput_Equals(t *testing.T) { - input1 := &iotago.UTXOInput{[iotago.SlotIdentifierLength]byte{1, 2, 3, 4, 5, 6, 7}, 10} - input2 := &iotago.UTXOInput{[iotago.SlotIdentifierLength]byte{1, 2, 3, 4, 5, 6, 7}, 10} - input3 := &iotago.UTXOInput{[iotago.SlotIdentifierLength]byte{1, 2, 3, 4, 5, 6, 8}, 10} - input4 := &iotago.UTXOInput{[iotago.SlotIdentifierLength]byte{1, 2, 3, 4, 5, 6, 7}, 12} + input1 := &iotago.UTXOInput{iotago.TransactionID{1, 2, 3, 4, 5, 6, 7}, 10} + input2 := &iotago.UTXOInput{iotago.TransactionID{1, 2, 3, 4, 5, 6, 7}, 10} + input3 := &iotago.UTXOInput{iotago.TransactionID{1, 2, 3, 4, 5, 6, 8}, 10} + input4 := &iotago.UTXOInput{iotago.TransactionID{1, 2, 3, 4, 5, 6, 7}, 12} //nolint:gocritic // false positive require.True(t, input1.Equals(input1)) require.True(t, input1.Equals(input2)) diff --git a/output.go b/output.go index 495df3edd..4e8eaa374 100644 --- a/output.go +++ b/output.go @@ -101,7 +101,7 @@ const ( // OutputIndexLength defines the length of an OutputIndex. OutputIndexLength = serializer.UInt16ByteSize // OutputIDLength defines the length of an OutputID. - OutputIDLength = SlotIdentifierLength + OutputIndexLength + OutputIDLength = TransactionIDLength + OutputIndexLength ) var ( @@ -129,7 +129,7 @@ var EmptyOutputID = OutputID{} func EmptyOutputIDWithCreationSlot(slot SlotIndex) OutputID { var outputID OutputID - binary.LittleEndian.PutUint32(outputID[IdentifierLength:SlotIdentifierLength], uint32(slot)) + binary.LittleEndian.PutUint32(outputID[IdentifierLength:TransactionIDLength], uint32(slot)) return outputID } @@ -146,14 +146,14 @@ func (outputID OutputID) String() string { // TransactionID returns the TransactionID of the Output this OutputID references. func (outputID OutputID) TransactionID() TransactionID { var txID TransactionID - copy(txID[:], outputID[:SlotIdentifierLength]) + copy(txID[:], outputID[:TransactionIDLength]) return txID } // Index returns the index of the Output this OutputID references. func (outputID OutputID) Index() uint16 { - return binary.LittleEndian.Uint16(outputID[SlotIdentifierLength:]) + return binary.LittleEndian.Uint16(outputID[TransactionIDLength:]) } // CreationSlot returns the slot the Output was created in. @@ -577,8 +577,8 @@ func (oih OutputIDHex) SplitParts() (*TransactionID, uint16, error) { return nil, 0, err } var txID TransactionID - copy(txID[:], outputIDBytes[:SlotIdentifierLength]) - outputIndex := binary.LittleEndian.Uint16(outputIDBytes[SlotIdentifierLength : SlotIdentifierLength+serializer.UInt16ByteSize]) + copy(txID[:], outputIDBytes[:TransactionIDLength]) + outputIndex := binary.LittleEndian.Uint16(outputIDBytes[TransactionIDLength : TransactionIDLength+serializer.UInt16ByteSize]) return &txID, outputIndex, nil } diff --git a/payload.go b/payload.go index 5e0297d79..598dbfe89 100644 --- a/payload.go +++ b/payload.go @@ -9,7 +9,7 @@ import ( const ( // MaxPayloadSize defines the maximum size of a basic block payload. // MaxPayloadSize = MaxBlockSize - block header - empty basic block - one strong parent - block signature. - MaxPayloadSize = MaxBlockSize - BlockHeaderLength - BasicBlockSizeEmptyParentsAndEmptyPayload - SlotIdentifierLength - Ed25519SignatureSerializedBytesSize + MaxPayloadSize = MaxBlockSize - BlockHeaderLength - BasicBlockSizeEmptyParentsAndEmptyPayload - BlockIDLength - Ed25519SignatureSerializedBytesSize ) // PayloadType denotes a type of payload. diff --git a/slot_identifier.go b/slot_identifier.go deleted file mode 100644 index 5e9ee3b46..000000000 --- a/slot_identifier.go +++ /dev/null @@ -1,148 +0,0 @@ -package iotago - -import ( - "encoding/binary" - "encoding/hex" - "fmt" - "sync" - - "golang.org/x/crypto/blake2b" - - "github.com/iotaledger/iota.go/v4/hexutil" -) - -const ( - SlotIdentifierLength = IdentifierLength + SlotIndexLength -) - -var ( - emptySlotIdentifier = SlotIdentifier{} -) - -// SlotIdentifier is a 32 byte hash value that can be used to uniquely identify some blob of data together with an 4 byte slot index. -type SlotIdentifier [SlotIdentifierLength]byte - -// SlotIdentifierRepresentingData returns a new SlotIdentifier for the given data by hashing it with blake2b and associating it with the given slot index. -func SlotIdentifierRepresentingData(slot SlotIndex, data []byte) SlotIdentifier { - return NewSlotIdentifier(slot, blake2b.Sum256(data)) -} - -func NewSlotIdentifier(slot SlotIndex, idBytes Identifier) SlotIdentifier { - id := SlotIdentifier{} - copy(id[:], idBytes[:]) - binary.LittleEndian.PutUint32(id[IdentifierLength:], uint32(slot)) - - return id -} - -// SlotIdentifierFromHexString converts the hex to a SlotIdentifier representation. -func SlotIdentifierFromHexString(hex string) (SlotIdentifier, error) { - bytes, err := hexutil.DecodeHex(hex) - if err != nil { - return SlotIdentifier{}, err - } - - s, _, err := SlotIdentifierFromBytes(bytes) - - return s, err -} - -// SlotIdentifierFromBytes returns a new SlotIdentifier represented by the passed bytes. -func SlotIdentifierFromBytes(bytes []byte) (SlotIdentifier, int, error) { - if len(bytes) < SlotIdentifierLength { - return SlotIdentifier{}, 0, ErrInvalidIdentifierLength - } - - return SlotIdentifier(bytes), SlotIdentifierLength, nil -} - -// MustSlotIdentifierFromHexString converts the hex to a SlotIdentifier representation. -func MustSlotIdentifierFromHexString(hex string) SlotIdentifier { - id, err := SlotIdentifierFromHexString(hex) - if err != nil { - panic(err) - } - - return id -} - -func (id SlotIdentifier) Bytes() ([]byte, error) { - return id[:], nil -} - -func (id SlotIdentifier) MarshalText() (text []byte, err error) { - dst := make([]byte, hex.EncodedLen(len(SlotIdentifier{}))) - hex.Encode(dst, id[:]) - - return dst, nil -} - -func (id *SlotIdentifier) UnmarshalText(text []byte) error { - _, err := hex.Decode(id[:], text) - - return err -} - -// Empty tells whether the Identifier is empty. -func (id SlotIdentifier) Empty() bool { - return id == emptySlotIdentifier -} - -// ToHex converts the Identifier to its hex representation. -func (id SlotIdentifier) ToHex() string { - return hexutil.EncodeHex(id[:]) -} - -func (id SlotIdentifier) String() string { - return fmt.Sprintf("%s:%d", id.Alias(), id.Slot()) -} - -func (id SlotIdentifier) Slot() SlotIndex { - return SlotIndex(binary.LittleEndian.Uint32(id[IdentifierLength:])) -} - -// Index returns a slot index to conform with hive's IndexedID interface. -func (id SlotIdentifier) Index() SlotIndex { - return id.Slot() -} - -func (id SlotIdentifier) Identifier() Identifier { - return Identifier(id[:IdentifierLength]) -} - -var ( - // slotIdentifierAliases contains a dictionary of identifiers associated to their human-readable alias. - slotIdentifierAliases = make(map[SlotIdentifier]string) - - // slotIdentifierAliasesMutex is the mutex that is used to synchronize access to the previous map. - slotIdentifierAliasesMutex = sync.RWMutex{} -) - -// RegisterAlias allows to register a human-readable alias for the Identifier which will be used as a replacement for -// the String method. -func (id SlotIdentifier) RegisterAlias(alias string) { - slotIdentifierAliasesMutex.Lock() - defer slotIdentifierAliasesMutex.Unlock() - - slotIdentifierAliases[id] = alias -} - -// Alias returns the human-readable alias of the Identifier (or the base58 encoded bytes of no alias was set). -func (id SlotIdentifier) Alias() (alias string) { - slotIdentifierAliasesMutex.RLock() - defer slotIdentifierAliasesMutex.RUnlock() - - if existingAlias, exists := slotIdentifierAliases[id]; exists { - return existingAlias - } - - return id.ToHex() -} - -// UnregisterAlias allows to unregister a previously registered alias. -func (id SlotIdentifier) UnregisterAlias() { - slotIdentifierAliasesMutex.Lock() - defer slotIdentifierAliasesMutex.Unlock() - - delete(slotIdentifierAliases, id) -} diff --git a/tpkg/util.go b/tpkg/util.go index e66da0792..c95468c7e 100644 --- a/tpkg/util.go +++ b/tpkg/util.go @@ -105,7 +105,7 @@ func RandOutputIDWithCreationSlot(slot iotago.SlotIndex, index uint16) iotago.Ou var outputID iotago.OutputID copy(outputID[:], txID[:]) - binary.LittleEndian.PutUint16(outputID[iotago.SlotIdentifierLength:], index) + binary.LittleEndian.PutUint16(outputID[iotago.TransactionIDLength:], index) return outputID } @@ -138,7 +138,7 @@ func RandSignedTransactionIDWithCreationSlot(slot iotago.SlotIndex) iotago.Signe if err != nil { panic(err) } - binary.LittleEndian.PutUint32(signedTransactionID[iotago.IdentifierLength:iotago.SlotIdentifierLength], uint32(slot)) + binary.LittleEndian.PutUint32(signedTransactionID[iotago.IdentifierLength:iotago.TransactionIDLength], uint32(slot)) return signedTransactionID } @@ -149,7 +149,7 @@ func RandTransactionIDWithCreationSlot(slot iotago.SlotIndex) iotago.Transaction if err != nil { panic(err) } - binary.LittleEndian.PutUint32(transactionID[iotago.IdentifierLength:iotago.SlotIdentifierLength], uint32(slot)) + binary.LittleEndian.PutUint32(transactionID[iotago.IdentifierLength:iotago.TransactionIDLength], uint32(slot)) return transactionID } @@ -804,7 +804,7 @@ func RandBlockIssuanceCreditInput() *iotago.BlockIssuanceCreditInput { // RandUTXOInputWithIndex returns a random UTXO input with a specific index. func RandUTXOInputWithIndex(index uint16) *iotago.UTXOInput { utxoInput := &iotago.UTXOInput{} - txID := RandBytes(iotago.SlotIdentifierLength) + txID := RandBytes(iotago.TransactionIDLength) copy(utxoInput.TransactionID[:], txID) utxoInput.TransactionOutputIndex = index @@ -863,9 +863,9 @@ func OneInputOutputTransaction() *iotago.SignedTransaction { ContextInputs: iotago.TxEssenceContextInputs{}, Inputs: iotago.TxEssenceInputs{ &iotago.UTXOInput{ - TransactionID: func() [iotago.SlotIdentifierLength]byte { - var b [iotago.SlotIdentifierLength]byte - copy(b[:], RandBytes(iotago.SlotIdentifierLength)) + TransactionID: func() iotago.TransactionID { + var b iotago.TransactionID + copy(b[:], RandBytes(iotago.TransactionIDLength)) return b }(), From 35eab82eb50e26e69c09a62bf55adf13f58d0815 Mon Sep 17 00:00:00 2001 From: jonastheis <4181434+jonastheis@users.noreply.github.com> Date: Thu, 5 Oct 2023 14:36:32 +0200 Subject: [PATCH 11/15] Adjust template to support OutputID, generate it from template and fix all incompatibilities --- gen/slot_identifier.tmpl | 22 +++- gen/slot_identifier_gen.go | 1 + output.go | 239 ------------------------------------- output_id.gen.go | 206 ++++++++++++++++++++++++++++++++ output_id.go | 143 ++++++++++++++++++++++ output_test.go | 13 -- 6 files changed, 369 insertions(+), 255 deletions(-) create mode 100644 output_id.gen.go create mode 100644 output_id.go diff --git a/gen/slot_identifier.tmpl b/gen/slot_identifier.tmpl index 40246518f..eb78d4a59 100644 --- a/gen/slot_identifier.tmpl +++ b/gen/slot_identifier.tmpl @@ -3,7 +3,7 @@ package iotago // Code generated by go generate; DO NOT EDIT. Check gen/ directory instead. import ( -{{if index .Features "ids"}} "bytes" {{end}} + {{if index .Features "ids"}} "bytes" {{end}} "encoding/binary" "encoding/hex" "fmt" @@ -14,10 +14,18 @@ import ( "github.com/iotaledger/hive.go/ierrors" "github.com/iotaledger/iota.go/v4/hexutil" + {{if index .Features "output"}}"github.com/iotaledger/hive.go/serializer/v2"{{end}} ) const ( - {{.Name}}Length = IdentifierLength + SlotIndexLength +{{if index .Features "output"}} + // OutputIndexLength defines the length of an OutputIndex. + OutputIndexLength = serializer.UInt16ByteSize + // OutputIDLength defines the length of an OutputID. + OutputIDLength = TransactionIDLength + OutputIndexLength +{{else}} + {{.Name}}Length = IdentifierLength + SlotIndexLength +{{end}} ) var ( @@ -108,10 +116,18 @@ func ({{.Receiver}} {{.Name}}) Slot() SlotIndex { return SlotIndex(binary.LittleEndian.Uint32({{.Receiver}}[IdentifierLength:])) } + +{{if index .Features "output"}} +// Index returns the index of the Output this OutputID references. +func (outputID OutputID) Index() uint16 { + return binary.LittleEndian.Uint16(outputID[TransactionIDLength:]) +} +{{else}} // Index returns a slot index to conform with hive's IndexedID interface. func ({{.Receiver}} {{.Name}}) Index() SlotIndex { - return {{.Receiver}}.Slot() +return {{.Receiver}}.Slot() } +{{end}} func ({{.Receiver}} {{.Name}}) Identifier() Identifier { return Identifier({{.Receiver}}[:IdentifierLength]) diff --git a/gen/slot_identifier_gen.go b/gen/slot_identifier_gen.go index 5478ac697..c0322c316 100644 --- a/gen/slot_identifier_gen.go +++ b/gen/slot_identifier_gen.go @@ -6,3 +6,4 @@ package gen //go:generate go run ./cmd slot_identifier.tmpl ../commitment_id.gen.go CommitmentID c "" //go:generate go run ./cmd slot_identifier.tmpl ../transaction_id.gen.go TransactionID t "ids" //go:generate go run ./cmd slot_identifier.tmpl ../signed_transaction_id.gen.go SignedTransactionID t "ids" +//go:generate go run ./cmd slot_identifier.tmpl ../output_id.gen.go OutputID o "ids output" diff --git a/output.go b/output.go index 4e8eaa374..55f493931 100644 --- a/output.go +++ b/output.go @@ -1,12 +1,9 @@ package iotago import ( - "bytes" - "encoding/binary" "fmt" "math" "math/big" - "sort" "strings" "github.com/ethereum/go-ethereum/accounts/abi" @@ -17,7 +14,6 @@ import ( "github.com/iotaledger/hive.go/ierrors" "github.com/iotaledger/hive.go/lo" "github.com/iotaledger/hive.go/serializer/v2" - "github.com/iotaledger/iota.go/v4/hexutil" ) // BaseToken defines the unit of the base token of the network. @@ -97,16 +93,7 @@ var outputNames = [OutputDelegation + 1]string{ "DelegationOutput", } -const ( - // OutputIndexLength defines the length of an OutputIndex. - OutputIndexLength = serializer.UInt16ByteSize - // OutputIDLength defines the length of an OutputID. - OutputIDLength = TransactionIDLength + OutputIndexLength -) - var ( - ErrInvalidOutputIDLength = ierrors.New("Invalid outputID length") - // ErrTransDepIdentOutputNonUTXOChainID gets returned when a TransDepIdentOutput has a ChainID which is not a UTXOIDChainID. ErrTransDepIdentOutputNonUTXOChainID = ierrors.New("transition dependable ident outputs must have UTXO chain IDs") // ErrTransDepIdentOutputNextInvalid gets returned when a TransDepIdentOutput's next state is invalid. @@ -120,129 +107,6 @@ func storageScoreOffsetOutput(rentStruct *RentStructure) StorageScore { rentStruct.StorageScoreFactorData().Multiply(OutputIDLength+BlockIDLength+SlotIndexLength) } -// OutputID defines the identifier for an UTXO which consists -// out of the referenced TransactionID and the output's index. -type OutputID [OutputIDLength]byte - -// EmptyOutputID is an empty OutputID. -var EmptyOutputID = OutputID{} - -func EmptyOutputIDWithCreationSlot(slot SlotIndex) OutputID { - var outputID OutputID - binary.LittleEndian.PutUint32(outputID[IdentifierLength:TransactionIDLength], uint32(slot)) - return outputID -} - -// ToHex converts the OutputID to its hex representation. -func (outputID OutputID) ToHex() string { - return hexutil.EncodeHex(outputID[:]) -} - -// String converts the OutputID to its human-readable string representation. -func (outputID OutputID) String() string { - return fmt.Sprintf("OutputID(%s:%d)", outputID.TransactionID().String(), outputID.Index()) -} - -// TransactionID returns the TransactionID of the Output this OutputID references. -func (outputID OutputID) TransactionID() TransactionID { - var txID TransactionID - copy(txID[:], outputID[:TransactionIDLength]) - - return txID -} - -// Index returns the index of the Output this OutputID references. -func (outputID OutputID) Index() uint16 { - return binary.LittleEndian.Uint16(outputID[TransactionIDLength:]) -} - -// CreationSlot returns the slot the Output was created in. -func (outputID OutputID) CreationSlot() SlotIndex { - return outputID.TransactionID().Slot() -} - -// UTXOInput creates a UTXOInput from this OutputID. -func (outputID OutputID) UTXOInput() *UTXOInput { - return &UTXOInput{ - TransactionID: outputID.TransactionID(), - TransactionOutputIndex: outputID.Index(), - } -} - -func (outputID OutputID) Bytes() ([]byte, error) { - return outputID[:], nil -} - -// HexOutputIDs is a slice of hex encoded OutputID strings. -type HexOutputIDs []string - -// MustOutputIDs converts the hex strings into OutputIDs. -func (ids HexOutputIDs) MustOutputIDs() OutputIDs { - vals, err := ids.OutputIDs() - if err != nil { - panic(err) - } - - return vals -} - -// OutputIDs converts the hex strings into OutputIDs. -func (ids HexOutputIDs) OutputIDs() (OutputIDs, error) { - vals := make(OutputIDs, len(ids)) - for i, v := range ids { - val, err := hexutil.DecodeHex(v) - if err != nil { - return nil, err - } - copy(vals[i][:], val) - } - - return vals, nil -} - -// OutputIDFromTransactionIDAndIndex creates a OutputID from the given TransactionID and output index. -func OutputIDFromTransactionIDAndIndex(txID TransactionID, index uint16) OutputID { - utxo := &UTXOInput{ - TransactionID: txID, - TransactionOutputIndex: index, - } - - return utxo.OutputID() -} - -// OutputIDFromBytes creates a OutputID from the given bytes. -func OutputIDFromBytes(bytes []byte) (OutputID, int, error) { - if len(bytes) < OutputIDLength { - return OutputID{}, 0, ErrInvalidOutputIDLength - } - - return OutputID(bytes), OutputIDLength, nil -} - -// OutputIDFromHex creates a OutputID from the given hex encoded OutputID data. -func OutputIDFromHex(hexStr string) (OutputID, error) { - outputIDData, err := hexutil.DecodeHex(hexStr) - if err != nil { - return OutputID{}, err - } - - o, _, err := OutputIDFromBytes(outputIDData) - - return o, err -} - -// MustOutputIDFromHex works like OutputIDFromHex but panics if an error is encountered. -func MustOutputIDFromHex(hexStr string) OutputID { - var outputID OutputID - outputIDData, err := hexutil.DecodeHex(hexStr) - if err != nil { - panic(err) - } - copy(outputID[:], outputIDData) - - return outputID -} - // OutputSet is a map of the OutputID to Output. type OutputSet map[OutputID]Output @@ -263,58 +127,6 @@ func (outputSet OutputSet) Filter(f func(outputID OutputID, output Output) bool) return m } -// OutputIDs is a slice of OutputID. -type OutputIDs []OutputID - -// ToHex converts all UTXOInput to their hex string representation. -func (outputIDs OutputIDs) ToHex() []string { - ids := make([]string, len(outputIDs)) - for i := range outputIDs { - ids[i] = hexutil.EncodeHex(outputIDs[i][:]) - } - - return ids -} - -// RemoveDupsAndSort removes duplicated OutputIDs and sorts the slice by the lexical ordering. -func (outputIDs OutputIDs) RemoveDupsAndSort() OutputIDs { - sorted := append(OutputIDs{}, outputIDs...) - sort.Slice(sorted, func(i, j int) bool { - return bytes.Compare(sorted[i][:], sorted[j][:]) == -1 - }) - - var result OutputIDs - var prev OutputID - for i, id := range sorted { - if i == 0 || !bytes.Equal(prev[:], id[:]) { - result = append(result, id) - } - prev = id - } - - return result -} - -// UTXOInputs converts the OutputIDs slice to Inputs. -func (outputIDs OutputIDs) UTXOInputs() TxEssenceInputs { - inputs := make(TxEssenceInputs, 0) - for _, outputID := range outputIDs { - inputs = append(inputs, outputID.UTXOInput()) - } - - return inputs -} - -// OrderedSet returns an Outputs slice ordered by this OutputIDs slice given an OutputSet. -func (outputIDs OutputIDs) OrderedSet(set OutputSet) Outputs[Output] { - outputs := make(Outputs[Output], len(outputIDs)) - for i, outputID := range outputIDs { - outputs[i] = set[outputID] - } - - return outputs -} - var ( // ErrAmountMustBeGreaterThanZero gets returned if the base token amount of an output is less or equal zero. ErrAmountMustBeGreaterThanZero = ierrors.New("base token amount must be greater than zero") @@ -556,57 +368,6 @@ type TransDepIdentOutput interface { UnlockableBy(ident Address, next TransDepIdentOutput, pastBoundedSlotIndex SlotIndex, futureBoundedSlotIndex SlotIndex) (bool, error) } -// OutputIDHex is the hex representation of an output ID. -type OutputIDHex string - -// MustSplitParts returns the transaction ID and output index parts of the hex output ID. -// It panics if the hex output ID is invalid. -func (oih OutputIDHex) MustSplitParts() (*TransactionID, uint16) { - txID, outputIndex, err := oih.SplitParts() - if err != nil { - panic(err) - } - - return txID, outputIndex -} - -// SplitParts returns the transaction ID and output index parts of the hex output ID. -func (oih OutputIDHex) SplitParts() (*TransactionID, uint16, error) { - outputIDBytes, err := hexutil.DecodeHex(string(oih)) - if err != nil { - return nil, 0, err - } - var txID TransactionID - copy(txID[:], outputIDBytes[:TransactionIDLength]) - outputIndex := binary.LittleEndian.Uint16(outputIDBytes[TransactionIDLength : TransactionIDLength+serializer.UInt16ByteSize]) - - return &txID, outputIndex, nil -} - -// MustAsUTXOInput converts the hex output ID to a UTXOInput. -// It panics if the hex output ID is invalid. -func (oih OutputIDHex) MustAsUTXOInput() *UTXOInput { - utxoInput, err := oih.AsUTXOInput() - if err != nil { - panic(err) - } - - return utxoInput -} - -// AsUTXOInput converts the hex output ID to a UTXOInput. -func (oih OutputIDHex) AsUTXOInput() (*UTXOInput, error) { - var utxoInput UTXOInput - txID, outputIndex, err := oih.SplitParts() - if err != nil { - return nil, err - } - copy(utxoInput.TransactionID[:], txID[:]) - utxoInput.TransactionOutputIndex = outputIndex - - return &utxoInput, nil -} - // OutputsSyntacticalValidationFunc which given the index of an output and the output itself, runs syntactical validations and returns an error if any should fail. type OutputsSyntacticalValidationFunc func(index int, output Output) error diff --git a/output_id.gen.go b/output_id.gen.go new file mode 100644 index 000000000..22b5900cf --- /dev/null +++ b/output_id.gen.go @@ -0,0 +1,206 @@ +package iotago + +// Code generated by go generate; DO NOT EDIT. Check gen/ directory instead. + +import ( + "bytes" + "encoding/binary" + "encoding/hex" + "fmt" + "sort" + "sync" + + "golang.org/x/crypto/blake2b" + + "github.com/iotaledger/hive.go/ierrors" + "github.com/iotaledger/hive.go/serializer/v2" + "github.com/iotaledger/iota.go/v4/hexutil" +) + +const ( + + // OutputIndexLength defines the length of an OutputIndex. + OutputIndexLength = serializer.UInt16ByteSize + // OutputIDLength defines the length of an OutputID. + OutputIDLength = TransactionIDLength + OutputIndexLength +) + +var ( + ErrInvalidOutputIDLength = ierrors.New("invalid outputID length") + + EmptyOutputID = OutputID{} +) + +// OutputID is a 32 byte hash value together with an 4 byte slot index. +type OutputID [OutputIDLength]byte + +// OutputIDRepresentingData returns a new OutputID for the given data by hashing it with blake2b and associating it with the given slot index. +func OutputIDRepresentingData(slot SlotIndex, data []byte) OutputID { + return NewOutputID(slot, blake2b.Sum256(data)) +} + +func NewOutputID(slot SlotIndex, idBytes Identifier) OutputID { + o := OutputID{} + copy(o[:], idBytes[:]) + binary.LittleEndian.PutUint32(o[IdentifierLength:], uint32(slot)) + + return o +} + +// OutputIDFromHexString converts the hex to a OutputID representation. +func OutputIDFromHexString(hex string) (OutputID, error) { + b, err := hexutil.DecodeHex(hex) + if err != nil { + return OutputID{}, err + } + + s, _, err := OutputIDFromBytes(b) + + return s, err +} + +// OutputIDFromBytes returns a new OutputID represented by the passed bytes. +func OutputIDFromBytes(b []byte) (OutputID, int, error) { + if len(b) < OutputIDLength { + return OutputID{}, 0, ErrInvalidOutputIDLength + } + + return OutputID(b), OutputIDLength, nil +} + +// MustOutputIDFromHexString converts the hex to a OutputID representation. +func MustOutputIDFromHexString(hex string) OutputID { + o, err := OutputIDFromHexString(hex) + if err != nil { + panic(err) + } + + return o +} + +func (o OutputID) Bytes() ([]byte, error) { + return o[:], nil +} + +func (o OutputID) MarshalText() (text []byte, err error) { + dst := make([]byte, hex.EncodedLen(len(OutputID{}))) + hex.Encode(dst, o[:]) + + return dst, nil +} + +func (o *OutputID) UnmarshalText(text []byte) error { + _, err := hex.Decode(o[:], text) + + return err +} + +// Empty tells whether the OutputID is empty. +func (o OutputID) Empty() bool { + return o == EmptyOutputID +} + +// ToHex converts the Identifier to its hex representation. +func (o OutputID) ToHex() string { + return hexutil.EncodeHex(o[:]) +} + +func (o OutputID) String() string { + return fmt.Sprintf("OutputID(%s:%d)", o.Alias(), o.Slot()) +} + +func (o OutputID) Slot() SlotIndex { + return SlotIndex(binary.LittleEndian.Uint32(o[IdentifierLength:])) +} + +// Index returns the index of the Output this OutputID references. +func (outputID OutputID) Index() uint16 { + return binary.LittleEndian.Uint16(outputID[TransactionIDLength:]) +} + +func (o OutputID) Identifier() Identifier { + return Identifier(o[:IdentifierLength]) +} + +var ( + // OutputIDAliases contains a dictionary of identifiers associated to their human-readable alias. + OutputIDAliases = make(map[OutputID]string) + + // OutputIDAliasesMutex is the mutex that is used to synchronize access to the previous map. + OutputIDAliasesMutex = sync.RWMutex{} +) + +// RegisterAlias allows to register a human-readable alias for the Identifier which will be used as a replacement for +// the String method. +func (o OutputID) RegisterAlias(alias string) { + OutputIDAliasesMutex.Lock() + defer OutputIDAliasesMutex.Unlock() + + OutputIDAliases[o] = alias +} + +// Alias returns the human-readable alias of the Identifier (or the base58 encoded bytes of no alias was set). +func (o OutputID) Alias() (alias string) { + OutputIDAliasesMutex.RLock() + defer OutputIDAliasesMutex.RUnlock() + + if existingAlias, exists := OutputIDAliases[o]; exists { + return existingAlias + } + + return o.ToHex() +} + +// UnregisterAlias allows to unregister a previously registered alias. +func (o OutputID) UnregisterAlias() { + OutputIDAliasesMutex.Lock() + defer OutputIDAliasesMutex.Unlock() + + delete(OutputIDAliases, o) +} + +type OutputIDs []OutputID + +// ToHex converts the OutputIDs to their hex representation. +func (ids OutputIDs) ToHex() []string { + hexIDs := make([]string, len(ids)) + for i, o := range ids { + hexIDs[i] = hexutil.EncodeHex(o[:]) + } + + return hexIDs +} + +// RemoveDupsAndSort removes duplicated OutputIDs and sorts the slice by the lexical ordering. +func (ids OutputIDs) RemoveDupsAndSort() OutputIDs { + sorted := append(OutputIDs{}, ids...) + sort.Slice(sorted, func(i, j int) bool { + return bytes.Compare(sorted[i][:], sorted[j][:]) == -1 + }) + + var result OutputIDs + var prev OutputID + for i, o := range sorted { + if i == 0 || !bytes.Equal(prev[:], o[:]) { + result = append(result, o) + } + prev = o + } + + return result +} + +// OutputIDsFromHexString converts the given block IDs from their hex to OutputID representation. +func OutputIDsFromHexString(OutputIDsHex []string) (OutputIDs, error) { + result := make(OutputIDs, len(OutputIDsHex)) + + for i, hexString := range OutputIDsHex { + OutputID, err := OutputIDFromHexString(hexString) + if err != nil { + return nil, err + } + result[i] = OutputID + } + + return result, nil +} diff --git a/output_id.go b/output_id.go new file mode 100644 index 000000000..13a3eca96 --- /dev/null +++ b/output_id.go @@ -0,0 +1,143 @@ +package iotago + +import ( + "encoding/binary" + + "github.com/iotaledger/hive.go/serializer/v2" + "github.com/iotaledger/iota.go/v4/hexutil" +) + +func EmptyOutputIDWithCreationSlot(slot SlotIndex) OutputID { + var outputID OutputID + binary.LittleEndian.PutUint32(outputID[IdentifierLength:OutputIDLength], uint32(slot)) + return outputID +} + +// TransactionID returns the TransactionID of the Output this OutputID references. +func (o OutputID) TransactionID() TransactionID { + var txID TransactionID + copy(txID[:], o[:TransactionIDLength]) + + return txID +} + +// CreationSlot returns the slot the Output was created in. +func (o OutputID) CreationSlot() SlotIndex { + return o.TransactionID().Slot() +} + +// UTXOInput creates a UTXOInput from this OutputID. +func (o OutputID) UTXOInput() *UTXOInput { + return &UTXOInput{ + TransactionID: o.TransactionID(), + TransactionOutputIndex: o.Index(), + } +} + +// OutputIDFromTransactionIDAndIndex creates a OutputID from the given TransactionID and output index. +func OutputIDFromTransactionIDAndIndex(txID TransactionID, index uint16) OutputID { + utxo := &UTXOInput{ + TransactionID: txID, + TransactionOutputIndex: index, + } + + return utxo.OutputID() +} + +// UTXOInputs converts the OutputIDs slice to Inputs. +func (o OutputIDs) UTXOInputs() TxEssenceInputs { + inputs := make(TxEssenceInputs, 0) + for _, outputID := range o { + inputs = append(inputs, outputID.UTXOInput()) + } + + return inputs +} + +// OrderedSet returns an Outputs slice ordered by this OutputIDs slice given an OutputSet. +func (o OutputIDs) OrderedSet(set OutputSet) Outputs[Output] { + outputs := make(Outputs[Output], len(o)) + for i, outputID := range o { + outputs[i] = set[outputID] + } + + return outputs +} + +// OutputIDHex is the hex representation of an output ID. +type OutputIDHex string + +// MustSplitParts returns the transaction ID and output index parts of the hex output ID. +// It panics if the hex output ID is invalid. +func (oih OutputIDHex) MustSplitParts() (*TransactionID, uint16) { + txID, outputIndex, err := oih.SplitParts() + if err != nil { + panic(err) + } + + return txID, outputIndex +} + +// SplitParts returns the transaction ID and output index parts of the hex output ID. +func (oih OutputIDHex) SplitParts() (*TransactionID, uint16, error) { + outputIDBytes, err := hexutil.DecodeHex(string(oih)) + if err != nil { + return nil, 0, err + } + var txID TransactionID + copy(txID[:], outputIDBytes[:TransactionIDLength]) + outputIndex := binary.LittleEndian.Uint16(outputIDBytes[TransactionIDLength : TransactionIDLength+serializer.UInt16ByteSize]) + + return &txID, outputIndex, nil +} + +// MustAsUTXOInput converts the hex output ID to a UTXOInput. +// It panics if the hex output ID is invalid. +func (oih OutputIDHex) MustAsUTXOInput() *UTXOInput { + utxoInput, err := oih.AsUTXOInput() + if err != nil { + panic(err) + } + + return utxoInput +} + +// AsUTXOInput converts the hex output ID to a UTXOInput. +func (oih OutputIDHex) AsUTXOInput() (*UTXOInput, error) { + var utxoInput UTXOInput + txID, outputIndex, err := oih.SplitParts() + if err != nil { + return nil, err + } + copy(utxoInput.TransactionID[:], txID[:]) + utxoInput.TransactionOutputIndex = outputIndex + + return &utxoInput, nil +} + +// HexOutputIDs is a slice of hex encoded OutputID strings. +type HexOutputIDs []string + +// MustOutputIDs converts the hex strings into OutputIDs. +func (ids HexOutputIDs) MustOutputIDs() OutputIDs { + vals, err := ids.OutputIDs() + if err != nil { + panic(err) + } + + return vals +} + +// OutputIDs converts the hex strings into OutputIDs. +func (ids HexOutputIDs) OutputIDs() (OutputIDs, error) { + vals := make(OutputIDs, len(ids)) + for i, v := range ids { + val, err := hexutil.DecodeHex(v) + if err != nil { + return nil, err + } + copy(vals[i][:], val) + } + + return vals, nil +} diff --git a/output_test.go b/output_test.go index 2d3bb5aca..79e446627 100644 --- a/output_test.go +++ b/output_test.go @@ -7,7 +7,6 @@ import ( "github.com/stretchr/testify/require" - "github.com/iotaledger/hive.go/lo" iotago "github.com/iotaledger/iota.go/v4" "github.com/iotaledger/iota.go/v4/tpkg" ) @@ -62,18 +61,6 @@ func TestOutputsCommitment(t *testing.T) { } -func TestOutputIDString(t *testing.T) { - tests := []struct { - outputID iotago.OutputID - outputTypeString string - }{ - {outputID: iotago.OutputIDFromTransactionIDAndIndex(lo.PanicOnErr(iotago.TransactionIDFromHexString("0xbaadf00ddeadbeefc8ed3cbe4acb99aeb94515ad89a6228f3f5d8f82dec429df135adafc")), 1), outputTypeString: "OutputID(TransactionID(0xbaadf00ddeadbeefc8ed3cbe4acb99aeb94515ad89a6228f3f5d8f82dec429df135adafc:4242168339):1)"}, - } - for _, tt := range tests { - require.Equal(t, tt.outputID.String(), tt.outputTypeString) - } -} - func TestOutputsDeSerialize(t *testing.T) { emptyAccountAddress := iotago.AccountAddress(iotago.EmptyAccountID) From fc01af86c1555460370752387ba5fd92a8374ac8 Mon Sep 17 00:00:00 2001 From: jonastheis <4181434+jonastheis@users.noreply.github.com> Date: Thu, 5 Oct 2023 14:38:33 +0200 Subject: [PATCH 12/15] Clean up --- identifier_account.go | 16 ++++++++-------- output_id.go | 10 +++++----- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/identifier_account.go b/identifier_account.go index ebf6b20e4..aed5774ea 100644 --- a/identifier_account.go +++ b/identifier_account.go @@ -2,30 +2,30 @@ package iotago import "golang.org/x/crypto/blake2b" -func (id AccountID) Addressable() bool { +func (a AccountID) Addressable() bool { return true } -func (id AccountID) Key() interface{} { - return id.String() +func (a AccountID) Key() interface{} { + return a.String() } -func (id AccountID) FromOutputID(in OutputID) ChainID { +func (a AccountID) FromOutputID(in OutputID) ChainID { return AccountIDFromOutputID(in) } -func (id AccountID) Matches(other ChainID) bool { +func (a AccountID) Matches(other ChainID) bool { otherAccountID, isAccountID := other.(AccountID) if !isAccountID { return false } - return id == otherAccountID + return a == otherAccountID } -func (id AccountID) ToAddress() ChainAddress { +func (a AccountID) ToAddress() ChainAddress { var addr AccountAddress - copy(addr[:], id[:]) + copy(addr[:], a[:]) return &addr } diff --git a/output_id.go b/output_id.go index 13a3eca96..222608fa8 100644 --- a/output_id.go +++ b/output_id.go @@ -45,9 +45,9 @@ func OutputIDFromTransactionIDAndIndex(txID TransactionID, index uint16) OutputI } // UTXOInputs converts the OutputIDs slice to Inputs. -func (o OutputIDs) UTXOInputs() TxEssenceInputs { +func (ids OutputIDs) UTXOInputs() TxEssenceInputs { inputs := make(TxEssenceInputs, 0) - for _, outputID := range o { + for _, outputID := range ids { inputs = append(inputs, outputID.UTXOInput()) } @@ -55,9 +55,9 @@ func (o OutputIDs) UTXOInputs() TxEssenceInputs { } // OrderedSet returns an Outputs slice ordered by this OutputIDs slice given an OutputSet. -func (o OutputIDs) OrderedSet(set OutputSet) Outputs[Output] { - outputs := make(Outputs[Output], len(o)) - for i, outputID := range o { +func (ids OutputIDs) OrderedSet(set OutputSet) Outputs[Output] { + outputs := make(Outputs[Output], len(ids)) + for i, outputID := range ids { outputs[i] = set[outputID] } From 0b1f4f053269aa303fd26fa81437c72438d6f9b6 Mon Sep 17 00:00:00 2001 From: jonastheis <4181434+jonastheis@users.noreply.github.com> Date: Thu, 5 Oct 2023 21:09:05 +0300 Subject: [PATCH 13/15] Move code generation to hive.go and update go.mod --- gen/cmd/cmd.go | 64 -------------------------------------- gen/cmd/configuration.go | 31 ------------------ gen/identifier_gen.go | 4 +-- gen/slot_identifier_gen.go | 10 +++--- go.mod | 13 ++++---- go.sum | 26 +++++++++------- 6 files changed, 28 insertions(+), 120 deletions(-) delete mode 100644 gen/cmd/cmd.go delete mode 100644 gen/cmd/configuration.go diff --git a/gen/cmd/cmd.go b/gen/cmd/cmd.go deleted file mode 100644 index 5f5f7d007..000000000 --- a/gen/cmd/cmd.go +++ /dev/null @@ -1,64 +0,0 @@ -// Package gen/cmd allows to generate .go source files using the go:generate command. -// Use with "cmd [templateFile] [outputFile] [typeName] [typeReceiver] [Features separated by space]". -// -// In the template the following are available: -// - typeName as {{.Name}} -// - typeReceiver as {{.Receiver}} -// - Features are available via map and can be evaluated as {{if index .Features "extended"}} -package main - -import ( - "bytes" - "fmt" - "go/format" - "os" - "strings" - "text/template" - - "github.com/iotaledger/hive.go/lo" -) - -func main() { - if len(os.Args) < 6 { - printUsage("not enough parameters") - } - - templateFilePath := os.Args[1] - conf := newConfiguration(os.Args[2], os.Args[3], os.Args[4], os.Args[5]) - - funcs := template.FuncMap{ - "firstLower": func(s string) string { - return strings.ToLower(s[0:1]) + s[1:] - }, - } - - tmplFile := lo.PanicOnErr(os.ReadFile(templateFilePath)) - - tmpl := template.Must( - template.New("gen"). - Funcs(funcs). - Parse(string(tmplFile)), - ) - - buffer := new(bytes.Buffer) - panicOnError(tmpl.Execute(buffer, conf)) - - formattedOutput := lo.PanicOnErr(format.Source(buffer.Bytes())) - - panicOnError(os.WriteFile(conf.FileName, formattedOutput, 0600)) -} - -// printUsage prints the usage of the variadic code generator in case of an error. -func printUsage(errorMsg string) { - _, _ = fmt.Fprintf(os.Stderr, "Error:\t%s\n\n", errorMsg) - _, _ = fmt.Fprintf(os.Stderr, "Usage of gen/cmd:\n") - _, _ = fmt.Fprintf(os.Stderr, "\tcmd [templateFile] [outputFile] [typeName] [typeReceiver] [features separated by space]\n") - - os.Exit(2) -} - -func panicOnError(err error) { - if err != nil { - panic(err) - } -} diff --git a/gen/cmd/configuration.go b/gen/cmd/configuration.go deleted file mode 100644 index 510079bf6..000000000 --- a/gen/cmd/configuration.go +++ /dev/null @@ -1,31 +0,0 @@ -package main - -import ( - "fmt" - "strings" -) - -type configuration struct { - FileName string - Name string - Receiver string - Features map[string]bool -} - -func newConfiguration(fileName, name, receiver, featuresStr string) *configuration { - features := make(map[string]bool) - for _, feature := range strings.Split(featuresStr, " ") { - features[feature] = true - } - - return &configuration{ - FileName: fileName, - Name: name, - Receiver: strings.ToLower(receiver), - Features: features, - } -} - -func (c *configuration) String() string { - return fmt.Sprintf("configuration{\n\tFileName:%s,\n\tName:%s,\n\tReceiver:%s,\n\tFeatures:%v,\n}\n", c.FileName, c.Name, c.Receiver, c.Features) -} diff --git a/gen/identifier_gen.go b/gen/identifier_gen.go index 89716ccdc..78927fe88 100644 --- a/gen/identifier_gen.go +++ b/gen/identifier_gen.go @@ -2,5 +2,5 @@ package gen -//go:generate go run ./cmd identifier.tmpl ../identifier.gen.go Identifier i "" -//go:generate go run ./cmd identifier.tmpl ../identifier_account.gen.go AccountID a "" +//go:generate go run github.com/iotaledger/hive.go/codegen/features/cmd@86973b2edb3b identifier.tmpl ../identifier.gen.go Identifier i "" +//go:generate go run github.com/iotaledger/hive.go/codegen/features/cmd@86973b2edb3b identifier.tmpl ../identifier_account.gen.go AccountID a "" diff --git a/gen/slot_identifier_gen.go b/gen/slot_identifier_gen.go index c0322c316..687532cba 100644 --- a/gen/slot_identifier_gen.go +++ b/gen/slot_identifier_gen.go @@ -2,8 +2,8 @@ package gen -//go:generate go run ./cmd slot_identifier.tmpl ../block_id.gen.go BlockID b "ids" -//go:generate go run ./cmd slot_identifier.tmpl ../commitment_id.gen.go CommitmentID c "" -//go:generate go run ./cmd slot_identifier.tmpl ../transaction_id.gen.go TransactionID t "ids" -//go:generate go run ./cmd slot_identifier.tmpl ../signed_transaction_id.gen.go SignedTransactionID t "ids" -//go:generate go run ./cmd slot_identifier.tmpl ../output_id.gen.go OutputID o "ids output" +//go:generate go run github.com/iotaledger/hive.go/codegen/features/cmd@86973b2edb3b slot_identifier.tmpl ../block_id.gen.go BlockID b "ids" +//go:generate go run github.com/iotaledger/hive.go/codegen/features/cmd@86973b2edb3b slot_identifier.tmpl ../commitment_id.gen.go CommitmentID c "" +//go:generate go run github.com/iotaledger/hive.go/codegen/features/cmd@86973b2edb3b slot_identifier.tmpl ../transaction_id.gen.go TransactionID t "ids" +//go:generate go run github.com/iotaledger/hive.go/codegen/features/cmd@86973b2edb3b slot_identifier.tmpl ../signed_transaction_id.gen.go SignedTransactionID t "ids" +//go:generate go run github.com/iotaledger/hive.go/codegen/features/cmd@86973b2edb3b slot_identifier.tmpl ../output_id.gen.go OutputID o "ids output" diff --git a/go.mod b/go.mod index 30306d34d..ece87be08 100644 --- a/go.mod +++ b/go.mod @@ -5,14 +5,14 @@ go 1.21 require ( github.com/eclipse/paho.mqtt.golang v1.4.3 github.com/ethereum/go-ethereum v1.12.2 - github.com/iotaledger/hive.go/constraints v0.0.0-20230929122509-67f34bfed40d - github.com/iotaledger/hive.go/core v1.0.0-rc.3.0.20230929122509-67f34bfed40d - github.com/iotaledger/hive.go/crypto v0.0.0-20230929122509-67f34bfed40d - github.com/iotaledger/hive.go/ierrors v0.0.0-20230929122509-67f34bfed40d + github.com/iotaledger/hive.go/constraints v0.0.0-20231005142627-86973b2edb3b + github.com/iotaledger/hive.go/core v1.0.0-rc.3.0.20231005142627-86973b2edb3b + github.com/iotaledger/hive.go/crypto v0.0.0-20231005142627-86973b2edb3b + github.com/iotaledger/hive.go/ierrors v0.0.0-20231005142627-86973b2edb3b github.com/iotaledger/hive.go/lo v0.0.0-20230929122509-67f34bfed40d github.com/iotaledger/hive.go/runtime v0.0.0-20230929122509-67f34bfed40d - github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20230929122509-67f34bfed40d - github.com/iotaledger/hive.go/stringify v0.0.0-20230929122509-67f34bfed40d + github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20231005142627-86973b2edb3b + github.com/iotaledger/hive.go/stringify v0.0.0-20231005142627-86973b2edb3b github.com/pasztorpisti/qs v0.0.0-20171216220353-8d6c33ee906c github.com/stretchr/testify v1.8.4 golang.org/x/crypto v0.12.0 @@ -28,6 +28,7 @@ require ( github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 // indirect github.com/holiman/uint256 v1.2.3 // indirect github.com/iancoleman/orderedmap v0.3.0 // indirect + github.com/iotaledger/hive.go/codegen v0.0.0-20231005142627-86973b2edb3b // indirect github.com/kr/text v0.2.0 // indirect github.com/mr-tron/base58 v1.2.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect diff --git a/go.sum b/go.sum index 552f4e460..37ff8d311 100644 --- a/go.sum +++ b/go.sum @@ -23,22 +23,24 @@ github.com/holiman/uint256 v1.2.3 h1:K8UWO1HUJpRMXBxbmaY1Y8IAMZC/RsKB+ArEnnK4l5o github.com/holiman/uint256 v1.2.3/go.mod h1:SC8Ryt4n+UBbPbIBKaG9zbbDlp4jOru9xFZmPzLUTxw= github.com/iancoleman/orderedmap v0.3.0 h1:5cbR2grmZR/DiVt+VJopEhtVs9YGInGIxAoMJn+Ichc= github.com/iancoleman/orderedmap v0.3.0/go.mod h1:XuLcCUkdL5owUCQeF2Ue9uuw1EptkJDkXXS7VoV7XGE= -github.com/iotaledger/hive.go/constraints v0.0.0-20230929122509-67f34bfed40d h1:bZXrxulDoDBsNg0wtXowrAyltjfgZahiGYuAoS5GKU4= -github.com/iotaledger/hive.go/constraints v0.0.0-20230929122509-67f34bfed40d/go.mod h1:dOBOM2s4se3HcWefPe8sQLUalGXJ8yVXw58oK8jke3s= -github.com/iotaledger/hive.go/core v1.0.0-rc.3.0.20230929122509-67f34bfed40d h1:pRcB0wfWAlfDJ10ZZ6LK1ukRXcPaL299LLU/zbYWnsQ= -github.com/iotaledger/hive.go/core v1.0.0-rc.3.0.20230929122509-67f34bfed40d/go.mod h1:jn3TNmiNRIiQm/rS4VD+7wFHI2+UXABHvCA3PbQxBqI= -github.com/iotaledger/hive.go/crypto v0.0.0-20230929122509-67f34bfed40d h1:Vn8BY/hLTcKJWh8LCw6PDTbCK2562wq93MPynV1pHjE= -github.com/iotaledger/hive.go/crypto v0.0.0-20230929122509-67f34bfed40d/go.mod h1:jP68na941d9uq7RtnA8aQ/FtIGRGz/51cU4uXrInQFU= -github.com/iotaledger/hive.go/ierrors v0.0.0-20230929122509-67f34bfed40d h1:tmaZvkBCP/OrQrwC728AEFtRAW8YUHBVNE8IXxtd4C4= -github.com/iotaledger/hive.go/ierrors v0.0.0-20230929122509-67f34bfed40d/go.mod h1:HcE8B5lP96enc/OALTb2/rIIi+yOLouRoHOKRclKmC8= +github.com/iotaledger/hive.go/codegen v0.0.0-20231005142627-86973b2edb3b h1:RpCqfmmxrkTdxPm56UzF1QuHppTo3VtyzhfaUUfzVA0= +github.com/iotaledger/hive.go/codegen v0.0.0-20231005142627-86973b2edb3b/go.mod h1:zBiQaY4DL7xx/gNgb1MWqMaV62x2o937nBCEaW++ztI= +github.com/iotaledger/hive.go/constraints v0.0.0-20231005142627-86973b2edb3b h1:8FdKoB755PjCL1aHTi+2rPt9lCUS4B2wg2fNKykw5dc= +github.com/iotaledger/hive.go/constraints v0.0.0-20231005142627-86973b2edb3b/go.mod h1:dOBOM2s4se3HcWefPe8sQLUalGXJ8yVXw58oK8jke3s= +github.com/iotaledger/hive.go/core v1.0.0-rc.3.0.20231005142627-86973b2edb3b h1:gQ+Wqg8h/LRpgX3CsmaOZYdMIBVL4fAPIrZbmA6Wn3Q= +github.com/iotaledger/hive.go/core v1.0.0-rc.3.0.20231005142627-86973b2edb3b/go.mod h1:jn3TNmiNRIiQm/rS4VD+7wFHI2+UXABHvCA3PbQxBqI= +github.com/iotaledger/hive.go/crypto v0.0.0-20231005142627-86973b2edb3b h1:F91AhJfeVN/XdvzUObUXa5mA38VezBZ9GHhdfQw4fVg= +github.com/iotaledger/hive.go/crypto v0.0.0-20231005142627-86973b2edb3b/go.mod h1:jP68na941d9uq7RtnA8aQ/FtIGRGz/51cU4uXrInQFU= +github.com/iotaledger/hive.go/ierrors v0.0.0-20231005142627-86973b2edb3b h1:D07ocbgOyj2d/AGjrIuAxIaQC5SQDndiKp9UaaQwLas= +github.com/iotaledger/hive.go/ierrors v0.0.0-20231005142627-86973b2edb3b/go.mod h1:HcE8B5lP96enc/OALTb2/rIIi+yOLouRoHOKRclKmC8= github.com/iotaledger/hive.go/lo v0.0.0-20230929122509-67f34bfed40d h1:qNmg1DUvge8zPvygQEoulQjLG7gFzWKqPMJ3r7ZESm0= github.com/iotaledger/hive.go/lo v0.0.0-20230929122509-67f34bfed40d/go.mod h1:4oKCdMEhHMLCudBz79kuvJmgSY/DhfVePNIyJhew/80= github.com/iotaledger/hive.go/runtime v0.0.0-20230929122509-67f34bfed40d h1:mn2Gax95UuUpuzEi4osLk+1IBjv5q56LwcxF/lAxk38= github.com/iotaledger/hive.go/runtime v0.0.0-20230929122509-67f34bfed40d/go.mod h1:fXVyQ1MAwxe/EmjAnG8WcQqbzGk9EW/FsJ/n16H/f/w= -github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20230929122509-67f34bfed40d h1:1839CFkegKrSvTfWkgYHpH1pudehOXxX05Mzy1KSR7I= -github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20230929122509-67f34bfed40d/go.mod h1:IJgaaxbgKCsNat18jlJJEAxCY2oVYR3F30B+M4vJ89I= -github.com/iotaledger/hive.go/stringify v0.0.0-20230929122509-67f34bfed40d h1:ekHWRypoaiCXgrJVUQS7rCewsK3FuG1gTbPxu5jYn9c= -github.com/iotaledger/hive.go/stringify v0.0.0-20230929122509-67f34bfed40d/go.mod h1:FTo/UWzNYgnQ082GI9QVM9HFDERqf9rw9RivNpqrnTs= +github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20231005142627-86973b2edb3b h1:6anjtWbaCszD5h43psnE8lsgIM0etpjr62ZlN59t0H8= +github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20231005142627-86973b2edb3b/go.mod h1:IJgaaxbgKCsNat18jlJJEAxCY2oVYR3F30B+M4vJ89I= +github.com/iotaledger/hive.go/stringify v0.0.0-20231005142627-86973b2edb3b h1:cc9VsDzLxPAaC8fj96EA1bJxbmrEZndJV+3SmG+HHOs= +github.com/iotaledger/hive.go/stringify v0.0.0-20231005142627-86973b2edb3b/go.mod h1:FTo/UWzNYgnQ082GI9QVM9HFDERqf9rw9RivNpqrnTs= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= From a45e0bd527b1220ea4066e741e2badccb1052f6c Mon Sep 17 00:00:00 2001 From: jonastheis <4181434+jonastheis@users.noreply.github.com> Date: Thu, 5 Oct 2023 21:10:31 +0300 Subject: [PATCH 14/15] Use firstLower for mutexes in slot_identifier.tmpl --- block_id.gen.go | 16 ++++++++-------- commitment_id.gen.go | 16 ++++++++-------- gen/slot_identifier.tmpl | 16 ++++++++-------- identifier.gen.go | 32 ++++++++++++++++---------------- identifier_account.gen.go | 32 ++++++++++++++++---------------- output_id.gen.go | 16 ++++++++-------- signed_transaction_id.gen.go | 16 ++++++++-------- transaction_id.gen.go | 16 ++++++++-------- 8 files changed, 80 insertions(+), 80 deletions(-) diff --git a/block_id.gen.go b/block_id.gen.go index df704787a..353a90d11 100644 --- a/block_id.gen.go +++ b/block_id.gen.go @@ -121,23 +121,23 @@ var ( // BlockIDAliases contains a dictionary of identifiers associated to their human-readable alias. BlockIDAliases = make(map[BlockID]string) - // BlockIDAliasesMutex is the mutex that is used to synchronize access to the previous map. - BlockIDAliasesMutex = sync.RWMutex{} + // blockIDAliasesMutex is the mutex that is used to synchronize access to the previous map. + blockIDAliasesMutex = sync.RWMutex{} ) // RegisterAlias allows to register a human-readable alias for the Identifier which will be used as a replacement for // the String method. func (b BlockID) RegisterAlias(alias string) { - BlockIDAliasesMutex.Lock() - defer BlockIDAliasesMutex.Unlock() + blockIDAliasesMutex.Lock() + defer blockIDAliasesMutex.Unlock() BlockIDAliases[b] = alias } // Alias returns the human-readable alias of the Identifier (or the base58 encoded bytes of no alias was set). func (b BlockID) Alias() (alias string) { - BlockIDAliasesMutex.RLock() - defer BlockIDAliasesMutex.RUnlock() + blockIDAliasesMutex.RLock() + defer blockIDAliasesMutex.RUnlock() if existingAlias, exists := BlockIDAliases[b]; exists { return existingAlias @@ -148,8 +148,8 @@ func (b BlockID) Alias() (alias string) { // UnregisterAlias allows to unregister a previously registered alias. func (b BlockID) UnregisterAlias() { - BlockIDAliasesMutex.Lock() - defer BlockIDAliasesMutex.Unlock() + blockIDAliasesMutex.Lock() + defer blockIDAliasesMutex.Unlock() delete(BlockIDAliases, b) } diff --git a/commitment_id.gen.go b/commitment_id.gen.go index bdd3150fe..069a1c751 100644 --- a/commitment_id.gen.go +++ b/commitment_id.gen.go @@ -120,23 +120,23 @@ var ( // CommitmentIDAliases contains a dictionary of identifiers associated to their human-readable alias. CommitmentIDAliases = make(map[CommitmentID]string) - // CommitmentIDAliasesMutex is the mutex that is used to synchronize access to the previous map. - CommitmentIDAliasesMutex = sync.RWMutex{} + // commitmentIDAliasesMutex is the mutex that is used to synchronize access to the previous map. + commitmentIDAliasesMutex = sync.RWMutex{} ) // RegisterAlias allows to register a human-readable alias for the Identifier which will be used as a replacement for // the String method. func (c CommitmentID) RegisterAlias(alias string) { - CommitmentIDAliasesMutex.Lock() - defer CommitmentIDAliasesMutex.Unlock() + commitmentIDAliasesMutex.Lock() + defer commitmentIDAliasesMutex.Unlock() CommitmentIDAliases[c] = alias } // Alias returns the human-readable alias of the Identifier (or the base58 encoded bytes of no alias was set). func (c CommitmentID) Alias() (alias string) { - CommitmentIDAliasesMutex.RLock() - defer CommitmentIDAliasesMutex.RUnlock() + commitmentIDAliasesMutex.RLock() + defer commitmentIDAliasesMutex.RUnlock() if existingAlias, exists := CommitmentIDAliases[c]; exists { return existingAlias @@ -147,8 +147,8 @@ func (c CommitmentID) Alias() (alias string) { // UnregisterAlias allows to unregister a previously registered alias. func (c CommitmentID) UnregisterAlias() { - CommitmentIDAliasesMutex.Lock() - defer CommitmentIDAliasesMutex.Unlock() + commitmentIDAliasesMutex.Lock() + defer commitmentIDAliasesMutex.Unlock() delete(CommitmentIDAliases, c) } diff --git a/gen/slot_identifier.tmpl b/gen/slot_identifier.tmpl index eb78d4a59..10768df02 100644 --- a/gen/slot_identifier.tmpl +++ b/gen/slot_identifier.tmpl @@ -137,23 +137,23 @@ var ( // {{.Name}}Aliases contains a dictionary of identifiers associated to their human-readable alias. {{.Name}}Aliases = make(map[{{.Name}}]string) - // {{.Name}}AliasesMutex is the mutex that is used to synchronize access to the previous map. - {{.Name}}AliasesMutex = sync.RWMutex{} + // {{firstLower .Name}}AliasesMutex is the mutex that is used to synchronize access to the previous map. + {{firstLower .Name}}AliasesMutex = sync.RWMutex{} ) // RegisterAlias allows to register a human-readable alias for the Identifier which will be used as a replacement for // the String method. func ({{.Receiver}} {{.Name}}) RegisterAlias(alias string) { - {{.Name}}AliasesMutex.Lock() - defer {{.Name}}AliasesMutex.Unlock() + {{firstLower .Name}}AliasesMutex.Lock() + defer {{firstLower .Name}}AliasesMutex.Unlock() {{.Name}}Aliases[{{.Receiver}}] = alias } // Alias returns the human-readable alias of the Identifier (or the base58 encoded bytes of no alias was set). func ({{.Receiver}} {{.Name}}) Alias() (alias string) { - {{.Name}}AliasesMutex.RLock() - defer {{.Name}}AliasesMutex.RUnlock() + {{firstLower .Name}}AliasesMutex.RLock() + defer {{firstLower .Name}}AliasesMutex.RUnlock() if existingAlias, exists := {{.Name}}Aliases[{{.Receiver}}]; exists { return existingAlias @@ -164,8 +164,8 @@ func ({{.Receiver}} {{.Name}}) Alias() (alias string) { // UnregisterAlias allows to unregister a previously registered alias. func ({{.Receiver}} {{.Name}}) UnregisterAlias() { - {{.Name}}AliasesMutex.Lock() - defer {{.Name}}AliasesMutex.Unlock() + {{firstLower .Name}}AliasesMutex.Lock() + defer {{firstLower .Name}}AliasesMutex.Unlock() delete({{.Name}}Aliases, {{.Receiver}}) } diff --git a/identifier.gen.go b/identifier.gen.go index d86cec063..1f0a17de7 100644 --- a/identifier.gen.go +++ b/identifier.gen.go @@ -97,28 +97,28 @@ func (i Identifier) String() string { } var ( - // identifierIAliases contains a dictionary of Identifiers associated to their human-readable alias. - identifierIAliases = make(map[Identifier]string) + // identifierAliases contains a dictionary of Identifiers associated to their human-readable alias. + identifierAliases = make(map[Identifier]string) - // identifierIAliasesMutex is the mutex that is used to synchronize access to the previous map. - identifierIAliasesMutex = sync.RWMutex{} + // identifierAliasesMutex is the mutex that is used to synchronize access to the previous map. + identifierAliasesMutex = sync.RWMutex{} ) // RegisterAlias allows to register a human-readable alias for the Identifier which will be used as a replacement for // the String method. func (i Identifier) RegisterAlias(alias string) { - identifierIAliasesMutex.Lock() - defer identifierIAliasesMutex.Unlock() + identifierAliasesMutex.Lock() + defer identifierAliasesMutex.Unlock() - identifierIAliases[i] = alias + identifierAliases[i] = alias } // Alias returns the human-readable alias of the Identifier (or the hex encoded bytes if no alias was set). func (i Identifier) Alias() (alias string) { - identifierIAliasesMutex.RLock() - defer identifierIAliasesMutex.RUnlock() + identifierAliasesMutex.RLock() + defer identifierAliasesMutex.RUnlock() - if existingAlias, exists := identifierIAliases[i]; exists { + if existingAlias, exists := identifierAliases[i]; exists { return existingAlias } @@ -127,16 +127,16 @@ func (i Identifier) Alias() (alias string) { // UnregisterAlias allows to unregister a previously registered alias. func (i Identifier) UnregisterAlias() { - identifierIAliasesMutex.Lock() - defer identifierIAliasesMutex.Unlock() + identifierAliasesMutex.Lock() + defer identifierAliasesMutex.Unlock() - delete(identifierIAliases, i) + delete(identifierAliases, i) } // UnregisterIdentifierAliases allows to unregister all previously registered aliases. func UnregisterIdentifierAliases() { - identifierIAliasesMutex.Lock() - defer identifierIAliasesMutex.Unlock() + identifierAliasesMutex.Lock() + defer identifierAliasesMutex.Unlock() - identifierIAliases = make(map[Identifier]string) + identifierAliases = make(map[Identifier]string) } diff --git a/identifier_account.gen.go b/identifier_account.gen.go index 34eb5a7a5..fe66a1bc6 100644 --- a/identifier_account.gen.go +++ b/identifier_account.gen.go @@ -97,28 +97,28 @@ func (a AccountID) String() string { } var ( - // accountidAAliases contains a dictionary of AccountIDs associated to their human-readable alias. - accountidAAliases = make(map[AccountID]string) + // accountIDAliases contains a dictionary of AccountIDs associated to their human-readable alias. + accountIDAliases = make(map[AccountID]string) - // accountidAAliasesMutex is the mutex that is used to synchronize access to the previous map. - accountidAAliasesMutex = sync.RWMutex{} + // accountIDAliasesMutex is the mutex that is used to synchronize access to the previous map. + accountIDAliasesMutex = sync.RWMutex{} ) // RegisterAlias allows to register a human-readable alias for the AccountID which will be used as a replacement for // the String method. func (a AccountID) RegisterAlias(alias string) { - accountidAAliasesMutex.Lock() - defer accountidAAliasesMutex.Unlock() + accountIDAliasesMutex.Lock() + defer accountIDAliasesMutex.Unlock() - accountidAAliases[a] = alias + accountIDAliases[a] = alias } // Alias returns the human-readable alias of the AccountID (or the hex encoded bytes if no alias was set). func (a AccountID) Alias() (alias string) { - accountidAAliasesMutex.RLock() - defer accountidAAliasesMutex.RUnlock() + accountIDAliasesMutex.RLock() + defer accountIDAliasesMutex.RUnlock() - if existingAlias, exists := accountidAAliases[a]; exists { + if existingAlias, exists := accountIDAliases[a]; exists { return existingAlias } @@ -127,16 +127,16 @@ func (a AccountID) Alias() (alias string) { // UnregisterAlias allows to unregister a previously registered alias. func (a AccountID) UnregisterAlias() { - accountidAAliasesMutex.Lock() - defer accountidAAliasesMutex.Unlock() + accountIDAliasesMutex.Lock() + defer accountIDAliasesMutex.Unlock() - delete(accountidAAliases, a) + delete(accountIDAliases, a) } // UnregisterAccountIDAliases allows to unregister all previously registered aliases. func UnregisterAccountIDAliases() { - accountidAAliasesMutex.Lock() - defer accountidAAliasesMutex.Unlock() + accountIDAliasesMutex.Lock() + defer accountIDAliasesMutex.Unlock() - accountidAAliases = make(map[AccountID]string) + accountIDAliases = make(map[AccountID]string) } diff --git a/output_id.gen.go b/output_id.gen.go index 22b5900cf..753257f53 100644 --- a/output_id.gen.go +++ b/output_id.gen.go @@ -126,23 +126,23 @@ var ( // OutputIDAliases contains a dictionary of identifiers associated to their human-readable alias. OutputIDAliases = make(map[OutputID]string) - // OutputIDAliasesMutex is the mutex that is used to synchronize access to the previous map. - OutputIDAliasesMutex = sync.RWMutex{} + // outputIDAliasesMutex is the mutex that is used to synchronize access to the previous map. + outputIDAliasesMutex = sync.RWMutex{} ) // RegisterAlias allows to register a human-readable alias for the Identifier which will be used as a replacement for // the String method. func (o OutputID) RegisterAlias(alias string) { - OutputIDAliasesMutex.Lock() - defer OutputIDAliasesMutex.Unlock() + outputIDAliasesMutex.Lock() + defer outputIDAliasesMutex.Unlock() OutputIDAliases[o] = alias } // Alias returns the human-readable alias of the Identifier (or the base58 encoded bytes of no alias was set). func (o OutputID) Alias() (alias string) { - OutputIDAliasesMutex.RLock() - defer OutputIDAliasesMutex.RUnlock() + outputIDAliasesMutex.RLock() + defer outputIDAliasesMutex.RUnlock() if existingAlias, exists := OutputIDAliases[o]; exists { return existingAlias @@ -153,8 +153,8 @@ func (o OutputID) Alias() (alias string) { // UnregisterAlias allows to unregister a previously registered alias. func (o OutputID) UnregisterAlias() { - OutputIDAliasesMutex.Lock() - defer OutputIDAliasesMutex.Unlock() + outputIDAliasesMutex.Lock() + defer outputIDAliasesMutex.Unlock() delete(OutputIDAliases, o) } diff --git a/signed_transaction_id.gen.go b/signed_transaction_id.gen.go index 35973505a..aea3d52f0 100644 --- a/signed_transaction_id.gen.go +++ b/signed_transaction_id.gen.go @@ -121,23 +121,23 @@ var ( // SignedTransactionIDAliases contains a dictionary of identifiers associated to their human-readable alias. SignedTransactionIDAliases = make(map[SignedTransactionID]string) - // SignedTransactionIDAliasesMutex is the mutex that is used to synchronize access to the previous map. - SignedTransactionIDAliasesMutex = sync.RWMutex{} + // signedTransactionIDAliasesMutex is the mutex that is used to synchronize access to the previous map. + signedTransactionIDAliasesMutex = sync.RWMutex{} ) // RegisterAlias allows to register a human-readable alias for the Identifier which will be used as a replacement for // the String method. func (t SignedTransactionID) RegisterAlias(alias string) { - SignedTransactionIDAliasesMutex.Lock() - defer SignedTransactionIDAliasesMutex.Unlock() + signedTransactionIDAliasesMutex.Lock() + defer signedTransactionIDAliasesMutex.Unlock() SignedTransactionIDAliases[t] = alias } // Alias returns the human-readable alias of the Identifier (or the base58 encoded bytes of no alias was set). func (t SignedTransactionID) Alias() (alias string) { - SignedTransactionIDAliasesMutex.RLock() - defer SignedTransactionIDAliasesMutex.RUnlock() + signedTransactionIDAliasesMutex.RLock() + defer signedTransactionIDAliasesMutex.RUnlock() if existingAlias, exists := SignedTransactionIDAliases[t]; exists { return existingAlias @@ -148,8 +148,8 @@ func (t SignedTransactionID) Alias() (alias string) { // UnregisterAlias allows to unregister a previously registered alias. func (t SignedTransactionID) UnregisterAlias() { - SignedTransactionIDAliasesMutex.Lock() - defer SignedTransactionIDAliasesMutex.Unlock() + signedTransactionIDAliasesMutex.Lock() + defer signedTransactionIDAliasesMutex.Unlock() delete(SignedTransactionIDAliases, t) } diff --git a/transaction_id.gen.go b/transaction_id.gen.go index ed8eadadd..f06573d0d 100644 --- a/transaction_id.gen.go +++ b/transaction_id.gen.go @@ -121,23 +121,23 @@ var ( // TransactionIDAliases contains a dictionary of identifiers associated to their human-readable alias. TransactionIDAliases = make(map[TransactionID]string) - // TransactionIDAliasesMutex is the mutex that is used to synchronize access to the previous map. - TransactionIDAliasesMutex = sync.RWMutex{} + // transactionIDAliasesMutex is the mutex that is used to synchronize access to the previous map. + transactionIDAliasesMutex = sync.RWMutex{} ) // RegisterAlias allows to register a human-readable alias for the Identifier which will be used as a replacement for // the String method. func (t TransactionID) RegisterAlias(alias string) { - TransactionIDAliasesMutex.Lock() - defer TransactionIDAliasesMutex.Unlock() + transactionIDAliasesMutex.Lock() + defer transactionIDAliasesMutex.Unlock() TransactionIDAliases[t] = alias } // Alias returns the human-readable alias of the Identifier (or the base58 encoded bytes of no alias was set). func (t TransactionID) Alias() (alias string) { - TransactionIDAliasesMutex.RLock() - defer TransactionIDAliasesMutex.RUnlock() + transactionIDAliasesMutex.RLock() + defer transactionIDAliasesMutex.RUnlock() if existingAlias, exists := TransactionIDAliases[t]; exists { return existingAlias @@ -148,8 +148,8 @@ func (t TransactionID) Alias() (alias string) { // UnregisterAlias allows to unregister a previously registered alias. func (t TransactionID) UnregisterAlias() { - TransactionIDAliasesMutex.Lock() - defer TransactionIDAliasesMutex.Unlock() + transactionIDAliasesMutex.Lock() + defer transactionIDAliasesMutex.Unlock() delete(TransactionIDAliases, t) } From 62e6761a7b7ceb6b0e7b3bc0df7461327f77cea5 Mon Sep 17 00:00:00 2001 From: jonastheis <4181434+jonastheis@users.noreply.github.com> Date: Thu, 5 Oct 2023 21:45:34 +0300 Subject: [PATCH 15/15] Add ids feature to CommitmentID --- commitment_id.gen.go | 49 +++++++++++++++++++++++++++++++++++++- gen/slot_identifier_gen.go | 2 +- 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/commitment_id.gen.go b/commitment_id.gen.go index 069a1c751..f1ccd8386 100644 --- a/commitment_id.gen.go +++ b/commitment_id.gen.go @@ -3,10 +3,11 @@ package iotago // Code generated by go generate; DO NOT EDIT. Check gen/ directory instead. import ( + "bytes" "encoding/binary" "encoding/hex" "fmt" - + "sort" "sync" "golang.org/x/crypto/blake2b" @@ -152,3 +153,49 @@ func (c CommitmentID) UnregisterAlias() { delete(CommitmentIDAliases, c) } + +type CommitmentIDs []CommitmentID + +// ToHex converts the CommitmentIDs to their hex representation. +func (ids CommitmentIDs) ToHex() []string { + hexIDs := make([]string, len(ids)) + for i, c := range ids { + hexIDs[i] = hexutil.EncodeHex(c[:]) + } + + return hexIDs +} + +// RemoveDupsAndSort removes duplicated CommitmentIDs and sorts the slice by the lexical ordering. +func (ids CommitmentIDs) RemoveDupsAndSort() CommitmentIDs { + sorted := append(CommitmentIDs{}, ids...) + sort.Slice(sorted, func(i, j int) bool { + return bytes.Compare(sorted[i][:], sorted[j][:]) == -1 + }) + + var result CommitmentIDs + var prev CommitmentID + for i, c := range sorted { + if i == 0 || !bytes.Equal(prev[:], c[:]) { + result = append(result, c) + } + prev = c + } + + return result +} + +// CommitmentIDsFromHexString converts the given block IDs from their hex to CommitmentID representation. +func CommitmentIDsFromHexString(CommitmentIDsHex []string) (CommitmentIDs, error) { + result := make(CommitmentIDs, len(CommitmentIDsHex)) + + for i, hexString := range CommitmentIDsHex { + CommitmentID, err := CommitmentIDFromHexString(hexString) + if err != nil { + return nil, err + } + result[i] = CommitmentID + } + + return result, nil +} diff --git a/gen/slot_identifier_gen.go b/gen/slot_identifier_gen.go index 687532cba..07a948e7f 100644 --- a/gen/slot_identifier_gen.go +++ b/gen/slot_identifier_gen.go @@ -3,7 +3,7 @@ package gen //go:generate go run github.com/iotaledger/hive.go/codegen/features/cmd@86973b2edb3b slot_identifier.tmpl ../block_id.gen.go BlockID b "ids" -//go:generate go run github.com/iotaledger/hive.go/codegen/features/cmd@86973b2edb3b slot_identifier.tmpl ../commitment_id.gen.go CommitmentID c "" +//go:generate go run github.com/iotaledger/hive.go/codegen/features/cmd@86973b2edb3b slot_identifier.tmpl ../commitment_id.gen.go CommitmentID c "ids" //go:generate go run github.com/iotaledger/hive.go/codegen/features/cmd@86973b2edb3b slot_identifier.tmpl ../transaction_id.gen.go TransactionID t "ids" //go:generate go run github.com/iotaledger/hive.go/codegen/features/cmd@86973b2edb3b slot_identifier.tmpl ../signed_transaction_id.gen.go SignedTransactionID t "ids" //go:generate go run github.com/iotaledger/hive.go/codegen/features/cmd@86973b2edb3b slot_identifier.tmpl ../output_id.gen.go OutputID o "ids output"