2020-01-15 07:52:59 +00:00
|
|
|
package mempool
|
Implement rpc server method: sendrawtransaction (#174)
* Added new config attributes: 'SecondsPerBlock','LowPriorityThreshold'
* Added new files:
* Added new method: CompareTo
* Fixed empty Slice case
* Added new methods: LessThan, GreaterThan, Equal, CompareTo
* Added new method: InputIntersection
* Added MaxTransactionSize, GroupOutputByAssetID
* Added ned method: ScriptHash
* Added new method: IsDoubleSpend
* Refactor blockchainer, Added Feer interface, Verify and GetMemPool method
* 1) Added MemPool
2) Added new methods to satisfy the blockchainer interface: IsLowPriority, Verify, GetMemPool
* Added new methods: RelayTxn, RelayDirectly
* Fixed tests
* Implemented RPC server method sendrawtransaction
* Refactor getrawtransaction, sendrawtransaction in separate methods
* Moved 'secondsPerBlock' to config file
* Implemented Kim suggestions:
1) Fixed data race issues
2) refactor Verify method
3) Get rid of unused InputIntersection method due to refactoring Verify method
4) Fixed bug in https://github.com/CityOfZion/neo-go/pull/174#discussion_r264108135
5) minor simplications of the code
* Fixed minor issues related to
1) space
2) getter methods do not need pointer on the receiver
3) error message
4) refactoring CompareTo method in uint256.go
* Fixed small issues
* Use sync.RWMutex instead of sync.Mutex
* Refined (R)Lock/(R)Unlock
* return error instead of bool in Verify methods
2019-03-20 12:30:05 +00:00
|
|
|
|
|
|
|
import (
|
2020-02-04 15:43:21 +00:00
|
|
|
"errors"
|
Implement rpc server method: sendrawtransaction (#174)
* Added new config attributes: 'SecondsPerBlock','LowPriorityThreshold'
* Added new files:
* Added new method: CompareTo
* Fixed empty Slice case
* Added new methods: LessThan, GreaterThan, Equal, CompareTo
* Added new method: InputIntersection
* Added MaxTransactionSize, GroupOutputByAssetID
* Added ned method: ScriptHash
* Added new method: IsDoubleSpend
* Refactor blockchainer, Added Feer interface, Verify and GetMemPool method
* 1) Added MemPool
2) Added new methods to satisfy the blockchainer interface: IsLowPriority, Verify, GetMemPool
* Added new methods: RelayTxn, RelayDirectly
* Fixed tests
* Implemented RPC server method sendrawtransaction
* Refactor getrawtransaction, sendrawtransaction in separate methods
* Moved 'secondsPerBlock' to config file
* Implemented Kim suggestions:
1) Fixed data race issues
2) refactor Verify method
3) Get rid of unused InputIntersection method due to refactoring Verify method
4) Fixed bug in https://github.com/CityOfZion/neo-go/pull/174#discussion_r264108135
5) minor simplications of the code
* Fixed minor issues related to
1) space
2) getter methods do not need pointer on the receiver
3) error message
4) refactoring CompareTo method in uint256.go
* Fixed small issues
* Use sync.RWMutex instead of sync.Mutex
* Refined (R)Lock/(R)Unlock
* return error instead of bool in Verify methods
2019-03-20 12:30:05 +00:00
|
|
|
"sort"
|
|
|
|
"sync"
|
|
|
|
"time"
|
|
|
|
|
2020-03-03 14:21:42 +00:00
|
|
|
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
|
|
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
Implement rpc server method: sendrawtransaction (#174)
* Added new config attributes: 'SecondsPerBlock','LowPriorityThreshold'
* Added new files:
* Added new method: CompareTo
* Fixed empty Slice case
* Added new methods: LessThan, GreaterThan, Equal, CompareTo
* Added new method: InputIntersection
* Added MaxTransactionSize, GroupOutputByAssetID
* Added ned method: ScriptHash
* Added new method: IsDoubleSpend
* Refactor blockchainer, Added Feer interface, Verify and GetMemPool method
* 1) Added MemPool
2) Added new methods to satisfy the blockchainer interface: IsLowPriority, Verify, GetMemPool
* Added new methods: RelayTxn, RelayDirectly
* Fixed tests
* Implemented RPC server method sendrawtransaction
* Refactor getrawtransaction, sendrawtransaction in separate methods
* Moved 'secondsPerBlock' to config file
* Implemented Kim suggestions:
1) Fixed data race issues
2) refactor Verify method
3) Get rid of unused InputIntersection method due to refactoring Verify method
4) Fixed bug in https://github.com/CityOfZion/neo-go/pull/174#discussion_r264108135
5) minor simplications of the code
* Fixed minor issues related to
1) space
2) getter methods do not need pointer on the receiver
3) error message
4) refactoring CompareTo method in uint256.go
* Fixed small issues
* Use sync.RWMutex instead of sync.Mutex
* Refined (R)Lock/(R)Unlock
* return error instead of bool in Verify methods
2019-03-20 12:30:05 +00:00
|
|
|
)
|
|
|
|
|
2020-02-04 15:43:21 +00:00
|
|
|
var (
|
|
|
|
// ErrConflict is returned when transaction being added is incompatible
|
|
|
|
// with the contents of the memory pool (using the same inputs as some
|
|
|
|
// other transaction in the pool)
|
|
|
|
ErrConflict = errors.New("conflicts with the memory pool")
|
|
|
|
// ErrDup is returned when transaction being added is already present
|
|
|
|
// in the memory pool.
|
|
|
|
ErrDup = errors.New("already in the memory pool")
|
|
|
|
// ErrOOM is returned when transaction just doesn't fit in the memory
|
|
|
|
// pool because of its capacity constraints.
|
|
|
|
ErrOOM = errors.New("out of memory")
|
|
|
|
)
|
|
|
|
|
2020-02-05 11:24:36 +00:00
|
|
|
// item represents a transaction in the the Memory pool.
|
|
|
|
type item struct {
|
2020-05-08 17:54:24 +00:00
|
|
|
txn *transaction.Transaction
|
|
|
|
timeStamp time.Time
|
|
|
|
isLowPrio bool
|
Implement rpc server method: sendrawtransaction (#174)
* Added new config attributes: 'SecondsPerBlock','LowPriorityThreshold'
* Added new files:
* Added new method: CompareTo
* Fixed empty Slice case
* Added new methods: LessThan, GreaterThan, Equal, CompareTo
* Added new method: InputIntersection
* Added MaxTransactionSize, GroupOutputByAssetID
* Added ned method: ScriptHash
* Added new method: IsDoubleSpend
* Refactor blockchainer, Added Feer interface, Verify and GetMemPool method
* 1) Added MemPool
2) Added new methods to satisfy the blockchainer interface: IsLowPriority, Verify, GetMemPool
* Added new methods: RelayTxn, RelayDirectly
* Fixed tests
* Implemented RPC server method sendrawtransaction
* Refactor getrawtransaction, sendrawtransaction in separate methods
* Moved 'secondsPerBlock' to config file
* Implemented Kim suggestions:
1) Fixed data race issues
2) refactor Verify method
3) Get rid of unused InputIntersection method due to refactoring Verify method
4) Fixed bug in https://github.com/CityOfZion/neo-go/pull/174#discussion_r264108135
5) minor simplications of the code
* Fixed minor issues related to
1) space
2) getter methods do not need pointer on the receiver
3) error message
4) refactoring CompareTo method in uint256.go
* Fixed small issues
* Use sync.RWMutex instead of sync.Mutex
* Refined (R)Lock/(R)Unlock
* return error instead of bool in Verify methods
2019-03-20 12:30:05 +00:00
|
|
|
}
|
|
|
|
|
2020-02-05 11:24:36 +00:00
|
|
|
// items is a slice of item.
|
|
|
|
type items []*item
|
Implement rpc server method: sendrawtransaction (#174)
* Added new config attributes: 'SecondsPerBlock','LowPriorityThreshold'
* Added new files:
* Added new method: CompareTo
* Fixed empty Slice case
* Added new methods: LessThan, GreaterThan, Equal, CompareTo
* Added new method: InputIntersection
* Added MaxTransactionSize, GroupOutputByAssetID
* Added ned method: ScriptHash
* Added new method: IsDoubleSpend
* Refactor blockchainer, Added Feer interface, Verify and GetMemPool method
* 1) Added MemPool
2) Added new methods to satisfy the blockchainer interface: IsLowPriority, Verify, GetMemPool
* Added new methods: RelayTxn, RelayDirectly
* Fixed tests
* Implemented RPC server method sendrawtransaction
* Refactor getrawtransaction, sendrawtransaction in separate methods
* Moved 'secondsPerBlock' to config file
* Implemented Kim suggestions:
1) Fixed data race issues
2) refactor Verify method
3) Get rid of unused InputIntersection method due to refactoring Verify method
4) Fixed bug in https://github.com/CityOfZion/neo-go/pull/174#discussion_r264108135
5) minor simplications of the code
* Fixed minor issues related to
1) space
2) getter methods do not need pointer on the receiver
3) error message
4) refactoring CompareTo method in uint256.go
* Fixed small issues
* Use sync.RWMutex instead of sync.Mutex
* Refined (R)Lock/(R)Unlock
* return error instead of bool in Verify methods
2019-03-20 12:30:05 +00:00
|
|
|
|
2020-02-18 15:56:41 +00:00
|
|
|
// TxWithFee combines transaction and its precalculated network fee.
|
|
|
|
type TxWithFee struct {
|
|
|
|
Tx *transaction.Transaction
|
|
|
|
Fee util.Fixed8
|
|
|
|
}
|
|
|
|
|
2020-05-18 08:20:41 +00:00
|
|
|
// utilityBalanceAndFees stores sender's balance and overall fees of
|
|
|
|
// sender's transactions which are currently in mempool
|
|
|
|
type utilityBalanceAndFees struct {
|
|
|
|
balance util.Fixed8
|
|
|
|
feeSum util.Fixed8
|
|
|
|
}
|
|
|
|
|
2020-01-15 12:10:05 +00:00
|
|
|
// Pool stores the unconfirms transactions.
|
|
|
|
type Pool struct {
|
2020-02-06 12:33:49 +00:00
|
|
|
lock sync.RWMutex
|
|
|
|
verifiedMap map[util.Uint256]*item
|
|
|
|
verifiedTxes items
|
2020-02-27 10:42:35 +00:00
|
|
|
inputs []*transaction.Input
|
|
|
|
claims []*transaction.Input
|
2020-05-18 08:20:41 +00:00
|
|
|
fees map[util.Uint160]utilityBalanceAndFees
|
Implement rpc server method: sendrawtransaction (#174)
* Added new config attributes: 'SecondsPerBlock','LowPriorityThreshold'
* Added new files:
* Added new method: CompareTo
* Fixed empty Slice case
* Added new methods: LessThan, GreaterThan, Equal, CompareTo
* Added new method: InputIntersection
* Added MaxTransactionSize, GroupOutputByAssetID
* Added ned method: ScriptHash
* Added new method: IsDoubleSpend
* Refactor blockchainer, Added Feer interface, Verify and GetMemPool method
* 1) Added MemPool
2) Added new methods to satisfy the blockchainer interface: IsLowPriority, Verify, GetMemPool
* Added new methods: RelayTxn, RelayDirectly
* Fixed tests
* Implemented RPC server method sendrawtransaction
* Refactor getrawtransaction, sendrawtransaction in separate methods
* Moved 'secondsPerBlock' to config file
* Implemented Kim suggestions:
1) Fixed data race issues
2) refactor Verify method
3) Get rid of unused InputIntersection method due to refactoring Verify method
4) Fixed bug in https://github.com/CityOfZion/neo-go/pull/174#discussion_r264108135
5) minor simplications of the code
* Fixed minor issues related to
1) space
2) getter methods do not need pointer on the receiver
3) error message
4) refactoring CompareTo method in uint256.go
* Fixed small issues
* Use sync.RWMutex instead of sync.Mutex
* Refined (R)Lock/(R)Unlock
* return error instead of bool in Verify methods
2019-03-20 12:30:05 +00:00
|
|
|
|
|
|
|
capacity int
|
|
|
|
}
|
|
|
|
|
2020-02-05 11:24:36 +00:00
|
|
|
func (p items) Len() int { return len(p) }
|
|
|
|
func (p items) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
|
|
|
|
func (p items) Less(i, j int) bool { return p[i].CompareTo(p[j]) < 0 }
|
Implement rpc server method: sendrawtransaction (#174)
* Added new config attributes: 'SecondsPerBlock','LowPriorityThreshold'
* Added new files:
* Added new method: CompareTo
* Fixed empty Slice case
* Added new methods: LessThan, GreaterThan, Equal, CompareTo
* Added new method: InputIntersection
* Added MaxTransactionSize, GroupOutputByAssetID
* Added ned method: ScriptHash
* Added new method: IsDoubleSpend
* Refactor blockchainer, Added Feer interface, Verify and GetMemPool method
* 1) Added MemPool
2) Added new methods to satisfy the blockchainer interface: IsLowPriority, Verify, GetMemPool
* Added new methods: RelayTxn, RelayDirectly
* Fixed tests
* Implemented RPC server method sendrawtransaction
* Refactor getrawtransaction, sendrawtransaction in separate methods
* Moved 'secondsPerBlock' to config file
* Implemented Kim suggestions:
1) Fixed data race issues
2) refactor Verify method
3) Get rid of unused InputIntersection method due to refactoring Verify method
4) Fixed bug in https://github.com/CityOfZion/neo-go/pull/174#discussion_r264108135
5) minor simplications of the code
* Fixed minor issues related to
1) space
2) getter methods do not need pointer on the receiver
3) error message
4) refactoring CompareTo method in uint256.go
* Fixed small issues
* Use sync.RWMutex instead of sync.Mutex
* Refined (R)Lock/(R)Unlock
* return error instead of bool in Verify methods
2019-03-20 12:30:05 +00:00
|
|
|
|
2020-02-05 11:24:36 +00:00
|
|
|
// CompareTo returns the difference between two items.
|
Implement rpc server method: sendrawtransaction (#174)
* Added new config attributes: 'SecondsPerBlock','LowPriorityThreshold'
* Added new files:
* Added new method: CompareTo
* Fixed empty Slice case
* Added new methods: LessThan, GreaterThan, Equal, CompareTo
* Added new method: InputIntersection
* Added MaxTransactionSize, GroupOutputByAssetID
* Added ned method: ScriptHash
* Added new method: IsDoubleSpend
* Refactor blockchainer, Added Feer interface, Verify and GetMemPool method
* 1) Added MemPool
2) Added new methods to satisfy the blockchainer interface: IsLowPriority, Verify, GetMemPool
* Added new methods: RelayTxn, RelayDirectly
* Fixed tests
* Implemented RPC server method sendrawtransaction
* Refactor getrawtransaction, sendrawtransaction in separate methods
* Moved 'secondsPerBlock' to config file
* Implemented Kim suggestions:
1) Fixed data race issues
2) refactor Verify method
3) Get rid of unused InputIntersection method due to refactoring Verify method
4) Fixed bug in https://github.com/CityOfZion/neo-go/pull/174#discussion_r264108135
5) minor simplications of the code
* Fixed minor issues related to
1) space
2) getter methods do not need pointer on the receiver
3) error message
4) refactoring CompareTo method in uint256.go
* Fixed small issues
* Use sync.RWMutex instead of sync.Mutex
* Refined (R)Lock/(R)Unlock
* return error instead of bool in Verify methods
2019-03-20 12:30:05 +00:00
|
|
|
// difference < 0 implies p < otherP.
|
|
|
|
// difference = 0 implies p = otherP.
|
|
|
|
// difference > 0 implies p > otherP.
|
2020-02-05 14:13:35 +00:00
|
|
|
func (p *item) CompareTo(otherP *item) int {
|
Implement rpc server method: sendrawtransaction (#174)
* Added new config attributes: 'SecondsPerBlock','LowPriorityThreshold'
* Added new files:
* Added new method: CompareTo
* Fixed empty Slice case
* Added new methods: LessThan, GreaterThan, Equal, CompareTo
* Added new method: InputIntersection
* Added MaxTransactionSize, GroupOutputByAssetID
* Added ned method: ScriptHash
* Added new method: IsDoubleSpend
* Refactor blockchainer, Added Feer interface, Verify and GetMemPool method
* 1) Added MemPool
2) Added new methods to satisfy the blockchainer interface: IsLowPriority, Verify, GetMemPool
* Added new methods: RelayTxn, RelayDirectly
* Fixed tests
* Implemented RPC server method sendrawtransaction
* Refactor getrawtransaction, sendrawtransaction in separate methods
* Moved 'secondsPerBlock' to config file
* Implemented Kim suggestions:
1) Fixed data race issues
2) refactor Verify method
3) Get rid of unused InputIntersection method due to refactoring Verify method
4) Fixed bug in https://github.com/CityOfZion/neo-go/pull/174#discussion_r264108135
5) minor simplications of the code
* Fixed minor issues related to
1) space
2) getter methods do not need pointer on the receiver
3) error message
4) refactoring CompareTo method in uint256.go
* Fixed small issues
* Use sync.RWMutex instead of sync.Mutex
* Refined (R)Lock/(R)Unlock
* return error instead of bool in Verify methods
2019-03-20 12:30:05 +00:00
|
|
|
if otherP == nil {
|
|
|
|
return 1
|
|
|
|
}
|
|
|
|
|
2020-02-05 14:13:35 +00:00
|
|
|
if !p.isLowPrio && otherP.isLowPrio {
|
|
|
|
return 1
|
|
|
|
}
|
|
|
|
|
|
|
|
if p.isLowPrio && !otherP.isLowPrio {
|
|
|
|
return -1
|
|
|
|
}
|
|
|
|
|
2020-02-05 11:34:58 +00:00
|
|
|
if p.isLowPrio && otherP.isLowPrio {
|
Implement rpc server method: sendrawtransaction (#174)
* Added new config attributes: 'SecondsPerBlock','LowPriorityThreshold'
* Added new files:
* Added new method: CompareTo
* Fixed empty Slice case
* Added new methods: LessThan, GreaterThan, Equal, CompareTo
* Added new method: InputIntersection
* Added MaxTransactionSize, GroupOutputByAssetID
* Added ned method: ScriptHash
* Added new method: IsDoubleSpend
* Refactor blockchainer, Added Feer interface, Verify and GetMemPool method
* 1) Added MemPool
2) Added new methods to satisfy the blockchainer interface: IsLowPriority, Verify, GetMemPool
* Added new methods: RelayTxn, RelayDirectly
* Fixed tests
* Implemented RPC server method sendrawtransaction
* Refactor getrawtransaction, sendrawtransaction in separate methods
* Moved 'secondsPerBlock' to config file
* Implemented Kim suggestions:
1) Fixed data race issues
2) refactor Verify method
3) Get rid of unused InputIntersection method due to refactoring Verify method
4) Fixed bug in https://github.com/CityOfZion/neo-go/pull/174#discussion_r264108135
5) minor simplications of the code
* Fixed minor issues related to
1) space
2) getter methods do not need pointer on the receiver
3) error message
4) refactoring CompareTo method in uint256.go
* Fixed small issues
* Use sync.RWMutex instead of sync.Mutex
* Refined (R)Lock/(R)Unlock
* return error instead of bool in Verify methods
2019-03-20 12:30:05 +00:00
|
|
|
thisIsClaimTx := p.txn.Type == transaction.ClaimType
|
|
|
|
otherIsClaimTx := otherP.txn.Type == transaction.ClaimType
|
|
|
|
|
|
|
|
if thisIsClaimTx != otherIsClaimTx {
|
|
|
|
// This is a claim Tx and other isn't.
|
|
|
|
if thisIsClaimTx {
|
|
|
|
return 1
|
|
|
|
}
|
|
|
|
// The other is claim Tx and this isn't.
|
|
|
|
return -1
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-22 14:56:03 +00:00
|
|
|
// Fees sorted ascending.
|
2020-05-08 17:54:24 +00:00
|
|
|
if ret := p.txn.FeePerByte().CompareTo(otherP.txn.FeePerByte()); ret != 0 {
|
Implement rpc server method: sendrawtransaction (#174)
* Added new config attributes: 'SecondsPerBlock','LowPriorityThreshold'
* Added new files:
* Added new method: CompareTo
* Fixed empty Slice case
* Added new methods: LessThan, GreaterThan, Equal, CompareTo
* Added new method: InputIntersection
* Added MaxTransactionSize, GroupOutputByAssetID
* Added ned method: ScriptHash
* Added new method: IsDoubleSpend
* Refactor blockchainer, Added Feer interface, Verify and GetMemPool method
* 1) Added MemPool
2) Added new methods to satisfy the blockchainer interface: IsLowPriority, Verify, GetMemPool
* Added new methods: RelayTxn, RelayDirectly
* Fixed tests
* Implemented RPC server method sendrawtransaction
* Refactor getrawtransaction, sendrawtransaction in separate methods
* Moved 'secondsPerBlock' to config file
* Implemented Kim suggestions:
1) Fixed data race issues
2) refactor Verify method
3) Get rid of unused InputIntersection method due to refactoring Verify method
4) Fixed bug in https://github.com/CityOfZion/neo-go/pull/174#discussion_r264108135
5) minor simplications of the code
* Fixed minor issues related to
1) space
2) getter methods do not need pointer on the receiver
3) error message
4) refactoring CompareTo method in uint256.go
* Fixed small issues
* Use sync.RWMutex instead of sync.Mutex
* Refined (R)Lock/(R)Unlock
* return error instead of bool in Verify methods
2019-03-20 12:30:05 +00:00
|
|
|
return ret
|
|
|
|
}
|
|
|
|
|
2020-05-08 17:54:24 +00:00
|
|
|
if ret := p.txn.NetworkFee.CompareTo(otherP.txn.NetworkFee); ret != 0 {
|
Implement rpc server method: sendrawtransaction (#174)
* Added new config attributes: 'SecondsPerBlock','LowPriorityThreshold'
* Added new files:
* Added new method: CompareTo
* Fixed empty Slice case
* Added new methods: LessThan, GreaterThan, Equal, CompareTo
* Added new method: InputIntersection
* Added MaxTransactionSize, GroupOutputByAssetID
* Added ned method: ScriptHash
* Added new method: IsDoubleSpend
* Refactor blockchainer, Added Feer interface, Verify and GetMemPool method
* 1) Added MemPool
2) Added new methods to satisfy the blockchainer interface: IsLowPriority, Verify, GetMemPool
* Added new methods: RelayTxn, RelayDirectly
* Fixed tests
* Implemented RPC server method sendrawtransaction
* Refactor getrawtransaction, sendrawtransaction in separate methods
* Moved 'secondsPerBlock' to config file
* Implemented Kim suggestions:
1) Fixed data race issues
2) refactor Verify method
3) Get rid of unused InputIntersection method due to refactoring Verify method
4) Fixed bug in https://github.com/CityOfZion/neo-go/pull/174#discussion_r264108135
5) minor simplications of the code
* Fixed minor issues related to
1) space
2) getter methods do not need pointer on the receiver
3) error message
4) refactoring CompareTo method in uint256.go
* Fixed small issues
* Use sync.RWMutex instead of sync.Mutex
* Refined (R)Lock/(R)Unlock
* return error instead of bool in Verify methods
2019-03-20 12:30:05 +00:00
|
|
|
return ret
|
|
|
|
}
|
|
|
|
|
2019-10-22 14:56:03 +00:00
|
|
|
// Transaction hash sorted descending.
|
Implement rpc server method: sendrawtransaction (#174)
* Added new config attributes: 'SecondsPerBlock','LowPriorityThreshold'
* Added new files:
* Added new method: CompareTo
* Fixed empty Slice case
* Added new methods: LessThan, GreaterThan, Equal, CompareTo
* Added new method: InputIntersection
* Added MaxTransactionSize, GroupOutputByAssetID
* Added ned method: ScriptHash
* Added new method: IsDoubleSpend
* Refactor blockchainer, Added Feer interface, Verify and GetMemPool method
* 1) Added MemPool
2) Added new methods to satisfy the blockchainer interface: IsLowPriority, Verify, GetMemPool
* Added new methods: RelayTxn, RelayDirectly
* Fixed tests
* Implemented RPC server method sendrawtransaction
* Refactor getrawtransaction, sendrawtransaction in separate methods
* Moved 'secondsPerBlock' to config file
* Implemented Kim suggestions:
1) Fixed data race issues
2) refactor Verify method
3) Get rid of unused InputIntersection method due to refactoring Verify method
4) Fixed bug in https://github.com/CityOfZion/neo-go/pull/174#discussion_r264108135
5) minor simplications of the code
* Fixed minor issues related to
1) space
2) getter methods do not need pointer on the receiver
3) error message
4) refactoring CompareTo method in uint256.go
* Fixed small issues
* Use sync.RWMutex instead of sync.Mutex
* Refined (R)Lock/(R)Unlock
* return error instead of bool in Verify methods
2019-03-20 12:30:05 +00:00
|
|
|
return otherP.txn.Hash().CompareTo(p.txn.Hash())
|
|
|
|
}
|
|
|
|
|
|
|
|
// Count returns the total number of uncofirm transactions.
|
2020-02-04 14:36:11 +00:00
|
|
|
func (mp *Pool) Count() int {
|
Implement rpc server method: sendrawtransaction (#174)
* Added new config attributes: 'SecondsPerBlock','LowPriorityThreshold'
* Added new files:
* Added new method: CompareTo
* Fixed empty Slice case
* Added new methods: LessThan, GreaterThan, Equal, CompareTo
* Added new method: InputIntersection
* Added MaxTransactionSize, GroupOutputByAssetID
* Added ned method: ScriptHash
* Added new method: IsDoubleSpend
* Refactor blockchainer, Added Feer interface, Verify and GetMemPool method
* 1) Added MemPool
2) Added new methods to satisfy the blockchainer interface: IsLowPriority, Verify, GetMemPool
* Added new methods: RelayTxn, RelayDirectly
* Fixed tests
* Implemented RPC server method sendrawtransaction
* Refactor getrawtransaction, sendrawtransaction in separate methods
* Moved 'secondsPerBlock' to config file
* Implemented Kim suggestions:
1) Fixed data race issues
2) refactor Verify method
3) Get rid of unused InputIntersection method due to refactoring Verify method
4) Fixed bug in https://github.com/CityOfZion/neo-go/pull/174#discussion_r264108135
5) minor simplications of the code
* Fixed minor issues related to
1) space
2) getter methods do not need pointer on the receiver
3) error message
4) refactoring CompareTo method in uint256.go
* Fixed small issues
* Use sync.RWMutex instead of sync.Mutex
* Refined (R)Lock/(R)Unlock
* return error instead of bool in Verify methods
2019-03-20 12:30:05 +00:00
|
|
|
mp.lock.RLock()
|
|
|
|
defer mp.lock.RUnlock()
|
2020-02-05 15:18:34 +00:00
|
|
|
return mp.count()
|
|
|
|
}
|
Implement rpc server method: sendrawtransaction (#174)
* Added new config attributes: 'SecondsPerBlock','LowPriorityThreshold'
* Added new files:
* Added new method: CompareTo
* Fixed empty Slice case
* Added new methods: LessThan, GreaterThan, Equal, CompareTo
* Added new method: InputIntersection
* Added MaxTransactionSize, GroupOutputByAssetID
* Added ned method: ScriptHash
* Added new method: IsDoubleSpend
* Refactor blockchainer, Added Feer interface, Verify and GetMemPool method
* 1) Added MemPool
2) Added new methods to satisfy the blockchainer interface: IsLowPriority, Verify, GetMemPool
* Added new methods: RelayTxn, RelayDirectly
* Fixed tests
* Implemented RPC server method sendrawtransaction
* Refactor getrawtransaction, sendrawtransaction in separate methods
* Moved 'secondsPerBlock' to config file
* Implemented Kim suggestions:
1) Fixed data race issues
2) refactor Verify method
3) Get rid of unused InputIntersection method due to refactoring Verify method
4) Fixed bug in https://github.com/CityOfZion/neo-go/pull/174#discussion_r264108135
5) minor simplications of the code
* Fixed minor issues related to
1) space
2) getter methods do not need pointer on the receiver
3) error message
4) refactoring CompareTo method in uint256.go
* Fixed small issues
* Use sync.RWMutex instead of sync.Mutex
* Refined (R)Lock/(R)Unlock
* return error instead of bool in Verify methods
2019-03-20 12:30:05 +00:00
|
|
|
|
2020-02-05 15:18:34 +00:00
|
|
|
// count is an internal unlocked version of Count.
|
|
|
|
func (mp *Pool) count() int {
|
2020-02-06 12:33:49 +00:00
|
|
|
return len(mp.verifiedTxes)
|
Implement rpc server method: sendrawtransaction (#174)
* Added new config attributes: 'SecondsPerBlock','LowPriorityThreshold'
* Added new files:
* Added new method: CompareTo
* Fixed empty Slice case
* Added new methods: LessThan, GreaterThan, Equal, CompareTo
* Added new method: InputIntersection
* Added MaxTransactionSize, GroupOutputByAssetID
* Added ned method: ScriptHash
* Added new method: IsDoubleSpend
* Refactor blockchainer, Added Feer interface, Verify and GetMemPool method
* 1) Added MemPool
2) Added new methods to satisfy the blockchainer interface: IsLowPriority, Verify, GetMemPool
* Added new methods: RelayTxn, RelayDirectly
* Fixed tests
* Implemented RPC server method sendrawtransaction
* Refactor getrawtransaction, sendrawtransaction in separate methods
* Moved 'secondsPerBlock' to config file
* Implemented Kim suggestions:
1) Fixed data race issues
2) refactor Verify method
3) Get rid of unused InputIntersection method due to refactoring Verify method
4) Fixed bug in https://github.com/CityOfZion/neo-go/pull/174#discussion_r264108135
5) minor simplications of the code
* Fixed minor issues related to
1) space
2) getter methods do not need pointer on the receiver
3) error message
4) refactoring CompareTo method in uint256.go
* Fixed small issues
* Use sync.RWMutex instead of sync.Mutex
* Refined (R)Lock/(R)Unlock
* return error instead of bool in Verify methods
2019-03-20 12:30:05 +00:00
|
|
|
}
|
|
|
|
|
2020-01-15 12:10:05 +00:00
|
|
|
// ContainsKey checks if a transactions hash is in the Pool.
|
2020-02-04 14:36:11 +00:00
|
|
|
func (mp *Pool) ContainsKey(hash util.Uint256) bool {
|
Implement rpc server method: sendrawtransaction (#174)
* Added new config attributes: 'SecondsPerBlock','LowPriorityThreshold'
* Added new files:
* Added new method: CompareTo
* Fixed empty Slice case
* Added new methods: LessThan, GreaterThan, Equal, CompareTo
* Added new method: InputIntersection
* Added MaxTransactionSize, GroupOutputByAssetID
* Added ned method: ScriptHash
* Added new method: IsDoubleSpend
* Refactor blockchainer, Added Feer interface, Verify and GetMemPool method
* 1) Added MemPool
2) Added new methods to satisfy the blockchainer interface: IsLowPriority, Verify, GetMemPool
* Added new methods: RelayTxn, RelayDirectly
* Fixed tests
* Implemented RPC server method sendrawtransaction
* Refactor getrawtransaction, sendrawtransaction in separate methods
* Moved 'secondsPerBlock' to config file
* Implemented Kim suggestions:
1) Fixed data race issues
2) refactor Verify method
3) Get rid of unused InputIntersection method due to refactoring Verify method
4) Fixed bug in https://github.com/CityOfZion/neo-go/pull/174#discussion_r264108135
5) minor simplications of the code
* Fixed minor issues related to
1) space
2) getter methods do not need pointer on the receiver
3) error message
4) refactoring CompareTo method in uint256.go
* Fixed small issues
* Use sync.RWMutex instead of sync.Mutex
* Refined (R)Lock/(R)Unlock
* return error instead of bool in Verify methods
2019-03-20 12:30:05 +00:00
|
|
|
mp.lock.RLock()
|
|
|
|
defer mp.lock.RUnlock()
|
|
|
|
|
2020-02-05 14:13:35 +00:00
|
|
|
return mp.containsKey(hash)
|
|
|
|
}
|
|
|
|
|
|
|
|
// containsKey is an internal unlocked version of ContainsKey.
|
|
|
|
func (mp *Pool) containsKey(hash util.Uint256) bool {
|
|
|
|
if _, ok := mp.verifiedMap[hash]; ok {
|
Implement rpc server method: sendrawtransaction (#174)
* Added new config attributes: 'SecondsPerBlock','LowPriorityThreshold'
* Added new files:
* Added new method: CompareTo
* Fixed empty Slice case
* Added new methods: LessThan, GreaterThan, Equal, CompareTo
* Added new method: InputIntersection
* Added MaxTransactionSize, GroupOutputByAssetID
* Added ned method: ScriptHash
* Added new method: IsDoubleSpend
* Refactor blockchainer, Added Feer interface, Verify and GetMemPool method
* 1) Added MemPool
2) Added new methods to satisfy the blockchainer interface: IsLowPriority, Verify, GetMemPool
* Added new methods: RelayTxn, RelayDirectly
* Fixed tests
* Implemented RPC server method sendrawtransaction
* Refactor getrawtransaction, sendrawtransaction in separate methods
* Moved 'secondsPerBlock' to config file
* Implemented Kim suggestions:
1) Fixed data race issues
2) refactor Verify method
3) Get rid of unused InputIntersection method due to refactoring Verify method
4) Fixed bug in https://github.com/CityOfZion/neo-go/pull/174#discussion_r264108135
5) minor simplications of the code
* Fixed minor issues related to
1) space
2) getter methods do not need pointer on the receiver
3) error message
4) refactoring CompareTo method in uint256.go
* Fixed small issues
* Use sync.RWMutex instead of sync.Mutex
* Refined (R)Lock/(R)Unlock
* return error instead of bool in Verify methods
2019-03-20 12:30:05 +00:00
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2020-02-27 10:42:35 +00:00
|
|
|
// findIndexForInput finds an index in a sorted Input pointers slice that is
|
|
|
|
// appropriate to place this input into (or which contains an identical Input).
|
|
|
|
func findIndexForInput(slice []*transaction.Input, input *transaction.Input) int {
|
|
|
|
return sort.Search(len(slice), func(n int) bool {
|
|
|
|
return input.Cmp(slice[n]) <= 0
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
// pushInputToSortedSlice pushes new Input into the given slice.
|
|
|
|
func pushInputToSortedSlice(slice *[]*transaction.Input, input *transaction.Input) {
|
|
|
|
n := findIndexForInput(*slice, input)
|
|
|
|
*slice = append(*slice, input)
|
|
|
|
if n != len(*slice)-1 {
|
|
|
|
copy((*slice)[n+1:], (*slice)[n:])
|
|
|
|
(*slice)[n] = input
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// dropInputFromSortedSlice removes given input from the given slice.
|
|
|
|
func dropInputFromSortedSlice(slice *[]*transaction.Input, input *transaction.Input) {
|
|
|
|
n := findIndexForInput(*slice, input)
|
|
|
|
if n == len(*slice) || *input != *(*slice)[n] {
|
|
|
|
// Not present.
|
|
|
|
return
|
|
|
|
}
|
|
|
|
copy((*slice)[n:], (*slice)[n+1:])
|
|
|
|
*slice = (*slice)[:len(*slice)-1]
|
|
|
|
}
|
|
|
|
|
2020-05-18 08:20:41 +00:00
|
|
|
// tryAddSendersFee tries to add system fee and network fee to the total sender`s fee in mempool
|
|
|
|
// and returns false if sender has not enough GAS to pay
|
|
|
|
func (mp *Pool) tryAddSendersFee(tx *transaction.Transaction, feer Feer) bool {
|
|
|
|
if !mp.checkBalanceAndUpdate(tx, feer) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
mp.addSendersFee(tx)
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
// checkBalanceAndUpdate returns true in case when sender has enough GAS to pay for
|
|
|
|
// the transaction and sets sender's balance value in mempool in case if it was not set
|
|
|
|
func (mp *Pool) checkBalanceAndUpdate(tx *transaction.Transaction, feer Feer) bool {
|
|
|
|
senderFee, ok := mp.fees[tx.Sender]
|
|
|
|
if !ok {
|
|
|
|
senderFee.balance = feer.GetUtilityTokenBalance(tx.Sender)
|
|
|
|
mp.fees[tx.Sender] = senderFee
|
|
|
|
}
|
|
|
|
needFee := senderFee.feeSum + tx.SystemFee + tx.NetworkFee
|
|
|
|
if senderFee.balance < needFee {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
// addSendersFee adds system fee and network fee to the total sender`s fee in mempool
|
|
|
|
func (mp *Pool) addSendersFee(tx *transaction.Transaction) {
|
|
|
|
senderFee := mp.fees[tx.Sender]
|
|
|
|
senderFee.feeSum += tx.SystemFee + tx.NetworkFee
|
|
|
|
mp.fees[tx.Sender] = senderFee
|
|
|
|
}
|
|
|
|
|
2020-02-05 11:24:36 +00:00
|
|
|
// Add tries to add given transaction to the Pool.
|
|
|
|
func (mp *Pool) Add(t *transaction.Transaction, fee Feer) error {
|
|
|
|
var pItem = &item{
|
2020-05-08 17:54:24 +00:00
|
|
|
txn: t,
|
|
|
|
timeStamp: time.Now().UTC(),
|
2020-02-05 11:24:36 +00:00
|
|
|
}
|
2020-05-08 17:54:24 +00:00
|
|
|
pItem.isLowPrio = fee.IsLowPriority(pItem.txn.NetworkFee)
|
core: fix potential locking problem in mempool
I think it should fix this issue mentioned in the #526:
INFO[1456] blockchain persist completed blockHeight=63480 headerHeight=1810000 persistedBlocks=1 persistedKeys=4 took=740.7113ms
fatal error: concurrent map read and map write
goroutine 322 [running]:
runtime.throw(0xc8a6dc, 0x21)
/usr/local/go/src/runtime/panic.go:774 +0x72 fp=0xc003473958 sp=0xc003473928 pc=0x42e282
runtime.mapaccess2(0xb706a0, 0xc0001893b0, 0xc0034739c8, 0xc0028704e0, 0x3)
/usr/local/go/src/runtime/map.go:470 +0x278 fp=0xc0034739a0 sp=0xc003473958 pc=0x40dc08
github.com/CityOfZion/neo-go/pkg/core.MemPool.ContainsKey(0xc0001d0d20, 0xc0001893b0, 0xc0001893e0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ...)
/neo-go/pkg/core/mem_pool.go:92 +0xcb fp=0xc003473a30 sp=0xc0034739a0 pc=0x9326db
github.com/CityOfZion/neo-go/pkg/core.(*Blockchain).HasTransaction(0xc0001ca8c0, 0x49f0b45d430e441b, 0x553db79b7072821c, 0x28969518de11976, 0xba5100efddbe79d4, 0xc003473cd0)
/neo-go/pkg/core/blockchain.go:803 +0xa1 fp=0xc003473b68 sp=0xc003473a30 pc=0x914b11
github.com/CityOfZion/neo-go/pkg/core.Blockchainer.HasTransaction-fm(0x49f0b45d430e441b, 0x553db79b7072821c, 0x28969518de11976, 0xba5100efddbe79d4, 0xc005a5d388)
/neo-go/pkg/core/blockchainer.go:28 +0x46 fp=0xc003473ba8 sp=0xc003473b68 pc=0x997326
github.com/CityOfZion/neo-go/pkg/network.(*Server).handleInvCmd(0xc00018f680, 0xd9d980, 0xc00025e190, 0xc005a5d380, 0x0, 0x0)
/neo-go/pkg/network/server.go:401 +0x3bb fp=0xc003473d38 sp=0xc003473ba8 pc=0x9924cb
github.com/CityOfZion/neo-go/pkg/network.(*Server).handleMessage(0xc00018f680, 0xd9d980, 0xc00025e190, 0xc007a0d050, 0x0, 0x0)
/neo-go/pkg/network/server.go:582 +0x1ae fp=0xc003473da0 sp=0xc003473d38 pc=0x993bbe
github.com/CityOfZion/neo-go/pkg/network.(*TCPTransport).handleConn(0xc000228420, 0xd9b880, 0xc0001b6f00)
/neo-go/pkg/network/tcp_transport.go:93 +0x202 fp=0xc003473fc8 sp=0xc003473da0 pc=0x996672
runtime.goexit()
/usr/local/go/src/runtime/asm_amd64.s:1357 +0x1 fp=0xc003473fd0 sp=0xc003473fc8 pc=0x45b3e1
created by github.com/CityOfZion/neo-go/pkg/network.(*TCPTransport).Dial
/neo-go/pkg/network/tcp_transport.go:36 +0xb4
The problem is that we're modifying `unsortedTxn` under a reader lock.
2019-12-02 19:36:59 +00:00
|
|
|
mp.lock.Lock()
|
2020-05-18 08:20:41 +00:00
|
|
|
if !mp.checkTxConflicts(t, fee) {
|
2020-02-04 15:43:21 +00:00
|
|
|
mp.lock.Unlock()
|
|
|
|
return ErrConflict
|
|
|
|
}
|
2020-02-05 14:13:35 +00:00
|
|
|
if mp.containsKey(t.Hash()) {
|
core: fix potential locking problem in mempool
I think it should fix this issue mentioned in the #526:
INFO[1456] blockchain persist completed blockHeight=63480 headerHeight=1810000 persistedBlocks=1 persistedKeys=4 took=740.7113ms
fatal error: concurrent map read and map write
goroutine 322 [running]:
runtime.throw(0xc8a6dc, 0x21)
/usr/local/go/src/runtime/panic.go:774 +0x72 fp=0xc003473958 sp=0xc003473928 pc=0x42e282
runtime.mapaccess2(0xb706a0, 0xc0001893b0, 0xc0034739c8, 0xc0028704e0, 0x3)
/usr/local/go/src/runtime/map.go:470 +0x278 fp=0xc0034739a0 sp=0xc003473958 pc=0x40dc08
github.com/CityOfZion/neo-go/pkg/core.MemPool.ContainsKey(0xc0001d0d20, 0xc0001893b0, 0xc0001893e0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ...)
/neo-go/pkg/core/mem_pool.go:92 +0xcb fp=0xc003473a30 sp=0xc0034739a0 pc=0x9326db
github.com/CityOfZion/neo-go/pkg/core.(*Blockchain).HasTransaction(0xc0001ca8c0, 0x49f0b45d430e441b, 0x553db79b7072821c, 0x28969518de11976, 0xba5100efddbe79d4, 0xc003473cd0)
/neo-go/pkg/core/blockchain.go:803 +0xa1 fp=0xc003473b68 sp=0xc003473a30 pc=0x914b11
github.com/CityOfZion/neo-go/pkg/core.Blockchainer.HasTransaction-fm(0x49f0b45d430e441b, 0x553db79b7072821c, 0x28969518de11976, 0xba5100efddbe79d4, 0xc005a5d388)
/neo-go/pkg/core/blockchainer.go:28 +0x46 fp=0xc003473ba8 sp=0xc003473b68 pc=0x997326
github.com/CityOfZion/neo-go/pkg/network.(*Server).handleInvCmd(0xc00018f680, 0xd9d980, 0xc00025e190, 0xc005a5d380, 0x0, 0x0)
/neo-go/pkg/network/server.go:401 +0x3bb fp=0xc003473d38 sp=0xc003473ba8 pc=0x9924cb
github.com/CityOfZion/neo-go/pkg/network.(*Server).handleMessage(0xc00018f680, 0xd9d980, 0xc00025e190, 0xc007a0d050, 0x0, 0x0)
/neo-go/pkg/network/server.go:582 +0x1ae fp=0xc003473da0 sp=0xc003473d38 pc=0x993bbe
github.com/CityOfZion/neo-go/pkg/network.(*TCPTransport).handleConn(0xc000228420, 0xd9b880, 0xc0001b6f00)
/neo-go/pkg/network/tcp_transport.go:93 +0x202 fp=0xc003473fc8 sp=0xc003473da0 pc=0x996672
runtime.goexit()
/usr/local/go/src/runtime/asm_amd64.s:1357 +0x1 fp=0xc003473fd0 sp=0xc003473fc8 pc=0x45b3e1
created by github.com/CityOfZion/neo-go/pkg/network.(*TCPTransport).Dial
/neo-go/pkg/network/tcp_transport.go:36 +0xb4
The problem is that we're modifying `unsortedTxn` under a reader lock.
2019-12-02 19:36:59 +00:00
|
|
|
mp.lock.Unlock()
|
2020-02-04 15:43:21 +00:00
|
|
|
return ErrDup
|
Implement rpc server method: sendrawtransaction (#174)
* Added new config attributes: 'SecondsPerBlock','LowPriorityThreshold'
* Added new files:
* Added new method: CompareTo
* Fixed empty Slice case
* Added new methods: LessThan, GreaterThan, Equal, CompareTo
* Added new method: InputIntersection
* Added MaxTransactionSize, GroupOutputByAssetID
* Added ned method: ScriptHash
* Added new method: IsDoubleSpend
* Refactor blockchainer, Added Feer interface, Verify and GetMemPool method
* 1) Added MemPool
2) Added new methods to satisfy the blockchainer interface: IsLowPriority, Verify, GetMemPool
* Added new methods: RelayTxn, RelayDirectly
* Fixed tests
* Implemented RPC server method sendrawtransaction
* Refactor getrawtransaction, sendrawtransaction in separate methods
* Moved 'secondsPerBlock' to config file
* Implemented Kim suggestions:
1) Fixed data race issues
2) refactor Verify method
3) Get rid of unused InputIntersection method due to refactoring Verify method
4) Fixed bug in https://github.com/CityOfZion/neo-go/pull/174#discussion_r264108135
5) minor simplications of the code
* Fixed minor issues related to
1) space
2) getter methods do not need pointer on the receiver
3) error message
4) refactoring CompareTo method in uint256.go
* Fixed small issues
* Use sync.RWMutex instead of sync.Mutex
* Refined (R)Lock/(R)Unlock
* return error instead of bool in Verify methods
2019-03-20 12:30:05 +00:00
|
|
|
}
|
|
|
|
|
2020-02-05 14:13:35 +00:00
|
|
|
mp.verifiedMap[t.Hash()] = pItem
|
2020-02-05 15:18:34 +00:00
|
|
|
// Insert into sorted array (from max to min, that could also be done
|
|
|
|
// using sort.Sort(sort.Reverse()), but it incurs more overhead. Notice
|
|
|
|
// also that we're searching for position that is strictly more
|
|
|
|
// prioritized than our new item because we do expect a lot of
|
|
|
|
// transactions with the same priority and appending to the end of the
|
|
|
|
// slice is always more efficient.
|
|
|
|
n := sort.Search(len(mp.verifiedTxes), func(n int) bool {
|
|
|
|
return pItem.CompareTo(mp.verifiedTxes[n]) > 0
|
|
|
|
})
|
2020-02-06 14:38:59 +00:00
|
|
|
|
|
|
|
// We've reached our capacity already.
|
|
|
|
if len(mp.verifiedTxes) == mp.capacity {
|
|
|
|
// Less prioritized than the least prioritized we already have, won't fit.
|
|
|
|
if n == len(mp.verifiedTxes) {
|
|
|
|
mp.lock.Unlock()
|
|
|
|
return ErrOOM
|
|
|
|
}
|
|
|
|
// Ditch the last one.
|
|
|
|
unlucky := mp.verifiedTxes[len(mp.verifiedTxes)-1]
|
|
|
|
delete(mp.verifiedMap, unlucky.txn.Hash())
|
|
|
|
mp.verifiedTxes[len(mp.verifiedTxes)-1] = pItem
|
|
|
|
} else {
|
|
|
|
mp.verifiedTxes = append(mp.verifiedTxes, pItem)
|
|
|
|
}
|
|
|
|
if n != len(mp.verifiedTxes)-1 {
|
2020-02-05 15:18:34 +00:00
|
|
|
copy(mp.verifiedTxes[n+1:], mp.verifiedTxes[n:])
|
|
|
|
mp.verifiedTxes[n] = pItem
|
|
|
|
}
|
2020-05-18 08:20:41 +00:00
|
|
|
mp.addSendersFee(pItem.txn)
|
2020-02-27 10:42:35 +00:00
|
|
|
|
|
|
|
// For lots of inputs it might be easier to push them all and sort
|
|
|
|
// afterwards, but that requires benchmarking.
|
|
|
|
for i := range t.Inputs {
|
|
|
|
pushInputToSortedSlice(&mp.inputs, &t.Inputs[i])
|
|
|
|
}
|
|
|
|
if t.Type == transaction.ClaimType {
|
|
|
|
claim := t.Data.(*transaction.ClaimTX)
|
|
|
|
for i := range claim.Claims {
|
|
|
|
pushInputToSortedSlice(&mp.claims, &claim.Claims[i])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-06 12:33:49 +00:00
|
|
|
updateMempoolMetrics(len(mp.verifiedTxes))
|
2020-02-06 14:38:59 +00:00
|
|
|
mp.lock.Unlock()
|
2020-02-04 15:43:21 +00:00
|
|
|
return nil
|
Implement rpc server method: sendrawtransaction (#174)
* Added new config attributes: 'SecondsPerBlock','LowPriorityThreshold'
* Added new files:
* Added new method: CompareTo
* Fixed empty Slice case
* Added new methods: LessThan, GreaterThan, Equal, CompareTo
* Added new method: InputIntersection
* Added MaxTransactionSize, GroupOutputByAssetID
* Added ned method: ScriptHash
* Added new method: IsDoubleSpend
* Refactor blockchainer, Added Feer interface, Verify and GetMemPool method
* 1) Added MemPool
2) Added new methods to satisfy the blockchainer interface: IsLowPriority, Verify, GetMemPool
* Added new methods: RelayTxn, RelayDirectly
* Fixed tests
* Implemented RPC server method sendrawtransaction
* Refactor getrawtransaction, sendrawtransaction in separate methods
* Moved 'secondsPerBlock' to config file
* Implemented Kim suggestions:
1) Fixed data race issues
2) refactor Verify method
3) Get rid of unused InputIntersection method due to refactoring Verify method
4) Fixed bug in https://github.com/CityOfZion/neo-go/pull/174#discussion_r264108135
5) minor simplications of the code
* Fixed minor issues related to
1) space
2) getter methods do not need pointer on the receiver
3) error message
4) refactoring CompareTo method in uint256.go
* Fixed small issues
* Use sync.RWMutex instead of sync.Mutex
* Refined (R)Lock/(R)Unlock
* return error instead of bool in Verify methods
2019-03-20 12:30:05 +00:00
|
|
|
}
|
|
|
|
|
2019-10-24 09:29:55 +00:00
|
|
|
// Remove removes an item from the mempool, if it exists there (and does
|
|
|
|
// nothing if it doesn't).
|
2020-01-15 12:10:05 +00:00
|
|
|
func (mp *Pool) Remove(hash util.Uint256) {
|
2019-10-24 09:29:55 +00:00
|
|
|
mp.lock.Lock()
|
2020-02-27 10:42:35 +00:00
|
|
|
if it, ok := mp.verifiedMap[hash]; ok {
|
2020-02-06 12:33:49 +00:00
|
|
|
var num int
|
|
|
|
delete(mp.verifiedMap, hash)
|
2020-02-27 10:40:58 +00:00
|
|
|
for num = range mp.verifiedTxes {
|
2020-02-06 12:33:49 +00:00
|
|
|
if hash.Equals(mp.verifiedTxes[num].txn.Hash()) {
|
|
|
|
break
|
2020-02-05 14:13:35 +00:00
|
|
|
}
|
2019-10-24 09:29:55 +00:00
|
|
|
}
|
2020-02-06 12:33:49 +00:00
|
|
|
if num < len(mp.verifiedTxes)-1 {
|
|
|
|
mp.verifiedTxes = append(mp.verifiedTxes[:num], mp.verifiedTxes[num+1:]...)
|
|
|
|
} else if num == len(mp.verifiedTxes)-1 {
|
|
|
|
mp.verifiedTxes = mp.verifiedTxes[:num]
|
|
|
|
}
|
2020-05-18 08:20:41 +00:00
|
|
|
senderFee := mp.fees[it.txn.Sender]
|
|
|
|
senderFee.feeSum -= it.txn.SystemFee + it.txn.NetworkFee
|
|
|
|
mp.fees[it.txn.Sender] = senderFee
|
2020-02-27 10:42:35 +00:00
|
|
|
for i := range it.txn.Inputs {
|
|
|
|
dropInputFromSortedSlice(&mp.inputs, &it.txn.Inputs[i])
|
|
|
|
}
|
|
|
|
if it.txn.Type == transaction.ClaimType {
|
|
|
|
claim := it.txn.Data.(*transaction.ClaimTX)
|
|
|
|
for i := range claim.Claims {
|
|
|
|
dropInputFromSortedSlice(&mp.claims, &claim.Claims[i])
|
|
|
|
}
|
|
|
|
}
|
2019-10-24 09:29:55 +00:00
|
|
|
}
|
2020-02-06 12:33:49 +00:00
|
|
|
updateMempoolMetrics(len(mp.verifiedTxes))
|
2019-10-24 09:29:55 +00:00
|
|
|
mp.lock.Unlock()
|
|
|
|
}
|
|
|
|
|
2020-02-05 21:23:49 +00:00
|
|
|
// RemoveStale filters verified transactions through the given function keeping
|
|
|
|
// only the transactions for which it returns a true result. It's used to quickly
|
|
|
|
// drop part of the mempool that is now invalid after the block acceptance.
|
2020-05-18 08:20:41 +00:00
|
|
|
func (mp *Pool) RemoveStale(isOK func(*transaction.Transaction) bool, feer Feer) {
|
2020-02-05 21:23:49 +00:00
|
|
|
mp.lock.Lock()
|
2020-02-19 13:10:40 +00:00
|
|
|
// We can reuse already allocated slice
|
|
|
|
// because items are iterated one-by-one in increasing order.
|
|
|
|
newVerifiedTxes := mp.verifiedTxes[:0]
|
2020-02-27 10:42:35 +00:00
|
|
|
newInputs := mp.inputs[:0]
|
|
|
|
newClaims := mp.claims[:0]
|
2020-05-18 08:20:41 +00:00
|
|
|
mp.fees = make(map[util.Uint160]utilityBalanceAndFees) // it'd be nice to reuse existing map, but we can't easily clear it
|
2020-02-05 21:23:49 +00:00
|
|
|
for _, itm := range mp.verifiedTxes {
|
2020-05-18 08:20:41 +00:00
|
|
|
if isOK(itm.txn) && mp.tryAddSendersFee(itm.txn, feer) {
|
2020-02-05 21:23:49 +00:00
|
|
|
newVerifiedTxes = append(newVerifiedTxes, itm)
|
2020-02-27 10:42:35 +00:00
|
|
|
for i := range itm.txn.Inputs {
|
|
|
|
newInputs = append(newInputs, &itm.txn.Inputs[i])
|
|
|
|
}
|
|
|
|
if itm.txn.Type == transaction.ClaimType {
|
|
|
|
claim := itm.txn.Data.(*transaction.ClaimTX)
|
|
|
|
for i := range claim.Claims {
|
|
|
|
newClaims = append(newClaims, &claim.Claims[i])
|
|
|
|
}
|
|
|
|
}
|
2020-02-05 21:23:49 +00:00
|
|
|
} else {
|
|
|
|
delete(mp.verifiedMap, itm.txn.Hash())
|
|
|
|
}
|
|
|
|
}
|
2020-02-27 10:42:35 +00:00
|
|
|
sort.Slice(newInputs, func(i, j int) bool {
|
|
|
|
return newInputs[i].Cmp(newInputs[j]) < 0
|
|
|
|
})
|
|
|
|
sort.Slice(newClaims, func(i, j int) bool {
|
|
|
|
return newClaims[i].Cmp(newClaims[j]) < 0
|
|
|
|
})
|
2020-02-05 21:23:49 +00:00
|
|
|
mp.verifiedTxes = newVerifiedTxes
|
2020-02-27 10:42:35 +00:00
|
|
|
mp.inputs = newInputs
|
|
|
|
mp.claims = newClaims
|
2020-02-05 21:23:49 +00:00
|
|
|
mp.lock.Unlock()
|
|
|
|
}
|
|
|
|
|
2020-01-15 12:10:05 +00:00
|
|
|
// NewMemPool returns a new Pool struct.
|
|
|
|
func NewMemPool(capacity int) Pool {
|
|
|
|
return Pool{
|
2020-02-06 12:33:49 +00:00
|
|
|
verifiedMap: make(map[util.Uint256]*item),
|
|
|
|
verifiedTxes: make([]*item, 0, capacity),
|
|
|
|
capacity: capacity,
|
2020-05-18 08:20:41 +00:00
|
|
|
fees: make(map[util.Uint160]utilityBalanceAndFees),
|
Implement rpc server method: sendrawtransaction (#174)
* Added new config attributes: 'SecondsPerBlock','LowPriorityThreshold'
* Added new files:
* Added new method: CompareTo
* Fixed empty Slice case
* Added new methods: LessThan, GreaterThan, Equal, CompareTo
* Added new method: InputIntersection
* Added MaxTransactionSize, GroupOutputByAssetID
* Added ned method: ScriptHash
* Added new method: IsDoubleSpend
* Refactor blockchainer, Added Feer interface, Verify and GetMemPool method
* 1) Added MemPool
2) Added new methods to satisfy the blockchainer interface: IsLowPriority, Verify, GetMemPool
* Added new methods: RelayTxn, RelayDirectly
* Fixed tests
* Implemented RPC server method sendrawtransaction
* Refactor getrawtransaction, sendrawtransaction in separate methods
* Moved 'secondsPerBlock' to config file
* Implemented Kim suggestions:
1) Fixed data race issues
2) refactor Verify method
3) Get rid of unused InputIntersection method due to refactoring Verify method
4) Fixed bug in https://github.com/CityOfZion/neo-go/pull/174#discussion_r264108135
5) minor simplications of the code
* Fixed minor issues related to
1) space
2) getter methods do not need pointer on the receiver
3) error message
4) refactoring CompareTo method in uint256.go
* Fixed small issues
* Use sync.RWMutex instead of sync.Mutex
* Refined (R)Lock/(R)Unlock
* return error instead of bool in Verify methods
2019-03-20 12:30:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-18 15:56:41 +00:00
|
|
|
// TryGetValue returns a transaction and its fee if it exists in the memory pool.
|
|
|
|
func (mp *Pool) TryGetValue(hash util.Uint256) (*transaction.Transaction, util.Fixed8, bool) {
|
2019-12-02 19:39:43 +00:00
|
|
|
mp.lock.RLock()
|
|
|
|
defer mp.lock.RUnlock()
|
2020-02-05 14:13:35 +00:00
|
|
|
if pItem, ok := mp.verifiedMap[hash]; ok {
|
2020-05-08 17:54:24 +00:00
|
|
|
return pItem.txn, pItem.txn.NetworkFee, ok
|
Implement rpc server method: sendrawtransaction (#174)
* Added new config attributes: 'SecondsPerBlock','LowPriorityThreshold'
* Added new files:
* Added new method: CompareTo
* Fixed empty Slice case
* Added new methods: LessThan, GreaterThan, Equal, CompareTo
* Added new method: InputIntersection
* Added MaxTransactionSize, GroupOutputByAssetID
* Added ned method: ScriptHash
* Added new method: IsDoubleSpend
* Refactor blockchainer, Added Feer interface, Verify and GetMemPool method
* 1) Added MemPool
2) Added new methods to satisfy the blockchainer interface: IsLowPriority, Verify, GetMemPool
* Added new methods: RelayTxn, RelayDirectly
* Fixed tests
* Implemented RPC server method sendrawtransaction
* Refactor getrawtransaction, sendrawtransaction in separate methods
* Moved 'secondsPerBlock' to config file
* Implemented Kim suggestions:
1) Fixed data race issues
2) refactor Verify method
3) Get rid of unused InputIntersection method due to refactoring Verify method
4) Fixed bug in https://github.com/CityOfZion/neo-go/pull/174#discussion_r264108135
5) minor simplications of the code
* Fixed minor issues related to
1) space
2) getter methods do not need pointer on the receiver
3) error message
4) refactoring CompareTo method in uint256.go
* Fixed small issues
* Use sync.RWMutex instead of sync.Mutex
* Refined (R)Lock/(R)Unlock
* return error instead of bool in Verify methods
2019-03-20 12:30:05 +00:00
|
|
|
}
|
|
|
|
|
2020-02-18 15:56:41 +00:00
|
|
|
return nil, 0, false
|
Implement rpc server method: sendrawtransaction (#174)
* Added new config attributes: 'SecondsPerBlock','LowPriorityThreshold'
* Added new files:
* Added new method: CompareTo
* Fixed empty Slice case
* Added new methods: LessThan, GreaterThan, Equal, CompareTo
* Added new method: InputIntersection
* Added MaxTransactionSize, GroupOutputByAssetID
* Added ned method: ScriptHash
* Added new method: IsDoubleSpend
* Refactor blockchainer, Added Feer interface, Verify and GetMemPool method
* 1) Added MemPool
2) Added new methods to satisfy the blockchainer interface: IsLowPriority, Verify, GetMemPool
* Added new methods: RelayTxn, RelayDirectly
* Fixed tests
* Implemented RPC server method sendrawtransaction
* Refactor getrawtransaction, sendrawtransaction in separate methods
* Moved 'secondsPerBlock' to config file
* Implemented Kim suggestions:
1) Fixed data race issues
2) refactor Verify method
3) Get rid of unused InputIntersection method due to refactoring Verify method
4) Fixed bug in https://github.com/CityOfZion/neo-go/pull/174#discussion_r264108135
5) minor simplications of the code
* Fixed minor issues related to
1) space
2) getter methods do not need pointer on the receiver
3) error message
4) refactoring CompareTo method in uint256.go
* Fixed small issues
* Use sync.RWMutex instead of sync.Mutex
* Refined (R)Lock/(R)Unlock
* return error instead of bool in Verify methods
2019-03-20 12:30:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// GetVerifiedTransactions returns a slice of Input from all the transactions in the memory pool
|
|
|
|
// whose hash is not included in excludedHashes.
|
2020-02-18 15:56:41 +00:00
|
|
|
func (mp *Pool) GetVerifiedTransactions() []TxWithFee {
|
2019-12-02 19:39:43 +00:00
|
|
|
mp.lock.RLock()
|
|
|
|
defer mp.lock.RUnlock()
|
2019-12-13 16:49:43 +00:00
|
|
|
|
2020-02-18 15:56:41 +00:00
|
|
|
var t = make([]TxWithFee, len(mp.verifiedTxes))
|
2019-12-13 16:49:43 +00:00
|
|
|
|
2020-02-18 15:56:41 +00:00
|
|
|
for i := range mp.verifiedTxes {
|
|
|
|
t[i].Tx = mp.verifiedTxes[i].txn
|
2020-05-08 17:54:24 +00:00
|
|
|
t[i].Fee = mp.verifiedTxes[i].txn.NetworkFee
|
Implement rpc server method: sendrawtransaction (#174)
* Added new config attributes: 'SecondsPerBlock','LowPriorityThreshold'
* Added new files:
* Added new method: CompareTo
* Fixed empty Slice case
* Added new methods: LessThan, GreaterThan, Equal, CompareTo
* Added new method: InputIntersection
* Added MaxTransactionSize, GroupOutputByAssetID
* Added ned method: ScriptHash
* Added new method: IsDoubleSpend
* Refactor blockchainer, Added Feer interface, Verify and GetMemPool method
* 1) Added MemPool
2) Added new methods to satisfy the blockchainer interface: IsLowPriority, Verify, GetMemPool
* Added new methods: RelayTxn, RelayDirectly
* Fixed tests
* Implemented RPC server method sendrawtransaction
* Refactor getrawtransaction, sendrawtransaction in separate methods
* Moved 'secondsPerBlock' to config file
* Implemented Kim suggestions:
1) Fixed data race issues
2) refactor Verify method
3) Get rid of unused InputIntersection method due to refactoring Verify method
4) Fixed bug in https://github.com/CityOfZion/neo-go/pull/174#discussion_r264108135
5) minor simplications of the code
* Fixed minor issues related to
1) space
2) getter methods do not need pointer on the receiver
3) error message
4) refactoring CompareTo method in uint256.go
* Fixed small issues
* Use sync.RWMutex instead of sync.Mutex
* Refined (R)Lock/(R)Unlock
* return error instead of bool in Verify methods
2019-03-20 12:30:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return t
|
|
|
|
}
|
|
|
|
|
2020-03-16 16:07:23 +00:00
|
|
|
// areInputsInPool tries to find inputs in a given sorted pool and returns true
|
|
|
|
// if it finds any.
|
|
|
|
func areInputsInPool(inputs []transaction.Input, pool []*transaction.Input) bool {
|
|
|
|
for i := range inputs {
|
|
|
|
n := findIndexForInput(pool, &inputs[i])
|
|
|
|
if n < len(pool) && *pool[n] == inputs[i] {
|
|
|
|
return true
|
2020-02-27 10:42:35 +00:00
|
|
|
}
|
2020-02-04 15:58:40 +00:00
|
|
|
}
|
2020-03-16 16:07:23 +00:00
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
// checkTxConflicts is an internal unprotected version of Verify.
|
2020-05-18 08:20:41 +00:00
|
|
|
func (mp *Pool) checkTxConflicts(tx *transaction.Transaction, fee Feer) bool {
|
2020-03-16 16:07:23 +00:00
|
|
|
if areInputsInPool(tx.Inputs, mp.inputs) {
|
|
|
|
return false
|
|
|
|
}
|
2020-05-18 08:20:41 +00:00
|
|
|
if !mp.checkBalanceAndUpdate(tx, fee) {
|
|
|
|
return false
|
|
|
|
}
|
2020-03-16 16:07:23 +00:00
|
|
|
switch tx.Type {
|
|
|
|
case transaction.ClaimType:
|
2020-02-27 10:42:35 +00:00
|
|
|
claim := tx.Data.(*transaction.ClaimTX)
|
2020-03-16 16:07:23 +00:00
|
|
|
if areInputsInPool(claim.Claims, mp.claims) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
case transaction.IssueType:
|
|
|
|
// It's a hack, because technically we could check for
|
|
|
|
// available asset amount, but these transactions are so rare
|
|
|
|
// that no one really cares about this restriction.
|
|
|
|
for i := range mp.verifiedTxes {
|
|
|
|
if mp.verifiedTxes[i].txn.Type == transaction.IssueType {
|
2020-02-27 10:42:35 +00:00
|
|
|
return false
|
Implement rpc server method: sendrawtransaction (#174)
* Added new config attributes: 'SecondsPerBlock','LowPriorityThreshold'
* Added new files:
* Added new method: CompareTo
* Fixed empty Slice case
* Added new methods: LessThan, GreaterThan, Equal, CompareTo
* Added new method: InputIntersection
* Added MaxTransactionSize, GroupOutputByAssetID
* Added ned method: ScriptHash
* Added new method: IsDoubleSpend
* Refactor blockchainer, Added Feer interface, Verify and GetMemPool method
* 1) Added MemPool
2) Added new methods to satisfy the blockchainer interface: IsLowPriority, Verify, GetMemPool
* Added new methods: RelayTxn, RelayDirectly
* Fixed tests
* Implemented RPC server method sendrawtransaction
* Refactor getrawtransaction, sendrawtransaction in separate methods
* Moved 'secondsPerBlock' to config file
* Implemented Kim suggestions:
1) Fixed data race issues
2) refactor Verify method
3) Get rid of unused InputIntersection method due to refactoring Verify method
4) Fixed bug in https://github.com/CityOfZion/neo-go/pull/174#discussion_r264108135
5) minor simplications of the code
* Fixed minor issues related to
1) space
2) getter methods do not need pointer on the receiver
3) error message
4) refactoring CompareTo method in uint256.go
* Fixed small issues
* Use sync.RWMutex instead of sync.Mutex
* Refined (R)Lock/(R)Unlock
* return error instead of bool in Verify methods
2019-03-20 12:30:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-12-13 20:23:33 +00:00
|
|
|
return true
|
Implement rpc server method: sendrawtransaction (#174)
* Added new config attributes: 'SecondsPerBlock','LowPriorityThreshold'
* Added new files:
* Added new method: CompareTo
* Fixed empty Slice case
* Added new methods: LessThan, GreaterThan, Equal, CompareTo
* Added new method: InputIntersection
* Added MaxTransactionSize, GroupOutputByAssetID
* Added ned method: ScriptHash
* Added new method: IsDoubleSpend
* Refactor blockchainer, Added Feer interface, Verify and GetMemPool method
* 1) Added MemPool
2) Added new methods to satisfy the blockchainer interface: IsLowPriority, Verify, GetMemPool
* Added new methods: RelayTxn, RelayDirectly
* Fixed tests
* Implemented RPC server method sendrawtransaction
* Refactor getrawtransaction, sendrawtransaction in separate methods
* Moved 'secondsPerBlock' to config file
* Implemented Kim suggestions:
1) Fixed data race issues
2) refactor Verify method
3) Get rid of unused InputIntersection method due to refactoring Verify method
4) Fixed bug in https://github.com/CityOfZion/neo-go/pull/174#discussion_r264108135
5) minor simplications of the code
* Fixed minor issues related to
1) space
2) getter methods do not need pointer on the receiver
3) error message
4) refactoring CompareTo method in uint256.go
* Fixed small issues
* Use sync.RWMutex instead of sync.Mutex
* Refined (R)Lock/(R)Unlock
* return error instead of bool in Verify methods
2019-03-20 12:30:05 +00:00
|
|
|
}
|
2020-02-04 15:43:21 +00:00
|
|
|
|
|
|
|
// Verify verifies if the inputs of a transaction tx are already used in any other transaction in the memory pool.
|
|
|
|
// If yes, the transaction tx is not a valid transaction and the function return false.
|
|
|
|
// If no, the transaction tx is a valid transaction and the function return true.
|
2020-05-18 08:20:41 +00:00
|
|
|
func (mp *Pool) Verify(tx *transaction.Transaction, feer Feer) bool {
|
2020-02-04 15:43:21 +00:00
|
|
|
mp.lock.RLock()
|
|
|
|
defer mp.lock.RUnlock()
|
2020-05-18 08:20:41 +00:00
|
|
|
return mp.checkTxConflicts(tx, feer)
|
2020-02-04 15:43:21 +00:00
|
|
|
}
|