We need a struct that represents an account's pending state. It should maintain a queue of contracts sorted by state nonce. It should also maintain the pending balance and pending state nonce of the account, which are describing: "hypothetically, once all these contracts are confirmed, the account's balance and nonce will be this and this value".
For the queue, there should be at least a push and pop operation. The push operation should take a contract, validate its signature, make sure its value is not greater than the pending balance, and make sure the nonce is one greater than the pending state nonce. It should also check to make sure the recipient is not the hash of the sender public key, and that the sender is not nil. This sounds a lot like the Validate function we have already, except this one may need to be created because it should not access the database. Any new validation functions such as this should go in the contracts package for consistency.
If it is a valid contract per these standards, make sure to append the contract to the end of the queue and update the pending balance and pending nonce. The queue should always be ordered from smallest nonce contract in the front to largest nonce in the end, with each one being +1 its preceding member. If the contract is invalid, return an error.
The pop operation should remove the first (smallest nonce) contract from the queue.
There should also be a contructor New function that takes in a contract, a pending balance, and a pending nonce, and creates a struct like the one described.
EDIT: Better solution
context: handlers
Pass a map into the contract request handler.
Once the request is converted into a Contract, check if the public key hash of the sender is in the map's key set. If it isn't in the map, validate normally as we do currently. If it's valid, then add to the map the public key hash as the map key, and for the value, some sort of struct containing the pending balance and pending state nonce of that sender's account. The pending balance would be the difference between the accounts table balance and the value of the contract. The pending state nonce would be the contract's nonce value.
If the public key hash is in the map, then we need to validate it differently. Make a new validate function in validation that does everything the same as the regular validateContract function, except here it doesn't access the SQL table; instead, pass it two parameters, the pending balance and pending nonce. The function should reject contracts that have a value greater than the pending balance and whos state nonce is not +1 the pending state nonce. If it's valid, return nil just like in our other validation function, otherwise an error. If this function returns nil, then go in the map, update that public key hash's pending balance to be the difference between the current pending balance and the value of the contract, and update the state nonce to be the contract's state nonce.
EDIT: The pending pool map should be reset to empty once a new block is created.
It might be a good idea to make a struct that controls the map, so as to make testable functions that attempt to add contracts to the map per the standards above. This will be sort of the master issue that describes everything and I'll link issues that break down this greater issue.
[x] Issue #269
[x] Issue #270
[x] Issue #271
[x] ContractRequestHandler & test updated with checking for the two cases.
[x] Modify cmd/handlers/main.go to use new structs
package context:pendingpool
We need a struct that represents an account's pending state. It should maintain a queue of contracts sorted by state nonce. It should also maintain the pending balance and pending state nonce of the account, which are describing: "hypothetically, once all these contracts are confirmed, the account's balance and nonce will be this and this value".For the queue, there should be at least a push and pop operation. The push operation should take a contract, validate its signature, make sure its value is not greater than the pending balance, and make sure the nonce is one greater than the pending state nonce. It should also check to make sure the recipient is not the hash of the sender public key, and that the sender is notnil
. This sounds a lot like theValidate
function we have already, except this one may need to be created because it should not access the database. Any new validation functions such as this should go in thecontracts
package for consistency.If it is a valid contract per these standards, make sure to append the contract to the end of the queue and update the pending balance and pending nonce. The queue should always be ordered from smallest nonce contract in the front to largest nonce in the end, with each one being +1 its preceding member. If the contract is invalid, return an error.The pop operation should remove the first (smallest nonce) contract from the queue.A useful link for tricks with slices: https://github.com/golang/go/wiki/SliceTricksThere should also be a contructorNew
function that takes in a contract, a pending balance, and a pending nonce, and creates a struct like the one described.EDIT: Better solution
context:
handlers
Pass a map into the contract request handler.
Once the request is converted into a
Contract
, check if the public key hash of the sender is in the map's key set. If it isn't in the map, validate normally as we do currently. If it's valid, then add to the map the public key hash as the map key, and for the value, some sort of struct containing the pending balance and pending state nonce of that sender's account. The pending balance would be the difference between the accounts table balance and the value of the contract. The pending state nonce would be the contract's nonce value.If the public key hash is in the map, then we need to validate it differently. Make a new validate function in
validation
that does everything the same as the regularvalidateContract
function, except here it doesn't access the SQL table; instead, pass it two parameters, the pending balance and pending nonce. The function should reject contracts that have a value greater than the pending balance and whos state nonce is not +1 the pending state nonce. If it's valid, returnnil
just like in our othervalidation
function, otherwise an error. If this function returnsnil
, then go in the map, update that public key hash's pending balance to be the difference between the current pending balance and the value of the contract, and update the state nonce to be the contract's state nonce.EDIT: The pending pool map should be reset to empty once a new block is created.
It might be a good idea to make a struct that controls the map, so as to make testable functions that attempt to add contracts to the map per the standards above. This will be sort of the master issue that describes everything and I'll link issues that break down this greater issue.
ContractRequestHandler
& test updated with checking for the two cases.cmd/handlers/main.go
to use new structs