提交 ebe34ca8 编写于 作者: M Matt Witherspoon

Merge remote-tracking branch 'origin/master' into more_fuzz

# Action - `{{ bidname }}`
This Contract is legally binding and can be used in the event of a dispute. Disputes shall be settled through the standard arbitration process established by EOS.IO.
### Description
The `{{ bidname }}` action places a bid on a premium account name, in the knowledge that the high bid will purchase the name.
### Inputs and Input Types
The `{{ bidname }}` action requires the following `inputs` and `input types`:
| Action | Input | Input Type |
|:--|:--|:--|
| `{{ bidname }}` | `{{ bidderVar }}`<br/>`{{ newnameVar }}`<br/>`{{ bidVar }}` | `{{ account_name }}`<br/>`{{ account_name }}`<br/>`{{ asset }}` |
As an authorized party I {{ signer }} wish to bid on behalf of {{ bidderVar }} the amount of {{ bidVar }} toward purchase of the account name {{ newnameVar }}.
All disputes arising from this contract shall be resolved in the EOS Core Arbitration Forum.
# Action - `{{ buyram }}`
This Contract is legally binding and can be used in the event of a dispute.
### Description
The `{{ buyram }}` action...
### Inputs and Input Types
The `{{ buyram }}` action requires the following `inputs` and `input types`:
| Action | Input | Input Type |
|:--|:--|:--|
| `{{ buyram }}` | `{{ payerVar }}`<br/>`{{ receiverVar }}`<br/>`{{ quantVar }}` | `{{ account_name }}`<br/>`{{ account_name }}`<br/>`{{ asset }}` |
As an authorized party I {{ signer }} wish to buy {{ quantVar }} worth of RAM using the funds of {{ payerVar }} with the RAM to be owned by and be the property of {{ receiverVar }}.
All disputes arising from this contract shall be resolved in the EOS Core Arbitration Forum.
# Action - `{{ buyrambytes }}`
This Contract is legally binding and can be used in the event of a dispute. Disputes shall be settled through the standard arbitration process established by EOS.IO.
### Description
The `{{ buyrambytes }}` action...
### Inputs and Input Types
The `{{ buyrambytes }}` action requires the following `inputs` and `input types`:
| Action | Input | Input Type |
|:--|:--|:--|
| `{{ buyrambytes }}` | `{{ payerVar }}`<br/>`{{ receiverVar }}`<br/>`{{ bytesVar }}` | `{{ account_name }}`<br/>`{{ account_name }}`<br/>`{{ uint32 }}` |
As an authorized party I {{ signer }} wish to buy {{ bytesVar }} bytes of RAM at the current price using the funds of {{ payerVar }} with the RAM to be owned by and be the property of {{ receiverVar }}.
All disputes arising from this contract shall be resolved in the EOS Core Arbitration Forum.
# Action - `{{ canceldelay }}`
This Contract is legally binding and can be used in the event of a dispute.
### Description
The `{{ canceldelay }}` action cancels an existing delayed transaction.
### Inputs and Input Types
The `{{ canceldelay }}` action requires the following `inputs` and `input types`:
| Action | Input | Input Type |
|:--|:--|:--|
| `{{ canceldelay }}` | `{{ canceling_authVar }}`<br/>`{{ trx_idVar }}` | `{{ permission_level }}`<br/>`{{ transaction_id_type }}` |
As an authorized party I {{ signer }} wish to invoke the authority of {{ canceling_authVar }} to cancel the transaction with ID {{ trx_idVar }}.
All disputes arising from this contract shall be resolved in the EOS Core Arbitration Forum.
# Action - `{{ claimrewards }}`
This Contract is legally binding and can be used in the event of a dispute.
### Description
The `{{ claimrewards }}` action allows a block producer (active or standby) to claim the system rewards due them for producing blocks and receiving votes.
### Input and Input Type
The `{{ claimrewards }}` action requires the following `input` and `input type`:
| Action | Input | Input Type |
|:--|:--|:--|
| `{{ claimrewards }}` | `{{ ownerVar }}` | `{{ account_name }}` |
As an authorized party I {{ signer }} wish to have the rewards earned by {{ ownerVar }} deposited into their (my) account.
All disputes arising from this contract shall be resolved in the EOS Core Arbitration Forum.
# eosio.system delegatebw
This Ricardian contract for the system action *delegatebw* is legally binding and can be used in the event of a dispute.
## delegatebw
(account_name-from;
account_name-to;
asset-stake_net_quantity;
asset-stake_cpu_quantity;
bool:transfer)
_Intent: stake tokens for bandwidth and/or CPU and optionally transfer ownership_
As an authorized party I {{ signer }} wish to stake {{ asset-stake_cpu_quantity }} for CPU and {{ asset-stake_net_quantity }} for bandwidth from the liquid tokens of {{ account_name-from }} for the use of delegatee {{ account_name-to }}.
{{if bool:transfer }}
It is {{ bool:transfer }} that I wish these tokens to become immediately owned by the delegatee.
{{/if}}
As signer I stipulate that, if I am not the beneficial owner of these tokens, I have proof that I’ve been authorized to take this action by their beneficial owner(s).
All disputes arising from this contract shall be resolved in the EOS Core Arbitration Forum.
# Action - `{{ deleteauth }}`
This Contract is legally binding and can be used in the event of a dispute.
### Description
The `{{ deleteauth }}` action...
### Inputs and Input Types
The `{{ deleteauth }}` action requires the following `inputs` and `input types`:
| Action | Input | Input Type |
|:--|:--|:--|
| `{{ deleteauth }}` | `{{ accountVar }}`<br/>`{{ permissionVar }}` | `{{ account_name }}`<br/>`{{ permission_name }}` |
As an authorized party I {{ signer }} wish to UNKNOWN
All disputes arising from this contract shall be resolved in the EOS Core Arbitration Forum.
# Action - `{{ linkauth }}`
This Contract is legally binding and can be used in the event of a dispute.
### Description
The `{{ linkauth }}` action...
### Inputs and Input Types
The `{{ linkauth }}` action requires the following `inputs` and `input types`:
| Action | Input | Input Type |
|:--|:--|:--|
| `{{ linkauth }}` | `{{ accountVar }}`<br/>`{{ codeVar }}`<br/>`{{ typeVar }}`<br/>`{{ requirementVar }}` | `{{ account_name }}`<br/>`{{ account_name }}`<br/>`{{ action_name }}`<br/>`{{ permission_name }}` |
As an authorized party I {{ signer }} wish to UNKNOWN
All disputes arising from this contract shall be resolved in the EOS Core Arbitration Forum.
# Action - `{{ newaccount }}`
This Contract is legally binding and can be used in the event of a dispute. Disputes shall be settled through the standard arbitration process established by EOS.IO.
### Description
The `{{ newaccount }}` action creates a new account.
### Inputs and Input Types
The `{{ newaccount }}` action requires the following `inputs` and `input types`:
| Action | Input | Input Type |
|:--|:--|:--|
| `{{ newaccount }}` | `{{ creatorVar }}`<br/>`{{ nameVar }}`<br/>`{{ ownerVar }}`<br/>`{{ activeVar }}` | `{{ account_name }}`<br/>`{{ account_name }}`<br/>`{{ authority }}`<br/>`{{ authority }}` |
As an authorized party I {{ signer }} wish to exercise the authority of {{ creatorVar }} to create a new account on this system named {{ nameVar }} such that the new account's owner public key shall be {{ ownerVar }} and the active public key shall be {{ activeVar }}.
All disputes arising from this contract shall be resolved in the EOS Core Arbitration Forum.
# Action - `{{ onerror }}`
This Contract is legally binding and can be used in the event of a dispute.
### Description
The `{{ onerror }}` action...
### Inputs and Input Types
The `{{ onerror }}` action requires the following `inputs` and `input types`:
| Action | Input | Input Type |
|:--|:--|:--|
| `{{ onerror }}` | `{{ sender_idVar }}`<br/>`{{ sent_trxVar }}` | `{{ uint128 }}`<br/>`{{ bytes }}` |
As an authorized party I {{ signer }} wish to UNKNOWN
All disputes arising from this contract shall be resolved in the EOS Core Arbitration Forum.
# Smart Contract - `{{ eosio.system }}`
This is an overview of the actions for the `{{ eosio.system }}` smart contract. This Contract is legally binding and can be used in the event of a dispute. Disputes shall be settled through the standard arbitration process established by EOS.IO.
### Description
The `{{ eosio.system }}` contract...
### Actions, Inputs and Input Types
The table below contains the `actions`, `inputs` and `input types` for the `{{ eosio.system }}` contract.
| Action | Input | Input Type |
|:--|:--|:--|
| `{{ newaccount }}` | `{{ creator }}`<br/>`{{ name }}`<br/>`{{ owner }}`<br/>`{{ active }}` | `{{ account_name }}`<br/>`{{ account_name }}`<br/>`{{ authority }}`<br/>`{{ authority }}` |
| `{{ setcode }}` | `{{ account }}`<br/>`{{ vmtype }}`<br/>`{{ vmversion }}`<br/>`{{ code }}` | `{{ account_name }}`<br/>`{{ uint8 }}`<br/>`{{ uint8 }}`<br/>`{{ bytes }}` |
| `{{ setabi }}` | `{{ account }}`<br/>`{{ abi }}` | `{{ account_name }}`<br/>`{{ bytes }}` |
| `{{ updateauth }}` | `{{ account }}`<br/>`{{ permission }}`<br/>`{{ parent }}`<br/>`{{ auth }}` | `{{ account_name }}`<br/>`{{ permission_name }}`<br/>`{{ permission_name }}`<br/>`{{ authority }}` |
| `{{ deleteauth }}` | `{{ account }}`<br/>`{{ permission }}` | `{{ account_name }}`<br/>`{{ permission_name }}` |
| `{{ linkauth }}` | `{{ account }}`<br/>`{{ code }}`<br/>`{{ type }}`<br/>`{{ requirement }}` | `{{ account_name }}`<br/>`{{ account_name }}`<br/>`{{ action_name }}`<br/>`{{ permission_name }}` |
| `{{ unlinkauth }}` | `{{ account }}`<br/>`{{ code }}`<br/>`{{ type }}` | `{{ account_name }}`<br/>`{{ account_name }}`<br/>`{{ action_name }}` |
| `{{ canceldelay }}` | `{{ canceling_auth }}`<br/>`{{ trx_id }}` | `{{ permission_level }}`<br/>`{{ transaction_id_type }}` |
| `{{ onerror }}` | `{{ sender_id }}`<br/>`{{ sent_trx }}` | `{{ uint128 }}`<br/>`{{ bytes }}` |
| `{{ buyrambytes }}` | `{{ payer }}`<br/>`{{ receiver }}`<br/>`{{ bytes }}` | `{{ account_name }}`<br/>`{{ account_name }}`<br/>`{{ uint32 }}` |
| `{{ buyram }}` | `{{ payer }}`<br/>`{{ receiver }}`<br/>`{{ quant }}` | `{{ account_name }}`<br/>`{{ account_name }}`<br/>`{{ asset }}` |
| `{{ sellram }}` | `{{ account }}`<br/>`{{ bytes }}` | `{{ account_name }}`<br/>`{{ uint64 }}` |
| `{{ delegatebw }}` | `{{ from }}`<br/>`{{ receiver }}`<br/>`{{ stake_net_quantity }}`<br/>`{{ stake_cpu_quantity }}`<br/>`{{ transfer }}` | `{{ account_name }}`<br/>`{{ account_name }}`<br/>`{{ asset }}`<br/>`{{ asset }}`<br/>`{{ bool }}` |
| `{{ undelegatebw }}` | `{{ from }}`<br/>`{{ receiver }}`<br/>`{{ unstake_net_quantity }}`<br/>`{{ unstake_cpu_quantity }}` | `{{ account_name }}`<br/>`{{ account_name }}`<br/>`{{ asset }}`<br/>`{{ asset }}` |
| `{{ refund }}` | `{{ owner }}` | `{{ account_name }}` |
| `{{ regproducer }}` | `{{ producer }}`<br/>`{{ producer_key }}`<br/>`{{ url }}`<br/>`{{ location }}` | `{{ account_name }}`<br/>`{{ public_key }}`<br/>`{{ string }}`<br/>`{{ uint16 }}` |
| `{{ setram }}` | `{{ max_ram_size }}` | `{{ uint64 }}` |
| `{{ bidname }}` | `{{ bidder }}`<br/>`{{ newname }}`<br/>`{{ bid }}` | `{{ account_name }}`<br/>`{{ account_name }}`<br/>`{{ asset }}` |
| `{{ unregprod }}` | `{{ producer }}` | `{{ account_name }}` |
| `{{ regproxy }}` | `{{ proxy }}`<br/>`{{ isproxy }}` | `{{ account_name }}`<br/>`{{ bool }}` |
| `{{ voteproducer }}` | `{{ voter }}`<br/>`{{ proxy }}`<br/>`{{ producers }}` | `{{ account_name }}`<br/>`{{ account_name }}`<br/>`{{ account_name[] }}` |
| `{{ claimrewards }}` | `{{ owner }}` | `{{ account_name }}` |
| `{{ setpriv }}` | `{{ account }}`<br/>`{{ is_priv }}` | `{{ account_name }}`<br/>`{{ int8 }}` |
| `{{ setalimits }}` | `{{ account }}`<br/>`{{ ram_bytes }}`<br/>`{{ net_weight }}`<br/>`{{ cpu_weight }}` | `{{ account_name }}`<br/>`{{ int64 }}`<br/>`{{ int64 }}`<br/>`{{ int64 }}` |
| `{{ setglimits }}` | `{{ cpu_usec_per_period }}` | `{{ int64 }}` |
| `{{ setprods }}` | `{{ schedule }}` | `{{ producer_key[] }}` |
| `{{ reqauth }}` | `{{ from }}` | `{{ account_name }}` |
\ No newline at end of file
# Action - `{{ refund }}`
This Contract is legally binding and can be used in the event of a dispute. Disputes shall be settled through the standard arbitration process established by EOS.IO.
### Description
The intent of the `{{ refund }}` action is to return previously unstaked tokens to an account after the unstaking period has elapsed.
### Input and Input Type
The `{{ refund }}` action requires the following `input` and `input type`:
| Action | Input | Input Type |
|:--|:--|:--|
| `{{ refund }}` | `{{ ownerVar }}` | `{{ account_name }}` |
As an authorized party I {{ signer }} wish to have the unstaked tokens of {{ ownerVar }} returned.
All disputes arising from this contract shall be resolved in the EOS Core Arbitration Forum.
# eosio.system regproducer
This Ricardian contract for the system action *regproducer* is legally binding and can be used in the event of a dispute.
## regproducer
( const account_name producer
, const public_key& producer_key
, const std::string& url
, uint16_t location );
_Intent: create a producer-config and producer-info object for 'producer'_
As an authorized party I {{ signer }} wish to register a producer candidate named {{ account_name }} and identified with {{ producer_key }} located at {{ url }} and located at {{ location }}.
All disputes arising from this contract shall be resolved in the EOS Core Arbitration Forum.
# Action - `{{ regproxy }}`
This Contract is legally binding and can be used in the event of a dispute.
### Description
The `{{ regproxy }}` action...
### Inputs and Input Types
The `{{ regproxy }}` action requires the following `inputs` and `input types`:
| Action | Input | Input Type |
|:--|:--|:--|
| `{{ regproxy }}` | `{{ proxyVar }}`<br/>`{{ isproxyVar }}` | `{{ account_name }}`<br/>`{{ bool }}` |
As an authorized party I {{ signer }} wish to UNKNOWN
All disputes arising from this contract shall be resolved in the EOS Core Arbitration Forum.
# Action - `{{ reqauth }}`
This Contract is legally binding and can be used in the event of a dispute.
### Description
The `{{ reqauth }}` action...
### Input and Input Type
The `{{ reqauth }}` action requires the following `input` and `input type`:
| Action | Input | Input Type |
|:--|:--|:--|
| `{{ reqauth }}` | `{{ fromVar }}` | `{{ account_name }}` |
As an authorized party I {{ signer }} wish to UNKNOWN
All disputes arising from this contract shall be resolved in the EOS Core Arbitration Forum.
# Action - `{{ sellram }}`
This Contract is legally binding and can be used in the event of a dispute.
### Description
The `{{ sellram }}` action...
### Inputs and Input Types
The `{{ sellram }}` action requires the following `inputs` and `input types`:
| Action | Input | Input Type |
|:--|:--|:--|
| `{{ sellram }}` | `{{ accountVar }}`<br/>`{{ bytesVar }}` | `{{ account_name }}`<br/>`{{ uint64 }}` |
As an authorized party I {{ signer }} wish to sell {{ bytesVar }} of RAM from account {{ accountVar }}.
All disputes arising from this contract shall be resolved in the EOS Core Arbitration Forum.
# Action - `{{ setabi }}`
This Contract is legally binding and can be used in the event of a dispute.
### Description
The intention of the `{{ setabi }}` action is to...
### Inputs and Input Types
The `{{ setabi }}` action requires the following `inputs` and `input types`:
| Action | Input | Input Type |
|:--|:--|:--|
| `{{ setabi }}` | `{{ accountVar }}`<br/>`{{ abiVar }}` | `{{ account_name }}`<br/>`{{ bytes }}` |
As an authorized party I {{ signer }} wish to UNKNOWN
All disputes arising from this contract shall be resolved in the EOS Core Arbitration Forum.
# Action - `{{ setalimits }}`
This Contract is legally binding and can be used in the event of a dispute.
### Description
The `{{ setalimits }}` action...
### Inputs and Input Types
The `{{ setalimits }}` action requires the following `inputs` and `input types`:
| Action | Input | Input Type |
|:--|:--|:--|
| `{{ setalimits }}` | `{{ accountVar }}`<br/>`{{ ram_bytesVar }}`<br/>`{{ net_weightVar }}`<br/>`{{ cpu_weightVar }}` | `{{ account_name }}`<br/>`{{ int64 }}`<br/>`{{ int64 }}`<br/>`{{ int64 }}` |
As an authorized party I {{ signer }} wish to UNKNOWN
All disputes arising from this contract shall be resolved in the EOS Core Arbitration Forum.
# Action - `{{ setcode }}`
This Contract is legally binding and can be used in the event of a dispute.
### Description
The intention of the `{{ setcode }}` action is to load a smart contract into memory and make it available for execution.
### Inputs and Input Types
The `{{ setcode }}` action requires the following `inputs` and `input types`:
| Action | Input | Input Type |
|:--|:--|:--|
| `{{ setcode }}` | `{{ accountVar }}`<br/>`{{ vmtypeVar }}`<br/>`{{ vmversionVar }}`<br/>`{{ codeVar }}` | `{{ account_name }}`<br/>`{{ uint8 }}`<br/>`{{ uint8 }}`<br/>`{{ bytes }}` |
As an authorized party I {{ signer }} wish to store in memory owned by {{ accountVar }} the code {{ codeVar }} which shall use VM Type {{ vmtypeVar }} version {{ vmversionVar }}.
All disputes arising from this contract shall be resolved in the EOS Core Arbitration Forum.
# Action - `{{ setglimits }}`
This Contract is legally binding and can be used in the event of a dispute.
### Description
The intention of the `{{ setglimits }}` action is to ...
### Input and Input Type
The `{{ setglimits }}` action requires the following `input` and `input type`:
| Action | Input | Input Type |
|:--|:--|:--|
| `{{ setglimits }}` | `{{ cpu_usec_per_periodVar }}` | `{{ int64 }}` |
As an authorized party I {{ signer }} wish to UNKNOWN
All disputes arising from this contract shall be resolved in the EOS Core Arbitration Forum.
# Action - `{{ setpriv }}`
This Contract is legally binding and can be used in the event of a dispute.
### Description
The intention of the `{{ setpriv }}` action is to ...
### Inputs and Input Types
The `{{ setpriv }}` action requires the following `inputs` and `input types`:
| Action | Input | Input Type |
|:--|:--|:--|
| `{{ setpriv }}` | `{{ accountVar }}`<br/>`{{ is_privVar }}` | `{{ account_name }}`<br/>`{{ int8 }}` |
As an authorized party I {{ signer }} wish to UNKNOWN
All disputes arising from this contract shall be resolved in the EOS Core Arbitration Forum.
# Action - `{{ setprods }}`
This Contract is legally binding and can be used in the event of a dispute.
### Description
The `{{ setprods }}` action creates a new schedule of active producers, who will produce blocks in the order given.
### Input and Input Type
The `{{ setprods }}` action requires the following `input` and `input type`:
| Action | Input | Input Type |
|:--|:--|:--|
| `{{ setprods }}` | `{{ scheduleVar }}` | `{{ producer_key[] }}` |
THIS IS A SYSTEM COMMAND NOT AVAILABLE FOR DIRECT ACCESS BY USERS.
As an authorized party I {{ signer }} wish to set the rotation of producers to be {{ scheduleVar }}.
All disputes arising from this contract shall be resolved in the EOS Core Arbitration Forum.
# Action - `{{ setram }}`
This Contract is legally binding and can be used in the event of a dispute.
### Description
The intent of the `{{ setram }}` action is ...
### Input and Input Type
The `{{ setram }}` action requires the following `input` and `input type`:
| Action | Input | Input Type |
|:--|:--|:--|
| `{{ setram }}` | `{{ max_ram_sizeVar }}` | `{{ uint64 }}` |
As an authorized party I {{ signer }} wish to UNKNOWN
All disputes arising from this contract shall be resolved in the EOS Core Arbitration Forum.
# eosio.system undelegatebw
This Ricardian contract for the system action *undelegatebw* is legally binding and can be used in the event of a dispute.
## undelegatebw
(account_name-from;
account_name-to;
asset-unstake_net_quantity;
asset-unstake_cpu_quantity)
_Intent: unstake tokens from bandwidth_
As an authorized party I {{ signer }} wish to unstake {{ asset-unstake_cpu_quantity }} from CPU and {{ asset-unstake_net_quantity }} from bandwidth from the tokens owned by {{ account_name-from }} previously delegated for the use of delegatee {{ account_name-to }}.
If I as signer am not the beneficial owner of these tokens I stipulate I have proof that I’ve been authorized to take this action by their beneficial owner(s).
All disputes arising from this contract shall be resolved in the EOS Core Arbitration Forum.
# Action - `{{ unlinkauth }}`
This Contract is legally binding and can be used in the event of a dispute.
### Description
The `{{ unlinkauth }}` action...
### Inputs and Input Types
The `{{ unlinkauth }}` action requires the following `inputs` and `input types`:
| Action | Input | Input Type |
|:--|:--|:--|
| `{{ unlinkauth }}` | `{{ accountVar }}`<br/>`{{ codeVar }}`<br/>`{{ typeVar }}` | `{{ account_name }}`<br/>`{{ account_name }}`<br/>`{{ action_name }}` |
As an authorized party I {{ signer }} wish to UNKNOWN
All disputes arising from this contract shall be resolved in the EOS Core Arbitration Forum.
# Action - `{{ unregprod }}`
This Contract is legally binding and can be used in the event of a dispute.
### Description
The `{{ unregprod }}` action...
### Input and Input Type
The `{{ unregprod }}` action requires the following `input` and `input type`:
| Action | Input | Input Type |
|:--|:--|:--|
| `{{ unregprod }}` | `{{ producerVar }}` | `{{ account_name }}` |
As an authorized party I {{ signer }} wish to unregister the block producer candidate {{ producerVar }}, rendering that candidate no longer able to receive votes.
All disputes arising from this contract shall be resolved in the EOS Core Arbitration Forum.
# Action - `{{ updateauth }}`
This Contract is legally binding and can be used in the event of a dispute.
### Description
The `{{ updateauth }}` action...
### Inputs and Input Types
The `{{ updateauth }}` action requires the following `inputs` and `input types`:
| Action | Input | Input Type |
|:--|:--|:--|
| `{{ updateauth }}` | `{{ accountVar }}`<br/>`{{ permissionVar }}`<br/>`{{ parentVar }}`<br/>`{{ authVar }}` | `{{ account_name }}`<br/>`{{ permission_name }}`<br/>`{{ permission_name }}`<br/>`{{ authority }}` |
As an authorized party I {{ signer }} wish to UNKNOWN
All disputes arising from this contract shall be resolved in the EOS Core Arbitration Forum.
...@@ -263,6 +263,7 @@ ...@@ -263,6 +263,7 @@
{"name":"total_activated_stake", "type":"int64"}, {"name":"total_activated_stake", "type":"int64"},
{"name":"thresh_activated_stake_time", "type":"uint64"}, {"name":"thresh_activated_stake_time", "type":"uint64"},
{"name":"last_producer_schedule_id", "type":"checksum160"}, {"name":"last_producer_schedule_id", "type":"checksum160"},
{"name":"last_producer_schedule_size", "type":"uint16"},
{"name":"total_producer_vote_weight", "type":"float64"}, {"name":"total_producer_vote_weight", "type":"float64"},
{"name":"last_name_close", "type":"block_timestamp_type"} {"name":"last_name_close", "type":"block_timestamp_type"}
] ]
...@@ -273,6 +274,7 @@ ...@@ -273,6 +274,7 @@
{"name":"owner", "type":"account_name"}, {"name":"owner", "type":"account_name"},
{"name":"total_votes", "type":"float64"}, {"name":"total_votes", "type":"float64"},
{"name":"producer_key", "type":"public_key"}, {"name":"producer_key", "type":"public_key"},
{"name":"is_active", "type":"bool"},
{"name":"url", "type":"string"}, {"name":"url", "type":"string"},
{"name":"unpaid_blocks", "type":"uint32"}, {"name":"unpaid_blocks", "type":"uint32"},
{"name":"last_claim_time", "type":"uint64"}, {"name":"last_claim_time", "type":"uint64"},
......
...@@ -59,21 +59,22 @@ namespace eosiosystem { ...@@ -59,21 +59,22 @@ namespace eosiosystem {
int64_t total_activated_stake = 0; int64_t total_activated_stake = 0;
uint64_t thresh_activated_stake_time = 0; uint64_t thresh_activated_stake_time = 0;
checksum160 last_producer_schedule_id; checksum160 last_producer_schedule_id;
uint16_t last_producer_schedule_size = 0;
double total_producer_vote_weight = 0; /// the sum of all producer votes double total_producer_vote_weight = 0; /// the sum of all producer votes
block_timestamp last_name_close; block_timestamp last_name_close;
// explicit serialization macro is not necessary, used here only to improve compilation time // explicit serialization macro is not necessary, used here only to improve compilation time
EOSLIB_SERIALIZE_DERIVED( eosio_global_state, eosio_parameters, (total_ram_bytes_reserved)(total_ram_stake) EOSLIB_SERIALIZE_DERIVED( eosio_global_state, eosio_parameters, (total_ram_bytes_reserved)(total_ram_stake)
(last_producer_schedule_update) (last_producer_schedule_update)(last_pervote_bucket_fill)
(last_pervote_bucket_fill)
(pervote_bucket)(perblock_bucket)(savings)(total_unpaid_blocks)(total_activated_stake)(thresh_activated_stake_time) (pervote_bucket)(perblock_bucket)(savings)(total_unpaid_blocks)(total_activated_stake)(thresh_activated_stake_time)
(last_producer_schedule_id)(total_producer_vote_weight)(last_name_close) ) (last_producer_schedule_id)(last_producer_schedule_size)(total_producer_vote_weight)(last_name_close) )
}; };
struct producer_info { struct producer_info {
account_name owner; account_name owner;
double total_votes = 0; double total_votes = 0;
eosio::public_key producer_key; /// a packed public key object eosio::public_key producer_key; /// a packed public key object
bool is_active = true;
std::string url; std::string url;
uint32_t unpaid_blocks = 0; uint32_t unpaid_blocks = 0;
uint64_t last_claim_time = 0; uint64_t last_claim_time = 0;
...@@ -81,12 +82,13 @@ namespace eosiosystem { ...@@ -81,12 +82,13 @@ namespace eosiosystem {
block_timestamp time_became_active; block_timestamp time_became_active;
block_timestamp last_produced_block_time; block_timestamp last_produced_block_time;
uint64_t primary_key()const { return owner; } uint64_t primary_key()const { return owner; }
double by_votes()const { return -total_votes; } double by_votes()const { return is_active ? -total_votes : total_votes; }
bool active() const { return producer_key != public_key(); } bool active()const { return is_active; }
void deactivate() { producer_key = public_key(); is_active = false; }
// explicit serialization macro is not necessary, used here only to improve compilation time // explicit serialization macro is not necessary, used here only to improve compilation time
EOSLIB_SERIALIZE( producer_info, (owner)(total_votes)(producer_key)(url) EOSLIB_SERIALIZE( producer_info, (owner)(total_votes)(producer_key)(is_active)(url)
(unpaid_blocks)(last_claim_time)(location) (unpaid_blocks)(last_claim_time)(location)
(time_became_active)(last_produced_block_time) ) (time_became_active)(last_produced_block_time) )
}; };
......
#Ricardian Contract for VOTEPRODUCER # Ricardian Contract for *voteproducer*
This Ricardian contract for the system command VOTEPRODUCER is legally binding and can be used in the event of a dispute. Disputes shall be settled in this system's default arbitration forum.
This Ricardian contract for the system command *voteproducer* is legally binding and can be used in the event of a dispute.
## VOTEPRODUCER (voter; array:producers)
_Intent: cast a valid vote for up to 30 BP candidates_
VOTEPRODUCER (voter; array:producers)
Intent: cast a valid vote for up to 30 BP candidates
As an authorized party I {{ signer }} wish to vote on behalf of {{ voter }} in favor of the block producer candidates {{ array:producers }} with a voting weight equal to all tokens currently owned by {{ voter }} and staked for CPU or bandwidth. As an authorized party I {{ signer }} wish to vote on behalf of {{ voter }} in favor of the block producer candidates {{ array:producers }} with a voting weight equal to all tokens currently owned by {{ voter }} and staked for CPU or bandwidth.
If I am not the beneficial owner of these shares I stipulate I have proof that I’ve been authorized to vote these shares by their beneficial owner(s). If I am not the beneficial owner of these shares I stipulate I have proof that I’ve been authorized to vote these shares by their beneficial owner(s).
I stipulate I have not and will not accept anything of value in exchange for these votes, on penalty of confiscation of these tokens, and other penalties. I stipulate I have not and will not accept anything of value in exchange for these votes, on penalty of confiscation of these tokens, and other penalties.
I acknowledge that using any system of automatic voting, re-voting, or vote refreshing, or allowing such a system to be used on my behalf or on behalf of another, is forbidden and doing so violates this contract. I acknowledge that using any system of automatic voting, re-voting, or vote refreshing, or allowing such a system to be used on my behalf or on behalf of another, is forbidden and doing so violates this contract.
\ No newline at end of file
All disputes arising from this contract shall be resolved in the EOS Core Arbitration Forum.
...@@ -36,6 +36,7 @@ namespace eosiosystem { ...@@ -36,6 +36,7 @@ namespace eosiosystem {
*/ */
void system_contract::regproducer( const account_name producer, const eosio::public_key& producer_key, const std::string& url, uint16_t location ) { void system_contract::regproducer( const account_name producer, const eosio::public_key& producer_key, const std::string& url, uint16_t location ) {
eosio_assert( url.size() < 512, "url too long" ); eosio_assert( url.size() < 512, "url too long" );
eosio_assert( producer_key != eosio::public_key(), "public key should not be the default value" );
require_auth( producer ); require_auth( producer );
auto prod = _producers.find( producer ); auto prod = _producers.find( producer );
...@@ -44,6 +45,7 @@ namespace eosiosystem { ...@@ -44,6 +45,7 @@ namespace eosiosystem {
if( producer_key != prod->producer_key ) { if( producer_key != prod->producer_key ) {
_producers.modify( prod, producer, [&]( producer_info& info ){ _producers.modify( prod, producer, [&]( producer_info& info ){
info.producer_key = producer_key; info.producer_key = producer_key;
info.is_active = true;
info.url = url; info.url = url;
info.location = location; info.location = location;
}); });
...@@ -53,6 +55,7 @@ namespace eosiosystem { ...@@ -53,6 +55,7 @@ namespace eosiosystem {
info.owner = producer; info.owner = producer;
info.total_votes = 0; info.total_votes = 0;
info.producer_key = producer_key; info.producer_key = producer_key;
info.is_active = true;
info.url = url; info.url = url;
info.location = location; info.location = location;
}); });
...@@ -65,7 +68,7 @@ namespace eosiosystem { ...@@ -65,7 +68,7 @@ namespace eosiosystem {
const auto& prod = _producers.get( producer, "producer not found" ); const auto& prod = _producers.get( producer, "producer not found" );
_producers.modify( prod, 0, [&]( producer_info& info ){ _producers.modify( prod, 0, [&]( producer_info& info ){
info.producer_key = eosio::public_key(); info.deactivate();
}); });
} }
...@@ -77,8 +80,8 @@ namespace eosiosystem { ...@@ -77,8 +80,8 @@ namespace eosiosystem {
std::vector< std::pair<eosio::producer_key,uint16_t> > top_producers; std::vector< std::pair<eosio::producer_key,uint16_t> > top_producers;
top_producers.reserve(21); top_producers.reserve(21);
for ( auto it = idx.cbegin(); it != idx.cend() && top_producers.size() < 21 && 0 < it->total_votes; ++it ) { std::vector<decltype(idx.cbegin())> inactive_iters;
if( !it->active() ) continue; for ( auto it = idx.cbegin(); it != idx.cend() && top_producers.size() < 21 && 0 < it->total_votes && it->active(); ++it ) {
/** /**
If it's the first time or it's been over a day since a producer was last voted in, If it's the first time or it's been over a day since a producer was last voted in,
...@@ -86,17 +89,14 @@ namespace eosiosystem { ...@@ -86,17 +89,14 @@ namespace eosiosystem {
he gets deactivated if he hasn't produced in 24 hours. he gets deactivated if he hasn't produced in 24 hours.
*/ */
if ( it->time_became_active.slot == 0 || if ( it->time_became_active.slot == 0 ||
block_time.slot > it->time_became_active.slot + blocks_per_day ) { block_time.slot > it->time_became_active.slot + 23 * blocks_per_hour ) {
_producers.modify( *it, 0, [&](auto& p) { _producers.modify( *it, 0, [&](auto& p) {
p.time_became_active = block_time; p.time_became_active = block_time;
}); });
} else if ( block_time.slot > (2 * 21 * 12 * 100) + it->time_became_active.slot && } else if ( block_time.slot > (2 * 21 * 12 * 100) + it->time_became_active.slot &&
block_time.slot > it->last_produced_block_time.slot + blocks_per_day ) { block_time.slot > it->last_produced_block_time.slot + blocks_per_day ) {
_producers.modify( *it, 0, [&](auto& p) { // save producers that will be deactivated
p.producer_key = public_key(); inactive_iters.push_back(it);
p.time_became_active.slot = 0;
});
continue; continue;
} else { } else {
_producers.modify( *it, 0, [&](auto& p) { _producers.modify( *it, 0, [&](auto& p) {
...@@ -104,10 +104,19 @@ namespace eosiosystem { ...@@ -104,10 +104,19 @@ namespace eosiosystem {
}); });
} }
top_producers.emplace_back( std::pair<eosio::producer_key,uint16_t>({{it->owner, it->producer_key}, it->location})); top_producers.emplace_back( std::pair<eosio::producer_key,uint16_t>({{it->owner, it->producer_key}, it->location}) );
} }
if ( top_producers.size() < _gstate.last_producer_schedule_size ) {
return;
}
for ( const auto& it: inactive_iters ) {
_producers.modify( *it, 0, [&](auto& p) {
p.deactivate();
p.time_became_active.slot = 0;
});
}
/// sort by producer name /// sort by producer name
std::sort( top_producers.begin(), top_producers.end() ); std::sort( top_producers.begin(), top_producers.end() );
...@@ -125,6 +134,7 @@ namespace eosiosystem { ...@@ -125,6 +134,7 @@ namespace eosiosystem {
if( new_id != _gstate.last_producer_schedule_id ) { if( new_id != _gstate.last_producer_schedule_id ) {
_gstate.last_producer_schedule_id = new_id; _gstate.last_producer_schedule_id = new_id;
set_proposed_producers( packed_schedule.data(), packed_schedule.size() ); set_proposed_producers( packed_schedule.data(), packed_schedule.size() );
_gstate.last_producer_schedule_size = top_producers.size();
} }
_gstate.last_producer_schedule_update = block_time; _gstate.last_producer_schedule_update = block_time;
} }
...@@ -234,7 +244,7 @@ namespace eosiosystem { ...@@ -234,7 +244,7 @@ namespace eosiosystem {
eosio_assert( !voting || pitr->active() || !pd.second.second /* not from new set */, "producer is not currently registered" ); eosio_assert( !voting || pitr->active() || !pd.second.second /* not from new set */, "producer is not currently registered" );
_producers.modify( pitr, 0, [&]( auto& p ) { _producers.modify( pitr, 0, [&]( auto& p ) {
p.total_votes += pd.second.first; p.total_votes += pd.second.first;
if ( p.total_votes < 0 ) { // floating point ariphmetics can give as small negative numbers if ( p.total_votes < 0 ) { // floating point arithmetics can give small negative numbers
p.total_votes = 0; p.total_votes = 0;
} }
_gstate.total_producer_vote_weight += pd.second.first; _gstate.total_producer_vote_weight += pd.second.first;
......
...@@ -375,6 +375,8 @@ int apply_context::get_action( uint32_t type, uint32_t index, char* buffer, size ...@@ -375,6 +375,8 @@ int apply_context::get_action( uint32_t type, uint32_t index, char* buffer, size
return -1; return -1;
act_ptr = &trx.actions[index]; act_ptr = &trx.actions[index];
} }
FC_ASSERT(act_ptr, "action is not found" );
auto ps = fc::raw::pack_size( *act_ptr ); auto ps = fc::raw::pack_size( *act_ptr );
if( ps <= buffer_size ) { if( ps <= buffer_size ) {
......
...@@ -157,6 +157,7 @@ class binaryen_runtime : public eosio::chain::wasm_runtime_interface { ...@@ -157,6 +157,7 @@ class binaryen_runtime : public eosio::chain::wasm_runtime_interface {
template<typename T> template<typename T>
inline array_ptr<T> array_ptr_impl (interpreter_interface* interface, uint32_t ptr, uint32_t length) inline array_ptr<T> array_ptr_impl (interpreter_interface* interface, uint32_t ptr, uint32_t length)
{ {
FC_ASSERT( length < INT_MAX/(uint32_t)sizeof(T), "length will overflow" );
return array_ptr<T>((T*)(interface->get_validated_pointer(ptr, length * (uint32_t)sizeof(T)))); return array_ptr<T>((T*)(interface->get_validated_pointer(ptr, length * (uint32_t)sizeof(T))));
} }
...@@ -326,7 +327,7 @@ struct intrinsic_invoker_impl<Ret, std::tuple<Input, Inputs...>> { ...@@ -326,7 +327,7 @@ struct intrinsic_invoker_impl<Ret, std::tuple<Input, Inputs...>> {
static Ret translate_one(interpreter_interface* interface, Inputs... rest, LiteralList& args, int offset) { static Ret translate_one(interpreter_interface* interface, Inputs... rest, LiteralList& args, int offset) {
auto& last = args.at(offset); auto& last = args.at(offset);
auto native = convert_literal_to_native<Input>(last); auto native = convert_literal_to_native<Input>(last);
return Then(interface, native, rest..., args, offset - 1); return Then(interface, native, rest..., args, (uint32_t)offset - 1);
}; };
template<then_type Then> template<then_type Then>
...@@ -351,35 +352,35 @@ struct intrinsic_invoker_impl<Ret, std::tuple<array_ptr<T>, size_t, Inputs...>> ...@@ -351,35 +352,35 @@ struct intrinsic_invoker_impl<Ret, std::tuple<array_ptr<T>, size_t, Inputs...>>
template<then_type Then, typename U=T> template<then_type Then, typename U=T>
static auto translate_one(interpreter_interface* interface, Inputs... rest, LiteralList& args, int offset) -> std::enable_if_t<std::is_const<U>::value, Ret> { static auto translate_one(interpreter_interface* interface, Inputs... rest, LiteralList& args, int offset) -> std::enable_if_t<std::is_const<U>::value, Ret> {
static_assert(!std::is_pointer<U>::value, "Currently don't support array of pointers"); static_assert(!std::is_pointer<U>::value, "Currently don't support array of pointers");
uint32_t ptr = args.at(offset - 1).geti32(); uint32_t ptr = args.at((uint32_t)offset - 1).geti32();
size_t length = args.at(offset).geti32(); size_t length = args.at((uint32_t)offset).geti32();
T* base = array_ptr_impl<T>(interface, ptr, length); T* base = array_ptr_impl<T>(interface, ptr, length);
if ( reinterpret_cast<uintptr_t>(base) % alignof(T) != 0 ) { if ( reinterpret_cast<uintptr_t>(base) % alignof(T) != 0 ) {
wlog( "misaligned array of const values" ); wlog( "misaligned array of const values" );
std::remove_const_t<T> copy[length]; std::remove_const_t<T> copy[length];
T* copy_ptr = &copy[0]; T* copy_ptr = &copy[0];
memcpy( (void*)copy_ptr, (void*)base, length * sizeof(T) ); memcpy( (void*)copy_ptr, (void*)base, length * sizeof(T) );
return Then(interface, static_cast<array_ptr<T>>(copy_ptr), length, rest..., args, offset - 2); return Then(interface, static_cast<array_ptr<T>>(copy_ptr), length, rest..., args, (uint32_t)offset - 2);
} }
return Then(interface, static_cast<array_ptr<T>>(base), length, rest..., args, offset - 2); return Then(interface, static_cast<array_ptr<T>>(base), length, rest..., args, (uint32_t)offset - 2);
}; };
template<then_type Then, typename U=T> template<then_type Then, typename U=T>
static auto translate_one(interpreter_interface* interface, Inputs... rest, LiteralList& args, int offset) -> std::enable_if_t<!std::is_const<U>::value, Ret> { static auto translate_one(interpreter_interface* interface, Inputs... rest, LiteralList& args, int offset) -> std::enable_if_t<!std::is_const<U>::value, Ret> {
static_assert(!std::is_pointer<U>::value, "Currently don't support array of pointers"); static_assert(!std::is_pointer<U>::value, "Currently don't support array of pointers");
uint32_t ptr = args.at(offset - 1).geti32(); uint32_t ptr = args.at((uint32_t)offset - 1).geti32();
size_t length = args.at(offset).geti32(); size_t length = args.at((uint32_t)offset).geti32();
T* base = array_ptr_impl<T>(interface, ptr, length); T* base = array_ptr_impl<T>(interface, ptr, length);
if ( reinterpret_cast<uintptr_t>(base) % alignof(T) != 0 ) { if ( reinterpret_cast<uintptr_t>(base) % alignof(T) != 0 ) {
wlog( "misaligned array of values" ); wlog( "misaligned array of values" );
std::remove_const_t<T> copy[length]; std::remove_const_t<T> copy[length];
T* copy_ptr = &copy[0]; T* copy_ptr = &copy[0];
memcpy( (void*)copy_ptr, (void*)base, length * sizeof(T) ); memcpy( (void*)copy_ptr, (void*)base, length * sizeof(T) );
Ret ret = Then(interface, static_cast<array_ptr<T>>(copy_ptr), length, rest..., args, offset - 2); Ret ret = Then(interface, static_cast<array_ptr<T>>(copy_ptr), length, rest..., args, (uint32_t)offset - 2);
memcpy( (void*)base, (void*)copy_ptr, length * sizeof(T) ); memcpy( (void*)base, (void*)copy_ptr, length * sizeof(T) );
return ret; return ret;
} }
return Then(interface, static_cast<array_ptr<T>>(base), length, rest..., args, offset - 2); return Then(interface, static_cast<array_ptr<T>>(base), length, rest..., args, (uint32_t)offset - 2);
}; };
template<then_type Then> template<then_type Then>
...@@ -403,8 +404,8 @@ struct intrinsic_invoker_impl<Ret, std::tuple<null_terminated_ptr, Inputs...>> { ...@@ -403,8 +404,8 @@ struct intrinsic_invoker_impl<Ret, std::tuple<null_terminated_ptr, Inputs...>> {
template<then_type Then> template<then_type Then>
static Ret translate_one(interpreter_interface* interface, Inputs... rest, LiteralList& args, int offset) { static Ret translate_one(interpreter_interface* interface, Inputs... rest, LiteralList& args, int offset) {
uint32_t ptr = args.at(offset).geti32(); uint32_t ptr = args.at((uint32_t)offset).geti32();
return Then(interface, null_terminated_ptr_impl(interface, ptr), rest..., args, offset - 1); return Then(interface, null_terminated_ptr_impl(interface, ptr), rest..., args, (uint32_t)offset - 1);
}; };
template<then_type Then> template<then_type Then>
...@@ -428,11 +429,11 @@ struct intrinsic_invoker_impl<Ret, std::tuple<array_ptr<T>, array_ptr<U>, size_t ...@@ -428,11 +429,11 @@ struct intrinsic_invoker_impl<Ret, std::tuple<array_ptr<T>, array_ptr<U>, size_t
template<then_type Then> template<then_type Then>
static Ret translate_one(interpreter_interface* interface, Inputs... rest, LiteralList& args, int offset) { static Ret translate_one(interpreter_interface* interface, Inputs... rest, LiteralList& args, int offset) {
uint32_t ptr_t = args.at(offset - 2).geti32(); uint32_t ptr_t = args.at((uint32_t)offset - 2).geti32();
uint32_t ptr_u = args.at(offset - 1).geti32(); uint32_t ptr_u = args.at((uint32_t)offset - 1).geti32();
size_t length = args.at(offset).geti32(); size_t length = args.at((uint32_t)offset).geti32();
static_assert(std::is_same<std::remove_const_t<T>, char>::value && std::is_same<std::remove_const_t<U>, char>::value, "Currently only support array of (const)chars"); static_assert(std::is_same<std::remove_const_t<T>, char>::value && std::is_same<std::remove_const_t<U>, char>::value, "Currently only support array of (const)chars");
return Then(interface, array_ptr_impl<T>(interface, ptr_t, length), array_ptr_impl<U>(interface, ptr_u, length), length, args, offset - 3); return Then(interface, array_ptr_impl<T>(interface, ptr_t, length), array_ptr_impl<U>(interface, ptr_u, length), length, args, (uint32_t)offset - 3);
}; };
template<then_type Then> template<then_type Then>
...@@ -454,10 +455,10 @@ struct intrinsic_invoker_impl<Ret, std::tuple<array_ptr<char>, int, size_t>> { ...@@ -454,10 +455,10 @@ struct intrinsic_invoker_impl<Ret, std::tuple<array_ptr<char>, int, size_t>> {
template<then_type Then> template<then_type Then>
static Ret translate_one(interpreter_interface* interface, LiteralList& args, int offset) { static Ret translate_one(interpreter_interface* interface, LiteralList& args, int offset) {
uint32_t ptr = args.at(offset - 2).geti32(); uint32_t ptr = args.at((uint32_t)offset - 2).geti32();
uint32_t value = args.at(offset - 1).geti32(); uint32_t value = args.at((uint32_t)offset - 1).geti32();
size_t length = args.at(offset).geti32(); size_t length = args.at((uint32_t)offset).geti32();
return Then(interface, array_ptr_impl<char>(interface, ptr, length), value, length, args, offset - 3); return Then(interface, array_ptr_impl<char>(interface, ptr, length), value, length, args, (uint32_t)offset - 3);
}; };
template<then_type Then> template<then_type Then>
...@@ -481,31 +482,31 @@ struct intrinsic_invoker_impl<Ret, std::tuple<T *, Inputs...>> { ...@@ -481,31 +482,31 @@ struct intrinsic_invoker_impl<Ret, std::tuple<T *, Inputs...>> {
template<then_type Then, typename U=T> template<then_type Then, typename U=T>
static auto translate_one(interpreter_interface* interface, Inputs... rest, LiteralList& args, int offset) -> std::enable_if_t<std::is_const<U>::value, Ret> { static auto translate_one(interpreter_interface* interface, Inputs... rest, LiteralList& args, int offset) -> std::enable_if_t<std::is_const<U>::value, Ret> {
uint32_t ptr = args.at(offset).geti32(); uint32_t ptr = args.at((uint32_t)offset).geti32();
T* base = array_ptr_impl<T>(interface, ptr, 1); T* base = array_ptr_impl<T>(interface, ptr, 1);
if ( reinterpret_cast<uintptr_t>(base) % alignof(T) != 0 ) { if ( reinterpret_cast<uintptr_t>(base) % alignof(T) != 0 ) {
wlog( "misaligned const pointer" ); wlog( "misaligned const pointer" );
std::remove_const_t<T> copy; std::remove_const_t<T> copy;
T* copy_ptr = &copy; T* copy_ptr = &copy;
memcpy( (void*)copy_ptr, (void*)base, sizeof(T) ); memcpy( (void*)copy_ptr, (void*)base, sizeof(T) );
return Then(interface, copy_ptr, rest..., args, offset - 1); return Then(interface, copy_ptr, rest..., args, (uint32_t)offset - 1);
} }
return Then(interface, base, rest..., args, offset - 1); return Then(interface, base, rest..., args, (uint32_t)offset - 1);
}; };
template<then_type Then, typename U=T> template<then_type Then, typename U=T>
static auto translate_one(interpreter_interface* interface, Inputs... rest, LiteralList& args, int offset) -> std::enable_if_t<!std::is_const<U>::value, Ret> { static auto translate_one(interpreter_interface* interface, Inputs... rest, LiteralList& args, int offset) -> std::enable_if_t<!std::is_const<U>::value, Ret> {
uint32_t ptr = args.at(offset).geti32(); uint32_t ptr = args.at((uint32_t)offset).geti32();
T* base = array_ptr_impl<T>(interface, ptr, 1); T* base = array_ptr_impl<T>(interface, ptr, 1);
if ( reinterpret_cast<uintptr_t>(base) % alignof(T) != 0 ) { if ( reinterpret_cast<uintptr_t>(base) % alignof(T) != 0 ) {
wlog( "misaligned pointer" ); wlog( "misaligned pointer" );
T copy; T copy;
memcpy( (void*)&copy, (void*)base, sizeof(T) ); memcpy( (void*)&copy, (void*)base, sizeof(T) );
Ret ret = Then(interface, &copy, rest..., args, offset - 1); Ret ret = Then(interface, &copy, rest..., args, (uint32_t)offset - 1);
memcpy( (void*)base, (void*)&copy, sizeof(T) ); memcpy( (void*)base, (void*)&copy, sizeof(T) );
return ret; return ret;
} }
return Then(interface, base, rest..., args, offset - 1); return Then(interface, base, rest..., args, (uint32_t)offset - 1);
}; };
template<then_type Then> template<then_type Then>
...@@ -529,9 +530,9 @@ struct intrinsic_invoker_impl<Ret, std::tuple<const name&, Inputs...>> { ...@@ -529,9 +530,9 @@ struct intrinsic_invoker_impl<Ret, std::tuple<const name&, Inputs...>> {
template<then_type Then> template<then_type Then>
static Ret translate_one(interpreter_interface* interface, Inputs... rest, LiteralList& args, int offset) { static Ret translate_one(interpreter_interface* interface, Inputs... rest, LiteralList& args, int offset) {
uint64_t wasm_value = args.at(offset).geti64(); uint64_t wasm_value = args.at((uint32_t)offset).geti64();
auto value = name(wasm_value); auto value = name(wasm_value);
return Then(interface, value, rest..., args, offset - 1); return Then(interface, value, rest..., args, (uint32_t)offset - 1);
} }
template<then_type Then> template<then_type Then>
...@@ -555,9 +556,9 @@ struct intrinsic_invoker_impl<Ret, std::tuple<const fc::time_point_sec&, Inputs. ...@@ -555,9 +556,9 @@ struct intrinsic_invoker_impl<Ret, std::tuple<const fc::time_point_sec&, Inputs.
template<then_type Then> template<then_type Then>
static Ret translate_one(interpreter_interface* interface, Inputs... rest, LiteralList& args, int offset) { static Ret translate_one(interpreter_interface* interface, Inputs... rest, LiteralList& args, int offset) {
uint32_t wasm_value = args.at(offset).geti32(); uint32_t wasm_value = args.at((uint32_t)offset).geti32();
auto value = fc::time_point_sec(wasm_value); auto value = fc::time_point_sec(wasm_value);
return Then(interface, value, rest..., args, offset - 1); return Then(interface, value, rest..., args, (uint32_t)offset - 1);
} }
template<then_type Then> template<then_type Then>
...@@ -583,7 +584,7 @@ struct intrinsic_invoker_impl<Ret, std::tuple<T &, Inputs...>> { ...@@ -583,7 +584,7 @@ struct intrinsic_invoker_impl<Ret, std::tuple<T &, Inputs...>> {
template<then_type Then, typename U=T> template<then_type Then, typename U=T>
static auto translate_one(interpreter_interface* interface, Inputs... rest, LiteralList& args, int offset) -> std::enable_if_t<std::is_const<U>::value, Ret> { static auto translate_one(interpreter_interface* interface, Inputs... rest, LiteralList& args, int offset) -> std::enable_if_t<std::is_const<U>::value, Ret> {
// references cannot be created for null pointers // references cannot be created for null pointers
uint32_t ptr = args.at(offset).geti32(); uint32_t ptr = args.at((uint32_t)offset).geti32();
FC_ASSERT(ptr != 0); FC_ASSERT(ptr != 0);
T* base = array_ptr_impl<T>(interface, ptr, 1); T* base = array_ptr_impl<T>(interface, ptr, 1);
if ( reinterpret_cast<uintptr_t>(base) % alignof(T) != 0 ) { if ( reinterpret_cast<uintptr_t>(base) % alignof(T) != 0 ) {
...@@ -591,26 +592,26 @@ struct intrinsic_invoker_impl<Ret, std::tuple<T &, Inputs...>> { ...@@ -591,26 +592,26 @@ struct intrinsic_invoker_impl<Ret, std::tuple<T &, Inputs...>> {
std::remove_const_t<T> copy; std::remove_const_t<T> copy;
T* copy_ptr = &copy; T* copy_ptr = &copy;
memcpy( (void*)copy_ptr, (void*)base, sizeof(T) ); memcpy( (void*)copy_ptr, (void*)base, sizeof(T) );
return Then(interface, *copy_ptr, rest..., args, offset - 1); return Then(interface, *copy_ptr, rest..., args, (uint32_t)offset - 1);
} }
return Then(interface, *base, rest..., args, offset - 1); return Then(interface, *base, rest..., args, (uint32_t)offset - 1);
} }
template<then_type Then, typename U=T> template<then_type Then, typename U=T>
static auto translate_one(interpreter_interface* interface, Inputs... rest, LiteralList& args, int offset) -> std::enable_if_t<!std::is_const<U>::value, Ret> { static auto translate_one(interpreter_interface* interface, Inputs... rest, LiteralList& args, int offset) -> std::enable_if_t<!std::is_const<U>::value, Ret> {
// references cannot be created for null pointers // references cannot be created for null pointers
uint32_t ptr = args.at(offset).geti32(); uint32_t ptr = args.at((uint32_t)offset).geti32();
FC_ASSERT(ptr != 0); FC_ASSERT(ptr != 0);
T* base = array_ptr_impl<T>(interface, ptr, 1); T* base = array_ptr_impl<T>(interface, ptr, 1);
if ( reinterpret_cast<uintptr_t>(base) % alignof(T) != 0 ) { if ( reinterpret_cast<uintptr_t>(base) % alignof(T) != 0 ) {
wlog( "misaligned reference" ); wlog( "misaligned reference" );
T copy; T copy;
memcpy( (void*)&copy, (void*)base, sizeof(T) ); memcpy( (void*)&copy, (void*)base, sizeof(T) );
Ret ret = Then(interface, copy, rest..., args, offset - 1); Ret ret = Then(interface, copy, rest..., args, (uint32_t)offset - 1);
memcpy( (void*)base, (void*)&copy, sizeof(T) ); memcpy( (void*)base, (void*)&copy, sizeof(T) );
return ret; return ret;
} }
return Then(interface, *base, rest..., args, offset - 1); return Then(interface, *base, rest..., args, (uint32_t)offset - 1);
} }
......
...@@ -170,7 +170,7 @@ inline auto convert_native_to_wasm(running_instance_context& ctx, char* ptr) { ...@@ -170,7 +170,7 @@ inline auto convert_native_to_wasm(running_instance_context& ctx, char* ptr) {
char* top_of_memory = base + IR::numBytesPerPage*Runtime::getMemoryNumPages(mem); char* top_of_memory = base + IR::numBytesPerPage*Runtime::getMemoryNumPages(mem);
if(ptr < base || ptr >= top_of_memory) if(ptr < base || ptr >= top_of_memory)
Runtime::causeException(Exception::Cause::accessViolation); Runtime::causeException(Exception::Cause::accessViolation);
return (int)(ptr - base); return (U32)(ptr - base);
} }
template<typename T> template<typename T>
...@@ -379,7 +379,7 @@ struct intrinsic_invoker_impl<Ret, std::tuple<array_ptr<T>, size_t, Inputs...>, ...@@ -379,7 +379,7 @@ struct intrinsic_invoker_impl<Ret, std::tuple<array_ptr<T>, size_t, Inputs...>,
static auto translate_one(running_instance_context& ctx, Inputs... rest, Translated... translated, I32 ptr, I32 size) -> std::enable_if_t<std::is_const<U>::value, Ret> { static auto translate_one(running_instance_context& ctx, Inputs... rest, Translated... translated, I32 ptr, I32 size) -> std::enable_if_t<std::is_const<U>::value, Ret> {
static_assert(!std::is_pointer<U>::value, "Currently don't support array of pointers"); static_assert(!std::is_pointer<U>::value, "Currently don't support array of pointers");
const auto length = size_t(size); const auto length = size_t(size);
T* base = array_ptr_impl<T>(ctx, ptr, length); T* base = array_ptr_impl<T>(ctx, (U32)ptr, length);
if ( reinterpret_cast<uintptr_t>(base) % alignof(T) != 0 ) { if ( reinterpret_cast<uintptr_t>(base) % alignof(T) != 0 ) {
wlog( "misaligned array of const values" ); wlog( "misaligned array of const values" );
std::remove_const_t<T> copy[length]; std::remove_const_t<T> copy[length];
...@@ -394,7 +394,7 @@ struct intrinsic_invoker_impl<Ret, std::tuple<array_ptr<T>, size_t, Inputs...>, ...@@ -394,7 +394,7 @@ struct intrinsic_invoker_impl<Ret, std::tuple<array_ptr<T>, size_t, Inputs...>,
static auto translate_one(running_instance_context& ctx, Inputs... rest, Translated... translated, I32 ptr, I32 size) -> std::enable_if_t<!std::is_const<U>::value, Ret> { static auto translate_one(running_instance_context& ctx, Inputs... rest, Translated... translated, I32 ptr, I32 size) -> std::enable_if_t<!std::is_const<U>::value, Ret> {
static_assert(!std::is_pointer<U>::value, "Currently don't support array of pointers"); static_assert(!std::is_pointer<U>::value, "Currently don't support array of pointers");
const auto length = size_t(size); const auto length = size_t(size);
T* base = array_ptr_impl<T>(ctx, ptr, length); T* base = array_ptr_impl<T>(ctx, (U32)ptr, length);
if ( reinterpret_cast<uintptr_t>(base) % alignof(T) != 0 ) { if ( reinterpret_cast<uintptr_t>(base) % alignof(T) != 0 ) {
wlog( "misaligned array of values" ); wlog( "misaligned array of values" );
std::remove_const_t<T> copy[length]; std::remove_const_t<T> copy[length];
...@@ -429,7 +429,7 @@ struct intrinsic_invoker_impl<Ret, std::tuple<null_terminated_ptr, Inputs...>, s ...@@ -429,7 +429,7 @@ struct intrinsic_invoker_impl<Ret, std::tuple<null_terminated_ptr, Inputs...>, s
template<then_type Then> template<then_type Then>
static Ret translate_one(running_instance_context& ctx, Inputs... rest, Translated... translated, I32 ptr) { static Ret translate_one(running_instance_context& ctx, Inputs... rest, Translated... translated, I32 ptr) {
return Then(ctx, null_terminated_ptr_impl(ctx, ptr), rest..., translated...); return Then(ctx, null_terminated_ptr_impl(ctx, (U32)ptr), rest..., translated...);
}; };
template<then_type Then> template<then_type Then>
...@@ -456,7 +456,7 @@ struct intrinsic_invoker_impl<Ret, std::tuple<array_ptr<T>, array_ptr<U>, size_t ...@@ -456,7 +456,7 @@ struct intrinsic_invoker_impl<Ret, std::tuple<array_ptr<T>, array_ptr<U>, size_t
static Ret translate_one(running_instance_context& ctx, Inputs... rest, Translated... translated, I32 ptr_t, I32 ptr_u, I32 size) { static Ret translate_one(running_instance_context& ctx, Inputs... rest, Translated... translated, I32 ptr_t, I32 ptr_u, I32 size) {
static_assert(std::is_same<std::remove_const_t<T>, char>::value && std::is_same<std::remove_const_t<U>, char>::value, "Currently only support array of (const)chars"); static_assert(std::is_same<std::remove_const_t<T>, char>::value && std::is_same<std::remove_const_t<U>, char>::value, "Currently only support array of (const)chars");
const auto length = size_t(size); const auto length = size_t(size);
return Then(ctx, array_ptr_impl<T>(ctx, ptr_t, length), array_ptr_impl<U>(ctx, ptr_u, length), length, rest..., translated...); return Then(ctx, array_ptr_impl<T>(ctx, (U32)ptr_t, length), array_ptr_impl<U>(ctx, (U32)ptr_u, length), length, rest..., translated...);
}; };
template<then_type Then> template<then_type Then>
...@@ -480,7 +480,7 @@ struct intrinsic_invoker_impl<Ret, std::tuple<array_ptr<char>, int, size_t>, std ...@@ -480,7 +480,7 @@ struct intrinsic_invoker_impl<Ret, std::tuple<array_ptr<char>, int, size_t>, std
template<then_type Then> template<then_type Then>
static Ret translate_one(running_instance_context& ctx, I32 ptr, I32 value, I32 size) { static Ret translate_one(running_instance_context& ctx, I32 ptr, I32 value, I32 size) {
const auto length = size_t(size); const auto length = size_t(size);
return Then(ctx, array_ptr_impl<char>(ctx, ptr, length), value, length); return Then(ctx, array_ptr_impl<char>(ctx, (U32)ptr, length), value, length);
}; };
template<then_type Then> template<then_type Then>
...@@ -505,7 +505,7 @@ struct intrinsic_invoker_impl<Ret, std::tuple<T *, Inputs...>, std::tuple<Transl ...@@ -505,7 +505,7 @@ struct intrinsic_invoker_impl<Ret, std::tuple<T *, Inputs...>, std::tuple<Transl
template<then_type Then, typename U=T> template<then_type Then, typename U=T>
static auto translate_one(running_instance_context& ctx, Inputs... rest, Translated... translated, I32 ptr) -> std::enable_if_t<std::is_const<U>::value, Ret> { static auto translate_one(running_instance_context& ctx, Inputs... rest, Translated... translated, I32 ptr) -> std::enable_if_t<std::is_const<U>::value, Ret> {
T* base = array_ptr_impl<T>(ctx, ptr, 1); T* base = array_ptr_impl<T>(ctx, (U32)ptr, 1);
if ( reinterpret_cast<uintptr_t>(base) % alignof(T) != 0 ) { if ( reinterpret_cast<uintptr_t>(base) % alignof(T) != 0 ) {
wlog( "misaligned const pointer" ); wlog( "misaligned const pointer" );
std::remove_const_t<T> copy; std::remove_const_t<T> copy;
...@@ -518,7 +518,7 @@ struct intrinsic_invoker_impl<Ret, std::tuple<T *, Inputs...>, std::tuple<Transl ...@@ -518,7 +518,7 @@ struct intrinsic_invoker_impl<Ret, std::tuple<T *, Inputs...>, std::tuple<Transl
template<then_type Then, typename U=T> template<then_type Then, typename U=T>
static auto translate_one(running_instance_context& ctx, Inputs... rest, Translated... translated, I32 ptr) -> std::enable_if_t<!std::is_const<U>::value, Ret> { static auto translate_one(running_instance_context& ctx, Inputs... rest, Translated... translated, I32 ptr) -> std::enable_if_t<!std::is_const<U>::value, Ret> {
T* base = array_ptr_impl<T>(ctx, ptr, 1); T* base = array_ptr_impl<T>(ctx, (U32)ptr, 1);
if ( reinterpret_cast<uintptr_t>(base) % alignof(T) != 0 ) { if ( reinterpret_cast<uintptr_t>(base) % alignof(T) != 0 ) {
wlog( "misaligned pointer" ); wlog( "misaligned pointer" );
std::remove_const_t<T> copy; std::remove_const_t<T> copy;
...@@ -580,11 +580,11 @@ struct intrinsic_invoker_impl<Ret, std::tuple<T &, Inputs...>, std::tuple<Transl ...@@ -580,11 +580,11 @@ struct intrinsic_invoker_impl<Ret, std::tuple<T &, Inputs...>, std::tuple<Transl
template<then_type Then, typename U=T> template<then_type Then, typename U=T>
static auto translate_one(running_instance_context& ctx, Inputs... rest, Translated... translated, I32 ptr) -> std::enable_if_t<std::is_const<U>::value, Ret> { static auto translate_one(running_instance_context& ctx, Inputs... rest, Translated... translated, I32 ptr) -> std::enable_if_t<std::is_const<U>::value, Ret> {
// references cannot be created for null pointers // references cannot be created for null pointers
FC_ASSERT(ptr != 0); FC_ASSERT((U32)ptr != 0);
MemoryInstance* mem = ctx.memory; MemoryInstance* mem = ctx.memory;
if(!mem || ptr+sizeof(T) >= IR::numBytesPerPage*Runtime::getMemoryNumPages(mem)) if(!mem || (U32)ptr+sizeof(T) >= IR::numBytesPerPage*Runtime::getMemoryNumPages(mem))
Runtime::causeException(Exception::Cause::accessViolation); Runtime::causeException(Exception::Cause::accessViolation);
T &base = *(T*)(getMemoryBaseAddress(mem)+ptr); T &base = *(T*)(getMemoryBaseAddress(mem)+(U32)ptr);
if ( reinterpret_cast<uintptr_t>(&base) % alignof(T) != 0 ) { if ( reinterpret_cast<uintptr_t>(&base) % alignof(T) != 0 ) {
wlog( "misaligned const reference" ); wlog( "misaligned const reference" );
std::remove_const_t<T> copy; std::remove_const_t<T> copy;
...@@ -598,11 +598,11 @@ struct intrinsic_invoker_impl<Ret, std::tuple<T &, Inputs...>, std::tuple<Transl ...@@ -598,11 +598,11 @@ struct intrinsic_invoker_impl<Ret, std::tuple<T &, Inputs...>, std::tuple<Transl
template<then_type Then, typename U=T> template<then_type Then, typename U=T>
static auto translate_one(running_instance_context& ctx, Inputs... rest, Translated... translated, I32 ptr) -> std::enable_if_t<!std::is_const<U>::value, Ret> { static auto translate_one(running_instance_context& ctx, Inputs... rest, Translated... translated, I32 ptr) -> std::enable_if_t<!std::is_const<U>::value, Ret> {
// references cannot be created for null pointers // references cannot be created for null pointers
FC_ASSERT(ptr != 0); FC_ASSERT((U32)ptr != 0);
MemoryInstance* mem = ctx.memory; MemoryInstance* mem = ctx.memory;
if(!mem || ptr+sizeof(T) >= IR::numBytesPerPage*Runtime::getMemoryNumPages(mem)) if(!mem || (U32)ptr+sizeof(T) >= IR::numBytesPerPage*Runtime::getMemoryNumPages(mem))
Runtime::causeException(Exception::Cause::accessViolation); Runtime::causeException(Exception::Cause::accessViolation);
T &base = *(T*)(getMemoryBaseAddress(mem)+ptr); T &base = *(T*)(getMemoryBaseAddress(mem)+(U32)ptr);
if ( reinterpret_cast<uintptr_t>(&base) % alignof(T) != 0 ) { if ( reinterpret_cast<uintptr_t>(&base) % alignof(T) != 0 ) {
wlog( "misaligned reference" ); wlog( "misaligned reference" );
std::remove_const_t<T> copy; std::remove_const_t<T> copy;
......
...@@ -23,10 +23,10 @@ running_instance_context the_running_instance_context; ...@@ -23,10 +23,10 @@ running_instance_context the_running_instance_context;
class wavm_instantiated_module : public wasm_instantiated_module_interface { class wavm_instantiated_module : public wasm_instantiated_module_interface {
public: public:
wavm_instantiated_module(ModuleInstance* instance, Module* module, std::vector<uint8_t> initial_mem) : wavm_instantiated_module(ModuleInstance* instance, std::unique_ptr<Module> module, std::vector<uint8_t> initial_mem) :
_initial_memory(initial_mem), _initial_memory(initial_mem),
_instance(instance), _instance(instance),
_module(module) _module(std::move(module))
{} {}
void apply(apply_context& context) override { void apply(apply_context& context) override {
...@@ -37,11 +37,6 @@ class wavm_instantiated_module : public wasm_instantiated_module_interface { ...@@ -37,11 +37,6 @@ class wavm_instantiated_module : public wasm_instantiated_module_interface {
call("apply", args, context); call("apply", args, context);
} }
~wavm_instantiated_module() {
delete _module;
//_instance is deleted via WAVM's object garbage collection when wavm_rutime is deleted
}
private: private:
void call(const string &entry_point, const vector <Value> &args, apply_context &context) { void call(const string &entry_point, const vector <Value> &args, apply_context &context) {
try { try {
...@@ -79,10 +74,11 @@ class wavm_instantiated_module : public wasm_instantiated_module_interface { ...@@ -79,10 +74,11 @@ class wavm_instantiated_module : public wasm_instantiated_module_interface {
} }
std::vector<uint8_t> _initial_memory; std::vector<uint8_t> _initial_memory;
//naked pointers because ModuleInstance is opaque //naked pointer because ModuleInstance is opaque
ModuleInstance* _instance; //_instance is deleted via WAVM's object garbage collection when wavm_rutime is deleted
Module* _module; ModuleInstance* _instance;
std::unique_ptr<Module> _module;
}; };
...@@ -113,7 +109,7 @@ wavm_runtime::~wavm_runtime() { ...@@ -113,7 +109,7 @@ wavm_runtime::~wavm_runtime() {
} }
std::unique_ptr<wasm_instantiated_module_interface> wavm_runtime::instantiate_module(const char* code_bytes, size_t code_size, std::vector<uint8_t> initial_memory) { std::unique_ptr<wasm_instantiated_module_interface> wavm_runtime::instantiate_module(const char* code_bytes, size_t code_size, std::vector<uint8_t> initial_memory) {
Module* module = new Module(); std::unique_ptr<Module> module = std::make_unique<Module>();
try { try {
Serialization::MemoryInputStream stream((const U8*)code_bytes, code_size); Serialization::MemoryInputStream stream((const U8*)code_bytes, code_size);
WASM::serialize(stream, *module); WASM::serialize(stream, *module);
...@@ -126,7 +122,7 @@ std::unique_ptr<wasm_instantiated_module_interface> wavm_runtime::instantiate_mo ...@@ -126,7 +122,7 @@ std::unique_ptr<wasm_instantiated_module_interface> wavm_runtime::instantiate_mo
ModuleInstance *instance = instantiateModule(*module, std::move(link_result.resolvedImports)); ModuleInstance *instance = instantiateModule(*module, std::move(link_result.resolvedImports));
FC_ASSERT(instance != nullptr); FC_ASSERT(instance != nullptr);
return std::make_unique<wavm_instantiated_module>(instance, module, initial_memory); return std::make_unique<wavm_instantiated_module>(instance, std::move(module), initial_memory);
} }
}}}} }}}}
...@@ -239,7 +239,7 @@ namespace fc { ...@@ -239,7 +239,7 @@ namespace fc {
s.get(b); s.get(b);
v |= uint32_t(uint8_t(b) & 0x7f) << by; v |= uint32_t(uint8_t(b) & 0x7f) << by;
by += 7; by += 7;
} while( uint8_t(b) & 0x80 ); } while( uint8_t(b) & 0x80 && by < 32 );
vi.value = static_cast<uint32_t>(v); vi.value = static_cast<uint32_t>(v);
} }
......
...@@ -219,6 +219,7 @@ namespace fc ...@@ -219,6 +219,7 @@ namespace fc
} catch( ... ) { } catch( ... ) {
ss << "<- exception in to_string.\n"; ss << "<- exception in to_string.\n";
} }
return ss.str();
} }
/** /**
......
...@@ -102,7 +102,7 @@ namespace LLVMJIT ...@@ -102,7 +102,7 @@ namespace LLVMJIT
if(hasRegisteredEHFrames) if(hasRegisteredEHFrames)
{ {
hasRegisteredEHFrames = false; hasRegisteredEHFrames = false;
deregisterEHFrames(ehFramesAddr,ehFramesLoadAddr,ehFramesNumBytes); llvm::RTDyldMemoryManager::deregisterEHFrames(ehFramesAddr,ehFramesLoadAddr,ehFramesNumBytes);
} }
// Decommit the image pages, but leave them reserved to catch any references to them that might erroneously remain. // Decommit the image pages, but leave them reserved to catch any references to them that might erroneously remain.
......
...@@ -85,6 +85,7 @@ struct hello { ...@@ -85,6 +85,7 @@ struct hello {
public_key_type peer_id; public_key_type peer_id;
string network_version; string network_version;
string agent; string agent;
string protocol_version = "1.0.0";
string user; string user;
string password; string password;
chain_id_type chain_id; chain_id_type chain_id;
...@@ -92,7 +93,7 @@ struct hello { ...@@ -92,7 +93,7 @@ struct hello {
uint32_t last_irr_block_num = 0; uint32_t last_irr_block_num = 0;
vector<block_id_type> pending_block_ids; vector<block_id_type> pending_block_ids;
}; };
FC_REFLECT( hello, (peer_id)(network_version)(user)(password)(agent)(chain_id)(request_transactions)(last_irr_block_num)(pending_block_ids) ) FC_REFLECT( hello, (peer_id)(network_version)(user)(password)(agent)(protocol_version)(chain_id)(request_transactions)(last_irr_block_num)(pending_block_ids) )
/** /**
...@@ -100,11 +101,10 @@ FC_REFLECT( hello, (peer_id)(network_version)(user)(password)(agent)(chain_id)(r ...@@ -100,11 +101,10 @@ FC_REFLECT( hello, (peer_id)(network_version)(user)(password)(agent)(chain_id)(r
* and informs a peer not to send this message. * and informs a peer not to send this message.
*/ */
struct trx_notice { struct trx_notice {
sha256 signed_trx_id; ///< hash of trx + sigs vector<sha256> signed_trx_id; ///< hash of trx + sigs
fc::time_point_sec expiration; ///< expiration of trx
}; };
FC_REFLECT( trx_notice, (signed_trx_id)(expiration) ) FC_REFLECT( trx_notice, (signed_trx_id) )
/** /**
* This message is sent upon successfully adding a transaction to the fork database * This message is sent upon successfully adding a transaction to the fork database
...@@ -239,7 +239,7 @@ namespace eosio { ...@@ -239,7 +239,7 @@ namespace eosio {
int _session_num = 0; int _session_num = 0;
session_state _state = hello_state; session_state _state = hello_state;
tcp::resolver _resolver; tcp::resolver _resolver;
bnet_plugin_impl& _net_plugin; bnet_ptr _net_plugin;
boost::asio::io_service& _ios; boost::asio::io_service& _ios;
unique_ptr<ws::stream<tcp::socket>> _ws; unique_ptr<ws::stream<tcp::socket>> _ws;
boost::asio::strand< boost::asio::io_context::executor_type> _strand; boost::asio::strand< boost::asio::io_context::executor_type> _strand;
...@@ -265,9 +265,9 @@ namespace eosio { ...@@ -265,9 +265,9 @@ namespace eosio {
/** /**
* Creating session from server socket acceptance * Creating session from server socket acceptance
*/ */
explicit session( tcp::socket socket, bnet_plugin_impl& net_plug ) explicit session( tcp::socket socket, bnet_ptr net_plug )
:_resolver(socket.get_io_service()), :_resolver(socket.get_io_service()),
_net_plugin( net_plug ), _net_plugin( std::move(net_plug) ),
_ios(socket.get_io_service()), _ios(socket.get_io_service()),
_ws( new ws::stream<tcp::socket>(move(socket)) ), _ws( new ws::stream<tcp::socket>(move(socket)) ),
_strand(_ws->get_executor() ), _strand(_ws->get_executor() ),
...@@ -284,9 +284,9 @@ namespace eosio { ...@@ -284,9 +284,9 @@ namespace eosio {
/** /**
* Creating outgoing session * Creating outgoing session
*/ */
explicit session( boost::asio::io_context& ioc, bnet_plugin_impl& net_plug ) explicit session( boost::asio::io_context& ioc, bnet_ptr net_plug )
:_resolver(ioc), :_resolver(ioc),
_net_plugin( net_plug ), _net_plugin( std::move(net_plug) ),
_ios(ioc), _ios(ioc),
_ws( new ws::stream<tcp::socket>(ioc) ), _ws( new ws::stream<tcp::socket>(ioc) ),
_strand( _ws->get_executor() ), _strand( _ws->get_executor() ),
...@@ -614,6 +614,9 @@ namespace eosio { ...@@ -614,6 +614,9 @@ namespace eosio {
if( send_block_notice() ) return; if( send_block_notice() ) return;
if( send_pong() ) return; if( send_pong() ) return;
if( send_ping() ) return; if( send_ping() ) return;
/// we don't know where we are (waiting on accept block localhost)
if( _local_head_block_id == block_id_type() ) return ;
if( send_next_block() ) return; if( send_next_block() ) return;
if( send_next_trx() ) return; if( send_next_trx() ) return;
} }
...@@ -935,6 +938,7 @@ namespace eosio { ...@@ -935,6 +938,7 @@ namespace eosio {
void check_for_redundant_connection(); void check_for_redundant_connection();
void on( const signed_block_ptr& b ) { void on( const signed_block_ptr& b ) {
FC_ASSERT( b, "bad block" );
status( "received block " + std::to_string(b->block_num()) ); status( "received block " + std::to_string(b->block_num()) );
//ilog( "recv block ${n}", ("n", b->block_num()) ); //ilog( "recv block ${n}", ("n", b->block_num()) );
auto id = b->id(); auto id = b->id();
...@@ -975,6 +979,8 @@ namespace eosio { ...@@ -975,6 +979,8 @@ namespace eosio {
} }
void on( const packed_transaction_ptr& p ) { void on( const packed_transaction_ptr& p ) {
FC_ASSERT( p, "bad transaction" );
auto id = p->id(); auto id = p->id();
// ilog( "recv trx ${n}", ("n", id) ); // ilog( "recv trx ${n}", ("n", id) );
if( p->expiration() < fc::time_point::now() ) return; if( p->expiration() < fc::time_point::now() ) return;
...@@ -1010,11 +1016,11 @@ namespace eosio { ...@@ -1010,11 +1016,11 @@ namespace eosio {
private: private:
tcp::acceptor _acceptor; tcp::acceptor _acceptor;
tcp::socket _socket; tcp::socket _socket;
bnet_plugin_impl& _net_plugin; bnet_ptr _net_plugin;
public: public:
listener( boost::asio::io_context& ioc, tcp::endpoint endpoint, bnet_plugin_impl& np ) listener( boost::asio::io_context& ioc, tcp::endpoint endpoint, bnet_ptr np )
:_acceptor(ioc), _socket(ioc),_net_plugin(np) :_acceptor(ioc), _socket(ioc), _net_plugin(std::move(np))
{ {
boost::system::error_code ec; boost::system::error_code ec;
...@@ -1049,26 +1055,22 @@ namespace eosio { ...@@ -1049,26 +1055,22 @@ namespace eosio {
class bnet_plugin_impl : public std::enable_shared_from_this<bnet_plugin_impl> { class bnet_plugin_impl : public std::enable_shared_from_this<bnet_plugin_impl> {
public: public:
bnet_plugin_impl() { bnet_plugin_impl() = default;
_peer_pk = fc::crypto::private_key::generate();
_peer_id = _peer_pk.get_public_key();
}
string _bnet_endpoint_address = "0.0.0.0";
uint16_t _bnet_endpoint_port = 4321;
bool _request_trx = true;
public_key_type _peer_id;
private_key_type _peer_pk; /// one time random key to identify this process
const private_key_type _peer_pk = fc::crypto::private_key::generate(); /// one time random key to identify this process
public_key_type _peer_id = _peer_pk.get_public_key();
string _bnet_endpoint_address = "0.0.0.0";
uint16_t _bnet_endpoint_port = 4321;
bool _request_trx = true;
std::vector<std::string> _connect_to_peers; /// list of peers to connect to std::vector<std::string> _connect_to_peers; /// list of peers to connect to
std::vector<std::thread> _socket_threads; std::vector<std::thread> _socket_threads;
int32_t _num_threads = 1; int32_t _num_threads = 1;
std::unique_ptr<boost::asio::io_context> _ioc;
std::shared_ptr<listener> _listener;
std::shared_ptr<boost::asio::deadline_timer> _timer;
std::map<const session*, std::weak_ptr<session> > _sessions; std::unique_ptr<boost::asio::io_context> _ioc; // lifetime guarded by shared_ptr of bnet_plugin_impl
std::shared_ptr<listener> _listener;
std::shared_ptr<boost::asio::deadline_timer> _timer; // only access on app io_service
std::map<const session*, std::weak_ptr<session> > _sessions; // only access on app io_service
channels::irreversible_block::channel_type::handle _on_irb_handle; channels::irreversible_block::channel_type::handle _on_irb_handle;
channels::accepted_block::channel_type::handle _on_accepted_block_handle; channels::accepted_block::channel_type::handle _on_accepted_block_handle;
...@@ -1085,6 +1087,7 @@ namespace eosio { ...@@ -1085,6 +1087,7 @@ namespace eosio {
} }
void on_session_close( const session* s ) { void on_session_close( const session* s ) {
if( !app().get_io_service().get_executor().running_in_this_thread() ) { elog( "wrong strand"); }
auto itr = _sessions.find(s); auto itr = _sessions.find(s);
if( _sessions.end() != itr ) if( _sessions.end() != itr )
_sessions.erase(itr); _sessions.erase(itr);
...@@ -1092,14 +1095,16 @@ namespace eosio { ...@@ -1092,14 +1095,16 @@ namespace eosio {
template<typename Call> template<typename Call>
void for_each_session( Call callback ) { void for_each_session( Call callback ) {
for( const auto& item : _sessions ) { app().get_io_service().post([this, callback = callback] {
if( auto ses = item.second.lock() ) { for (const auto& item : _sessions) {
ses->_ios.post( boost::asio::bind_executor( if (auto ses = item.second.lock()) {
ses->_strand, ses->_ios.post(boost::asio::bind_executor(
[ses,cb=callback](){ cb(ses); } ses->_strand,
)); [ses, cb = callback]() { cb(ses); }
));
}
} }
} });
} }
void on_accepted_transaction( transaction_metadata_ptr trx ) { void on_accepted_transaction( transaction_metadata_ptr trx ) {
...@@ -1146,6 +1151,7 @@ namespace eosio { ...@@ -1146,6 +1151,7 @@ namespace eosio {
}; };
void on_reconnect_peers() { void on_reconnect_peers() {
if( !app().get_io_service().get_executor().running_in_this_thread() ) { elog( "wrong strand"); }
for( const auto& peer : _connect_to_peers ) { for( const auto& peer : _connect_to_peers ) {
bool found = false; bool found = false;
for( const auto& con : _sessions ) { for( const auto& con : _sessions ) {
...@@ -1158,7 +1164,7 @@ namespace eosio { ...@@ -1158,7 +1164,7 @@ namespace eosio {
if( !found ) { if( !found ) {
wlog( "attempt to connect to ${p}", ("p",peer) ); wlog( "attempt to connect to ${p}", ("p",peer) );
auto s = std::make_shared<session>( *_ioc, std::ref(*this) ); auto s = std::make_shared<session>( *_ioc, shared_from_this() );
s->_local_peer_id = _peer_id; s->_local_peer_id = _peer_id;
_sessions[s.get()] = s; _sessions[s.get()] = s;
s->run( peer ); s->run( peer );
...@@ -1185,9 +1191,9 @@ namespace eosio { ...@@ -1185,9 +1191,9 @@ namespace eosio {
if( ec ) { if( ec ) {
return; return;
} }
auto newsession = std::make_shared<session>( move( _socket ), std::ref(_net_plugin) ); auto newsession = std::make_shared<session>( move( _socket ), _net_plugin );
_net_plugin.async_add_session( newsession ); _net_plugin->async_add_session( newsession );
newsession->_local_peer_id = _net_plugin._peer_id; newsession->_local_peer_id = _net_plugin->_peer_id;
newsession->run(); newsession->run();
do_accept(); do_accept();
} }
...@@ -1274,7 +1280,7 @@ namespace eosio { ...@@ -1274,7 +1280,7 @@ namespace eosio {
my->_listener = std::make_shared<listener>( ioc, my->_listener = std::make_shared<listener>( ioc,
tcp::endpoint{ address, my->_bnet_endpoint_port }, tcp::endpoint{ address, my->_bnet_endpoint_port },
std::ref(*my) ); my );
my->_listener->run(); my->_listener->run();
my->_socket_threads.reserve( my->_num_threads ); my->_socket_threads.reserve( my->_num_threads );
...@@ -1283,7 +1289,7 @@ namespace eosio { ...@@ -1283,7 +1289,7 @@ namespace eosio {
} }
for( const auto& peer : my->_connect_to_peers ) { for( const auto& peer : my->_connect_to_peers ) {
auto s = std::make_shared<session>( ioc, std::ref(*my) ); auto s = std::make_shared<session>( ioc, my );
s->_local_peer_id = my->_peer_id; s->_local_peer_id = my->_peer_id;
my->_sessions[s.get()] = s; my->_sessions[s.get()] = s;
s->run( peer ); s->run( peer );
...@@ -1298,6 +1304,12 @@ namespace eosio { ...@@ -1298,6 +1304,12 @@ namespace eosio {
elog( "exception thrown on timer shutdown" ); elog( "exception thrown on timer shutdown" );
} }
/// shut down all threads and close all connections
my->for_each_session([](auto ses){
ses->do_goodbye( "shutting down" );
});
my->_listener.reset(); my->_listener.reset();
my->_ioc->stop(); my->_ioc->stop();
...@@ -1306,14 +1318,18 @@ namespace eosio { ...@@ -1306,14 +1318,18 @@ namespace eosio {
t.join(); t.join();
} }
wlog( "done joining threads" ); wlog( "done joining threads" );
my->_ioc.reset();
/// shut down all threads and close all connections my->for_each_session([](auto ses){
FC_ASSERT( false, "session ${ses} still active", ("ses", ses->_session_num) );
});
// lifetime of _ioc is guarded by shared_ptr of bnet_plugin_impl
} }
session::~session() { session::~session() {
wlog( "close session ${n}",("n",_session_num) ); wlog( "close session ${n}",("n",_session_num) );
std::weak_ptr<bnet_plugin_impl> netp = _net_plugin.shared_from_this(); std::weak_ptr<bnet_plugin_impl> netp = _net_plugin;
_app_ios.post( [netp,ses=this]{ _app_ios.post( [netp,ses=this]{
if( auto net = netp.lock() ) if( auto net = netp.lock() )
net->on_session_close(ses); net->on_session_close(ses);
...@@ -1327,7 +1343,7 @@ namespace eosio { ...@@ -1327,7 +1343,7 @@ namespace eosio {
hello_msg.peer_id = self->_local_peer_id; hello_msg.peer_id = self->_local_peer_id;
hello_msg.last_irr_block_num = lib; hello_msg.last_irr_block_num = lib;
hello_msg.pending_block_ids = ids; hello_msg.pending_block_ids = ids;
hello_msg.request_transactions = self->_net_plugin._request_trx; hello_msg.request_transactions = self->_net_plugin->_request_trx;
hello_msg.chain_id = app().get_plugin<chain_plugin>().get_chain_id(); // TODO: Quick fix in a rush. Maybe a better solution is needed. hello_msg.chain_id = app().get_plugin<chain_plugin>().get_chain_id(); // TODO: Quick fix in a rush. Maybe a better solution is needed.
self->_local_lib = lib; self->_local_lib = lib;
...@@ -1338,7 +1354,7 @@ namespace eosio { ...@@ -1338,7 +1354,7 @@ namespace eosio {
void session::check_for_redundant_connection() { void session::check_for_redundant_connection() {
app().get_io_service().post( [self=shared_from_this()]{ app().get_io_service().post( [self=shared_from_this()]{
self->_net_plugin.for_each_session( [self]( auto ses ){ self->_net_plugin->for_each_session( [self]( auto ses ){
if( ses != self && ses->_remote_peer_id == self->_remote_peer_id ) { if( ses != self && ses->_remote_peer_id == self->_remote_peer_id ) {
self->do_goodbye( "redundant connection" ); self->do_goodbye( "redundant connection" );
} }
......
...@@ -272,6 +272,14 @@ ...@@ -272,6 +272,14 @@
printf "\\n\\tExiting now.\\n" printf "\\n\\tExiting now.\\n"
exit 1 exit 1
fi fi
if [ -d "$BUILD_DIR" ]; then
if ! rm -rf "$BUILD_DIR"
then
printf "\\tUnable to remove directory %s. Please remove this directory and run this script %s again. 0\\n" "$BUILD_DIR" "${BASH_SOURCE[0]}"
printf "\\tExiting now.\\n\\n"
exit 1;
fi
fi
printf "\\tBoost successfully installed @ %s/opt/boost_1_67_0.\\n" "${HOME}" printf "\\tBoost successfully installed @ %s/opt/boost_1_67_0.\\n" "${HOME}"
else else
printf "\\tBoost 1.67.0 found at %s/opt/boost_1_67_0.\\n" "${HOME}" printf "\\tBoost 1.67.0 found at %s/opt/boost_1_67_0.\\n" "${HOME}"
......
...@@ -56,6 +56,7 @@ add_test(NAME distributed-transactions-test COMMAND tests/distributed-transactio ...@@ -56,6 +56,7 @@ add_test(NAME distributed-transactions-test COMMAND tests/distributed-transactio
add_test(NAME distributed-transactions-remote-test COMMAND tests/distributed-transactions-remote-test.py -v --dump-error-detail WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) add_test(NAME distributed-transactions-remote-test COMMAND tests/distributed-transactions-remote-test.py -v --dump-error-detail WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
# TODO removed on slim: add_test(NAME restart-scenarios-test_resync COMMAND tests/restart-scenarios-test.py -c resync -p4 -v --dump-error-details WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) # TODO removed on slim: add_test(NAME restart-scenarios-test_resync COMMAND tests/restart-scenarios-test.py -c resync -p4 -v --dump-error-details WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
# add_test(NAME restart-scenarios-test_replay COMMAND tests/restart-scenarios-test.py -c replay -p4 -v --dump-error-details WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) # add_test(NAME restart-scenarios-test_replay COMMAND tests/restart-scenarios-test.py -c replay -p4 -v --dump-error-details WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
add_test(NAME restart-scenarios-test_hard_replay COMMAND tests/restart-scenarios-test.py -c hardReplay -p4 -v --dump-error-details WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
# TODO: add_test(NAME consensus-validation-malicious-producers COMMAND tests/consensus-validation-malicious-producers.py -w 80 --dump-error-details WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) # TODO: add_test(NAME consensus-validation-malicious-producers COMMAND tests/consensus-validation-malicious-producers.py -w 80 --dump-error-details WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
if(ENABLE_COVERAGE_TESTING) if(ENABLE_COVERAGE_TESTING)
......
...@@ -4,7 +4,6 @@ import testUtils ...@@ -4,7 +4,6 @@ import testUtils
import argparse import argparse
import random import random
import signal
############################################################### ###############################################################
# Test for different nodes restart scenarios. # Test for different nodes restart scenarios.
...@@ -65,8 +64,8 @@ testSuccessful=False ...@@ -65,8 +64,8 @@ testSuccessful=False
random.seed(seed) # Use a fixed seed for repeatability. random.seed(seed) # Use a fixed seed for repeatability.
cluster=testUtils.Cluster() cluster=testUtils.Cluster(walletd=True)
walletMgr=testUtils.WalletMgr(False) walletMgr=testUtils.WalletMgr(True)
try: try:
cluster.setChainStrategy(chainSyncStrategyStr) cluster.setChainStrategy(chainSyncStrategyStr)
...@@ -87,6 +86,12 @@ try: ...@@ -87,6 +86,12 @@ try:
if not cluster.waitOnClusterBlockNumSync(3): if not cluster.waitOnClusterBlockNumSync(3):
errorExit("Cluster never stabilized") errorExit("Cluster never stabilized")
Print("Stand up EOS wallet keosd")
walletMgr.killall()
walletMgr.cleanup()
if walletMgr.launch() is False:
errorExit("Failed to stand up keosd.")
accountsCount=total_nodes accountsCount=total_nodes
walletName="MyWallet" walletName="MyWallet"
Print("Creating wallet %s if one doesn't already exist." % walletName) Print("Creating wallet %s if one doesn't already exist." % walletName)
...@@ -99,14 +104,15 @@ try: ...@@ -99,14 +104,15 @@ try:
errorExit("Wallet initialization failed.") errorExit("Wallet initialization failed.")
defproduceraAccount=cluster.defproduceraAccount defproduceraAccount=cluster.defproduceraAccount
eosioAccount=cluster.eosioAccount
Print("Importing keys for account %s into wallet %s." % (defproduceraAccount.name, wallet.name)) Print("Importing keys for account %s into wallet %s." % (defproduceraAccount.name, wallet.name))
if not walletMgr.importKey(defproduceraAccount, wallet): if not walletMgr.importKey(defproduceraAccount, wallet):
errorExit("Failed to import key for account %s" % (defproduceraAccount.name)) errorExit("Failed to import key for account %s" % (defproduceraAccount.name))
Print("Create accounts.") Print("Create accounts.")
#if not cluster.createAccounts(wallet): #if not cluster.createAccounts(defproduceraAccount):
if not cluster.createAccounts(defproduceraAccount): if not cluster.createAccounts(eosioAccount):
errorExit("Accounts creation failed.") errorExit("Accounts creation failed.")
Print("Wait on cluster sync.") Print("Wait on cluster sync.")
...@@ -115,9 +121,9 @@ try: ...@@ -115,9 +121,9 @@ try:
# TBD: Known issue (Issue 2043) that 'get currency0000 balance' doesn't return balance. # TBD: Known issue (Issue 2043) that 'get currency0000 balance' doesn't return balance.
# Uncomment when functional # Uncomment when functional
# Print("Spread funds and validate") Print("Spread funds and validate")
# if not cluster.spreadFundsAndValidate(10): if not cluster.spreadFundsAndValidate(10):
# errorExit("Failed to spread and validate funds.") errorExit("Failed to spread and validate funds.")
Print("Wait on cluster sync.") Print("Wait on cluster sync.")
if not cluster.waitOnClusterSync(): if not cluster.waitOnClusterSync():
...@@ -130,9 +136,9 @@ try: ...@@ -130,9 +136,9 @@ try:
# TBD: Known issue (Issue 2043) that 'get currency0000 balance' doesn't return balance. # TBD: Known issue (Issue 2043) that 'get currency0000 balance' doesn't return balance.
# Uncomment when functional # Uncomment when functional
# Print("Spread funds and validate") Print("Spread funds and validate")
# if not cluster.spreadFundsAndValidate(10): if not cluster.spreadFundsAndValidate(10):
# errorExit("Failed to spread and validate funds.") errorExit("Failed to spread and validate funds.")
Print("Wait on cluster sync.") Print("Wait on cluster sync.")
if not cluster.waitOnClusterSync(): if not cluster.waitOnClusterSync():
...@@ -150,9 +156,9 @@ try: ...@@ -150,9 +156,9 @@ try:
# TBD: Known issue (Issue 2043) that 'get currency0000 balance' doesn't return balance. # TBD: Known issue (Issue 2043) that 'get currency0000 balance' doesn't return balance.
# Uncomment when functional # Uncomment when functional
# Print("Spread funds and validate") Print("Spread funds and validate")
# if not cluster.spreadFundsAndValidate(10): if not cluster.spreadFundsAndValidate(10):
# errorExit("Failed to spread and validate funds.") errorExit("Failed to spread and validate funds.")
Print("Wait on cluster sync.") Print("Wait on cluster sync.")
if not cluster.waitOnClusterSync(): if not cluster.waitOnClusterSync():
...@@ -173,6 +179,5 @@ finally: ...@@ -173,6 +179,5 @@ finally:
Print("Cleanup cluster and wallet data.") Print("Cleanup cluster and wallet data.")
cluster.cleanup() cluster.cleanup()
walletMgr.cleanup() walletMgr.cleanup()
pass
exit(0) exit(0)
...@@ -16,6 +16,7 @@ import sys ...@@ -16,6 +16,7 @@ import sys
import random import random
import json import json
import shlex import shlex
from sys import stdout
from core_symbol import CORE_SYMBOL from core_symbol import CORE_SYMBOL
...@@ -39,7 +40,7 @@ class Utils: ...@@ -39,7 +40,7 @@ class Utils:
def Print(*args, **kwargs): def Print(*args, **kwargs):
stackDepth=len(inspect.stack())-2 stackDepth=len(inspect.stack())-2
s=' '*stackDepth s=' '*stackDepth
sys.stdout.write(s) stdout.write(s)
print(*args, **kwargs) print(*args, **kwargs)
SyncStrategy=namedtuple("ChainSyncStrategy", "name id arg") SyncStrategy=namedtuple("ChainSyncStrategy", "name id arg")
...@@ -47,6 +48,7 @@ class Utils: ...@@ -47,6 +48,7 @@ class Utils:
SyncNoneTag="none" SyncNoneTag="none"
SyncReplayTag="replay" SyncReplayTag="replay"
SyncResyncTag="resync" SyncResyncTag="resync"
SyncHardReplayTag="hardReplay"
SigKillTag="kill" SigKillTag="kill"
SigTermTag="term" SigTermTag="term"
...@@ -78,6 +80,9 @@ class Utils: ...@@ -78,6 +80,9 @@ class Utils:
chainSyncStrategy=Utils.SyncStrategy(Utils.SyncResyncTag, 2, "--delete-all-blocks") chainSyncStrategy=Utils.SyncStrategy(Utils.SyncResyncTag, 2, "--delete-all-blocks")
chainSyncStrategies[chainSyncStrategy.name]=chainSyncStrategy chainSyncStrategies[chainSyncStrategy.name]=chainSyncStrategy
chainSyncStrategy=Utils.SyncStrategy(Utils.SyncHardReplayTag, 3, "--hard-replay-blockchain")
chainSyncStrategies[chainSyncStrategy.name]=chainSyncStrategy
return chainSyncStrategies return chainSyncStrategies
@staticmethod @staticmethod
...@@ -98,14 +103,24 @@ class Utils: ...@@ -98,14 +103,24 @@ class Utils:
timeout=60 timeout=60
endTime=time.time()+timeout endTime=time.time()+timeout
while endTime > time.time(): needsNewLine=False
ret=lam() try:
if ret is not None: while endTime > time.time():
return ret ret=lam()
sleepTime=3 if ret is not None:
Utils.Print("cmd: sleep %d seconds, remaining time: %d seconds" % return ret
(sleepTime, endTime - time.time())) sleepTime=3
time.sleep(sleepTime) if Utils.Debug:
Utils.Print("cmd: sleep %d seconds, remaining time: %d seconds" %
(sleepTime, endTime - time.time()))
else:
stdout.write('.')
stdout.flush()
needsNewLine=True
time.sleep(sleepTime)
finally:
if needsNewLine:
Utils.Print()
return None return None
...@@ -170,16 +185,17 @@ class Node(object): ...@@ -170,16 +185,17 @@ class Node(object):
assert trans["processed"]["receipt"]["status"] == "executed", printTrans(trans) assert trans["processed"]["receipt"]["status"] == "executed", printTrans(trans)
@staticmethod @staticmethod
def runCmdReturnJson(cmd, trace=False): def runCmdReturnJson(cmd, trace=False, silentErrors=False):
cmdArr=shlex.split(cmd) cmdArr=shlex.split(cmd)
retStr=Utils.checkOutput(cmdArr) retStr=Utils.checkOutput(cmdArr)
jStr=Node.filterJsonObject(retStr) jStr=Node.filterJsonObject(retStr)
if trace: Utils.Print ("RAW > %s"% (retStr)) if trace: Utils.Print ("RAW > %s"% (retStr))
if trace: Utils.Print ("JSON> %s"% (jStr)) if trace: Utils.Print ("JSON> %s"% (jStr))
if not jStr: if not jStr:
msg="Expected JSON response" msg="Received empty JSON response"
Utils.Print ("ERROR: "+ msg) if not silentErrors:
Utils.Print ("RAW > %s"% retStr) Utils.Print ("ERROR: "+ msg)
Utils.Print ("RAW > %s"% retStr)
raise TypeError(msg) raise TypeError(msg)
try: try:
...@@ -446,7 +462,7 @@ class Node(object): ...@@ -446,7 +462,7 @@ class Node(object):
refBlockNum=int(refBlockNum)+1 refBlockNum=int(refBlockNum)+1
except (TypeError, ValueError, KeyError) as _: except (TypeError, ValueError, KeyError) as _:
Utils.Print("transaction parsing failed. Transaction: %s" % (trans)) Utils.Print("transaction parsing failed. Transaction: %s" % (trans))
raise return None
headBlockNum=self.getHeadBlockNum() headBlockNum=self.getHeadBlockNum()
assert(headBlockNum) assert(headBlockNum)
...@@ -1000,7 +1016,7 @@ class Node(object): ...@@ -1000,7 +1016,7 @@ class Node(object):
cmd="%s %s get info" % (Utils.EosClientPath, self.endpointArgs) cmd="%s %s get info" % (Utils.EosClientPath, self.endpointArgs)
if Utils.Debug: Utils.Print("cmd: %s" % (cmd)) if Utils.Debug: Utils.Print("cmd: %s" % (cmd))
try: try:
trans=Node.runCmdReturnJson(cmd) trans=Node.runCmdReturnJson(cmd, silentErrors=silentErrors)
return trans return trans
except subprocess.CalledProcessError as ex: except subprocess.CalledProcessError as ex:
if not silentErrors: if not silentErrors:
...@@ -1070,7 +1086,7 @@ class Node(object): ...@@ -1070,7 +1086,7 @@ class Node(object):
return False return False
if not Utils.waitForBool(myFunc): if not Utils.waitForBool(myFunc):
Utils.Print("ERROR: Failed to kill node (%s)." % (self.cmd), ex) Utils.Print("ERROR: Failed to validate node shutdown.")
return False return False
# mark node as killed # mark node as killed
...@@ -1079,30 +1095,40 @@ class Node(object): ...@@ -1079,30 +1095,40 @@ class Node(object):
return True return True
# TBD: make nodeId an internal property # TBD: make nodeId an internal property
def relaunch(self, nodeId, chainArg): def relaunch(self, nodeId, chainArg, timeout=Utils.systemWaitTimeout):
assert(self.pid is None)
assert(self.killed)
if Utils.Debug: Utils.Print("Launching node process, Id: %d" % (nodeId))
dataDir="var/lib/node_%02d" % (nodeId)
dt = datetime.datetime.now()
dateStr="%d_%02d_%02d_%02d_%02d_%02d" % (
dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second)
stdoutFile="%s/stdout.%s.txt" % (dataDir, dateStr)
stderrFile="%s/stderr.%s.txt" % (dataDir, dateStr)
with open(stdoutFile, 'w') as sout, open(stderrFile, 'w') as serr:
cmd=self.cmd + ("" if chainArg is None else (" " + chainArg))
Utils.Print("cmd: %s" % (cmd))
popen=subprocess.Popen(cmd.split(), stdout=sout, stderr=serr)
self.pid=popen.pid
running=True def isNodeAlive():
try: """wait for node to be responsive."""
os.kill(self.pid, 0) #check if process with pid is running try:
except OSError as _: return True if self.checkPulse() else False
running=False except (TypeError) as _:
pass
return False
if running: isAlive=Utils.waitForBool(isNodeAlive, timeout)
Utils.Print("WARNING: A process with pid (%d) is already running." % (self.pid)) if isAlive:
Utils.Print("Node relaunch was successfull.")
else: else:
if Utils.Debug: Utils.Print("Launching node process, Id: %d" % (nodeId)) Utils.Print("ERROR: Node relaunch Failed.")
dataDir="var/lib/node_%02d" % (nodeId) self.pid=None
dt = datetime.datetime.now() return False
dateStr="%d_%02d_%02d_%02d_%02d_%02d" % (
dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second)
stdoutFile="%s/stdout.%s.txt" % (dataDir, dateStr)
stderrFile="%s/stderr.%s.txt" % (dataDir, dateStr)
with open(stdoutFile, 'w') as sout, open(stderrFile, 'w') as serr:
cmd=self.cmd + ("" if chainArg is None else (" " + chainArg))
Utils.Print("cmd: %s" % (cmd))
popen=subprocess.Popen(cmd.split(), stdout=sout, stderr=serr)
self.pid=popen.pid
self.killed=False self.killed=False
return True return True
...@@ -1726,7 +1752,7 @@ class Cluster(object): ...@@ -1726,7 +1752,7 @@ class Cluster(object):
Utils.Print("ERROR: Failed to spread funds across nodes.") Utils.Print("ERROR: Failed to spread funds across nodes.")
return False return False
Utils.Print("Funds spread across all accounts. Noew validate funds") Utils.Print("Funds spread across all accounts. Now validate funds")
if False == self.validateSpreadFunds(initialBalances, transferAmount, self.defproduceraAccount, self.accounts): if False == self.validateSpreadFunds(initialBalances, transferAmount, self.defproduceraAccount, self.accounts):
Utils.Print("ERROR: Failed to validate funds transfer across nodes.") Utils.Print("ERROR: Failed to validate funds transfer across nodes.")
...@@ -2157,7 +2183,7 @@ class Cluster(object): ...@@ -2157,7 +2183,7 @@ class Cluster(object):
for i in range(0, len(self.nodes)): for i in range(0, len(self.nodes)):
node=self.nodes[i] node=self.nodes[i]
if not node.relaunch(i, chainArg): if node.killed and not node.relaunch(i, chainArg):
return False return False
return True return True
......
...@@ -28,7 +28,6 @@ systemAccounts = [ ...@@ -28,7 +28,6 @@ systemAccounts = [
'eosio.vpay', 'eosio.vpay',
] ]
def jsonArg(a): def jsonArg(a):
return " '" + json.dumps(a) + "' " return " '" + json.dumps(a) + "' "
...@@ -105,7 +104,7 @@ def startNode(nodeIndex, account): ...@@ -105,7 +104,7 @@ def startNode(nodeIndex, account):
) )
cmd = ( cmd = (
args.nodeos + args.nodeos +
' --max-transaction-time 200' ' --max-irreversible-block-age 9999999'
' --contracts-console' ' --contracts-console'
' --genesis-json ' + os.path.abspath(args.genesis) + ' --genesis-json ' + os.path.abspath(args.genesis) +
' --blocks-dir ' + os.path.abspath(dir) + '/blocks' ' --blocks-dir ' + os.path.abspath(dir) + '/blocks'
...@@ -115,6 +114,7 @@ def startNode(nodeIndex, account): ...@@ -115,6 +114,7 @@ def startNode(nodeIndex, account):
' --http-server-address 127.0.0.1:' + str(8000 + nodeIndex) + ' --http-server-address 127.0.0.1:' + str(8000 + nodeIndex) +
' --p2p-listen-endpoint 127.0.0.1:' + str(9000 + nodeIndex) + ' --p2p-listen-endpoint 127.0.0.1:' + str(9000 + nodeIndex) +
' --max-clients ' + str(maxClients) + ' --max-clients ' + str(maxClients) +
' --p2p-max-nodes-per-host ' + str(maxClients) +
' --enable-stale-production' ' --enable-stale-production'
' --producer-name ' + account['name'] + ' --producer-name ' + account['name'] +
' --private-key \'["' + account['pub'] + '","' + account['pvt'] + '"]\'' ' --private-key \'["' + account['pub'] + '","' + account['pvt'] + '"]\''
...@@ -137,25 +137,40 @@ def createSystemAccounts(): ...@@ -137,25 +137,40 @@ def createSystemAccounts():
def intToCurrency(i): def intToCurrency(i):
return '%d.%04d %s' % (i // 10000, i % 10000, args.symbol) return '%d.%04d %s' % (i // 10000, i % 10000, args.symbol)
def fillStake(b, e): def allocateFunds(b, e):
dist = numpy.random.pareto(1.161, e - b).tolist() # 1.161 = 80/20 rule dist = numpy.random.pareto(1.161, e - b).tolist() # 1.161 = 80/20 rule
dist.sort() dist.sort()
dist.reverse() dist.reverse()
factor = 1_000_000_000 / sum(dist) factor = 1_000_000_000 / sum(dist)
total = 0 total = 0
for i in range(b, e): for i in range(b, e):
stake = round(factor * dist[i - b] * 10000 / 2) funds = round(factor * dist[i - b] * 10000)
if i >= firstProducer and i < firstProducer + numProducers: if i >= firstProducer and i < firstProducer + numProducers:
stake = max(stake, round(args.min_producer_stake * 10000)) funds = max(funds, round(args.min_producer_funds * 10000))
total += stake * 2 total += funds
accounts[i]['stake'] = stake accounts[i]['funds'] = funds
return total + round(args.extra_issue * 10000) return total
def createStakedAccounts(b, e): def createStakedAccounts(b, e):
ramFunds = round(args.ram_funds * 10000)
configuredMinStake = round(args.min_stake * 10000)
maxUnstaked = round(args.max_unstaked * 10000)
for i in range(b, e): for i in range(b, e):
a = accounts[i] a = accounts[i]
stake = intToCurrency(a['stake']) funds = a['funds']
run(args.cleos + 'system newaccount eosio --transfer ' + a['name'] + ' ' + a['pub'] + ' --stake-net "' + stake + '" --stake-cpu "' + stake + '"') if funds < ramFunds:
print('skipping %s: not enough funds to cover ram' % a['name'])
continue
minStake = min(funds - ramFunds, configuredMinStake)
unstaked = min(funds - ramFunds - minStake, maxUnstaked)
stake = funds - ramFunds - unstaked
stakeNet = round(stake / 2)
stakeCpu = stake - stakeNet
print('%s: total funds=%s, ram=%s, net=%s, cpu=%s, unstaked=%s' % (a['name'], intToCurrency(a['funds']), intToCurrency(ramFunds), intToCurrency(stakeNet), intToCurrency(stakeCpu), intToCurrency(unstaked)))
assert(funds == ramFunds + stakeNet + stakeCpu + unstaked)
run(args.cleos + 'system newaccount --transfer eosio %s %s --stake-net "%s" --stake-cpu "%s" --buy-ram-EOS "%s" ' %
(a['name'], a['pub'], intToCurrency(stakeNet), intToCurrency(stakeCpu), intToCurrency(ramFunds)))
run(args.cleos + 'transfer eosio %s "%s"' % (a['name'], intToCurrency(unstaked)))
def regProducers(b, e): def regProducers(b, e):
for i in range(b, e): for i in range(b, e):
...@@ -216,11 +231,6 @@ def resign(account, controller): ...@@ -216,11 +231,6 @@ def resign(account, controller):
sleep(1) sleep(1)
run(args.cleos + 'get account ' + account) run(args.cleos + 'get account ' + account)
def sendUnstakedFunds(b, e):
for i in range(b, e):
a = accounts[i]
run(args.cleos + 'transfer eosio ' + a['name'] + ' "10.0000 ' + args.symbol + '"')
def randomTransfer(b, e): def randomTransfer(b, e):
for j in range(20): for j in range(20):
src = accounts[random.randint(b, e - 1)]['name'] src = accounts[random.randint(b, e - 1)]['name']
...@@ -258,7 +268,7 @@ def msigReplaceSystem(): ...@@ -258,7 +268,7 @@ def msigReplaceSystem():
def produceNewAccounts(): def produceNewAccounts():
with open('newusers', 'w') as f: with open('newusers', 'w') as f:
for i in range(0, 3000): for i in range(3000, 30000):
x = getOutput(args.cleos + 'create key') x = getOutput(args.cleos + 'create key')
r = re.match('Private key: *([^ \n]*)\nPublic key: *([^ \n]*)', x, re.DOTALL | re.MULTILINE) r = re.match('Private key: *([^ \n]*)\nPublic key: *([^ \n]*)', x, re.DOTALL | re.MULTILINE)
name = 'user' name = 'user'
...@@ -267,7 +277,6 @@ def produceNewAccounts(): ...@@ -267,7 +277,6 @@ def produceNewAccounts():
print(i, name) print(i, name)
f.write(' {"name":"%s", "pvt":"%s", "pub":"%s"},\n' % (name, r[1], r[2])) f.write(' {"name":"%s", "pvt":"%s", "pub":"%s"},\n' % (name, r[1], r[2]))
def stepKillAll(): def stepKillAll():
run('killall keosd nodeos || true') run('killall keosd nodeos || true')
sleep(1.5) sleep(1.5)
...@@ -282,7 +291,7 @@ def stepInstallSystemContracts(): ...@@ -282,7 +291,7 @@ def stepInstallSystemContracts():
run(args.cleos + 'set contract eosio.msig ' + args.contracts_dir + 'eosio.msig/') run(args.cleos + 'set contract eosio.msig ' + args.contracts_dir + 'eosio.msig/')
def stepCreateTokens(): def stepCreateTokens():
run(args.cleos + 'push action eosio.token create \'["eosio", "10000000000.0000 %s"]\' -p eosio.token' % (args.symbol)) run(args.cleos + 'push action eosio.token create \'["eosio", "10000000000.0000 %s"]\' -p eosio.token' % (args.symbol))
totalAllocation = fillStake(0, len(accounts)) totalAllocation = allocateFunds(0, len(accounts))
run(args.cleos + 'push action eosio.token issue \'["eosio", "%s", "memo"]\' -p eosio' % intToCurrency(totalAllocation)) run(args.cleos + 'push action eosio.token issue \'["eosio", "%s", "memo"]\' -p eosio' % intToCurrency(totalAllocation))
sleep(1) sleep(1)
def stepSetSystemContract(): def stepSetSystemContract():
...@@ -309,9 +318,6 @@ def stepResign(): ...@@ -309,9 +318,6 @@ def stepResign():
resign('eosio', 'eosio.prods') resign('eosio', 'eosio.prods')
for a in systemAccounts: for a in systemAccounts:
resign(a, 'eosio') resign(a, 'eosio')
def stepIssueUnstaked():
run(args.cleos + 'push action eosio.token issue \'["eosio", "%d.0000 %s", "memo"]\' -p eosio' % ((len(accounts)) * 10, args.symbol))
sendUnstakedFunds(0, args.num_senders)
def stepTransfer(): def stepTransfer():
while True: while True:
randomTransfer(0, args.num_senders) randomTransfer(0, args.num_senders)
...@@ -338,12 +344,10 @@ commands = [ ...@@ -338,12 +344,10 @@ commands = [
('x', 'proxy', stepProxyVotes, True, "Proxy votes"), ('x', 'proxy', stepProxyVotes, True, "Proxy votes"),
('q', 'resign', stepResign, True, "Resign eosio"), ('q', 'resign', stepResign, True, "Resign eosio"),
('m', 'msg-replace', msigReplaceSystem, False, "Replace system contract using msig"), ('m', 'msg-replace', msigReplaceSystem, False, "Replace system contract using msig"),
('u', 'issue', stepIssueUnstaked, True, "Issue unstaked tokens"),
('X', 'xfer', stepTransfer, False, "Random transfer tokens (infinite loop)"), ('X', 'xfer', stepTransfer, False, "Random transfer tokens (infinite loop)"),
('l', 'log', stepLog, True, "Show tail of node's log"), ('l', 'log', stepLog, True, "Show tail of node's log"),
] ]
parser.add_argument('--public-key', metavar='', help="EOSIO Public Key", default='EOS8Znrtgwt8TfpmbVpTKvA2oB8Nqey625CLN8bCN3TEbgx86Dsvr', dest="public_key") parser.add_argument('--public-key', metavar='', help="EOSIO Public Key", default='EOS8Znrtgwt8TfpmbVpTKvA2oB8Nqey625CLN8bCN3TEbgx86Dsvr', dest="public_key")
parser.add_argument('--private-Key', metavar='', help="EOSIO Private Key", default='5K463ynhZoCDDa4RDcr63cUwWLTnKqmdcoTKTHBjqoKfv4u5V7p', dest="private_key") parser.add_argument('--private-Key', metavar='', help="EOSIO Private Key", default='5K463ynhZoCDDa4RDcr63cUwWLTnKqmdcoTKTHBjqoKfv4u5V7p', dest="private_key")
parser.add_argument('--cleos', metavar='', help="Cleos command", default='../../build/programs/cleos/cleos --wallet-url http://localhost:6666 ') parser.add_argument('--cleos', metavar='', help="Cleos command", default='../../build/programs/cleos/cleos --wallet-url http://localhost:6666 ')
...@@ -355,11 +359,13 @@ parser.add_argument('--genesis', metavar='', help="Path to genesis.json", defaul ...@@ -355,11 +359,13 @@ parser.add_argument('--genesis', metavar='', help="Path to genesis.json", defaul
parser.add_argument('--wallet-dir', metavar='', help="Path to wallet directory", default='./wallet/') parser.add_argument('--wallet-dir', metavar='', help="Path to wallet directory", default='./wallet/')
parser.add_argument('--log-path', metavar='', help="Path to log file", default='./output.log') parser.add_argument('--log-path', metavar='', help="Path to log file", default='./output.log')
parser.add_argument('--symbol', metavar='', help="The eosio.system symbol", default='SYS') parser.add_argument('--symbol', metavar='', help="The eosio.system symbol", default='SYS')
parser.add_argument('--user-limit', metavar='', help="Max number of users. (0 = no limit)", type=int, default=0) parser.add_argument('--user-limit', metavar='', help="Max number of users. (0 = no limit)", type=int, default=3000)
parser.add_argument('--max-user-keys', metavar='', help="Maximum user keys to import into wallet", type=int, default=10) parser.add_argument('--max-user-keys', metavar='', help="Maximum user keys to import into wallet", type=int, default=10)
parser.add_argument('--extra-issue', metavar='', help="Extra amount to issue to cover buying ram", type=float, default=10.0000) parser.add_argument('--ram-funds', metavar='', help="How much funds for each user to spend on ram", type=float, default=0.1)
parser.add_argument('--min-stake', metavar='', help="Minimum stake before allocating unstaked funds", type=float, default=0.9)
parser.add_argument('--max-unstaked', metavar='', help="Maximum unstaked funds", type=float, default=10)
parser.add_argument('--producer-limit', metavar='', help="Maximum number of producers. (0 = no limit)", type=int, default=0) parser.add_argument('--producer-limit', metavar='', help="Maximum number of producers. (0 = no limit)", type=int, default=0)
parser.add_argument('--min-producer-stake', metavar='', help="Minimum producer CPU and BW stake", type=float, default=200.0000) parser.add_argument('--min-producer-funds', metavar='', help="Minimum producer funds", type=float, default=1000.0000)
parser.add_argument('--num-producers-vote', metavar='', help="Number of producers for which each user votes", type=int, default=20) parser.add_argument('--num-producers-vote', metavar='', help="Number of producers for which each user votes", type=int, default=20)
parser.add_argument('--num-voters', metavar='', help="Number of voters", type=int, default=10) parser.add_argument('--num-voters', metavar='', help="Number of voters", type=int, default=10)
parser.add_argument('--num-senders', metavar='', help="Number of users to transfer funds randomly", type=int, default=10) parser.add_argument('--num-senders', metavar='', help="Number of users to transfer funds randomly", type=int, default=10)
......
此差异已折叠。
...@@ -1573,6 +1573,7 @@ INCBIN(fuzz12, "fuzz12.wasm"); ...@@ -1573,6 +1573,7 @@ INCBIN(fuzz12, "fuzz12.wasm");
INCBIN(fuzz13, "fuzz13.wasm"); INCBIN(fuzz13, "fuzz13.wasm");
INCBIN(fuzz14, "fuzz14.wasm"); INCBIN(fuzz14, "fuzz14.wasm");
INCBIN(fuzz15, "fuzz15.wasm"); INCBIN(fuzz15, "fuzz15.wasm");
//INCBIN(fuzz13, "fuzz13.wasm");
BOOST_FIXTURE_TEST_CASE( fuzz, TESTER ) try { BOOST_FIXTURE_TEST_CASE( fuzz, TESTER ) try {
produce_blocks(2); produce_blocks(2);
...@@ -1640,6 +1641,17 @@ BOOST_FIXTURE_TEST_CASE( fuzz, TESTER ) try { ...@@ -1640,6 +1641,17 @@ BOOST_FIXTURE_TEST_CASE( fuzz, TESTER ) try {
vector<uint8_t> wasm(gfuzz15Data, gfuzz15Data + gfuzz15Size); vector<uint8_t> wasm(gfuzz15Data, gfuzz15Data + gfuzz15Size);
BOOST_CHECK_THROW(set_code(N(fuzzy), wasm), fc::exception); BOOST_CHECK_THROW(set_code(N(fuzzy), wasm), fc::exception);
} }
/* TODO: update wasm to have apply(...) then call, claim is that this
* takes 1.6 seconds under wavm...
{
auto start = fc::time_point::now();
vector<uint8_t> wasm(gfuzz13Data, gfuzz13Data + gfuzz13Size);
set_code(N(fuzzy), wasm);
BOOST_CHECK_THROW(set_code(N(fuzzy), wasm), fc::exception);
auto end = fc::time_point::now();
edump((end-start));
}
*/
produce_blocks(1); produce_blocks(1);
} FC_LOG_AND_RETHROW() } FC_LOG_AND_RETHROW()
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册