mirror of
https://github.com/nspcc-dev/neo-go.git
synced 2024-12-05 03:58:23 +00:00
rpc: fix gettxout result for already spent outputs
As per C# documentation [1]: If the transaction output is already spent, the result value will be null . [1]: https://docs.neo.org/docs/en-us/reference/rpc/latest-version/api/gettxout.html
This commit is contained in:
parent
124c674b17
commit
9e35758653
4 changed files with 25 additions and 8 deletions
|
@ -43,6 +43,11 @@ func (s *UnspentCoin) EncodeBinary(bw *io.BinWriter) {
|
||||||
func (s *UnspentCoin) DecodeBinary(br *io.BinReader) {
|
func (s *UnspentCoin) DecodeBinary(br *io.BinReader) {
|
||||||
s.Height = br.ReadU32LE()
|
s.Height = br.ReadU32LE()
|
||||||
br.ReadArray(&s.States)
|
br.ReadArray(&s.States)
|
||||||
|
if br.Err == nil {
|
||||||
|
for i := range s.States {
|
||||||
|
s.States[i].Output.Position = i
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// EncodeBinary implements Serializable interface.
|
// EncodeBinary implements Serializable interface.
|
||||||
|
|
|
@ -27,6 +27,7 @@ func TestDecodeEncodeUnspentCoin(t *testing.T) {
|
||||||
AssetID: random.Uint256(),
|
AssetID: random.Uint256(),
|
||||||
Amount: util.Fixed8(420),
|
Amount: util.Fixed8(420),
|
||||||
ScriptHash: random.Uint160(),
|
ScriptHash: random.Uint160(),
|
||||||
|
Position: 1,
|
||||||
},
|
},
|
||||||
SpendHeight: 0,
|
SpendHeight: 0,
|
||||||
State: CoinConfirmed,
|
State: CoinConfirmed,
|
||||||
|
@ -36,6 +37,7 @@ func TestDecodeEncodeUnspentCoin(t *testing.T) {
|
||||||
AssetID: random.Uint256(),
|
AssetID: random.Uint256(),
|
||||||
Amount: util.Fixed8(4200),
|
Amount: util.Fixed8(4200),
|
||||||
ScriptHash: random.Uint160(),
|
ScriptHash: random.Uint160(),
|
||||||
|
Position: 2,
|
||||||
},
|
},
|
||||||
SpendHeight: 111000,
|
SpendHeight: 111000,
|
||||||
State: CoinSpent & CoinClaimed,
|
State: CoinSpent & CoinClaimed,
|
||||||
|
|
|
@ -1207,17 +1207,19 @@ func (s *Server) getTxOut(ps request.Params) (interface{}, *response.Error) {
|
||||||
return nil, response.ErrInvalidParams
|
return nil, response.ErrInvalidParams
|
||||||
}
|
}
|
||||||
|
|
||||||
tx, _, err := s.chain.GetTransaction(h)
|
ucs := s.chain.GetUnspentCoinState(h)
|
||||||
if err != nil {
|
if ucs == nil {
|
||||||
return nil, response.NewInvalidParamsError(err.Error(), err)
|
return nil, response.NewInvalidParamsError("invalid tx hash", errors.New("unknown"))
|
||||||
}
|
}
|
||||||
|
|
||||||
if num >= len(tx.Outputs) {
|
if num >= len(ucs.States) {
|
||||||
return nil, response.NewInvalidParamsError("invalid index", errors.New("too big index"))
|
return nil, response.NewInvalidParamsError("invalid index", errors.New("too big index"))
|
||||||
}
|
}
|
||||||
|
|
||||||
out := tx.Outputs[num]
|
if ucs.States[num].State&state.CoinSpent != 0 {
|
||||||
return result.NewTxOutput(&out), nil
|
return nil, nil
|
||||||
|
}
|
||||||
|
return result.NewTxOutput(&ucs.States[num].Output), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// getContractState returns contract state (contract information, according to the contract script hash).
|
// getContractState returns contract state (contract information, according to the contract script hash).
|
||||||
|
|
|
@ -1204,13 +1204,21 @@ func testRPCProtocol(t *testing.T, doRPCCall func(string, string, *testing.T) []
|
||||||
`"`+tx.Hash().StringLE()+`"`, 0)
|
`"`+tx.Hash().StringLE()+`"`, 0)
|
||||||
body := doRPCCall(rpc, httpSrv.URL, t)
|
body := doRPCCall(rpc, httpSrv.URL, t)
|
||||||
res := checkErrGetResult(t, body, false)
|
res := checkErrGetResult(t, body, false)
|
||||||
|
assert.Equal(t, "null", string(res)) // already spent
|
||||||
|
|
||||||
|
block, _ = chain.GetBlock(e.chain.GetHeaderHash(1))
|
||||||
|
tx = block.Transactions[1]
|
||||||
|
rpc = fmt.Sprintf(`{"jsonrpc": "2.0", "id": 1, "method": "gettxout", "params": [%s, %d]}"`,
|
||||||
|
`"`+tx.Hash().StringLE()+`"`, 1) // Neo remainder in txMoveNeo
|
||||||
|
body = doRPCCall(rpc, httpSrv.URL, t)
|
||||||
|
res = checkErrGetResult(t, body, false)
|
||||||
|
|
||||||
var txOut result.TransactionOutput
|
var txOut result.TransactionOutput
|
||||||
err := json.Unmarshal(res, &txOut)
|
err := json.Unmarshal(res, &txOut)
|
||||||
require.NoErrorf(t, err, "could not parse response: %s", res)
|
require.NoErrorf(t, err, "could not parse response: %s", res)
|
||||||
assert.Equal(t, 0, txOut.N)
|
assert.Equal(t, 1, txOut.N)
|
||||||
assert.Equal(t, "0x9b7cffdaa674beae0f930ebe6085af9093e5fe56b34a5c220ccdcf6efc336fc5", txOut.Asset)
|
assert.Equal(t, "0x9b7cffdaa674beae0f930ebe6085af9093e5fe56b34a5c220ccdcf6efc336fc5", txOut.Asset)
|
||||||
assert.Equal(t, util.Fixed8FromInt64(100000000), txOut.Value)
|
assert.Equal(t, util.Fixed8FromInt64(1000), txOut.Value)
|
||||||
assert.Equal(t, "AZ81H31DMWzbSnFDLFkzh9vHwaDLayV7fU", txOut.Address)
|
assert.Equal(t, "AZ81H31DMWzbSnFDLFkzh9vHwaDLayV7fU", txOut.Address)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue