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-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"
2023-10-11 10:24:16 +00:00
"sync/atomic"
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
2021-11-30 15:42:22 +00:00
"github.com/holiman/uint256"
2021-05-28 11:47:33 +00:00
"github.com/nspcc-dev/neo-go/pkg/core/mempoolevent"
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 (
2022-04-20 18:30:09 +00:00
// ErrInsufficientFunds is returned when the Sender is not able to pay for
// the transaction being added irrespective of the other contents of the
2020-08-19 16:27:15 +00:00
// pool.
ErrInsufficientFunds = errors . New ( "insufficient funds" )
2022-04-20 18:30:09 +00:00
// ErrConflict is returned when the 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).
2021-09-27 12:33:06 +00:00
ErrConflict = errors . New ( "conflicts: insufficient funds for all pooled tx" )
2022-04-20 18:30:09 +00:00
// ErrDup is returned when the transaction being added is already present
2020-02-04 15:43:21 +00:00
// in the memory pool.
ErrDup = errors . New ( "already in the memory pool" )
2022-04-20 18:30:09 +00:00
// ErrOOM is returned when the transaction just doesn't fit in the memory
2020-02-04 15:43:21 +00:00
// pool because of its capacity constraints.
ErrOOM = errors . New ( "out of memory" )
2022-04-20 18:30:09 +00:00
// ErrConflictsAttribute is returned when the transaction conflicts with other transactions
2020-10-15 11:45:29 +00:00
// due to its (or theirs) Conflicts attributes.
ErrConflictsAttribute = errors . New ( "conflicts with memory pool due to Conflicts attribute" )
2022-04-20 18:30:09 +00:00
// ErrOracleResponse is returned when the mempool already contains a transaction
2020-11-30 09:48:18 +00:00
// 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
2023-04-03 10:34:24 +00:00
data any
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
}
2022-04-20 18:30:09 +00:00
// items is a slice of an 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
2022-04-20 18:30:09 +00:00
// utilityBalanceAndFees stores the sender's balance and overall fees of
// the sender's transactions which are currently in the mempool.
2020-05-18 08:20:41 +00:00
type utilityBalanceAndFees struct {
2021-11-30 15:42:22 +00:00
balance uint256 . Int
feeSum uint256 . Int
2020-05-18 08:20:41 +00:00
}
2022-04-20 18:30:09 +00:00
// Pool stores the unconfirmed transactions.
2020-01-15 12:10:05 +00:00
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
2022-04-20 18:30:09 +00:00
// conflicts is a map of the hashes of the transactions which are conflicting with the mempooled ones.
2020-10-15 11:45:29 +00:00
conflicts map [ util . Uint256 ] [ ] util . Uint256
2022-04-20 18:30:09 +00:00
// oracleResp contains the ids of oracle responses for the tx in the pool.
2020-11-30 09:48:18 +00:00
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
2023-04-13 11:03:02 +00:00
capacity int
feePerByte int64
payerIndex int
updateMetricsCb func ( int )
2020-11-11 12:49:51 +00:00
resendThreshold uint32
2023-04-03 10:34:24 +00:00
resendFunc func ( * transaction . Transaction , any )
2021-01-15 12:40:15 +00:00
// subscriptions for mempool events
subscriptionsEnabled bool
subscriptionsOn atomic . Bool
stopCh chan struct { }
2021-05-28 11:47:33 +00:00
events chan mempoolevent . Event
subCh chan chan <- mempoolevent . Event // there are no other events in mempool except Event, so no need in generic subscribers type
unsubCh chan chan <- mempoolevent . Event
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
}
2022-04-20 18:30:09 +00:00
// Count returns the total number of uncofirmed 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
}
2022-04-20 18:30:09 +00:00
// ContainsKey checks if the 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
}
2022-04-20 18:30:09 +00:00
// HasConflicts returns true if the transaction is already in the pool or in the Conflicts attributes
// of the pooled transactions or has Conflicts attributes against the pooled transactions.
2020-10-15 11:45:29 +00:00
func ( mp * Pool ) HasConflicts ( t * transaction . Transaction , fee Feer ) bool {
mp . lock . RLock ( )
defer mp . lock . RUnlock ( )
if mp . containsKey ( t . Hash ( ) ) {
return true
}
2023-04-07 08:26:58 +00:00
// 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 ) {
2020-10-15 11:45:29 +00:00
return true
}
}
return false
}
2022-04-20 18:30:09 +00:00
// tryAddSendersFee tries to add system fee and network fee to the total sender`s fee in the mempool
// and returns false if both balance check is required and the sender does not have enough GAS to pay.
2020-07-09 16:23:41 +00:00
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 {
2021-11-30 15:42:22 +00:00
_ = senderFee . balance . SetFromBig ( feer . GetUtilityTokenBalance ( payer ) )
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
}
2021-11-30 15:42:22 +00:00
senderFee . feeSum = newFeeSum
2020-09-10 12:35:19 +00:00
} else {
2021-11-30 15:42:22 +00:00
senderFee . feeSum . AddUint64 ( & senderFee . feeSum , uint64 ( tx . SystemFee + tx . NetworkFee ) )
2020-07-09 16:23:41 +00:00
}
2021-11-30 15:42:22 +00:00
mp . fees [ payer ] = senderFee
2020-07-09 16:23:41 +00:00
return true
2020-07-09 15:27:20 +00:00
}
2022-04-20 18:30:09 +00:00
// checkBalance returns a new cumulative fee balance for the account or an error in
// case the sender doesn't have enough GAS to pay for the transaction.
2021-11-30 15:42:22 +00:00
func checkBalance ( tx * transaction . Transaction , balance utilityBalanceAndFees ) ( uint256 . Int , error ) {
var txFee uint256 . Int
txFee . SetUint64 ( uint64 ( tx . SystemFee + tx . NetworkFee ) )
if balance . balance . Cmp ( & txFee ) < 0 {
return txFee , ErrInsufficientFunds
2020-08-19 16:27:15 +00:00
}
2021-11-30 15:42:22 +00:00
txFee . Add ( & txFee , & balance . feeSum )
if balance . balance . Cmp ( & txFee ) < 0 {
return txFee , 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
}
2022-04-20 18:30:09 +00:00
// Add tries to add the given transaction to the Pool.
2023-04-03 10:34:24 +00:00
func ( mp * Pool ) Add ( t * transaction . Transaction , fee Feer , data ... any ) 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
}
2024-07-30 14:36:57 +00:00
mp . removeInternal ( h )
2020-11-30 09:48:18 +00:00
}
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
2023-04-07 08:26:58 +00:00
// Remove conflicting transactions.
for _ , conflictingTx := range conflictsToBeRemoved {
2024-07-30 14:36:57 +00:00
mp . removeInternal ( conflictingTx . Hash ( ) )
2020-10-15 11:45:29 +00:00
}
2022-04-20 18:30:09 +00:00
// Insert into a sorted array (from max to min, that could also be done
2020-02-05 15:18:34 +00:00
// using sort.Sort(sort.Reverse()), but it incurs more overhead. Notice
2022-04-20 18:30:09 +00:00
// also that we're searching for a position that is strictly more
2020-02-05 15:18:34 +00:00
// 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 ]
mp . verifiedTxes [ len ( mp . verifiedTxes ) - 1 ] = pItem
2024-07-30 15:11:05 +00:00
mp . removeFromMapWithFeesAndAttrs ( unlucky )
2020-02-06 14:38:59 +00:00
} 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
2023-04-07 08:26:58 +00:00
// 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-10-15 11:45:29 +00:00
}
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
2023-04-13 11:03:02 +00:00
if mp . updateMetricsCb != nil {
mp . updateMetricsCb ( len ( mp . verifiedTxes ) )
}
2020-02-06 14:38:59 +00:00
mp . lock . Unlock ( )
2021-01-15 12:40:15 +00:00
if mp . subscriptionsOn . Load ( ) {
2021-05-28 11:47:33 +00:00
mp . events <- mempoolevent . Event {
Type : mempoolevent . TransactionAdded ,
2021-01-15 12:40:15 +00:00
Tx : pItem . txn ,
Data : pItem . data ,
}
}
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
}
2022-04-20 18:30:09 +00:00
// Remove removes an item from the mempool if it exists there (and does
2019-10-24 09:29:55 +00:00
// nothing if it doesn't).
2024-07-30 14:36:57 +00:00
func ( mp * Pool ) Remove ( hash util . Uint256 ) {
2019-10-24 09:29:55 +00:00
mp . lock . Lock ( )
2024-07-30 14:36:57 +00:00
mp . removeInternal ( hash )
2024-07-30 14:42:10 +00:00
if mp . updateMetricsCb != nil {
mp . updateMetricsCb ( len ( mp . verifiedTxes ) )
}
2020-10-15 11:45:29 +00:00
mp . lock . Unlock ( )
}
2024-07-30 15:11:05 +00:00
// removeInternal is an internal unlocked representation of Remove, it drops
// transaction from verifiedMap and verifiedTxs, adjusts fees and fires a
// "removed" event.
2024-07-30 14:36:57 +00:00
func ( mp * Pool ) removeInternal ( hash util . Uint256 ) {
2024-07-30 15:11:05 +00:00
_ , ok := mp . verifiedMap [ hash ]
2024-07-30 14:42:10 +00:00
if ! ok {
return
}
var num int
for num = range mp . verifiedTxes {
if hash . Equals ( mp . verifiedTxes [ num ] . txn . Hash ( ) ) {
break
2021-01-15 12:40:15 +00:00
}
2019-10-24 09:29:55 +00:00
}
2024-07-30 14:42:10 +00:00
itm := mp . verifiedTxes [ num ]
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 ]
}
2024-07-30 15:11:05 +00:00
mp . removeFromMapWithFeesAndAttrs ( itm )
}
// removeFromMapWithFeesAndAttrs removes given item (with the given hash) from
// verifiedMap, adjusts fees, handles attributes and fires an event. Notice
// that it does not do anything to verifiedTxes (the presumption is that if
// you have itm already, you can handle it fine for the specific case).
// It's an internal method, locking is to be handled by the caller.
func ( mp * Pool ) removeFromMapWithFeesAndAttrs ( itm item ) {
delete ( mp . verifiedMap , itm . txn . Hash ( ) )
2024-07-30 14:42:10 +00:00
payer := itm . txn . Signers [ mp . payerIndex ] . Account
senderFee := mp . fees [ payer ]
2024-07-30 15:11:05 +00:00
senderFee . feeSum . SubUint64 ( & senderFee . feeSum , uint64 ( itm . txn . SystemFee + itm . txn . NetworkFee ) )
2024-07-30 14:42:10 +00:00
mp . fees [ payer ] = senderFee
// remove all conflicting hashes from mp.conflicts list
2024-07-30 15:11:05 +00:00
mp . removeConflictsOf ( itm . txn )
if attrs := itm . txn . GetAttributes ( transaction . OracleResponseT ) ; len ( attrs ) != 0 {
2024-07-30 14:42:10 +00:00
delete ( mp . oracleResp , attrs [ 0 ] . Value . ( * transaction . OracleResponse ) . ID )
}
if mp . subscriptionsOn . Load ( ) {
mp . events <- mempoolevent . Event {
Type : mempoolevent . TransactionRemoved ,
Tx : itm . txn ,
Data : itm . data ,
}
2023-04-13 11:03:02 +00:00
}
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
2022-04-20 18:30:09 +00:00
// only the transactions for which it returns true result. It's used to quickly
// drop a 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 ]
*: use clear() to clear maps
Supposedly more efficient since we can avoid some memory management dances.
Memory pool agrees:
goos: linux
goarch: amd64
pkg: github.com/nspcc-dev/neo-go/pkg/core/mempool
cpu: AMD Ryzen 7 PRO 7840U w/ Radeon 780M Graphics
│ pool.old │ pool.new │
│ sec/op │ sec/op vs base │
Pool/one,_incr_fee-16 12.44m ± 1% 12.51m ± 1% +0.55% (p=0.029 n=10)
Pool/many,_same_fee-16 4.960m ± 2% 3.100m ± 1% -37.50% (p=0.000 n=10)
Pool/many,_incr_fee-16 16.03m ± 2% 14.11m ± 1% -12.00% (p=0.000 n=10)
Pool/one,_same_fee-16 1.742m ± 1%
geomean 9.964m 5.556m -17.92%
│ pool.old │ pool.new │
│ B/op │ B/op vs base │
Pool/one,_incr_fee-16 8.117Ki ± 120% 7.101Ki ± 128% -12.52% (p=0.022 n=10)
Pool/many,_same_fee-16 3941.2Ki ± 0% 805.4Ki ± 0% -79.56% (p=0.000 n=10)
Pool/many,_incr_fee-16 3936.2Ki ± 0% 829.8Ki ± 0% -78.92% (p=0.000 n=10)
Pool/one,_same_fee-16 12.98Ki ± 10%
geomean 501.2Ki 88.59Ki -66.47%
│ pool.old │ pool.new │
│ allocs/op │ allocs/op vs base │
Pool/one,_incr_fee-16 28.00 ± 21% 24.00 ± 21% -14.29% (p=0.002 n=10)
Pool/many,_same_fee-16 40.38k ± 0% 40.03k ± 0% -0.86% (p=0.000 n=10)
Pool/many,_incr_fee-16 40.38k ± 0% 40.04k ± 0% -0.85% (p=0.000 n=10)
Pool/one,_same_fee-16 23.00 ± 4%
geomean 3.574k 969.8 -5.55%
Signed-off-by: Roman Khimov <roman@nspcc.ru>
2024-08-23 19:21:20 +00:00
clear ( mp . fees )
clear ( mp . conflicts )
2020-11-11 12:49:51 +00:00
height := feer . BlockHeight ( )
2020-12-30 08:01:13 +00:00
var (
2021-01-15 12:40:15 +00:00
staleItems [ ] item
2020-12-30 08:01:13 +00:00
)
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 )
2023-04-07 08:26:58 +00:00
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-10-15 11:45:29 +00:00
}
2020-11-11 12:49:51 +00:00
if mp . resendThreshold != 0 {
2022-04-20 18:30:09 +00:00
// item is resent 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 )
}
2021-01-15 12:40:15 +00:00
if mp . subscriptionsOn . Load ( ) {
2021-05-28 11:47:33 +00:00
mp . events <- mempoolevent . Event {
Type : mempoolevent . TransactionRemoved ,
2021-01-15 12:40:15 +00:00
Tx : itm . txn ,
Data : itm . data ,
}
2020-12-30 08:01:13 +00:00
}
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 ( )
}
2022-04-20 18:30:09 +00:00
// loadPolicy updates feePerByte field and returns whether the policy has been
2020-06-17 12:29:56 +00:00
// 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
}
2022-04-20 18:30:09 +00:00
// checkPolicy checks whether the transaction fits the policy.
2020-06-17 12:29:56 +00:00
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.
2023-04-13 11:03:02 +00:00
func New ( capacity int , payerIndex int , enableSubscriptions bool , updateMetricsCb func ( int ) ) * Pool {
2021-01-15 12:40:15 +00:00
mp := & Pool {
2021-11-30 16:19:43 +00:00
verifiedMap : make ( map [ util . Uint256 ] * transaction . Transaction , capacity ) ,
2021-01-15 12:40:15 +00:00
verifiedTxes : make ( [ ] item , 0 , capacity ) ,
capacity : capacity ,
payerIndex : payerIndex ,
fees : make ( map [ util . Uint160 ] utilityBalanceAndFees ) ,
conflicts : make ( map [ util . Uint256 ] [ ] util . Uint256 ) ,
oracleResp : make ( map [ uint64 ] util . Uint256 ) ,
subscriptionsEnabled : enableSubscriptions ,
stopCh : make ( chan struct { } ) ,
2021-05-28 11:47:33 +00:00
events : make ( chan mempoolevent . Event ) ,
subCh : make ( chan chan <- mempoolevent . Event ) ,
unsubCh : make ( chan chan <- mempoolevent . Event ) ,
2023-04-13 11:03:02 +00:00
updateMetricsCb : updateMetricsCb ,
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
}
2021-01-15 12:40:15 +00:00
mp . subscriptionsOn . Store ( false )
return mp
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
}
2022-04-20 18:30:09 +00:00
// SetResendThreshold sets a threshold after which the transaction will be considered stale
2020-11-11 12:49:51 +00:00
// and returned for retransmission by `GetStaleTransactions`.
2023-04-03 10:34:24 +00:00
func ( mp * Pool ) SetResendThreshold ( h uint32 , f func ( * transaction . Transaction , any ) ) {
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.
2023-04-03 10:34:24 +00:00
func ( mp * Pool ) TryGetData ( hash util . Uint256 ) ( any , bool ) {
2020-11-27 10:55:48 +00:00
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 {
2021-11-30 15:42:22 +00:00
actualSenderFee . balance . SetFromBig ( fee . GetUtilityTokenBalance ( payer ) )
2020-07-09 16:23:41 +00:00
}
2020-10-15 11:45:29 +00:00
var expectedSenderFee utilityBalanceAndFees
// Check Conflicts attributes.
2023-05-31 16:22:04 +00:00
var (
conflictsToBeRemoved [ ] * transaction . Transaction
conflictingFee int64
)
2023-04-07 08:26:58 +00:00
// 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 ]
if existingTx . HasSigner ( payer ) {
conflictingFee += existingTx . NetworkFee
2020-10-15 11:45:29 +00:00
}
2023-04-07 08:26:58 +00:00
conflictsToBeRemoved = append ( conflictsToBeRemoved , existingTx )
2020-10-15 11:45:29 +00:00
}
2023-04-07 08:26:58 +00:00
}
// Step 2: check if mempooled transactions were in `tx`'s attributes.
conflictsAttrs := tx . GetAttributes ( transaction . ConflictsT )
if len ( conflictsAttrs ) != 0 {
txSigners := make ( map [ util . Uint160 ] struct { } , len ( tx . Signers ) )
for _ , s := range tx . Signers {
txSigners [ s . Account ] = struct { } { }
}
for _ , attr := range conflictsAttrs {
hash := attr . Value . ( * transaction . Conflicts ) . Hash
existingTx , ok := mp . verifiedMap [ hash ]
if ! ok {
continue
2020-10-15 11:45:29 +00:00
}
2023-04-07 08:26:58 +00:00
var signerOK bool
for _ , s := range existingTx . Signers {
if _ , ok := txSigners [ s . Account ] ; ok {
signerOK = true
break
2023-07-14 08:57:18 +00:00
}
2020-10-15 11:45:29 +00:00
}
2023-04-07 08:26:58 +00:00
if ! signerOK {
return nil , fmt . Errorf ( "%w: not signed by a signer of conflicting transaction %s" , ErrConflictsAttribute , existingTx . Hash ( ) . StringBE ( ) )
2020-10-15 11:45:29 +00:00
}
2023-04-07 08:26:58 +00:00
conflictingFee += existingTx . NetworkFee
conflictsToBeRemoved = append ( conflictsToBeRemoved , existingTx )
}
}
if conflictingFee != 0 && tx . NetworkFee <= conflictingFee {
return nil , fmt . Errorf ( "%w: conflicting transactions have bigger or equal network fee: %d vs %d" , ErrConflictsAttribute , tx . NetworkFee , conflictingFee )
}
// Step 3: take into account sender's conflicting transactions before balance check.
expectedSenderFee = actualSenderFee
for _ , conflictingTx := range conflictsToBeRemoved {
if conflictingTx . Signers [ mp . payerIndex ] . Account . Equals ( payer ) {
expectedSenderFee . feeSum . SubUint64 ( & expectedSenderFee . feeSum , uint64 ( conflictingTx . SystemFee + conflictingTx . NetworkFee ) )
2020-10-15 11:45:29 +00:00
}
}
_ , 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
2022-04-20 18:30:09 +00:00
// Verify checks if the Sender of the tx is able to pay for it (and all the other
2020-06-05 14:26:11 +00:00
// transactions in the pool). If yes, the transaction tx is a valid
// transaction and the function returns true. If no, the transaction tx is
2022-04-20 18:30:09 +00:00
// 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
}
2022-04-20 18:30:09 +00:00
// removeConflictsOf removes the hash of the given transaction from the conflicts list
2020-10-15 11:45:29 +00:00
// 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
}
2023-08-22 09:24:59 +00:00
// IterateVerifiedTransactions iterates through verified transactions and invokes
// function `cont`. Iterations continue while the function `cont` returns true.
// Function `cont` is executed within a read-locked memory pool,
// thus IterateVerifiedTransactions will block any write mempool operation,
// use it with care. Do not modify transaction or data via `cont`.
func ( mp * Pool ) IterateVerifiedTransactions ( cont func ( tx * transaction . Transaction , data any ) bool ) {
mp . lock . RLock ( )
defer mp . lock . RUnlock ( )
for i := range mp . verifiedTxes {
if ! cont ( mp . verifiedTxes [ i ] . txn , mp . verifiedTxes [ i ] . data ) {
return
}
}
}