Skip to content

Commit

Permalink
Added quai_getUTXO API
Browse files Browse the repository at this point in the history
  • Loading branch information
jdowning100 committed Oct 25, 2024
1 parent e0216d9 commit 4e300a6
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 4 deletions.
4 changes: 4 additions & 0 deletions common/address.go
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,10 @@ func (a AddressBytes) hex() []byte {
return buf[:]
}

func (a AddressBytes) Bytes() []byte {
return a[:]
}

func (a AddressBytes) Location() *Location {
// Extract nibbles
lowerNib := a[0] & 0x0F // Lower 4 bits
Expand Down
63 changes: 60 additions & 3 deletions core/types/utxo.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ package types

import (
"encoding/binary"
"encoding/json"
"errors"
"math"
"math/big"

"github.com/dominant-strategies/go-quai/common"
"github.com/dominant-strategies/go-quai/common/hexutil"
"github.com/dominant-strategies/go-quai/crypto"
"github.com/dominant-strategies/go-quai/params"
)
Expand Down Expand Up @@ -188,6 +190,36 @@ type OutpointAndDenomination struct {
Lock *big.Int `json:"lock"`
}

func (outpoint *OutpointAndDenomination) UnmarshalJSON(input []byte) error {
var dec struct {
Txhash *common.Hash `json:"txHash"`
Index *hexutil.Uint64 `json:"index"`
Denomination *hexutil.Uint64 `json:"denomination"`
Lock *hexutil.Big `json:"lock"`
}
if err := json.Unmarshal(input, &dec); err != nil {
return err
}
if dec.Txhash == nil {
return errors.New("missing txHash")
}
if dec.Index == nil {
return errors.New("missing index")
}
if dec.Denomination == nil {
return errors.New("missing denomination")
}
outpoint.TxHash = *dec.Txhash
outpoint.Index = uint16(*dec.Index)
outpoint.Denomination = uint8(*dec.Denomination)
if dec.Lock != nil {
outpoint.Lock = dec.Lock.ToInt()
} else {
outpoint.Lock = big.NewInt(0)
}
return nil
}

func (outPoint OutpointAndDenomination) Key() string {
indexBytes := make([]byte, 2)
binary.BigEndian.PutUint16(indexBytes, outPoint.Index)
Expand Down Expand Up @@ -314,9 +346,9 @@ func NewTxOut(denomination uint8, address []byte, lock *big.Int) *TxOut {
// the block that contains the tx, whether or not it is spent, its public key
// script, and how much it pays.
type UtxoEntry struct {
Denomination uint8
Address []byte // The address of the output holder.
Lock *big.Int // Block height the entry unlocks. 0 = unlocked
Denomination uint8 `json:"denomination"`
Address []byte `json:"address"` // The address of the output holder.
Lock *big.Int `json:"lock"` // Block height the entry unlocks. 0 = unlocked
}

// SpentUtxoEntry houses details about a spent UtxoEntry.
Expand Down Expand Up @@ -397,6 +429,31 @@ func (utxo *UtxoEntry) ProtoDecode(protoTxOut *ProtoTxOut) error {
return nil
}

func (utxo *UtxoEntry) UnmarshalJSON(input []byte) error {
var dec struct {
Denomination *hexutil.Uint64 `json:"denomination"`
Address *string `json:"address"`
Lock *hexutil.Big `json:"lock"`
}
if err := json.Unmarshal(input, &dec); err != nil {
return err
}
if dec.Denomination == nil {
return errors.New("missing denomination")
}
if dec.Address == nil {
return errors.New("missing address")
}
utxo.Denomination = uint8(*dec.Denomination)
utxo.Address = common.HexToAddressBytes(*dec.Address).Bytes()
if dec.Lock != nil {
utxo.Lock = dec.Lock.ToInt()
} else {
utxo.Lock = big.NewInt(0)
}
return nil
}

func UTXOHash(txHash common.Hash, index uint16, utxo *UtxoEntry) common.Hash {
indexBytes := make([]byte, 2)
binary.BigEndian.PutUint16(indexBytes, index)
Expand Down
19 changes: 18 additions & 1 deletion internal/quaiapi/quai_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ func (s *PublicBlockChainQuaiAPI) GetOutpointsByAddress(ctx context.Context, add
return jsonOutpoints, nil
}

func (s *PublicBlockChainAPI) GetOutPointsByAddressAndRange(ctx context.Context, address common.Address, start, end hexutil.Uint64) (map[string][]interface{}, error) {
func (s *PublicBlockChainQuaiAPI) GetOutPointsByAddressAndRange(ctx context.Context, address common.Address, start, end hexutil.Uint64) (map[string][]interface{}, error) {
if start > end {
return nil, fmt.Errorf("start is greater than end")
}
Expand Down Expand Up @@ -212,6 +212,23 @@ func (s *PublicBlockChainAPI) GetOutPointsByAddressAndRange(ctx context.Context,
return txHashToOutpointsJson, nil
}

func (s *PublicBlockChainQuaiAPI) GetUTXO(ctx context.Context, txHash common.Hash, index hexutil.Uint64) (map[string]interface{}, error) {
utxo := rawdb.GetUTXO(s.b.Database(), txHash, uint16(index))
if utxo == nil {
return nil, nil
}
lock := big.NewInt(0)
if utxo.Lock != nil {
lock = utxo.Lock
}
jsonOutpoint := map[string]interface{}{
"address": common.BytesToAddress(utxo.Address, s.b.NodeLocation()).Hex(),
"denomination": hexutil.Uint64(utxo.Denomination),
"lock": hexutil.Big(*lock),
}
return jsonOutpoint, nil
}

// GetProof returns the Merkle-proof for a given account and optionally some storage keys.
func (s *PublicBlockChainQuaiAPI) GetProof(ctx context.Context, address common.Address, storageKeys []string, blockNrOrHash rpc.BlockNumberOrHash) (*AccountResult, error) {
nodeCtx := s.b.NodeCtx()
Expand Down
6 changes: 6 additions & 0 deletions quaiclient/ethclient/ethclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,12 @@ func (ec *Client) GetOutpointsByAddress(ctx context.Context, address common.Mixe
return outpoints, err
}

func (ec *Client) GetUTXO(ctx context.Context, txHash common.Hash, index uint16) (*types.UtxoEntry, error) {
var utxo *types.UtxoEntry
err := ec.c.CallContext(ctx, &utxo, "quai_getUTXO", txHash, hexutil.Uint64(index))
return utxo, err
}

// StorageAt returns the value of key in the contract storage of the given account.
// The block number can be nil, in which case the value is taken from the latest known block.
func (ec *Client) StorageAt(ctx context.Context, account common.MixedcaseAddress, key common.Hash, blockNumber *big.Int) ([]byte, error) {
Expand Down

0 comments on commit 4e300a6

Please sign in to comment.