Skip to content

Commit

Permalink
Unify restricted addresses in RestrictedAddress type
Browse files Browse the repository at this point in the history
  • Loading branch information
muXxer committed Sep 18, 2023
1 parent 7b8bf97 commit d327065
Show file tree
Hide file tree
Showing 14 changed files with 983 additions and 662 deletions.
61 changes: 32 additions & 29 deletions address.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import (
var (
// ErrUnknownAddrType gets returned for unknown address types.
ErrUnknownAddrType = ierrors.New("unknown address type")
// ErrNestedMultiAddress gets returned when a MultiAddress is nested inside a MultiAddress.
ErrNestedMultiAddress = ierrors.New("multi addresses can't be nested")
// ErrInvalidNestedAddressType gets returned when a nested address inside a MultiAddress or RestrictedAddress is invalid.
ErrInvalidNestedAddressType = ierrors.New("invalid nested address type")
)

// AddressType defines the type of addresses.
Expand All @@ -22,8 +22,6 @@ type AddressType byte
const (
// AddressEd25519 denotes an Ed25519 address.
AddressEd25519 AddressType = 0
// AddressRestrictedEd25519 denotes an Ed25519 address that has a capability bitmask.
AddressRestrictedEd25519 AddressType = 1
// AddressAccount denotes an Account address.
AddressAccount AddressType = 8
// AddressNFT denotes an NFT address.
Expand All @@ -32,6 +30,8 @@ const (
AddressImplicitAccountCreation AddressType = 24
// AddressMulti denotes a multi address.
AddressMulti AddressType = 32
// AddressRestricted denotes a restricted address that has a capability bitmask.
AddressRestricted AddressType = 40
)

func (addrType AddressType) String() string {
Expand All @@ -51,12 +51,13 @@ func (addrType AddressType) String() string {
type AddressTypeSet map[AddressType]struct{}

var (
addressNames = [AddressMulti + 1]string{
"Ed25519Address", "RestrictedEd25519Address", "", "", "", "", "", "",
addressNames = [AddressRestricted + 1]string{
"Ed25519Address", "", "", "", "", "", "", "",
"AccountAddress", "", "", "", "", "", "", "",
"NFTAddress", "", "", "", "", "", "", "",
"ImplicitAccountCreationAddress", "", "", "", "", "", "", "",
"MultiAddress",
"MultiAddress", "", "", "", "", "", "", "",
"RestrictedAddress",
}
)

Expand All @@ -76,7 +77,6 @@ type Address interface {
Sizer
NonEphemeralObject
fmt.Stringer
AddressCapabilities

// Type returns the type of the address.
Type() AddressType
Expand Down Expand Up @@ -108,11 +108,6 @@ type AddressCapabilities interface {
CannotReceiveDelegationOutputs() bool
}

type RestrictedAddress interface {
Address
AllowedCapabilitiesBitMask() AddressCapabilitiesBitMask
}

// DirectUnlockableAddress is a type of Address which can be directly unlocked.
type DirectUnlockableAddress interface {
Address
Expand Down Expand Up @@ -147,20 +142,20 @@ type UTXOIDChainID interface {
FromOutputID(id OutputID) ChainID
}

func newAddress(addressType byte) (address Address, err error) {
switch AddressType(addressType) {
func newAddress(addressType AddressType) (address Address, err error) {
switch addressType {
case AddressEd25519:
return &Ed25519Address{}, nil
case AddressRestrictedEd25519:
return &RestrictedEd25519Address{}, nil
case AddressAccount:
return &AccountAddress{}, nil
case AddressNFT:
return &NFTAddress{}, nil
case AddressImplicitAccountCreation:
return &ImplicitAccountCreationAddress{}, nil
case AddressMulti:
return nil, ErrMultiAddrCannotBeReconstructedViaBech32
return &MultiAddress{}, nil
case AddressRestricted:
return &RestrictedAddress{}, nil
default:
return nil, ierrors.Wrapf(ErrUnknownAddrType, "type %d", addressType)
}
Expand All @@ -175,16 +170,6 @@ func bech32StringBytes(hrp NetworkPrefix, bytes []byte) string {
return s
}

func bech32StringAddress(hrp NetworkPrefix, addr Address) string {
serixAPI := CommonSerixAPI()
bytes, err := serixAPI.Encode(context.Background(), addr)
if err != nil {
panic(err)
}

return bech32StringBytes(hrp, bytes)
}

// ParseBech32 decodes a bech32 encoded string.
func ParseBech32(s string) (NetworkPrefix, Address, error) {
hrp, addrData, err := bech32.Decode(s)
Expand All @@ -196,7 +181,25 @@ func ParseBech32(s string) (NetworkPrefix, Address, error) {
return "", nil, serializer.ErrDeserializationNotEnoughData
}

addr, err := newAddress(addrData[0])
addrType := AddressType(addrData[0])

// check for invalid MultiAddresses in bech32 string
// MultiAddresses are hashed and can't be reconstructed via bech32
//nolint:exhaustive
switch addrType {
case AddressMulti:
return "", nil, ErrMultiAddrCannotBeReconstructedViaBech32
case AddressRestricted:
if len(addrData) == 1 {
return "", nil, serializer.ErrDeserializationNotEnoughData
}
underlyingAddrType := AddressType(addrData[1])
if underlyingAddrType == AddressMulti {
return "", nil, ErrMultiAddrCannotBeReconstructedViaBech32
}
}

addr, err := newAddress(addrType)
if err != nil {
return "", nil, err
}
Expand Down
34 changes: 1 addition & 33 deletions address_account.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ func (addr *AccountAddress) Type() AddressType {
}

func (addr *AccountAddress) Bech32(hrp NetworkPrefix) string {
return bech32StringAddress(hrp, addr)
return bech32StringBytes(hrp, addr.ID())
}

func (addr *AccountAddress) String() string {
Expand All @@ -74,38 +74,6 @@ func (addr *AccountAddress) Size() int {
return AccountAddressSerializedBytesSize
}

func (addr *AccountAddress) CannotReceiveNativeTokens() bool {
return false
}

func (addr *AccountAddress) CannotReceiveMana() bool {
return false
}

func (addr *AccountAddress) CannotReceiveOutputsWithTimelockUnlockCondition() bool {
return false
}

func (addr *AccountAddress) CannotReceiveOutputsWithExpirationUnlockCondition() bool {
return false
}

func (addr *AccountAddress) CannotReceiveOutputsWithStorageDepositReturnUnlockCondition() bool {
return false
}

func (addr *AccountAddress) CannotReceiveAccountOutputs() bool {
return false
}

func (addr *AccountAddress) CannotReceiveNFTOutputs() bool {
return false
}

func (addr *AccountAddress) CannotReceiveDelegationOutputs() bool {
return false
}

// AccountAddressFromOutputID returns the account address computed from a given OutputID.
func AccountAddressFromOutputID(outputID OutputID) *AccountAddress {
address := blake2b.Sum256(outputID[:])
Expand Down
34 changes: 1 addition & 33 deletions address_ed25519.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ func (addr *Ed25519Address) Type() AddressType {
}

func (addr *Ed25519Address) Bech32(hrp NetworkPrefix) string {
return bech32StringAddress(hrp, addr)
return bech32StringBytes(hrp, addr.ID())
}

func (addr *Ed25519Address) String() string {
Expand All @@ -76,38 +76,6 @@ func (addr *Ed25519Address) Size() int {
return Ed25519AddressSerializedBytesSize
}

func (addr *Ed25519Address) CannotReceiveNativeTokens() bool {
return false
}

func (addr *Ed25519Address) CannotReceiveMana() bool {
return false
}

func (addr *Ed25519Address) CannotReceiveOutputsWithTimelockUnlockCondition() bool {
return false
}

func (addr *Ed25519Address) CannotReceiveOutputsWithExpirationUnlockCondition() bool {
return false
}

func (addr *Ed25519Address) CannotReceiveOutputsWithStorageDepositReturnUnlockCondition() bool {
return false
}

func (addr *Ed25519Address) CannotReceiveAccountOutputs() bool {
return false
}

func (addr *Ed25519Address) CannotReceiveNFTOutputs() bool {
return false
}

func (addr *Ed25519Address) CannotReceiveDelegationOutputs() bool {
return false
}

// Ed25519AddressFromPubKey returns the address belonging to the given Ed25519 public key.
func Ed25519AddressFromPubKey(pubKey ed25519.PublicKey) *Ed25519Address {
address := blake2b.Sum256(pubKey[:])
Expand Down
2 changes: 1 addition & 1 deletion address_implicit_account_creation.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ func (addr *ImplicitAccountCreationAddress) Type() AddressType {
}

func (addr *ImplicitAccountCreationAddress) Bech32(hrp NetworkPrefix) string {
return bech32StringAddress(hrp, addr)
return bech32StringBytes(hrp, addr.ID())
}

func (addr *ImplicitAccountCreationAddress) String() string {
Expand Down
77 changes: 5 additions & 72 deletions address_multi.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,18 +37,15 @@ type AddressesWithWeight []*AddressWithWeight

// MultiAddress defines a multi address that consists of addresses with weights and
// a threshold value that needs to be reached to unlock the multi address.
// It has a capability bitmask that enables additional features.
type MultiAddress struct {
Addresses AddressesWithWeight `serix:"0,mapKey=addresses"`
Threshold uint16 `serix:"1,mapKey=threshold"`
AllowedCapabilities AddressCapabilitiesBitMask `serix:"2,mapKey=allowedCapabilities,lengthPrefixType=uint8,maxLen=1"`
Addresses AddressesWithWeight `serix:"0,mapKey=addresses"`
Threshold uint16 `serix:"1,mapKey=threshold"`
}

func (addr *MultiAddress) Clone() Address {
cpy := &MultiAddress{
Addresses: make(AddressesWithWeight, 0, len(addr.Addresses)),
Threshold: addr.Threshold,
AllowedCapabilities: addr.AllowedCapabilities.Clone(),
Addresses: make(AddressesWithWeight, 0, len(addr.Addresses)),
Threshold: addr.Threshold,
}

for i, address := range addr.Addresses {
Expand Down Expand Up @@ -98,7 +95,7 @@ func (addr *MultiAddress) Equal(other Address) bool {
}
}

return bytes.Equal(addr.AllowedCapabilities, otherAddr.AllowedCapabilities)
return true
}

func (addr *MultiAddress) Type() AddressType {
Expand All @@ -113,42 +110,6 @@ func (addr *MultiAddress) String() string {
return hexutil.EncodeHex(addr.ID())
}

func (addr *MultiAddress) CannotReceiveNativeTokens() bool {
return addr.AllowedCapabilities.CannotReceiveNativeTokens()
}

func (addr *MultiAddress) CannotReceiveMana() bool {
return addr.AllowedCapabilities.CannotReceiveMana()
}

func (addr *MultiAddress) CannotReceiveOutputsWithTimelockUnlockCondition() bool {
return addr.AllowedCapabilities.CannotReceiveOutputsWithTimelockUnlockCondition()
}

func (addr *MultiAddress) CannotReceiveOutputsWithExpirationUnlockCondition() bool {
return addr.AllowedCapabilities.CannotReceiveOutputsWithExpirationUnlockCondition()
}

func (addr *MultiAddress) CannotReceiveOutputsWithStorageDepositReturnUnlockCondition() bool {
return addr.AllowedCapabilities.CannotReceiveOutputsWithStorageDepositReturnUnlockCondition()
}

func (addr *MultiAddress) CannotReceiveAccountOutputs() bool {
return addr.AllowedCapabilities.CannotReceiveAccountOutputs()
}

func (addr *MultiAddress) CannotReceiveNFTOutputs() bool {
return addr.AllowedCapabilities.CannotReceiveNFTOutputs()
}

func (addr *MultiAddress) CannotReceiveDelegationOutputs() bool {
return addr.AllowedCapabilities.CannotReceiveDelegationOutputs()
}

func (addr *MultiAddress) AllowedCapabilitiesBitMask() AddressCapabilitiesBitMask {
return addr.AllowedCapabilities
}

func (addr *MultiAddress) Size() int {
// Address Type + Addresses Length + Threshold
sum := serializer.SmallTypeDenotationByteSize + serializer.SmallTypeDenotationByteSize + serializer.UInt16ByteSize
Expand All @@ -157,9 +118,6 @@ func (addr *MultiAddress) Size() int {
sum += address.Size()
}

// AllowedCapabilities
sum += addr.AllowedCapabilities.Size()

return sum
}

Expand All @@ -169,28 +127,3 @@ func NewMultiAddress(addresses AddressesWithWeight, threshold uint16) *MultiAddr
Threshold: threshold,
}
}

// NewMultiAddressWithCapabilities returns the MultiAddress with the given capabilities.
func NewMultiAddressWithCapabilities(addresses AddressesWithWeight, threshold uint16,
canReceiveNativeTokens bool,
canReceiveMana bool,
canReceiveOutputsWithTimelockUnlockCondition bool,
canReceiveOutputsWithExpirationUnlockCondition bool,
canReceiveOutputsWithStorageDepositReturnUnlockCondition bool,
canReceiveAccountOutputs bool,
canReceiveNFTOutputs bool,
canReceiveDelegationOutputs bool) *MultiAddress {
addr := NewMultiAddress(addresses, threshold)
addr.AllowedCapabilities = AddressCapabilitiesBitMaskWithCapabilities(
canReceiveNativeTokens,
canReceiveMana,
canReceiveOutputsWithTimelockUnlockCondition,
canReceiveOutputsWithExpirationUnlockCondition,
canReceiveOutputsWithStorageDepositReturnUnlockCondition,
canReceiveAccountOutputs,
canReceiveNFTOutputs,
canReceiveDelegationOutputs,
)

return addr
}
Loading

0 comments on commit d327065

Please sign in to comment.