Skip to content

Commit

Permalink
Merge pull request #8 from blockcypher/Uint64
Browse files Browse the repository at this point in the history
Allow uint64 or string in JSON file for uint64
  • Loading branch information
quentinlesceller authored Jul 10, 2019
2 parents 6cc7c51 + f9ff0f9 commit 8e696da
Show file tree
Hide file tree
Showing 6 changed files with 81 additions and 55 deletions.
38 changes: 36 additions & 2 deletions core/transaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,42 @@ package core
import (
"bytes"
"encoding/json"
"errors"
"strconv"
)

// Uint64 is an uint64 that can be unmarshal from a string or uint64 is
// marshal to a string
type Uint64 uint64

// MarshalJSON marshals the Uint64 as a quoted uint64 string
func (u Uint64) MarshalJSON() ([]byte, error) {
str := strconv.FormatUint(uint64(u), 10)
bytes, err := json.Marshal(str)
if err != nil {
return nil, err
}
return bytes, nil
}

// UnmarshalJSON unmarshals a quoted an uint64 or a string to an uint64 value
func (u *Uint64) UnmarshalJSON(bs []byte) error {
var i uint64
if err := json.Unmarshal(bs, &i); err == nil {
*u = Uint64(i)
return nil
}
var s string
if err := json.Unmarshal(bs, &s); err != nil {
return errors.New("expected a string or an integer")
}
if err := json.Unmarshal([]byte(s), &i); err != nil {
return err
}
*u = Uint64(i)
return nil
}

// KernelFeatures is an enum of various supported kernels "features".
type KernelFeatures int

