diff --git a/.github/workflows/full_test.yml b/.github/workflows/full_test.yml
index fbe6132c3..3fb01f4e2 100644
--- a/.github/workflows/full_test.yml
+++ b/.github/workflows/full_test.yml
@@ -29,7 +29,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v3
with:
- go-version: 1.19
+ go-version: '1.19'
- name: Install dependencies
run: |
diff --git a/.github/workflows/manual_test.yml b/.github/workflows/manual_test.yml
index 38d09e716..74192e24d 100644
--- a/.github/workflows/manual_test.yml
+++ b/.github/workflows/manual_test.yml
@@ -20,7 +20,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v3
with:
- go-version: 1.19
+ go-version: '1.19'
- name: Install dependencies
run: |
diff --git a/.github/workflows/short_test.yml b/.github/workflows/short_test.yml
index b957fef90..6ed2b6a02 100644
--- a/.github/workflows/short_test.yml
+++ b/.github/workflows/short_test.yml
@@ -35,7 +35,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v3
with:
- go-version: 1.19
+ go-version: '1.19'
- name: Install dependencies
run: |
diff --git a/account/accountservice.go b/account/accountservice.go
index 030179c5c..dc5152a98 100644
--- a/account/accountservice.go
+++ b/account/accountservice.go
@@ -10,6 +10,7 @@ import (
"github.com/aergoio/aergo/v2/contract/name"
"github.com/aergoio/aergo/v2/pkg/component"
"github.com/aergoio/aergo/v2/state"
+ "github.com/aergoio/aergo/v2/state/statedb"
"github.com/aergoio/aergo/v2/types"
"github.com/aergoio/aergo/v2/types/message"
)
@@ -63,7 +64,7 @@ func (as *AccountService) Statistics() *map[string]interface{} {
}
}
func (as *AccountService) resolveName(namedAddress []byte) ([]byte, error) {
- scs, err := as.sdb.GetStateDB().GetNameAccountState()
+ scs, err := statedb.GetNameAccountState(as.sdb.GetStateDB())
if err != nil {
return nil, err
}
diff --git a/chain/chaindb.go b/chain/chaindb.go
index 52b50495c..b48c11bb1 100644
--- a/chain/chaindb.go
+++ b/chain/chaindb.go
@@ -647,7 +647,7 @@ func (cdb *ChainDB) getReceipts(blockHash []byte, blockNo types.BlockNo,
hardForkConfig *config.HardforkConfig) (*types.Receipts, error) {
data := cdb.store.Get(dbkey.Receipts(blockHash, blockNo))
if len(data) == 0 {
- return nil, errors.New("cannot find a receipt")
+ return nil, fmt.Errorf("empty : blockNo=%d", blockNo)
}
var receipts types.Receipts
diff --git a/chain/chainhandle.go b/chain/chainhandle.go
index df526505f..0a35e7082 100644
--- a/chain/chainhandle.go
+++ b/chain/chainhandle.go
@@ -22,6 +22,7 @@ import (
"github.com/aergoio/aergo/v2/internal/enc/base58"
"github.com/aergoio/aergo/v2/internal/enc/proto"
"github.com/aergoio/aergo/v2/state"
+ "github.com/aergoio/aergo/v2/state/statedb"
"github.com/aergoio/aergo/v2/types"
"github.com/aergoio/aergo/v2/types/message"
)
@@ -136,6 +137,72 @@ func (cs *ChainService) getReceipt(txHash []byte) (*types.Receipt, error) {
return r, nil
}
+func (cs *ChainService) getReceipts(blockHash []byte) (*types.Receipts, error) {
+ block, err := cs.cdb.getBlock(blockHash)
+ if err != nil {
+ return nil, &ErrNoBlock{blockHash}
+ }
+
+ blockInMainChain, err := cs.cdb.GetBlockByNo(block.Header.BlockNo)
+ if !bytes.Equal(block.BlockHash(), blockInMainChain.BlockHash()) {
+ return nil, errors.New("cannot find a receipt")
+ }
+
+ receipts, err := cs.cdb.getReceipts(block.BlockHash(), block.GetHeader().BlockNo, cs.cfg.Hardfork)
+ if err != nil {
+ return nil, err
+ }
+
+ for idx, r := range receipts.Get() {
+ r.SetMemoryInfo(blockHash, block.Header.BlockNo, int32(idx))
+
+ r.ContractAddress = types.AddressOrigin(r.ContractAddress)
+
+ for _, tx := range block.GetBody().GetTxs() {
+ if bytes.Equal(r.GetTxHash(), tx.GetHash()) {
+ r.From = tx.GetBody().GetAccount()
+ r.To = tx.GetBody().GetRecipient()
+ break
+ }
+ }
+ }
+
+ return receipts, nil
+}
+
+func (cs *ChainService) getReceiptsByNo(blockNo types.BlockNo) (*types.Receipts, error) {
+ blockInMainChain, err := cs.cdb.GetBlockByNo(blockNo)
+ if err != nil {
+ return nil, &ErrNoBlock{blockNo}
+ }
+
+ block, err := cs.cdb.getBlock(blockInMainChain.BlockHash())
+ if !bytes.Equal(block.BlockHash(), blockInMainChain.BlockHash()) {
+ return nil, errors.New("cannot find a receipt")
+ }
+
+ receipts, err := cs.cdb.getReceipts(block.BlockHash(), block.GetHeader().BlockNo, cs.cfg.Hardfork)
+ if err != nil {
+ return nil, err
+ }
+
+ for idx, r := range receipts.Get() {
+ r.SetMemoryInfo(blockInMainChain.BlockHash(), blockNo, int32(idx))
+
+ r.ContractAddress = types.AddressOrigin(r.ContractAddress)
+
+ for _, tx := range block.GetBody().GetTxs() {
+ if bytes.Equal(r.GetTxHash(), tx.GetHash()) {
+ r.From = tx.GetBody().GetAccount()
+ r.To = tx.GetBody().GetRecipient()
+ break
+ }
+ }
+ }
+
+ return receipts, nil
+}
+
func (cs *ChainService) getEvents(events *[]*types.Event, blkNo types.BlockNo, filter *types.FilterInfo,
argFilter []types.ArgFilter) uint64 {
blkHash, err := cs.cdb.getHashByNo(blkNo)
@@ -624,7 +691,7 @@ func newBlockExecutor(cs *ChainService, bState *state.BlockState, block *types.B
}
// NewTxExecutor returns a new TxExecFn.
-func NewTxExecutor(execCtx context.Context, ccc consensus.ChainConsensusCluster, cdb contract.ChainAccessor, bi *types.BlockHeaderInfo, preloadService int) TxExecFn {
+func NewTxExecutor(execCtx context.Context, ccc consensus.ChainConsensusCluster, cdb contract.ChainAccessor, bi *types.BlockHeaderInfo, executionMode int) TxExecFn {
return func(bState *state.BlockState, tx types.Transaction) error {
if bState == nil {
logger.Error().Msg("bstate is nil in txExec")
@@ -636,7 +703,7 @@ func NewTxExecutor(execCtx context.Context, ccc consensus.ChainConsensusCluster,
}
blockSnap := bState.Snapshot()
- err := executeTx(execCtx, ccc, cdb, bState, tx, bi, preloadService)
+ err := executeTx(execCtx, ccc, cdb, bState, tx, bi, executionMode)
if err != nil {
logger.Error().Err(err).Str("hash", base58.Encode(tx.GetHash())).Msg("tx failed")
if err2 := bState.Rollback(blockSnap); err2 != nil {
@@ -653,22 +720,14 @@ func (e *blockExecutor) execute() error {
// Receipt must be committed unconditionally.
if !e.commitOnly {
defer contract.CloseDatabase()
- var preloadTx *types.Tx
- numTxs := len(e.txs)
- for i, tx := range e.txs {
- // if tx is not the last one, preload the next tx
- if i != numTxs-1 {
- preloadTx = e.txs[i+1]
- contract.RequestPreload(e.BlockState, e.bi, preloadTx, tx, contract.ChainService)
- }
+ logger.Trace().Int("txCount", len(e.txs)).Msg("executing txs")
+ for _, tx := range e.txs {
// execute the transaction
if err := e.execTx(e.BlockState, types.NewTransaction(tx)); err != nil {
//FIXME maybe system error. restart or panic
// all txs have executed successfully in BP node
return err
}
- // mark the next preload tx to be executed
- contract.SetPreloadTx(preloadTx, contract.ChainService)
}
if e.validateSignWait != nil {
@@ -870,7 +929,7 @@ func adjustRv(ret string) string {
return ret
}
-func resetAccount(account *state.V, fee *big.Int, nonce *uint64) error {
+func resetAccount(account *state.AccountState, fee *big.Int, nonce *uint64) error {
account.Reset()
if fee != nil {
if account.Balance().Cmp(fee) < 0 {
@@ -884,7 +943,7 @@ func resetAccount(account *state.V, fee *big.Int, nonce *uint64) error {
return account.PutState()
}
-func executeTx(execCtx context.Context, ccc consensus.ChainConsensusCluster, cdb contract.ChainAccessor, bs *state.BlockState, tx types.Transaction, bi *types.BlockHeaderInfo, preloadService int) error {
+func executeTx(execCtx context.Context, ccc consensus.ChainConsensusCluster, cdb contract.ChainAccessor, bs *state.BlockState, tx types.Transaction, bi *types.BlockHeaderInfo, executionMode int) error {
var (
txBody = tx.GetBody()
isQuirkTx = types.IsQuirkTx(tx.GetHash())
@@ -910,7 +969,7 @@ func executeTx(execCtx context.Context, ccc consensus.ChainConsensusCluster, cdb
return err
}
- sender, err := bs.GetAccountStateV(account)
+ sender, err := state.GetAccountState(account, bs.StateDB)
if err != nil {
return err
}
@@ -923,16 +982,16 @@ func executeTx(execCtx context.Context, ccc consensus.ChainConsensusCluster, cdb
if recipient, err = name.Resolve(bs, txBody.Recipient, isQuirkTx); err != nil {
return err
}
- var receiver *state.V
+ var receiver *state.AccountState
status := "SUCCESS"
if len(recipient) > 0 {
- receiver, err = bs.GetAccountStateV(recipient)
+ receiver, err = state.GetAccountState(recipient, bs.StateDB)
if receiver != nil && txBody.Type == types.TxType_REDEPLOY {
status = "RECREATED"
receiver.SetRedeploy()
}
} else {
- receiver, err = bs.CreateAccountStateV(contract.CreateContractID(txBody.Account, txBody.Nonce))
+ receiver, err = state.CreateAccountState(contract.CreateContractID(txBody.Account, txBody.Nonce), bs.StateDB)
status = "CREATED"
}
if err != nil {
@@ -944,7 +1003,7 @@ func executeTx(execCtx context.Context, ccc consensus.ChainConsensusCluster, cdb
var events []*types.Event
switch txBody.Type {
case types.TxType_NORMAL, types.TxType_REDEPLOY, types.TxType_TRANSFER, types.TxType_CALL, types.TxType_DEPLOY:
- rv, events, txFee, err = contract.Execute(execCtx, bs, cdb, tx.GetTx(), sender, receiver, bi, preloadService, false)
+ rv, events, txFee, err = contract.Execute(execCtx, bs, cdb, tx.GetTx(), sender, receiver, bi, executionMode, false)
sender.SubBalance(txFee)
case types.TxType_GOVERNANCE:
txFee = new(big.Int).SetUint64(0)
@@ -958,8 +1017,8 @@ func executeTx(execCtx context.Context, ccc consensus.ChainConsensusCluster, cdb
return err
}
- var contractState *state.ContractState
- contractState, err = bs.OpenContractState(receiver.AccountID(), receiver.State())
+ var contractState *statedb.ContractState
+ contractState, err = statedb.OpenContractState(receiver.ID(), receiver.State(), bs.StateDB)
if err != nil {
return err
}
@@ -972,7 +1031,7 @@ func executeTx(execCtx context.Context, ccc consensus.ChainConsensusCluster, cdb
}
return types.ErrNotAllowedFeeDelegation
}
- rv, events, txFee, err = contract.Execute(execCtx, bs, cdb, tx.GetTx(), sender, receiver, bi, preloadService, true)
+ rv, events, txFee, err = contract.Execute(execCtx, bs, cdb, tx.GetTx(), sender, receiver, bi, executionMode, true)
receiver.SubBalance(txFee)
}
@@ -1055,22 +1114,19 @@ func sendRewardCoinbase(bState *state.BlockState, coinbaseAccount []byte) error
return nil
}
- receiverID := types.ToAccountID(coinbaseAccount)
- receiverState, err := bState.GetAccountState(receiverID)
+ // add bp reward to coinbase account
+ coinbaseAccountState, err := state.GetAccountState(coinbaseAccount, bState.StateDB)
if err != nil {
return err
}
-
- receiverChange := types.State(*receiverState)
- receiverChange.Balance = new(big.Int).Add(receiverChange.GetBalanceBigInt(), bpReward).Bytes()
-
- err = bState.PutState(receiverID, &receiverChange)
+ coinbaseAccountState.AddBalance(bpReward)
+ err = coinbaseAccountState.PutState()
if err != nil {
return err
}
logger.Debug().Str("reward", bpReward.String()).
- Str("newbalance", receiverChange.GetBalanceBigInt().String()).Msg("send reward to coinbase account")
+ Str("newbalance", coinbaseAccountState.Balance().String()).Msg("send reward to coinbase account")
return nil
}
diff --git a/chain/chainservice.go b/chain/chainservice.go
index a9631001b..d69fd8af7 100644
--- a/chain/chainservice.go
+++ b/chain/chainservice.go
@@ -27,6 +27,7 @@ import (
"github.com/aergoio/aergo/v2/internal/enc/base58"
"github.com/aergoio/aergo/v2/pkg/component"
"github.com/aergoio/aergo/v2/state"
+ "github.com/aergoio/aergo/v2/state/statedb"
"github.com/aergoio/aergo/v2/types"
"github.com/aergoio/aergo/v2/types/dbkey"
"github.com/aergoio/aergo/v2/types/message"
@@ -179,6 +180,8 @@ type IChainHandler interface {
getBlockByNo(blockNo types.BlockNo) (*types.Block, error)
getTx(txHash []byte) (*types.Tx, *types.TxIdx, error)
getReceipt(txHash []byte) (*types.Receipt, error)
+ getReceipts(blockHash []byte) (*types.Receipts, error)
+ getReceiptsByNo(blockNo types.BlockNo) (*types.Receipts, error)
getAccountVote(addr []byte) (*types.AccountVoteInfo, error)
getVotes(id string, n uint32) (*types.VoteList, error)
getStaking(addr []byte) (*types.Staking, error)
@@ -231,6 +234,11 @@ func NewChainService(cfg *cfg.Config) *ChainService {
logger.Panic().Err(err).Msg("failed to initialize DB")
}
+ // check legacy format about trie key
+ if legacy := cs.SDB().GetStateDB().IsLegacyTrieKey(); legacy {
+ logger.Panic().Msg("Legacy key format detected. Clear existing data and restart.")
+ }
+
if err = Init(cfg.Blockchain.MaxBlockSize,
cfg.Blockchain.CoinbaseAccount,
cfg.Consensus.EnableBp,
@@ -294,7 +302,8 @@ func NewChainService(cfg *cfg.Config) *ChainService {
types.InitGovernance(cs.ConsensusType(), cs.IsPublic())
//reset parameter of aergo.system
- systemState, err := cs.SDB().GetSystemAccountState()
+
+ systemState, err := statedb.GetSystemAccountState(cs.SDB().GetStateDB())
if err != nil {
logger.Panic().Err(err).Msg("failed to read aergo.system state")
}
@@ -433,6 +442,8 @@ func (cs *ChainService) Receive(context actor.Context) {
*message.GetStateAndProof,
*message.GetTx,
*message.GetReceipt,
+ *message.GetReceipts,
+ *message.GetReceiptsByNo,
*message.GetABI,
*message.GetQuery,
*message.GetStateQuery,
@@ -495,10 +506,14 @@ func (cs *ChainService) getVotes(id string, n uint32) (*types.VoteList, error) {
switch ConsensusName() {
case consensus.ConsensusName[consensus.ConsensusDPOS]:
sdb := cs.sdb.OpenNewStateDB(cs.sdb.GetRoot())
+ scs, err := statedb.GetSystemAccountState(sdb)
+ if err != nil {
+ return nil, err
+ }
if n == 0 {
- return system.GetVoteResult(sdb, []byte(id), system.GetBpCount())
+ return system.GetVoteResult(scs, []byte(id), system.GetBpCount())
}
- return system.GetVoteResult(sdb, []byte(id), int(n))
+ return system.GetVoteResult(scs, []byte(id), int(n))
case consensus.ConsensusName[consensus.ConsensusRAFT]:
//return cs.GetBPs()
return nil, ErrNotSupportedConsensus
@@ -513,11 +528,11 @@ func (cs *ChainService) getAccountVote(addr []byte) (*types.AccountVoteInfo, err
}
sdb := cs.sdb.OpenNewStateDB(cs.sdb.GetRoot())
- scs, err := sdb.GetSystemAccountState()
+ scs, err := statedb.GetSystemAccountState(sdb)
if err != nil {
return nil, err
}
- namescs, err := sdb.GetNameAccountState()
+ namescs, err := statedb.GetNameAccountState(sdb)
if err != nil {
return nil, err
}
@@ -535,11 +550,11 @@ func (cs *ChainService) getStaking(addr []byte) (*types.Staking, error) {
}
sdb := cs.sdb.OpenNewStateDB(cs.sdb.GetRoot())
- scs, err := sdb.GetSystemAccountState()
+ scs, err := statedb.GetSystemAccountState(sdb)
if err != nil {
return nil, err
}
- namescs, err := sdb.GetNameAccountState()
+ namescs, err := statedb.GetNameAccountState(sdb)
if err != nil {
return nil, err
}
@@ -551,7 +566,7 @@ func (cs *ChainService) getStaking(addr []byte) (*types.Staking, error) {
}
func (cs *ChainService) getNameInfo(qname string, blockNo types.BlockNo) (*types.NameInfo, error) {
- var stateDB *state.StateDB
+ var stateDB *statedb.StateDB
if blockNo != 0 {
block, err := cs.cdb.GetBlockByNo(blockNo)
if err != nil {
@@ -561,22 +576,34 @@ func (cs *ChainService) getNameInfo(qname string, blockNo types.BlockNo) (*types
} else {
stateDB = cs.sdb.OpenNewStateDB(cs.sdb.GetRoot())
}
- return name.GetNameInfo(stateDB, qname)
+
+ ncs, err := statedb.GetNameAccountState(stateDB)
+ if err != nil {
+ return nil, err
+ }
+ return name.GetNameInfo(ncs, qname)
}
func (cs *ChainService) getEnterpriseConf(key string) (*types.EnterpriseConfig, error) {
sdb := cs.sdb.OpenNewStateDB(cs.sdb.GetRoot())
+ ecs, err := statedb.GetEnterpriseAccountState(sdb)
+ if err != nil {
+ return nil, err
+ }
if strings.ToUpper(key) != string(dbkey.EnterpriseAdmins()) {
- return enterprise.GetConf(sdb, key)
+ return enterprise.GetConf(ecs, key)
}
- return enterprise.GetAdmin(sdb)
+ return enterprise.GetAdmin(ecs)
}
func (cs *ChainService) getSystemValue(key types.SystemValue) (*big.Int, error) {
- stateDB := cs.sdb.GetStateDB()
switch key {
case types.StakingTotal:
- return system.GetStakingTotal(stateDB)
+ scs, err := statedb.GetSystemAccountState(cs.sdb.GetStateDB())
+ if err != nil {
+ return nil, err
+ }
+ return system.GetStakingTotal(scs)
case types.StakingMin:
return system.GetStakingMinimum(), nil
case types.GasPrice:
@@ -682,9 +709,9 @@ func (cm *ChainManager) Receive(context actor.Context) {
}
}
-func getAddressNameResolved(sdb *state.StateDB, account []byte) ([]byte, error) {
+func getAddressNameResolved(sdb *statedb.StateDB, account []byte) ([]byte, error) {
if len(account) == types.NameLength {
- scs, err := sdb.GetNameAccountState()
+ scs, err := statedb.GetNameAccountState(sdb)
if err != nil {
logger.Error().Str("hash", base58.Encode(account)).Err(err).Msg("failed to get state for account")
return nil, err
@@ -695,9 +722,9 @@ func getAddressNameResolved(sdb *state.StateDB, account []byte) ([]byte, error)
}
func (cw *ChainWorker) Receive(context actor.Context) {
- var sdb *state.StateDB
+ var sdb *statedb.StateDB
- getAccProof := func(sdb *state.StateDB, account, root []byte, compressed bool) (*types.AccountProof, error) {
+ getAccProof := func(sdb *statedb.StateDB, account, root []byte, compressed bool) (*types.AccountProof, error) {
address, err := getAddressNameResolved(sdb, account)
if err != nil {
return nil, err
@@ -773,6 +800,18 @@ func (cw *ChainWorker) Receive(context actor.Context) {
Receipt: receipt,
Err: err,
})
+ case *message.GetReceipts:
+ receipts, err := cw.getReceipts(msg.BlockHash)
+ context.Respond(message.GetReceiptsRsp{
+ Receipts: receipts,
+ Err: err,
+ })
+ case *message.GetReceiptsByNo:
+ receipts, err := cw.getReceiptsByNo(msg.BlockNo)
+ context.Respond(message.GetReceiptsByNoRsp{
+ Receipts: receipts,
+ Err: err,
+ })
case *message.GetABI:
sdb = cw.sdb.OpenNewStateDB(cw.sdb.GetRoot())
address, err := getAddressNameResolved(sdb, msg.Contract)
@@ -783,7 +822,7 @@ func (cw *ChainWorker) Receive(context actor.Context) {
})
break
}
- contractState, err := sdb.OpenContractStateAccount(types.ToAccountID(address))
+ contractState, err := statedb.OpenContractStateAccount(address, sdb)
if err == nil {
abi, err := contract.GetABI(contractState, nil)
context.Respond(message.GetABIRsp{
@@ -805,7 +844,7 @@ func (cw *ChainWorker) Receive(context actor.Context) {
context.Respond(message.GetQueryRsp{Result: nil, Err: err})
break
}
- ctrState, err := sdb.OpenContractStateAccount(types.ToAccountID(address))
+ ctrState, err := statedb.OpenContractStateAccount(address, sdb)
if err != nil {
logger.Error().Str("hash", base58.Encode(address)).Err(err).Msg("failed to get state for contract")
context.Respond(message.GetQueryRsp{Result: nil, Err: err})
@@ -893,7 +932,7 @@ func (cw *ChainWorker) Receive(context actor.Context) {
defer runtime.UnlockOSThread()
sdb = cw.sdb.OpenNewStateDB(cw.sdb.GetRoot())
- ctrState, err := sdb.OpenContractStateAccount(types.ToAccountID(msg.Contract))
+ ctrState, err := statedb.OpenContractStateAccount(msg.Contract, sdb)
if err != nil {
logger.Error().Str("hash", base58.Encode(msg.Contract)).Err(err).Msg("failed to get state for contract")
context.Respond(message.CheckFeeDelegationRsp{Err: err})
diff --git a/chain/governance.go b/chain/governance.go
index fcc6457a6..994bb1bda 100644
--- a/chain/governance.go
+++ b/chain/governance.go
@@ -14,10 +14,11 @@ import (
"github.com/aergoio/aergo/v2/contract/name"
"github.com/aergoio/aergo/v2/contract/system"
"github.com/aergoio/aergo/v2/state"
+ "github.com/aergoio/aergo/v2/state/statedb"
"github.com/aergoio/aergo/v2/types"
)
-func executeGovernanceTx(ccc consensus.ChainConsensusCluster, bs *state.BlockState, txBody *types.TxBody, sender, receiver *state.V,
+func executeGovernanceTx(ccc consensus.ChainConsensusCluster, bs *state.BlockState, txBody *types.TxBody, sender, receiver *state.AccountState,
blockInfo *types.BlockHeaderInfo) ([]*types.Event, error) {
if len(txBody.Payload) <= 0 {
@@ -25,8 +26,7 @@ func executeGovernanceTx(ccc consensus.ChainConsensusCluster, bs *state.BlockSta
}
governance := string(txBody.Recipient)
-
- scs, err := bs.StateDB.OpenContractState(receiver.AccountID(), receiver.State())
+ scs, err := statedb.OpenContractState(receiver.IDNoPadding(), receiver.State(), bs.StateDB)
if err != nil {
return nil, err
}
@@ -47,7 +47,7 @@ func executeGovernanceTx(ccc consensus.ChainConsensusCluster, bs *state.BlockSta
err = types.ErrTxInvalidRecipient
}
if err == nil {
- err = bs.StateDB.StageContractState(scs)
+ err = statedb.StageContractState(scs, bs.StateDB)
}
return events, err
@@ -55,8 +55,8 @@ func executeGovernanceTx(ccc consensus.ChainConsensusCluster, bs *state.BlockSta
// InitGenesisBPs opens system contract and put initial voting result
// it also set *State in Genesis to use statedb
-func InitGenesisBPs(states *state.StateDB, genesis *types.Genesis) error {
- scs, err := states.GetSystemAccountState()
+func InitGenesisBPs(states *statedb.StateDB, genesis *types.Genesis) error {
+ scs, err := statedb.GetSystemAccountState(states)
if err != nil {
return err
}
@@ -72,7 +72,7 @@ func InitGenesisBPs(states *state.StateDB, genesis *types.Genesis) error {
// Set genesis.BPs to the votes-ordered BPs. This will be used later for
// bootstrapping.
genesis.BPs = system.BuildOrderedCandidates(voteResult)
- if err = states.StageContractState(scs); err != nil {
+ if err = statedb.StageContractState(scs, states); err != nil {
return err
}
if err = states.Update(); err != nil {
diff --git a/chain/reorg.go b/chain/reorg.go
index 7f3f3f867..41babf9b4 100644
--- a/chain/reorg.go
+++ b/chain/reorg.go
@@ -10,6 +10,7 @@ import (
"github.com/aergoio/aergo/v2/contract/system"
"github.com/aergoio/aergo/v2/internal/enc/base58"
"github.com/aergoio/aergo/v2/state"
+ "github.com/aergoio/aergo/v2/state/statedb"
"github.com/aergoio/aergo/v2/types"
"github.com/aergoio/aergo/v2/types/message"
)
@@ -168,7 +169,7 @@ func (cs *ChainService) reorg(topBlock *types.Block, marker *ReorgMarker) error
}
cs.stat.updateEvent(ReorgStat, time.Since(begT), reorg.oldBlocks[0], reorg.newBlocks[0], reorg.brStartBlock)
- systemStateDB, err := cs.SDB().GetSystemAccountState()
+ systemStateDB, err := statedb.GetSystemAccountState(cs.SDB().GetStateDB())
system.InitSystemParams(systemStateDB, system.RESET)
logger.Info().Msg("reorg end")
diff --git a/chain/signVerifier.go b/chain/signVerifier.go
index a9ce80512..330ca7989 100644
--- a/chain/signVerifier.go
+++ b/chain/signVerifier.go
@@ -10,6 +10,7 @@ import (
"github.com/aergoio/aergo/v2/internal/enc/base58"
"github.com/aergoio/aergo/v2/pkg/component"
"github.com/aergoio/aergo/v2/state"
+ "github.com/aergoio/aergo/v2/state/statedb"
"github.com/aergoio/aergo/v2/types"
"github.com/aergoio/aergo/v2/types/message"
)
@@ -132,7 +133,7 @@ func (sv *SignVerifier) verifyTx(comm component.IComponentRequester, tx *types.T
}
if tx.NeedNameVerify() {
- cs, err := sv.sdb.GetStateDB().GetNameAccountState()
+ cs, err := statedb.GetNameAccountState(sv.sdb.GetStateDB())
if err != nil {
logger.Error().Err(err).Msg("failed to get verify because of opening contract error")
return false, err
diff --git a/cmd/aergocli/cmd/accounts.go b/cmd/aergocli/cmd/accounts.go
index 69fe50e0c..6c9f10bd9 100644
--- a/cmd/aergocli/cmd/accounts.go
+++ b/cmd/aergocli/cmd/accounts.go
@@ -5,7 +5,6 @@ import (
"errors"
"fmt"
"io"
- "io/ioutil"
"log"
"os"
"path/filepath"
@@ -237,7 +236,7 @@ func importKeystore(cmd *cobra.Command) ([]byte, error) {
if err != nil {
return nil, err
}
- keystore, err := ioutil.ReadFile(absPath)
+ keystore, err := os.ReadFile(absPath)
if err != nil {
return nil, err
}
diff --git a/cmd/aergocli/cmd/blockchain.go b/cmd/aergocli/cmd/blockchain.go
index 0e5b4a579..dd2bb0855 100644
--- a/cmd/aergocli/cmd/blockchain.go
+++ b/cmd/aergocli/cmd/blockchain.go
@@ -8,8 +8,8 @@ package cmd
import (
"context"
- "github.com/aergoio/aergo/v2/cmd/aergocli/util"
aergorpc "github.com/aergoio/aergo/v2/types"
+ "github.com/aergoio/aergo/v2/types/jsonrpc"
"github.com/spf13/cobra"
)
@@ -30,9 +30,11 @@ var blockchainCmd = &cobra.Command{
return
}
if printHex {
- cmd.Println(util.ConvHexBlockchainStatus(msg))
+ res := jsonrpc.ConvHexBlockchainStatus(msg)
+ cmd.Println(jsonrpc.MarshalJSON(res))
} else {
- cmd.Println(util.ConvBlockchainStatus(msg))
+ res := jsonrpc.ConvBlockchainStatus(msg)
+ cmd.Println(jsonrpc.MarshalJSON(res))
}
},
}
diff --git a/cmd/aergocli/cmd/blockchain_test.go b/cmd/aergocli/cmd/blockchain_test.go
index 271f32234..f5650a9c6 100644
--- a/cmd/aergocli/cmd/blockchain_test.go
+++ b/cmd/aergocli/cmd/blockchain_test.go
@@ -1,9 +1,9 @@
package cmd
import (
+ "encoding/json"
"testing"
- "github.com/aergoio/aergo/v2/cmd/aergocli/util/encoding/json"
"github.com/aergoio/aergo/v2/internal/enc/base58"
"github.com/aergoio/aergo/v2/internal/enc/hex"
"github.com/aergoio/aergo/v2/types"
@@ -35,8 +35,8 @@ func TestBlockchainWithMock(t *testing.T) {
t.Fatal(err)
}
- assert.Equal(t, testBlockHashString, result["Hash"])
- assert.Equal(t, float64(1), result["Height"])
+ assert.Equal(t, testBlockHashString, result["hash"])
+ assert.Equal(t, float64(1), result["height"])
output, err = executeCommand(rootCmd, "blockchain", "trashargs")
assert.NoError(t, err, "should be success")
@@ -49,6 +49,6 @@ func TestBlockchainWithMock(t *testing.T) {
t.Fatal(err)
}
testBlockHashByte, _ := base58.Decode(testBlockHashString)
- assert.Equal(t, hex.Encode(testBlockHashByte), result["Hash"])
- assert.Equal(t, float64(1), result["Height"])
+ assert.Equal(t, hex.Encode(testBlockHashByte), result["hash"])
+ assert.Equal(t, float64(1), result["height"])
}
diff --git a/cmd/aergocli/cmd/chaininfo.go b/cmd/aergocli/cmd/chaininfo.go
index fce5e3b90..dd95d5f73 100644
--- a/cmd/aergocli/cmd/chaininfo.go
+++ b/cmd/aergocli/cmd/chaininfo.go
@@ -3,8 +3,8 @@ package cmd
import (
"context"
- "github.com/aergoio/aergo/v2/cmd/aergocli/util"
"github.com/aergoio/aergo/v2/types"
+ "github.com/aergoio/aergo/v2/types/jsonrpc"
"github.com/spf13/cobra"
)
@@ -21,6 +21,7 @@ var chaininfoCmd = &cobra.Command{
cmd.Printf("Failed: %s\n", err.Error())
return
}
- cmd.Println(util.ConvChainInfoMsg(msg))
+ res := jsonrpc.ConvChainInfo(msg)
+ cmd.Println(jsonrpc.MarshalJSON(res))
},
}
diff --git a/cmd/aergocli/util/grpccommon.go b/cmd/aergocli/cmd/client.go
similarity index 57%
rename from cmd/aergocli/util/grpccommon.go
rename to cmd/aergocli/cmd/client.go
index 11a6b3b93..52d90ed76 100644
--- a/cmd/aergocli/util/grpccommon.go
+++ b/cmd/aergocli/cmd/client.go
@@ -3,13 +3,11 @@
* @copyright defined in aergo/LICENSE.txt
*/
-package util
+package cmd
import (
"fmt"
- "github.com/aergoio/aergo/v2/cmd/aergocli/util/encoding/json"
- "github.com/aergoio/aergo/v2/internal/enc/proto"
"github.com/aergoio/aergo/v2/types"
"google.golang.org/grpc"
)
@@ -42,22 +40,3 @@ func (c *ConnClient) Close() {
c.conn.Close()
c.conn = nil
}
-
-// JSON converts protobuf message(struct) to json notation
-func JSON(pb proto.Message) string {
- jsonout, err := json.MarshalIndent(pb, "", " ")
- if err != nil {
- fmt.Printf("Failed: %s\n", err.Error())
- return ""
- }
- return string(jsonout)
-}
-
-func B58JSON(i interface{}) string {
- jsonout, err := json.MarshalIndent(i, "", " ")
- if err != nil {
- fmt.Printf("Failed: %s\n", err.Error())
- return ""
- }
- return string(jsonout)
-}
diff --git a/cmd/aergocli/cmd/committx.go b/cmd/aergocli/cmd/committx.go
index 9dbdfd8a2..94b382ea4 100644
--- a/cmd/aergocli/cmd/committx.go
+++ b/cmd/aergocli/cmd/committx.go
@@ -8,10 +8,10 @@ package cmd
import (
"context"
"errors"
- "io/ioutil"
+ "os"
- "github.com/aergoio/aergo/v2/cmd/aergocli/util"
"github.com/aergoio/aergo/v2/types"
+ "github.com/aergoio/aergo/v2/types/jsonrpc"
"github.com/spf13/cobra"
)
@@ -50,7 +50,7 @@ func init() {
func execCommitTX(cmd *cobra.Command, args []string) error {
if jsonPath != "" {
- b, readerr := ioutil.ReadFile(jsonPath)
+ b, readerr := os.ReadFile(jsonPath)
if readerr != nil {
return errors.New("Failed to read --jsontxpath\n" + readerr.Error())
}
@@ -59,7 +59,7 @@ func execCommitTX(cmd *cobra.Command, args []string) error {
if jsonTx != "" {
var msg *types.CommitResultList
- txlist, err := util.ParseBase58Tx([]byte(jsonTx))
+ txlist, err := jsonrpc.ParseBase58Tx([]byte(jsonTx))
if err != nil {
return errors.New("Failed to parse --jsontx\n" + err.Error())
}
@@ -67,7 +67,8 @@ func execCommitTX(cmd *cobra.Command, args []string) error {
if err != nil {
return errors.New("Failed request to aergo server\n" + err.Error())
}
- cmd.Println(util.JSON(msg))
+ res := jsonrpc.ConvCommitResultList(msg)
+ cmd.Println(jsonrpc.MarshalJSON(res))
}
return nil
}
diff --git a/cmd/aergocli/cmd/committx_test.go b/cmd/aergocli/cmd/committx_test.go
index aa5eb00fd..3b3cc2999 100644
--- a/cmd/aergocli/cmd/committx_test.go
+++ b/cmd/aergocli/cmd/committx_test.go
@@ -1,11 +1,12 @@
package cmd
import (
+ "encoding/json"
"testing"
- "github.com/aergoio/aergo/v2/cmd/aergocli/util/encoding/json"
"github.com/aergoio/aergo/v2/internal/enc/base58"
"github.com/aergoio/aergo/v2/types"
+ "github.com/aergoio/aergo/v2/types/jsonrpc"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert"
)
@@ -34,10 +35,10 @@ func TestCommitTxWithMock(t *testing.T) {
).MaxTimes(1)
output, err = executeCommand(rootCmd, "committx", "--jsontx", "{\"Body\":{}}")
- out := &types.CommitResultList{}
+ out := &jsonrpc.InOutCommitResultList{}
err = json.Unmarshal([]byte(output), out)
assert.NoError(t, err, "commit output is invalid")
- assert.Equal(t, "tx invalid format", out.GetResults()[0].Detail)
+ assert.Equal(t, "tx invalid format", out.Results[0].Detail)
mock.EXPECT().CommitTX(
gomock.Any(), // expect any value for first parameter
@@ -56,5 +57,5 @@ func TestCommitTxWithMock(t *testing.T) {
output, err = executeCommand(rootCmd, "committx", "--jsontx", "{ \"Hash\": \"HB44gJvHhVoEfgiGq3VZmV9VUXfBXhHjcEvroBMkJGnY\", \"Body\": {\"Nonce\": 2, \"Account\": \"AmNBZ8WQKP8DbuP9Q9W9vGFhiT8vQNcuSZ2SbBbVvbJWGV3Wh1mn\", \"Recipient\": \"AmLnVfGwq49etaa7dnzfGJTbaZWV7aVmrxFes4KmWukXwtooVZPJ\", \"Amount\": \"25000\", \"Payload\": \"\", \"Limit\": 100, \"Price\": \"1\", \"Type\": 0, \"Sign\": \"381yXYxTtq2tRPRQPF7tHH6Cq3y8PvcsFWztPwCRmmYfqnK83Z3a6Yj9fyy8Rpvrrw76Y52SNAP6Th3BYQjX1Bcmf6NQrDHQ\"}}")
err = json.Unmarshal([]byte(output), out)
assert.NoError(t, err, "should no error")
- assert.Equal(t, "HB44gJvHhVoEfgiGq3VZmV9VUXfBXhHjcEvroBMkJGnY", base58.Encode(out.GetResults()[0].Hash))
+ assert.Equal(t, "HB44gJvHhVoEfgiGq3VZmV9VUXfBXhHjcEvroBMkJGnY", out.Results[0].Hash)
}
diff --git a/cmd/aergocli/cmd/contract.go b/cmd/aergocli/cmd/contract.go
index 010b7f6ac..9d0b6f4cb 100644
--- a/cmd/aergocli/cmd/contract.go
+++ b/cmd/aergocli/cmd/contract.go
@@ -6,10 +6,9 @@ import (
"encoding/json"
"errors"
"fmt"
- "io/ioutil"
+ "os"
"strconv"
- "github.com/aergoio/aergo/v2/cmd/aergocli/util"
luacEncoding "github.com/aergoio/aergo/v2/cmd/aergoluac/encoding"
luac "github.com/aergoio/aergo/v2/cmd/aergoluac/util"
"github.com/aergoio/aergo/v2/internal/common"
@@ -17,11 +16,12 @@ import (
"github.com/aergoio/aergo/v2/internal/enc/hex"
"github.com/aergoio/aergo/v2/types"
aergorpc "github.com/aergoio/aergo/v2/types"
+ "github.com/aergoio/aergo/v2/types/jsonrpc"
"github.com/spf13/cobra"
)
var (
- client *util.ConnClient
+ client *ConnClient
admClient types.AdminRPCServiceClient
data string
nonce uint64
@@ -170,12 +170,12 @@ func runDeployCmd(cmd *cobra.Command, args []string) error {
cmd.SilenceUsage = false
return errors.New("not enough arguments")
}
- code, err = ioutil.ReadFile(args[1])
+ code, err = os.ReadFile(args[1])
if err != nil {
return fmt.Errorf("failed to read code file: %v", err.Error())
}
var abi []byte
- abi, err = ioutil.ReadFile(args[2])
+ abi, err = os.ReadFile(args[2])
if err != nil {
return fmt.Errorf("failed to read abi file: %v", err.Error())
}
@@ -212,7 +212,7 @@ func runDeployCmd(cmd *cobra.Command, args []string) error {
}
}
- amountBigInt, err := util.ParseUnit(amount)
+ amountBigInt, err := jsonrpc.ParseUnit(amount)
if err != nil {
return fmt.Errorf("failed to parse amount: %v", err.Error())
}
@@ -284,7 +284,7 @@ func runCallCmd(cmd *cobra.Command, args []string) error {
}
}
- amountBigInt, err := util.ParseUnit(amount)
+ amountBigInt, err := jsonrpc.ParseUnit(amount)
if err != nil {
return fmt.Errorf("failed to parse amount: %v", err)
}
@@ -342,7 +342,8 @@ func runCallCmd(cmd *cobra.Command, args []string) error {
}
if toJSON {
- cmd.Println(util.TxConvBase58Addr(tx))
+ res := jsonrpc.ConvTx(tx, jsonrpc.Base58)
+ cmd.Println(jsonrpc.MarshalJSON(res))
} else {
txs := []*types.Tx{tx}
var msgs *types.CommitResultList
@@ -350,7 +351,8 @@ func runCallCmd(cmd *cobra.Command, args []string) error {
if err != nil {
return fmt.Errorf("failed to commit tx: %v", err.Error())
}
- cmd.Println(util.JSON(msgs.Results[0]))
+ res := jsonrpc.ConvCommitResult(msgs.Results[0])
+ cmd.Println(jsonrpc.MarshalJSON(res))
}
return nil
}
@@ -366,7 +368,8 @@ func runGetABICmd(cmd *cobra.Command, args []string) error {
if err != nil {
return fmt.Errorf("failed to get abi: %v", err.Error())
}
- cmd.Println(util.JSON(abi))
+ res := jsonrpc.ConvAbi(abi)
+ cmd.Println(jsonrpc.MarshalJSON(res))
return nil
}
diff --git a/cmd/aergocli/cmd/enterprise.go b/cmd/aergocli/cmd/enterprise.go
index ed57846d4..fdd5c80f1 100644
--- a/cmd/aergocli/cmd/enterprise.go
+++ b/cmd/aergocli/cmd/enterprise.go
@@ -8,17 +8,17 @@ package cmd
import (
"context"
"encoding/binary"
+ "encoding/json"
"errors"
"fmt"
"strings"
"time"
- "github.com/aergoio/aergo/v2/cmd/aergocli/util"
- "github.com/aergoio/aergo/v2/cmd/aergocli/util/encoding/json"
"github.com/aergoio/aergo/v2/contract/enterprise"
"github.com/aergoio/aergo/v2/internal/enc/base58"
"github.com/aergoio/aergo/v2/types"
aergorpc "github.com/aergoio/aergo/v2/types"
+ "github.com/aergoio/aergo/v2/types/jsonrpc"
"github.com/spf13/cobra"
)
@@ -67,7 +67,7 @@ var enterpriseKeyCmd = &cobra.Command{
if strings.ToUpper(args[0]) != "PERMISSIONS" {
out.On = &msg.On //it's for print false
}
- cmd.Println(util.B58JSON(out))
+ cmd.Println(jsonrpc.MarshalJSON(out))
},
}
@@ -86,7 +86,7 @@ func getConfChangeBlockNo(blockHash []byte) (aergorpc.BlockNo, error) {
type OutConfChange struct {
Payload string
- TxStatus *aergorpc.EnterpriseTxStatus
+ TxStatus *jsonrpc.InOutEnterpriseTxStatus
}
func (occ *OutConfChange) ToString() string {
@@ -222,21 +222,21 @@ var enterpriseTxCmd = &cobra.Command{
cmd.Println(output.ToString())
return
}
- output.TxStatus = &aergorpc.EnterpriseTxStatus{
+ TxStatus := &aergorpc.EnterpriseTxStatus{
Status: receipt.GetStatus(),
Ret: receipt.GetRet(),
}
if ci.Name == enterprise.ChangeCluster {
if confChange, err = getChangeClusterStatus(cmd, msgblock.TxIdx.BlockHash, timer); err != nil {
- output.TxStatus.CCStatus = &types.ChangeClusterStatus{Error: err.Error()}
+ TxStatus.CCStatus = &types.ChangeClusterStatus{Error: err.Error()}
}
if confChange != nil {
- output.TxStatus.CCStatus = confChange.ToPrintable()
+ TxStatus.CCStatus = confChange.ToPrintable()
}
}
-
+ output.TxStatus = jsonrpc.ConvEnterpriseTxStatus(TxStatus)
cmd.Println(output.ToString())
}
diff --git a/cmd/aergocli/cmd/event.go b/cmd/aergocli/cmd/event.go
index 41d8dc2dd..4c50acaac 100644
--- a/cmd/aergocli/cmd/event.go
+++ b/cmd/aergocli/cmd/event.go
@@ -9,8 +9,8 @@ import (
"context"
"log"
- "github.com/aergoio/aergo/v2/cmd/aergocli/util"
aergorpc "github.com/aergoio/aergo/v2/types"
+ "github.com/aergoio/aergo/v2/types/jsonrpc"
"github.com/spf13/cobra"
)
@@ -82,7 +82,8 @@ func execListEvent(cmd *cobra.Command, args []string) {
return
}
for _, event := range events.GetEvents() {
- cmd.Println(util.JSON(event))
+ res := jsonrpc.ConvEvent(event)
+ cmd.Println(jsonrpc.MarshalJSON(res))
}
}
@@ -108,6 +109,7 @@ func execStreamEvent(cmd *cobra.Command, args []string) {
cmd.Printf("Failed: %s\n", err.Error())
return
}
- cmd.Println(util.JSON(event))
+ res := jsonrpc.ConvEvent(event)
+ cmd.Println(jsonrpc.MarshalJSON(res))
}
}
diff --git a/cmd/aergocli/cmd/getblock.go b/cmd/aergocli/cmd/getblock.go
index f54e43dbb..b3ac3c123 100644
--- a/cmd/aergocli/cmd/getblock.go
+++ b/cmd/aergocli/cmd/getblock.go
@@ -11,9 +11,9 @@ import (
"errors"
"fmt"
- "github.com/aergoio/aergo/v2/cmd/aergocli/util"
"github.com/aergoio/aergo/v2/internal/enc/base58"
aergorpc "github.com/aergoio/aergo/v2/types"
+ "github.com/aergoio/aergo/v2/types/jsonrpc"
"github.com/spf13/cobra"
)
@@ -45,7 +45,8 @@ func streamBlocks(cmd *cobra.Command) error {
if err != nil {
return fmt.Errorf("failed to receive block: %v", err)
}
- cmd.Println(util.BlockConvBase58Addr(b))
+ res := jsonrpc.ConvBlock(b)
+ cmd.Println(jsonrpc.MarshalJSON(res))
}
}
@@ -70,7 +71,8 @@ func getSingleBlock(cmd *cobra.Command) error {
if err != nil {
return fmt.Errorf("failed to get block: %v", err)
}
- cmd.Println(util.BlockConvBase58Addr(msg))
+ res := jsonrpc.ConvBlock(msg)
+ cmd.Println(jsonrpc.MarshalJSON(res))
return nil
}
diff --git a/cmd/aergocli/cmd/getpeers.go b/cmd/aergocli/cmd/getpeers.go
index 571313eac..93d490a11 100644
--- a/cmd/aergocli/cmd/getpeers.go
+++ b/cmd/aergocli/cmd/getpeers.go
@@ -12,8 +12,8 @@ import (
"sort"
"strings"
- "github.com/aergoio/aergo/v2/cmd/aergocli/util"
"github.com/aergoio/aergo/v2/types"
+ "github.com/aergoio/aergo/v2/types/jsonrpc"
"github.com/spf13/cobra"
)
@@ -59,12 +59,15 @@ func execGetPeers(cmd *cobra.Command, args []string) {
// address and peerid should be encoded, respectively
sorter.Sort(msg.Peers)
if detailed == 0 {
- cmd.Println(util.PeerListToString(msg))
+ res := jsonrpc.ConvPeerList(msg)
+ cmd.Println(jsonrpc.MarshalJSON(res))
} else if detailed > 0 {
// TODO show long fields
- cmd.Println(util.LongPeerListToString(msg))
+ res := jsonrpc.ConvLongPeerList(msg)
+ cmd.Println(jsonrpc.MarshalJSON(res))
} else {
- cmd.Println(util.ShortPeerListToString(msg))
+ res := jsonrpc.ConvShortPeerList(msg)
+ cmd.Println(jsonrpc.MarshalJSON(res))
}
}
diff --git a/cmd/aergocli/cmd/getstate.go b/cmd/aergocli/cmd/getstate.go
index 7e3080523..e30f80533 100644
--- a/cmd/aergocli/cmd/getstate.go
+++ b/cmd/aergocli/cmd/getstate.go
@@ -8,9 +8,9 @@ package cmd
import (
"context"
- "github.com/aergoio/aergo/v2/cmd/aergocli/util"
"github.com/aergoio/aergo/v2/internal/enc/base58"
"github.com/aergoio/aergo/v2/types"
+ "github.com/aergoio/aergo/v2/types/jsonrpc"
"github.com/spf13/cobra"
)
@@ -53,7 +53,7 @@ func execGetState(cmd *cobra.Command, args []string) {
cmd.Printf("Failed: %s", err.Error())
return
}
- amount, err := util.ConvertUnit(msg.GetAmountBigInt(), unit)
+ amount, err := jsonrpc.ConvertUnit(msg.GetAmountBigInt(), unit)
if err != nil {
cmd.Printf("Failed: %s", err.Error())
return
@@ -73,7 +73,7 @@ func execGetState(cmd *cobra.Command, args []string) {
cmd.Printf("Failed: %s", err.Error())
return
}
- balance, err := util.ConvertUnit(msg.GetBalanceBigInt(), unit)
+ balance, err := jsonrpc.ConvertUnit(msg.GetBalanceBigInt(), unit)
if err != nil {
cmd.Printf("Failed: %s", err.Error())
return
@@ -89,7 +89,7 @@ func execGetState(cmd *cobra.Command, args []string) {
cmd.Printf("Failed: %s", err.Error())
return
}
- balance, err := util.ConvertUnit(msg.GetState().GetBalanceBigInt(), unit)
+ balance, err := jsonrpc.ConvertUnit(msg.GetState().GetBalanceBigInt(), unit)
if err != nil {
cmd.Printf("Failed: %s", err.Error())
return
diff --git a/cmd/aergocli/cmd/gettx.go b/cmd/aergocli/cmd/gettx.go
index a122aec0c..3791bcf34 100644
--- a/cmd/aergocli/cmd/gettx.go
+++ b/cmd/aergocli/cmd/gettx.go
@@ -8,9 +8,9 @@ package cmd
import (
"context"
- "github.com/aergoio/aergo/v2/cmd/aergocli/util"
"github.com/aergoio/aergo/v2/internal/enc/base58"
aergorpc "github.com/aergoio/aergo/v2/types"
+ "github.com/aergoio/aergo/v2/types/jsonrpc"
"github.com/spf13/cobra"
)
@@ -35,20 +35,20 @@ func execGetTX(cmd *cobra.Command, args []string) {
cmd.Printf("Failed decode: %s", err.Error())
return
}
- payloadEncodingType := util.Base58
+ payloadEncodingType := jsonrpc.Base58
if rawPayload {
- payloadEncodingType = util.Raw
+ payloadEncodingType = jsonrpc.Raw
}
msg, err := client.GetTX(context.Background(), &aergorpc.SingleBytes{Value: txHash})
if err == nil {
- cmd.Println(util.ConvTxEx(msg, payloadEncodingType))
+ cmd.Println(jsonrpc.ConvTx(msg, payloadEncodingType))
} else {
msgblock, err := client.GetBlockTX(context.Background(), &aergorpc.SingleBytes{Value: txHash})
if err != nil {
cmd.Printf("Failed: %s", err.Error())
return
}
- cmd.Println(util.ConvTxInBlockEx(msgblock, payloadEncodingType))
+ cmd.Println(jsonrpc.ConvTxInBlock(msgblock, payloadEncodingType))
}
}
diff --git a/cmd/aergocli/cmd/keygen.go b/cmd/aergocli/cmd/keygen.go
index ef553d154..96b62e391 100644
--- a/cmd/aergocli/cmd/keygen.go
+++ b/cmd/aergocli/cmd/keygen.go
@@ -105,7 +105,7 @@ func generateKeyFiles(prefix string) error {
pkFile := prefix + ".key"
// Write private key file
- err := saveKeyFile(pkFile, priv)
+ err := savePrivKeyFile(pkFile, priv)
if err != nil {
return err
}
@@ -117,7 +117,7 @@ func saveFilesFromKeys(priv crypto.PrivKey, pub crypto.PubKey, prefix string) er
pubFile := prefix + ".pub"
idFile := prefix + ".id"
// Write public key file
- err := saveKeyFile(pubFile, pub)
+ err := savePubKeyFile(pubFile, pub)
if err != nil {
return err
}
@@ -128,7 +128,7 @@ func saveFilesFromKeys(priv crypto.PrivKey, pub crypto.PubKey, prefix string) er
saveBytesToFile(idFile, idBytes)
if genAddress {
- pkBytes, err := priv.Bytes()
+ pkBytes, err := crypto.MarshalPrivateKey(priv)
if err != nil {
return err
}
@@ -149,12 +149,28 @@ func saveFilesFromKeys(priv crypto.PrivKey, pub crypto.PubKey, prefix string) er
return nil
}
-func saveKeyFile(pkFile string, priv crypto.Key) error {
+func savePrivKeyFile(pkFile string, priv crypto.PrivKey) error {
pkf, err := os.Create(pkFile)
if err != nil {
return err
}
- pkBytes, err := priv.Bytes()
+ pkBytes, err := crypto.MarshalPrivateKey(priv)
+ if err != nil {
+ return err
+ }
+ _, err = pkf.Write(pkBytes)
+ if err != nil {
+ return err
+ }
+ return pkf.Sync()
+}
+
+func savePubKeyFile(pkFile string, pub crypto.PubKey) error {
+ pkf, err := os.Create(pkFile)
+ if err != nil {
+ return err
+ }
+ pkBytes, err := crypto.MarshalPublicKey(pub)
if err != nil {
return err
}
@@ -179,7 +195,7 @@ func saveBytesToFile(fileName string, bytes []byte) error {
func generateKeyJson(priv crypto.PrivKey, pub crypto.PubKey) error {
btcPK := p2putil.ConvertPKToBTCEC(priv)
pkBytes := btcPK.Serialize()
- pubBytes, err := pub.Bytes()
+ pubBytes, err := crypto.MarshalPublicKey(pub)
pid, _ := types.IDFromPublicKey(pub)
if err != nil {
return err
diff --git a/cmd/aergocli/cmd/listblocks.go b/cmd/aergocli/cmd/listblocks.go
index aa4c1c003..e384a5ba6 100644
--- a/cmd/aergocli/cmd/listblocks.go
+++ b/cmd/aergocli/cmd/listblocks.go
@@ -8,9 +8,9 @@ package cmd
import (
"context"
- "github.com/aergoio/aergo/v2/cmd/aergocli/util"
"github.com/aergoio/aergo/v2/internal/enc/base58"
"github.com/aergoio/aergo/v2/types"
+ "github.com/aergoio/aergo/v2/types/jsonrpc"
"github.com/spf13/cobra"
)
@@ -64,5 +64,6 @@ func execListBlockHeaders(cmd *cobra.Command, args []string) {
cmd.Printf("Failed: %s", err.Error())
return
}
- cmd.Println(util.JSON(msg))
+ res := jsonrpc.ConvBlockHeaderList(msg)
+ cmd.Println(jsonrpc.MarshalJSON(res))
}
diff --git a/cmd/aergocli/cmd/mempool.go b/cmd/aergocli/cmd/mempool.go
index 846d80a79..96643675d 100644
--- a/cmd/aergocli/cmd/mempool.go
+++ b/cmd/aergocli/cmd/mempool.go
@@ -6,7 +6,6 @@ import (
"log"
"strings"
- "github.com/aergoio/aergo/v2/cmd/aergocli/util"
"github.com/aergoio/aergo/v2/types"
"github.com/spf13/cobra"
"google.golang.org/grpc"
@@ -77,6 +76,6 @@ func newAergoAdminClient(sockPath string) types.AdminRPCServiceClient {
grpc.WithInsecure(),
}
return types.NewAdminRPCServiceClient(
- util.GetConn(fmt.Sprintf("unix:%s", sockPath), opts),
+ GetConn(fmt.Sprintf("unix:%s", sockPath), opts),
)
}
diff --git a/cmd/aergocli/cmd/metric.go b/cmd/aergocli/cmd/metric.go
index a18268a12..40e22a8e6 100644
--- a/cmd/aergocli/cmd/metric.go
+++ b/cmd/aergocli/cmd/metric.go
@@ -8,8 +8,8 @@ package cmd
import (
"context"
- "github.com/aergoio/aergo/v2/cmd/aergocli/util"
"github.com/aergoio/aergo/v2/types"
+ "github.com/aergoio/aergo/v2/types/jsonrpc"
"github.com/spf13/cobra"
)
@@ -40,5 +40,6 @@ func execMetric(cmd *cobra.Command, args []string) {
return
}
// address and peerid should be encoded, respectively
- cmd.Println(util.JSON(msg))
+ res := jsonrpc.ConvMetrics(msg)
+ cmd.Println(jsonrpc.MarshalJSON(res))
}
diff --git a/cmd/aergocli/cmd/name.go b/cmd/aergocli/cmd/name.go
index 68b065ef1..82d4338ff 100644
--- a/cmd/aergocli/cmd/name.go
+++ b/cmd/aergocli/cmd/name.go
@@ -13,8 +13,8 @@ import (
"log"
"math/big"
- "github.com/aergoio/aergo/v2/cmd/aergocli/util"
"github.com/aergoio/aergo/v2/types"
+ "github.com/aergoio/aergo/v2/types/jsonrpc"
"github.com/spf13/cobra"
)
@@ -77,7 +77,7 @@ func execNameNew(cmd *cobra.Command, args []string) error {
if len(name) != types.NameLength {
return errors.New("the name must be 12 alphabetic characters")
}
- amount, err := util.ParseUnit(spending)
+ amount, err := jsonrpc.ParseUnit(spending)
if err != nil {
return fmt.Errorf("wrong value in --amount flag: %v", err.Error())
}
@@ -114,7 +114,7 @@ func execNameUpdate(cmd *cobra.Command, args []string) error {
if err != nil {
return fmt.Errorf("Wrong address in --to flag: %v", err.Error())
}
- amount, err := util.ParseUnit(spending)
+ amount, err := jsonrpc.ParseUnit(spending)
if err != nil {
return fmt.Errorf("Wrong value in --amount flag: %v", err.Error())
}
diff --git a/cmd/aergocli/cmd/receipt.go b/cmd/aergocli/cmd/receipt.go
index c36945556..3a033707c 100644
--- a/cmd/aergocli/cmd/receipt.go
+++ b/cmd/aergocli/cmd/receipt.go
@@ -9,9 +9,9 @@ import (
"context"
"log"
- "github.com/aergoio/aergo/v2/cmd/aergocli/util"
"github.com/aergoio/aergo/v2/internal/enc/base58"
aergorpc "github.com/aergoio/aergo/v2/types"
+ "github.com/aergoio/aergo/v2/types/jsonrpc"
"github.com/spf13/cobra"
)
@@ -36,7 +36,8 @@ func init() {
if err != nil {
log.Fatal(err)
}
- cmd.Println(util.JSON(msg))
+ res := jsonrpc.ConvReceipt(msg)
+ cmd.Println(jsonrpc.MarshalJSON(res))
},
},
)
diff --git a/cmd/aergocli/cmd/root.go b/cmd/aergocli/cmd/root.go
index 53d496d95..b1e4957a0 100644
--- a/cmd/aergocli/cmd/root.go
+++ b/cmd/aergocli/cmd/root.go
@@ -9,11 +9,9 @@ import (
"crypto/tls"
"crypto/x509"
"fmt"
- "io/ioutil"
"log"
"os"
- "github.com/aergoio/aergo/v2/cmd/aergocli/util"
"github.com/aergoio/aergo/v2/types"
"github.com/rs/zerolog"
"github.com/spf13/cobra"
@@ -143,7 +141,7 @@ func connectAergo(cmd *cobra.Command, args []string) {
log.Fatal("wrong tls setting : ", err)
}
certPool := x509.NewCertPool()
- ca, err := ioutil.ReadFile(rootConfig.TLS.CACert)
+ ca, err := os.ReadFile(rootConfig.TLS.CACert)
if err != nil {
log.Fatal("could not read server certification file : ", err)
}
@@ -160,7 +158,7 @@ func connectAergo(cmd *cobra.Command, args []string) {
opts = append(opts, grpc.WithInsecure())
}
var ok bool
- client, ok = util.GetClient(serverAddr, opts).(*util.ConnClient)
+ client, ok = GetClient(serverAddr, opts).(*ConnClient)
if !ok {
log.Fatal("internal error. wrong RPC client type")
}
diff --git a/cmd/aergocli/cmd/root_test.go b/cmd/aergocli/cmd/root_test.go
index 1e4af6798..a372794d1 100644
--- a/cmd/aergocli/cmd/root_test.go
+++ b/cmd/aergocli/cmd/root_test.go
@@ -5,7 +5,6 @@ import (
"testing"
"github.com/aergoio/aergo/v2/cmd/aergocli/cmd/mock_types"
- "github.com/aergoio/aergo/v2/cmd/aergocli/util"
"github.com/golang/mock/gomock"
"github.com/spf13/cobra"
)
@@ -14,7 +13,7 @@ func initMock(t *testing.T) *mock_types.MockAergoRPCServiceClient {
test = true
ctrl := gomock.NewController(t)
mock := mock_types.NewMockAergoRPCServiceClient(ctrl)
- mockClient := &util.ConnClient{
+ mockClient := &ConnClient{
AergoRPCServiceClient: mock,
}
client = mockClient
diff --git a/cmd/aergocli/cmd/sendtx.go b/cmd/aergocli/cmd/sendtx.go
index 0b01d7df6..44fbfcaff 100644
--- a/cmd/aergocli/cmd/sendtx.go
+++ b/cmd/aergocli/cmd/sendtx.go
@@ -9,9 +9,9 @@ import (
"context"
"errors"
- "github.com/aergoio/aergo/v2/cmd/aergocli/util"
"github.com/aergoio/aergo/v2/internal/enc/base58"
"github.com/aergoio/aergo/v2/types"
+ "github.com/aergoio/aergo/v2/types/jsonrpc"
"github.com/spf13/cobra"
)
@@ -46,7 +46,7 @@ func execSendTX(cmd *cobra.Command, args []string) error {
if err != nil {
return errors.New("Wrong address in --to flag\n" + err.Error())
}
- amountBigInt, err := util.ParseUnit(amount)
+ amountBigInt, err := jsonrpc.ParseUnit(amount)
if err != nil {
return errors.New("Wrong value in --amount flag\n" + err.Error())
}
@@ -100,12 +100,14 @@ func sendTX(cmd *cobra.Command, tx *types.Tx, account []byte) string {
if err != nil {
return "Failed request to aergo server: " + err.Error()
}
- return util.JSON(msgs.Results[0])
+ res := jsonrpc.ConvCommitResult(msgs.Results[0])
+ return jsonrpc.MarshalJSON(res)
} else {
msg, err := client.SendTX(context.Background(), tx)
if err != nil {
return "Failed request to aergo sever: " + err.Error()
}
- return util.JSON(msg)
+ res := jsonrpc.ConvCommitResult(msg)
+ return jsonrpc.MarshalJSON(res)
}
}
diff --git a/cmd/aergocli/cmd/sendtx_test.go b/cmd/aergocli/cmd/sendtx_test.go
index cec44f02e..c5ef7574c 100644
--- a/cmd/aergocli/cmd/sendtx_test.go
+++ b/cmd/aergocli/cmd/sendtx_test.go
@@ -1,11 +1,12 @@
package cmd
import (
+ "encoding/json"
"testing"
- "github.com/aergoio/aergo/v2/cmd/aergocli/util/encoding/json"
"github.com/aergoio/aergo/v2/internal/enc/base58"
"github.com/aergoio/aergo/v2/types"
+ "github.com/aergoio/aergo/v2/types/jsonrpc"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert"
)
@@ -32,9 +33,9 @@ func TestSendTxWithMock(t *testing.T) {
output, err := executeCommand(rootCmd, "sendtx", "--from", "AmNL5neKQS2ZwRuBeqfcfHMLg3aSmGoefEh5bW8ozWxrtmxaGHZ3", "--to", "AmNfacq5A3orqn3MhgkHSncufXEP8gVJgqDy8jTgBphXQeuuaHHF", "--amount", "1000", "--keystore", "")
assert.NoError(t, err, "should no error")
t.Log(output)
- out := &types.CommitResult{}
+ out := &jsonrpc.InOutCommitResult{}
err = json.Unmarshal([]byte(output), out)
- assert.Equal(t, testTxHashString, base58.Encode(out.Hash))
+ assert.Equal(t, testTxHashString, out.Hash)
}
func TestSendTxFromToValidation(t *testing.T) {
diff --git a/cmd/aergocli/cmd/signtx.go b/cmd/aergocli/cmd/signtx.go
index 748784ff1..86b90bfc8 100644
--- a/cmd/aergocli/cmd/signtx.go
+++ b/cmd/aergocli/cmd/signtx.go
@@ -7,9 +7,9 @@ import (
"github.com/aergoio/aergo/v2/account/key"
crypto "github.com/aergoio/aergo/v2/account/key/crypto"
- "github.com/aergoio/aergo/v2/cmd/aergocli/util"
"github.com/aergoio/aergo/v2/internal/enc/base58"
"github.com/aergoio/aergo/v2/types"
+ "github.com/aergoio/aergo/v2/types/jsonrpc"
"github.com/btcsuite/btcd/btcec"
"github.com/spf13/cobra"
)
@@ -36,7 +36,7 @@ var signCmd = &cobra.Command{
cmd.Printf("need to transaction json input")
return
}
- param, err := util.ParseBase58TxBody([]byte(jsonTx))
+ param, err := jsonrpc.ParseBase58TxBody([]byte(jsonTx))
if err != nil {
cmd.Printf("Failed: %s\n", err.Error())
return
@@ -89,7 +89,8 @@ var signCmd = &cobra.Command{
}
if nil == err && msg != nil {
- cmd.Println(util.TxConvBase58Addr(msg))
+ res := jsonrpc.ConvTx(msg, jsonrpc.Base58)
+ cmd.Println(jsonrpc.MarshalJSON(res))
} else {
cmd.Printf("Failed: %s\n", err.Error())
}
@@ -105,7 +106,7 @@ var verifyCmd = &cobra.Command{
cmd.Printf("need to transaction json input")
return
}
- param, err := util.ParseBase58Tx([]byte(jsonTx))
+ param, err := jsonrpc.ParseBase58Tx([]byte(jsonTx))
if err != nil {
cmd.Printf("Failed: %s\n", err.Error())
return
@@ -117,7 +118,8 @@ var verifyCmd = &cobra.Command{
return
}
if msg.Tx != nil {
- cmd.Println(util.TxConvBase58Addr(msg.Tx))
+ res := jsonrpc.ConvTx(msg.Tx, jsonrpc.Base58)
+ cmd.Println(jsonrpc.MarshalJSON(res))
} else {
cmd.Println(msg.Error)
}
@@ -127,7 +129,8 @@ var verifyCmd = &cobra.Command{
cmd.Printf("Failed: %s\n", err.Error())
return
}
- cmd.Println(util.TxConvBase58Addr(param[0]))
+ res := jsonrpc.ConvTx(param[0], jsonrpc.Base58)
+ cmd.Println(jsonrpc.MarshalJSON(res))
}
},
}
diff --git a/cmd/aergocli/cmd/signtx_test.go b/cmd/aergocli/cmd/signtx_test.go
index 972aca344..109a9af38 100644
--- a/cmd/aergocli/cmd/signtx_test.go
+++ b/cmd/aergocli/cmd/signtx_test.go
@@ -1,15 +1,15 @@
package cmd
import (
+ "encoding/json"
"os"
"regexp"
"strings"
"testing"
- "github.com/aergoio/aergo/v2/cmd/aergocli/util"
- "github.com/aergoio/aergo/v2/cmd/aergocli/util/encoding/json"
"github.com/aergoio/aergo/v2/internal/enc/base58"
"github.com/aergoio/aergo/v2/types"
+ "github.com/aergoio/aergo/v2/types/jsonrpc"
"github.com/stretchr/testify/assert"
)
@@ -26,7 +26,7 @@ func TestSignWithKey(t *testing.T) {
assert.Equalf(t, types.AddressLength, len(addr), "wrong address length value = %s", output)
ouputjson := strings.Join(outputline[1:], "")
- var tx util.InOutTx
+ var tx jsonrpc.InOutTx
err = json.Unmarshal([]byte(ouputjson), &tx)
assert.NoError(t, err, "should be success")
diff --git a/cmd/aergocli/cmd/stake.go b/cmd/aergocli/cmd/stake.go
index b4bc18038..0f843ef0a 100644
--- a/cmd/aergocli/cmd/stake.go
+++ b/cmd/aergocli/cmd/stake.go
@@ -9,8 +9,8 @@ import (
"encoding/json"
"errors"
- "github.com/aergoio/aergo/v2/cmd/aergocli/util"
"github.com/aergoio/aergo/v2/types"
+ "github.com/aergoio/aergo/v2/types/jsonrpc"
"github.com/spf13/cobra"
)
@@ -47,7 +47,7 @@ func sendStake(cmd *cobra.Command, s bool) error {
} else {
ci.Name = types.Opunstake.Cmd()
}
- amountBigInt, err := util.ParseUnit(amount)
+ amountBigInt, err := jsonrpc.ParseUnit(amount)
if err != nil {
return errors.New("Failed to parse --amount flag\n" + err.Error())
}
diff --git a/cmd/aergocli/cmd/vote.go b/cmd/aergocli/cmd/vote.go
index 122c35441..09957d7c7 100644
--- a/cmd/aergocli/cmd/vote.go
+++ b/cmd/aergocli/cmd/vote.go
@@ -12,9 +12,9 @@ import (
"os"
"strings"
- "github.com/aergoio/aergo/v2/cmd/aergocli/util"
"github.com/aergoio/aergo/v2/internal/enc/base58"
"github.com/aergoio/aergo/v2/types"
+ "github.com/aergoio/aergo/v2/types/jsonrpc"
"github.com/spf13/cobra"
)
@@ -136,7 +136,8 @@ func execVoteStat(cmd *cobra.Command, args []string) {
cmd.Printf("Failed: %s\n", err.Error())
return
}
- cmd.Println(util.JSON(msg))
+ res := jsonrpc.ConvInOutAccountVoteInfo(msg)
+ cmd.Println(jsonrpc.MarshalJSON(res))
return
} else if fflags.Changed("id") == true {
msg, err := client.GetVotes(context.Background(), &types.VoteParams{
diff --git a/cmd/aergocli/util/base58addr.go b/cmd/aergocli/util/base58addr.go
deleted file mode 100644
index c744d6591..000000000
--- a/cmd/aergocli/util/base58addr.go
+++ /dev/null
@@ -1,354 +0,0 @@
-package util
-
-import (
- "encoding/json"
- "errors"
- "fmt"
- "math/big"
- "strconv"
- "time"
-
- "github.com/aergoio/aergo/v2/internal/enc/base58"
- "github.com/aergoio/aergo/v2/p2p/p2putil"
- "github.com/aergoio/aergo/v2/types"
-)
-
-type InOutBlockHeader struct {
- ChainID string
- Version int32
- PrevBlockHash string
- BlockNo uint64
- Timestamp int64
- BlockRootHash string
- TxRootHash string
- ReceiptsRootHash string
- Confirms uint64
- PubKey string
- Sign string
- CoinbaseAccount string
- Consensus string
-}
-
-type InOutBlockBody struct {
- Txs []*InOutTx
-}
-
-type InOutBlock struct {
- Hash string
- Header InOutBlockHeader
- Body InOutBlockBody
-}
-
-type InOutBlockIdx struct {
- BlockHash string
- BlockNo uint64
-}
-
-type InOutPeerAddress struct {
- Address string
- Port string
- PeerId string
-}
-
-type InOutPeer struct {
- Role string
- Address InOutPeerAddress
- BestBlock InOutBlockIdx
- LastCheck time.Time
- State string
- Hidden bool
- Self bool
- Version string
-}
-
-type LongInOutPeer struct {
- InOutPeer
- ProducerIDs []string
- Certificates []*InOutCert
-}
-
-type InOutCert struct {
- CertVersion uint32
- ProducerID string
- CreateTime time.Time
- ExpireTime time.Time
- AgentID string
- Addresses []string
-}
-
-func FillTxBody(source *InOutTxBody, target *types.TxBody) error {
- var err error
- if source == nil {
- return errors.New("tx body is empty")
- }
- target.Nonce = source.Nonce
- if source.Account != "" {
- target.Account, err = types.DecodeAddress(source.Account)
- if err != nil {
- return err
- }
- }
- if source.Recipient != "" {
- target.Recipient, err = types.DecodeAddress(source.Recipient)
- if err != nil {
- return err
- }
- }
- if source.Amount != "" {
- amount, err := ParseUnit(source.Amount)
- if err != nil {
- return err
- }
- target.Amount = amount.Bytes()
- }
- if source.Payload != "" {
- target.Payload, err = base58.Decode(source.Payload)
- if err != nil {
- return err
- }
- }
- target.GasLimit = source.GasLimit
- if source.GasPrice != "" {
- price, err := ParseUnit(source.GasPrice)
- if err != nil {
- return err
- }
- target.GasPrice = price.Bytes()
- }
- if source.ChainIdHash != "" {
- target.ChainIdHash, err = base58.Decode(source.ChainIdHash)
- if err != nil {
- return err
- }
- }
- if source.Sign != "" {
- target.Sign, err = base58.Decode(source.Sign)
- if err != nil {
- return err
- }
- }
- target.Type = source.Type
- return nil
-}
-
-func ParseBase58Tx(jsonTx []byte) ([]*types.Tx, error) {
- var inputlist []InOutTx
- err := json.Unmarshal([]byte(jsonTx), &inputlist)
- if err != nil {
- var input InOutTx
- err = json.Unmarshal([]byte(jsonTx), &input)
- if err != nil {
- return nil, err
- }
- inputlist = append(inputlist, input)
- }
- txs := make([]*types.Tx, len(inputlist))
- for i, in := range inputlist {
- tx := &types.Tx{Body: &types.TxBody{}}
- if in.Hash != "" {
- tx.Hash, err = base58.Decode(in.Hash)
- if err != nil {
- return nil, err
- }
- }
- err = FillTxBody(in.Body, tx.Body)
- if err != nil {
- return nil, err
- }
- txs[i] = tx
- }
-
- return txs, nil
-}
-
-func ParseBase58TxBody(jsonTx []byte) (*types.TxBody, error) {
- body := &types.TxBody{}
- in := &InOutTxBody{}
-
- err := json.Unmarshal(jsonTx, in)
- if err != nil {
- return nil, err
- }
-
- err = FillTxBody(in, body)
- if err != nil {
- return nil, err
- }
-
- return body, nil
-}
-
-func ConvTxEx(tx *types.Tx, payloadType EncodingType) *InOutTx {
- out := &InOutTx{Body: &InOutTxBody{}}
- if tx == nil {
- return out
- }
- out.Hash = base58.Encode(tx.Hash)
- out.Body.Nonce = tx.Body.Nonce
- if tx.Body.Account != nil {
- out.Body.Account = types.EncodeAddress(tx.Body.Account)
- }
- if tx.Body.Recipient != nil {
- out.Body.Recipient = types.EncodeAddress(tx.Body.Recipient)
- }
- if tx.Body.Amount != nil {
- out.Body.Amount = new(big.Int).SetBytes(tx.Body.Amount).String()
- }
- switch payloadType {
- case Raw:
- out.Body.Payload = string(tx.Body.Payload)
- case Base58:
- out.Body.Payload = base58.Encode(tx.Body.Payload)
- }
- out.Body.GasLimit = tx.Body.GasLimit
- if tx.Body.GasPrice != nil {
- out.Body.GasPrice = new(big.Int).SetBytes(tx.Body.GasPrice).String()
- }
- out.Body.ChainIdHash = base58.Encode(tx.Body.ChainIdHash)
- out.Body.Sign = base58.Encode(tx.Body.Sign)
- out.Body.Type = tx.Body.Type
- return out
-}
-
-func ConvTxInBlockEx(txInBlock *types.TxInBlock, payloadType EncodingType) *InOutTxInBlock {
- out := &InOutTxInBlock{TxIdx: &InOutTxIdx{}, Tx: &InOutTx{}}
- out.TxIdx.BlockHash = base58.Encode(txInBlock.GetTxIdx().GetBlockHash())
- out.TxIdx.Idx = txInBlock.GetTxIdx().GetIdx()
- out.Tx = ConvTxEx(txInBlock.GetTx(), payloadType)
- return out
-}
-
-func ConvBlock(b *types.Block) *InOutBlock {
- out := &InOutBlock{}
- if b != nil {
- out.Hash = base58.Encode(b.Hash)
- out.Header.ChainID = base58.Encode(b.GetHeader().GetChainID())
- out.Header.Version = types.DecodeChainIdVersion(b.GetHeader().GetChainID())
- out.Header.PrevBlockHash = base58.Encode(b.GetHeader().GetPrevBlockHash())
- out.Header.BlockNo = b.GetHeader().GetBlockNo()
- out.Header.Timestamp = b.GetHeader().GetTimestamp()
- out.Header.BlockRootHash = base58.Encode(b.GetHeader().GetBlocksRootHash())
- out.Header.TxRootHash = base58.Encode(b.GetHeader().GetTxsRootHash())
- out.Header.ReceiptsRootHash = base58.Encode(b.GetHeader().GetReceiptsRootHash())
- out.Header.Confirms = b.GetHeader().GetConfirms()
- out.Header.PubKey = base58.Encode(b.GetHeader().GetPubKey())
- out.Header.Sign = base58.Encode(b.GetHeader().GetSign())
- if b.GetHeader().GetCoinbaseAccount() != nil {
- out.Header.CoinbaseAccount = types.EncodeAddress(b.GetHeader().GetCoinbaseAccount())
- }
- if consensus := b.GetHeader().GetConsensus(); consensus != nil {
- out.Header.Consensus = types.EncodeAddress(consensus)
- }
-
- if b.Body != nil {
- for _, tx := range b.Body.Txs {
- out.Body.Txs = append(out.Body.Txs, ConvTx(tx))
- }
- }
- }
- return out
-}
-
-func ConvPeer(p *types.Peer) *InOutPeer {
- out := &InOutPeer{}
- out.Role = p.AcceptedRole.String()
- out.Address.Address = p.GetAddress().GetAddress()
- out.Address.Port = strconv.Itoa(int(p.GetAddress().GetPort()))
- out.Address.PeerId = base58.Encode(p.GetAddress().GetPeerID())
- out.LastCheck = time.Unix(0, p.GetLashCheck())
- out.BestBlock.BlockNo = p.GetBestblock().GetBlockNo()
- out.BestBlock.BlockHash = base58.Encode(p.GetBestblock().GetBlockHash())
- out.State = types.PeerState(p.State).String()
- out.Hidden = p.Hidden
- out.Self = p.Selfpeer
- if p.Version != "" {
- out.Version = p.Version
- } else {
- out.Version = "(old)"
- }
- return out
-}
-
-func ConvPeerLong(p *types.Peer) *LongInOutPeer {
- out := &LongInOutPeer{InOutPeer: *ConvPeer(p)}
- out.ProducerIDs = make([]string, len(p.Address.ProducerIDs))
- for i, pid := range p.Address.ProducerIDs {
- out.ProducerIDs[i] = base58.Encode(pid)
- }
- if p.Address.Role == types.PeerRole_Agent {
- out.Certificates = make([]*InOutCert, len(p.Certificates))
- for i, cert := range p.Certificates {
- addrs := []string{}
- for _, ad := range cert.AgentAddress {
- addrs = append(addrs, string(ad))
- }
- out.Certificates[i] = &InOutCert{CertVersion: cert.CertVersion,
- ProducerID: base58.Encode(cert.BPID), AgentID: base58.Encode(cert.AgentID),
- CreateTime: time.Unix(0, cert.CreateTime), ExpireTime: time.Unix(0, cert.ExpireTime),
- Addresses: addrs}
- }
- }
- return out
-}
-
-func ConvBlockchainStatus(in *types.BlockchainStatus) string {
- out := &InOutBlockchainStatus{}
- if in == nil {
- return ""
- }
- out.Hash = base58.Encode(in.BestBlockHash)
- out.Height = in.BestHeight
-
- out.ChainIdHash = base58.Encode(in.BestChainIdHash)
-
- toJRM := func(s string) *json.RawMessage {
- if len(s) > 0 {
- m := json.RawMessage(s)
- return &m
- }
- return nil
- }
- out.ConsensusInfo = toJRM(in.ConsensusInfo)
- if in.ChainInfo != nil {
- out.ChainInfo = convChainInfo(in.ChainInfo)
- }
- jsonout, err := json.Marshal(out)
- if err != nil {
- return ""
- }
- return string(jsonout)
-}
-
-func BlockConvBase58Addr(b *types.Block) string {
- return toString(ConvBlock(b))
-}
-
-func PeerListToString(p *types.PeerList) string {
- peers := []*InOutPeer{}
- for _, peer := range p.GetPeers() {
- peers = append(peers, ConvPeer(peer))
- }
- return toString(peers)
-}
-func ShortPeerListToString(p *types.PeerList) string {
- var peers []string
- for _, peer := range p.GetPeers() {
- pa := peer.Address
- peers = append(peers, fmt.Sprintf("%s;%s/%d;%s;%d", p2putil.ShortForm(types.PeerID(pa.PeerID)), pa.Address, pa.Port, peer.AcceptedRole.String(), peer.Bestblock.BlockNo))
- }
- return toString(peers)
-}
-func LongPeerListToString(p *types.PeerList) string {
- peers := []*LongInOutPeer{}
- for _, peer := range p.GetPeers() {
- peers = append(peers, ConvPeerLong(peer))
- }
- return toString(peers)
-}
-func toString(out interface{}) string {
- jsonout, err := json.MarshalIndent(out, "", " ")
- if err != nil {
- return ""
- }
- return string(jsonout)
-}
diff --git a/cmd/aergocli/util/base58addr_test.go b/cmd/aergocli/util/base58addr_test.go
deleted file mode 100644
index ec6800c28..000000000
--- a/cmd/aergocli/util/base58addr_test.go
+++ /dev/null
@@ -1,86 +0,0 @@
-package util
-
-import (
- "testing"
-
- "github.com/aergoio/aergo/v2/internal/enc/base58"
- "github.com/aergoio/aergo/v2/types"
- "github.com/stretchr/testify/assert"
-)
-
-func TestParseConvBase58Tx(t *testing.T) {
- testjson := "[{\"Hash\":\"525mQMtsWaDLVJbzQZgTFkSG33gtZsho7m4io1HUCeJi\",\"Body\":{\"Nonce\":9,\"Account\":\"AsiFCzSukVNUGufJSzSNLA1nKx39NxKcVBEWvW3riyfixcBjN1Qd\",\"Recipient\":\"AsjHhFbCuULoUVZPiNNV6WEemtEi7Eiy6G4TDaUsMDiedCARbhQR\",\"Amount\":\"100000000\",\"Payload\":null,\"Limit\":100,\"Price\":\"1\",\"Type\":0,\"Sign\":\"3tMHYrizQ532D1WJkt5RSs5AcRmq7betw8zvC66Wh3XHUdvNpNzLWh1SkkGYMGJ669nCVuYHrhwfg1HrUUp6KDwzK\"}}]"
- res, err := ParseBase58Tx([]byte(testjson))
- assert.NoError(t, err, "should be success")
- assert.NotEmpty(t, res, "failed to parse json")
- assert.Equal(t, "525mQMtsWaDLVJbzQZgTFkSG33gtZsho7m4io1HUCeJi", base58.Encode(res[0].Hash), "wrong hash")
- assert.Equal(t, "3tMHYrizQ532D1WJkt5RSs5AcRmq7betw8zvC66Wh3XHUdvNpNzLWh1SkkGYMGJ669nCVuYHrhwfg1HrUUp6KDwzK", base58.Encode(res[0].Body.Sign), "wrong sign")
-
- account, err := types.DecodeAddress("AsiFCzSukVNUGufJSzSNLA1nKx39NxKcVBEWvW3riyfixcBjN1Qd")
- assert.NoError(t, err, "should be success")
- assert.Equal(t, account, res[0].Body.Account, "wrong account")
-
- recipient, err := types.DecodeAddress("AsjHhFbCuULoUVZPiNNV6WEemtEi7Eiy6G4TDaUsMDiedCARbhQR")
- assert.NoError(t, err, "should be success")
- assert.Equal(t, recipient, res[0].Body.Recipient, "wrong recipient")
-}
-
-func TestParseBase58TxBody(t *testing.T) {
- testjson := "{\"Nonce\":1,\"Account\":\"AsiFCzSukVNUGufJSzSNLA1nKx39NxKcVBEWvW3riyfixcBjN1Qd\",\"Recipient\":\"AsjHhFbCuULoUVZPiNNV6WEemtEi7Eiy6G4TDaUsMDiedCARbhQR\",\"Amount\":\"25000\",\"Payload\":\"aergo\",\"Limit\":100,\"Price\":\"1\",\"Type\":0,\"Sign\":\"3roWPzztf5aLLh16vAnd2ugcPux3wJ1oqqvqkWARobjuAC32xftF42nnbTkXUQdkDaFvuUmctrpQSv8FAVUKcywHW\"}"
- res, err := ParseBase58TxBody([]byte(testjson))
- assert.NoError(t, err, "should be success")
- assert.NotEmpty(t, res, "failed to parse json")
-
- assert.Equal(t, "3roWPzztf5aLLh16vAnd2ugcPux3wJ1oqqvqkWARobjuAC32xftF42nnbTkXUQdkDaFvuUmctrpQSv8FAVUKcywHW", base58.Encode(res.Sign), "wrong sign")
- assert.Equal(t, "aergo", base58.Encode(res.Payload), "wrong payload")
- account, err := types.DecodeAddress("AsiFCzSukVNUGufJSzSNLA1nKx39NxKcVBEWvW3riyfixcBjN1Qd")
- assert.NoError(t, err, "should be success")
- assert.Equal(t, account, res.Account, "wrong account")
-
- recipient, err := types.DecodeAddress("AsjHhFbCuULoUVZPiNNV6WEemtEi7Eiy6G4TDaUsMDiedCARbhQR")
- assert.NoError(t, err, "should be success")
- assert.Equal(t, recipient, res.Recipient, "wrong recipient")
-}
-
-func TestBlockConvBase58(t *testing.T) {
- const accountBase58 = "AmMW2bVcfroiuV4Bvy56op5zzqn42xgrLCwSxMka23K75yTBmudz"
- const recipientBase58 = "AmMW2bVcfroiuV4Bvy56op5zzqn42xgrLCwSxMka23K75yTBmudz"
- const payloadBase58 = "525mQMtsWaDLVJbzQZgTFkSG33gtZsho7m4io1HUCeJi"
-
- account, err := types.DecodeAddress(accountBase58)
- assert.NoError(t, err, "should be decode account")
-
- testBlock := &types.Block{
- Header: &types.BlockHeader{
- CoinbaseAccount: account,
- },
- Body: &types.BlockBody{
- Txs: []*types.Tx{},
- },
- }
- result := ConvBlock(nil)
- assert.Empty(t, result, "failed to convert nil")
-
- result = ConvBlock(testBlock)
- assert.Empty(t, result.Body.Txs, "failed to convert txs")
- assert.Equal(t, accountBase58, result.Header.CoinbaseAccount, "failed to convert coinbase account")
-
- recipient, err := types.DecodeAddress(recipientBase58)
- assert.NoError(t, err, "should be decode recipient")
-
- payload, err := base58.Decode(payloadBase58)
- assert.NoError(t, err, "should be decode payload")
-
- testTx := &types.Tx{Body: &types.TxBody{
- Account: account,
- Recipient: recipient,
- Payload: payload,
- }}
-
- testBlock.Body.Txs = append(testBlock.Body.Txs, testTx)
- result = ConvBlock(testBlock)
- assert.Equal(t, accountBase58, result.Body.Txs[0].Body.Account, "failed to convert account")
- assert.Equal(t, recipientBase58, result.Body.Txs[0].Body.Recipient, "failed to convert recipient")
- assert.Equal(t, payloadBase58, result.Body.Txs[0].Body.Payload, "failed to convert payload")
- t.Log(BlockConvBase58Addr(testBlock))
-}
diff --git a/cmd/aergocli/util/base64ToHex.go b/cmd/aergocli/util/base64ToHex.go
deleted file mode 100644
index 6ce5d33aa..000000000
--- a/cmd/aergocli/util/base64ToHex.go
+++ /dev/null
@@ -1,29 +0,0 @@
-package util
-
-import (
- "encoding/json"
-
- "github.com/aergoio/aergo/v2/internal/enc/hex"
- "github.com/aergoio/aergo/v2/types"
-)
-
-type InOutBlockchainStatus struct {
- Hash string
- Height uint64
- ConsensusInfo *json.RawMessage `json:",omitempty"`
- ChainIdHash string
- ChainStat *json.RawMessage `json:",omitempty"`
- ChainInfo *InOutChainInfo `json:",omitempty"`
-}
-
-func ConvHexBlockchainStatus(in *types.BlockchainStatus) string {
- out := &InOutBlockchainStatus{}
- out.Hash = hex.Encode(in.BestBlockHash)
- out.Height = in.BestHeight
- out.ChainIdHash = hex.Encode(in.BestChainIdHash)
- jsonout, err := json.Marshal(out)
- if err != nil {
- return ""
- }
- return string(jsonout)
-}
diff --git a/cmd/aergocli/util/convChaininfo.go b/cmd/aergocli/util/convChaininfo.go
deleted file mode 100644
index 0efa70662..000000000
--- a/cmd/aergocli/util/convChaininfo.go
+++ /dev/null
@@ -1,61 +0,0 @@
-package util
-
-import (
- "encoding/json"
- "math/big"
-
- "github.com/aergoio/aergo/v2/consensus"
- "github.com/aergoio/aergo/v2/types"
-)
-
-type InOutChainId struct {
- Magic string
- Public bool
- Mainnet bool
- Consensus string
- Version int32
-}
-
-type InOutChainInfo struct {
- Chainid InOutChainId
- BpNumber uint32
- MaxBlockSize uint64
- MaxTokens string
- StakingMinimum string `json:",omitempty"`
- StakingTotal string `json:",omitempty"`
- GasPrice string `json:",omitempty"`
- NamePrice string `json:",omitempty"`
- TotalVotingPower string `json:",omitempty"`
- VotingReward string `json:",omitempty"`
-}
-
-func ConvChainInfoMsg(msg *types.ChainInfo) string {
- jsonout, err := json.MarshalIndent(convChainInfo(msg), "", " ")
- if err != nil {
- return ""
- }
- return string(jsonout)
-}
-
-func convChainInfo(msg *types.ChainInfo) *InOutChainInfo {
- out := &InOutChainInfo{}
- out.Chainid.Magic = msg.Id.Magic
- out.Chainid.Public = msg.Id.Public
- out.Chainid.Mainnet = msg.Id.Mainnet
- out.Chainid.Consensus = msg.Id.Consensus
- out.Chainid.Version = msg.Id.Version
- out.BpNumber = msg.BpNumber
- out.MaxBlockSize = msg.Maxblocksize
- out.MaxTokens = new(big.Int).SetBytes(msg.Maxtokens).String()
-
- if consensus.IsDposName(msg.Id.Consensus) {
- out.StakingMinimum = new(big.Int).SetBytes(msg.Stakingminimum).String()
- out.StakingTotal = new(big.Int).SetBytes(msg.Totalstaking).String()
- }
-
- out.GasPrice = new(big.Int).SetBytes(msg.Gasprice).String()
- out.NamePrice = new(big.Int).SetBytes(msg.Nameprice).String()
- out.TotalVotingPower = new(big.Int).SetBytes(msg.Totalvotingpower).String()
- out.VotingReward = new(big.Int).SetBytes(msg.Votingreward).String()
- return out
-}
diff --git a/cmd/aergocli/util/convTx.go b/cmd/aergocli/util/convTx.go
deleted file mode 100644
index a3392d258..000000000
--- a/cmd/aergocli/util/convTx.go
+++ /dev/null
@@ -1,76 +0,0 @@
-package util
-
-import "github.com/aergoio/aergo/v2/types"
-
-type EncodingType int
-
-const (
- Raw EncodingType = 0 + iota
- Base58
-)
-
-type InOutTx struct {
- Hash string `json:",omitempty"`
- Body *InOutTxBody `json:",omitempty"`
-}
-
-type InOutTxBody struct {
- Nonce uint64 `json:",omitempty"`
- Account string `json:",omitempty"`
- Recipient string `json:",omitempty"`
- Amount string `json:",omitempty"`
- Payload string `json:",omitempty"`
- GasLimit uint64 `json:",omitempty"`
- GasPrice string `json:",omitempty"`
- Type types.TxType `json:",omitempty"`
- ChainIdHash string `json:",omitempty"`
- Sign string `json:",omitempty"`
-}
-
-type InOutTxIdx struct {
- BlockHash string
- Idx int32
-}
-
-type InOutTxInBlock struct {
- TxIdx *InOutTxIdx
- Tx *InOutTx
-}
-
-func (b *InOutTxBody) String() string {
- return toString(b)
-}
-
-func (t *InOutTx) String() string {
- return toString(t)
-}
-
-func (t *InOutTxInBlock) String() string {
- return toString(t)
-}
-
-func TxConvBase58Addr(tx *types.Tx) string {
- return toString(ConvTx(tx))
-}
-
-func TxConvBase58AddrEx(tx *types.Tx, payloadType EncodingType) string {
- switch payloadType {
- case Raw:
- return toString(ConvTxEx(tx, Raw))
- case Base58:
- return toString(ConvTxEx(tx, Base58))
- }
- return ""
-}
-
-func TxInBlockConvBase58Addr(txInBlock *types.TxInBlock) string {
- return toString(ConvTxInBlock(txInBlock))
-}
-
-func ConvTx(tx *types.Tx) *InOutTx {
- return ConvTxEx(tx, Base58)
-}
-
-func ConvTxInBlock(txInBlock *types.TxInBlock) *InOutTxInBlock {
- return ConvTxInBlockEx(txInBlock, Base58)
-}
diff --git a/cmd/aergocli/util/convTx_test.go b/cmd/aergocli/util/convTx_test.go
deleted file mode 100644
index 536c9950c..000000000
--- a/cmd/aergocli/util/convTx_test.go
+++ /dev/null
@@ -1,16 +0,0 @@
-package util
-
-import (
- "testing"
-
- "github.com/aergoio/aergo/v2/types"
- "github.com/stretchr/testify/assert"
-)
-
-func TestConvTxEx(t *testing.T) {
- testTx := &types.Tx{Body: &types.TxBody{Payload: []byte("{\"Name\":\"v1createName\",\"Args\":[\"honggildong3\"]}")}}
- result := toString(ConvTxEx(testTx, Base58))
- assert.Equal(t, "{\n \"Body\": {\n \"Payload\": \"22MZAFWvxtVWehpgwEVxrvoqGL5xmcPmyLBiwraDfxRwKUNrV9tmhuB7Uu6ZeJWvp\"\n }\n}", result, "")
- result = toString(ConvTxEx(testTx, Raw))
- assert.Equal(t, "{\n \"Body\": {\n \"Payload\": \"{\\\"Name\\\":\\\"v1createName\\\",\\\"Args\\\":[\\\"honggildong3\\\"]}\"\n }\n}", result, "")
-}
diff --git a/cmd/aergocli/util/encoding/encoding.go b/cmd/aergocli/util/encoding/encoding.go
deleted file mode 100644
index cc5a53699..000000000
--- a/cmd/aergocli/util/encoding/encoding.go
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2013 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package encoding defines interfaces shared by other packages that
-// convert data to and from byte-level and textual representations.
-// Packages that check for these interfaces include encoding/gob,
-// encoding/json, and encoding/xml. As a result, implementing an
-// interface once can make a type useful in multiple encodings.
-// Standard types that implement these interfaces include time.Time and net.IP.
-// The interfaces come in pairs that produce and consume encoded data.
-package encoding
-
-// BinaryMarshaler is the interface implemented by an object that can
-// marshal itself into a binary form.
-//
-// MarshalBinary encodes the receiver into a binary form and returns the result.
-type BinaryMarshaler interface {
- MarshalBinary() (data []byte, err error)
-}
-
-// BinaryUnmarshaler is the interface implemented by an object that can
-// unmarshal a binary representation of itself.
-//
-// UnmarshalBinary must be able to decode the form generated by MarshalBinary.
-// UnmarshalBinary must copy the data if it wishes to retain the data
-// after returning.
-type BinaryUnmarshaler interface {
- UnmarshalBinary(data []byte) error
-}
-
-// TextMarshaler is the interface implemented by an object that can
-// marshal itself into a textual form.
-//
-// MarshalText encodes the receiver into UTF-8-encoded text and returns the result.
-type TextMarshaler interface {
- MarshalText() (text []byte, err error)
-}
-
-// TextUnmarshaler is the interface implemented by an object that can
-// unmarshal a textual representation of itself.
-//
-// UnmarshalText must be able to decode the form generated by MarshalText.
-// UnmarshalText must copy the text if it wishes to retain the text
-// after returning.
-type TextUnmarshaler interface {
- UnmarshalText(text []byte) error
-}
diff --git a/cmd/aergocli/util/encoding/json/decode.go b/cmd/aergocli/util/encoding/json/decode.go
deleted file mode 100644
index a6dd2b0d8..000000000
--- a/cmd/aergocli/util/encoding/json/decode.go
+++ /dev/null
@@ -1,1289 +0,0 @@
-// Copyright 2010 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Represents JSON data structure using native Go types: booleans, floats,
-// strings, arrays, and maps.
-
-package json
-
-import (
- "bytes"
- "encoding"
- "fmt"
- "reflect"
- "strconv"
- "unicode"
- "unicode/utf16"
- "unicode/utf8"
-
- "github.com/aergoio/aergo/v2/internal/enc/base58"
-)
-
-// Unmarshal parses the JSON-encoded data and stores the result
-// in the value pointed to by v. If v is nil or not a pointer,
-// Unmarshal returns an InvalidUnmarshalError.
-//
-// Unmarshal uses the inverse of the encodings that
-// Marshal uses, allocating maps, slices, and pointers as necessary,
-// with the following additional rules:
-//
-// To unmarshal JSON into a pointer, Unmarshal first handles the case of
-// the JSON being the JSON literal null. In that case, Unmarshal sets
-// the pointer to nil. Otherwise, Unmarshal unmarshals the JSON into
-// the value pointed at by the pointer. If the pointer is nil, Unmarshal
-// allocates a new value for it to point to.
-//
-// To unmarshal JSON into a value implementing the Unmarshaler interface,
-// Unmarshal calls that value's UnmarshalJSON method, including
-// when the input is a JSON null.
-// Otherwise, if the value implements encoding.TextUnmarshaler
-// and the input is a JSON quoted string, Unmarshal calls that value's
-// UnmarshalText method with the unquoted form of the string.
-//
-// To unmarshal JSON into a struct, Unmarshal matches incoming object
-// keys to the keys used by Marshal (either the struct field name or its tag),
-// preferring an exact match but also accepting a case-insensitive match. By
-// default, object keys which don't have a corresponding struct field are
-// ignored (see Decoder.DisallowUnknownFields for an alternative).
-//
-// To unmarshal JSON into an interface value,
-// Unmarshal stores one of these in the interface value:
-//
-// bool, for JSON booleans
-// float64, for JSON numbers
-// string, for JSON strings
-// []interface{}, for JSON arrays
-// map[string]interface{}, for JSON objects
-// nil for JSON null
-//
-// To unmarshal a JSON array into a slice, Unmarshal resets the slice length
-// to zero and then appends each element to the slice.
-// As a special case, to unmarshal an empty JSON array into a slice,
-// Unmarshal replaces the slice with a new empty slice.
-//
-// To unmarshal a JSON array into a Go array, Unmarshal decodes
-// JSON array elements into corresponding Go array elements.
-// If the Go array is smaller than the JSON array,
-// the additional JSON array elements are discarded.
-// If the JSON array is smaller than the Go array,
-// the additional Go array elements are set to zero values.
-//
-// To unmarshal a JSON object into a map, Unmarshal first establishes a map to
-// use. If the map is nil, Unmarshal allocates a new map. Otherwise Unmarshal
-// reuses the existing map, keeping existing entries. Unmarshal then stores
-// key-value pairs from the JSON object into the map. The map's key type must
-// either be a string, an integer, or implement encoding.TextUnmarshaler.
-//
-// If a JSON value is not appropriate for a given target type,
-// or if a JSON number overflows the target type, Unmarshal
-// skips that field and completes the unmarshaling as best it can.
-// If no more serious errors are encountered, Unmarshal returns
-// an UnmarshalTypeError describing the earliest such error. In any
-// case, it's not guaranteed that all the remaining fields following
-// the problematic one will be unmarshaled into the target object.
-//
-// The JSON null value unmarshals into an interface, map, pointer, or slice
-// by setting that Go value to nil. Because null is often used in JSON to mean
-// “not present,” unmarshaling a JSON null into any other Go type has no effect
-// on the value and produces no error.
-//
-// When unmarshaling quoted strings, invalid UTF-8 or
-// invalid UTF-16 surrogate pairs are not treated as an error.
-// Instead, they are replaced by the Unicode replacement
-// character U+FFFD.
-func Unmarshal(data []byte, v interface{}) error {
- // Check for well-formedness.
- // Avoids filling out half a data structure
- // before discovering a JSON syntax error.
- var d decodeState
- err := checkValid(data, &d.scan)
- if err != nil {
- return err
- }
-
- d.init(data)
- return d.unmarshal(v)
-}
-
-// Unmarshaler is the interface implemented by types
-// that can unmarshal a JSON description of themselves.
-// The input can be assumed to be a valid encoding of
-// a JSON value. UnmarshalJSON must copy the JSON data
-// if it wishes to retain the data after returning.
-//
-// By convention, to approximate the behavior of Unmarshal itself,
-// Unmarshalers implement UnmarshalJSON([]byte("null")) as a no-op.
-type Unmarshaler interface {
- UnmarshalJSON([]byte) error
-}
-
-// An UnmarshalTypeError describes a JSON value that was
-// not appropriate for a value of a specific Go type.
-type UnmarshalTypeError struct {
- Value string // description of JSON value - "bool", "array", "number -5"
- Type reflect.Type // type of Go value it could not be assigned to
- Offset int64 // error occurred after reading Offset bytes
- Struct string // name of the struct type containing the field
- Field string // name of the field holding the Go value
-}
-
-func (e *UnmarshalTypeError) Error() string {
- if e.Struct != "" || e.Field != "" {
- return "json: cannot unmarshal " + e.Value + " into Go struct field " + e.Struct + "." + e.Field + " of type " + e.Type.String()
- }
- return "json: cannot unmarshal " + e.Value + " into Go value of type " + e.Type.String()
-}
-
-// An UnmarshalFieldError describes a JSON object key that
-// led to an unexported (and therefore unwritable) struct field.
-//
-// Deprecated: No longer used; kept for compatibility.
-type UnmarshalFieldError struct {
- Key string
- Type reflect.Type
- Field reflect.StructField
-}
-
-func (e *UnmarshalFieldError) Error() string {
- return "json: cannot unmarshal object key " + strconv.Quote(e.Key) + " into unexported field " + e.Field.Name + " of type " + e.Type.String()
-}
-
-// An InvalidUnmarshalError describes an invalid argument passed to Unmarshal.
-// (The argument to Unmarshal must be a non-nil pointer.)
-type InvalidUnmarshalError struct {
- Type reflect.Type
-}
-
-func (e *InvalidUnmarshalError) Error() string {
- if e.Type == nil {
- return "json: Unmarshal(nil)"
- }
-
- if e.Type.Kind() != reflect.Ptr {
- return "json: Unmarshal(non-pointer " + e.Type.String() + ")"
- }
- return "json: Unmarshal(nil " + e.Type.String() + ")"
-}
-
-func (d *decodeState) unmarshal(v interface{}) error {
- rv := reflect.ValueOf(v)
- if rv.Kind() != reflect.Ptr || rv.IsNil() {
- return &InvalidUnmarshalError{reflect.TypeOf(v)}
- }
-
- d.scan.reset()
- d.scanWhile(scanSkipSpace)
- // We decode rv not rv.Elem because the Unmarshaler interface
- // test must be applied at the top level of the value.
- err := d.value(rv)
- if err != nil {
- return d.addErrorContext(err)
- }
- return d.savedError
-}
-
-// A Number represents a JSON number literal.
-type Number string
-
-// String returns the literal text of the number.
-func (n Number) String() string { return string(n) }
-
-// Float64 returns the number as a float64.
-func (n Number) Float64() (float64, error) {
- return strconv.ParseFloat(string(n), 64)
-}
-
-// Int64 returns the number as an int64.
-func (n Number) Int64() (int64, error) {
- return strconv.ParseInt(string(n), 10, 64)
-}
-
-// isValidNumber reports whether s is a valid JSON number literal.
-func isValidNumber(s string) bool {
- // This function implements the JSON numbers grammar.
- // See https://tools.ietf.org/html/rfc7159#section-6
- // and https://json.org/number.gif
-
- if s == "" {
- return false
- }
-
- // Optional -
- if s[0] == '-' {
- s = s[1:]
- if s == "" {
- return false
- }
- }
-
- // Digits
- switch {
- default:
- return false
-
- case s[0] == '0':
- s = s[1:]
-
- case '1' <= s[0] && s[0] <= '9':
- s = s[1:]
- for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
- s = s[1:]
- }
- }
-
- // . followed by 1 or more digits.
- if len(s) >= 2 && s[0] == '.' && '0' <= s[1] && s[1] <= '9' {
- s = s[2:]
- for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
- s = s[1:]
- }
- }
-
- // e or E followed by an optional - or + and
- // 1 or more digits.
- if len(s) >= 2 && (s[0] == 'e' || s[0] == 'E') {
- s = s[1:]
- if s[0] == '+' || s[0] == '-' {
- s = s[1:]
- if s == "" {
- return false
- }
- }
- for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
- s = s[1:]
- }
- }
-
- // Make sure we are at the end.
- return s == ""
-}
-
-// decodeState represents the state while decoding a JSON value.
-type decodeState struct {
- data []byte
- off int // next read offset in data
- opcode int // last read result
- scan scanner
- errorContext struct { // provides context for type errors
- Struct reflect.Type
- Field string
- }
- savedError error
- useNumber bool
- disallowUnknownFields bool
-}
-
-// readIndex returns the position of the last byte read.
-func (d *decodeState) readIndex() int {
- return d.off - 1
-}
-
-// phasePanicMsg is used as a panic message when we end up with something that
-// shouldn't happen. It can indicate a bug in the JSON decoder, or that
-// something is editing the data slice while the decoder executes.
-const phasePanicMsg = "JSON decoder out of sync - data changing underfoot?"
-
-func (d *decodeState) init(data []byte) *decodeState {
- d.data = data
- d.off = 0
- d.savedError = nil
- d.errorContext.Struct = nil
- d.errorContext.Field = ""
- return d
-}
-
-// saveError saves the first err it is called with,
-// for reporting at the end of the unmarshal.
-func (d *decodeState) saveError(err error) {
- if d.savedError == nil {
- d.savedError = d.addErrorContext(err)
- }
-}
-
-// addErrorContext returns a new error enhanced with information from d.errorContext
-func (d *decodeState) addErrorContext(err error) error {
- if d.errorContext.Struct != nil || d.errorContext.Field != "" {
- switch err := err.(type) {
- case *UnmarshalTypeError:
- err.Struct = d.errorContext.Struct.Name()
- err.Field = d.errorContext.Field
- return err
- }
- }
- return err
-}
-
-// skip scans to the end of what was started.
-func (d *decodeState) skip() {
- s, data, i := &d.scan, d.data, d.off
- depth := len(s.parseState)
- for {
- op := s.step(s, data[i])
- i++
- if len(s.parseState) < depth {
- d.off = i
- d.opcode = op
- return
- }
- }
-}
-
-// scanNext processes the byte at d.data[d.off].
-func (d *decodeState) scanNext() {
- if d.off < len(d.data) {
- d.opcode = d.scan.step(&d.scan, d.data[d.off])
- d.off++
- } else {
- d.opcode = d.scan.eof()
- d.off = len(d.data) + 1 // mark processed EOF with len+1
- }
-}
-
-// scanWhile processes bytes in d.data[d.off:] until it
-// receives a scan code not equal to op.
-func (d *decodeState) scanWhile(op int) {
- s, data, i := &d.scan, d.data, d.off
- for i < len(data) {
- newOp := s.step(s, data[i])
- i++
- if newOp != op {
- d.opcode = newOp
- d.off = i
- return
- }
- }
-
- d.off = len(data) + 1 // mark processed EOF with len+1
- d.opcode = d.scan.eof()
-}
-
-// value consumes a JSON value from d.data[d.off-1:], decoding into v, and
-// reads the following byte ahead. If v is invalid, the value is discarded.
-// The first byte of the value has been read already.
-func (d *decodeState) value(v reflect.Value) error {
- switch d.opcode {
- default:
- panic(phasePanicMsg)
-
- case scanBeginArray:
- if v.IsValid() {
- if err := d.array(v); err != nil {
- return err
- }
- } else {
- d.skip()
- }
- d.scanNext()
-
- case scanBeginObject:
- if v.IsValid() {
- if err := d.object(v); err != nil {
- return err
- }
- } else {
- d.skip()
- }
- d.scanNext()
-
- case scanBeginLiteral:
- // All bytes inside literal return scanContinue op code.
- start := d.readIndex()
- d.scanWhile(scanContinue)
-
- if v.IsValid() {
- if err := d.literalStore(d.data[start:d.readIndex()], v, false); err != nil {
- return err
- }
- }
- }
- return nil
-}
-
-type unquotedValue struct{}
-
-// valueQuoted is like value but decodes a
-// quoted string literal or literal null into an interface value.
-// If it finds anything other than a quoted string literal or null,
-// valueQuoted returns unquotedValue{}.
-func (d *decodeState) valueQuoted() interface{} {
- switch d.opcode {
- default:
- panic(phasePanicMsg)
-
- case scanBeginArray, scanBeginObject:
- d.skip()
- d.scanNext()
-
- case scanBeginLiteral:
- v := d.literalInterface()
- switch v.(type) {
- case nil, string:
- return v
- }
- }
- return unquotedValue{}
-}
-
-// indirect walks down v allocating pointers as needed,
-// until it gets to a non-pointer.
-// if it encounters an Unmarshaler, indirect stops and returns that.
-// if decodingNull is true, indirect stops at the last pointer so it can be set to nil.
-func indirect(v reflect.Value, decodingNull bool) (Unmarshaler, encoding.TextUnmarshaler, reflect.Value) {
- // Issue #24153 indicates that it is generally not a guaranteed property
- // that you may round-trip a reflect.Value by calling Value.Addr().Elem()
- // and expect the value to still be settable for values derived from
- // unexported embedded struct fields.
- //
- // The logic below effectively does this when it first addresses the value
- // (to satisfy possible pointer methods) and continues to dereference
- // subsequent pointers as necessary.
- //
- // After the first round-trip, we set v back to the original value to
- // preserve the original RW flags contained in reflect.Value.
- v0 := v
- haveAddr := false
-
- // If v is a named type and is addressable,
- // start with its address, so that if the type has pointer methods,
- // we find them.
- if v.Kind() != reflect.Ptr && v.Type().Name() != "" && v.CanAddr() {
- haveAddr = true
- v = v.Addr()
- }
- for {
- // Load value from interface, but only if the result will be
- // usefully addressable.
- if v.Kind() == reflect.Interface && !v.IsNil() {
- e := v.Elem()
- if e.Kind() == reflect.Ptr && !e.IsNil() && (!decodingNull || e.Elem().Kind() == reflect.Ptr) {
- haveAddr = false
- v = e
- continue
- }
- }
-
- if v.Kind() != reflect.Ptr {
- break
- }
-
- if v.Elem().Kind() != reflect.Ptr && decodingNull && v.CanSet() {
- break
- }
- if v.IsNil() {
- v.Set(reflect.New(v.Type().Elem()))
- }
- if v.Type().NumMethod() > 0 {
- if u, ok := v.Interface().(Unmarshaler); ok {
- return u, nil, reflect.Value{}
- }
- if !decodingNull {
- if u, ok := v.Interface().(encoding.TextUnmarshaler); ok {
- return nil, u, reflect.Value{}
- }
- }
- }
-
- if haveAddr {
- v = v0 // restore original value after round-trip Value.Addr().Elem()
- haveAddr = false
- } else {
- v = v.Elem()
- }
- }
- return nil, nil, v
-}
-
-// array consumes an array from d.data[d.off-1:], decoding into v.
-// The first byte of the array ('[') has been read already.
-func (d *decodeState) array(v reflect.Value) error {
- // Check for unmarshaler.
- u, ut, pv := indirect(v, false)
- if u != nil {
- start := d.readIndex()
- d.skip()
- return u.UnmarshalJSON(d.data[start:d.off])
- }
- if ut != nil {
- d.saveError(&UnmarshalTypeError{Value: "array", Type: v.Type(), Offset: int64(d.off)})
- d.skip()
- return nil
- }
- v = pv
-
- // Check type of target.
- switch v.Kind() {
- case reflect.Interface:
- if v.NumMethod() == 0 {
- // Decoding into nil interface? Switch to non-reflect code.
- ai := d.arrayInterface()
- v.Set(reflect.ValueOf(ai))
- return nil
- }
- // Otherwise it's invalid.
- fallthrough
- default:
- d.saveError(&UnmarshalTypeError{Value: "array", Type: v.Type(), Offset: int64(d.off)})
- d.skip()
- return nil
- case reflect.Array, reflect.Slice:
- break
- }
-
- i := 0
- for {
- // Look ahead for ] - can only happen on first iteration.
- d.scanWhile(scanSkipSpace)
- if d.opcode == scanEndArray {
- break
- }
-
- // Get element of array, growing if necessary.
- if v.Kind() == reflect.Slice {
- // Grow slice if necessary
- if i >= v.Cap() {
- newcap := v.Cap() + v.Cap()/2
- if newcap < 4 {
- newcap = 4
- }
- newv := reflect.MakeSlice(v.Type(), v.Len(), newcap)
- reflect.Copy(newv, v)
- v.Set(newv)
- }
- if i >= v.Len() {
- v.SetLen(i + 1)
- }
- }
-
- if i < v.Len() {
- // Decode into element.
- if err := d.value(v.Index(i)); err != nil {
- return err
- }
- } else {
- // Ran out of fixed array: skip.
- if err := d.value(reflect.Value{}); err != nil {
- return err
- }
- }
- i++
-
- // Next token must be , or ].
- if d.opcode == scanSkipSpace {
- d.scanWhile(scanSkipSpace)
- }
- if d.opcode == scanEndArray {
- break
- }
- if d.opcode != scanArrayValue {
- panic(phasePanicMsg)
- }
- }
-
- if i < v.Len() {
- if v.Kind() == reflect.Array {
- // Array. Zero the rest.
- z := reflect.Zero(v.Type().Elem())
- for ; i < v.Len(); i++ {
- v.Index(i).Set(z)
- }
- } else {
- v.SetLen(i)
- }
- }
- if i == 0 && v.Kind() == reflect.Slice {
- v.Set(reflect.MakeSlice(v.Type(), 0, 0))
- }
- return nil
-}
-
-var nullLiteral = []byte("null")
-var textUnmarshalerType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem()
-
-// object consumes an object from d.data[d.off-1:], decoding into v.
-// The first byte ('{') of the object has been read already.
-func (d *decodeState) object(v reflect.Value) error {
- // Check for unmarshaler.
- u, ut, pv := indirect(v, false)
- if u != nil {
- start := d.readIndex()
- d.skip()
- return u.UnmarshalJSON(d.data[start:d.off])
- }
- if ut != nil {
- d.saveError(&UnmarshalTypeError{Value: "object", Type: v.Type(), Offset: int64(d.off)})
- d.skip()
- return nil
- }
- v = pv
- t := v.Type()
-
- // Decoding into nil interface? Switch to non-reflect code.
- if v.Kind() == reflect.Interface && v.NumMethod() == 0 {
- oi := d.objectInterface()
- v.Set(reflect.ValueOf(oi))
- return nil
- }
-
- var fields []field
-
- // Check type of target:
- // struct or
- // map[T1]T2 where T1 is string, an integer type,
- // or an encoding.TextUnmarshaler
- switch v.Kind() {
- case reflect.Map:
- // Map key must either have string kind, have an integer kind,
- // or be an encoding.TextUnmarshaler.
- switch t.Key().Kind() {
- case reflect.String,
- reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
- reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
- default:
- if !reflect.PtrTo(t.Key()).Implements(textUnmarshalerType) {
- d.saveError(&UnmarshalTypeError{Value: "object", Type: t, Offset: int64(d.off)})
- d.skip()
- return nil
- }
- }
- if v.IsNil() {
- v.Set(reflect.MakeMap(t))
- }
- case reflect.Struct:
- fields = cachedTypeFields(t)
- // ok
- default:
- d.saveError(&UnmarshalTypeError{Value: "object", Type: t, Offset: int64(d.off)})
- d.skip()
- return nil
- }
-
- var mapElem reflect.Value
- originalErrorContext := d.errorContext
-
- for {
- // Read opening " of string key or closing }.
- d.scanWhile(scanSkipSpace)
- if d.opcode == scanEndObject {
- // closing } - can only happen on first iteration.
- break
- }
- if d.opcode != scanBeginLiteral {
- panic(phasePanicMsg)
- }
-
- // Read key.
- start := d.readIndex()
- d.scanWhile(scanContinue)
- item := d.data[start:d.readIndex()]
- key, ok := unquoteBytes(item)
- if !ok {
- panic(phasePanicMsg)
- }
-
- // Figure out field corresponding to key.
- var subv reflect.Value
- destring := false // whether the value is wrapped in a string to be decoded first
-
- if v.Kind() == reflect.Map {
- elemType := t.Elem()
- if !mapElem.IsValid() {
- mapElem = reflect.New(elemType).Elem()
- } else {
- mapElem.Set(reflect.Zero(elemType))
- }
- subv = mapElem
- } else {
- var f *field
- for i := range fields {
- ff := &fields[i]
- if bytes.Equal(ff.nameBytes, key) {
- f = ff
- break
- }
- if f == nil && ff.equalFold(ff.nameBytes, key) {
- f = ff
- }
- }
- if f != nil {
- subv = v
- destring = f.quoted
- for _, i := range f.index {
- if subv.Kind() == reflect.Ptr {
- if subv.IsNil() {
- // If a struct embeds a pointer to an unexported type,
- // it is not possible to set a newly allocated value
- // since the field is unexported.
- //
- // See https://golang.org/issue/21357
- if !subv.CanSet() {
- d.saveError(fmt.Errorf("json: cannot set embedded pointer to unexported struct: %v", subv.Type().Elem()))
- // Invalidate subv to ensure d.value(subv) skips over
- // the JSON value without assigning it to subv.
- subv = reflect.Value{}
- destring = false
- break
- }
- subv.Set(reflect.New(subv.Type().Elem()))
- }
- subv = subv.Elem()
- }
- subv = subv.Field(i)
- }
- d.errorContext.Field = f.name
- d.errorContext.Struct = t
- } else if d.disallowUnknownFields {
- d.saveError(fmt.Errorf("json: unknown field %q", key))
- }
- }
-
- // Read : before value.
- if d.opcode == scanSkipSpace {
- d.scanWhile(scanSkipSpace)
- }
- if d.opcode != scanObjectKey {
- panic(phasePanicMsg)
- }
- d.scanWhile(scanSkipSpace)
-
- if destring {
- switch qv := d.valueQuoted().(type) {
- case nil:
- if err := d.literalStore(nullLiteral, subv, false); err != nil {
- return err
- }
- case string:
- if err := d.literalStore([]byte(qv), subv, true); err != nil {
- return err
- }
- default:
- d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal unquoted value into %v", subv.Type()))
- }
- } else {
- if err := d.value(subv); err != nil {
- return err
- }
- }
-
- // Write value back to map;
- // if using struct, subv points into struct already.
- if v.Kind() == reflect.Map {
- kt := t.Key()
- var kv reflect.Value
- switch {
- case kt.Kind() == reflect.String:
- kv = reflect.ValueOf(key).Convert(kt)
- case reflect.PtrTo(kt).Implements(textUnmarshalerType):
- kv = reflect.New(kt)
- if err := d.literalStore(item, kv, true); err != nil {
- return err
- }
- kv = kv.Elem()
- default:
- switch kt.Kind() {
- case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
- s := string(key)
- n, err := strconv.ParseInt(s, 10, 64)
- if err != nil || reflect.Zero(kt).OverflowInt(n) {
- d.saveError(&UnmarshalTypeError{Value: "number " + s, Type: kt, Offset: int64(start + 1)})
- return nil
- }
- kv = reflect.ValueOf(n).Convert(kt)
- case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
- s := string(key)
- n, err := strconv.ParseUint(s, 10, 64)
- if err != nil || reflect.Zero(kt).OverflowUint(n) {
- d.saveError(&UnmarshalTypeError{Value: "number " + s, Type: kt, Offset: int64(start + 1)})
- return nil
- }
- kv = reflect.ValueOf(n).Convert(kt)
- default:
- panic("json: Unexpected key type") // should never occur
- }
- }
- v.SetMapIndex(kv, subv)
- }
-
- // Next token must be , or }.
- if d.opcode == scanSkipSpace {
- d.scanWhile(scanSkipSpace)
- }
- if d.opcode == scanEndObject {
- break
- }
- if d.opcode != scanObjectValue {
- panic(phasePanicMsg)
- }
-
- d.errorContext = originalErrorContext
- }
- return nil
-}
-
-// convertNumber converts the number literal s to a float64 or a Number
-// depending on the setting of d.useNumber.
-func (d *decodeState) convertNumber(s string) (interface{}, error) {
- if d.useNumber {
- return Number(s), nil
- }
- f, err := strconv.ParseFloat(s, 64)
- if err != nil {
- return nil, &UnmarshalTypeError{Value: "number " + s, Type: reflect.TypeOf(0.0), Offset: int64(d.off)}
- }
- return f, nil
-}
-
-var numberType = reflect.TypeOf(Number(""))
-
-// literalStore decodes a literal stored in item into v.
-//
-// fromQuoted indicates whether this literal came from unwrapping a
-// string from the ",string" struct tag option. this is used only to
-// produce more helpful error messages.
-func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool) error {
- // Check for unmarshaler.
- if len(item) == 0 {
- //Empty string given
- d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
- return nil
- }
- isNull := item[0] == 'n' // null
- u, ut, pv := indirect(v, isNull)
- if u != nil {
- return u.UnmarshalJSON(item)
- }
- if ut != nil {
- if item[0] != '"' {
- if fromQuoted {
- d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
- return nil
- }
- val := "number"
- switch item[0] {
- case 'n':
- val = "null"
- case 't', 'f':
- val = "bool"
- }
- d.saveError(&UnmarshalTypeError{Value: val, Type: v.Type(), Offset: int64(d.readIndex())})
- return nil
- }
- s, ok := unquoteBytes(item)
- if !ok {
- if fromQuoted {
- return fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())
- }
- panic(phasePanicMsg)
- }
- return ut.UnmarshalText(s)
- }
-
- v = pv
-
- switch c := item[0]; c {
- case 'n': // null
- // The main parser checks that only true and false can reach here,
- // but if this was a quoted string input, it could be anything.
- if fromQuoted && string(item) != "null" {
- d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
- break
- }
- switch v.Kind() {
- case reflect.Interface, reflect.Ptr, reflect.Map, reflect.Slice:
- v.Set(reflect.Zero(v.Type()))
- // otherwise, ignore null for primitives/string
- }
- case 't', 'f': // true, false
- value := item[0] == 't'
- // The main parser checks that only true and false can reach here,
- // but if this was a quoted string input, it could be anything.
- if fromQuoted && string(item) != "true" && string(item) != "false" {
- d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
- break
- }
- switch v.Kind() {
- default:
- if fromQuoted {
- d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
- } else {
- d.saveError(&UnmarshalTypeError{Value: "bool", Type: v.Type(), Offset: int64(d.readIndex())})
- }
- case reflect.Bool:
- v.SetBool(value)
- case reflect.Interface:
- if v.NumMethod() == 0 {
- v.Set(reflect.ValueOf(value))
- } else {
- d.saveError(&UnmarshalTypeError{Value: "bool", Type: v.Type(), Offset: int64(d.readIndex())})
- }
- }
-
- case '"': // string
- s, ok := unquoteBytes(item)
- if !ok {
- if fromQuoted {
- return fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())
- }
- panic(phasePanicMsg)
- }
- switch v.Kind() {
- default:
- d.saveError(&UnmarshalTypeError{Value: "string", Type: v.Type(), Offset: int64(d.readIndex())})
- case reflect.Slice:
- if v.Type().Elem().Kind() != reflect.Uint8 {
- d.saveError(&UnmarshalTypeError{Value: "string", Type: v.Type(), Offset: int64(d.readIndex())})
- break
- }
- b, err := base58.Decode(string(s))
- if err != nil {
- d.saveError(err)
- break
- }
- v.SetBytes(b)
- case reflect.String:
- v.SetString(string(s))
- case reflect.Interface:
- if v.NumMethod() == 0 {
- v.Set(reflect.ValueOf(string(s)))
- } else {
- d.saveError(&UnmarshalTypeError{Value: "string", Type: v.Type(), Offset: int64(d.readIndex())})
- }
- }
-
- default: // number
- if c != '-' && (c < '0' || c > '9') {
- if fromQuoted {
- return fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())
- }
- panic(phasePanicMsg)
- }
- s := string(item)
- switch v.Kind() {
- default:
- if v.Kind() == reflect.String && v.Type() == numberType {
- v.SetString(s)
- if !isValidNumber(s) {
- return fmt.Errorf("json: invalid number literal, trying to unmarshal %q into Number", item)
- }
- break
- }
- if fromQuoted {
- return fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())
- }
- d.saveError(&UnmarshalTypeError{Value: "number", Type: v.Type(), Offset: int64(d.readIndex())})
- case reflect.Interface:
- n, err := d.convertNumber(s)
- if err != nil {
- d.saveError(err)
- break
- }
- if v.NumMethod() != 0 {
- d.saveError(&UnmarshalTypeError{Value: "number", Type: v.Type(), Offset: int64(d.readIndex())})
- break
- }
- v.Set(reflect.ValueOf(n))
-
- case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
- n, err := strconv.ParseInt(s, 10, 64)
- if err != nil || v.OverflowInt(n) {
- d.saveError(&UnmarshalTypeError{Value: "number " + s, Type: v.Type(), Offset: int64(d.readIndex())})
- break
- }
- v.SetInt(n)
-
- case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
- n, err := strconv.ParseUint(s, 10, 64)
- if err != nil || v.OverflowUint(n) {
- d.saveError(&UnmarshalTypeError{Value: "number " + s, Type: v.Type(), Offset: int64(d.readIndex())})
- break
- }
- v.SetUint(n)
-
- case reflect.Float32, reflect.Float64:
- n, err := strconv.ParseFloat(s, v.Type().Bits())
- if err != nil || v.OverflowFloat(n) {
- d.saveError(&UnmarshalTypeError{Value: "number " + s, Type: v.Type(), Offset: int64(d.readIndex())})
- break
- }
- v.SetFloat(n)
- }
- }
- return nil
-}
-
-// The xxxInterface routines build up a value to be stored
-// in an empty interface. They are not strictly necessary,
-// but they avoid the weight of reflection in this common case.
-
-// valueInterface is like value but returns interface{}
-func (d *decodeState) valueInterface() (val interface{}) {
- switch d.opcode {
- default:
- panic(phasePanicMsg)
- case scanBeginArray:
- val = d.arrayInterface()
- d.scanNext()
- case scanBeginObject:
- val = d.objectInterface()
- d.scanNext()
- case scanBeginLiteral:
- val = d.literalInterface()
- }
- return
-}
-
-// arrayInterface is like array but returns []interface{}.
-func (d *decodeState) arrayInterface() []interface{} {
- var v = make([]interface{}, 0)
- for {
- // Look ahead for ] - can only happen on first iteration.
- d.scanWhile(scanSkipSpace)
- if d.opcode == scanEndArray {
- break
- }
-
- v = append(v, d.valueInterface())
-
- // Next token must be , or ].
- if d.opcode == scanSkipSpace {
- d.scanWhile(scanSkipSpace)
- }
- if d.opcode == scanEndArray {
- break
- }
- if d.opcode != scanArrayValue {
- panic(phasePanicMsg)
- }
- }
- return v
-}
-
-// objectInterface is like object but returns map[string]interface{}.
-func (d *decodeState) objectInterface() map[string]interface{} {
- m := make(map[string]interface{})
- for {
- // Read opening " of string key or closing }.
- d.scanWhile(scanSkipSpace)
- if d.opcode == scanEndObject {
- // closing } - can only happen on first iteration.
- break
- }
- if d.opcode != scanBeginLiteral {
- panic(phasePanicMsg)
- }
-
- // Read string key.
- start := d.readIndex()
- d.scanWhile(scanContinue)
- item := d.data[start:d.readIndex()]
- key, ok := unquote(item)
- if !ok {
- panic(phasePanicMsg)
- }
-
- // Read : before value.
- if d.opcode == scanSkipSpace {
- d.scanWhile(scanSkipSpace)
- }
- if d.opcode != scanObjectKey {
- panic(phasePanicMsg)
- }
- d.scanWhile(scanSkipSpace)
-
- // Read value.
- m[key] = d.valueInterface()
-
- // Next token must be , or }.
- if d.opcode == scanSkipSpace {
- d.scanWhile(scanSkipSpace)
- }
- if d.opcode == scanEndObject {
- break
- }
- if d.opcode != scanObjectValue {
- panic(phasePanicMsg)
- }
- }
- return m
-}
-
-// literalInterface consumes and returns a literal from d.data[d.off-1:] and
-// it reads the following byte ahead. The first byte of the literal has been
-// read already (that's how the caller knows it's a literal).
-func (d *decodeState) literalInterface() interface{} {
- // All bytes inside literal return scanContinue op code.
- start := d.readIndex()
- d.scanWhile(scanContinue)
-
- item := d.data[start:d.readIndex()]
-
- switch c := item[0]; c {
- case 'n': // null
- return nil
-
- case 't', 'f': // true, false
- return c == 't'
-
- case '"': // string
- s, ok := unquote(item)
- if !ok {
- panic(phasePanicMsg)
- }
- return s
-
- default: // number
- if c != '-' && (c < '0' || c > '9') {
- panic(phasePanicMsg)
- }
- n, err := d.convertNumber(string(item))
- if err != nil {
- d.saveError(err)
- }
- return n
- }
-}
-
-// getu4 decodes \uXXXX from the beginning of s, returning the hex value,
-// or it returns -1.
-func getu4(s []byte) rune {
- if len(s) < 6 || s[0] != '\\' || s[1] != 'u' {
- return -1
- }
- var r rune
- for _, c := range s[2:6] {
- switch {
- case '0' <= c && c <= '9':
- c = c - '0'
- case 'a' <= c && c <= 'f':
- c = c - 'a' + 10
- case 'A' <= c && c <= 'F':
- c = c - 'A' + 10
- default:
- return -1
- }
- r = r*16 + rune(c)
- }
- return r
-}
-
-// unquote converts a quoted JSON string literal s into an actual string t.
-// The rules are different than for Go, so cannot use strconv.Unquote.
-func unquote(s []byte) (t string, ok bool) {
- s, ok = unquoteBytes(s)
- t = string(s)
- return
-}
-
-func unquoteBytes(s []byte) (t []byte, ok bool) {
- if len(s) < 2 || s[0] != '"' || s[len(s)-1] != '"' {
- return
- }
- s = s[1 : len(s)-1]
-
- // Check for unusual characters. If there are none,
- // then no unquoting is needed, so return a slice of the
- // original bytes.
- r := 0
- for r < len(s) {
- c := s[r]
- if c == '\\' || c == '"' || c < ' ' {
- break
- }
- if c < utf8.RuneSelf {
- r++
- continue
- }
- rr, size := utf8.DecodeRune(s[r:])
- if rr == utf8.RuneError && size == 1 {
- break
- }
- r += size
- }
- if r == len(s) {
- return s, true
- }
-
- b := make([]byte, len(s)+2*utf8.UTFMax)
- w := copy(b, s[0:r])
- for r < len(s) {
- // Out of room? Can only happen if s is full of
- // malformed UTF-8 and we're replacing each
- // byte with RuneError.
- if w >= len(b)-2*utf8.UTFMax {
- nb := make([]byte, (len(b)+utf8.UTFMax)*2)
- copy(nb, b[0:w])
- b = nb
- }
- switch c := s[r]; {
- case c == '\\':
- r++
- if r >= len(s) {
- return
- }
- switch s[r] {
- default:
- return
- case '"', '\\', '/', '\'':
- b[w] = s[r]
- r++
- w++
- case 'b':
- b[w] = '\b'
- r++
- w++
- case 'f':
- b[w] = '\f'
- r++
- w++
- case 'n':
- b[w] = '\n'
- r++
- w++
- case 'r':
- b[w] = '\r'
- r++
- w++
- case 't':
- b[w] = '\t'
- r++
- w++
- case 'u':
- r--
- rr := getu4(s[r:])
- if rr < 0 {
- return
- }
- r += 6
- if utf16.IsSurrogate(rr) {
- rr1 := getu4(s[r:])
- if dec := utf16.DecodeRune(rr, rr1); dec != unicode.ReplacementChar {
- // A valid pair; consume.
- r += 6
- w += utf8.EncodeRune(b[w:], dec)
- break
- }
- // Invalid surrogate; fall back to replacement rune.
- rr = unicode.ReplacementChar
- }
- w += utf8.EncodeRune(b[w:], rr)
- }
-
- // Quote, control characters are invalid.
- case c == '"', c < ' ':
- return
-
- // ASCII
- case c < utf8.RuneSelf:
- b[w] = c
- r++
- w++
-
- // Coerce to well-formed UTF-8.
- default:
- rr, size := utf8.DecodeRune(s[r:])
- r += size
- w += utf8.EncodeRune(b[w:], rr)
- }
- }
- return b[0:w], true
-}
diff --git a/cmd/aergocli/util/encoding/json/decode_test.go b/cmd/aergocli/util/encoding/json/decode_test.go
deleted file mode 100644
index 1fb8c03eb..000000000
--- a/cmd/aergocli/util/encoding/json/decode_test.go
+++ /dev/null
@@ -1,2271 +0,0 @@
-// Copyright 2010 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package json
-
-import (
- "bytes"
- "encoding"
- "errors"
- "fmt"
- "image"
- "math"
- "math/big"
- "net"
- "reflect"
- "strconv"
- "strings"
- "testing"
- "time"
-)
-
-type T struct {
- X string
- Y int
- Z int `json:"-"`
-}
-
-type U struct {
- Alphabet string `json:"alpha"`
-}
-
-type V struct {
- F1 interface{}
- F2 int32
- F3 Number
- F4 *VOuter
-}
-
-type VOuter struct {
- V V
-}
-
-type W struct {
- S SS
-}
-
-type SS string
-
-func (*SS) UnmarshalJSON(data []byte) error {
- return &UnmarshalTypeError{Value: "number", Type: reflect.TypeOf(SS(""))}
-}
-
-// ifaceNumAsFloat64/ifaceNumAsNumber are used to test unmarshaling with and
-// without UseNumber
-var ifaceNumAsFloat64 = map[string]interface{}{
- "k1": float64(1),
- "k2": "s",
- "k3": []interface{}{float64(1), float64(2.0), float64(3e-3)},
- "k4": map[string]interface{}{"kk1": "s", "kk2": float64(2)},
-}
-
-var ifaceNumAsNumber = map[string]interface{}{
- "k1": Number("1"),
- "k2": "s",
- "k3": []interface{}{Number("1"), Number("2.0"), Number("3e-3")},
- "k4": map[string]interface{}{"kk1": "s", "kk2": Number("2")},
-}
-
-type tx struct {
- x int
-}
-
-type u8 uint8
-
-// A type that can unmarshal itself.
-
-type unmarshaler struct {
- T bool
-}
-
-func (u *unmarshaler) UnmarshalJSON(b []byte) error {
- *u = unmarshaler{true} // All we need to see that UnmarshalJSON is called.
- return nil
-}
-
-type ustruct struct {
- M unmarshaler
-}
-
-type unmarshalerText struct {
- A, B string
-}
-
-// needed for re-marshaling tests
-func (u unmarshalerText) MarshalText() ([]byte, error) {
- return []byte(u.A + ":" + u.B), nil
-}
-
-func (u *unmarshalerText) UnmarshalText(b []byte) error {
- pos := bytes.IndexByte(b, ':')
- if pos == -1 {
- return errors.New("missing separator")
- }
- u.A, u.B = string(b[:pos]), string(b[pos+1:])
- return nil
-}
-
-var _ encoding.TextUnmarshaler = (*unmarshalerText)(nil)
-
-type ustructText struct {
- M unmarshalerText
-}
-
-// u8marshal is an integer type that can marshal/unmarshal itself.
-type u8marshal uint8
-
-func (u8 u8marshal) MarshalText() ([]byte, error) {
- return []byte(fmt.Sprintf("u%d", u8)), nil
-}
-
-var errMissingU8Prefix = errors.New("missing 'u' prefix")
-
-func (u8 *u8marshal) UnmarshalText(b []byte) error {
- if !bytes.HasPrefix(b, []byte{'u'}) {
- return errMissingU8Prefix
- }
- n, err := strconv.Atoi(string(b[1:]))
- if err != nil {
- return err
- }
- *u8 = u8marshal(n)
- return nil
-}
-
-var _ encoding.TextUnmarshaler = (*u8marshal)(nil)
-
-var (
- um0, um1 unmarshaler // target2 of unmarshaling
- ump = &um1
- umtrue = unmarshaler{true}
- umslice = []unmarshaler{{true}}
- umslicep = new([]unmarshaler)
- umstruct = ustruct{unmarshaler{true}}
-
- um0T, um1T unmarshalerText // target2 of unmarshaling
- umpType = &um1T
- umtrueXY = unmarshalerText{"x", "y"}
- umsliceXY = []unmarshalerText{{"x", "y"}}
- umslicepType = new([]unmarshalerText)
- umstructType = new(ustructText)
- umstructXY = ustructText{unmarshalerText{"x", "y"}}
-
- ummapType = map[unmarshalerText]bool{}
- ummapXY = map[unmarshalerText]bool{{"x", "y"}: true}
-)
-
-// Test data structures for anonymous fields.
-
-type Point struct {
- Z int
-}
-
-type Top struct {
- Level0 int
- Embed0
- *Embed0a
- *Embed0b `json:"e,omitempty"` // treated as named
- Embed0c `json:"-"` // ignored
- Loop
- Embed0p // has Point with X, Y, used
- Embed0q // has Point with Z, used
- embed // contains exported field
-}
-
-type Embed0 struct {
- Level1a int // overridden by Embed0a's Level1a with json tag
- Level1b int // used because Embed0a's Level1b is renamed
- Level1c int // used because Embed0a's Level1c is ignored
- Level1d int // annihilated by Embed0a's Level1d
- Level1e int `json:"x"` // annihilated by Embed0a.Level1e
-}
-
-type Embed0a struct {
- Level1a int `json:"Level1a,omitempty"`
- Level1b int `json:"LEVEL1B,omitempty"`
- Level1c int `json:"-"`
- Level1d int // annihilated by Embed0's Level1d
- Level1f int `json:"x"` // annihilated by Embed0's Level1e
-}
-
-type Embed0b Embed0
-
-type Embed0c Embed0
-
-type Embed0p struct {
- image.Point
-}
-
-type Embed0q struct {
- Point
-}
-
-type embed struct {
- Q int
-}
-
-type Loop struct {
- Loop1 int `json:",omitempty"`
- Loop2 int `json:",omitempty"`
- *Loop
-}
-
-// From reflect test:
-// The X in S6 and S7 annihilate, but they also block the X in S8.S9.
-type S5 struct {
- S6
- S7
- S8
-}
-
-type S6 struct {
- X int
-}
-
-type S7 S6
-
-type S8 struct {
- S9
-}
-
-type S9 struct {
- X int
- Y int
-}
-
-// From reflect test:
-// The X in S11.S6 and S12.S6 annihilate, but they also block the X in S13.S8.S9.
-type S10 struct {
- S11
- S12
- S13
-}
-
-type S11 struct {
- S6
-}
-
-type S12 struct {
- S6
-}
-
-type S13 struct {
- S8
-}
-
-type Ambig struct {
- // Given "hello", the first match should win.
- First int `json:"HELLO"`
- Second int `json:"Hello"`
-}
-
-type XYZ struct {
- X interface{}
- Y interface{}
- Z interface{}
-}
-
-func sliceAddr(x []int) *[]int { return &x }
-func mapAddr(x map[string]int) *map[string]int { return &x }
-
-type byteWithMarshalJSON byte
-
-func (b byteWithMarshalJSON) MarshalJSON() ([]byte, error) {
- return []byte(fmt.Sprintf(`"Z%.2x"`, byte(b))), nil
-}
-
-func (b *byteWithMarshalJSON) UnmarshalJSON(data []byte) error {
- if len(data) != 5 || data[0] != '"' || data[1] != 'Z' || data[4] != '"' {
- return fmt.Errorf("bad quoted string")
- }
- i, err := strconv.ParseInt(string(data[2:4]), 16, 8)
- if err != nil {
- return fmt.Errorf("bad hex")
- }
- *b = byteWithMarshalJSON(i)
- return nil
-}
-
-type byteWithPtrMarshalJSON byte
-
-func (b *byteWithPtrMarshalJSON) MarshalJSON() ([]byte, error) {
- return byteWithMarshalJSON(*b).MarshalJSON()
-}
-
-func (b *byteWithPtrMarshalJSON) UnmarshalJSON(data []byte) error {
- return (*byteWithMarshalJSON)(b).UnmarshalJSON(data)
-}
-
-type byteWithMarshalText byte
-
-func (b byteWithMarshalText) MarshalText() ([]byte, error) {
- return []byte(fmt.Sprintf(`Z%.2x`, byte(b))), nil
-}
-
-func (b *byteWithMarshalText) UnmarshalText(data []byte) error {
- if len(data) != 3 || data[0] != 'Z' {
- return fmt.Errorf("bad quoted string")
- }
- i, err := strconv.ParseInt(string(data[1:3]), 16, 8)
- if err != nil {
- return fmt.Errorf("bad hex")
- }
- *b = byteWithMarshalText(i)
- return nil
-}
-
-type byteWithPtrMarshalText byte
-
-func (b *byteWithPtrMarshalText) MarshalText() ([]byte, error) {
- return byteWithMarshalText(*b).MarshalText()
-}
-
-func (b *byteWithPtrMarshalText) UnmarshalText(data []byte) error {
- return (*byteWithMarshalText)(b).UnmarshalText(data)
-}
-
-type intWithMarshalJSON int
-
-func (b intWithMarshalJSON) MarshalJSON() ([]byte, error) {
- return []byte(fmt.Sprintf(`"Z%.2x"`, int(b))), nil
-}
-
-func (b *intWithMarshalJSON) UnmarshalJSON(data []byte) error {
- if len(data) != 5 || data[0] != '"' || data[1] != 'Z' || data[4] != '"' {
- return fmt.Errorf("bad quoted string")
- }
- i, err := strconv.ParseInt(string(data[2:4]), 16, 8)
- if err != nil {
- return fmt.Errorf("bad hex")
- }
- *b = intWithMarshalJSON(i)
- return nil
-}
-
-type intWithPtrMarshalJSON int
-
-func (b *intWithPtrMarshalJSON) MarshalJSON() ([]byte, error) {
- return intWithMarshalJSON(*b).MarshalJSON()
-}
-
-func (b *intWithPtrMarshalJSON) UnmarshalJSON(data []byte) error {
- return (*intWithMarshalJSON)(b).UnmarshalJSON(data)
-}
-
-type intWithMarshalText int
-
-func (b intWithMarshalText) MarshalText() ([]byte, error) {
- return []byte(fmt.Sprintf(`Z%.2x`, int(b))), nil
-}
-
-func (b *intWithMarshalText) UnmarshalText(data []byte) error {
- if len(data) != 3 || data[0] != 'Z' {
- return fmt.Errorf("bad quoted string")
- }
- i, err := strconv.ParseInt(string(data[1:3]), 16, 8)
- if err != nil {
- return fmt.Errorf("bad hex")
- }
- *b = intWithMarshalText(i)
- return nil
-}
-
-type intWithPtrMarshalText int
-
-func (b *intWithPtrMarshalText) MarshalText() ([]byte, error) {
- return intWithMarshalText(*b).MarshalText()
-}
-
-func (b *intWithPtrMarshalText) UnmarshalText(data []byte) error {
- return (*intWithMarshalText)(b).UnmarshalText(data)
-}
-
-type mapStringToStringData struct {
- Data map[string]string `json:"data"`
-}
-
-type unmarshalTest struct {
- in string
- ptr interface{}
- out interface{}
- err error
- useNumber bool
- golden bool
- disallowUnknownFields bool
-}
-
-type B struct {
- B bool `json:",string"`
-}
-
-var unmarshalTests = []unmarshalTest{
- // basic types
- {in: `true`, ptr: new(bool), out: true},
- {in: `1`, ptr: new(int), out: 1},
- {in: `1.2`, ptr: new(float64), out: 1.2},
- {in: `-5`, ptr: new(int16), out: int16(-5)},
- {in: `2`, ptr: new(Number), out: Number("2"), useNumber: true},
- {in: `2`, ptr: new(Number), out: Number("2")},
- {in: `2`, ptr: new(interface{}), out: float64(2.0)},
- {in: `2`, ptr: new(interface{}), out: Number("2"), useNumber: true},
- {in: `"a\u1234"`, ptr: new(string), out: "a\u1234"},
- {in: `"http:\/\/"`, ptr: new(string), out: "http://"},
- {in: `"g-clef: \uD834\uDD1E"`, ptr: new(string), out: "g-clef: \U0001D11E"},
- {in: `"invalid: \uD834x\uDD1E"`, ptr: new(string), out: "invalid: \uFFFDx\uFFFD"},
- {in: "null", ptr: new(interface{}), out: nil},
- {in: `{"X": [1,2,3], "Y": 4}`, ptr: new(T), out: T{Y: 4}, err: &UnmarshalTypeError{"array", reflect.TypeOf(""), 7, "T", "X"}},
- {in: `{"X": 23}`, ptr: new(T), out: T{}, err: &UnmarshalTypeError{"number", reflect.TypeOf(""), 8, "T", "X"}}, {in: `{"x": 1}`, ptr: new(tx), out: tx{}},
- {in: `{"x": 1}`, ptr: new(tx), out: tx{}},
- {in: `{"x": 1}`, ptr: new(tx), err: fmt.Errorf("json: unknown field \"x\""), disallowUnknownFields: true},
- {in: `{"S": 23}`, ptr: new(W), out: W{}, err: &UnmarshalTypeError{"number", reflect.TypeOf(SS("")), 0, "W", "S"}},
- {in: `{"F1":1,"F2":2,"F3":3}`, ptr: new(V), out: V{F1: float64(1), F2: int32(2), F3: Number("3")}},
- {in: `{"F1":1,"F2":2,"F3":3}`, ptr: new(V), out: V{F1: Number("1"), F2: int32(2), F3: Number("3")}, useNumber: true},
- {in: `{"k1":1,"k2":"s","k3":[1,2.0,3e-3],"k4":{"kk1":"s","kk2":2}}`, ptr: new(interface{}), out: ifaceNumAsFloat64},
- {in: `{"k1":1,"k2":"s","k3":[1,2.0,3e-3],"k4":{"kk1":"s","kk2":2}}`, ptr: new(interface{}), out: ifaceNumAsNumber, useNumber: true},
-
- // raw values with whitespace
- {in: "\n true ", ptr: new(bool), out: true},
- {in: "\t 1 ", ptr: new(int), out: 1},
- {in: "\r 1.2 ", ptr: new(float64), out: 1.2},
- {in: "\t -5 \n", ptr: new(int16), out: int16(-5)},
- {in: "\t \"a\\u1234\" \n", ptr: new(string), out: "a\u1234"},
-
- // Z has a "-" tag.
- {in: `{"Y": 1, "Z": 2}`, ptr: new(T), out: T{Y: 1}},
- {in: `{"Y": 1, "Z": 2}`, ptr: new(T), err: fmt.Errorf("json: unknown field \"Z\""), disallowUnknownFields: true},
-
- {in: `{"alpha": "abc", "alphabet": "xyz"}`, ptr: new(U), out: U{Alphabet: "abc"}},
- {in: `{"alpha": "abc", "alphabet": "xyz"}`, ptr: new(U), err: fmt.Errorf("json: unknown field \"alphabet\""), disallowUnknownFields: true},
- {in: `{"alpha": "abc"}`, ptr: new(U), out: U{Alphabet: "abc"}},
- {in: `{"alphabet": "xyz"}`, ptr: new(U), out: U{}},
- {in: `{"alphabet": "xyz"}`, ptr: new(U), err: fmt.Errorf("json: unknown field \"alphabet\""), disallowUnknownFields: true},
-
- // syntax errors
- {in: `{"X": "foo", "Y"}`, err: &SyntaxError{"invalid character '}' after object key", 17}},
- {in: `[1, 2, 3+]`, err: &SyntaxError{"invalid character '+' after array element", 9}},
- {in: `{"X":12x}`, err: &SyntaxError{"invalid character 'x' after object key:value pair", 8}, useNumber: true},
- {in: `[2, 3`, err: &SyntaxError{msg: "unexpected end of JSON input", Offset: 5}},
-
- // raw value errors
- {in: "\x01 42", err: &SyntaxError{"invalid character '\\x01' looking for beginning of value", 1}},
- {in: " 42 \x01", err: &SyntaxError{"invalid character '\\x01' after top-level value", 5}},
- {in: "\x01 true", err: &SyntaxError{"invalid character '\\x01' looking for beginning of value", 1}},
- {in: " false \x01", err: &SyntaxError{"invalid character '\\x01' after top-level value", 8}},
- {in: "\x01 1.2", err: &SyntaxError{"invalid character '\\x01' looking for beginning of value", 1}},
- {in: " 3.4 \x01", err: &SyntaxError{"invalid character '\\x01' after top-level value", 6}},
- {in: "\x01 \"string\"", err: &SyntaxError{"invalid character '\\x01' looking for beginning of value", 1}},
- {in: " \"string\" \x01", err: &SyntaxError{"invalid character '\\x01' after top-level value", 11}},
-
- // array tests
- {in: `[1, 2, 3]`, ptr: new([3]int), out: [3]int{1, 2, 3}},
- {in: `[1, 2, 3]`, ptr: new([1]int), out: [1]int{1}},
- {in: `[1, 2, 3]`, ptr: new([5]int), out: [5]int{1, 2, 3, 0, 0}},
- {in: `[1, 2, 3]`, ptr: new(MustNotUnmarshalJSON), err: errors.New("MustNotUnmarshalJSON was used")},
-
- // empty array to interface test
- {in: `[]`, ptr: new([]interface{}), out: []interface{}{}},
- {in: `null`, ptr: new([]interface{}), out: []interface{}(nil)},
- {in: `{"T":[]}`, ptr: new(map[string]interface{}), out: map[string]interface{}{"T": []interface{}{}}},
- {in: `{"T":null}`, ptr: new(map[string]interface{}), out: map[string]interface{}{"T": interface{}(nil)}},
-
- // composite tests
- {in: allValueIndent, ptr: new(All), out: allValue},
- {in: allValueCompact, ptr: new(All), out: allValue},
- {in: allValueIndent, ptr: new(*All), out: &allValue},
- {in: allValueCompact, ptr: new(*All), out: &allValue},
- {in: pallValueIndent, ptr: new(All), out: pallValue},
- {in: pallValueCompact, ptr: new(All), out: pallValue},
- {in: pallValueIndent, ptr: new(*All), out: &pallValue},
- {in: pallValueCompact, ptr: new(*All), out: &pallValue},
-
- // unmarshal interface test
- {in: `{"T":false}`, ptr: &um0, out: umtrue}, // use "false" so test will fail if custom unmarshaler is not called
- {in: `{"T":false}`, ptr: &ump, out: &umtrue},
- {in: `[{"T":false}]`, ptr: &umslice, out: umslice},
- {in: `[{"T":false}]`, ptr: &umslicep, out: &umslice},
- {in: `{"M":{"T":"x:y"}}`, ptr: &umstruct, out: umstruct},
-
- // UnmarshalText interface test
- {in: `"x:y"`, ptr: &um0T, out: umtrueXY},
- {in: `"x:y"`, ptr: &umpType, out: &umtrueXY},
- {in: `["x:y"]`, ptr: &umsliceXY, out: umsliceXY},
- {in: `["x:y"]`, ptr: &umslicepType, out: &umsliceXY},
- {in: `{"M":"x:y"}`, ptr: umstructType, out: umstructXY},
-
- // integer-keyed map test
- {
- in: `{"-1":"a","0":"b","1":"c"}`,
- ptr: new(map[int]string),
- out: map[int]string{-1: "a", 0: "b", 1: "c"},
- },
- {
- in: `{"0":"a","10":"c","9":"b"}`,
- ptr: new(map[u8]string),
- out: map[u8]string{0: "a", 9: "b", 10: "c"},
- },
- {
- in: `{"-9223372036854775808":"min","9223372036854775807":"max"}`,
- ptr: new(map[int64]string),
- out: map[int64]string{math.MinInt64: "min", math.MaxInt64: "max"},
- },
- {
- in: `{"18446744073709551615":"max"}`,
- ptr: new(map[uint64]string),
- out: map[uint64]string{math.MaxUint64: "max"},
- },
- {
- in: `{"0":false,"10":true}`,
- ptr: new(map[uintptr]bool),
- out: map[uintptr]bool{0: false, 10: true},
- },
-
- // Check that MarshalText and UnmarshalText take precedence
- // over default integer handling in map keys.
- {
- in: `{"u2":4}`,
- ptr: new(map[u8marshal]int),
- out: map[u8marshal]int{2: 4},
- },
- {
- in: `{"2":4}`,
- ptr: new(map[u8marshal]int),
- err: errMissingU8Prefix,
- },
-
- // integer-keyed map errors
- {
- in: `{"abc":"abc"}`,
- ptr: new(map[int]string),
- err: &UnmarshalTypeError{Value: "number abc", Type: reflect.TypeOf(0), Offset: 2},
- },
- {
- in: `{"256":"abc"}`,
- ptr: new(map[uint8]string),
- err: &UnmarshalTypeError{Value: "number 256", Type: reflect.TypeOf(uint8(0)), Offset: 2},
- },
- {
- in: `{"128":"abc"}`,
- ptr: new(map[int8]string),
- err: &UnmarshalTypeError{Value: "number 128", Type: reflect.TypeOf(int8(0)), Offset: 2},
- },
- {
- in: `{"-1":"abc"}`,
- ptr: new(map[uint8]string),
- err: &UnmarshalTypeError{Value: "number -1", Type: reflect.TypeOf(uint8(0)), Offset: 2},
- },
-
- // Map keys can be encoding.TextUnmarshalers.
- {in: `{"x:y":true}`, ptr: &ummapType, out: ummapXY},
- // If multiple values for the same key exists, only the most recent value is used.
- {in: `{"x:y":false,"x:y":true}`, ptr: &ummapType, out: ummapXY},
-
- // Overwriting of data.
- // This is different from package xml, but it's what we've always done.
- // Now documented and tested.
- {in: `[2]`, ptr: sliceAddr([]int{1}), out: []int{2}},
- {in: `{"key": 2}`, ptr: mapAddr(map[string]int{"old": 0, "key": 1}), out: map[string]int{"key": 2}},
-
- {
- in: `{
- "Level0": 1,
- "Level1b": 2,
- "Level1c": 3,
- "x": 4,
- "Level1a": 5,
- "LEVEL1B": 6,
- "e": {
- "Level1a": 8,
- "Level1b": 9,
- "Level1c": 10,
- "Level1d": 11,
- "x": 12
- },
- "Loop1": 13,
- "Loop2": 14,
- "X": 15,
- "Y": 16,
- "Z": 17,
- "Q": 18
- }`,
- ptr: new(Top),
- out: Top{
- Level0: 1,
- Embed0: Embed0{
- Level1b: 2,
- Level1c: 3,
- },
- Embed0a: &Embed0a{
- Level1a: 5,
- Level1b: 6,
- },
- Embed0b: &Embed0b{
- Level1a: 8,
- Level1b: 9,
- Level1c: 10,
- Level1d: 11,
- Level1e: 12,
- },
- Loop: Loop{
- Loop1: 13,
- Loop2: 14,
- },
- Embed0p: Embed0p{
- Point: image.Point{X: 15, Y: 16},
- },
- Embed0q: Embed0q{
- Point: Point{Z: 17},
- },
- embed: embed{
- Q: 18,
- },
- },
- },
- {
- in: `{"hello": 1}`,
- ptr: new(Ambig),
- out: Ambig{First: 1},
- },
-
- {
- in: `{"X": 1,"Y":2}`,
- ptr: new(S5),
- out: S5{S8: S8{S9: S9{Y: 2}}},
- },
- {
- in: `{"X": 1,"Y":2}`,
- ptr: new(S5),
- err: fmt.Errorf("json: unknown field \"X\""),
- disallowUnknownFields: true,
- },
- {
- in: `{"X": 1,"Y":2}`,
- ptr: new(S10),
- out: S10{S13: S13{S8: S8{S9: S9{Y: 2}}}},
- },
- {
- in: `{"X": 1,"Y":2}`,
- ptr: new(S10),
- err: fmt.Errorf("json: unknown field \"X\""),
- disallowUnknownFields: true,
- },
-
- // invalid UTF-8 is coerced to valid UTF-8.
- {
- in: "\"hello\xffworld\"",
- ptr: new(string),
- out: "hello\ufffdworld",
- },
- {
- in: "\"hello\xc2\xc2world\"",
- ptr: new(string),
- out: "hello\ufffd\ufffdworld",
- },
- {
- in: "\"hello\xc2\xffworld\"",
- ptr: new(string),
- out: "hello\ufffd\ufffdworld",
- },
- {
- in: "\"hello\\ud800world\"",
- ptr: new(string),
- out: "hello\ufffdworld",
- },
- {
- in: "\"hello\\ud800\\ud800world\"",
- ptr: new(string),
- out: "hello\ufffd\ufffdworld",
- },
- {
- in: "\"hello\\ud800\\ud800world\"",
- ptr: new(string),
- out: "hello\ufffd\ufffdworld",
- },
- {
- in: "\"hello\xed\xa0\x80\xed\xb0\x80world\"",
- ptr: new(string),
- out: "hello\ufffd\ufffd\ufffd\ufffd\ufffd\ufffdworld",
- },
-
- // Used to be issue 8305, but time.Time implements encoding.TextUnmarshaler so this works now.
- {
- in: `{"2009-11-10T23:00:00Z": "hello world"}`,
- ptr: &map[time.Time]string{},
- out: map[time.Time]string{time.Date(2009, 11, 10, 23, 0, 0, 0, time.UTC): "hello world"},
- },
-
- // issue 8305
- {
- in: `{"2009-11-10T23:00:00Z": "hello world"}`,
- ptr: &map[Point]string{},
- err: &UnmarshalTypeError{Value: "object", Type: reflect.TypeOf(map[Point]string{}), Offset: 1},
- },
- {
- in: `{"asdf": "hello world"}`,
- ptr: &map[unmarshaler]string{},
- err: &UnmarshalTypeError{Value: "object", Type: reflect.TypeOf(map[unmarshaler]string{}), Offset: 1},
- },
-
- // related to issue 13783.
- // Go 1.7 changed marshaling a slice of typed byte to use the methods on the byte type,
- // similar to marshaling a slice of typed int.
- // These tests check that, assuming the byte type also has valid decoding methods,
- // either the old base64 string encoding or the new per-element encoding can be
- // successfully unmarshaled. The custom unmarshalers were accessible in earlier
- // versions of Go, even though the custom marshaler was not.
- //
- // TODO: fix to base58
- //{
- // in: `"AQID"`,
- // ptr: new([]byteWithMarshalJSON),
- // out: []byteWithMarshalJSON{1, 2, 3},
- //},
- //{
- // in: `["Z01","Z02","Z03"]`,
- // ptr: new([]byteWithMarshalJSON),
- // out: []byteWithMarshalJSON{1, 2, 3},
- // golden: true,
- //},
- //{
- // in: `"AQID"`,
- // ptr: new([]byteWithMarshalText),
- // out: []byteWithMarshalText{1, 2, 3},
- //},
- //{
- // in: `["Z01","Z02","Z03"]`,
- // ptr: new([]byteWithMarshalText),
- // out: []byteWithMarshalText{1, 2, 3},
- // golden: true,
- //},
- //{
- // in: `"AQID"`,
- // ptr: new([]byteWithPtrMarshalJSON),
- // out: []byteWithPtrMarshalJSON{1, 2, 3},
- //},
- //{
- // in: `["Z01","Z02","Z03"]`,
- // ptr: new([]byteWithPtrMarshalJSON),
- // out: []byteWithPtrMarshalJSON{1, 2, 3},
- // golden: true,
- //},
- //{
- // in: `"AQID"`,
- // ptr: new([]byteWithPtrMarshalText),
- // out: []byteWithPtrMarshalText{1, 2, 3},
- //},
- //{
- // in: `["Z01","Z02","Z03"]`,
- // ptr: new([]byteWithPtrMarshalText),
- // out: []byteWithPtrMarshalText{1, 2, 3},
- // golden: true,
- //},
- //
- // ints work with the marshaler but not the base64 []byte case
- //{
- // in: `["Z01","Z02","Z03"]`,
- // ptr: new([]intWithMarshalJSON),
- // out: []intWithMarshalJSON{1, 2, 3},
- // golden: true,
- //},
- //{
- // in: `["Z01","Z02","Z03"]`,
- // ptr: new([]intWithMarshalText),
- // out: []intWithMarshalText{1, 2, 3},
- // golden: true,
- //},
- //{
- // in: `["Z01","Z02","Z03"]`,
- // ptr: new([]intWithPtrMarshalJSON),
- // out: []intWithPtrMarshalJSON{1, 2, 3},
- // golden: true,
- //},
- //{
- // in: `["Z01","Z02","Z03"]`,
- // ptr: new([]intWithPtrMarshalText),
- // out: []intWithPtrMarshalText{1, 2, 3},
- // golden: true,
- //},
-
- {in: `0.000001`, ptr: new(float64), out: 0.000001, golden: true},
- {in: `1e-7`, ptr: new(float64), out: 1e-7, golden: true},
- {in: `100000000000000000000`, ptr: new(float64), out: 100000000000000000000.0, golden: true},
- {in: `1e+21`, ptr: new(float64), out: 1e21, golden: true},
- {in: `-0.000001`, ptr: new(float64), out: -0.000001, golden: true},
- {in: `-1e-7`, ptr: new(float64), out: -1e-7, golden: true},
- {in: `-100000000000000000000`, ptr: new(float64), out: -100000000000000000000.0, golden: true},
- {in: `-1e+21`, ptr: new(float64), out: -1e21, golden: true},
- {in: `999999999999999900000`, ptr: new(float64), out: 999999999999999900000.0, golden: true},
- {in: `9007199254740992`, ptr: new(float64), out: 9007199254740992.0, golden: true},
- {in: `9007199254740993`, ptr: new(float64), out: 9007199254740992.0, golden: false},
-
- {
- in: `{"V": {"F2": "hello"}}`,
- ptr: new(VOuter),
- err: &UnmarshalTypeError{
- Value: "string",
- Struct: "V",
- Field: "F2",
- Type: reflect.TypeOf(int32(0)),
- Offset: 20,
- },
- },
- {
- in: `{"V": {"F4": {}, "F2": "hello"}}`,
- ptr: new(VOuter),
- err: &UnmarshalTypeError{
- Value: "string",
- Struct: "V",
- Field: "F2",
- Type: reflect.TypeOf(int32(0)),
- Offset: 30,
- },
- },
-
- // issue 15146.
- // invalid inputs in wrongStringTests below.
- {in: `{"B":"true"}`, ptr: new(B), out: B{true}, golden: true},
- {in: `{"B":"false"}`, ptr: new(B), out: B{false}, golden: true},
- {in: `{"B": "maybe"}`, ptr: new(B), err: errors.New(`json: invalid use of ,string struct tag, trying to unmarshal "maybe" into bool`)},
- {in: `{"B": "tru"}`, ptr: new(B), err: errors.New(`json: invalid use of ,string struct tag, trying to unmarshal "tru" into bool`)},
- {in: `{"B": "False"}`, ptr: new(B), err: errors.New(`json: invalid use of ,string struct tag, trying to unmarshal "False" into bool`)},
- {in: `{"B": "null"}`, ptr: new(B), out: B{false}},
- {in: `{"B": "nul"}`, ptr: new(B), err: errors.New(`json: invalid use of ,string struct tag, trying to unmarshal "nul" into bool`)},
- {in: `{"B": [2, 3]}`, ptr: new(B), err: errors.New(`json: invalid use of ,string struct tag, trying to unmarshal unquoted value into bool`)},
-
- // additional tests for disallowUnknownFields
- {
- in: `{
- "Level0": 1,
- "Level1b": 2,
- "Level1c": 3,
- "x": 4,
- "Level1a": 5,
- "LEVEL1B": 6,
- "e": {
- "Level1a": 8,
- "Level1b": 9,
- "Level1c": 10,
- "Level1d": 11,
- "x": 12
- },
- "Loop1": 13,
- "Loop2": 14,
- "X": 15,
- "Y": 16,
- "Z": 17,
- "Q": 18,
- "extra": true
- }`,
- ptr: new(Top),
- err: fmt.Errorf("json: unknown field \"extra\""),
- disallowUnknownFields: true,
- },
- {
- in: `{
- "Level0": 1,
- "Level1b": 2,
- "Level1c": 3,
- "x": 4,
- "Level1a": 5,
- "LEVEL1B": 6,
- "e": {
- "Level1a": 8,
- "Level1b": 9,
- "Level1c": 10,
- "Level1d": 11,
- "x": 12,
- "extra": null
- },
- "Loop1": 13,
- "Loop2": 14,
- "X": 15,
- "Y": 16,
- "Z": 17,
- "Q": 18
- }`,
- ptr: new(Top),
- err: fmt.Errorf("json: unknown field \"extra\""),
- disallowUnknownFields: true,
- },
- // issue 26444
- // UnmarshalTypeError without field & struct values
- {
- in: `{"data":{"test1": "bob", "test2": 123}}`,
- ptr: new(mapStringToStringData),
- err: &UnmarshalTypeError{Value: "number", Type: reflect.TypeOf(""), Offset: 37, Struct: "mapStringToStringData", Field: "data"},
- },
- {
- in: `{"data":{"test1": 123, "test2": "bob"}}`,
- ptr: new(mapStringToStringData),
- err: &UnmarshalTypeError{Value: "number", Type: reflect.TypeOf(""), Offset: 21, Struct: "mapStringToStringData", Field: "data"},
- },
-
- // trying to decode JSON arrays or objects via TextUnmarshaler
- {
- in: `[1, 2, 3]`,
- ptr: new(MustNotUnmarshalText),
- err: &UnmarshalTypeError{Value: "array", Type: reflect.TypeOf(&MustNotUnmarshalText{}), Offset: 1},
- },
- {
- in: `{"foo": "bar"}`,
- ptr: new(MustNotUnmarshalText),
- err: &UnmarshalTypeError{Value: "object", Type: reflect.TypeOf(&MustNotUnmarshalText{}), Offset: 1},
- },
-}
-
-func TestMarshal(t *testing.T) {
- b, err := Marshal(allValue)
- if err != nil {
- t.Fatalf("Marshal allValue: %v", err)
- }
- if string(b) != allValueCompact {
- t.Errorf("Marshal allValueCompact")
- diff(t, b, []byte(allValueCompact))
- return
- }
-
- b, err = Marshal(pallValue)
- if err != nil {
- t.Fatalf("Marshal pallValue: %v", err)
- }
- if string(b) != pallValueCompact {
- t.Errorf("Marshal pallValueCompact")
- diff(t, b, []byte(pallValueCompact))
- return
- }
-}
-
-var badUTF8 = []struct {
- in, out string
-}{
- {"hello\xffworld", `"hello\ufffdworld"`},
- {"", `""`},
- {"\xff", `"\ufffd"`},
- {"\xff\xff", `"\ufffd\ufffd"`},
- {"a\xffb", `"a\ufffdb"`},
- {"\xe6\x97\xa5\xe6\x9c\xac\xff\xaa\x9e", `"日本\ufffd\ufffd\ufffd"`},
-}
-
-func TestMarshalBadUTF8(t *testing.T) {
- for _, tt := range badUTF8 {
- b, err := Marshal(tt.in)
- if string(b) != tt.out || err != nil {
- t.Errorf("Marshal(%q) = %#q, %v, want %#q, nil", tt.in, b, err, tt.out)
- }
- }
-}
-
-func TestMarshalNumberZeroVal(t *testing.T) {
- var n Number
- out, err := Marshal(n)
- if err != nil {
- t.Fatal(err)
- }
- outStr := string(out)
- if outStr != "0" {
- t.Fatalf("Invalid zero val for Number: %q", outStr)
- }
-}
-
-func TestMarshalEmbeds(t *testing.T) {
- top := &Top{
- Level0: 1,
- Embed0: Embed0{
- Level1b: 2,
- Level1c: 3,
- },
- Embed0a: &Embed0a{
- Level1a: 5,
- Level1b: 6,
- },
- Embed0b: &Embed0b{
- Level1a: 8,
- Level1b: 9,
- Level1c: 10,
- Level1d: 11,
- Level1e: 12,
- },
- Loop: Loop{
- Loop1: 13,
- Loop2: 14,
- },
- Embed0p: Embed0p{
- Point: image.Point{X: 15, Y: 16},
- },
- Embed0q: Embed0q{
- Point: Point{Z: 17},
- },
- embed: embed{
- Q: 18,
- },
- }
- b, err := Marshal(top)
- if err != nil {
- t.Fatal(err)
- }
- want := "{\"Level0\":1,\"Level1b\":2,\"Level1c\":3,\"Level1a\":5,\"LEVEL1B\":6,\"e\":{\"Level1a\":8,\"Level1b\":9,\"Level1c\":10,\"Level1d\":11,\"x\":12},\"Loop1\":13,\"Loop2\":14,\"X\":15,\"Y\":16,\"Z\":17,\"Q\":18}"
- if string(b) != want {
- t.Errorf("Wrong marshal result.\n got: %q\nwant: %q", b, want)
- }
-}
-
-func TestUnmarshal(t *testing.T) {
- for i, tt := range unmarshalTests {
- var scan scanner
- in := []byte(tt.in)
- if err := checkValid(in, &scan); err != nil {
- if !reflect.DeepEqual(err, tt.err) {
- t.Errorf("#%d: checkValid: %#v", i, err)
- continue
- }
- }
- if tt.ptr == nil {
- continue
- }
-
- // v = new(right-type)
- v := reflect.New(reflect.TypeOf(tt.ptr).Elem())
- dec := NewDecoder(bytes.NewReader(in))
- if tt.useNumber {
- dec.UseNumber()
- }
- if tt.disallowUnknownFields {
- dec.DisallowUnknownFields()
- }
- if err := dec.Decode(v.Interface()); !reflect.DeepEqual(err, tt.err) {
- t.Errorf("#%d: %v, want %v", i, err, tt.err)
- continue
- } else if err != nil {
- continue
- }
- if !reflect.DeepEqual(v.Elem().Interface(), tt.out) {
- t.Errorf("#%d: mismatch\nhave: %#+v\nwant: %#+v", i, v.Elem().Interface(), tt.out)
- data, _ := Marshal(v.Elem().Interface())
- println(string(data))
- data, _ = Marshal(tt.out)
- println(string(data))
- continue
- }
-
- // Check round trip also decodes correctly.
- if tt.err == nil {
- enc, err := Marshal(v.Interface())
- if err != nil {
- t.Errorf("#%d: error re-marshaling: %v", i, err)
- continue
- }
- if tt.golden && !bytes.Equal(enc, in) {
- t.Errorf("#%d: remarshal mismatch:\nhave: %s\nwant: %s", i, enc, in)
- }
- vv := reflect.New(reflect.TypeOf(tt.ptr).Elem())
- dec = NewDecoder(bytes.NewReader(enc))
- if tt.useNumber {
- dec.UseNumber()
- }
- if err := dec.Decode(vv.Interface()); err != nil {
- t.Errorf("#%d: error re-unmarshaling %#q: %v", i, enc, err)
- continue
- }
- if !reflect.DeepEqual(v.Elem().Interface(), vv.Elem().Interface()) {
- t.Errorf("#%d: mismatch\nhave: %#+v\nwant: %#+v", i, v.Elem().Interface(), vv.Elem().Interface())
- t.Errorf(" In: %q", strings.Map(noSpace, string(in)))
- t.Errorf("Marshal: %q", strings.Map(noSpace, string(enc)))
- continue
- }
- }
- }
-}
-
-func TestUnmarshalMarshal(t *testing.T) {
- initBig()
- var v interface{}
- if err := Unmarshal(jsonBig, &v); err != nil {
- t.Fatalf("Unmarshal: %v", err)
- }
- b, err := Marshal(v)
- if err != nil {
- t.Fatalf("Marshal: %v", err)
- }
- if !bytes.Equal(jsonBig, b) {
- t.Errorf("Marshal jsonBig")
- diff(t, b, jsonBig)
- return
- }
-}
-
-var numberTests = []struct {
- in string
- i int64
- intErr string
- f float64
- floatErr string
-}{
- {in: "-1.23e1", intErr: "strconv.ParseInt: parsing \"-1.23e1\": invalid syntax", f: -1.23e1},
- {in: "-12", i: -12, f: -12.0},
- {in: "1e1000", intErr: "strconv.ParseInt: parsing \"1e1000\": invalid syntax", floatErr: "strconv.ParseFloat: parsing \"1e1000\": value out of range"},
-}
-
-// Independent of Decode, basic coverage of the accessors in Number
-func TestNumberAccessors(t *testing.T) {
- for _, tt := range numberTests {
- n := Number(tt.in)
- if s := n.String(); s != tt.in {
- t.Errorf("Number(%q).String() is %q", tt.in, s)
- }
- if i, err := n.Int64(); err == nil && tt.intErr == "" && i != tt.i {
- t.Errorf("Number(%q).Int64() is %d", tt.in, i)
- } else if (err == nil && tt.intErr != "") || (err != nil && err.Error() != tt.intErr) {
- t.Errorf("Number(%q).Int64() wanted error %q but got: %v", tt.in, tt.intErr, err)
- }
- if f, err := n.Float64(); err == nil && tt.floatErr == "" && f != tt.f {
- t.Errorf("Number(%q).Float64() is %g", tt.in, f)
- } else if (err == nil && tt.floatErr != "") || (err != nil && err.Error() != tt.floatErr) {
- t.Errorf("Number(%q).Float64() wanted error %q but got: %v", tt.in, tt.floatErr, err)
- }
- }
-}
-
-func TestLargeByteSlice(t *testing.T) {
- s0 := make([]byte, 2000)
- for i := range s0 {
- s0[i] = byte(i)
- }
- b, err := Marshal(s0)
- if err != nil {
- t.Fatalf("Marshal: %v", err)
- }
- var s1 []byte
- if err := Unmarshal(b, &s1); err != nil {
- t.Fatalf("Unmarshal: %v", err)
- }
- if !bytes.Equal(s0, s1) {
- t.Errorf("Marshal large byte slice")
- diff(t, s0, s1)
- }
-}
-
-type Xint struct {
- X int
-}
-
-func TestUnmarshalInterface(t *testing.T) {
- var xint Xint
- var i interface{} = &xint
- if err := Unmarshal([]byte(`{"X":1}`), &i); err != nil {
- t.Fatalf("Unmarshal: %v", err)
- }
- if xint.X != 1 {
- t.Fatalf("Did not write to xint")
- }
-}
-
-func TestUnmarshalPtrPtr(t *testing.T) {
- var xint Xint
- pxint := &xint
- if err := Unmarshal([]byte(`{"X":1}`), &pxint); err != nil {
- t.Fatalf("Unmarshal: %v", err)
- }
- if xint.X != 1 {
- t.Fatalf("Did not write to xint")
- }
-}
-
-func TestEscape(t *testing.T) {
- const input = `"foobar"` + " [\u2028 \u2029]"
- const expected = `"\"foobar\"\u003chtml\u003e [\u2028 \u2029]"`
- b, err := Marshal(input)
- if err != nil {
- t.Fatalf("Marshal error: %v", err)
- }
- if s := string(b); s != expected {
- t.Errorf("Encoding of [%s]:\n got [%s]\nwant [%s]", input, s, expected)
- }
-}
-
-// WrongString is a struct that's misusing the ,string modifier.
-type WrongString struct {
- Message string `json:"result,string"`
-}
-
-type wrongStringTest struct {
- in, err string
-}
-
-var wrongStringTests = []wrongStringTest{
- {`{"result":"x"}`, `json: invalid use of ,string struct tag, trying to unmarshal "x" into string`},
- {`{"result":"foo"}`, `json: invalid use of ,string struct tag, trying to unmarshal "foo" into string`},
- {`{"result":"123"}`, `json: invalid use of ,string struct tag, trying to unmarshal "123" into string`},
- {`{"result":123}`, `json: invalid use of ,string struct tag, trying to unmarshal unquoted value into string`},
-}
-
-// If people misuse the ,string modifier, the error message should be
-// helpful, telling the user that they're doing it wrong.
-func TestErrorMessageFromMisusedString(t *testing.T) {
- for n, tt := range wrongStringTests {
- r := strings.NewReader(tt.in)
- var s WrongString
- err := NewDecoder(r).Decode(&s)
- got := fmt.Sprintf("%v", err)
- if got != tt.err {
- t.Errorf("%d. got err = %q, want %q", n, got, tt.err)
- }
- }
-}
-
-func noSpace(c rune) rune {
- if isSpace(byte(c)) { //only used for ascii
- return -1
- }
- return c
-}
-
-type All struct {
- Bool bool
- Int int
- Int8 int8
- Int16 int16
- Int32 int32
- Int64 int64
- Uint uint
- Uint8 uint8
- Uint16 uint16
- Uint32 uint32
- Uint64 uint64
- Uintptr uintptr
- Float32 float32
- Float64 float64
-
- Foo string `json:"bar"`
- Foo2 string `json:"bar2,dummyopt"`
-
- IntStr int64 `json:",string"`
- UintptrStr uintptr `json:",string"`
-
- PBool *bool
- PInt *int
- PInt8 *int8
- PInt16 *int16
- PInt32 *int32
- PInt64 *int64
- PUint *uint
- PUint8 *uint8
- PUint16 *uint16
- PUint32 *uint32
- PUint64 *uint64
- PUintptr *uintptr
- PFloat32 *float32
- PFloat64 *float64
-
- String string
- PString *string
-
- Map map[string]Small
- MapP map[string]*Small
- PMap *map[string]Small
- PMapP *map[string]*Small
-
- EmptyMap map[string]Small
- NilMap map[string]Small
-
- Slice []Small
- SliceP []*Small
- PSlice *[]Small
- PSliceP *[]*Small
-
- EmptySlice []Small
- NilSlice []Small
-
- StringSlice []string
- ByteSlice []byte
-
- Small Small
- PSmall *Small
- PPSmall **Small
-
- Interface interface{}
- PInterface *interface{}
-
- unexported int
-}
-
-type Small struct {
- Tag string
-}
-
-var allValue = All{
- Bool: true,
- Int: 2,
- Int8: 3,
- Int16: 4,
- Int32: 5,
- Int64: 6,
- Uint: 7,
- Uint8: 8,
- Uint16: 9,
- Uint32: 10,
- Uint64: 11,
- Uintptr: 12,
- Float32: 14.1,
- Float64: 15.1,
- Foo: "foo",
- Foo2: "foo2",
- IntStr: 42,
- UintptrStr: 44,
- String: "16",
- Map: map[string]Small{
- "17": {Tag: "tag17"},
- "18": {Tag: "tag18"},
- },
- MapP: map[string]*Small{
- "19": {Tag: "tag19"},
- "20": nil,
- },
- EmptyMap: map[string]Small{},
- Slice: []Small{{Tag: "tag20"}, {Tag: "tag21"}},
- SliceP: []*Small{{Tag: "tag22"}, nil, {Tag: "tag23"}},
- EmptySlice: []Small{},
- StringSlice: []string{"str24", "str25", "str26"},
- ByteSlice: []byte{27, 28, 29},
- Small: Small{Tag: "tag30"},
- PSmall: &Small{Tag: "tag31"},
- Interface: 5.2,
-}
-
-var pallValue = All{
- PBool: &allValue.Bool,
- PInt: &allValue.Int,
- PInt8: &allValue.Int8,
- PInt16: &allValue.Int16,
- PInt32: &allValue.Int32,
- PInt64: &allValue.Int64,
- PUint: &allValue.Uint,
- PUint8: &allValue.Uint8,
- PUint16: &allValue.Uint16,
- PUint32: &allValue.Uint32,
- PUint64: &allValue.Uint64,
- PUintptr: &allValue.Uintptr,
- PFloat32: &allValue.Float32,
- PFloat64: &allValue.Float64,
- PString: &allValue.String,
- PMap: &allValue.Map,
- PMapP: &allValue.MapP,
- PSlice: &allValue.Slice,
- PSliceP: &allValue.SliceP,
- PPSmall: &allValue.PSmall,
- PInterface: &allValue.Interface,
-}
-
-var allValueIndent = `{
- "Bool": true,
- "Int": 2,
- "Int8": 3,
- "Int16": 4,
- "Int32": 5,
- "Int64": 6,
- "Uint": 7,
- "Uint8": 8,
- "Uint16": 9,
- "Uint32": 10,
- "Uint64": 11,
- "Uintptr": 12,
- "Float32": 14.1,
- "Float64": 15.1,
- "bar": "foo",
- "bar2": "foo2",
- "IntStr": "42",
- "UintptrStr": "44",
- "PBool": null,
- "PInt": null,
- "PInt8": null,
- "PInt16": null,
- "PInt32": null,
- "PInt64": null,
- "PUint": null,
- "PUint8": null,
- "PUint16": null,
- "PUint32": null,
- "PUint64": null,
- "PUintptr": null,
- "PFloat32": null,
- "PFloat64": null,
- "String": "16",
- "PString": null,
- "Map": {
- "17": {
- "Tag": "tag17"
- },
- "18": {
- "Tag": "tag18"
- }
- },
- "MapP": {
- "19": {
- "Tag": "tag19"
- },
- "20": null
- },
- "PMap": null,
- "PMapP": null,
- "EmptyMap": {},
- "NilMap": null,
- "Slice": [
- {
- "Tag": "tag20"
- },
- {
- "Tag": "tag21"
- }
- ],
- "SliceP": [
- {
- "Tag": "tag22"
- },
- null,
- {
- "Tag": "tag23"
- }
- ],
- "PSlice": null,
- "PSliceP": null,
- "EmptySlice": [],
- "NilSlice": null,
- "StringSlice": [
- "str24",
- "str25",
- "str26"
- ],
- "ByteSlice": "A79E",
- "Small": {
- "Tag": "tag30"
- },
- "PSmall": {
- "Tag": "tag31"
- },
- "PPSmall": null,
- "Interface": 5.2,
- "PInterface": null
-}`
-
-var allValueCompact = strings.Map(noSpace, allValueIndent)
-
-var pallValueIndent = `{
- "Bool": false,
- "Int": 0,
- "Int8": 0,
- "Int16": 0,
- "Int32": 0,
- "Int64": 0,
- "Uint": 0,
- "Uint8": 0,
- "Uint16": 0,
- "Uint32": 0,
- "Uint64": 0,
- "Uintptr": 0,
- "Float32": 0,
- "Float64": 0,
- "bar": "",
- "bar2": "",
- "IntStr": "0",
- "UintptrStr": "0",
- "PBool": true,
- "PInt": 2,
- "PInt8": 3,
- "PInt16": 4,
- "PInt32": 5,
- "PInt64": 6,
- "PUint": 7,
- "PUint8": 8,
- "PUint16": 9,
- "PUint32": 10,
- "PUint64": 11,
- "PUintptr": 12,
- "PFloat32": 14.1,
- "PFloat64": 15.1,
- "String": "",
- "PString": "16",
- "Map": null,
- "MapP": null,
- "PMap": {
- "17": {
- "Tag": "tag17"
- },
- "18": {
- "Tag": "tag18"
- }
- },
- "PMapP": {
- "19": {
- "Tag": "tag19"
- },
- "20": null
- },
- "EmptyMap": null,
- "NilMap": null,
- "Slice": null,
- "SliceP": null,
- "PSlice": [
- {
- "Tag": "tag20"
- },
- {
- "Tag": "tag21"
- }
- ],
- "PSliceP": [
- {
- "Tag": "tag22"
- },
- null,
- {
- "Tag": "tag23"
- }
- ],
- "EmptySlice": null,
- "NilSlice": null,
- "StringSlice": null,
- "ByteSlice": null,
- "Small": {
- "Tag": ""
- },
- "PSmall": null,
- "PPSmall": {
- "Tag": "tag31"
- },
- "Interface": null,
- "PInterface": 5.2
-}`
-
-var pallValueCompact = strings.Map(noSpace, pallValueIndent)
-
-func TestRefUnmarshal(t *testing.T) {
- type S struct {
- // Ref is defined in encode_test.go.
- R0 Ref
- R1 *Ref
- R2 RefText
- R3 *RefText
- }
- want := S{
- R0: 12,
- R1: new(Ref),
- R2: 13,
- R3: new(RefText),
- }
- *want.R1 = 12
- *want.R3 = 13
-
- var got S
- if err := Unmarshal([]byte(`{"R0":"ref","R1":"ref","R2":"ref","R3":"ref"}`), &got); err != nil {
- t.Fatalf("Unmarshal: %v", err)
- }
- if !reflect.DeepEqual(got, want) {
- t.Errorf("got %+v, want %+v", got, want)
- }
-}
-
-// Test that the empty string doesn't panic decoding when ,string is specified
-// Issue 3450
-func TestEmptyString(t *testing.T) {
- type T2 struct {
- Number1 int `json:",string"`
- Number2 int `json:",string"`
- }
- data := `{"Number1":"1", "Number2":""}`
- dec := NewDecoder(strings.NewReader(data))
- var t2 T2
- err := dec.Decode(&t2)
- if err == nil {
- t.Fatal("Decode: did not return error")
- }
- if t2.Number1 != 1 {
- t.Fatal("Decode: did not set Number1")
- }
-}
-
-// Test that a null for ,string is not replaced with the previous quoted string (issue 7046).
-// It should also not be an error (issue 2540, issue 8587).
-func TestNullString(t *testing.T) {
- type T struct {
- A int `json:",string"`
- B int `json:",string"`
- C *int `json:",string"`
- }
- data := []byte(`{"A": "1", "B": null, "C": null}`)
- var s T
- s.B = 1
- s.C = new(int)
- *s.C = 2
- err := Unmarshal(data, &s)
- if err != nil {
- t.Fatalf("Unmarshal: %v", err)
- }
- if s.B != 1 || s.C != nil {
- t.Fatalf("after Unmarshal, s.B=%d, s.C=%p, want 1, nil", s.B, s.C)
- }
-}
-
-func intp(x int) *int {
- p := new(int)
- *p = x
- return p
-}
-
-func intpp(x *int) **int {
- pp := new(*int)
- *pp = x
- return pp
-}
-
-var interfaceSetTests = []struct {
- pre interface{}
- json string
- post interface{}
-}{
- {"foo", `"bar"`, "bar"},
- {"foo", `2`, 2.0},
- {"foo", `true`, true},
- {"foo", `null`, nil},
-
- {nil, `null`, nil},
- {new(int), `null`, nil},
- {(*int)(nil), `null`, nil},
- {new(*int), `null`, new(*int)},
- {(**int)(nil), `null`, nil},
- {intp(1), `null`, nil},
- {intpp(nil), `null`, intpp(nil)},
- {intpp(intp(1)), `null`, intpp(nil)},
-}
-
-func TestInterfaceSet(t *testing.T) {
- for _, tt := range interfaceSetTests {
- b := struct{ X interface{} }{tt.pre}
- blob := `{"X":` + tt.json + `}`
- if err := Unmarshal([]byte(blob), &b); err != nil {
- t.Errorf("Unmarshal %#q: %v", blob, err)
- continue
- }
- if !reflect.DeepEqual(b.X, tt.post) {
- t.Errorf("Unmarshal %#q into %#v: X=%#v, want %#v", blob, tt.pre, b.X, tt.post)
- }
- }
-}
-
-type NullTest struct {
- Bool bool
- Int int
- Int8 int8
- Int16 int16
- Int32 int32
- Int64 int64
- Uint uint
- Uint8 uint8
- Uint16 uint16
- Uint32 uint32
- Uint64 uint64
- Float32 float32
- Float64 float64
- String string
- PBool *bool
- Map map[string]string
- Slice []string
- Interface interface{}
-
- PRaw *RawMessage
- PTime *time.Time
- PBigInt *big.Int
- PText *MustNotUnmarshalText
- PBuffer *bytes.Buffer // has methods, just not relevant ones
- PStruct *struct{}
-
- Raw RawMessage
- Time time.Time
- BigInt big.Int
- Text MustNotUnmarshalText
- Buffer bytes.Buffer
- Struct struct{}
-}
-
-type NullTestStrings struct {
- Bool bool `json:",string"`
- Int int `json:",string"`
- Int8 int8 `json:",string"`
- Int16 int16 `json:",string"`
- Int32 int32 `json:",string"`
- Int64 int64 `json:",string"`
- Uint uint `json:",string"`
- Uint8 uint8 `json:",string"`
- Uint16 uint16 `json:",string"`
- Uint32 uint32 `json:",string"`
- Uint64 uint64 `json:",string"`
- Float32 float32 `json:",string"`
- Float64 float64 `json:",string"`
- String string `json:",string"`
- PBool *bool `json:",string"`
- Map map[string]string `json:",string"`
- Slice []string `json:",string"`
- Interface interface{} `json:",string"`
-
- PRaw *RawMessage `json:",string"`
- PTime *time.Time `json:",string"`
- PBigInt *big.Int `json:",string"`
- PText *MustNotUnmarshalText `json:",string"`
- PBuffer *bytes.Buffer `json:",string"`
- PStruct *struct{} `json:",string"`
-
- Raw RawMessage `json:",string"`
- Time time.Time `json:",string"`
- BigInt big.Int `json:",string"`
- Text MustNotUnmarshalText `json:",string"`
- Buffer bytes.Buffer `json:",string"`
- Struct struct{} `json:",string"`
-}
-
-// JSON null values should be ignored for primitives and string values instead of resulting in an error.
-// Issue 2540
-func TestUnmarshalNulls(t *testing.T) {
- // Unmarshal docs:
- // The JSON null value unmarshals into an interface, map, pointer, or slice
- // by setting that Go value to nil. Because null is often used in JSON to mean
- // ``not present,'' unmarshaling a JSON null into any other Go type has no effect
- // on the value and produces no error.
-
- jsonData := []byte(`{
- "Bool" : null,
- "Int" : null,
- "Int8" : null,
- "Int16" : null,
- "Int32" : null,
- "Int64" : null,
- "Uint" : null,
- "Uint8" : null,
- "Uint16" : null,
- "Uint32" : null,
- "Uint64" : null,
- "Float32" : null,
- "Float64" : null,
- "String" : null,
- "PBool": null,
- "Map": null,
- "Slice": null,
- "Interface": null,
- "PRaw": null,
- "PTime": null,
- "PBigInt": null,
- "PText": null,
- "PBuffer": null,
- "PStruct": null,
- "Raw": null,
- "Time": null,
- "BigInt": null,
- "Text": null,
- "Buffer": null,
- "Struct": null
- }`)
- nulls := NullTest{
- Bool: true,
- Int: 2,
- Int8: 3,
- Int16: 4,
- Int32: 5,
- Int64: 6,
- Uint: 7,
- Uint8: 8,
- Uint16: 9,
- Uint32: 10,
- Uint64: 11,
- Float32: 12.1,
- Float64: 13.1,
- String: "14",
- PBool: new(bool),
- Map: map[string]string{},
- Slice: []string{},
- Interface: new(MustNotUnmarshalJSON),
- PRaw: new(RawMessage),
- PTime: new(time.Time),
- PBigInt: new(big.Int),
- PText: new(MustNotUnmarshalText),
- PStruct: new(struct{}),
- PBuffer: new(bytes.Buffer),
- Raw: RawMessage("123"),
- Time: time.Unix(123456789, 0),
- BigInt: *big.NewInt(123),
- }
-
- before := nulls.Time.String()
-
- err := Unmarshal(jsonData, &nulls)
- if err != nil {
- t.Errorf("Unmarshal of null values failed: %v", err)
- }
- if !nulls.Bool || nulls.Int != 2 || nulls.Int8 != 3 || nulls.Int16 != 4 || nulls.Int32 != 5 || nulls.Int64 != 6 ||
- nulls.Uint != 7 || nulls.Uint8 != 8 || nulls.Uint16 != 9 || nulls.Uint32 != 10 || nulls.Uint64 != 11 ||
- nulls.Float32 != 12.1 || nulls.Float64 != 13.1 || nulls.String != "14" {
- t.Errorf("Unmarshal of null values affected primitives")
- }
-
- if nulls.PBool != nil {
- t.Errorf("Unmarshal of null did not clear nulls.PBool")
- }
- if nulls.Map != nil {
- t.Errorf("Unmarshal of null did not clear nulls.Map")
- }
- if nulls.Slice != nil {
- t.Errorf("Unmarshal of null did not clear nulls.Slice")
- }
- if nulls.Interface != nil {
- t.Errorf("Unmarshal of null did not clear nulls.Interface")
- }
- if nulls.PRaw != nil {
- t.Errorf("Unmarshal of null did not clear nulls.PRaw")
- }
- if nulls.PTime != nil {
- t.Errorf("Unmarshal of null did not clear nulls.PTime")
- }
- if nulls.PBigInt != nil {
- t.Errorf("Unmarshal of null did not clear nulls.PBigInt")
- }
- if nulls.PText != nil {
- t.Errorf("Unmarshal of null did not clear nulls.PText")
- }
- if nulls.PBuffer != nil {
- t.Errorf("Unmarshal of null did not clear nulls.PBuffer")
- }
- if nulls.PStruct != nil {
- t.Errorf("Unmarshal of null did not clear nulls.PStruct")
- }
-
- if string(nulls.Raw) != "null" {
- t.Errorf("Unmarshal of RawMessage null did not record null: %v", string(nulls.Raw))
- }
- if nulls.Time.String() != before {
- t.Errorf("Unmarshal of time.Time null set time to %v", nulls.Time.String())
- }
- if nulls.BigInt.String() != "123" {
- t.Errorf("Unmarshal of big.Int null set int to %v", nulls.BigInt.String())
- }
-}
-
-type MustNotUnmarshalJSON struct{}
-
-func (x MustNotUnmarshalJSON) UnmarshalJSON(data []byte) error {
- return errors.New("MustNotUnmarshalJSON was used")
-}
-
-type MustNotUnmarshalText struct{}
-
-func (x MustNotUnmarshalText) UnmarshalText(text []byte) error {
- return errors.New("MustNotUnmarshalText was used")
-}
-
-func TestStringKind(t *testing.T) {
- type stringKind string
-
- var m1, m2 map[stringKind]int
- m1 = map[stringKind]int{
- "foo": 42,
- }
-
- data, err := Marshal(m1)
- if err != nil {
- t.Errorf("Unexpected error marshaling: %v", err)
- }
-
- err = Unmarshal(data, &m2)
- if err != nil {
- t.Errorf("Unexpected error unmarshaling: %v", err)
- }
-
- if !reflect.DeepEqual(m1, m2) {
- t.Error("Items should be equal after encoding and then decoding")
- }
-}
-
-// Custom types with []byte as underlying type could not be marshaled
-// and then unmarshaled.
-// Issue 8962.
-func TestByteKind(t *testing.T) {
- type byteKind []byte
-
- a := byteKind("hello")
-
- data, err := Marshal(a)
- if err != nil {
- t.Error(err)
- }
- var b byteKind
- err = Unmarshal(data, &b)
- if err != nil {
- t.Fatal(err)
- }
- if !reflect.DeepEqual(a, b) {
- t.Errorf("expected %v == %v", a, b)
- }
-}
-
-// The fix for issue 8962 introduced a regression.
-// Issue 12921.
-func TestSliceOfCustomByte(t *testing.T) {
- type Uint8 uint8
-
- a := []Uint8("hello")
-
- data, err := Marshal(a)
- if err != nil {
- t.Fatal(err)
- }
- var b []Uint8
- err = Unmarshal(data, &b)
- if err != nil {
- t.Fatal(err)
- }
- if !reflect.DeepEqual(a, b) {
- t.Fatalf("expected %v == %v", a, b)
- }
-}
-
-var decodeTypeErrorTests = []struct {
- dest interface{}
- src string
-}{
- {new(string), `{"user": "name"}`}, // issue 4628.
- {new(error), `{}`}, // issue 4222
- {new(error), `[]`},
- {new(error), `""`},
- {new(error), `123`},
- {new(error), `true`},
-}
-
-func TestUnmarshalTypeError(t *testing.T) {
- for _, item := range decodeTypeErrorTests {
- err := Unmarshal([]byte(item.src), item.dest)
- if _, ok := err.(*UnmarshalTypeError); !ok {
- t.Errorf("expected type error for Unmarshal(%q, type %T): got %T",
- item.src, item.dest, err)
- }
- }
-}
-
-var unmarshalSyntaxTests = []string{
- "tru",
- "fals",
- "nul",
- "123e",
- `"hello`,
- `[1,2,3`,
- `{"key":1`,
- `{"key":1,`,
-}
-
-func TestUnmarshalSyntax(t *testing.T) {
- var x interface{}
- for _, src := range unmarshalSyntaxTests {
- err := Unmarshal([]byte(src), &x)
- if _, ok := err.(*SyntaxError); !ok {
- t.Errorf("expected syntax error for Unmarshal(%q): got %T", src, err)
- }
- }
-}
-
-// Test handling of unexported fields that should be ignored.
-// Issue 4660
-type unexportedFields struct {
- Name string
- m map[string]interface{} `json:"-"`
- m2 map[string]interface{} `json:"abcd"`
-
- s []int `json:"-"`
-}
-
-func TestUnmarshalUnexported(t *testing.T) {
- input := `{"Name": "Bob", "m": {"x": 123}, "m2": {"y": 456}, "abcd": {"z": 789}, "s": [2, 3]}`
- want := &unexportedFields{Name: "Bob"}
-
- out := &unexportedFields{}
- err := Unmarshal([]byte(input), out)
- if err != nil {
- t.Errorf("got error %v, expected nil", err)
- }
- if !reflect.DeepEqual(out, want) {
- t.Errorf("got %q, want %q", out, want)
- }
-}
-
-// Time3339 is a time.Time which encodes to and from JSON
-// as an RFC 3339 time in UTC.
-type Time3339 time.Time
-
-func (t *Time3339) UnmarshalJSON(b []byte) error {
- if len(b) < 2 || b[0] != '"' || b[len(b)-1] != '"' {
- return fmt.Errorf("types: failed to unmarshal non-string value %q as an RFC 3339 time", b)
- }
- tm, err := time.Parse(time.RFC3339, string(b[1:len(b)-1]))
- if err != nil {
- return err
- }
- *t = Time3339(tm)
- return nil
-}
-
-func TestUnmarshalJSONLiteralError(t *testing.T) {
- var t3 Time3339
- err := Unmarshal([]byte(`"0000-00-00T00:00:00Z"`), &t3)
- if err == nil {
- t.Fatalf("expected error; got time %v", time.Time(t3))
- }
- if !strings.Contains(err.Error(), "range") {
- t.Errorf("got err = %v; want out of range error", err)
- }
-}
-
-// Test that extra object elements in an array do not result in a
-// "data changing underfoot" error.
-// Issue 3717
-func TestSkipArrayObjects(t *testing.T) {
- json := `[{}]`
- var dest [0]interface{}
-
- err := Unmarshal([]byte(json), &dest)
- if err != nil {
- t.Errorf("got error %q, want nil", err)
- }
-}
-
-// Test semantics of pre-filled struct fields and pre-filled map fields.
-// Issue 4900.
-func TestPrefilled(t *testing.T) {
- ptrToMap := func(m map[string]interface{}) *map[string]interface{} { return &m }
-
- // Values here change, cannot reuse table across runs.
- var prefillTests = []struct {
- in string
- ptr interface{}
- out interface{}
- }{
- {
- in: `{"X": 1, "Y": 2}`,
- ptr: &XYZ{X: float32(3), Y: int16(4), Z: 1.5},
- out: &XYZ{X: float64(1), Y: float64(2), Z: 1.5},
- },
- {
- in: `{"X": 1, "Y": 2}`,
- ptr: ptrToMap(map[string]interface{}{"X": float32(3), "Y": int16(4), "Z": 1.5}),
- out: ptrToMap(map[string]interface{}{"X": float64(1), "Y": float64(2), "Z": 1.5}),
- },
- }
-
- for _, tt := range prefillTests {
- ptrstr := fmt.Sprintf("%v", tt.ptr)
- err := Unmarshal([]byte(tt.in), tt.ptr) // tt.ptr edited here
- if err != nil {
- t.Errorf("Unmarshal: %v", err)
- }
- if !reflect.DeepEqual(tt.ptr, tt.out) {
- t.Errorf("Unmarshal(%#q, %s): have %v, want %v", tt.in, ptrstr, tt.ptr, tt.out)
- }
- }
-}
-
-var invalidUnmarshalTests = []struct {
- v interface{}
- want string
-}{
- {nil, "json: Unmarshal(nil)"},
- {struct{}{}, "json: Unmarshal(non-pointer struct {})"},
- {(*int)(nil), "json: Unmarshal(nil *int)"},
-}
-
-func TestInvalidUnmarshal(t *testing.T) {
- buf := []byte(`{"a":"1"}`)
- for _, tt := range invalidUnmarshalTests {
- err := Unmarshal(buf, tt.v)
- if err == nil {
- t.Errorf("Unmarshal expecting error, got nil")
- continue
- }
- if got := err.Error(); got != tt.want {
- t.Errorf("Unmarshal = %q; want %q", got, tt.want)
- }
- }
-}
-
-var invalidUnmarshalTextTests = []struct {
- v interface{}
- want string
-}{
- {nil, "json: Unmarshal(nil)"},
- {struct{}{}, "json: Unmarshal(non-pointer struct {})"},
- {(*int)(nil), "json: Unmarshal(nil *int)"},
- {new(net.IP), "json: cannot unmarshal number into Go value of type *net.IP"},
-}
-
-func TestInvalidUnmarshalText(t *testing.T) {
- buf := []byte(`123`)
- for _, tt := range invalidUnmarshalTextTests {
- err := Unmarshal(buf, tt.v)
- if err == nil {
- t.Errorf("Unmarshal expecting error, got nil")
- continue
- }
- if got := err.Error(); got != tt.want {
- t.Errorf("Unmarshal = %q; want %q", got, tt.want)
- }
- }
-}
-
-// Test that string option is ignored for invalid types.
-// Issue 9812.
-func TestInvalidStringOption(t *testing.T) {
- num := 0
- item := struct {
- T time.Time `json:",string"`
- M map[string]string `json:",string"`
- S []string `json:",string"`
- A [1]string `json:",string"`
- I interface{} `json:",string"`
- P *int `json:",string"`
- }{M: make(map[string]string), S: make([]string, 0), I: num, P: &num}
-
- data, err := Marshal(item)
- if err != nil {
- t.Fatalf("Marshal: %v", err)
- }
-
- err = Unmarshal(data, &item)
- if err != nil {
- t.Fatalf("Unmarshal: %v", err)
- }
-}
-
-// Test unmarshal behavior with regards to embedded unexported structs.
-//
-// (Issue 21357) If the embedded struct is a pointer and is unallocated,
-// this returns an error because unmarshal cannot set the field.
-//
-// (Issue 24152) If the embedded struct is given an explicit name,
-// ensure that the normal unmarshal logic does not panic in reflect.
-func TestUnmarshalEmbeddedUnexported(t *testing.T) {
- type (
- embed1 struct{ Q int }
- embed2 struct{ Q int }
- embed3 struct {
- Q int64 `json:",string"`
- }
- S1 struct {
- *embed1
- R int
- }
- S2 struct {
- *embed1
- Q int
- }
- S3 struct {
- embed1
- R int
- }
- S4 struct {
- *embed1
- embed2
- }
- S5 struct {
- *embed3
- R int
- }
- S6 struct {
- embed1 `json:"embed1"`
- }
- S7 struct {
- embed1 `json:"embed1"`
- embed2
- }
- S8 struct {
- embed1 `json:"embed1"`
- embed2 `json:"embed2"`
- Q int
- }
- )
-
- tests := []struct {
- in string
- ptr interface{}
- out interface{}
- err error
- }{{
- // Error since we cannot set S1.embed1, but still able to set S1.R.
- in: `{"R":2,"Q":1}`,
- ptr: new(S1),
- out: &S1{R: 2},
- err: fmt.Errorf("json: cannot set embedded pointer to unexported struct: json.embed1"),
- }, {
- // The top level Q field takes precedence.
- in: `{"Q":1}`,
- ptr: new(S2),
- out: &S2{Q: 1},
- }, {
- // No issue with non-pointer variant.
- in: `{"R":2,"Q":1}`,
- ptr: new(S3),
- out: &S3{embed1: embed1{Q: 1}, R: 2},
- }, {
- // No error since both embedded structs have field R, which annihilate each other.
- // Thus, no attempt is made at setting S4.embed1.
- in: `{"R":2}`,
- ptr: new(S4),
- out: new(S4),
- }, {
- // Error since we cannot set S5.embed1, but still able to set S5.R.
- in: `{"R":2,"Q":1}`,
- ptr: new(S5),
- out: &S5{R: 2},
- err: fmt.Errorf("json: cannot set embedded pointer to unexported struct: json.embed3"),
- }, {
- // Issue 24152, ensure decodeState.indirect does not panic.
- in: `{"embed1": {"Q": 1}}`,
- ptr: new(S6),
- out: &S6{embed1{1}},
- }, {
- // Issue 24153, check that we can still set forwarded fields even in
- // the presence of a name conflict.
- //
- // This relies on obscure behavior of reflect where it is possible
- // to set a forwarded exported field on an unexported embedded struct
- // even though there is a name conflict, even when it would have been
- // impossible to do so according to Go visibility rules.
- // Go forbids this because it is ambiguous whether S7.Q refers to
- // S7.embed1.Q or S7.embed2.Q. Since embed1 and embed2 are unexported,
- // it should be impossible for an external package to set either Q.
- //
- // It is probably okay for a future reflect change to break this.
- in: `{"embed1": {"Q": 1}, "Q": 2}`,
- ptr: new(S7),
- out: &S7{embed1{1}, embed2{2}},
- }, {
- // Issue 24153, similar to the S7 case.
- in: `{"embed1": {"Q": 1}, "embed2": {"Q": 2}, "Q": 3}`,
- ptr: new(S8),
- out: &S8{embed1{1}, embed2{2}, 3},
- }}
-
- for i, tt := range tests {
- err := Unmarshal([]byte(tt.in), tt.ptr)
- if !reflect.DeepEqual(err, tt.err) {
- t.Errorf("#%d: %v, want %v", i, err, tt.err)
- }
- if !reflect.DeepEqual(tt.ptr, tt.out) {
- t.Errorf("#%d: mismatch\ngot: %#+v\nwant: %#+v", i, tt.ptr, tt.out)
- }
- }
-}
-
-type unmarshalPanic struct{}
-
-func (unmarshalPanic) UnmarshalJSON([]byte) error { panic(0xdead) }
-
-func TestUnmarshalPanic(t *testing.T) {
- defer func() {
- if got := recover(); !reflect.DeepEqual(got, 0xdead) {
- t.Errorf("panic() = (%T)(%v), want 0xdead", got, got)
- }
- }()
- Unmarshal([]byte("{}"), &unmarshalPanic{})
- t.Fatalf("Unmarshal should have panicked")
-}
diff --git a/cmd/aergocli/util/encoding/json/encode.go b/cmd/aergocli/util/encoding/json/encode.go
deleted file mode 100644
index 26b0c472a..000000000
--- a/cmd/aergocli/util/encoding/json/encode.go
+++ /dev/null
@@ -1,1253 +0,0 @@
-// Copyright 2010 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package json implements encoding and decoding of JSON as defined in
-// RFC 7159. The mapping between JSON and Go values is described
-// in the documentation for the Marshal and Unmarshal functions.
-//
-// See "JSON and Go" for an introduction to this package:
-// https://golang.org/doc/articles/json_and_go.html
-package json
-
-import (
- "bytes"
- "encoding"
- "fmt"
- "math"
- "reflect"
- "sort"
- "strconv"
- "strings"
- "sync"
- "unicode"
- "unicode/utf8"
-
- "github.com/aergoio/aergo/v2/internal/enc/base58"
-)
-
-// Marshal returns the JSON encoding of v.
-//
-// Marshal traverses the value v recursively.
-// If an encountered value implements the Marshaler interface
-// and is not a nil pointer, Marshal calls its MarshalJSON method
-// to produce JSON. If no MarshalJSON method is present but the
-// value implements encoding.TextMarshaler instead, Marshal calls
-// its MarshalText method and encodes the result as a JSON string.
-// The nil pointer exception is not strictly necessary
-// but mimics a similar, necessary exception in the behavior of
-// UnmarshalJSON.
-//
-// Otherwise, Marshal uses the following type-dependent default encodings:
-//
-// Boolean values encode as JSON booleans.
-//
-// Floating point, integer, and Number values encode as JSON numbers.
-//
-// String values encode as JSON strings coerced to valid UTF-8,
-// replacing invalid bytes with the Unicode replacement rune.
-// The angle brackets "<" and ">" are escaped to "\u003c" and "\u003e"
-// to keep some browsers from misinterpreting JSON output as HTML.
-// Ampersand "&" is also escaped to "\u0026" for the same reason.
-// This escaping can be disabled using an Encoder that had SetEscapeHTML(false)
-// called on it.
-//
-// Array and slice values encode as JSON arrays, except that
-// []byte encodes as a base64-encoded string, and a nil slice
-// encodes as the null JSON value.
-//
-// Struct values encode as JSON objects.
-// Each exported struct field becomes a member of the object, using the
-// field name as the object key, unless the field is omitted for one of the
-// reasons given below.
-//
-// The encoding of each struct field can be customized by the format string
-// stored under the "json" key in the struct field's tag.
-// The format string gives the name of the field, possibly followed by a
-// comma-separated list of options. The name may be empty in order to
-// specify options without overriding the default field name.
-//
-// The "omitempty" option specifies that the field should be omitted
-// from the encoding if the field has an empty value, defined as
-// false, 0, a nil pointer, a nil interface value, and any empty array,
-// slice, map, or string.
-//
-// As a special case, if the field tag is "-", the field is always omitted.
-// Note that a field with name "-" can still be generated using the tag "-,".
-//
-// Examples of struct field tags and their meanings:
-//
-// // Field appears in JSON as key "myName".
-// Field int `json:"myName"`
-//
-// // Field appears in JSON as key "myName" and
-// // the field is omitted from the object if its value is empty,
-// // as defined above.
-// Field int `json:"myName,omitempty"`
-//
-// // Field appears in JSON as key "Field" (the default), but
-// // the field is skipped if empty.
-// // Note the leading comma.
-// Field int `json:",omitempty"`
-//
-// // Field is ignored by this package.
-// Field int `json:"-"`
-//
-// // Field appears in JSON as key "-".
-// Field int `json:"-,"`
-//
-// The "string" option signals that a field is stored as JSON inside a
-// JSON-encoded string. It applies only to fields of string, floating point,
-// integer, or boolean types. This extra level of encoding is sometimes used
-// when communicating with JavaScript programs:
-//
-// Int64String int64 `json:",string"`
-//
-// The key name will be used if it's a non-empty string consisting of
-// only Unicode letters, digits, and ASCII punctuation except quotation
-// marks, backslash, and comma.
-//
-// Anonymous struct fields are usually marshaled as if their inner exported fields
-// were fields in the outer struct, subject to the usual Go visibility rules amended
-// as described in the next paragraph.
-// An anonymous struct field with a name given in its JSON tag is treated as
-// having that name, rather than being anonymous.
-// An anonymous struct field of interface type is treated the same as having
-// that type as its name, rather than being anonymous.
-//
-// The Go visibility rules for struct fields are amended for JSON when
-// deciding which field to marshal or unmarshal. If there are
-// multiple fields at the same level, and that level is the least
-// nested (and would therefore be the nesting level selected by the
-// usual Go rules), the following extra rules apply:
-//
-// 1) Of those fields, if any are JSON-tagged, only tagged fields are considered,
-// even if there are multiple untagged fields that would otherwise conflict.
-//
-// 2) If there is exactly one field (tagged or not according to the first rule), that is selected.
-//
-// 3) Otherwise there are multiple fields, and all are ignored; no error occurs.
-//
-// Handling of anonymous struct fields is new in Go 1.1.
-// Prior to Go 1.1, anonymous struct fields were ignored. To force ignoring of
-// an anonymous struct field in both current and earlier versions, give the field
-// a JSON tag of "-".
-//
-// Map values encode as JSON objects. The map's key type must either be a
-// string, an integer type, or implement encoding.TextMarshaler. The map keys
-// are sorted and used as JSON object keys by applying the following rules,
-// subject to the UTF-8 coercion described for string values above:
-// - string keys are used directly
-// - encoding.TextMarshalers are marshaled
-// - integer keys are converted to strings
-//
-// Pointer values encode as the value pointed to.
-// A nil pointer encodes as the null JSON value.
-//
-// Interface values encode as the value contained in the interface.
-// A nil interface value encodes as the null JSON value.
-//
-// Channel, complex, and function values cannot be encoded in JSON.
-// Attempting to encode such a value causes Marshal to return
-// an UnsupportedTypeError.
-//
-// JSON cannot represent cyclic data structures and Marshal does not
-// handle them. Passing cyclic structures to Marshal will result in
-// an infinite recursion.
-func Marshal(v interface{}) ([]byte, error) {
- e := newEncodeState()
-
- err := e.marshal(v, encOpts{escapeHTML: true})
- if err != nil {
- return nil, err
- }
- buf := append([]byte(nil), e.Bytes()...)
-
- e.Reset()
- encodeStatePool.Put(e)
-
- return buf, nil
-}
-
-// MarshalIndent is like Marshal but applies Indent to format the output.
-// Each JSON element in the output will begin on a new line beginning with prefix
-// followed by one or more copies of indent according to the indentation nesting.
-func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error) {
- b, err := Marshal(v)
- if err != nil {
- return nil, err
- }
- var buf bytes.Buffer
- err = Indent(&buf, b, prefix, indent)
- if err != nil {
- return nil, err
- }
- return buf.Bytes(), nil
-}
-
-// HTMLEscape appends to dst the JSON-encoded src with <, >, &, U+2028 and U+2029
-// characters inside string literals changed to \u003c, \u003e, \u0026, \u2028, \u2029
-// so that the JSON will be safe to embed inside HTML
+
+
+
+