Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve delegation tx management #39

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 43 additions & 6 deletions address.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const (
Base AddressType = 0x00
Ptr AddressType = 0x04
Enterprise AddressType = 0x06
Stake AddressType = 0x0e
)

// Address represents a Cardano address.
Expand Down Expand Up @@ -94,7 +95,7 @@ func NewAddressFromBytes(bytes []byte) (Address, error) {
}
case Ptr:
if len(bytes) <= 29 {
return addr, errors.New("enterprise address length should be greater than 29")
return addr, errors.New("pointer address length should be greater than 29")
}

index := uint(29)
Expand All @@ -120,7 +121,7 @@ func NewAddressFromBytes(bytes []byte) (Address, error) {
addr.Pointer = Pointer{Slot: slot, TxIndex: txIndex, CertIndex: certIndex}
case Ptr + 1:
if len(bytes) <= 29 {
return addr, errors.New("enterprise address length should be greater than 29")
return addr, errors.New("pointer address length should be greater than 29")
}

index := uint(29)
Expand Down Expand Up @@ -160,6 +161,22 @@ func NewAddressFromBytes(bytes []byte) (Address, error) {
Type: ScriptCredential,
ScriptHash: bytes[1:29],
}
case Stake:
if len(bytes) != 29 {
return addr, errors.New("stake address length should be 29")
}
addr.Stake = StakeCredential{
Type: KeyCredential,
KeyHash: bytes[1:29],
}
case Stake + 1:
if len(bytes) != 29 {
return addr, errors.New("stake address length should be 29")
}
addr.Stake = StakeCredential{
Type: ScriptCredential,
ScriptHash: bytes[1:29],
}
}

