Merge pull request #1303 from nspcc-dev/some-cleanup
Cleanup some old code
This commit is contained in:
commit
483eed1852
20 changed files with 39 additions and 564 deletions
|
@ -1,20 +0,0 @@
|
|||
# Integration package
|
||||
The main goal is to have integration tests here.
|
||||
|
||||
### Performance test
|
||||
Right now we have `performance_test.go` to measure number of processed TX per second.
|
||||
In order to run it:
|
||||
```
|
||||
$ cd integration
|
||||
$ go test -bench=. -benchmem
|
||||
```
|
||||
|
||||
Result:
|
||||
```
|
||||
10000 402421 ns/op 177370 B/op 90 allocs/op
|
||||
PASS
|
||||
ok github.com/nspcc-dev/neo-go/integration 4.360s
|
||||
|
||||
```
|
||||
|
||||
Which means that in 4.360 seconds neo-go processes 10 000 transactions.
|
|
@ -1,110 +0,0 @@
|
|||
package integration
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"testing"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/pkg/config"
|
||||
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/storage"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
|
||||
"github.com/nspcc-dev/neo-go/pkg/network"
|
||||
"github.com/nspcc-dev/neo-go/pkg/wallet"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"go.uber.org/zap/zaptest"
|
||||
)
|
||||
|
||||
// Benchmark test to measure number of processed TX.
|
||||
// Same benchmark made on reference C# node https://github.com/neo-project/neo/issues/1321.
|
||||
func BenchmarkTXPerformanceTest(t *testing.B) {
|
||||
net := netmode.UnitTestNet
|
||||
configPath := "../config"
|
||||
cfg, err := config.Load(configPath, net)
|
||||
require.NoError(t, err, "could not load config")
|
||||
|
||||
logger := zaptest.NewLogger(t)
|
||||
memoryStore := storage.NewMemoryStore()
|
||||
chain, err := core.NewBlockchain(memoryStore, cfg.ProtocolConfiguration, logger)
|
||||
require.NoError(t, err, "could not create chain")
|
||||
|
||||
go chain.Run()
|
||||
|
||||
serverConfig := network.NewServerConfig(cfg)
|
||||
server, err := network.NewServer(serverConfig, chain, logger)
|
||||
require.NoError(t, err, "could not create server")
|
||||
data := prepareData(t)
|
||||
t.ResetTimer()
|
||||
|
||||
for n := 0; n < t.N; n++ {
|
||||
assert.Equal(t, network.RelaySucceed, server.RelayTxn(data[n]))
|
||||
assert.Equal(t, network.RelayAlreadyExists, server.RelayTxn(data[n]))
|
||||
}
|
||||
chain.Close()
|
||||
}
|
||||
|
||||
func prepareData(t *testing.B) []*transaction.Transaction {
|
||||
var data []*transaction.Transaction
|
||||
|
||||
wif := getWif(t)
|
||||
acc, err := wallet.NewAccountFromWIF(wif.S)
|
||||
require.NoError(t, err)
|
||||
|
||||
for n := 0; n < t.N; n++ {
|
||||
tx := getTX(t, wif)
|
||||
require.NoError(t, acc.SignTx(tx))
|
||||
data = append(data, tx)
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
// getWif returns Wif.
|
||||
func getWif(t *testing.B) *keys.WIF {
|
||||
var (
|
||||
wifEncoded = "KxhEDBQyyEFymvfJD96q8stMbJMbZUb6D1PmXqBWZDU2WvbvVs9o"
|
||||
version = byte(0x00)
|
||||
)
|
||||
wif, err := keys.WIFDecode(wifEncoded, version)
|
||||
require.NoError(t, err)
|
||||
return wif
|
||||
}
|
||||
|
||||
// getTX returns Invocation transaction with some random attributes in order to have different hashes.
|
||||
func getTX(t *testing.B, wif *keys.WIF) *transaction.Transaction {
|
||||
fromAddress := wif.PrivateKey.Address()
|
||||
fromAddressHash, err := address.StringToUint160(fromAddress)
|
||||
require.NoError(t, err)
|
||||
|
||||
tx := transaction.New(netmode.UnitTestNet, []byte{0x51}, 1)
|
||||
tx.Version = 0
|
||||
tx.Signers = []transaction.Signer{
|
||||
{
|
||||
Account: fromAddressHash,
|
||||
Scopes: transaction.FeeOnly,
|
||||
},
|
||||
}
|
||||
tx.Attributes = append(tx.Attributes,
|
||||
transaction.Attribute{
|
||||
Usage: transaction.DescriptionURL,
|
||||
Data: []byte(randString(10)),
|
||||
})
|
||||
return tx
|
||||
}
|
||||
|
||||
// String returns a random string with the n as its length.
|
||||
func randString(n int) string {
|
||||
b := make([]byte, n)
|
||||
for i := range b {
|
||||
b[i] = byte(Int(65, 90))
|
||||
}
|
||||
|
||||
return string(b)
|
||||
}
|
||||
|
||||
// Int returns a random integer in [min,max).
|
||||
func Int(min, max int) int {
|
||||
return min + rand.Intn(max-min)
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
// Package integration contains integration tests.
|
||||
// See README.md for more info.
|
||||
// This file exists with the sole purpose to get rid of
|
||||
// "go build github.com/nspcc-dev/neo-go/integration: no non-test Go files in *"
|
||||
// when running `go test -coverpkg=all`.
|
||||
package integration
|
|
@ -1034,15 +1034,6 @@ func (bc *Blockchain) GetContractScriptHash(id int32) (util.Uint160, error) {
|
|||
return bc.dao.GetContractScriptHash(id)
|
||||
}
|
||||
|
||||
// GetAccountState returns the account state from its script hash.
|
||||
func (bc *Blockchain) GetAccountState(scriptHash util.Uint160) *state.Account {
|
||||
as, err := bc.dao.GetAccountState(scriptHash)
|
||||
if as == nil && err != storage.ErrKeyNotFound {
|
||||
bc.log.Warn("failed to get account state", zap.Error(err))
|
||||
}
|
||||
return as
|
||||
}
|
||||
|
||||
// GetConfig returns the config stored in the blockchain.
|
||||
func (bc *Blockchain) GetConfig() config.ProtocolConfiguration {
|
||||
return bc.config
|
||||
|
@ -1520,10 +1511,6 @@ func hashAndIndexToBytes(h util.Uint256, index uint32) []byte {
|
|||
return buf.Bytes()
|
||||
}
|
||||
|
||||
func (bc *Blockchain) secondsPerBlock() int {
|
||||
return bc.config.SecondsPerBlock
|
||||
}
|
||||
|
||||
func (bc *Blockchain) newInteropContext(trigger trigger.Type, d dao.DAO, block *block.Block, tx *transaction.Transaction) *interop.Context {
|
||||
ic := interop.NewContext(trigger, bc, d, bc.contracts.Contracts, block, tx, bc.log)
|
||||
ic.Functions = [][]interop.Function{systemInterops, neoInterops}
|
||||
|
|
|
@ -37,7 +37,6 @@ type Blockchainer interface {
|
|||
CurrentBlockHash() util.Uint256
|
||||
HasBlock(util.Uint256) bool
|
||||
HasTransaction(util.Uint256) bool
|
||||
GetAccountState(util.Uint160) *state.Account
|
||||
GetAppExecResult(util.Uint256) (*state.AppExecResult, error)
|
||||
GetNextBlockValidators() ([]*keys.PublicKey, error)
|
||||
GetNEP5Balances(util.Uint160) *state.NEP5Balances
|
||||
|
|
|
@ -13,7 +13,6 @@ import (
|
|||
// objects in the storeBlock().
|
||||
type Cached struct {
|
||||
DAO
|
||||
accounts map[util.Uint160]*state.Account
|
||||
contracts map[util.Uint160]*state.Contract
|
||||
balances map[util.Uint160]*state.NEP5Balances
|
||||
transfers map[util.Uint160]map[uint32]*state.NEP5TransferLog
|
||||
|
@ -23,34 +22,10 @@ type Cached struct {
|
|||
|
||||
// NewCached returns new Cached wrapping around given backing store.
|
||||
func NewCached(d DAO) *Cached {
|
||||
accs := make(map[util.Uint160]*state.Account)
|
||||
ctrs := make(map[util.Uint160]*state.Contract)
|
||||
balances := make(map[util.Uint160]*state.NEP5Balances)
|
||||
transfers := make(map[util.Uint160]map[uint32]*state.NEP5TransferLog)
|
||||
return &Cached{d.GetWrapped(), accs, ctrs, balances, transfers, false}
|
||||
}
|
||||
|
||||
// GetAccountStateOrNew retrieves Account from cache or underlying store
|
||||
// or creates a new one if it doesn't exist.
|
||||
func (cd *Cached) GetAccountStateOrNew(hash util.Uint160) (*state.Account, error) {
|
||||
if cd.accounts[hash] != nil {
|
||||
return cd.accounts[hash], nil
|
||||
}
|
||||
return cd.DAO.GetAccountStateOrNew(hash)
|
||||
}
|
||||
|
||||
// GetAccountState retrieves Account from cache or underlying store.
|
||||
func (cd *Cached) GetAccountState(hash util.Uint160) (*state.Account, error) {
|
||||
if cd.accounts[hash] != nil {
|
||||
return cd.accounts[hash], nil
|
||||
}
|
||||
return cd.DAO.GetAccountState(hash)
|
||||
}
|
||||
|
||||
// PutAccountState saves given Account in the cache.
|
||||
func (cd *Cached) PutAccountState(as *state.Account) error {
|
||||
cd.accounts[as.ScriptHash] = as
|
||||
return nil
|
||||
return &Cached{d.GetWrapped(), ctrs, balances, transfers, false}
|
||||
}
|
||||
|
||||
// GetContractState returns contract state from cache or underlying store.
|
||||
|
@ -149,13 +124,6 @@ func (cd *Cached) Persist() (int, error) {
|
|||
}
|
||||
buf := io.NewBufBinWriter()
|
||||
|
||||
for sc := range cd.accounts {
|
||||
err := cd.DAO.putAccountState(cd.accounts[sc], buf)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
buf.Reset()
|
||||
}
|
||||
for acc, bs := range cd.balances {
|
||||
err := cd.DAO.putNEP5Balances(acc, bs, buf)
|
||||
if err != nil {
|
||||
|
@ -177,7 +145,6 @@ func (cd *Cached) Persist() (int, error) {
|
|||
// GetWrapped implements DAO interface.
|
||||
func (cd *Cached) GetWrapped() DAO {
|
||||
return &Cached{cd.DAO.GetWrapped(),
|
||||
cd.accounts,
|
||||
cd.contracts,
|
||||
cd.balances,
|
||||
cd.transfers,
|
||||
|
|
|
@ -13,43 +13,6 @@ import (
|
|||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestCachedDaoAccounts(t *testing.T) {
|
||||
store := storage.NewMemoryStore()
|
||||
// Persistent DAO to check for backing storage.
|
||||
pdao := NewSimple(store, netmode.UnitTestNet)
|
||||
// Cached DAO.
|
||||
cdao := NewCached(pdao)
|
||||
|
||||
hash := random.Uint160()
|
||||
_, err := cdao.GetAccountState(hash)
|
||||
require.NotNil(t, err)
|
||||
|
||||
acc, err := cdao.GetAccountStateOrNew(hash)
|
||||
require.Nil(t, err)
|
||||
_, err = pdao.GetAccountState(hash)
|
||||
require.NotNil(t, err)
|
||||
|
||||
acc.Version = 42
|
||||
require.NoError(t, cdao.PutAccountState(acc))
|
||||
_, err = pdao.GetAccountState(hash)
|
||||
require.NotNil(t, err)
|
||||
|
||||
acc2, err := cdao.GetAccountState(hash)
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, acc, acc2)
|
||||
|
||||
acc2, err = cdao.GetAccountStateOrNew(hash)
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, acc, acc2)
|
||||
|
||||
_, err = cdao.Persist()
|
||||
require.Nil(t, err)
|
||||
|
||||
acct, err := pdao.GetAccountState(hash)
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, acc, acct)
|
||||
}
|
||||
|
||||
func TestCachedDaoContracts(t *testing.T) {
|
||||
store := storage.NewMemoryStore()
|
||||
pdao := NewSimple(store, netmode.UnitTestNet)
|
||||
|
|
|
@ -21,8 +21,6 @@ type DAO interface {
|
|||
AppendNEP5Transfer(acc util.Uint160, index uint32, tr *state.NEP5Transfer) (bool, error)
|
||||
DeleteContractState(hash util.Uint160) error
|
||||
DeleteStorageItem(id int32, key []byte) error
|
||||
GetAccountState(hash util.Uint160) (*state.Account, error)
|
||||
GetAccountStateOrNew(hash util.Uint160) (*state.Account, error)
|
||||
GetAndDecode(entity io.Serializable, key []byte) error
|
||||
GetAppExecResult(hash util.Uint256) (*state.AppExecResult, error)
|
||||
GetBatch() *storage.MemBatch
|
||||
|
@ -46,7 +44,6 @@ type DAO interface {
|
|||
GetWrapped() DAO
|
||||
HasTransaction(hash util.Uint256) bool
|
||||
Persist() (int, error)
|
||||
PutAccountState(as *state.Account) error
|
||||
PutAppExecResult(aer *state.AppExecResult) error
|
||||
PutContractState(cs *state.Contract) error
|
||||
PutCurrentHeader(hashAndIndex []byte) error
|
||||
|
@ -57,7 +54,6 @@ type DAO interface {
|
|||
StoreAsBlock(block *block.Block) error
|
||||
StoreAsCurrentBlock(block *block.Block) error
|
||||
StoreAsTransaction(tx *transaction.Transaction, index uint32) error
|
||||
putAccountState(as *state.Account, buf *io.BufBinWriter) error
|
||||
putNEP5Balances(acc util.Uint160, bs *state.NEP5Balances, buf *io.BufBinWriter) error
|
||||
}
|
||||
|
||||
|
@ -112,45 +108,6 @@ func (dao *Simple) putWithBuffer(entity io.Serializable, key []byte, buf *io.Buf
|
|||
return dao.Store.Put(key, buf.Bytes())
|
||||
}
|
||||
|
||||
// -- start accounts.
|
||||
|
||||
// GetAccountStateOrNew retrieves Account from temporary or persistent Store
|
||||
// or creates a new one if it doesn't exist and persists it.
|
||||
func (dao *Simple) GetAccountStateOrNew(hash util.Uint160) (*state.Account, error) {
|
||||
account, err := dao.GetAccountState(hash)
|
||||
if err != nil {
|
||||
if err != storage.ErrKeyNotFound {
|
||||
return nil, err
|
||||
}
|
||||
account = state.NewAccount(hash)
|
||||
}
|
||||
return account, nil
|
||||
}
|
||||
|
||||
// GetAccountState returns Account from the given Store if it's
|
||||
// present there. Returns nil otherwise.
|
||||
func (dao *Simple) GetAccountState(hash util.Uint160) (*state.Account, error) {
|
||||
account := &state.Account{}
|
||||
key := storage.AppendPrefix(storage.STAccount, hash.BytesBE())
|
||||
err := dao.GetAndDecode(account, key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return account, err
|
||||
}
|
||||
|
||||
// PutAccountState saves given Account in given store.
|
||||
func (dao *Simple) PutAccountState(as *state.Account) error {
|
||||
return dao.putAccountState(as, io.NewBufBinWriter())
|
||||
}
|
||||
|
||||
func (dao *Simple) putAccountState(as *state.Account, buf *io.BufBinWriter) error {
|
||||
key := storage.AppendPrefix(storage.STAccount, as.ScriptHash.BytesBE())
|
||||
return dao.putWithBuffer(as, key, buf)
|
||||
}
|
||||
|
||||
// -- end accounts.
|
||||
|
||||
// -- start contracts.
|
||||
|
||||
// GetContractState returns contract state as recorded in the given
|
||||
|
|
|
@ -41,25 +41,6 @@ func (t *TestSerializable) DecodeBinary(reader *io.BinReader) {
|
|||
t.field = reader.ReadString()
|
||||
}
|
||||
|
||||
func TestGetAccountStateOrNew_New(t *testing.T) {
|
||||
dao := NewSimple(storage.NewMemoryStore(), netmode.UnitTestNet)
|
||||
hash := random.Uint160()
|
||||
createdAccount, err := dao.GetAccountStateOrNew(hash)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, createdAccount)
|
||||
}
|
||||
|
||||
func TestPutAndGetAccountStateOrNew(t *testing.T) {
|
||||
dao := NewSimple(storage.NewMemoryStore(), netmode.UnitTestNet)
|
||||
hash := random.Uint160()
|
||||
accountState := &state.Account{ScriptHash: hash}
|
||||
err := dao.PutAccountState(accountState)
|
||||
require.NoError(t, err)
|
||||
gotAccount, err := dao.GetAccountStateOrNew(hash)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, accountState.ScriptHash, gotAccount.ScriptHash)
|
||||
}
|
||||
|
||||
func TestPutAndGetContractState(t *testing.T) {
|
||||
dao := NewSimple(storage.NewMemoryStore(), netmode.UnitTestNet)
|
||||
contractState := &state.Contract{Script: []byte{}}
|
||||
|
|
|
@ -12,11 +12,6 @@ type HeaderHashList struct {
|
|||
hashes []util.Uint256
|
||||
}
|
||||
|
||||
// NewHeaderHashListFromBytes returns a new hash list from the given bytes.
|
||||
func NewHeaderHashListFromBytes(b []byte) (*HeaderHashList, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// NewHeaderHashList returns a new pointer to a HeaderHashList.
|
||||
func NewHeaderHashList(hashes ...util.Uint256) *HeaderHashList {
|
||||
return &HeaderHashList{
|
||||
|
@ -47,17 +42,9 @@ func (l *HeaderHashList) Last() util.Uint256 {
|
|||
return l.hashes[l.Len()-1]
|
||||
}
|
||||
|
||||
// Slice return a subslice of the underlying hashes.
|
||||
// Subsliced from start to end.
|
||||
// Example:
|
||||
// headers := headerList.Slice(0, 2000)
|
||||
func (l *HeaderHashList) Slice(start, end int) []util.Uint256 {
|
||||
return l.hashes[start:end]
|
||||
}
|
||||
|
||||
// WriteTo writes n underlying hashes to the given BinWriter
|
||||
// Write writes n underlying hashes to the given BinWriter
|
||||
// starting from start.
|
||||
func (l *HeaderHashList) Write(bw *io.BinWriter, start, n int) error {
|
||||
bw.WriteArray(l.Slice(start, start+n))
|
||||
bw.WriteArray(l.hashes[start : start+n])
|
||||
return bw.Err
|
||||
}
|
||||
|
|
|
@ -29,8 +29,6 @@ import (
|
|||
|
||||
/* Missing tests:
|
||||
* TestTxGetWitnesses
|
||||
* TestBcGetAccount
|
||||
* TestAccountGetBalance
|
||||
* TestAccountIsStandard
|
||||
* TestCreateContractStateFromVM
|
||||
* TestContractCreate
|
||||
|
@ -301,29 +299,10 @@ func createVMAndContractState(t *testing.T) (*vm.VM, *state.Contract, *interop.C
|
|||
return v, contractState, context, chain
|
||||
}
|
||||
|
||||
func createVMAndAccState(t *testing.T) (*vm.VM, *state.Account, *interop.Context, *Blockchain) {
|
||||
rawHash := "4d3b96ae1bcc5a585e075e3b81920210dec16302"
|
||||
hash, err := util.Uint160DecodeStringBE(rawHash)
|
||||
accountState := state.NewAccount(hash)
|
||||
|
||||
require.NoError(t, err)
|
||||
chain := newTestChain(t)
|
||||
context := chain.newInteropContext(trigger.Application, dao.NewSimple(storage.NewMemoryStore(), netmode.UnitTestNet), nil, nil)
|
||||
v := context.SpawnVM()
|
||||
return v, accountState, context, chain
|
||||
}
|
||||
|
||||
func createVMAndTX(t *testing.T) (*vm.VM, *transaction.Transaction, *interop.Context, *Blockchain) {
|
||||
script := []byte{byte(opcode.PUSH1), byte(opcode.RET)}
|
||||
tx := transaction.New(netmode.UnitTestNet, script, 0)
|
||||
|
||||
bytes := make([]byte, 1)
|
||||
attributes := append(tx.Attributes, transaction.Attribute{
|
||||
Usage: transaction.DescriptionURL,
|
||||
Data: bytes,
|
||||
})
|
||||
|
||||
tx.Attributes = attributes
|
||||
tx.Signers = []transaction.Signer{{Account: util.Uint160{1, 2, 3, 4}}}
|
||||
chain := newTestChain(t)
|
||||
context := chain.newInteropContext(trigger.Application, dao.NewSimple(storage.NewMemoryStore(), netmode.UnitTestNet), nil, tx)
|
||||
|
|
|
@ -68,28 +68,23 @@ func TestOverCapacity(t *testing.T) {
|
|||
require.Equal(t, mempoolSize, mp.Count())
|
||||
require.Equal(t, true, sort.IsSorted(sort.Reverse(mp.verifiedTxes)))
|
||||
|
||||
bigScript := make([]byte, 64)
|
||||
bigScript[0] = byte(opcode.PUSH1)
|
||||
bigScript[1] = byte(opcode.RET)
|
||||
// Fees are also prioritized.
|
||||
for i := 0; i < mempoolSize; i++ {
|
||||
tx := transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0)
|
||||
tx.Attributes = append(tx.Attributes, transaction.Attribute{
|
||||
Usage: transaction.DescriptionURL,
|
||||
Data: util.Uint256{1, 2, 3, 4}.BytesBE(),
|
||||
})
|
||||
tx := transaction.New(netmode.UnitTestNet, bigScript, 0)
|
||||
tx.NetworkFee = 10000
|
||||
tx.Nonce = txcnt
|
||||
tx.Signers = []transaction.Signer{{Account: util.Uint160{1, 2, 3}}}
|
||||
txcnt++
|
||||
// size is 84, networkFee is 10000 => feePerByte is 119
|
||||
// size is ~90, networkFee is 10000 => feePerByte is 119
|
||||
require.NoError(t, mp.Add(tx, fs))
|
||||
require.Equal(t, mempoolSize, mp.Count())
|
||||
require.Equal(t, true, sort.IsSorted(sort.Reverse(mp.verifiedTxes)))
|
||||
}
|
||||
// Less prioritized txes are not allowed anymore.
|
||||
tx := transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0)
|
||||
tx.Attributes = append(tx.Attributes, transaction.Attribute{
|
||||
Usage: transaction.DescriptionURL,
|
||||
Data: util.Uint256{1, 2, 3, 4}.BytesBE(),
|
||||
})
|
||||
tx := transaction.New(netmode.UnitTestNet, bigScript, 0)
|
||||
tx.NetworkFee = 100
|
||||
tx.Nonce = txcnt
|
||||
tx.Signers = []transaction.Signer{{Account: util.Uint160{1, 2, 3}}}
|
||||
|
@ -104,7 +99,7 @@ func TestOverCapacity(t *testing.T) {
|
|||
tx.NetworkFee = 7000
|
||||
tx.Signers = []transaction.Signer{{Account: util.Uint160{1, 2, 3}}}
|
||||
txcnt++
|
||||
// size is 51 (no attributes), networkFee is 7000 (<10000)
|
||||
// size is ~51 (small script), networkFee is 7000 (<10000)
|
||||
// => feePerByte is 137 (>119)
|
||||
require.NoError(t, mp.Add(tx, fs))
|
||||
require.Equal(t, mempoolSize, mp.Count())
|
||||
|
|
|
@ -1,108 +0,0 @@
|
|||
package state
|
||||
|
||||
import (
|
||||
"github.com/nspcc-dev/neo-go/pkg/io"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
)
|
||||
|
||||
// UnspentBalance contains input/output transactons that sum up into the
|
||||
// account balance for the given asset.
|
||||
type UnspentBalance struct {
|
||||
Tx util.Uint256 `json:"txid"`
|
||||
Index uint16 `json:"n"`
|
||||
Value util.Fixed8 `json:"value"`
|
||||
}
|
||||
|
||||
// UnspentBalances is a slice of UnspentBalance (mostly needed to sort them).
|
||||
type UnspentBalances []UnspentBalance
|
||||
|
||||
// Account represents the state of a NEO account.
|
||||
type Account struct {
|
||||
Version uint8
|
||||
ScriptHash util.Uint160
|
||||
IsFrozen bool
|
||||
Balances map[util.Uint256][]UnspentBalance
|
||||
}
|
||||
|
||||
// NewAccount returns a new Account object.
|
||||
func NewAccount(scriptHash util.Uint160) *Account {
|
||||
return &Account{
|
||||
Version: 0,
|
||||
ScriptHash: scriptHash,
|
||||
IsFrozen: false,
|
||||
Balances: make(map[util.Uint256][]UnspentBalance),
|
||||
}
|
||||
}
|
||||
|
||||
// DecodeBinary decodes Account from the given BinReader.
|
||||
func (s *Account) DecodeBinary(br *io.BinReader) {
|
||||
s.Version = uint8(br.ReadB())
|
||||
s.ScriptHash.DecodeBinary(br)
|
||||
s.IsFrozen = br.ReadBool()
|
||||
|
||||
s.Balances = make(map[util.Uint256][]UnspentBalance)
|
||||
lenBalances := br.ReadVarUint()
|
||||
for i := 0; i < int(lenBalances); i++ {
|
||||
key := util.Uint256{}
|
||||
br.ReadBytes(key[:])
|
||||
len := int(br.ReadVarUint())
|
||||
ubs := make([]UnspentBalance, len)
|
||||
for j := 0; j < len; j++ {
|
||||
ubs[j].DecodeBinary(br)
|
||||
}
|
||||
s.Balances[key] = ubs
|
||||
}
|
||||
}
|
||||
|
||||
// EncodeBinary encodes Account to the given BinWriter.
|
||||
func (s *Account) EncodeBinary(bw *io.BinWriter) {
|
||||
bw.WriteB(byte(s.Version))
|
||||
s.ScriptHash.EncodeBinary(bw)
|
||||
bw.WriteBool(s.IsFrozen)
|
||||
|
||||
bw.WriteVarUint(uint64(len(s.Balances)))
|
||||
for k, v := range s.Balances {
|
||||
bw.WriteBytes(k[:])
|
||||
bw.WriteVarUint(uint64(len(v)))
|
||||
for i := range v {
|
||||
v[i].EncodeBinary(bw)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DecodeBinary implements io.Serializable interface.
|
||||
func (u *UnspentBalance) DecodeBinary(r *io.BinReader) {
|
||||
u.Tx.DecodeBinary(r)
|
||||
u.Index = r.ReadU16LE()
|
||||
u.Value.DecodeBinary(r)
|
||||
}
|
||||
|
||||
// EncodeBinary implements io.Serializable interface.
|
||||
func (u *UnspentBalance) EncodeBinary(w *io.BinWriter) {
|
||||
u.Tx.EncodeBinary(w)
|
||||
w.WriteU16LE(u.Index)
|
||||
u.Value.EncodeBinary(w)
|
||||
}
|
||||
|
||||
// GetBalanceValues sums all unspent outputs and returns a map of asset IDs to
|
||||
// overall balances.
|
||||
func (s *Account) GetBalanceValues() map[util.Uint256]util.Fixed8 {
|
||||
res := make(map[util.Uint256]util.Fixed8)
|
||||
for k, v := range s.Balances {
|
||||
balance := util.Fixed8(0)
|
||||
for _, b := range v {
|
||||
balance += b.Value
|
||||
}
|
||||
res[k] = balance
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// Len returns the length of UnspentBalances (used to sort things).
|
||||
func (us UnspentBalances) Len() int { return len(us) }
|
||||
|
||||
// Less compares two elements of UnspentBalances (used to sort things).
|
||||
func (us UnspentBalances) Less(i, j int) bool { return us[i].Value < us[j].Value }
|
||||
|
||||
// Swap swaps two elements of UnspentBalances (used to sort things).
|
||||
func (us UnspentBalances) Swap(i, j int) { us[i], us[j] = us[j], us[i] }
|
|
@ -1,51 +0,0 @@
|
|||
package state
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/pkg/internal/random"
|
||||
"github.com/nspcc-dev/neo-go/pkg/internal/testserdes"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestDecodeEncodeAccountState(t *testing.T) {
|
||||
var (
|
||||
n = 10
|
||||
balances = make(map[util.Uint256][]UnspentBalance)
|
||||
)
|
||||
for i := 0; i < n; i++ {
|
||||
asset := random.Uint256()
|
||||
for j := 0; j < i+1; j++ {
|
||||
balances[asset] = append(balances[asset], UnspentBalance{
|
||||
Tx: random.Uint256(),
|
||||
Index: uint16(random.Int(0, 65535)),
|
||||
Value: util.Fixed8(int64(random.Int(1, 10000))),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
a := &Account{
|
||||
Version: 0,
|
||||
ScriptHash: random.Uint160(),
|
||||
IsFrozen: true,
|
||||
Balances: balances,
|
||||
}
|
||||
|
||||
testserdes.EncodeDecodeBinary(t, a, new(Account))
|
||||
}
|
||||
|
||||
func TestAccountStateBalanceValues(t *testing.T) {
|
||||
asset1 := random.Uint256()
|
||||
asset2 := random.Uint256()
|
||||
as := Account{Balances: make(map[util.Uint256][]UnspentBalance)}
|
||||
ref := 0
|
||||
for i := 0; i < 10; i++ {
|
||||
ref += i
|
||||
as.Balances[asset1] = append(as.Balances[asset1], UnspentBalance{Value: util.Fixed8(i)})
|
||||
as.Balances[asset2] = append(as.Balances[asset2], UnspentBalance{Value: util.Fixed8(i * 10)})
|
||||
}
|
||||
bVals := as.GetBalanceValues()
|
||||
assert.Equal(t, util.Fixed8(ref), bVals[asset1])
|
||||
assert.Equal(t, util.Fixed8(ref*10), bVals[asset2])
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
package transaction
|
||||
|
||||
//go:generate stringer -type=AttrUsage
|
||||
|
||||
// AttrUsage represents the purpose of the attribute.
|
||||
type AttrUsage uint8
|
||||
|
||||
// List of valid attribute usages.
|
||||
const (
|
||||
DescriptionURL AttrUsage = 0x81
|
||||
)
|
|
@ -3,7 +3,6 @@ package transaction
|
|||
import (
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/pkg/io"
|
||||
|
@ -11,50 +10,46 @@ import (
|
|||
|
||||
// Attribute represents a Transaction attribute.
|
||||
type Attribute struct {
|
||||
Usage AttrUsage
|
||||
Type AttrType
|
||||
Data []byte
|
||||
}
|
||||
|
||||
// attrJSON is used for JSON I/O of Attribute.
|
||||
type attrJSON struct {
|
||||
Usage string `json:"usage"`
|
||||
Type string `json:"type"`
|
||||
Data string `json:"data"`
|
||||
}
|
||||
|
||||
// DecodeBinary implements Serializable interface.
|
||||
func (attr *Attribute) DecodeBinary(br *io.BinReader) {
|
||||
attr.Usage = AttrUsage(br.ReadB())
|
||||
attr.Type = AttrType(br.ReadB())
|
||||
|
||||
var datasize uint64
|
||||
switch attr.Usage {
|
||||
case DescriptionURL:
|
||||
// It's not VarUint as per C# implementation, dunno why
|
||||
var urllen = br.ReadB()
|
||||
datasize = uint64(urllen)
|
||||
/**
|
||||
|
||||
switch attr.Type {
|
||||
default:
|
||||
br.Err = fmt.Errorf("failed decoding TX attribute usage: 0x%2x", int(attr.Usage))
|
||||
br.Err = fmt.Errorf("failed decoding TX attribute usage: 0x%2x", int(attr.Type))
|
||||
return
|
||||
}
|
||||
*/
|
||||
attr.Data = make([]byte, datasize)
|
||||
br.ReadBytes(attr.Data)
|
||||
}
|
||||
|
||||
// EncodeBinary implements Serializable interface.
|
||||
func (attr *Attribute) EncodeBinary(bw *io.BinWriter) {
|
||||
bw.WriteB(byte(attr.Usage))
|
||||
switch attr.Usage {
|
||||
case DescriptionURL:
|
||||
bw.WriteB(byte(len(attr.Data)))
|
||||
bw.WriteBytes(attr.Data)
|
||||
bw.WriteB(byte(attr.Type))
|
||||
switch attr.Type {
|
||||
default:
|
||||
bw.Err = fmt.Errorf("failed encoding TX attribute usage: 0x%2x", attr.Usage)
|
||||
bw.Err = fmt.Errorf("failed encoding TX attribute usage: 0x%2x", attr.Type)
|
||||
}
|
||||
}
|
||||
|
||||
// MarshalJSON implements the json Marshaller interface.
|
||||
func (attr *Attribute) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(attrJSON{
|
||||
Usage: attr.Usage.String(),
|
||||
Type: "", // attr.Type.String() when we're to have some real attributes
|
||||
Data: base64.StdEncoding.EncodeToString(attr.Data),
|
||||
})
|
||||
}
|
||||
|
@ -70,13 +65,13 @@ func (attr *Attribute) UnmarshalJSON(data []byte) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
switch aj.Usage {
|
||||
case "DescriptionURL":
|
||||
attr.Usage = DescriptionURL
|
||||
/**
|
||||
switch aj.Type {
|
||||
default:
|
||||
return errors.New("wrong Usage")
|
||||
return errors.New("wrong Type")
|
||||
|
||||
}
|
||||
*/
|
||||
attr.Data = binData
|
||||
return nil
|
||||
}
|
||||
|
|
10
pkg/core/transaction/attrtype.go
Normal file
10
pkg/core/transaction/attrtype.go
Normal file
|
@ -0,0 +1,10 @@
|
|||
package transaction
|
||||
|
||||
//go:generate stringer -type=AttrType
|
||||
|
||||
// AttrType represents the purpose of the attribute.
|
||||
type AttrType uint8
|
||||
|
||||
// List of valid attribute types (none for preview3).
|
||||
//const (
|
||||
//)
|
|
@ -1,24 +0,0 @@
|
|||
// Code generated by "stringer -type=AttrUsage"; DO NOT EDIT.
|
||||
|
||||
package transaction
|
||||
|
||||
import "strconv"
|
||||
|
||||
func _() {
|
||||
// An "invalid array index" compiler error signifies that the constant values have changed.
|
||||
// Re-run the stringer command to generate them again.
|
||||
var x [1]struct{}
|
||||
_ = x[DescriptionURL-129]
|
||||
}
|
||||
|
||||
const _AttrUsage_name = "DescriptionURL"
|
||||
|
||||
var _AttrUsage_index = [...]uint8{0, 14}
|
||||
|
||||
func (i AttrUsage) String() string {
|
||||
i -= 129
|
||||
if i >= AttrUsage(len(_AttrUsage_index)-1) {
|
||||
return "AttrUsage(" + strconv.FormatInt(int64(i+129), 10) + ")"
|
||||
}
|
||||
return _AttrUsage_name[_AttrUsage_index[i]:_AttrUsage_index[i+1]]
|
||||
}
|
|
@ -88,9 +88,6 @@ func (chain testChain) GetHeader(hash util.Uint256) (*block.Header, error) {
|
|||
panic("TODO")
|
||||
}
|
||||
|
||||
func (chain testChain) GetAccountState(util.Uint160) *state.Account {
|
||||
panic("TODO")
|
||||
}
|
||||
func (chain testChain) GetNextBlockValidators() ([]*keys.PublicKey, error) {
|
||||
panic("TODO")
|
||||
}
|
||||
|
|
|
@ -365,18 +365,6 @@ func (c *Client) invokeSomething(method string, p request.RawParams, signers []t
|
|||
p.Values = append(p.Values, signers)
|
||||
}
|
||||
if err := c.performRequest(method, p, resp); err != nil {
|
||||
// Retry with old-fashioned hashes (see neo/neo-modules#260).
|
||||
if signers != nil {
|
||||
var hashes = make([]util.Uint160, len(signers))
|
||||
for i := range signers {
|
||||
hashes[i] = signers[i].Account
|
||||
}
|
||||
p.Values[len(p.Values)-1] = hashes
|
||||
err = c.performRequest(method, p, resp)
|
||||
if err == nil {
|
||||
return resp, nil
|
||||
}
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return resp, nil
|
||||
|
|
Loading…
Reference in a new issue