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"
2020-10-15 11:45:29 +00:00
"fmt"
2020-07-09 09:57:24 +00:00
"math/big"
2020-11-11 12:49:51 +00:00
"math/bits"
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"
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 (
2020-08-19 16:27:15 +00:00
// ErrInsufficientFunds is returned when Sender is not able to pay for
// transaction being added irrespective of the other contents of the
// pool.
ErrInsufficientFunds = errors . New ( "insufficient funds" )
2020-02-04 15:43:21 +00:00
// ErrConflict is returned when transaction being added is incompatible
2020-06-05 14:26:11 +00:00
// with the contents of the memory pool (Sender doesn't have enough GAS
// to pay for all transactions in the pool).
2020-02-04 15:43:21 +00:00
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-10-15 11:45:29 +00:00
// ErrConflictsAttribute is returned when transaction conflicts with other transactions
// due to its (or theirs) Conflicts attributes.
ErrConflictsAttribute = errors . New ( "conflicts with memory pool due to Conflicts attribute" )
2020-11-30 09:48:18 +00:00
// ErrOracleResponse is returned when mempool already contains transaction
// with the same oracle response ID and higher network fee.
ErrOracleResponse = errors . New ( "conflicts with memory pool due to OracleResponse attribute" )
2020-02-04 15:43:21 +00:00
)
2020-02-05 11:24:36 +00:00
// item represents a transaction in the the Memory pool.
type item struct {
2020-09-09 12:32:31 +00:00
txn * transaction . Transaction
blockStamp uint32
2020-11-27 10:55:48 +00:00
data interface { }
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.
2020-08-29 19:20:56 +00:00
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-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 {
2020-07-09 09:57:24 +00:00
balance * big . Int
2020-08-20 16:06:59 +00:00
feeSum * big . Int
2020-05-18 08:20:41 +00:00
}
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
2020-08-31 20:57:10 +00:00
verifiedMap map [ util . Uint256 ] * transaction . Transaction
2020-02-06 12:33:49 +00:00
verifiedTxes items
2020-05-18 08:20:41 +00:00
fees map [ util . Uint160 ] utilityBalanceAndFees
2020-10-15 11:45:29 +00:00
// conflicts is a map of hashes of transactions which are conflicting with the mempooled ones.
conflicts map [ util . Uint256 ] [ ] util . Uint256
2020-11-30 09:48:18 +00:00
// oracleResp contains ids of oracle responses for tx in pool.
oracleResp map [ uint64 ] util . Uint256
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-06-17 12:29:56 +00:00
capacity int
2020-06-23 14:15:35 +00:00
feePerByte int64
2020-11-27 10:55:48 +00:00
payerIndex int
2020-11-11 12:49:51 +00:00
resendThreshold uint32
2020-11-27 10:55:48 +00:00
resendFunc func ( * transaction . Transaction , interface { } )
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
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-08-29 19:20:56 +00:00
func ( p item ) CompareTo ( otherP item ) int {
2020-08-19 13:20:48 +00:00
pHigh := p . txn . HasAttribute ( transaction . HighPriority )
otherHigh := otherP . txn . HasAttribute ( transaction . HighPriority )
if pHigh && ! otherHigh {
return 1
} else if ! pHigh && otherHigh {
return - 1
}
2019-10-22 14:56:03 +00:00
// Fees sorted ascending.
2020-06-23 14:15:35 +00:00
if ret := int ( p . txn . FeePerByte ( ) - 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-08-30 11:46:42 +00:00
return int ( p . txn . NetworkFee - otherP . 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
}
// 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-10-15 11:45:29 +00:00
// HasConflicts returns true if transaction is already in pool or in the Conflicts attributes
// of pooled transactions or has Conflicts attributes for pooled transactions.
func ( mp * Pool ) HasConflicts ( t * transaction . Transaction , fee Feer ) bool {
mp . lock . RLock ( )
defer mp . lock . RUnlock ( )
if mp . containsKey ( t . Hash ( ) ) {
return true
}
if fee . P2PSigExtensionsEnabled ( ) {
// do not check sender's signature and fee
if _ , ok := mp . conflicts [ t . Hash ( ) ] ; ok {
return true
}
for _ , attr := range t . GetAttributes ( transaction . ConflictsT ) {
if mp . containsKey ( attr . Value . ( * transaction . Conflicts ) . Hash ) {
return true
}
}
}
return false
}
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
2020-07-09 16:23:41 +00:00
// and returns false if both balance check is required and sender has not enough GAS to pay
func ( mp * Pool ) tryAddSendersFee ( tx * transaction . Transaction , feer Feer , needCheck bool ) bool {
2020-11-27 10:55:48 +00:00
payer := tx . Signers [ mp . payerIndex ] . Account
senderFee , ok := mp . fees [ payer ]
2020-05-18 08:20:41 +00:00
if ! ok {
2020-11-27 10:55:48 +00:00
senderFee . balance = feer . GetUtilityTokenBalance ( payer )
2020-08-20 16:06:59 +00:00
senderFee . feeSum = big . NewInt ( 0 )
2020-11-27 10:55:48 +00:00
mp . fees [ payer ] = senderFee
2020-05-18 08:20:41 +00:00
}
2020-09-10 12:35:19 +00:00
if needCheck {
newFeeSum , err := checkBalance ( tx , senderFee )
if err != nil {
return false
}
senderFee . feeSum . Set ( newFeeSum )
} else {
senderFee . feeSum . Add ( senderFee . feeSum , big . NewInt ( tx . SystemFee + tx . NetworkFee ) )
2020-07-09 16:23:41 +00:00
}
return true
2020-07-09 15:27:20 +00:00
}
2020-09-10 12:35:19 +00:00
// checkBalance returns new cumulative fee balance for account or an error in
// case sender doesn't have enough GAS to pay for the transaction.
func checkBalance ( tx * transaction . Transaction , balance utilityBalanceAndFees ) ( * big . Int , error ) {
2020-08-20 16:06:59 +00:00
txFee := big . NewInt ( tx . SystemFee + tx . NetworkFee )
if balance . balance . Cmp ( txFee ) < 0 {
2020-09-10 12:35:19 +00:00
return nil , ErrInsufficientFunds
2020-08-19 16:27:15 +00:00
}
2020-09-10 12:35:19 +00:00
txFee . Add ( txFee , balance . feeSum )
if balance . balance . Cmp ( txFee ) < 0 {
return nil , ErrConflict
2020-08-19 16:27:15 +00:00
}
2020-09-10 12:35:19 +00:00
return txFee , nil
2020-05-18 08:20:41 +00:00
}
2020-02-05 11:24:36 +00:00
// Add tries to add given transaction to the Pool.
2020-11-27 10:55:48 +00:00
func ( mp * Pool ) Add ( t * transaction . Transaction , fee Feer , data ... interface { } ) error {
2020-08-29 19:20:56 +00:00
var pItem = item {
2020-09-09 12:32:31 +00:00
txn : t ,
blockStamp : fee . BlockHeight ( ) ,
2020-02-05 11:24:36 +00:00
}
2020-11-27 10:55:48 +00:00
if data != nil {
pItem . data = data [ 0 ]
}
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-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-10-15 11:45:29 +00:00
conflictsToBeRemoved , err := mp . checkTxConflicts ( t , fee )
2020-08-19 16:27:15 +00:00
if err != nil {
2020-08-19 15:36:57 +00:00
mp . lock . Unlock ( )
2020-08-19 16:27:15 +00:00
return err
2020-08-19 15:36:57 +00:00
}
2020-11-30 09:48:18 +00:00
if attrs := t . GetAttributes ( transaction . OracleResponseT ) ; len ( attrs ) != 0 {
id := attrs [ 0 ] . Value . ( * transaction . OracleResponse ) . ID
h , ok := mp . oracleResp [ id ]
if ok {
if mp . verifiedMap [ h ] . NetworkFee >= t . NetworkFee {
mp . lock . Unlock ( )
return ErrOracleResponse
}
mp . removeInternal ( h , fee )
}
mp . oracleResp [ id ] = t . Hash ( )
}
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-10-15 11:45:29 +00:00
if fee . P2PSigExtensionsEnabled ( ) {
// Remove conflicting transactions.
for _ , conflictingTx := range conflictsToBeRemoved {
mp . removeInternal ( conflictingTx . Hash ( ) , fee )
}
}
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 ( ) )
2020-10-15 11:45:29 +00:00
if fee . P2PSigExtensionsEnabled ( ) {
mp . removeConflictsOf ( unlucky . txn )
}
2021-01-15 13:12:27 +00:00
if attrs := unlucky . txn . GetAttributes ( transaction . OracleResponseT ) ; len ( attrs ) != 0 {
delete ( mp . oracleResp , attrs [ 0 ] . Value . ( * transaction . OracleResponse ) . ID )
}
2020-02-06 14:38:59 +00:00
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-12-16 10:14:30 +00:00
mp . verifiedMap [ t . Hash ( ) ] = t
2020-10-15 11:45:29 +00:00
if fee . P2PSigExtensionsEnabled ( ) {
// Add conflicting hashes to the mp.conflicts list.
for _ , attr := range t . GetAttributes ( transaction . ConflictsT ) {
hash := attr . Value . ( * transaction . Conflicts ) . Hash
mp . conflicts [ hash ] = append ( mp . conflicts [ hash ] , t . Hash ( ) )
}
}
2020-07-09 16:23:41 +00:00
// we already checked balance in checkTxConflicts, so don't need to check again
mp . tryAddSendersFee ( pItem . txn , fee , false )
2020-02-27 10:42:35 +00:00
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-10-15 11:45:29 +00:00
func ( mp * Pool ) Remove ( hash util . Uint256 , feer Feer ) {
2019-10-24 09:29:55 +00:00
mp . lock . Lock ( )
2020-10-15 11:45:29 +00:00
mp . removeInternal ( hash , feer )
mp . lock . Unlock ( )
}
// removeInternal is an internal unlocked representation of Remove
func ( mp * Pool ) removeInternal ( hash util . Uint256 , feer Feer ) {
2020-08-31 20:57:10 +00:00
if tx , 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-11-27 10:55:48 +00:00
itm := mp . verifiedTxes [ num ]
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-11-27 10:55:48 +00:00
payer := itm . txn . Signers [ mp . payerIndex ] . Account
senderFee := mp . fees [ payer ]
2020-08-31 20:57:10 +00:00
senderFee . feeSum . Sub ( senderFee . feeSum , big . NewInt ( tx . SystemFee + tx . NetworkFee ) )
2020-11-27 10:55:48 +00:00
mp . fees [ payer ] = senderFee
2020-10-15 11:45:29 +00:00
if feer . P2PSigExtensionsEnabled ( ) {
// remove all conflicting hashes from mp.conflicts list
mp . removeConflictsOf ( tx )
}
2020-11-30 09:48:18 +00:00
if attrs := tx . GetAttributes ( transaction . OracleResponseT ) ; len ( attrs ) != 0 {
delete ( mp . oracleResp , attrs [ 0 ] . Value . ( * transaction . OracleResponse ) . ID )
}
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
}
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-06-17 12:29:56 +00:00
policyChanged := mp . loadPolicy ( feer )
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-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-10-15 11:45:29 +00:00
if feer . P2PSigExtensionsEnabled ( ) {
mp . conflicts = make ( map [ util . Uint256 ] [ ] util . Uint256 )
}
2020-11-11 12:49:51 +00:00
height := feer . BlockHeight ( )
2020-11-27 10:55:48 +00:00
var staleItems [ ] item
2020-02-05 21:23:49 +00:00
for _ , itm := range mp . verifiedTxes {
2020-07-09 16:23:41 +00:00
if isOK ( itm . txn ) && mp . checkPolicy ( itm . txn , policyChanged ) && mp . tryAddSendersFee ( itm . txn , feer , true ) {
2020-02-05 21:23:49 +00:00
newVerifiedTxes = append ( newVerifiedTxes , itm )
2020-10-15 11:45:29 +00:00
if feer . P2PSigExtensionsEnabled ( ) {
for _ , attr := range itm . txn . GetAttributes ( transaction . ConflictsT ) {
hash := attr . Value . ( * transaction . Conflicts ) . Hash
mp . conflicts [ hash ] = append ( mp . conflicts [ hash ] , itm . txn . Hash ( ) )
}
}
2020-11-11 12:49:51 +00:00
if mp . resendThreshold != 0 {
2020-11-27 10:55:48 +00:00
// item is resend at resendThreshold, 2*resendThreshold, 4*resendThreshold ...
2020-11-11 12:49:51 +00:00
// so quotient must be a power of two.
diff := ( height - itm . blockStamp )
if diff % mp . resendThreshold == 0 && bits . OnesCount32 ( diff / mp . resendThreshold ) == 1 {
2020-11-27 10:55:48 +00:00
staleItems = append ( staleItems , itm )
2020-11-11 12:49:51 +00:00
}
}
2020-02-05 21:23:49 +00:00
} else {
delete ( mp . verifiedMap , itm . txn . Hash ( ) )
2020-11-30 09:48:18 +00:00
if attrs := itm . txn . GetAttributes ( transaction . OracleResponseT ) ; len ( attrs ) != 0 {
delete ( mp . oracleResp , attrs [ 0 ] . Value . ( * transaction . OracleResponse ) . ID )
}
2020-02-05 21:23:49 +00:00
}
}
2020-11-27 10:55:48 +00:00
if len ( staleItems ) != 0 {
go mp . resendStaleItems ( staleItems )
2020-11-11 12:49:51 +00:00
}
2020-02-05 21:23:49 +00:00
mp . verifiedTxes = newVerifiedTxes
mp . lock . Unlock ( )
}
2020-06-17 12:29:56 +00:00
// loadPolicy updates feePerByte field and returns whether policy has been
// changed.
func ( mp * Pool ) loadPolicy ( feer Feer ) bool {
newFeePerByte := feer . FeePerByte ( )
2020-06-23 14:15:35 +00:00
if newFeePerByte > mp . feePerByte {
2020-06-17 12:29:56 +00:00
mp . feePerByte = newFeePerByte
return true
}
return false
}
// checkPolicy checks whether transaction fits policy.
func ( mp * Pool ) checkPolicy ( tx * transaction . Transaction , policyChanged bool ) bool {
if ! policyChanged || tx . FeePerByte ( ) >= mp . feePerByte {
return true
}
return false
}
2020-08-19 14:57:30 +00:00
// New returns a new Pool struct.
2020-11-27 10:55:48 +00:00
func New ( capacity int , payerIndex int ) * Pool {
2020-08-19 16:27:15 +00:00
return & Pool {
2020-08-31 20:57:10 +00:00
verifiedMap : make ( map [ util . Uint256 ] * transaction . Transaction ) ,
2020-08-29 19:20:56 +00:00
verifiedTxes : make ( [ ] item , 0 , capacity ) ,
2020-02-06 12:33:49 +00:00
capacity : capacity ,
2020-11-27 10:55:48 +00:00
payerIndex : payerIndex ,
2020-05-18 08:20:41 +00:00
fees : make ( map [ util . Uint160 ] utilityBalanceAndFees ) ,
2020-10-15 11:45:29 +00:00
conflicts : make ( map [ util . Uint256 ] [ ] util . Uint256 ) ,
2020-11-30 09:48:18 +00:00
oracleResp : make ( map [ uint64 ] util . Uint256 ) ,
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-11-11 12:49:51 +00:00
// SetResendThreshold sets threshold after which transaction will be considered stale
// and returned for retransmission by `GetStaleTransactions`.
2020-11-27 10:55:48 +00:00
func ( mp * Pool ) SetResendThreshold ( h uint32 , f func ( * transaction . Transaction , interface { } ) ) {
2020-11-11 12:49:51 +00:00
mp . lock . Lock ( )
defer mp . lock . Unlock ( )
mp . resendThreshold = h
mp . resendFunc = f
}
2020-11-27 10:55:48 +00:00
func ( mp * Pool ) resendStaleItems ( items [ ] item ) {
for i := range items {
mp . resendFunc ( items [ i ] . txn , items [ i ] . data )
2020-11-11 12:49:51 +00:00
}
}
2020-02-18 15:56:41 +00:00
// TryGetValue returns a transaction and its fee if it exists in the memory pool.
2020-06-05 16:01:10 +00:00
func ( mp * Pool ) TryGetValue ( hash util . Uint256 ) ( * transaction . Transaction , bool ) {
2019-12-02 19:39:43 +00:00
mp . lock . RLock ( )
defer mp . lock . RUnlock ( )
2020-08-31 20:57:10 +00:00
if tx , ok := mp . verifiedMap [ hash ] ; ok {
return tx , 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-06-05 16:01:10 +00:00
return nil , 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
}
2020-11-27 10:55:48 +00:00
// TryGetData returns data associated with the specified transaction if it exists in the memory pool.
func ( mp * Pool ) TryGetData ( hash util . Uint256 ) ( interface { } , bool ) {
mp . lock . RLock ( )
defer mp . lock . RUnlock ( )
if tx , ok := mp . verifiedMap [ hash ] ; ok {
itm := item { txn : tx }
n := sort . Search ( len ( mp . verifiedTxes ) , func ( n int ) bool {
return itm . CompareTo ( mp . verifiedTxes [ n ] ) >= 0
} )
if n < len ( mp . verifiedTxes ) {
for i := n ; i < len ( mp . verifiedTxes ) ; i ++ { // items may have equal priority, so `n` is the left bound of the items which are as prioritized as the desired `itm`.
if mp . verifiedTxes [ i ] . txn . Hash ( ) == hash {
return mp . verifiedTxes [ i ] . data , ok
}
if itm . CompareTo ( mp . verifiedTxes [ i ] ) != 0 {
break
}
}
}
}
return nil , false
}
2020-06-05 14:26:11 +00:00
// GetVerifiedTransactions returns a slice of transactions with their fees.
2020-06-05 16:01:10 +00:00
func ( mp * Pool ) GetVerifiedTransactions ( ) [ ] * transaction . Transaction {
2019-12-02 19:39:43 +00:00
mp . lock . RLock ( )
defer mp . lock . RUnlock ( )
2019-12-13 16:49:43 +00:00
2020-06-05 16:01:10 +00:00
var t = make ( [ ] * transaction . Transaction , len ( mp . verifiedTxes ) )
2019-12-13 16:49:43 +00:00
2020-02-18 15:56:41 +00:00
for i := range mp . verifiedTxes {
2020-06-05 16:01:10 +00:00
t [ i ] = mp . verifiedTxes [ i ] . txn
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-10-15 11:45:29 +00:00
// checkTxConflicts is an internal unprotected version of Verify. It takes into
// consideration conflicting transactions which are about to be removed from mempool.
func ( mp * Pool ) checkTxConflicts ( tx * transaction . Transaction , fee Feer ) ( [ ] * transaction . Transaction , error ) {
2020-11-27 10:55:48 +00:00
payer := tx . Signers [ mp . payerIndex ] . Account
actualSenderFee , ok := mp . fees [ payer ]
2020-07-09 16:23:41 +00:00
if ! ok {
2020-11-27 10:55:48 +00:00
actualSenderFee . balance = fee . GetUtilityTokenBalance ( payer )
2020-10-15 11:45:29 +00:00
actualSenderFee . feeSum = big . NewInt ( 0 )
2020-07-09 16:23:41 +00:00
}
2020-10-15 11:45:29 +00:00
var expectedSenderFee utilityBalanceAndFees
// Check Conflicts attributes.
var conflictsToBeRemoved [ ] * transaction . Transaction
if fee . P2PSigExtensionsEnabled ( ) {
// Step 1: check if `tx` was in attributes of mempooled transactions.
if conflictingHashes , ok := mp . conflicts [ tx . Hash ( ) ] ; ok {
for _ , hash := range conflictingHashes {
existingTx := mp . verifiedMap [ hash ]
2020-11-27 10:55:48 +00:00
if existingTx . HasSigner ( payer ) && existingTx . NetworkFee > tx . NetworkFee {
2020-10-15 11:45:29 +00:00
return nil , fmt . Errorf ( "%w: conflicting transaction %s has bigger network fee" , ErrConflictsAttribute , existingTx . Hash ( ) . StringBE ( ) )
}
conflictsToBeRemoved = append ( conflictsToBeRemoved , existingTx )
}
}
// Step 2: check if mempooled transactions were in `tx`'s attributes.
for _ , attr := range tx . GetAttributes ( transaction . ConflictsT ) {
hash := attr . Value . ( * transaction . Conflicts ) . Hash
existingTx , ok := mp . verifiedMap [ hash ]
if ! ok {
continue
}
2020-11-27 10:55:48 +00:00
if ! tx . HasSigner ( existingTx . Signers [ mp . payerIndex ] . Account ) {
2020-10-15 11:45:29 +00:00
return nil , fmt . Errorf ( "%w: not signed by the sender of conflicting transaction %s" , ErrConflictsAttribute , existingTx . Hash ( ) . StringBE ( ) )
}
if existingTx . NetworkFee >= tx . NetworkFee {
return nil , fmt . Errorf ( "%w: conflicting transaction %s has bigger or equal network fee" , ErrConflictsAttribute , existingTx . Hash ( ) . StringBE ( ) )
}
conflictsToBeRemoved = append ( conflictsToBeRemoved , existingTx )
}
// Step 3: take into account sender's conflicting transactions before balance check.
expectedSenderFee = utilityBalanceAndFees {
balance : new ( big . Int ) . Set ( actualSenderFee . balance ) ,
feeSum : new ( big . Int ) . Set ( actualSenderFee . feeSum ) ,
}
for _ , conflictingTx := range conflictsToBeRemoved {
2020-11-27 10:55:48 +00:00
if conflictingTx . Signers [ mp . payerIndex ] . Account . Equals ( payer ) {
2020-10-15 11:45:29 +00:00
expectedSenderFee . feeSum . Sub ( expectedSenderFee . feeSum , big . NewInt ( conflictingTx . SystemFee + conflictingTx . NetworkFee ) )
}
}
} else {
expectedSenderFee = actualSenderFee
}
_ , err := checkBalance ( tx , expectedSenderFee )
return conflictsToBeRemoved , err
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
2020-06-05 14:26:11 +00:00
// Verify checks if a Sender of tx is able to pay for it (and all the other
// transactions in the pool). If yes, the transaction tx is a valid
// transaction and the function returns true. If no, the transaction tx is
// considered to be invalid the function returns false.
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-10-15 11:45:29 +00:00
_ , err := mp . checkTxConflicts ( tx , feer )
return err == nil
}
// removeConflictsOf removes hash of the given transaction from the conflicts list
// for each Conflicts attribute.
func ( mp * Pool ) removeConflictsOf ( tx * transaction . Transaction ) {
// remove all conflicting hashes from mp.conflicts list
for _ , attr := range tx . GetAttributes ( transaction . ConflictsT ) {
conflictsHash := attr . Value . ( * transaction . Conflicts ) . Hash
if len ( mp . conflicts [ conflictsHash ] ) == 1 {
delete ( mp . conflicts , conflictsHash )
continue
}
for i , existingHash := range mp . conflicts [ conflictsHash ] {
if existingHash == tx . Hash ( ) {
// tx.Hash can occur in the conflicting hashes array only once, because we can't add the same transaction to the mempol twice
mp . conflicts [ conflictsHash ] = append ( mp . conflicts [ conflictsHash ] [ : i ] , mp . conflicts [ conflictsHash ] [ i + 1 : ] ... )
break
}
}
}
2020-02-04 15:43:21 +00:00
}