diff --git a/LICENSE.txt b/LICENSE.txt
index 25f6394107b..55e80764e3a 100644
--- a/LICENSE.txt
+++ b/LICENSE.txt
@@ -1,6 +1,4 @@
-Copyright (c) 2017, Respective Authors all rights reserved.
-
-After June 1, 2018 this software is available under the following terms:
+Copyright (c) 2018, Respective Authors all rights reserved.
The MIT License
diff --git a/contracts/eosio.system/eosio.system-bidname-rc.md b/contracts/eosio.system/eosio.system-bidname-rc.md
deleted file mode 100644
index 87b11b131b8..00000000000
--- a/contracts/eosio.system/eosio.system-bidname-rc.md
+++ /dev/null
@@ -1,19 +0,0 @@
-# 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 }}`
`{{ newnameVar }}`
`{{ bidVar }}` | `{{ account_name }}`
`{{ account_name }}`
`{{ 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.
diff --git a/contracts/eosio.system/eosio.system-buyram-rc.md b/contracts/eosio.system/eosio.system-buyram-rc.md
deleted file mode 100644
index d6ff406d865..00000000000
--- a/contracts/eosio.system/eosio.system-buyram-rc.md
+++ /dev/null
@@ -1,19 +0,0 @@
-# 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 }}`
`{{ receiverVar }}`
`{{ quantVar }}` | `{{ account_name }}`
`{{ account_name }}`
`{{ 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.
diff --git a/contracts/eosio.system/eosio.system-buyrambytes-rc.md b/contracts/eosio.system/eosio.system-buyrambytes-rc.md
deleted file mode 100644
index 63a60e83f58..00000000000
--- a/contracts/eosio.system/eosio.system-buyrambytes-rc.md
+++ /dev/null
@@ -1,16 +0,0 @@
-# Action - `{{ buyrambytes }}`
-
-### Description
-
-This action will attempt to reserve about {{bytes}} bytes of RAM on behalf of {{receiver}}.
-
-{{buyer}} authorizes this conrtact to transfer sufficient SYS tokens to buy the RAM based upon the current price as determined by the market maker algorithm.
-
-{{buyer}} accepts that a 0.5% fee will be charged on the SYS spent and that the actual RAM received may be slightly less than requested due to the approximations necessary to enable this service.
-{{buyer}} accepts that a 0.5% fee will be charged if and when they sell the RAM received.
-{{buyer}} accepts that rounding errors resulting from limits of computational precision may result in less RAM being allocated.
-{{buyer}} acknowledges that the supply of RAM may be increased at any time up to the limits of off-the-shelf computer equipment and that this may result in RAM selling for less than purchase price.
-{{buyer}} acknowledges that the price of RAM may increase or decrease over time according to supply and demand.
-{{buyer}} acknowledges that RAM is non-transferrable.
-{{buyer}} acknowledges RAM currently in use by their account cannot be sold until it is freed and that freeing RAM may be subject to terms of other contracts.
-
diff --git a/contracts/eosio.system/eosio.system-canceldelay-rc.md b/contracts/eosio.system/eosio.system-canceldelay-rc.md
deleted file mode 100644
index db68ca85066..00000000000
--- a/contracts/eosio.system/eosio.system-canceldelay-rc.md
+++ /dev/null
@@ -1,19 +0,0 @@
-# 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 }}`
`{{ trx_idVar }}` | `{{ permission_level }}`
`{{ 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.
diff --git a/contracts/eosio.system/eosio.system-claimrewards-rc.md b/contracts/eosio.system/eosio.system-claimrewards-rc.md
deleted file mode 100644
index 8470bcb2c18..00000000000
--- a/contracts/eosio.system/eosio.system-claimrewards-rc.md
+++ /dev/null
@@ -1,19 +0,0 @@
-# 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.
diff --git a/contracts/eosio.system/eosio.system-clause-constitution-rc.md b/contracts/eosio.system/eosio.system-clause-constitution-rc.md
deleted file mode 100644
index 0f4057b026a..00000000000
--- a/contracts/eosio.system/eosio.system-clause-constitution-rc.md
+++ /dev/null
@@ -1,58 +0,0 @@
-This Constitution is a multi-party contract entered into by the Members by virtue of their use of this blockchain.
-
-# Article I - No Initiation of Violence
-Members shall not initiate violence or the threat of violence against another Member.
-
-# Article II - No Perjury
-Members shall be liable for losses caused by false or misleading attestations and shall forfeit any profit gained thereby.
-
-# Article III - Rights
-The Members grant the right of contract and of private property to each other, therefore no property shall change hands except with the consent of the owner, by a valid Arbitrator’s order, or via community referendum. This Constitution creates no positive rights for or between any Members.
-
-# Article IV - No Vote Buying
-No Member shall offer nor accept anything of value in exchange for a vote of any type, nor shall any Member unduly influence the vote of another.
-
-# Article V - No Fiduciary
-No Member nor SYS token holder shall have fiduciary responsibility to support the value of the SYS token. The Members do not authorize anyone to hold assets, borrow, nor contract on behalf of SYS token holders collectively. This blockchain has no owners, managers or fiduciaries; therefore, no Member shall have beneficial interest in more than 10% of the SYS token supply.
-
-# Article VI - Restitution
-Each Member agrees that penalties for breach of contract may include, but are not limited to, fines, loss of account, and other restitution.
-
-# Article VII - Open Source
-Each Member who makes available a smart contract on this blockchain shall be a Developer. Each Developer shall offer their smart contracts via a free and open source license, and each smart contract shall be documented with a Ricardian Contract stating the intent of all parties and naming the Arbitration Forum that will resolve disputes arising from that contract.
-
-# Article VIII - Language
-Multi-lingual contracts must specify one prevailing language in case of dispute and the author of any translation shall be liable for losses due to their false, misleading, or ambiguous attested translations.
-
-# Article IX - Dispute Resolution
-All disputes arising out of or in connection with this Constitution shall be finally settled under the Rules of Arbitration of the International Chamber of Commerce by one or more arbitrators appointed in accordance with the said Rules.
-
-# Article X - Choice of Law
-Choice of law for disputes shall be, in order of precedence, this Constitution and the Maxims of Equity.
-
-# Article XI - Amending
-This Constitution and its subordinate documents shall not be amended except by a vote of the token holders with no less than 15% vote participation among tokens and no fewer than 10% more Yes than No votes, sustained for 30 continuous days within a 120 day period.
-
-# Article XII - Publishing
-Members may only publish information to the Blockchain that is within their right to publish. Furthermore, Members voluntarily consent for all Members to permanently and irrevocably retain a copy, analyze, and distribute all broadcast transactions and derivative information.
-
-# Article XIII - Informed Consent
-All service providers who produce tools to facilitate the construction and signing of transactions on behalf of other Members shall present to said other Members the full Ricardian contract terms of this Constitution and other referenced contracts. Service providers shall be liable for losses resulting from failure to disclose the full Ricardian contract terms to users.
-
-# Article XIV - Severability
-If any part of this Constitution is declared unenforceable or invalid, the remainder will continue to be valid and enforceable.
-
-# Article XV - Termination of Agreement
-A Member is automatically released from all revocable obligations under this Constitution 3 years after the last transaction signed by that Member is incorporated into the blockchain. After 3 years of inactivity an account may be put up for auction and the proceeds distributed to all Members according to the system contract provisions then in effect for such redistribution.
-
-# Article XVI - Developer Liability
-Members agree to hold software developers harmless for unintentional mistakes made in the expression of contractual intent, whether or not said mistakes were due to actual or perceived negligence.
-
-# Article XVII - Consideration
-All rights and obligations under this Constitution are mutual and reciprocal and of equally significant value and cost to all parties.
-
-# Article XVIII - Acceptance
-A contract is deemed accepted when a member signs a transaction which incorporates a TAPOS proof of a block whose implied state incorporates an ABI of said contract and said transaction is incorporated into the blockchain.
-
-# Article XIX - Counterparts
-This Constitution may be executed in any number of counterparts, each of which when executed and delivered shall constitute a duplicate original, but all counterparts together shall constitute a single agreement.
diff --git a/contracts/eosio.system/eosio.system-delegatebw-rc.md b/contracts/eosio.system/eosio.system-delegatebw-rc.md
deleted file mode 100644
index 904d43db957..00000000000
--- a/contracts/eosio.system/eosio.system-delegatebw-rc.md
+++ /dev/null
@@ -1,24 +0,0 @@
-# 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.
diff --git a/contracts/eosio.system/eosio.system-deleteauth-rc.md b/contracts/eosio.system/eosio.system-deleteauth-rc.md
deleted file mode 100644
index fc1db915e9b..00000000000
--- a/contracts/eosio.system/eosio.system-deleteauth-rc.md
+++ /dev/null
@@ -1,19 +0,0 @@
-# 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 }}`
`{{ permissionVar }}` | `{{ account_name }}`
`{{ 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.
diff --git a/contracts/eosio.system/eosio.system-linkauth-rc.md b/contracts/eosio.system/eosio.system-linkauth-rc.md
deleted file mode 100644
index 9ba584cf60b..00000000000
--- a/contracts/eosio.system/eosio.system-linkauth-rc.md
+++ /dev/null
@@ -1,19 +0,0 @@
-# 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 }}`
`{{ codeVar }}`
`{{ typeVar }}`
`{{ requirementVar }}` | `{{ account_name }}`
`{{ account_name }}`
`{{ action_name }}`
`{{ 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.
diff --git a/contracts/eosio.system/eosio.system-newaccount-rc.md b/contracts/eosio.system/eosio.system-newaccount-rc.md
deleted file mode 100644
index 1392f41a727..00000000000
--- a/contracts/eosio.system/eosio.system-newaccount-rc.md
+++ /dev/null
@@ -1,19 +0,0 @@
-# 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 }}`
`{{ nameVar }}`
`{{ ownerVar }}`
`{{ activeVar }}` | `{{ account_name }}`
`{{ account_name }}`
`{{ authority }}`
`{{ 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.
diff --git a/contracts/eosio.system/eosio.system-onerror-rc.md b/contracts/eosio.system/eosio.system-onerror-rc.md
deleted file mode 100644
index 7b8755ec676..00000000000
--- a/contracts/eosio.system/eosio.system-onerror-rc.md
+++ /dev/null
@@ -1,19 +0,0 @@
-# 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 }}`
`{{ sent_trxVar }}` | `{{ uint128 }}`
`{{ 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.
diff --git a/contracts/eosio.system/eosio.system-rc.md b/contracts/eosio.system/eosio.system-rc.md
deleted file mode 100644
index 8919cbaec0c..00000000000
--- a/contracts/eosio.system/eosio.system-rc.md
+++ /dev/null
@@ -1,41 +0,0 @@
-# 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 }}`
`{{ name }}`
`{{ owner }}`
`{{ active }}` | `{{ account_name }}`
`{{ account_name }}`
`{{ authority }}`
`{{ authority }}` |
-| `{{ setcode }}` | `{{ account }}`
`{{ vmtype }}`
`{{ vmversion }}`
`{{ code }}` | `{{ account_name }}`
`{{ uint8 }}`
`{{ uint8 }}`
`{{ bytes }}` |
-| `{{ setabi }}` | `{{ account }}`
`{{ abi }}` | `{{ account_name }}`
`{{ bytes }}` |
-| `{{ updateauth }}` | `{{ account }}`
`{{ permission }}`
`{{ parent }}`
`{{ auth }}` | `{{ account_name }}`
`{{ permission_name }}`
`{{ permission_name }}`
`{{ authority }}` |
-| `{{ deleteauth }}` | `{{ account }}`
`{{ permission }}` | `{{ account_name }}`
`{{ permission_name }}` |
-| `{{ linkauth }}` | `{{ account }}`
`{{ code }}`
`{{ type }}`
`{{ requirement }}` | `{{ account_name }}`
`{{ account_name }}`
`{{ action_name }}`
`{{ permission_name }}` |
-| `{{ unlinkauth }}` | `{{ account }}`
`{{ code }}`
`{{ type }}` | `{{ account_name }}`
`{{ account_name }}`
`{{ action_name }}` |
-| `{{ canceldelay }}` | `{{ canceling_auth }}`
`{{ trx_id }}` | `{{ permission_level }}`
`{{ transaction_id_type }}` |
-| `{{ onerror }}` | `{{ sender_id }}`
`{{ sent_trx }}` | `{{ uint128 }}`
`{{ bytes }}` |
-| `{{ buyrambytes }}` | `{{ payer }}`
`{{ receiver }}`
`{{ bytes }}` | `{{ account_name }}`
`{{ account_name }}`
`{{ uint32 }}` |
-| `{{ buyram }}` | `{{ payer }}`
`{{ receiver }}`
`{{ quant }}` | `{{ account_name }}`
`{{ account_name }}`
`{{ asset }}` |
-| `{{ sellram }}` | `{{ account }}`
`{{ bytes }}` | `{{ account_name }}`
`{{ uint64 }}` |
-| `{{ delegatebw }}` | `{{ from }}`
`{{ receiver }}`
`{{ stake_net_quantity }}`
`{{ stake_cpu_quantity }}`
`{{ transfer }}` | `{{ account_name }}`
`{{ account_name }}`
`{{ asset }}`
`{{ asset }}`
`{{ bool }}` |
-| `{{ undelegatebw }}` | `{{ from }}`
`{{ receiver }}`
`{{ unstake_net_quantity }}`
`{{ unstake_cpu_quantity }}` | `{{ account_name }}`
`{{ account_name }}`
`{{ asset }}`
`{{ asset }}` |
-| `{{ refund }}` | `{{ owner }}` | `{{ account_name }}` |
-| `{{ regproducer }}` | `{{ producer }}`
`{{ producer_key }}`
`{{ url }}`
`{{ location }}` | `{{ account_name }}`
`{{ public_key }}`
`{{ string }}`
`{{ uint16 }}` |
-| `{{ setram }}` | `{{ max_ram_size }}` | `{{ uint64 }}` |
-| `{{ bidname }}` | `{{ bidder }}`
`{{ newname }}`
`{{ bid }}` | `{{ account_name }}`
`{{ account_name }}`
`{{ asset }}` |
-| `{{ unregprod }}` | `{{ producer }}` | `{{ account_name }}` |
-| `{{ regproxy }}` | `{{ proxy }}`
`{{ isproxy }}` | `{{ account_name }}`
`{{ bool }}` |
-| `{{ voteproducer }}` | `{{ voter }}`
`{{ proxy }}`
`{{ producers }}` | `{{ account_name }}`
`{{ account_name }}`
`{{ account_name[] }}` |
-| `{{ claimrewards }}` | `{{ owner }}` | `{{ account_name }}` |
-| `{{ setpriv }}` | `{{ account }}`
`{{ is_priv }}` | `{{ account_name }}`
`{{ int8 }}` |
-| `{{ setalimits }}` | `{{ account }}`
`{{ ram_bytes }}`
`{{ net_weight }}`
`{{ cpu_weight }}` | `{{ account_name }}`
`{{ int64 }}`
`{{ int64 }}`
`{{ int64 }}` |
-| `{{ setglimits }}` | `{{ cpu_usec_per_period }}` | `{{ int64 }}` |
-| `{{ setprods }}` | `{{ schedule }}` | `{{ producer_key[] }}` |
-| `{{ reqauth }}` | `{{ from }}` | `{{ account_name }}` |
\ No newline at end of file
diff --git a/contracts/eosio.system/eosio.system-refund-rc.md b/contracts/eosio.system/eosio.system-refund-rc.md
deleted file mode 100644
index 7e2af0284d8..00000000000
--- a/contracts/eosio.system/eosio.system-refund-rc.md
+++ /dev/null
@@ -1,20 +0,0 @@
-# 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.
diff --git a/contracts/eosio.system/eosio.system-regproducer-rc.md b/contracts/eosio.system/eosio.system-regproducer-rc.md
deleted file mode 100644
index 9857bc9082d..00000000000
--- a/contracts/eosio.system/eosio.system-regproducer-rc.md
+++ /dev/null
@@ -1,62 +0,0 @@
-# eosio.system regproducer
-
-I, {{producer}}, hereby nominate myself for consideration as an elected block producer.
-
-If {{producer}} is selected to produce blocks by the eosio contract, I will sign blocks with {{producer_key}} and I hereby attest that I will keep this key secret and secure.
-
-If {{producer}} is unable to perform obligations under this contract I will resign my position by resubmitting this contract with the null producer key.
-
-I acknowledge that a block is 'objectively valid' if it conforms to the deterministic blockchain rules in force at the time of its creation, and is 'objectively invalid' if it fails to conform to those rules.
-
-{{producer}} hereby agrees to only use {{producer_key}} to sign messages under the following scenarios:
-
-1. proposing an objectively valid block at the time appointed by the block scheduling algorithm
-2. pre-confirming a block produced by another producer in the schedule when I find said block objectively valid
-3. confirming a block for which {{producer}} has received 2/3+ pre-confirmation messages from other producers
-
-I hereby accept liability for any and all provable damages that result from my:
-
-1. signing two different block proposals with the same timestamp with {{producer_key}
-2. signing two different block proposals with the same block number with {{producer_key}
-3. signing any block proposal which builds off of an objectively invalid block
-4. signing a pre-confirmation for an objectively invalid block
-5. signing a confirmation for a block for which I do not possess pre-confirmation messages from 2/3+ other producers
-
-I hereby agree that double-signing for a timestamp or block number in concert with 2 or more other producers shall automatically be deemed malicious and subject to a fine equal to the past year of compensation received and imediate disqualification from being a producer, and other damages. An exception may be made if {{producer}} can demonstrate that the double-signing occured due to a bug in the reference software; the burden of proof is on {{producer}}.
-
-I hereby agree not to interfere with the producer election process. I agree to process all producer election transactions that occur in blocks I create, to sign all objectively valid blocks I create that contain election transactions, and to sign all pre-confirmations and confirmations necessary to facilitate transfer of control to the next set of producers as determined by the system contract.
-
-I hereby acknowledge that 2/3+ other elected producers may vote to disqualify {{producer}} in the event {{producer}} is unable to produce blocks or is unable to be reached, according to criteria agreed to among producers.
-
-If {{producer}} qualifies for and chooses to collect compensation due to votes received, {{producer}} will provide a public endpoint allowing at least 100 peers to maintain synchronization with the blockchain and/or submit transactions to be included. {{producer}} shall maintain at least 1 validating node with full state and signature checking and shall report any objectively invalid blocks produced by the active block producers. Reporting shall be via a method to be agreed to among producers, said method and reports to be made public.
-
-The community agrees to allow {{producer}} to authenticate peers as necessary to prevent abuse and denial of service attacks; however, {{producer}} agrees not to discriminate against non-abusive peers.
-
-I agree to process transactions on a FIFO best-effort basis and to honestly bill transactions for measured execution time.
-
-I {{producer}} agree not to manipulate the contents of blocks in order to derive profit from:
-
-1. the order in which transactions are included
-2. the hash of the block that is produced
-
-I, {{producer}}, hereby agree to disclose and attest under penalty of perjury all ultimate beneficial owners of my company who own more than 1%.
-
-I, {{producer}}, hereby agree to cooperate with other block producers to carry out our respective and mutual obligations under this agreement, including but not limited to maintaining network stability and a valid blockchain.
-
-I, {{producer}}, agree to maintain a website hosted at {{url}} which contains up-to-date information on all disclosures required by this contract.
-
-I, {{producer}}, agree to set {{location}} such that {{producer}} is scheduled with minimal latency between my previous and next peer.
-
-I, {{producer}}, agree to maintain time synchronization within 10 ms of global atomic clock time, using a method agreed to among producers.
-
-I, {{producer}}, agree not to produce blocks before my scheduled time unless I have received all blocks produced by the prior producer.
-
-I, {{producer}}, agree not to publish blocks with timestamps more than 500ms in the future unless the prior block is more than 75% full by either CPU or network bandwidth metrics.
-
-I, {{producer}}, agree not to set the RAM supply to more RAM than my nodes contain and to resign if I am unable to provide the RAM approved by 2/3+ producers, as shown in the system parameters.
-
-## Constitution
-
-This agreement incorporates the current blockchain constitution:
-
-{{constitution}}
diff --git a/contracts/eosio.system/eosio.system-regproxy-rc.md b/contracts/eosio.system/eosio.system-regproxy-rc.md
deleted file mode 100644
index 3c78aa692b8..00000000000
--- a/contracts/eosio.system/eosio.system-regproxy-rc.md
+++ /dev/null
@@ -1,19 +0,0 @@
-# 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 }}`
`{{ isproxyVar }}` | `{{ account_name }}`
`{{ 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.
diff --git a/contracts/eosio.system/eosio.system-reqauth-rc.md b/contracts/eosio.system/eosio.system-reqauth-rc.md
deleted file mode 100644
index c347e5b044f..00000000000
--- a/contracts/eosio.system/eosio.system-reqauth-rc.md
+++ /dev/null
@@ -1,19 +0,0 @@
-# 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.
diff --git a/contracts/eosio.system/eosio.system-sellram-rc.md b/contracts/eosio.system/eosio.system-sellram-rc.md
deleted file mode 100644
index b10dfb04ced..00000000000
--- a/contracts/eosio.system/eosio.system-sellram-rc.md
+++ /dev/null
@@ -1,19 +0,0 @@
-# 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 }}`
`{{ bytesVar }}` | `{{ account_name }}`
`{{ 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.
diff --git a/contracts/eosio.system/eosio.system-setabi-rc.md b/contracts/eosio.system/eosio.system-setabi-rc.md
deleted file mode 100644
index 6167d2a8b14..00000000000
--- a/contracts/eosio.system/eosio.system-setabi-rc.md
+++ /dev/null
@@ -1,19 +0,0 @@
-# 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 }}`
`{{ abiVar }}` | `{{ account_name }}`
`{{ 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.
diff --git a/contracts/eosio.system/eosio.system-setalimits-rc.md b/contracts/eosio.system/eosio.system-setalimits-rc.md
deleted file mode 100644
index 70b210ffcad..00000000000
--- a/contracts/eosio.system/eosio.system-setalimits-rc.md
+++ /dev/null
@@ -1,20 +0,0 @@
-# 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 }}`
`{{ ram_bytesVar }}`
`{{ net_weightVar }}`
`{{ cpu_weightVar }}` | `{{ account_name }}`
`{{ int64 }}`
`{{ int64 }}`
`{{ 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.
diff --git a/contracts/eosio.system/eosio.system-setcode-rc.md b/contracts/eosio.system/eosio.system-setcode-rc.md
deleted file mode 100644
index 5a0d7217a84..00000000000
--- a/contracts/eosio.system/eosio.system-setcode-rc.md
+++ /dev/null
@@ -1,12 +0,0 @@
-# Action - `{{ setcode }}`
-
-### Description
-
-This action updates the code that will run in response to delivered actions. It may be performed by the account upon which the code is being deployed.
-
-By deploying this code you certify that:
-
-1. the code is not malicious
-2. you are authorized to perform the actions automated by the code
-3. the code is consistant with the ABI deployed and intent of the contract
-4. updates to the code are consistant with the prior code's intent
diff --git a/contracts/eosio.system/eosio.system-setglimits-rc.md b/contracts/eosio.system/eosio.system-setglimits-rc.md
deleted file mode 100644
index fa8405a45e3..00000000000
--- a/contracts/eosio.system/eosio.system-setglimits-rc.md
+++ /dev/null
@@ -1,19 +0,0 @@
-# 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.
diff --git a/contracts/eosio.system/eosio.system-setpriv-rc.md b/contracts/eosio.system/eosio.system-setpriv-rc.md
deleted file mode 100644
index 9425fbedba3..00000000000
--- a/contracts/eosio.system/eosio.system-setpriv-rc.md
+++ /dev/null
@@ -1,19 +0,0 @@
-# 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 }}`
`{{ is_privVar }}` | `{{ account_name }}`
`{{ 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.
diff --git a/contracts/eosio.system/eosio.system-setprods-rc.md b/contracts/eosio.system/eosio.system-setprods-rc.md
deleted file mode 100644
index fd4f8d67fc5..00000000000
--- a/contracts/eosio.system/eosio.system-setprods-rc.md
+++ /dev/null
@@ -1,22 +0,0 @@
-# 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.
diff --git a/contracts/eosio.system/eosio.system-setram-rc.md b/contracts/eosio.system/eosio.system-setram-rc.md
deleted file mode 100644
index e9a3ce66572..00000000000
--- a/contracts/eosio.system/eosio.system-setram-rc.md
+++ /dev/null
@@ -1,8 +0,0 @@
-# Action - `{{ setram }}`
-
-### Description
-
-This action sets the total RAM that may be allocated for use by accounts. It may only increase.
-
-Only the controller of this contract may update the RAM availablity. If the owner is a multi-sig collective, the
-parties to the multi-sig each certify that off-the-shelf machines exist capable of supporting the available RAM.
diff --git a/contracts/eosio.system/eosio.system-undelegatebw-rc.md b/contracts/eosio.system/eosio.system-undelegatebw-rc.md
deleted file mode 100644
index f0290732736..00000000000
--- a/contracts/eosio.system/eosio.system-undelegatebw-rc.md
+++ /dev/null
@@ -1,17 +0,0 @@
-# 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.
diff --git a/contracts/eosio.system/eosio.system-unlinkauth-rc.md b/contracts/eosio.system/eosio.system-unlinkauth-rc.md
deleted file mode 100644
index 0e6034f8a6a..00000000000
--- a/contracts/eosio.system/eosio.system-unlinkauth-rc.md
+++ /dev/null
@@ -1,20 +0,0 @@
-# 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 }}`
`{{ codeVar }}`
`{{ typeVar }}` | `{{ account_name }}`
`{{ account_name }}`
`{{ 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.
diff --git a/contracts/eosio.system/eosio.system-unregprod-rc.md b/contracts/eosio.system/eosio.system-unregprod-rc.md
deleted file mode 100644
index 1d21b022c59..00000000000
--- a/contracts/eosio.system/eosio.system-unregprod-rc.md
+++ /dev/null
@@ -1,17 +0,0 @@
-# Action - `{{ unregprod }}`
-
-### 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.
diff --git a/contracts/eosio.system/eosio.system-updateauth-rc.md b/contracts/eosio.system/eosio.system-updateauth-rc.md
deleted file mode 100644
index fe5d639a2b5..00000000000
--- a/contracts/eosio.system/eosio.system-updateauth-rc.md
+++ /dev/null
@@ -1,19 +0,0 @@
-# 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 }}`
`{{ permissionVar }}`
`{{ parentVar }}`
`{{ authVar }}` | `{{ account_name }}`
`{{ permission_name }}`
`{{ permission_name }}`
`{{ 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.
diff --git a/contracts/eosio.system/eosio.system.voteproducer-rc.md b/contracts/eosio.system/eosio.system.voteproducer-rc.md
deleted file mode 100644
index bc80e22f65d..00000000000
--- a/contracts/eosio.system/eosio.system.voteproducer-rc.md
+++ /dev/null
@@ -1,18 +0,0 @@
-# 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.
-
-
-## 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.
-
-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 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.
-
-All disputes arising from this contract shall be resolved in the EOS Core Arbitration Forum.
diff --git a/contracts/eosio.system/voting.cpp b/contracts/eosio.system/voting.cpp
index a00e20547fd..8d31f24483b 100644
--- a/contracts/eosio.system/voting.cpp
+++ b/contracts/eosio.system/voting.cpp
@@ -126,12 +126,11 @@ namespace eosiosystem {
* If voting for a proxy, the producer votes will not change until the proxy updates their own vote.
*/
void system_contract::voteproducer( const account_name voter_name, const account_name proxy, const std::vector& producers ) {
+ require_auth( voter_name );
update_votes( voter_name, proxy, producers, true );
}
void system_contract::update_votes( const account_name voter_name, const account_name proxy, const std::vector& producers, bool voting ) {
- require_auth( voter_name );
-
//validate input
if ( proxy ) {
eosio_assert( producers.size() == 0, "cannot vote for producers and proxy at same time" );
diff --git a/contracts/eosio.token/eosio.token-transfer-rc.md b/contracts/eosio.token/eosio.token-transfer-rc.md
deleted file mode 100644
index 9c098d20d0e..00000000000
--- a/contracts/eosio.token/eosio.token-transfer-rc.md
+++ /dev/null
@@ -1,13 +0,0 @@
-## Transfer Terms & Conditions
-
-I, {{from}}, certify the following to be true to the best of my knowledge:
-
-1. I know the person(s) who transferred {{quantity}} to '{{from}}'.
-2. I know the owner(s) of the '{{to}}' account.
-3. I certify that {{quantity}} is not the proceeds of fraudulent or violent activities.
-4. I certify that, to the best of my knowledge, {{to}} is not supporting initiation of violence against others.
-5. I have disclosed any contractual terms & conditions with respect to {{quantity}} to {{to}}.
-
-I understand that funds transfers are not reversible after the {{transaction.delay}} seconds or other delay as configured by {{from}}'s permissions.
-
-If this action fails to be irreversibly confirmed after receiving goods or services from '{{to}}', I agree to either return the goods or services or resend {{quantity}} in a timely manner.
diff --git a/eosio_build.sh b/eosio_build.sh
index 67f7e939f3c..ad1245c570e 100755
--- a/eosio_build.sh
+++ b/eosio_build.sh
@@ -42,7 +42,7 @@
function usage()
{
- printf "\\tUsage: %s [Build Option -o ] [CodeCoverage -c ] [Doxygen -d]\\n\\n" "$0" 1>&2
+ printf "\\tUsage: %s \\n\\t[Build Option -o ] \\n\\t[CodeCoverage -c ] \\n\\t[Doxygen -d] \\n\\t[CoreSymbolName -s <1-7 characters>]\\n\\n" "$0" 1>&2
exit 1
}
@@ -52,6 +52,7 @@
DISK_MIN=20
DOXYGEN=false
ENABLE_COVERAGE_TESTING=false
+ CORE_SYMBOL_NAME="SYS"
TEMP_DIR="/tmp"
TIME_BEGIN=$( date -u +%s )
VERSION=1.2
@@ -61,7 +62,7 @@
txtrst=$(tput sgr0)
if [ $# -ne 0 ]; then
- while getopts ":cdo:" opt; do
+ while getopts ":cdos:" opt; do
case "${opt}" in
o )
options=( "Debug" "Release" "RelWithDebInfo" "MinSizeRel" )
@@ -79,6 +80,15 @@
d )
DOXYGEN=true
;;
+ s)
+ if [ "${#OPTARG}" -gt 6 ] || [ -z "${#OPTARG}" ]; then
+ printf "\\n\\tInvalid argument: %s\\n" "${OPTARG}" 1>&2
+ usage
+ exit 1
+ else
+ CORE_SYMBOL_NAME="${OPTARG}"
+ fi
+ ;;
\? )
printf "\\n\\tInvalid Option: %s\\n" "-${OPTARG}" 1>&2
usage
@@ -143,7 +153,6 @@
export LLVM_DIR=${HOME}/opt/wasm/lib/cmake/llvm
export CMAKE=${HOME}/opt/cmake/bin/cmake
export PATH=${HOME}/opt/mongodb/bin:$PATH
- export BOOST_ROOT="${HOME}/opt/boost"
;;
"CentOS Linux")
FILE="${PWD}/scripts/eosio_build_centos.sh"
@@ -153,7 +162,6 @@
export LLVM_DIR=${HOME}/opt/wasm/lib/cmake/llvm
export CMAKE=${HOME}/opt/cmake/bin/cmake
export PATH=${HOME}/opt/mongodb/bin:$PATH
- export BOOST_ROOT="${HOME}/opt/boost_1_67_0"
;;
"elementary OS")
FILE="${PWD}/scripts/eosio_build_ubuntu.sh"
@@ -161,7 +169,6 @@
C_COMPILER=clang-4.0
MONGOD_CONF=${HOME}/opt/mongodb/mongod.conf
export PATH=${HOME}/opt/mongodb/bin:$PATH
- export BOOST_ROOT="${HOME}/opt/boost_1_67_0"
;;
"Fedora")
FILE="${PWD}/scripts/eosio_build_fedora.sh"
@@ -169,7 +176,6 @@
C_COMPILER=gcc
MONGOD_CONF=/etc/mongod.conf
export LLVM_DIR=${HOME}/opt/wasm/lib/cmake/llvm
- export BOOST_ROOT="${HOME}/opt/boost_1_67_0"
;;
"Linux Mint")
FILE="${PWD}/scripts/eosio_build_ubuntu.sh"
@@ -177,7 +183,6 @@
C_COMPILER=clang-4.0
MONGOD_CONF=${HOME}/opt/mongodb/mongod.conf
export PATH=${HOME}/opt/mongodb/bin:$PATH
- export BOOST_ROOT="${HOME}/opt/boost_1_67_0"
;;
"Ubuntu")
FILE="${PWD}/scripts/eosio_build_ubuntu.sh"
@@ -185,13 +190,13 @@
C_COMPILER=clang-4.0
MONGOD_CONF=${HOME}/opt/mongodb/mongod.conf
export PATH=${HOME}/opt/mongodb/bin:$PATH
- export BOOST_ROOT="${HOME}/opt/boost_1_67_0"
;;
*)
printf "\\n\\tUnsupported Linux Distribution. Exiting now.\\n\\n"
exit 1
esac
+ export BOOST_ROOT="${HOME}/opt/boost"
OPENSSL_ROOT_DIR=/usr/include/openssl
WASM_ROOT="${HOME}/opt/wasm"
fi
@@ -231,7 +236,7 @@
fi
if ! "${CMAKE}" -DCMAKE_BUILD_TYPE="${CMAKE_BUILD_TYPE}" -DCMAKE_CXX_COMPILER="${CXX_COMPILER}" \
- -DCMAKE_C_COMPILER="${C_COMPILER}" -DWASM_ROOT="${WASM_ROOT}" \
+ -DCMAKE_C_COMPILER="${C_COMPILER}" -DWASM_ROOT="${WASM_ROOT}" -DCORE_SYMBOL_NAME="${CORE_SYMBOL_NAME}" \
-DOPENSSL_ROOT_DIR="${OPENSSL_ROOT_DIR}" -DBUILD_MONGO_DB_PLUGIN=true \
-DENABLE_COVERAGE_TESTING="${ENABLE_COVERAGE_TESTING}" -DBUILD_DOXYGEN="${DOXYGEN}" ..
then
diff --git a/libraries/abi_generator/abi_generator.cpp b/libraries/abi_generator/abi_generator.cpp
index c6a084007c9..44a0a6f5216 100644
--- a/libraries/abi_generator/abi_generator.cpp
+++ b/libraries/abi_generator/abi_generator.cpp
@@ -124,7 +124,7 @@ bool abi_generator::inspect_type_methods_for_actions(const Decl* decl) { try {
qt.setLocalFastQualifiers(0);
string field_name = p->getNameAsString();
- string field_type_name = add_type(qt);
+ string field_type_name = add_type(qt, 0);
field_def struct_field{field_name, field_type_name};
ABI_ASSERT(is_builtin_type(get_vector_element_type(struct_field.type))
@@ -236,7 +236,7 @@ void abi_generator::handle_decl(const Decl* decl) { try {
auto qt = action_decl->getTypeForDecl()->getCanonicalTypeInternal();
- auto type_name = add_struct(qt);
+ auto type_name = add_struct(qt, "", 0);
ABI_ASSERT(!is_builtin_type(type_name),
"A built-in type with the same name exists, try using another name: ${type_name}", ("type_name",type_name));
@@ -259,7 +259,7 @@ void abi_generator::handle_decl(const Decl* decl) { try {
ABI_ASSERT(table_decl != nullptr);
auto qt = table_decl->getTypeForDecl()->getCanonicalTypeInternal();
- auto type_name = add_struct(qt);
+ auto type_name = add_struct(qt, "", 0);
ABI_ASSERT(!is_builtin_type(type_name),
"A built-in type with the same name exists, try using another name: ${type_name}", ("type_name",type_name));
@@ -433,7 +433,11 @@ const struct_def* abi_generator::find_struct(const type_name& name) {
type_name abi_generator::resolve_type(const type_name& type){
const auto* td = find_type(type);
if( td ) {
- return resolve_type(td->type);
+ for( auto i = output->types.size(); i > 0; --i ) { // avoid infinite recursion
+ const type_name& t = td->type;
+ td = find_type(t);
+ if( td == nullptr ) return t;
+ }
}
return type;
}
@@ -505,7 +509,9 @@ string abi_generator::get_type_name(const clang::QualType& qt, bool with_namespa
return name;
}
-clang::QualType abi_generator::add_typedef(const clang::QualType& tqt) {
+clang::QualType abi_generator::add_typedef(const clang::QualType& tqt, size_t recursion_depth) {
+
+ ABI_ASSERT( ++recursion_depth < max_recursion_depth, "recursive definition, max_recursion_depth" );
clang::QualType qt(get_named_type_if_elaborated(tqt));
@@ -516,7 +522,7 @@ clang::QualType abi_generator::add_typedef(const clang::QualType& tqt) {
auto underlying_type_name = get_type_name(underlying_type);
if ( is_vector(underlying_type) ) {
- underlying_type_name = add_vector(underlying_type);
+ underlying_type_name = add_vector(underlying_type, recursion_depth);
}
type_def abi_typedef;
@@ -531,7 +537,7 @@ clang::QualType abi_generator::add_typedef(const clang::QualType& tqt) {
}
if( is_typedef(underlying_type) && !is_builtin_type(get_type_name(underlying_type)) )
- return add_typedef(underlying_type);
+ return add_typedef(underlying_type, recursion_depth);
return underlying_type;
}
@@ -568,14 +574,16 @@ const clang::RecordDecl::field_range abi_generator::get_struct_fields(const clan
return record_type->getDecl()->fields();
}
-string abi_generator::add_vector(const clang::QualType& vqt) {
+string abi_generator::add_vector(const clang::QualType& vqt, size_t recursion_depth) {
+
+ ABI_ASSERT( ++recursion_depth < max_recursion_depth, "recursive definition, max_recursion_depth" );
clang::QualType qt(get_named_type_if_elaborated(vqt));
auto vector_element_type = get_vector_element_type(qt);
ABI_ASSERT(!is_vector(vector_element_type), "Only one-dimensional arrays are supported");
- add_type(vector_element_type);
+ add_type(vector_element_type, recursion_depth);
auto vector_element_type_str = translate_type(get_type_name(vector_element_type));
vector_element_type_str += "[]";
@@ -583,7 +591,9 @@ string abi_generator::add_vector(const clang::QualType& vqt) {
return vector_element_type_str;
}
-string abi_generator::add_type(const clang::QualType& tqt) {
+string abi_generator::add_type(const clang::QualType& tqt, size_t recursion_depth) {
+
+ ABI_ASSERT( ++recursion_depth < max_recursion_depth, "recursive definition, max_recursion_depth" );
clang::QualType qt(get_named_type_if_elaborated(tqt));
@@ -596,7 +606,7 @@ string abi_generator::add_type(const clang::QualType& tqt) {
}
if( is_typedef(qt) ) {
- qt = add_typedef(qt);
+ qt = add_typedef(qt, recursion_depth);
if( is_builtin_type(translate_type(get_type_name(qt))) ) {
return type_name;
}
@@ -604,12 +614,12 @@ string abi_generator::add_type(const clang::QualType& tqt) {
}
if( is_vector(qt) ) {
- auto vector_type_name = add_vector(qt);
+ auto vector_type_name = add_vector(qt, recursion_depth);
return is_type_def ? type_name : vector_type_name;
}
if( is_struct(qt) ) {
- return add_struct(qt, full_type_name);
+ return add_struct(qt, full_type_name, recursion_depth);
}
ABI_ASSERT(false, "types can only be: vector, struct, class or a built-in type. (${type}) ", ("type",get_type_name(qt)));
@@ -623,7 +633,9 @@ clang::QualType abi_generator::get_named_type_if_elaborated(const clang::QualTyp
return qt;
}
-string abi_generator::add_struct(const clang::QualType& sqt, string full_name) {
+string abi_generator::add_struct(const clang::QualType& sqt, string full_name, size_t recursion_depth) {
+
+ ABI_ASSERT( ++recursion_depth < max_recursion_depth, "recursive definition, max_recursion_depth" );
clang::QualType qt(get_named_type_if_elaborated(sqt));
@@ -653,7 +665,7 @@ string abi_generator::add_struct(const clang::QualType& sqt, string full_name) {
const auto* record_type = base_qt->getAs();
if( record_type && is_struct(base_qt) && !record_type->getDecl()->field_empty() ) {
ABI_ASSERT(total_bases == 0, "Multiple inheritance not supported - ${type}", ("type",full_name));
- base_name = add_type(base_qt);
+ base_name = add_type(base_qt, recursion_depth);
++total_bases;
}
++bitr;
@@ -664,7 +676,7 @@ string abi_generator::add_struct(const clang::QualType& sqt, string full_name) {
clang::QualType qt = field->getType();
string field_name = field->getNameAsString();
- string field_type_name = add_type(qt);
+ string field_type_name = add_type(qt, recursion_depth);
field_def struct_field{field_name, field_type_name};
ABI_ASSERT(is_builtin_type(get_vector_element_type(struct_field.type))
diff --git a/libraries/abi_generator/include/eosio/abi_generator/abi_generator.hpp b/libraries/abi_generator/include/eosio/abi_generator/abi_generator.hpp
index 093409d22ba..cdb5d0ffe3e 100644
--- a/libraries/abi_generator/include/eosio/abi_generator/abi_generator.hpp
+++ b/libraries/abi_generator/include/eosio/abi_generator/abi_generator.hpp
@@ -159,7 +159,8 @@ namespace eosio {
* @brief Generates eosio::abi_def struct handling events from ASTConsumer
*/
class abi_generator {
- private:
+ private:
+ static constexpr size_t max_recursion_depth = 25; // arbitrary depth to prevent infinite recursion
bool verbose;
int optimizations;
abi_def* output;
@@ -171,6 +172,7 @@ namespace eosio {
string target_contract;
vector target_actions;
ricardian_contracts rc;
+
public:
enum optimization {
@@ -178,7 +180,8 @@ namespace eosio {
};
abi_generator()
- :optimizations(0)
+ : verbose(false)
+ , optimizations(0)
, output(nullptr)
, compiler_instance(nullptr)
, ast_context(nullptr)
@@ -283,17 +286,17 @@ namespace eosio {
string decl_to_string(clang::Decl* d);
bool is_typedef(const clang::QualType& qt);
- QualType add_typedef(const clang::QualType& qt);
+ QualType add_typedef(const clang::QualType& qt, size_t recursion_depth);
bool is_vector(const clang::QualType& qt);
bool is_vector(const string& type_name);
- string add_vector(const clang::QualType& qt);
+ string add_vector(const clang::QualType& qt, size_t recursion_depth);
bool is_struct(const clang::QualType& qt);
- string add_struct(const clang::QualType& qt, string full_type_name="");
+ string add_struct(const clang::QualType& qt, string full_type_name, size_t recursion_depth);
string get_type_name(const clang::QualType& qt, bool no_namespace);
- string add_type(const clang::QualType& tqt);
+ string add_type(const clang::QualType& tqt, size_t recursion_depth);
bool is_elaborated(const clang::QualType& qt);
bool is_struct_specialization(const clang::QualType& qt);
diff --git a/libraries/chain/block_header_state.cpp b/libraries/chain/block_header_state.cpp
index d741ace2de1..785e7c8ebfd 100644
--- a/libraries/chain/block_header_state.cpp
+++ b/libraries/chain/block_header_state.cpp
@@ -155,7 +155,7 @@ namespace eosio { namespace chain {
auto itr = producer_to_last_produced.find(h.producer);
if( itr != producer_to_last_produced.end() ) {
- FC_ASSERT( itr->second < result.block_num - h.confirmed, "producer double-confirming known range" );
+ FC_ASSERT( itr->second < result.block_num - h.confirmed, "producer ${prod} double-confirming known range", ("prod", h.producer) );
}
// FC_ASSERT( result.header.block_mroot == h.block_mroot, "mismatch block merkle root" );
diff --git a/libraries/chain/controller.cpp b/libraries/chain/controller.cpp
index bb543ca5cb7..58110734339 100644
--- a/libraries/chain/controller.cpp
+++ b/libraries/chain/controller.cpp
@@ -776,12 +776,7 @@ struct controller_impl {
void sign_block( const std::function& signer_callback, bool trust ) {
auto p = pending->_pending_block_state;
- try {
- p->sign( signer_callback, false); //trust );
- } catch ( ... ) {
- edump(( fc::json::to_pretty_string( p->header ) ) );
- throw;
- }
+ p->sign( signer_callback, false); //trust );
static_cast(*p->block) = p->header;
} /// sign_block
diff --git a/libraries/chain/fork_database.cpp b/libraries/chain/fork_database.cpp
index 34a77030e43..560221afde0 100644
--- a/libraries/chain/fork_database.cpp
+++ b/libraries/chain/fork_database.cpp
@@ -79,8 +79,6 @@ namespace eosio { namespace chain {
void fork_database::close() {
if( my->index.size() == 0 ) return;
- fc::datastream ps;
-
auto fork_db_dat = my->datadir / config::forkdb_filename;
std::ofstream out( fork_db_dat.generic_string().c_str(), std::ios::out | std::ios::binary | std::ofstream::trunc );
uint32_t num_blocks_in_fork_db = my->index.size();
diff --git a/libraries/chain/include/eosio/chain/config.hpp b/libraries/chain/include/eosio/chain/config.hpp
index d9c7fc31f33..dc4d608c6de 100644
--- a/libraries/chain/include/eosio/chain/config.hpp
+++ b/libraries/chain/include/eosio/chain/config.hpp
@@ -69,7 +69,7 @@ const static uint32_t default_context_free_discount_net_usage_den = 100;
const static uint32_t transaction_id_net_usage = 32; // 32 bytes for the size of a transaction id
const static uint32_t default_max_block_cpu_usage = 200'000; /// max block cpu usage in microseconds
-const static uint32_t default_target_block_cpu_usage_pct = percent_1; /// target 1000 TPS
+const static uint32_t default_target_block_cpu_usage_pct = 10 * percent_1;
const static uint32_t default_max_transaction_cpu_usage = 3*default_max_block_cpu_usage/4; /// max trx cpu usage in microseconds
const static uint32_t default_min_transaction_cpu_usage = 100; /// min trx cpu usage in microseconds (10000 TPS equiv)
diff --git a/libraries/chain/include/eosio/chain/transaction_context.hpp b/libraries/chain/include/eosio/chain/transaction_context.hpp
index 623c65fabe8..008c341a179 100644
--- a/libraries/chain/include/eosio/chain/transaction_context.hpp
+++ b/libraries/chain/include/eosio/chain/transaction_context.hpp
@@ -77,7 +77,7 @@ namespace eosio { namespace chain {
bool apply_context_free = true;
fc::time_point deadline = fc::time_point::maximum();
- fc::microseconds leeway = fc::microseconds(1000);
+ fc::microseconds leeway = fc::microseconds(3000);
int64_t billed_cpu_time_us = 0;
private:
diff --git a/libraries/chain/resource_limits.cpp b/libraries/chain/resource_limits.cpp
index 482d45119aa..a3fe393f6b7 100644
--- a/libraries/chain/resource_limits.cpp
+++ b/libraries/chain/resource_limits.cpp
@@ -93,7 +93,6 @@ void resource_limits_manager::update_account_usage(const flat_set&
void resource_limits_manager::add_transaction_usage(const flat_set& accounts, uint64_t cpu_usage, uint64_t net_usage, uint32_t time_slot ) {
const auto& state = _db.get();
const auto& config = _db.get();
- set> authorizing_accounts;
for( const auto& a : accounts ) {
@@ -232,7 +231,6 @@ bool resource_limits_manager::set_account_limits( const account_name& account, i
*/
}
- auto old_ram_bytes = limits.ram_bytes;
_db.modify( limits, [&]( resource_limits_object& pending_limits ){
pending_limits.ram_bytes = ram_bytes;
pending_limits.net_weight = net_weight;
diff --git a/libraries/chain/transaction_context.cpp b/libraries/chain/transaction_context.cpp
index e8fe6401b84..01e04484990 100644
--- a/libraries/chain/transaction_context.cpp
+++ b/libraries/chain/transaction_context.cpp
@@ -289,16 +289,16 @@ namespace eosio { namespace chain {
} else if( deadline_exception_code == block_cpu_usage_exceeded::code_value ) {
EOS_THROW( block_cpu_usage_exceeded,
"not enough time left in block to complete executing transaction",
- ("now", now)("deadline", _deadline)("start", start) );
+ ("now", now)("deadline", _deadline)("start", start)("billing_timer", now - pseudo_start) );
} else if( deadline_exception_code == tx_cpu_usage_exceeded::code_value ) {
EOS_THROW( tx_cpu_usage_exceeded,
"transaction was executing for too long",
- ("now", now)("deadline", _deadline)("start", start) );
+ ("now", now)("deadline", _deadline)("start", start)("billing_timer", now - pseudo_start) );
} else if( deadline_exception_code == leeway_deadline_exception::code_value ) {
EOS_THROW( leeway_deadline_exception,
"the transaction was unable to complete by deadline, "
- "but it is possible it could have succeeded if it were allow to run to completion",
- ("now", now)("deadline", _deadline)("start", start) );
+ "but it is possible it could have succeeded if it were allowed to run to completion",
+ ("now", now)("deadline", _deadline)("start", start)("billing_timer", now - pseudo_start) );
}
FC_ASSERT( false, "unexpected deadline exception code" );
}
diff --git a/libraries/fc/CMakeLists.txt b/libraries/fc/CMakeLists.txt
index 15450b78a8e..46dc87102bc 100644
--- a/libraries/fc/CMakeLists.txt
+++ b/libraries/fc/CMakeLists.txt
@@ -104,6 +104,7 @@ set( fc_sources
src/network/resolve.cpp
src/network/udp_socket.cpp
src/network/url.cpp
+ src/network/http/http_client.cpp
src/compress/smaz.cpp
src/compress/zlib.cpp
)
diff --git a/libraries/fc/include/fc/io/json.hpp b/libraries/fc/include/fc/io/json.hpp
index e35517a9a63..1395cf75b32 100644
--- a/libraries/fc/include/fc/io/json.hpp
+++ b/libraries/fc/include/fc/io/json.hpp
@@ -2,6 +2,8 @@
#include
#include
+#define DEFAULT_MAX_RECURSION_DEPTH 200
+
namespace fc
{
using std::ostream;
@@ -32,12 +34,12 @@ namespace fc
static ostream& to_stream( ostream& out, const variants& v, output_formatting format = stringify_large_ints_and_doubles );
static ostream& to_stream( ostream& out, const variant_object& v, output_formatting format = stringify_large_ints_and_doubles );
- static variant from_string( const string& utf8_str, parse_type ptype = legacy_parser );
- static variants variants_from_string( const string& utf8_str, parse_type ptype = legacy_parser );
+ static variant from_string( const string& utf8_str, parse_type ptype = legacy_parser, uint32_t max_depth = DEFAULT_MAX_RECURSION_DEPTH );
+ static variants variants_from_string( const string& utf8_str, parse_type ptype = legacy_parser, uint32_t max_depth = DEFAULT_MAX_RECURSION_DEPTH );
static string to_string( const variant& v, output_formatting format = stringify_large_ints_and_doubles );
static string to_pretty_string( const variant& v, output_formatting format = stringify_large_ints_and_doubles );
- static bool is_valid( const std::string& json_str, parse_type ptype = legacy_parser );
+ static bool is_valid( const std::string& json_str, parse_type ptype = legacy_parser, uint32_t max_depth = DEFAULT_MAX_RECURSION_DEPTH );
template
static void save_to_file( const T& v, const fc::path& fi, bool pretty = true, output_formatting format = stringify_large_ints_and_doubles )
@@ -46,16 +48,16 @@ namespace fc
}
static void save_to_file( const variant& v, const fc::path& fi, bool pretty = true, output_formatting format = stringify_large_ints_and_doubles );
- static variant from_file( const fc::path& p, parse_type ptype = legacy_parser );
+ static variant from_file( const fc::path& p, parse_type ptype = legacy_parser, uint32_t max_depth = DEFAULT_MAX_RECURSION_DEPTH );
template
- static T from_file( const fc::path& p, parse_type ptype = legacy_parser )
+ static T from_file( const fc::path& p, parse_type ptype = legacy_parser, uint32_t max_depth = DEFAULT_MAX_RECURSION_DEPTH )
{
- return json::from_file(p, ptype).as();
+ return json::from_file(p, ptype, max_depth).as();
}
template
- static string to_string( const T& v, output_formatting format = stringify_large_ints_and_doubles )
+ static string to_string( const T& v, output_formatting format = stringify_large_ints_and_doubles )
{
return to_string( variant(v), format );
}
@@ -69,8 +71,10 @@ namespace fc
template
static void save_to_file( const T& v, const std::string& p, bool pretty = true, output_formatting format = stringify_large_ints_and_doubles )
{
- save_to_file( variant(v), fc::path(p), pretty );
+ save_to_file( variant(v), fc::path(p), pretty, format );
}
};
} // fc
+
+#undef DEFAULT_MAX_RECURSION_DEPTH
diff --git a/libraries/fc/include/fc/io/json_relaxed.hpp b/libraries/fc/include/fc/io/json_relaxed.hpp
index 3ddf0ae894f..c2691d44bec 100644
--- a/libraries/fc/include/fc/io/json_relaxed.hpp
+++ b/libraries/fc/include/fc/io/json_relaxed.hpp
@@ -21,7 +21,7 @@
namespace fc { namespace json_relaxed
{
template
- variant variant_from_stream( T& in );
+ variant variant_from_stream( T& in, uint32_t max_depth );
template
std::string tokenFromStream( T& in )
@@ -562,7 +562,7 @@ namespace fc { namespace json_relaxed
} FC_CAPTURE_AND_RETHROW( (token) ) }
template
- variant_object objectFromStream( T& in )
+ variant_object objectFromStream( T& in, uint32_t max_depth )
{
mutable_variant_object obj;
try
@@ -590,7 +590,7 @@ namespace fc { namespace json_relaxed
("key", key) );
}
in.get();
- auto val = json_relaxed::variant_from_stream( in );
+ auto val = json_relaxed::variant_from_stream( in, max_depth - 1 );
obj(std::move(key),std::move(val));
skip_white_space(in);
@@ -613,7 +613,7 @@ namespace fc { namespace json_relaxed
}
template
- variants arrayFromStream( T& in )
+ variants arrayFromStream( T& in, uint32_t max_depth )
{
variants ar;
try
@@ -631,7 +631,7 @@ namespace fc { namespace json_relaxed
continue;
}
if( skip_white_space(in) ) continue;
- ar.push_back( json_relaxed::variant_from_stream(in) );
+ ar.push_back( json_relaxed::variant_from_stream(in, max_depth - 1) );
skip_white_space(in);
}
if( in.peek() != ']' )
@@ -686,7 +686,7 @@ namespace fc { namespace json_relaxed
}
template
- variant variant_from_stream( T& in )
+ variant variant_from_stream( T& in, uint32_t max_depth )
{
skip_white_space(in);
variant var;
@@ -701,11 +701,11 @@ namespace fc { namespace json_relaxed
in.get();
continue;
case '"':
- return json_relaxed::stringFromStream( in );
+ return json_relaxed::stringFromStream( in );
case '{':
- return json_relaxed::objectFromStream( in );
+ return json_relaxed::objectFromStream( in, max_depth - 1 );
case '[':
- return json_relaxed::arrayFromStream( in );
+ return json_relaxed::arrayFromStream( in, max_depth - 1 );
case '-':
case '+':
case '.':
diff --git a/libraries/fc/include/fc/network/http/http_client.hpp b/libraries/fc/include/fc/network/http/http_client.hpp
new file mode 100644
index 00000000000..47a38f434e4
--- /dev/null
+++ b/libraries/fc/include/fc/network/http/http_client.hpp
@@ -0,0 +1,36 @@
+/**
+ * @file
+ * @copyright defined in LICENSE.txt
+ */
+#pragma once
+
+#include
+#include
+#include
+#include
+#include
+
+namespace fc {
+
+class http_client {
+ public:
+ http_client();
+ ~http_client();
+
+ variant post_sync(const url& dest, const variant& payload, const time_point& deadline = time_point::maximum());
+
+ template
+ variant post_sync(const url& dest, const T& payload, const time_point& deadline = time_point::maximum()) {
+ variant payload_v;
+ to_variant(payload, payload_v);
+ return post_sync(dest, payload_v, deadline);
+ }
+
+ void add_cert(const std::string& cert_pem_string);
+ void set_verify_peers(bool enabled);
+
+private:
+ std::unique_ptr _my;
+};
+
+}
\ No newline at end of file
diff --git a/libraries/fc/include/fc/network/message_buffer.hpp b/libraries/fc/include/fc/network/message_buffer.hpp
index 702beacd3e5..aae6c9d3ed0 100644
--- a/libraries/fc/include/fc/network/message_buffer.hpp
+++ b/libraries/fc/include/fc/network/message_buffer.hpp
@@ -8,6 +8,7 @@
#include
#include
#include
+#include
namespace fc {
template
@@ -120,7 +121,15 @@ namespace fc {
* Logically, this is the different between where the read and write pointers are.
*/
uint32_t bytes_to_read() const {
- return (write_ind.first - read_ind.first) * buffer_len + write_ind.second - read_ind.second;
+ return bytes_to_read_from_index(read_ind);
+ }
+
+ /*
+ * Returns the current number of bytes remaining to be read from a given index
+ * Logically, this is the different between where the given index is and the write pointers.
+ */
+ uint32_t bytes_to_read_from_index(index_t ind) const {
+ return (write_ind.first - ind.first) * buffer_len + write_ind.second - ind.second;
}
/*
@@ -198,7 +207,7 @@ namespace fc {
*/
bool read(void* s, uint32_t size) {
if (bytes_to_read() < size) {
- return false;
+ FC_THROW_EXCEPTION(out_of_range_exception, "tried to read ${r} but only ${s} left", ("r", size)("s", bytes_to_read()));
}
if (read_ind.second + size <= buffer_len) {
memcpy(s, read_ptr(), size);
@@ -217,8 +226,8 @@ namespace fc {
* The supplied index is advanced, but the read pointer is unaffected.
*/
bool peek(void* s, uint32_t size, index_t& index) {
- if (bytes_to_read() < size) {
- return false;
+ if (bytes_to_read_from_index(index) < size) {
+ FC_THROW_EXCEPTION(out_of_range_exception, "tried to peek ${r} but only ${s} left", ("r", size)("s",bytes_to_read_from_index(index)));
}
if (index.second + size <= buffer_len) {
memcpy(s, get_ptr(index), size);
diff --git a/libraries/fc/include/fc/network/url.hpp b/libraries/fc/include/fc/network/url.hpp
index 6f8c7451f58..2e94498e3a0 100644
--- a/libraries/fc/include/fc/network/url.hpp
+++ b/libraries/fc/include/fc/network/url.hpp
@@ -47,6 +47,7 @@ namespace fc {
ostring user()const;
ostring pass()const;
opath path()const;
+ ostring query()const;
ovariant_object args()const;
fc::optional port()const;
@@ -86,6 +87,7 @@ namespace fc {
ostring user()const;
ostring pass()const;
opath path()const;
+ ostring query()const;
ovariant_object args()const;
fc::optional port()const;
@@ -94,6 +96,7 @@ namespace fc {
void set_user( string );
void set_pass( string );
void set_path( fc::path p );
+ void set_query( string );
void set_args( variant_object );
void set_port( uint16_t );
diff --git a/libraries/fc/include/fc/static_variant.hpp b/libraries/fc/include/fc/static_variant.hpp
index 19a423949da..376246cdb57 100644
--- a/libraries/fc/include/fc/static_variant.hpp
+++ b/libraries/fc/include/fc/static_variant.hpp
@@ -198,16 +198,10 @@ class static_variant {
alignas(Types...) char storage[impl::type_info::size];
int _tag;
- template
- void init(const X& x) {
- _tag = impl::position::pos;
- new(storage) X(x);
- }
-
template
void init(X&& x) {
- _tag = impl::position::pos;
- new(storage) X( std::move(x) );
+ _tag = impl::position, Types...>::pos;
+ new(storage) std::decay_t( std::forward(x) );
}
template
@@ -246,14 +240,15 @@ class static_variant {
}
template
- static_variant(const X& v) {
+ static_variant(X&& v) {
static_assert(
- impl::position::pos != -1,
+ impl::position, Types...>::pos != -1,
"Type not in static_variant."
);
- init(v);
+ init(std::forward(v));
}
- ~static_variant() {
+
+ ~static_variant() {
impl::storage_ops<0, Types...>::del(_tag, storage);
}
diff --git a/libraries/fc/src/filesystem.cpp b/libraries/fc/src/filesystem.cpp
index 89edc00a81c..2337d101794 100644
--- a/libraries/fc/src/filesystem.cpp
+++ b/libraries/fc/src/filesystem.cpp
@@ -18,7 +18,7 @@
#include
#include
#include
-# ifdef FC_HAS_SIMPLE_FILE_LOCK
+# ifdef FC_HAS_SIMPLE_FILE_LOCK
#include
#include
# endif
@@ -26,7 +26,7 @@
namespace fc {
// when converting to and from a variant, store utf-8 in the variant
- void to_variant( const fc::path& path_to_convert, variant& variant_output )
+ void to_variant( const fc::path& path_to_convert, variant& variant_output )
{
std::wstring wide_string = path_to_convert.generic_wstring();
std::string utf8_string;
@@ -38,7 +38,7 @@ namespace fc {
//v = path;
}
- void from_variant( const fc::variant& variant_to_convert, fc::path& path_output )
+ void from_variant( const fc::variant& variant_to_convert, fc::path& path_output )
{
std::wstring wide_string;
fc::decodeUtf8(variant_to_convert.as_string(), &wide_string);
@@ -128,7 +128,7 @@ namespace fc {
const size_t maxPath = 32*1024;
std::vector short_path;
short_path.resize(maxPath + 1);
-
+
wchar_t* buffer = short_path.data();
DWORD res = GetShortPathNameW(path.c_str(), buffer, maxPath);
if(res != 0)
@@ -140,7 +140,7 @@ namespace fc {
}
/**
- * @todo use iterators instead of indexes for
+ * @todo use iterators instead of indexes for
* faster performance
*/
fc::string path::windows_string()const {
@@ -209,11 +209,11 @@ namespace fc {
return *r._p != *l._p;
}
-
+
bool exists( const path& p ) { return boost::filesystem::exists(p); }
- void create_directories( const path& p ) {
+ void create_directories( const path& p ) {
try {
- boost::filesystem::create_directories(p);
+ boost::filesystem::create_directories(p);
} catch ( ... ) {
FC_THROW( "Unable to create directories ${path}", ("path", p )("inner", fc::except_str() ) );
}
@@ -242,9 +242,10 @@ namespace fc {
}
void remove_all( const path& p ) { boost::filesystem::remove_all(p); }
- void copy( const path& f, const path& t ) {
+ void copy( const path& f, const path& t ) {
+ boost::system::error_code ec;
try {
- boost::filesystem::copy( boost::filesystem::path(f), boost::filesystem::path(t) );
+ boost::filesystem::copy( boost::filesystem::path(f), boost::filesystem::path(t), ec );
} catch ( boost::system::system_error& e ) {
FC_THROW( "Copy from ${srcfile} to ${dstfile} failed because ${reason}",
("srcfile",f)("dstfile",t)("reason",e.what() ) );
@@ -252,18 +253,22 @@ namespace fc {
FC_THROW( "Copy from ${srcfile} to ${dstfile} failed",
("srcfile",f)("dstfile",t)("inner", fc::except_str() ) );
}
+ if( ec ) {
+ FC_THROW( "Copy from ${srcfile} to ${dstfile} failed because ${reason}",
+ ("srcfile",f)("dstfile",t)("reason", ec.category().name() ) );
+ }
}
- void resize_file( const path& f, size_t t )
- {
+ void resize_file( const path& f, size_t t )
+ {
try {
boost::filesystem::resize_file( f, t );
- }
+ }
catch ( boost::system::system_error& e )
{
FC_THROW( "Resize file '${f}' to size ${s} failed: ${reason}",
("f",f)("s",t)( "reason", e.what() ) );
- }
- catch ( ... )
+ }
+ catch ( ... )
{
FC_THROW( "Resize file '${f}' to size ${s} failed: ${reason}",
("f",f)("s",t)( "reason", fc::except_str() ) );
@@ -276,15 +281,15 @@ namespace fc {
void chmod( const path& p, int perm )
{
#ifndef WIN32
- mode_t actual_perm =
+ mode_t actual_perm =
((perm & 0400) ? S_IRUSR : 0)
| ((perm & 0200) ? S_IWUSR : 0)
| ((perm & 0100) ? S_IXUSR : 0)
-
+
| ((perm & 0040) ? S_IRGRP : 0)
| ((perm & 0020) ? S_IWGRP : 0)
| ((perm & 0010) ? S_IXGRP : 0)
-
+
| ((perm & 0004) ? S_IROTH : 0)
| ((perm & 0002) ? S_IWOTH : 0)
| ((perm & 0001) ? S_IXOTH : 0)
@@ -297,13 +302,13 @@ namespace fc {
return;
}
- void rename( const path& f, const path& t ) {
+ void rename( const path& f, const path& t ) {
try {
- boost::filesystem::rename( boost::filesystem::path(f), boost::filesystem::path(t) );
+ boost::filesystem::rename( boost::filesystem::path(f), boost::filesystem::path(t) );
} catch ( boost::system::system_error& ) {
try{
- boost::filesystem::copy( boost::filesystem::path(f), boost::filesystem::path(t) );
- boost::filesystem::remove( boost::filesystem::path(f));
+ boost::filesystem::copy( boost::filesystem::path(f), boost::filesystem::path(t) );
+ boost::filesystem::remove( boost::filesystem::path(f));
} catch ( boost::system::system_error& e ) {
FC_THROW( "Rename from ${srcfile} to ${dstfile} failed because ${reason}",
("srcfile",f)("dstfile",t)("reason",e.what() ) );
@@ -313,24 +318,24 @@ namespace fc {
("srcfile",f)("dstfile",t)("inner", fc::except_str() ) );
}
}
- void create_hard_link( const path& f, const path& t ) {
+ void create_hard_link( const path& f, const path& t ) {
try {
- boost::filesystem::create_hard_link( f, t );
+ boost::filesystem::create_hard_link( f, t );
} catch ( ... ) {
- FC_THROW( "Unable to create hard link from '${from}' to '${to}'",
+ FC_THROW( "Unable to create hard link from '${from}' to '${to}'",
( "from", f )("to",t)("exception", fc::except_str() ) );
}
}
- bool remove( const path& f ) {
+ bool remove( const path& f ) {
try {
- return boost::filesystem::remove( f );
+ return boost::filesystem::remove( f );
} catch ( ... ) {
FC_THROW( "Unable to remove '${path}'", ( "path", f )("exception", fc::except_str() ) );
}
}
- fc::path canonical( const fc::path& p ) {
+ fc::path canonical( const fc::path& p ) {
try {
- return boost::filesystem::canonical(p);
+ return boost::filesystem::canonical(p);
} catch ( ... ) {
FC_THROW( "Unable to resolve path '${path}'", ( "path", p )("exception", fc::except_str() ) );
}
@@ -477,7 +482,7 @@ namespace fc {
const fc::path& app_path()
{
#ifdef __APPLE__
- static fc::path appdir = [](){ return home_path() / "Library" / "Application Support"; }();
+ static fc::path appdir = [](){ return home_path() / "Library" / "Application Support"; }();
#elif defined( WIN32 )
static fc::path appdir = [](){
wchar_t app_data_dir[MAX_PATH];
@@ -499,7 +504,7 @@ namespace fc {
}
-#ifdef FC_HAS_SIMPLE_FILE_LOCK
+#ifdef FC_HAS_SIMPLE_FILE_LOCK
class simple_lock_file::impl
{
public:
@@ -517,7 +522,7 @@ namespace fc {
bool try_lock();
void unlock();
};
-
+
simple_lock_file::impl::impl(const path& lock_file_path) :
#ifdef _WIN32
file_handle(INVALID_HANDLE_VALUE),
@@ -527,7 +532,7 @@ namespace fc {
is_locked(false),
lock_file_path(lock_file_path)
{}
-
+
simple_lock_file::impl::~impl()
{
unlock();
diff --git a/libraries/fc/src/io/json.cpp b/libraries/fc/src/io/json.cpp
index 281634c3853..57c6462aa0c 100644
--- a/libraries/fc/src/io/json.cpp
+++ b/libraries/fc/src/io/json.cpp
@@ -13,13 +13,13 @@
namespace fc
{
// forward declarations of provided functions
- template variant variant_from_stream( T& in );
+ template variant variant_from_stream( T& in, uint32_t max_depth );
template char parseEscape( T& in );
template std::string stringFromStream( T& in );
template bool skip_white_space( T& in );
template std::string stringFromToken( T& in );
- template variant_object objectFromStream( T& in );
- template variants arrayFromStream( T& in );
+ template variant_object objectFromStream( T& in, uint32_t max_depth );
+ template variants arrayFromStream( T& in, uint32_t max_depth );
template variant number_from_stream( T& in );
template variant token_from_stream( T& in );
void escape_string( const std::string& str, std::ostream& os );
@@ -169,7 +169,7 @@ namespace fc
}
template
- variant_object objectFromStream( T& in )
+ variant_object objectFromStream( T& in, uint32_t max_depth )
{
mutable_variant_object obj;
try
@@ -180,7 +180,6 @@ namespace fc
"Expected '{', but read '${char}'",
("char",string(&c, &c + 1)) );
in.get();
- skip_white_space(in);
while( in.peek() != '}' )
{
if( in.peek() == ',' )
@@ -197,10 +196,10 @@ namespace fc
("key", key) );
}
in.get();
- auto val = variant_from_stream( in );
+ auto val = variant_from_stream( in, max_depth - 1 );
obj(std::move(key),std::move(val));
- skip_white_space(in);
+ //skip_white_space(in);
}
if( in.peek() == '}' )
{
@@ -220,7 +219,7 @@ namespace fc
}
template
- variants arrayFromStream( T& in )
+ variants arrayFromStream( T& in, uint32_t max_depth )
{
variants ar;
try
@@ -238,7 +237,7 @@ namespace fc
continue;
}
if( skip_white_space(in) ) continue;
- ar.push_back( variant_from_stream(in) );
+ ar.push_back( variant_from_stream( in, max_depth - 1) );
skip_white_space(in);
}
if( in.peek() != ']' )
@@ -307,7 +306,7 @@ namespace fc
{
}
std::string str = ss.str();
- if (str == "-." || str == ".") // check the obviously wrong things we could have encountered
+ if (str == "-." || str == "." || str == "-") // check the obviously wrong things we could have encountered
FC_THROW_EXCEPTION(parse_error_exception, "Can't parse token \"${token}\" as a JSON numeric constant", ("token", str));
if( dot )
return parser_type == json::legacy_parser_with_string_doubles ? variant(str) : variant(to_double(str));
@@ -388,8 +387,10 @@ namespace fc
template
- variant variant_from_stream( T& in )
+ variant variant_from_stream( T& in, uint32_t max_depth )
{
+ if( max_depth == 0 )
+ FC_THROW_EXCEPTION( parse_error_exception, "Too many nested items in JSON input!" );
skip_white_space(in);
variant var;
while( 1 )
@@ -406,9 +407,9 @@ namespace fc
case '"':
return stringFromStream( in );
case '{':
- return objectFromStream( in );
+ return objectFromStream( in, max_depth - 1 );
case '[':
- return arrayFromStream( in );
+ return arrayFromStream( in, max_depth - 1 );
case '-':
case '.':
case '0':
@@ -439,50 +440,27 @@ namespace fc
return variant();
}
-
- /** the purpose of this check is to verify that we will not get a stack overflow in the recursive descent parser */
- void check_string_depth( const string& utf8_str )
- {
- int32_t open_object = 0;
- int32_t open_array = 0;
- for( auto c : utf8_str )
- {
- switch( c )
- {
- case '{': open_object++; break;
- case '}': open_object--; break;
- case '[': open_array++; break;
- case ']': open_array--; break;
- default: break;
- }
- FC_ASSERT( open_object < 100 && open_array < 100, "object graph too deep", ("object depth",open_object)("array depth", open_array) );
- }
- }
-
- variant json::from_string( const std::string& utf8_str, parse_type ptype )
+ variant json::from_string( const std::string& utf8_str, parse_type ptype, uint32_t max_depth )
{ try {
- check_string_depth( utf8_str );
-
std::stringstream in( utf8_str );
//in.exceptions( std::ifstream::eofbit );
switch( ptype )
{
case legacy_parser:
- return variant_from_stream( in );
+ return variant_from_stream( in, max_depth );
case legacy_parser_with_string_doubles:
- return variant_from_stream( in );
+ return variant_from_stream( in, max_depth );
case strict_parser:
- return json_relaxed::variant_from_stream( in );
+ return json_relaxed::variant_from_stream( in, max_depth );
case relaxed_parser:
- return json_relaxed::variant_from_stream( in );
+ return json_relaxed::variant_from_stream( in, max_depth );
default:
FC_ASSERT( false, "Unknown JSON parser type {ptype}", ("ptype", ptype) );
}
} FC_RETHROW_EXCEPTIONS( warn, "", ("str",utf8_str) ) }
- variants json::variants_from_string( const std::string& utf8_str, parse_type ptype )
+ variants json::variants_from_string( const std::string& utf8_str, parse_type ptype, uint32_t max_depth )
{ try {
- check_string_depth( utf8_str );
variants result;
std::stringstream in( utf8_str );
//in.exceptions( std::ifstream::eofbit );
@@ -490,7 +468,7 @@ namespace fc
while( true )
{
// result.push_back( variant_from_stream( in ));
- result.push_back(json_relaxed::variant_from_stream( in ));
+ result.push_back(json_relaxed::variant_from_stream( in, max_depth ));
}
} catch ( const fc::eof_exception& ){}
return result;
@@ -678,10 +656,12 @@ namespace fc
to_stream(os, o, format );
return;
}
+ default:
+ FC_THROW_EXCEPTION( fc::invalid_arg_exception, "Unsupported variant type: " + v.get_type() );
}
}
- std::string json::to_string( const variant& v, output_formatting format /* = stringify_large_ints_and_doubles */ )
+ std::string json::to_string( const variant& v, output_formatting format )
{
std::stringstream ss;
fc::to_stream( ss, v, format );
@@ -779,16 +759,16 @@ namespace fc
- std::string json::to_pretty_string( const variant& v, output_formatting format /* = stringify_large_ints_and_doubles */ )
+ std::string json::to_pretty_string( const variant& v, output_formatting format )
{
- return pretty_print(to_string(v, format), 2);
+ return pretty_print(to_string(v, format), 2);
}
- void json::save_to_file( const variant& v, const fc::path& fi, bool pretty, output_formatting format /* = stringify_large_ints_and_doubles */ )
+ void json::save_to_file( const variant& v, const fc::path& fi, bool pretty, output_formatting format )
{
if( pretty )
{
- auto str = json::to_pretty_string( v, format );
+ auto str = json::to_pretty_string( v, format );
std::ofstream o(fi.generic_string().c_str());
o.write( str.c_str(), str.size() );
}
@@ -798,7 +778,7 @@ namespace fc
fc::to_stream( o, v, format );
}
}
- variant json::from_file( const fc::path& p, parse_type ptype )
+ variant json::from_file( const fc::path& p, parse_type ptype, uint32_t max_depth )
{
//auto tmp = std::make_shared( p, ifstream::binary );
//auto tmp = std::make_shared( p.generic_string().c_str(), std::ios::binary );
@@ -807,69 +787,69 @@ namespace fc
switch( ptype )
{
case legacy_parser:
- return variant_from_stream( bi );
+ return variant_from_stream( bi, max_depth );
case legacy_parser_with_string_doubles:
- return variant_from_stream( bi );
+ return variant_from_stream( bi, max_depth );
case strict_parser:
- return json_relaxed::variant_from_stream( bi );
+ return json_relaxed::variant_from_stream( bi, max_depth );
case relaxed_parser:
- return json_relaxed::variant_from_stream( bi );
+ return json_relaxed::variant_from_stream( bi, max_depth );
default:
FC_ASSERT( false, "Unknown JSON parser type {ptype}", ("ptype", ptype) );
}
}
/*
- variant json::from_stream( buffered_istream& in, parse_type ptype )
+ variant json::from_stream( buffered_istream& in, parse_type ptype, uint32_t max_depth )
{
switch( ptype )
{
case legacy_parser:
- return variant_from_stream( in );
+ return variant_from_stream( in, max_depth );
case legacy_parser_with_string_doubles:
- return variant_from_stream( in );
+ return variant_from_stream( in, max_depth );
case strict_parser:
- return json_relaxed::variant_from_stream( in );
+ return json_relaxed::variant_from_stream( in, max_depth );
case relaxed_parser:
- return json_relaxed::variant_from_stream( in );
+ return json_relaxed::variant_from_stream( in, max_depth );
default:
FC_ASSERT( false, "Unknown JSON parser type {ptype}", ("ptype", ptype) );
}
}
*/
- std::ostream& json::to_stream( std::ostream& out, const variant& v, output_formatting format /* = stringify_large_ints_and_doubles */ )
+ std::ostream& json::to_stream( std::ostream& out, const variant& v, output_formatting format )
{
fc::to_stream( out, v, format );
return out;
}
- std::ostream& json::to_stream( std::ostream& out, const variants& v, output_formatting format /* = stringify_large_ints_and_doubles */ )
+ std::ostream& json::to_stream( std::ostream& out, const variants& v, output_formatting format )
{
fc::to_stream( out, v, format );
return out;
}
- std::ostream& json::to_stream( std::ostream& out, const variant_object& v, output_formatting format /* = stringify_large_ints_and_doubles */ )
+ std::ostream& json::to_stream( std::ostream& out, const variant_object& v, output_formatting format )
{
fc::to_stream( out, v, format );
return out;
}
- bool json::is_valid( const std::string& utf8_str, parse_type ptype )
+ bool json::is_valid( const std::string& utf8_str, parse_type ptype, uint32_t max_depth )
{
if( utf8_str.size() == 0 ) return false;
std::stringstream in( utf8_str );
switch( ptype )
{
case legacy_parser:
- variant_from_stream( in );
+ variant_from_stream( in, max_depth );
break;
case legacy_parser_with_string_doubles:
- variant_from_stream( in );
+ variant_from_stream( in, max_depth );
break;
case strict_parser:
- json_relaxed::variant_from_stream( in );
+ json_relaxed::variant_from_stream( in, max_depth );
break;
case relaxed_parser:
- json_relaxed::variant_from_stream( in );
+ json_relaxed::variant_from_stream( in, max_depth );
break;
default:
FC_ASSERT( false, "Unknown JSON parser type {ptype}", ("ptype", ptype) );
diff --git a/libraries/fc/src/network/http/http_client.cpp b/libraries/fc/src/network/http/http_client.cpp
new file mode 100644
index 00000000000..409ff3eb8be
--- /dev/null
+++ b/libraries/fc/src/network/http/http_client.cpp
@@ -0,0 +1,365 @@
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+using tcp = boost::asio::ip::tcp; // from
+namespace http = boost::beast::http; // from
+namespace ssl = boost::asio::ssl; // from
+
+namespace fc {
+
+class http_client_impl {
+public:
+ using host_key = std::tuple;
+ using raw_socket_ptr = std::unique_ptr;
+ using ssl_socket_ptr = std::unique_ptr>;
+ using connection = static_variant;
+ using connection_map = std::map;
+ using error_code = boost::system::error_code;
+ using deadline_type = boost::posix_time::ptime;
+
+ http_client_impl()
+ :_ioc()
+ ,_sslc(ssl::context::sslv23_client)
+ {
+ set_verify_peers(true);
+ }
+
+ void add_cert(const std::string& cert_pem_string) {
+ error_code ec;
+ _sslc.add_certificate_authority(boost::asio::buffer(cert_pem_string.data(), cert_pem_string.size()), ec);
+ FC_ASSERT(!ec, "Failed to add cert: ${msg}", ("msg", ec.message()));
+ }
+
+ void set_verify_peers(bool enabled) {
+ if (enabled) {
+ _sslc.set_verify_mode(ssl::verify_peer);
+ } else {
+ _sslc.set_verify_mode(ssl::verify_none);
+ }
+ }
+
+ template
+ error_code sync_do_with_deadline( SyncReadStream& s, deadline_type deadline, Fn f, CancelFn cf ) {
+ bool timer_expired = false;
+ boost::asio::deadline_timer timer(s.get_io_service());
+
+ timer.expires_at(deadline);
+ bool timer_cancelled = false;
+ timer.async_wait([&timer_expired, &timer_cancelled] (const error_code&) {
+ // the only non-success error_code this is called with is operation_aborted but since
+ // we could have queued "success" when we cancelled the timer, we set a flag at the
+ // safer scope and only respect that.
+ if (!timer_cancelled) {
+ timer_expired = true;
+ }
+ });
+
+ optional f_result;
+ f(f_result);
+
+ s.get_io_service().restart();
+ while (s.get_io_service().run_one())
+ {
+ if (f_result) {
+ timer_cancelled = true;
+ timer.cancel();
+ } else if (timer_expired) {
+ cf();
+ }
+ }
+
+ if (!timer_expired) {
+ return *f_result;
+ } else {
+ return error_code(boost::system::errc::timed_out, boost::system::system_category());
+ }
+ }
+
+ template
+ error_code sync_do_with_deadline( SyncReadStream& s, deadline_type deadline, Fn f) {
+ return sync_do_with_deadline(s, deadline, f, [&s](){
+ s.lowest_layer().cancel();
+ });
+ };
+
+ template
+ error_code sync_connect_with_timeout( SyncReadStream& s, const std::string& host, const std::string& port, const deadline_type& deadline ) {
+ tcp::resolver local_resolver(s.get_io_service());
+ bool cancelled = false;
+
+ auto res = sync_do_with_deadline(s, deadline, [&local_resolver, &cancelled, &s, &host, &port](optional& final_ec){
+ local_resolver.async_resolve(host, port, [&cancelled, &s, &final_ec](const error_code& ec, tcp::resolver::results_type resolved ){
+ if (ec) {
+ final_ec.emplace(ec);
+ return;
+ }
+
+ if (!cancelled) {
+ boost::asio::async_connect(s, resolved.begin(), resolved.end(), [&final_ec](const error_code& ec, tcp::resolver::iterator ){
+ final_ec.emplace(ec);
+ });
+ }
+ });
+ },[&local_resolver, &cancelled](){
+ cancelled = true;
+ local_resolver.cancel();
+ });
+
+ return res;
+ };
+
+ template
+ error_code sync_write_with_timeout(SyncReadStream& s, http::request& req, const deadline_type& deadline ) {
+ return sync_do_with_deadline(s, deadline, [&s, &req](optional& final_ec){
+ http::async_write(s, req, [&final_ec]( const error_code& ec, std::size_t ) {
+ final_ec.emplace(ec);
+ });
+ });
+ }
+
+ template
+ error_code sync_read_with_timeout(SyncReadStream& s, boost::beast::flat_buffer& buffer, http::response& res, const deadline_type& deadline ) {
+ return sync_do_with_deadline(s, deadline, [&s, &buffer, &res](optional& final_ec){
+ http::async_read(s, buffer, res, [&final_ec]( const error_code& ec, std::size_t ) {
+ final_ec.emplace(ec);
+ });
+ });
+ }
+
+ host_key url_to_host_key( const url& dest ) {
+ FC_ASSERT(dest.host(), "Provided URL has no host");
+ uint16_t port = 80;
+ if (dest.port()) {
+ port = *dest.port();
+ }
+
+ return std::make_tuple(dest.proto(), *dest.host(), port);
+ }
+
+ connection_map::iterator create_raw_connection( const url& dest, const deadline_type& deadline ) {
+ auto key = url_to_host_key(dest);
+ auto socket = std::make_unique(_ioc);
+
+ error_code ec = sync_connect_with_timeout(*socket, *dest.host(), dest.port() ? std::to_string(*dest.port()) : "80", deadline);
+ FC_ASSERT(!ec, "Failed to connect: ${message}", ("message",ec.message()));
+
+ auto res = _connections.emplace(std::piecewise_construct,
+ std::forward_as_tuple(key),
+ std::forward_as_tuple(std::move(socket)));
+
+ return res.first;
+ }
+
+ connection_map::iterator create_ssl_connection( const url& dest, const deadline_type& deadline ) {
+ auto key = url_to_host_key(dest);
+ auto ssl_socket = std::make_unique>(_ioc, _sslc);
+
+ // Set SNI Hostname (many hosts need this to handshake successfully)
+ if(!SSL_set_tlsext_host_name(ssl_socket->native_handle(), dest.host()->c_str()))
+ {
+ error_code ec{static_cast(::ERR_get_error()), boost::asio::error::get_ssl_category()};
+ FC_THROW("Unable to set SNI Host Name: ${msg}", ("msg", ec.message()));
+ }
+
+ error_code ec = sync_connect_with_timeout(ssl_socket->next_layer(), *dest.host(), dest.port() ? std::to_string(*dest.port()) : "443", deadline);
+ if (!ec) {
+ ec = sync_do_with_deadline(ssl_socket->next_layer(), deadline, [&ssl_socket](optional& final_ec) {
+ ssl_socket->async_handshake(ssl::stream_base::client, [&final_ec](const error_code& ec) {
+ final_ec.emplace(ec);
+ });
+ });
+ }
+ FC_ASSERT(!ec, "Failed to connect: ${message}", ("message",ec.message()));
+
+ auto res = _connections.emplace(std::piecewise_construct,
+ std::forward_as_tuple(key),
+ std::forward_as_tuple(std::move(ssl_socket)));
+
+ return res.first;
+ }
+
+ connection_map::iterator create_connection( const url& dest, const deadline_type& deadline ) {
+ if (dest.proto() == "http") {
+ return create_raw_connection(dest, deadline);
+ } else if (dest.proto() == "https") {
+ return create_ssl_connection(dest, deadline);
+ } else {
+ FC_THROW("Unknown protocol ${proto}", ("proto", dest.proto()));
+ }
+ }
+
+ struct check_closed_visitor : public visitor {
+ bool operator() ( const raw_socket_ptr& ptr ) const {
+ return !ptr->is_open();
+ }
+
+ bool operator() ( const ssl_socket_ptr& ptr ) const {
+ return !ptr->lowest_layer().is_open();
+ }
+ };
+
+ bool check_closed( const connection_map::iterator& conn_itr ) {
+ if (conn_itr->second.visit(check_closed_visitor())) {
+ _connections.erase(conn_itr);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ connection_map::iterator get_connection( const url& dest, const deadline_type& deadline ) {
+ auto key = url_to_host_key(dest);
+ auto conn_itr = _connections.find(key);
+ if (conn_itr == _connections.end() || check_closed(conn_itr)) {
+ return create_connection(dest, deadline);
+ } else {
+ return conn_itr;
+ }
+ }
+
+ struct write_request_visitor : visitor {
+ write_request_visitor(http_client_impl* that, http::request& req, const deadline_type& deadline)
+ :that(that)
+ ,req(req)
+ ,deadline(deadline)
+ {}
+
+ template
+ error_code operator() ( S& stream ) const {
+ return that->sync_write_with_timeout(*stream, req, deadline);
+ }
+
+ http_client_impl* that;
+ http::request& req;
+ const deadline_type& deadline;
+ };
+
+ struct read_response_visitor : visitor {
+ read_response_visitor(http_client_impl* that, boost::beast::flat_buffer& buffer, http::response& res, const deadline_type& deadline)
+ :that(that)
+ ,buffer(buffer)
+ ,res(res)
+ ,deadline(deadline)
+ {}
+
+ template
+ error_code operator() ( S& stream ) const {
+ return that->sync_read_with_timeout(*stream, buffer, res, deadline);
+ }
+
+ http_client_impl* that;
+ boost::beast::flat_buffer& buffer;
+ http::response& res;
+ const deadline_type& deadline;
+ };
+
+ variant post_sync(const url& dest, const variant& payload, const fc::time_point& _deadline) {
+ static const deadline_type epoch(boost::gregorian::date(1970, 1, 1));
+ auto deadline = epoch + boost::posix_time::microseconds(_deadline.time_since_epoch().count());
+ FC_ASSERT(dest.host(), "No host set on URL");
+
+ string path = dest.path() ? dest.path()->generic_string() : "/";
+ if (dest.query()) {
+ path = path + "?" + *dest.query();
+ }
+
+ http::request req{http::verb::post, path, 11};
+ req.set(http::field::host, *dest.host());
+ req.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING);
+ req.set(http::field::content_type, "application/json");
+ req.keep_alive(true);
+ req.body() = json::to_string(payload);
+ req.prepare_payload();
+
+ auto conn_iter = get_connection(dest, deadline);
+ auto eraser = make_scoped_exit([this, &conn_iter](){
+ _connections.erase(conn_iter);
+ });
+
+ // Send the HTTP request to the remote host
+ error_code ec = conn_iter->second.visit(write_request_visitor(this, req, deadline));
+ FC_ASSERT(!ec, "Failed to send request: ${message}", ("message",ec.message()));
+
+ // This buffer is used for reading and must be persisted
+ boost::beast::flat_buffer buffer;
+
+ // Declare a container to hold the response
+ http::response res;
+
+ // Receive the HTTP response
+ ec = conn_iter->second.visit(read_response_visitor(this, buffer, res, deadline));
+ FC_ASSERT(!ec, "Failed to read response: ${message}", ("message",ec.message()));
+
+ // if the connection can be kept open, keep it open
+ if (res.keep_alive()) {
+ eraser.cancel();
+ }
+
+ auto result = json::from_string(res.body());
+ if (res.result() == http::status::internal_server_error) {
+ fc::exception_ptr excp;
+ try {
+ auto err_var = result.get_object()["error"].get_object();
+ excp = std::make_shared(err_var["code"].as_int64(), err_var["name"].as_string(), err_var["what"].as_string());
+
+ if (err_var.contains("details")) {
+ auto details = err_var["details"].get_array();
+ for (const auto dvar : details) {
+ excp->append_log(FC_LOG_MESSAGE(error, dvar.get_object()["message"].as_string()));
+ }
+ }
+ } catch( ... ) {
+
+ }
+
+ if (excp) {
+ throw *excp;
+ } else {
+ FC_THROW("Request failed with 500 response, but response was not parseable");
+ }
+ } else if (res.result() == http::status::not_found) {
+ FC_THROW("URL not found: ${url}", ("url", (std::string)dest));
+ }
+
+ return result;
+ }
+
+
+ boost::asio::io_context _ioc;
+ ssl::context _sslc;
+ connection_map _connections;
+};
+
+
+http_client::http_client()
+:_my(new http_client_impl())
+{
+
+}
+
+variant http_client::post_sync(const url& dest, const variant& payload, const fc::time_point& deadline) {
+ return _my->post_sync(dest, payload, deadline);
+}
+
+void http_client::add_cert(const std::string& cert_pem_string) {
+ _my->add_cert(cert_pem_string);
+}
+
+void http_client::set_verify_peers(bool enabled) {
+ _my->set_verify_peers(enabled);
+}
+
+http_client::~http_client() {
+
+}
+
+}
\ No newline at end of file
diff --git a/libraries/fc/src/network/http/http_connection.cpp b/libraries/fc/src/network/http/http_connection.cpp
deleted file mode 100644
index 59fb39b46a0..00000000000
--- a/libraries/fc/src/network/http/http_connection.cpp
+++ /dev/null
@@ -1,212 +0,0 @@
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-
-class fc::http::connection::impl
-{
- public:
- fc::tcp_socket sock;
- fc::ip::endpoint ep;
- impl() {
- }
-
- int read_until( char* buffer, char* end, char c = '\n' ) {
- char* p = buffer;
- // try {
- while( p < end && 1 == sock.readsome(p,1) ) {
- if( *p == c ) {
- *p = '\0';
- return (p - buffer)-1;
- }
- ++p;
- }
- // } catch ( ... ) {
- // elog("%s", fc::current_exception().diagnostic_information().c_str() );
- //elog( "%s", fc::except_str().c_str() );
- // }
- return (p-buffer);
- }
-
- fc::http::reply parse_reply() {
- fc::http::reply rep;
- try {
- std::vector line(1024*8);
- int s = read_until( line.data(), line.data()+line.size(), ' ' ); // HTTP/1.1
- s = read_until( line.data(), line.data()+line.size(), ' ' ); // CODE
- rep.status = static_cast(to_int64(fc::string(line.data())));
- s = read_until( line.data(), line.data()+line.size(), '\n' ); // DESCRIPTION
-
- while( (s = read_until( line.data(), line.data()+line.size(), '\n' )) > 1 ) {
- fc::http::header h;
- char* end = line.data();
- while( *end != ':' )++end;
- h.key = fc::string(line.data(),end);
- ++end; // skip ':'
- ++end; // skip space
- char* skey = end;
- while( *end != '\r' ) ++end;
- h.val = fc::string(skey,end);
- rep.headers.push_back(h);
- if( boost::iequals(h.key, "Content-Length") ) {
- rep.body.resize( static_cast(to_uint64( fc::string(h.val) ) ));
- }
- }
- if( rep.body.size() ) {
- sock.read( rep.body.data(), rep.body.size() );
- }
- return rep;
- } catch ( fc::exception& e ) {
- elog( "${exception}", ("exception",e.to_detail_string() ) );
- sock.close();
- rep.status = http::reply::InternalServerError;
- return rep;
- }
- }
-};
-
-
-
-namespace fc { namespace http {
-
- connection::connection()
- :my( new connection::impl() ){}
- connection::~connection(){}
-
-
-// used for clients
-void connection::connect_to( const fc::ip::endpoint& ep ) {
- my->sock.close();
- my->sock.connect_to( my->ep = ep );
-}
-
-http::reply connection::request( const fc::string& method,
- const fc::string& url,
- const fc::string& body, const headers& he ) {
-
- fc::url parsed_url(url);
- if( !my->sock.is_open() ) {
- wlog( "Re-open socket!" );
- my->sock.connect_to( my->ep );
- }
- try {
- fc::stringstream req;
- req << method <<" "<generic_string()<<" HTTP/1.1\r\n";
- req << "Host: "<<*parsed_url.host()<<"\r\n";
- req << "Content-Type: application/json\r\n";
- for( auto i = he.begin(); i != he.end(); ++i )
- {
- req << i->key <<": " << i->val<<"\r\n";
- }
- if( body.size() ) req << "Content-Length: "<< body.size() << "\r\n";
- req << "\r\n";
- fc::string head = req.str();
-
- my->sock.write( head.c_str(), head.size() );
- // fc::cerr.write( head.c_str() );
-
- if( body.size() ) {
- my->sock.write( body.c_str(), body.size() );
- // fc::cerr.write( body.c_str() );
- }
- // fc::cerr.flush();
-
- return my->parse_reply();
- } catch ( ... ) {
- my->sock.close();
- FC_THROW_EXCEPTION( exception, "Error Sending HTTP Request" ); // TODO: provide more info
- // return http::reply( http::reply::InternalServerError ); // TODO: replace with connection error
- }
-}
-
-// used for servers
-fc::tcp_socket& connection::get_socket()const {
- return my->sock;
-}
-
-http::request connection::read_request()const {
- http::request req;
- req.remote_endpoint = fc::variant(get_socket().remote_endpoint()).as_string();
- std::vector line(1024*8);
- int s = my->read_until( line.data(), line.data()+line.size(), ' ' ); // METHOD
- req.method = line.data();
- s = my->read_until( line.data(), line.data()+line.size(), ' ' ); // PATH
- req.path = line.data();
- s = my->read_until( line.data(), line.data()+line.size(), '\n' ); // HTTP/1.0
-
- while( (s = my->read_until( line.data(), line.data()+line.size(), '\n' )) > 1 ) {
- fc::http::header h;
- char* end = line.data();
- while( *end != ':' )++end;
- h.key = fc::string(line.data(),end);
- ++end; // skip ':'
- ++end; // skip space
- char* skey = end;
- while( *end != '\r' ) ++end;
- h.val = fc::string(skey,end);
- req.headers.push_back(h);
- if( boost::iequals(h.key, "Content-Length")) {
- auto s = static_cast(to_uint64( fc::string(h.val) ) );
- FC_ASSERT( s < 1024*1024 );
- req.body.resize( static_cast(to_uint64( fc::string(h.val) ) ));
- }
- if( boost::iequals(h.key, "Host") ) {
- req.domain = h.val;
- }
- }
- // TODO: some common servers won't give a Content-Length, they'll use
- // Transfer-Encoding: chunked. handle that here.
-
- if( req.body.size() ) {
- my->sock.read( req.body.data(), req.body.size() );
- }
- return req;
-}
-
-fc::string request::get_header( const fc::string& key )const {
- for( auto itr = headers.begin(); itr != headers.end(); ++itr ) {
- if( boost::iequals(itr->key, key) ) { return itr->val; }
- }
- return fc::string();
-}
-std::vector parse_urlencoded_params( const fc::string& f ) {
- int num_args = 0;
- for( size_t i = 0; i < f.size(); ++i ) {
- if( f[i] == '=' ) ++num_args;
- }
- std::vector h(num_args);
- int arg = 0;
- for( size_t i = 0; i < f.size(); ++i ) {
- while( f[i] != '=' && i < f.size() ) {
- if( f[i] == '%' ) {
- h[arg].key += char((fc::from_hex(f[i+1]) << 4) | fc::from_hex(f[i+2]));
- i += 3;
- } else {
- h[arg].key += f[i];
- ++i;
- }
- }
- ++i;
- while( i < f.size() && f[i] != '&' ) {
- if( f[i] == '%' ) {
- h[arg].val += char((fc::from_hex(f[i+1]) << 4) | fc::from_hex(f[i+2]));
- i += 3;
- } else {
- h[arg].val += f[i] == '+' ? ' ' : f[i];
- ++i;
- }
- }
- ++arg;
- }
- return h;
-}
-
-} } // fc::http
diff --git a/libraries/fc/src/network/http/http_server.cpp b/libraries/fc/src/network/http/http_server.cpp
deleted file mode 100644
index 648fc548e3a..00000000000
--- a/libraries/fc/src/network/http/http_server.cpp
+++ /dev/null
@@ -1,207 +0,0 @@
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-
-namespace fc { namespace http {
-
- class server::response::impl : public fc::retainable
- {
- public:
- impl( const fc::http::connection_ptr& c, const std::function& cont = std::function() )
- :body_bytes_sent(0),body_length(0),con(c),handle_next_req(cont)
- {}
-
- void send_header() {
- //ilog( "sending header..." );
- fc::stringstream ss;
- ss << "HTTP/1.1 " << rep.status << " ";
- switch( rep.status ) {
- case fc::http::reply::OK: ss << "OK\r\n"; break;
- case fc::http::reply::RecordCreated: ss << "Record Created\r\n"; break;
- case fc::http::reply::NotFound: ss << "Not Found\r\n"; break;
- case fc::http::reply::Found: ss << "Found\r\n"; break;
- default: ss << "Internal Server Error\r\n"; break;
- }
- for( uint32_t i = 0; i < rep.headers.size(); ++i ) {
- ss << rep.headers[i].key <<": "<get_socket().write( s.c_str(), s.size() );
- }
-
- http::reply rep;
- int64_t body_bytes_sent;
- uint64_t body_length;
- http::connection_ptr con;
- std::function handle_next_req;
- };
-
-
- class server::impl
- {
- public:
- impl(){}
-
- impl(const fc::ip::endpoint& p )
- {
- tcp_serv.set_reuse_address();
- tcp_serv.listen(p);
- accept_complete = fc::async([this](){ this->accept_loop(); }, "http_server accept_loop");
- }
-
- ~impl()
- {
- try
- {
- tcp_serv.close();
- if (accept_complete.valid())
- accept_complete.wait();
- }
- catch (...)
- {
- }
-
- for (fc::future& request_in_progress : requests_in_progress)
- {
- try
- {
- request_in_progress.cancel_and_wait();
- }
- catch (const fc::exception& e)
- {
- wlog("Caught exception while canceling http request task: ${error}", ("error", e));
- }
- catch (const std::exception& e)
- {
- wlog("Caught exception while canceling http request task: ${error}", ("error", e.what()));
- }
- catch (...)
- {
- wlog("Caught unknown exception while canceling http request task");
- }
- }
- requests_in_progress.clear();
- }
-
- void accept_loop()
- {
- while( !accept_complete.canceled() )
- {
- http::connection_ptr con = std::make_shared();
- tcp_serv.accept( con->get_socket() );
- //ilog( "Accept Connection" );
- // clean up futures for any completed requests
- for (auto iter = requests_in_progress.begin(); iter != requests_in_progress.end();)
- if (!iter->valid() || iter->ready())
- iter = requests_in_progress.erase(iter);
- else
- ++iter;
- requests_in_progress.emplace_back(fc::async([=](){ handle_connection(con, on_req); }, "http_server handle_connection"));
- }
- }
-
- void handle_connection( const http::connection_ptr& c,
- std::function do_on_req )
- {
- try
- {
- http::server::response rep( fc::shared_ptr( new response::impl(c) ) );
- request req = c->read_request();
- if( do_on_req )
- do_on_req( req, rep );
- c->get_socket().close();
- }
- catch ( fc::exception& e )
- {
- wlog( "unable to read request ${1}", ("1", e.to_detail_string() ) );//fc::except_str().c_str());
- }
- //wlog( "done handle connection" );
- }
-
- fc::future accept_complete;
- std::function on_req;
- std::vector > requests_in_progress;
- fc::tcp_server tcp_serv;
- };
-
-
-
- server::server():my( new impl() ){}
- server::server( uint16_t port ) :my( new impl(fc::ip::endpoint( fc::ip::address(),port)) ){}
- server::server( server&& s ):my(fc::move(s.my)){}
-
- server& server::operator=(server&& s) { fc_swap(my,s.my); return *this; }
-
- server::~server(){}
-
- void server::listen( const fc::ip::endpoint& p )
- {
- my.reset( new impl(p) );
- }
-
- fc::ip::endpoint server::get_local_endpoint() const
- {
- return my->tcp_serv.get_local_endpoint();
- }
-
-
- server::response::response(){}
- server::response::response( const server::response& s ):my(s.my){}
- server::response::response( server::response&& s ):my(fc::move(s.my)){}
- server::response::response( const fc::shared_ptr& m ):my(m){}
-
- server::response& server::response::operator=(const server::response& s) { my = s.my; return *this; }
- server::response& server::response::operator=(server::response&& s) { fc_swap(my,s.my); return *this; }
-
- void server::response::add_header( const fc::string& key, const fc::string& val )const {
- my->rep.headers.push_back( fc::http::header( key, val ) );
- }
- void server::response::set_status( const http::reply::status_code& s )const {
- if( my->body_bytes_sent != 0 ) {
- wlog( "Attempt to set status after sending headers" );
- }
- my->rep.status = s;
- }
- void server::response::set_length( uint64_t s )const {
- if( my->body_bytes_sent != 0 ) {
- wlog( "Attempt to set length after sending headers" );
- }
- my->body_length = s;
- }
- void server::response::write( const char* data, uint64_t len )const {
- if( my->body_bytes_sent + len > my->body_length ) {
- wlog( "Attempt to send to many bytes.." );
- len = my->body_bytes_sent + len - my->body_length;
- }
- if( my->body_bytes_sent == 0 ) {
- my->send_header();
- }
- my->body_bytes_sent += len;
- my->con->get_socket().write( data, static_cast(len) );
- if( my->body_bytes_sent == int64_t(my->body_length) ) {
- if( false || my->handle_next_req ) {
- ilog( "handle next request..." );
- //fc::async( std::function(my->handle_next_req) );
- fc::async( my->handle_next_req, "http_server handle_next_req" );
- }
- }
- }
-
- server::response::~response(){}
-
- void server::on_request( const std::function& cb )
- {
- my->on_req = cb;
- }
-
-
-
-
-} }
diff --git a/libraries/fc/src/network/url.cpp b/libraries/fc/src/network/url.cpp
index 635dd2d68c4..6ff7522465d 100644
--- a/libraries/fc/src/network/url.cpp
+++ b/libraries/fc/src/network/url.cpp
@@ -63,6 +63,7 @@ namespace fc
if( _args.valid() && _args->size() )
{
// TODO: args = fc::move(_args);
+ _query = fc::move(_largs);
}
}
@@ -71,6 +72,7 @@ namespace fc
ostring _user;
ostring _pass;
opath _path;
+ ostring _query;
ovariant_object _args;
fc::optional _port;
};
@@ -99,6 +101,7 @@ namespace fc
if( my->_host.valid() ) ss<<*my->_host;
if( my->_port.valid() ) ss<<":"<<*my->_port;
if( my->_path.valid() ) ss<_path->generic_string();
+ if( my->_query.valid() ) ss<<"?"<<*my->_query;
// if( my->_args ) ss<<"?"<<*my->_args;
return ss.str();
}
@@ -185,6 +188,10 @@ namespace fc
{
return my->_path;
}
+ ostring url::query()const
+ {
+ return my->_query;
+ }
ovariant_object url::args()const
{
return my->_args;
diff --git a/libraries/fc/vendor/websocketpp/websocketpp/impl/connection_impl.hpp b/libraries/fc/vendor/websocketpp/websocketpp/impl/connection_impl.hpp
index cdf2a9ffe63..a4ff96cc847 100644
--- a/libraries/fc/vendor/websocketpp/websocketpp/impl/connection_impl.hpp
+++ b/libraries/fc/vendor/websocketpp/websocketpp/impl/connection_impl.hpp
@@ -1326,6 +1326,8 @@ void connection::write_http_response(lib::error_code const & ec) {
}
}
+ m_response.replace_header("Connection", "close");
+
// have the processor generate the raw bytes for the wire (if it exists)
if (m_processor) {
m_handshake_buffer = m_processor->get_raw(m_response);
diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt
index 5325a3ae78b..f3c0d05d85d 100644
--- a/plugins/CMakeLists.txt
+++ b/plugins/CMakeLists.txt
@@ -2,6 +2,7 @@ add_subdirectory(bnet_plugin)
add_subdirectory(net_plugin)
add_subdirectory(net_api_plugin)
add_subdirectory(http_plugin)
+add_subdirectory(http_client_plugin)
add_subdirectory(chain_plugin)
add_subdirectory(chain_api_plugin)
add_subdirectory(producer_plugin)
diff --git a/plugins/chain_plugin/chain_plugin.cpp b/plugins/chain_plugin/chain_plugin.cpp
index 7208e6c51ec..368756828e1 100644
--- a/plugins/chain_plugin/chain_plugin.cpp
+++ b/plugins/chain_plugin/chain_plugin.cpp
@@ -294,9 +294,12 @@ void chain_plugin::plugin_initialize(const variables_map& options) {
my->chain_config->reversible_cache_size,
my->chain_config->blocks_dir/config::reversible_blocks_dir_name ) ) {
ilog("Reversible blocks database was not corrupted. Copying from backup to blocks directory.");
- fc::copy( backup_dir/config::reversible_blocks_dir_name, my->chain_config->blocks_dir/config::reversible_blocks_dir_name );
- fc::copy( backup_dir/"reversible/shared_memory.bin", my->chain_config->blocks_dir/"reversible/shared_memory.bin" );
- fc::copy( backup_dir/"reversible/shared_memory.meta", my->chain_config->blocks_dir/"reversible/shared_memory.meta" );
+ fc::copy( backup_dir / config::reversible_blocks_dir_name,
+ my->chain_config->blocks_dir / config::reversible_blocks_dir_name );
+ fc::copy( backup_dir / config::reversible_blocks_dir_name / "shared_memory.bin",
+ my->chain_config->blocks_dir/ config::reversible_blocks_dir_name / "shared_memory.bin" );
+ fc::copy( backup_dir / config::reversible_blocks_dir_name / "shared_memory.meta",
+ my->chain_config->blocks_dir/ config::reversible_blocks_dir_name / "shared_memory.meta" );
}
}
} else if( options.at("replay-blockchain").as() ) {
diff --git a/plugins/http_client_plugin/CMakeLists.txt b/plugins/http_client_plugin/CMakeLists.txt
new file mode 100644
index 00000000000..48ae140fca6
--- /dev/null
+++ b/plugins/http_client_plugin/CMakeLists.txt
@@ -0,0 +1,7 @@
+file(GLOB HEADERS "include/eosio/http_client_plugin/*.hpp")
+add_library( http_client_plugin
+ http_client_plugin.cpp
+ ${HEADERS} )
+
+target_link_libraries( http_client_plugin appbase fc )
+target_include_directories( http_client_plugin PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" )
diff --git a/plugins/http_client_plugin/http_client_plugin.cpp b/plugins/http_client_plugin/http_client_plugin.cpp
new file mode 100644
index 00000000000..886c5f13ebf
--- /dev/null
+++ b/plugins/http_client_plugin/http_client_plugin.cpp
@@ -0,0 +1,60 @@
+/**
+ * @file
+ * @copyright defined in eos/LICENSE.txt
+ */
+#include
+#include
+#include
+
+namespace eosio {
+
+http_client_plugin::http_client_plugin():my(new http_client()){}
+http_client_plugin::~http_client_plugin(){}
+
+void http_client_plugin::set_program_options(options_description&, options_description& cfg) {
+ cfg.add_options()
+ ("https-client-root-cert", boost::program_options::value>()->composing()->multitoken(),
+ "PEM encoded trusted root certificate (or path to file containing one) used to validate any TLS connections made. (may specify multiple times)\n")
+ ("https-client-validate-peers", boost::program_options::value()->default_value(true),
+ "true: validate that the peer certificates are valid and trusted, false: ignore cert errors")
+ ;
+
+}
+
+void http_client_plugin::plugin_initialize(const variables_map& options) {
+ if ( options.count("https-client-root-cert") ) {
+ const std::vector root_pems = options["https-client-root-cert"].as>();
+ for (const auto& root_pem : root_pems) {
+ std::string pem_str = root_pem;
+ if (!boost::algorithm::starts_with(pem_str, "-----BEGIN CERTIFICATE-----\n")) {
+ try {
+ auto infile = std::ifstream(pem_str);
+ std::stringstream sstr;
+ sstr << infile.rdbuf();
+ pem_str = sstr.str();
+ FC_ASSERT(boost::algorithm::starts_with(pem_str, "-----BEGIN CERTIFICATE-----\n"), "File does not appear to be a PEM encoded certificate");
+ } catch (const fc::exception& e) {
+ elog("Failed to read PEM ${f} : ${e}", ("f", root_pem)("e",e.to_detail_string()));
+ }
+ }
+
+ try {
+ my->add_cert(pem_str);
+ } catch (const fc::exception& e) {
+ elog("Failed to read PEM : ${e} \n${pem}\n", ("pem", pem_str)("e",e.to_detail_string()));
+ }
+ }
+ }
+
+ my->set_verify_peers(options.at("https-client-validate-peers").as());
+}
+
+void http_client_plugin::plugin_startup() {
+
+}
+
+void http_client_plugin::plugin_shutdown() {
+
+}
+
+}
diff --git a/plugins/http_client_plugin/include/eosio/http_client_plugin/http_client_plugin.hpp b/plugins/http_client_plugin/include/eosio/http_client_plugin/http_client_plugin.hpp
new file mode 100644
index 00000000000..b4bb8a5740e
--- /dev/null
+++ b/plugins/http_client_plugin/include/eosio/http_client_plugin/http_client_plugin.hpp
@@ -0,0 +1,34 @@
+/**
+ * @file
+ * @copyright defined in eos/LICENSE.txt
+ */
+#pragma once
+#include
+#include
+
+namespace eosio {
+ using namespace appbase;
+ using fc::http_client;
+
+ class http_client_plugin : public appbase::plugin
+ {
+ public:
+ http_client_plugin();
+ virtual ~http_client_plugin();
+
+ APPBASE_PLUGIN_REQUIRES()
+ virtual void set_program_options(options_description&, options_description& cfg) override;
+
+ void plugin_initialize(const variables_map& options);
+ void plugin_startup();
+ void plugin_shutdown();
+
+ http_client& get_client() {
+ return *my;
+ }
+
+ private:
+ std::unique_ptr my;
+ };
+
+}
diff --git a/plugins/net_plugin/net_plugin.cpp b/plugins/net_plugin/net_plugin.cpp
index cf95eb61950..49f19351ecc 100644
--- a/plugins/net_plugin/net_plugin.cpp
+++ b/plugins/net_plugin/net_plugin.cpp
@@ -1188,7 +1188,7 @@ namespace eosio {
pending_message_buffer.peek(&b, 1, index);
which |= uint32_t(uint8_t(b) & 0x7f) << by;
by += 7;
- } while( uint8_t(b) & 0x80 );
+ } while( uint8_t(b) & 0x80 && by < 32);
if (which == uint64_t(net_message::tag::value)) {
blk_buffer.resize(message_length);
@@ -2055,7 +2055,7 @@ namespace eosio {
uint32_t message_length;
auto index = conn->pending_message_buffer.read_index();
conn->pending_message_buffer.peek(&message_length, sizeof(message_length), index);
- if(message_length > def_send_buffer_size*2) {
+ if(message_length > def_send_buffer_size*2 || message_length == 0) {
elog("incoming message length unexpected (${i})", ("i", message_length));
close(conn);
return;
diff --git a/plugins/producer_plugin/CMakeLists.txt b/plugins/producer_plugin/CMakeLists.txt
index c9fb7ec01e3..d7f9188d5bb 100644
--- a/plugins/producer_plugin/CMakeLists.txt
+++ b/plugins/producer_plugin/CMakeLists.txt
@@ -5,6 +5,6 @@ add_library( producer_plugin
${HEADERS}
)
-target_link_libraries( producer_plugin chain_plugin appbase eosio_chain eos_utilities )
+target_link_libraries( producer_plugin chain_plugin http_client_plugin appbase eosio_chain eos_utilities )
target_include_directories( producer_plugin
PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" "${CMAKE_CURRENT_SOURCE_DIR}/../chain_interface/include" )
diff --git a/plugins/producer_plugin/include/eosio/producer_plugin/producer_plugin.hpp b/plugins/producer_plugin/include/eosio/producer_plugin/producer_plugin.hpp
index be6efe79171..33a10f9c221 100644
--- a/plugins/producer_plugin/include/eosio/producer_plugin/producer_plugin.hpp
+++ b/plugins/producer_plugin/include/eosio/producer_plugin/producer_plugin.hpp
@@ -6,6 +6,7 @@
#pragma once
#include
+#include
#include
@@ -15,7 +16,7 @@ using boost::signals2::signal;
class producer_plugin : public appbase::plugin {
public:
- APPBASE_PLUGIN_REQUIRES((chain_plugin))
+ APPBASE_PLUGIN_REQUIRES((chain_plugin)(http_client_plugin))
struct runtime_options {
fc::optional max_transaction_time;
diff --git a/plugins/producer_plugin/producer_plugin.cpp b/plugins/producer_plugin/producer_plugin.cpp
index 464e112e271..2ba9ffd2da0 100644
--- a/plugins/producer_plugin/producer_plugin.cpp
+++ b/plugins/producer_plugin/producer_plugin.cpp
@@ -121,7 +121,8 @@ class producer_plugin_impl : public std::enable_shared_from_this _private_keys;
+ using signature_provider_type = std::function;
+ std::map _signature_providers;
std::set _producers;
boost::asio::deadline_timer _timer;
std::map _producer_watermarks;
@@ -131,6 +132,7 @@ class producer_plugin_impl : public std::enable_shared_from_thisblock_signing_key );
- if( private_key_itr != _private_keys.end() ) {
+ auto private_key_itr = _signature_providers.find( itr->block_signing_key );
+ if( private_key_itr != _signature_providers.end() ) {
auto d = bsp->sig_digest();
- auto sig = private_key_itr->second.sign( d );
+ auto sig = private_key_itr->second( d );
_last_signed_block_time = bsp->header.timestamp;
_last_signed_block_num = bsp->block_num;
@@ -412,21 +414,30 @@ void producer_plugin::set_program_options(
("pause-on-startup,x", boost::program_options::bool_switch()->notifier([this](bool p){my->_pause_production = p;}), "Start this node in a state where production is paused")
("max-transaction-time", bpo::value()->default_value(30),
"Limits the maximum time (in milliseconds) that is allowed a pushed transaction's code to execute before being considered invalid")
- ("max-irreversible-block-age", bpo::value()->default_value( 30 * 60 ),
- "Limits the maximum age (in seconds) of the DPOS Irreversible Block for a chain this node will produce blocks on")
+ ("max-irreversible-block-age", bpo::value()->default_value( -1 ),
+ "Limits the maximum age (in seconds) of the DPOS Irreversible Block for a chain this node will produce blocks on (use negative value to indicate unlimited)")
("producer-name,p", boost::program_options::value>()->composing()->multitoken(),
"ID of producer controlled by this node (e.g. inita; may specify multiple times)")
- ("private-key", boost::program_options::value>()->composing()->multitoken()->default_value({fc::json::to_string(private_key_default)},
- fc::json::to_string(private_key_default)),
- "Tuple of [public key, WIF private key] (may specify multiple times)")
+ ("private-key", boost::program_options::value>()->composing()->multitoken(),
+ "(DEPRECATED - Use signature-provider instead) Tuple of [public key, WIF private key] (may specify multiple times)")
+ ("signature-provider", boost::program_options::value>()->composing()->multitoken()->default_value({std::string(default_priv_key.get_public_key()) + "=KEY:" + std::string(default_priv_key)}, std::string(default_priv_key.get_public_key()) + "=KEY:" + std::string(default_priv_key)),
+ "Key=Value pairs in the form =\n"
+ "Where:\n"
+ " \tis a string form of a vaild EOSIO public key\n\n"
+ "