Expand Down Expand Up @@ -76,10 +110,10 @@ type TxKernel struct {
// Options for a kernel's structure or use
Features KernelFeatures `json:"features"`
// Fee originally included in the transaction this proof is for.
Fee uint64 `json:"fee,string"`
Fee Uint64 `json:"fee"`
// This kernel is not valid earlier than lock_height blocks
// The max lock_height of all *inputs* to this transaction
LockHeight uint64 `json:"lock_height,string"`
LockHeight Uint64 `json:"lock_height"`
// Remainder of the sum of all transaction commitments. If the transaction
// is well formed, amounts components should sum to zero and the excess
// is hence a valid public key.
Expand Down
12 changes: 6 additions & 6 deletions libwallet/api_impl_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@ type InitTxArgs struct {
// The human readable account name from which to draw outputs
// for the transaction, overriding whatever the active account is as set via the
// [`set_active_account`](../grin_wallet_api/owner/struct.Owner.html#method.set_active_account) method.
SrcAcctName *string `json:"src_acct_name,string"`
SrcAcctName *string `json:"src_acct_name"`
// The amount to send, in nanogrins. (`1 G = 1_000_000_000nG`)
Amount uint64 `json:"amount,string"`
Amount core.Uint64 `json:"amount"`
// The minimum number of confirmations an output
// should have in order to be included in the transaction.
MinimumConfirmations uint64 `json:"minimum_confirmations"`
Expand Down Expand Up @@ -114,7 +114,7 @@ type IssueInvoiceTxArgs struct {
// [`set_active_account`](../grin_wallet_api/owner/struct.Owner.html#method.set_active_account) method.
DestAcctName *string `json:"dest_acct_name"`
// The invoice amount in nanogrins. (`1 G = 1_000_000_000nG`)
Amount uint64 `json:"amount,string"`
Amount core.Uint64 `json:"amount"`
// Optional message, that will be signed
Message *string `json:"message"`
// Optionally set the output target slate version (acceptable
Expand All @@ -126,9 +126,9 @@ type IssueInvoiceTxArgs struct {
// BlockFees are the fees in block to use for coinbase amount calculation
type BlockFees struct {
// fees
Fees uint64 `json:"fees,string"`
Fees core.Uint64 `json:"fees"`
// height
Height uint64 `json:"height,string"`
Height core.Uint64 `json:"height"`
// key id
KeyID *keychain.Identifier `json:"key_id"`
}
Expand All @@ -154,7 +154,7 @@ type OutputCommitMapping struct {
// NodeHeightResult is the node height result
type NodeHeightResult struct {
// Last known height
Height uint64 `json:"height,string"`
Height core.Uint64 `json:"height"`
// Whether this height was updated from the node
UpdatedFromNode bool `json:"updated_from_node"`
}
Expand Down
12 changes: 6 additions & 6 deletions libwallet/slate.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import (
// ParticipantData is a public data for each participant in the slate
type ParticipantData struct {
// Id of participant in the transaction. (For now, 0=sender, 1=rec)
ID uint64 `json:"id,string"`
ID core.Uint64 `json:"id"`
// Public key corresponding to private blinding factor
PublicBlindExcess string `json:"public_blind_excess"`
// Public key corresponding to private nonce
Expand All @@ -43,7 +43,7 @@ type ParticipantData struct {
// ParticipantMessageData is the public message data (for serializing and storage)
type ParticipantMessageData struct {
// id of the particpant in the tx
ID uint64 `json:"id,string"`
ID core.Uint64 `json:"id"`
// Public key
PublicKey string `json:"public_key"`
// Message,
Expand All @@ -67,13 +67,13 @@ type Slate struct {
// inputs, outputs, kernels, kernel offset
Transaction core.Transaction `json:"tx"`
// base amount (excluding fee)
Amount uint64 `json:"amount,string"`
Amount core.Uint64 `json:"amount"`
// fee amount
Fee uint64 `json:"fee,string"`
Fee core.Uint64 `json:"fee"`
// Block height for the transaction
Height uint64 `json:"height,string"`
Height core.Uint64 `json:"height"`
// Lock height
LockHeight uint64 `json:"lock_height,string"`
LockHeight core.Uint64 `json:"lock_height"`
// Participant data, each participant in the transaction will
// insert their public data here. For now, 0 is sender and 1
// is receiver, though this will change for multi-party
Expand Down
17 changes: 4 additions & 13 deletions libwallet/slate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,28 +24,19 @@ import (
"github.com/stretchr/testify/assert"
)

func TestUnmarshalUpgradeV2(t *testing.T) {
func TestUnmarshalV2(t *testing.T) {
slateV2JSON, _ := ioutil.ReadFile("slateversions/test_data/v2.slate")
var slateV2 libwallet.Slate
err := libwallet.UnmarshalUpgrade(slateV2JSON, &slateV2)
err := json.Unmarshal(slateV2JSON, &slateV2)
assert.Nil(t, err)

// Compare with a direct unmarshal
slateV2JSONReference, _ := ioutil.ReadFile("slateversions/test_data/v2.slate")
var slateV2Reference libwallet.Slate
assert.Nil(t, json.Unmarshal(slateV2JSONReference, &slateV2Reference))
assert.Exactly(t, slateV2Reference, slateV2)

}

func TestMarshal(t *testing.T) {
func TestMarshalV2(t *testing.T) {
slateV2JSON, _ := ioutil.ReadFile("slateversions/test_data/v2_raw.slate")
var slateV2 libwallet.Slate
err := libwallet.UnmarshalUpgrade(slateV2JSON, &slateV2)
err := json.Unmarshal(slateV2JSON, &slateV2)
assert.Nil(t, err)

// First test that if we put nothing it serialize as a Slate V2
serializedSlateV2, err := json.Marshal(slateV2)
assert.Nil(t, err)
assert.Equal(t, slateV2JSON, serializedSlateV2)
}
24 changes: 12 additions & 12 deletions libwallet/slateversions/v2.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,13 @@ type SlateV2 struct {
// inputs, outputs, kernels, kernel offset
Transaction TransactionV2 `json:"tx"`
// base amount (excluding fee)
Amount uint64 `json:"amount,string"`
Amount core.Uint64 `json:"amount"`
// fee amount
Fee uint64 `json:"fee,string"`
Fee core.Uint64 `json:"fee"`
// Block height for the transaction
Height uint64 `json:"height,string"`
Height core.Uint64 `json:"height"`
// Lock height
LockHeight uint64 `json:"lock_height,string"`
LockHeight core.Uint64 `json:"lock_height"`
// Participant data, each participant in the transaction will
// insert their public data here. For now, 0 is sender and 1
// is receiver, though this will change for multi-party
Expand All @@ -80,7 +80,7 @@ type VersionCompatInfoV2 struct {
// ParticipantDataV2 is the participant data slate version 0
type ParticipantDataV2 struct {
// Id of participant in the transaction. (For now, 0=sender, 1=rec)
ID uint64 `json:"id,string"`
ID core.Uint64 `json:"id"`
// Public key corresponding to private blinding factor
PublicBlindExcess string `json:"public_blind_excess"`
// Public key corresponding to private nonce
Expand All @@ -93,7 +93,7 @@ type ParticipantDataV2 struct {
MessageSig *string `json:"message_sig"`
}

// TransactionV2 is a v1 transaction
// TransactionV2 is a v2 transaction
type TransactionV2 struct {
/// The kernel "offset" k2
/// excess is k1G after splitting the key k = k1 + k2
Expand All @@ -102,7 +102,7 @@ type TransactionV2 struct {
Body TransactionBodyV2 `json:"body"`
}

// TransactionBodyV2 represent a v1 transaction body
// TransactionBodyV2 represent a v2 transaction body
type TransactionBodyV2 struct {
// List of inputs spent by the transaction.
Inputs []InputV2 `json:"inputs"`
Expand All @@ -112,7 +112,7 @@ type TransactionBodyV2 struct {
Kernels []TxKernelV2 `json:"kernels"`
}

// InputV2 is a v1 input
// InputV2 is a v2 input
type InputV2 struct {
// The features of the output being spent.
// We will check maturity for coinbase output.
Expand All @@ -121,7 +121,7 @@ type InputV2 struct {
Commit string `json:"commit"`
}

// OutputV2 is a v1 output
// OutputV2 is a v2 output
type OutputV2 struct {
// Options for an output's structure or use
Features core.OutputFeatures `json:"features"`
Expand All @@ -131,15 +131,15 @@ type OutputV2 struct {
Proof string `json:"proof"`
}

// TxKernelV2 is a v1 tx kernel
// TxKernelV2 is a v2 tx kernel
type TxKernelV2 struct {
// Options for a kernel's structure or use
Features core.KernelFeatures `json:"features"`
// Fee originally included in the transaction this proof is for.
Fee uint64 `json:"fee,string"`
Fee core.Uint64 `json:"fee"`
// This kernel is not valid earlier than lock_height blocks
// The max lock_height of all *inputs* to this transaction
LockHeight uint64 `json:"lock_height,string"`
LockHeight core.Uint64 `json:"lock_height"`
// Remainder of the sum of all transaction commitments. If the transaction
// is well formed, amounts components should sum to zero and the excess
// is hence a valid public key.
Expand Down
33 changes: 17 additions & 16 deletions libwallet/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"encoding/json"
"time"

"github.com/blockcypher/libgrin/core"
"github.com/blockcypher/libgrin/keychain"
"github.com/google/uuid"
)
Expand All @@ -37,15 +38,15 @@ type OutputData struct {
Commit *string `json:"commit"`
// PMMR Index, used on restore in case of duplicate wallets using the same
// key_id (2 wallets using same seed, for instance
MMRIndex *uint64 `json:"mmr_index,string"`
MMRIndex *core.Uint64 `json:"mmr_index"`
// Value of the output, necessary to rebuild the commitment
Value uint64 `json:"value,string"`
Value core.Uint64 `json:"value"`
// Current status of the output
Status OutputStatus `json:"status"`
// Height of the output
Height uint64 `json:"height,string"`
Height core.Uint64 `json:"height"`
// Height we are locked until
LockHeight uint64 `json:"lock_height,string"`
LockHeight core.Uint64 `json:"lock_height"`
// Is this a coinbase output? Is it subject to coinbase locktime?
IsCoinbase bool `json:"is_coinbase"`
// Optional corresponding internal entry in tx entry log
Expand Down Expand Up @@ -111,21 +112,21 @@ func (s *OutputStatus) UnmarshalJSON(b []byte) error {
// wallet info can add more fields here over time as needed
type WalletInfo struct {
// height from which info was taken
LastConfirmedHeight uint64 `json:"last_confirmed_height,string"`
LastConfirmedHeight core.Uint64 `json:"last_confirmed_height"`
// Minimum number of confirmations for an output to be treated as "spendable".
MinimumConfirmations uint64 `json:"minimum_confirmations,string"`
MinimumConfirmations core.Uint64 `json:"minimum_confirmations"`
// total amount in the wallet
Total uint64 `json:"total,string"`
Total core.Uint64 `json:"total"`
// amount awaiting finalization
AmountAwaitingFinalization uint64 `json:"amount_awaiting_finalization,string"`
AmountAwaitingFinalization core.Uint64 `json:"amount_awaiting_finalization"`
// amount awaiting confirmation
AmountAwaitingConfirmation uint64 `json:"amount_awaiting_confirmation,string"`
AmountAwaitingConfirmation core.Uint64 `json:"amount_awaiting_confirmation"`
// coinbases waiting for lock height
AmountImmature uint64 `json:"amount_immature,string"`
AmountImmature core.Uint64 `json:"amount_immature"`
// amount currently spendable
AmountCurrentlySpendable uint64 `json:"amount_currently_spendable,string"`
AmountCurrentlySpendable core.Uint64 `json:"amount_currently_spendable"`
// amount locked via previous transactions
AmountLocked uint64 `json:"amount_locked,string"`
AmountLocked core.Uint64 `json:"amount_locked"`
}

// TxLogEntryType represent the type of transactions that can be contained
Expand Down Expand Up @@ -196,7 +197,7 @@ type ParticipantMessages struct {
// to one or many outputs
type TxLogEntry struct {
// BIP32 account path used for creating this tx
ParentKeyID keychain.Identifier `json:"parent_key_id,string"`
ParentKeyID keychain.Identifier `json:"parent_key_id"`
// Local id for this transaction (distinct from a slate transaction id)
ID uint32 `json:"id"`
// Slate transaction this entry is associated with, if any
Expand All @@ -218,11 +219,11 @@ type TxLogEntry struct {
// number of outputs involved in TX
NumOutputs uint `json:"num_outputs"`
// Amount credited via this transaction
AmountCredited uint64 `json:"amount_credited,string"`
AmountCredited core.Uint64 `json:"amount_credited"`
// Amount debited via this transaction
AmountDebited uint64 `json:"amount_debited,string"`
AmountDebited core.Uint64 `json:"amount_debited"`
// Fee
Fee *uint64 `json:"fee,string"`
Fee *core.Uint64 `json:"fee"`
// Message data, stored as json
Messages *ParticipantMessages `json:"messages"`
// Location of the store transaction, (reference or resending)
Expand Down

0 comments on commit 8e696da

Please sign in to comment.