return addr, nil
Expand Down Expand Up @@ -208,6 +225,8 @@ func (addr *Address) Bytes() []byte {
addrBytes = append(addrBytes, addr.Stake.Hash()...)
case Enterprise, Enterprise + 1:
addrBytes = append(addrBytes, addr.Payment.Hash()...)
case Stake, Stake + 1:
addrBytes = append(addrBytes, addr.Stake.Hash()...)
case Ptr, Ptr + 1:
addrBytes = append(addrBytes, addr.Payment.Hash()...)
addrBytes = append(addrBytes, encodeToNat(addr.Pointer.Slot)...)
Expand All @@ -220,7 +239,7 @@ func (addr *Address) Bytes() []byte {

// Bech32 returns the Address encoded as bech32.
func (addr *Address) Bech32() string {
addrStr, err := bech32.EncodeFromBase256(getHrp(addr.Network), addr.Bytes())
addrStr, err := bech32.EncodeFromBase256(getHrp(addr.Network, addr.Type), addr.Bytes())
if err != nil {
panic(err)
}
Expand Down Expand Up @@ -254,6 +273,15 @@ func NewEnterpriseAddress(network Network, payment StakeCredential) (Address, er
return Address{Type: addrType, Network: network, Payment: payment}, nil
}

// NewStakeAddress returns a new Staake Address.
func NewStakeAddress(network Network, stake StakeCredential) (Address, error) {
addrType := Stake
if stake.Type == ScriptCredential {
addrType = Stake + 1
}
return Address{Type: addrType, Network: network, Stake: stake}, nil
}

// Pointer is the location of the Stake Registration Certificate in the blockchain.
type Pointer struct {
Slot uint64
Expand Down Expand Up @@ -316,11 +344,20 @@ func Blake224Hash(b []byte) ([]byte, error) {
return hash.Sum(nil), err
}

func getHrp(network Network) string {
func getHrp(network Network, atyp ...AddressType) string {
prefix := "addr"
suffix := ""
switch network {
case Testnet, Preprod:
return "addr_test"
suffix = "_test"
default:
return "addr"
}
if len(atyp) == 1 {
switch atyp[0] {
case Stake:
prefix = "stake"
default:
}
}
return prefix + suffix
}
122 changes: 122 additions & 0 deletions bech32/bech32.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
package bech32

import (
"fmt"

"github.com/echovl/cardano-go/bech32/prefixes"
"github.com/echovl/cardano-go/internal/bech32"
)

type Bech32Prefix = prefixes.Bech32Prefix

var (
EncodeWithPrefix = bech32.Encode
Decode = bech32.Decode
DecodeNoLimit = bech32.DecodeNoLimit

EncodeFromBase256WithPrefix = bech32.EncodeFromBase256
DecodeToBase256 = bech32.DecodeToBase256
)

type (
Bech32Codec interface {
Prefix() string
Bytes() []byte
SetBytes([]byte)
Len() int
}
Bech32Encoder interface {
Prefix() string
Bytes() []byte
}
)

func Encode(args ...any) (string, error) {
var hrp string
var data []byte
switch len(args) {
case 1:
// the argument have to be a Bech32Codec
if c, ok := args[0].(Bech32Encoder); !ok {
return "", fmt.Errorf("Wrong parameter: %T is not a Bech32Encoder", c)
}
hrp = args[0].(Bech32Encoder).Prefix()
data = args[0].(Bech32Encoder).Bytes()
case 2:
// the argument haave to be a Bech32Codec or a string, and the second have to be a []byte
a1 := args[0]
a2 := args[1]

switch a1.(type) {
case Bech32Encoder:
hrp = a1.(Bech32Codec).Prefix()
case string:
hrp = a1.(string)
default:
return "", fmt.Errorf("Wrong 1st parameter: %T is not a string or Bech32Codec", a1)
}

if _, ok := a2.([]byte); !ok {
return "", fmt.Errorf("Wrong 2nd parameter: %T is not a []byte", a2)
}
data = a2.([]byte)
}
return bech32.Encode(hrp, data)
}

func EncodeFromBase256(args ...any) (string, error) {
var hrp string
var data []byte
switch len(args) {
case 1:
// the argument have to be a Bech32Codec
if c, ok := args[0].(Bech32Encoder); !ok {
return "", fmt.Errorf("Wrong parameter: %T is not a Bech32Encoder", c)
}
hrp = args[0].(Bech32Encoder).Prefix()
if converted, err := bech32.ConvertBits(args[0].(Bech32Encoder).Bytes(), 8, 5, true); err != nil {
return "", err
} else {
data = converted
}
case 2:
// the argument haave to be a Bech32Codec or a string, and the second have to be a []byte
a1 := args[0]
a2 := args[1]

switch a1.(type) {
case Bech32Encoder:
hrp = a1.(Bech32Encoder).Prefix()
case string:
hrp = a1.(string)
default:
return "", fmt.Errorf("Wrong 1st parameter: %T is not a string or Bech32Codec", a1)
}

if _, ok := a2.([]byte); !ok {
return "", fmt.Errorf("Wrong 2nd parameter: %T is not a []byte", a2)
}
if converted, err := bech32.ConvertBits(a2.([]byte), 8, 5, true); err != nil {
} else {
data = converted
}
}
return bech32.Encode(hrp, data)
}

func DecodeInto(be32 string, codec Bech32Codec) error {
expectedLen := codec.Len()
expectedPrefix := codec.Prefix()
hrp, data, err := bech32.DecodeToBase256(be32)
if err != nil {
return err
}
if hrp != expectedPrefix {
return fmt.Errorf("Wrong prefix: want %s got %s", expectedPrefix, hrp)
}
codec.SetBytes(data)
if len(codec.Bytes()) != expectedLen || string(codec.Bytes()) != string(data) {
return fmt.Errorf("Set bytes failed")
}
return nil
}
91 changes: 91 additions & 0 deletions bech32/prefixes/cip5.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package prefixes

// As specified in [CIP-5](https://github.com/cardano-foundation/CIPs/tree/master/CIP5)
//
// copied from cardano-addresses core/lib/Cardano/Codec/Bech32/Prefixes.hs

type Bech32Prefix = string

const (
// -- * Addresses

Addr Bech32Prefix = "addr"
AddrTest Bech32Prefix = "addr_test"
Script Bech32Prefix = "script"
Stake Bech32Prefix = "stake"
StakeTest Bech32Prefix = "stake_test"

// -- * Hashes

AddrPublicKeyHash Bech32Prefix = "addr_vkh"
StakePublicKeyHash Bech32Prefix = "stake_vkh"
AddrSharedPublicKeyHash Bech32Prefix = "addr_shared_vkh"
StakeSharedPublicKeyHash Bech32Prefix = "stake_shared_vkh"

// -- * Keys for 1852H
AddrPublicKey Bech32Prefix = "addr_vk"
AddrPrivateKey Bech32Prefix = "addr_sk"
AddrXPub Bech32Prefix = "addr_xvk"
AddrXPrv Bech32Prefix = "addr_xsk"
AddrExtendedPublicKey = AddrXPub
AddrExtendedPrivateKey = AddrXPrv

AcctPublicKey Bech32Prefix = "acct_vk"
AcctPrivateKey Bech32Prefix = "acct_sk"
AcctXPub Bech32Prefix = "acct_xvk"
AcctXPrv Bech32Prefix = "acct_xsk"
AcctExtendedPublicKey = AcctXPub
AcctExtendedPrivateKey = AcctXPrv

RootPublicKey Bech32Prefix = "root_vk"
RootPrivateKey Bech32Prefix = "root_sk"
RootXPub Bech32Prefix = "root_xvk"
RootXPrv Bech32Prefix = "root_xsk"
RootExtendedPublicKey = RootXPub
RootExtendedPrivateKey = RootXPrv

StakePublicKey Bech32Prefix = "stake_vk"
StakePrivateKey Bech32Prefix = "stake_sk"
StakeXPub Bech32Prefix = "stake_xvk"
StakeXPrv Bech32Prefix = "stake_xsk"
StakeExtendedPublicKey = StakeXPub
StakeExtendedPrivateKey = StakeXPrv

// -- * Keys for 1854H

AddrSharedPublicKey Bech32Prefix = "addr_shared_vk"
AddrSharedPrivateKey Bech32Prefix = "addr_shared_sk"
AddrSharedXPub Bech32Prefix = "addr_shared_xvk"
AddrSharedXPrv Bech32Prefix = "addr_shared_xsk"
AddrSharedExtendedPublicKey = AddrSharedXPub
AddrSharedExtendedPrivateKey = AddrSharedXPrv

AcctSharedPublicKey Bech32Prefix = "acct_shared_vk"
AcctSharedPrivateKey Bech32Prefix = "acct_shared_sk"
AcctSharedXPub Bech32Prefix = "acct_shared_xvk"
AcctSharedXPrv Bech32Prefix = "acct_shared_xsk"
AcctSharedExtendedPublicKey = AcctSharedXPub
AcctSharedExtendedPrivateKey = AcctSharedXPrv

RootSharedPublicKey Bech32Prefix = "root_shared_vk"
RootSharedPrivateKey Bech32Prefix = "root_shared_sk"
RootSharedXPub Bech32Prefix = "root_shared_xvk"
RootSharedXPrv Bech32Prefix = "root_shared_xsk"
RootSharedExtendedPublicKey = RootSharedXPub
RootSharedExtendedPrivateKey = RootSharedXPrv

StakeSharedPublicKey Bech32Prefix = "stake_shared_vk"
StakeSharedPrivateKey Bech32Prefix = "stake_shared_sk"
StakeSharedXPub Bech32Prefix = "stake_shared_xvk"
StakeSharedXPrv Bech32Prefix = "stake_shared_xsk"
StakeSharedExtendedPublicKey = StakeSharedXPub
StakeSharedExtendedPrivateKey = StakeSharedXPrv

// -- * Keys for 1855H
PolicyPublicKey Bech32Prefix = "policy_vk"
PolicyPrivateKey Bech32Prefix = "policy_sk"
PolicyXPub Bech32Prefix = "policy_xvk"
PolicyXPrv Bech32Prefix = "policy_xsk"
PolicyExtendedPublicKey = PolicyXPub
PolicyExtendedPrivateKey = PolicyXPrv
)
Loading