epm 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 71968fbf0b3c65f40ed5f98a9340c3de0b6c9f57
4
+ data.tar.gz: d8be28a9138e03c27ade4091e79aa6c4558ef3a3
5
+ SHA512:
6
+ metadata.gz: b63fc02ea393ff5a9d09590231193b41daa16756e792c627936a27375996e4692df19b807e50dc3e783adf17386c0ee72cb30ea0b0161772c08861f6b1113438
7
+ data.tar.gz: c7cff450ec22cc08ea6a98e509127ffdf8b4313f8c129a292a3f0422f5b858fdbb52c18769054ce8a22a233f77d45fc22cce12bf02464bfa4d4f5ed519dcc40d
data/.gitignore ADDED
@@ -0,0 +1,19 @@
1
+ .ruby*
2
+ *.gem
3
+ *.rbc
4
+ .bundle
5
+ .config
6
+ .yardoc
7
+ Gemfile.lock
8
+ InstalledFiles
9
+ _yardoc
10
+ coverage
11
+ doc/
12
+ lib/bundler/man
13
+ pkg
14
+ rdoc
15
+ spec/reports
16
+ test/tmp
17
+ test/version_tmp
18
+ tmp
19
+ coverage
data/.travis.yml ADDED
@@ -0,0 +1,15 @@
1
+ language: ruby
2
+ rvm:
3
+ - "1.9.3"
4
+ - "2.0.0"
5
+ - "2.1.1"
6
+ - jruby-19mode
7
+ - jruby-20mode
8
+
9
+ notifications:
10
+ email:
11
+ on_failure: change
12
+ slack:
13
+ rooms:
14
+ - douglas:CkaMdC9JhYYG1NVbRXnu6xLc#general
15
+ - douglas:CkaMdC9JhYYG1NVbRXnu6xLc#infrastructure
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/LICENSE.md ADDED
@@ -0,0 +1,23 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 Watershed Legal Service, PLLC
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
22
+
23
+ In other words, don't be a jerk.
data/README.md ADDED
@@ -0,0 +1,166 @@
1
+ # Introduction
2
+
3
+ EPM is a package (provision?) manager. It is meant to simplify the management of git hosted repositories which contain Ethereum standard or customized contracts. This package manager should work in the way which most package managers operate -- with the addition that it will be able to interact with the Ethereum BlockChain.
4
+
5
+ In addition to installing, uninstalling, updating, and upgrading your packages for you, the Gem will also act as a hub for different Ethereum contract building, testing, simulating, and deploying mechanisms.
6
+
7
+ The package manager builds in a standard tipping system which is -- by convention -- built to allow tipping of the EPM system as well as the other tools which developers use to build, test, and deploy their contracts onto the Ethereum BlockChain. The tipping system is on by default as a mechanism to assist in further development of Ethereum contract deployment products. It can, of course, be turned off (this is open source software).
8
+
9
+ # Installing
10
+
11
+ This is a Ruby gem and will require that you have Ruby on your system (unless and until someone ports this to Python or Node). Once you have ensured that you have Ruby on your system, `gem install epm`.
12
+
13
+ # Using
14
+
15
+ The gem is a command line tool. All of the commands are built to run primarily from the command line. Of course the gem will integrate as a Ruby gem into your Ruby application, but primarily it is meant to work from the command line.
16
+
17
+ ## Contract Tools Features
18
+
19
+ `epm install` -- used like brew install to install a particular Ethereum tool. Use in conjuction with the `-l` or `--local` flag to install the tool as the local tool only for this particular project. Otherwise will install the tool as a global user tool.
20
+
21
+ `epm uninstall` -- used like brew uninstall to uninstall a particular Ethereum tool. Same restrictions for the `-l` or `--local` flag as with `epm install` are applicable to `epm uninstall`.
22
+
23
+ `epm upgrade` -- used like brew upgrade to upgrade a particular Ethereum tool. Same restrictions for the `-l` or `--local` flag as with `epm install` are applicable to `epm upgrade`.
24
+
25
+ `epm list` -- list installable tools.
26
+
27
+ `epm list-installed` -- list currently installed tools.
28
+
29
+ ## Package Management Features
30
+
31
+ `epm pull` -- will pull contract provisions, contracts, or packages of contracts based on the contract definition files in the project folder. If used without calling any contract definition file after `epm pull` will pull all the necessary components for all of the contract definition files viewable from the project root. If used with a contract definition file after `epm pull` will pull all the necessary components for the contract definition file.
32
+
33
+ `epm push` -- will push contract provisions, contracts, or packages of contracts assembled in the project root to the repository noted in the local configuration file's `repository` setting
34
+
35
+ `epm update` -- will pull updates to the contract provisions, contracts, or packages of contracts based on the contract definition files in the project folder. Can be used with or without a contract definition file as with `epm pull`.
36
+
37
+ ## Contract Workflow Features
38
+
39
+ `epm make` -- used to pull Ethereum provisions, contracts, or packaged and build out the application or package(s) in this project based on the contract definition files. If used without calling a particular contract definition file after `epm make` will make all the contract definition files visible from the project root (which is where epm make should be called from). If used with a particular contract definition file after `epm make` will only make that particular contract definition.
40
+
41
+ `epm test` -- used to test Ethereum contracts based upon the tester included in the global or local configuration file.
42
+
43
+ `epm simulate` -- used to simulate Ethereum contracts or sets of contracts based upon the simulator included in the global or locla configuration file.
44
+
45
+ `epm deploy` -- used to deploy contracts to the Ethereum blockchain.
46
+
47
+ `epm update-deployed` -- used to send a command to currently running contracts on the Ethereum blockchain to update themselves based on the git diff between the most recent commit of the project repository and the current commit when the contracts were deployed to the blockchain.
48
+
49
+ `epm destroy` -- used to send a suicide command to all of the contracts in the Ethereum blockchain which are derived from the project root.
50
+
51
+ ## EPM Self-Reflective Features
52
+
53
+ `epm configure-local` -- open the local configuration file in the default editor.
54
+
55
+ `epm configure-global` -- open the global configuration file in the default editor.
56
+
57
+ `epm self-update` -- update the EPM tool to the latest version.
58
+
59
+ `epm implode` -- remove EPM entirely.
60
+
61
+ ## Package Management Features
62
+
63
+ `epm install` --
64
+
65
+ `epm pull` --
66
+
67
+ `epm push` --
68
+
69
+ `epm destroy` --
70
+
71
+ `epm update` --
72
+
73
+ `epm list` --
74
+
75
+ ## Contract Workflow Features
76
+
77
+ `epm make` --
78
+
79
+ `epm test` --
80
+
81
+ `epm simulate` --
82
+
83
+ `epm deploy` --
84
+
85
+ # Configuration Options
86
+
87
+ EPM uses what should be a fairly approachable two configuration layers approach to managing configurations. The first level which the gem will look at will be the `~/.epm/config.epm` file. These are the user global configurations. The global configurations will be overwritten by local configuration files in the config.epm file of the root directory of the project you are working on (for the time being epm should be called from this directory). The config.epm file is a [TOML](https://github.com/mojombo/toml) formated configuration file with the following options.
88
+
89
+ ## Global Configuration Options
90
+
91
+ `editor` -- String denoting the path which EPM should call in order to edit the contract. Default: shell environment's editor.
92
+
93
+ `linter` -- String denoting the path which EPM should call in order to lint a contract. Default: ???
94
+
95
+ `tester` -- String denoting the path which EPM should call in order to run your test suite. Default: ???
96
+
97
+ `simulator` -- String denoting the path which EPM should call in order to start the simulator. Default: ???
98
+
99
+ `compiler` -- String denoting the path which EPM should call in order to compile the contract into the byte language for deployment to the Ethereum BlockChain. Default: ???
100
+
101
+ `blacklisted-repos` -- Array of strings denoting github or other git repos which are Blacklisted. Default: []
102
+
103
+ `deployer-keys` -- String denoting the public key of the deploying coder|lawyer -- which some or all contracts can use to ensure a tip is sent to the deployer.
104
+
105
+ `infrastructure-keys` -- Array of strings denoting the public keys of the testers, linters, simulators, package managers, and other infrastructure which the deployer used to assist in the deployment of the contract. Strings should be in the form `KEY:AMOUNT:MESSAGE` where KEY is the public hash which the contract will send the tip and where AMOUNT is the **percentage** of the tip which will go to this key. MESSAGE is the signing message of the tip and is optional.
106
+
107
+ ## Local Configuration Options
108
+
109
+ The local configuration options include *all* of the global configuration options, and local configuration options will override the global configuration options. In addition, there are a few local configuration options which are not read by the global config file.
110
+
111
+ `name` -- String denoting the name of the package. If the package contains one contract the package and the contract will be the same thing. If the package contains more than one contract then the package will include all of the contracts.
112
+
113
+ `author` -- String denoting the author of the package.
114
+
115
+ `author-address` -- String denoting the Ethereum address of the author of the package (used for tipping system when others reuse the contract or package).
116
+
117
+ `repository` -- String denoting the remote git repository for the package. When the user calls `epm push` EPM will send the package to this address.
118
+
119
+ # Contract and Package Definition Files
120
+
121
+ EPM uses contract definition files to build and maintain contracts. Contract definition files are TOML files.
122
+
123
+ ## Package Definition Files
124
+
125
+ Define the contracts used in the package and the relationships between them. TODO.
126
+
127
+ ## Contract Definition Files -- Shortform
128
+
129
+ The shortform contract definition allows coder|lawyers to pull in \*.ethereum-contract files to the working folder to be tested, simulated, and deployed from established git repositories.
130
+
131
+ EPM will pull from any git repository, but it will default to github repositories, so when you send it the following repository: `watershedlegal/ethereum-boilerplate-prefaces` it will know that that is a github address. If you would like to add a private repository or a bitbucket or any other repository simply add the full address to the line. If the repository contains multiple `.ethereum-contract` files and you only want one of those files, you can state the contract you want EPM to pull into the working directory by specifying that instead of the repository in the `XXXXXXX.ethereum-definition` file.
132
+
133
+ The `XXXX.ethereum-definition` file will simply be a list of the repositories or contract files which EPM should import into the working directory's repo folder. After that it will be up to the coder|lawyer to build the contracts into a working network or meta contract, test, simulate, and deploy.
134
+
135
+ ## Contract Definition Files -- Longform
136
+
137
+ The longform contract definition allows coder|lawyers to pull in pieces of contracts from different sources and have EPM attempt to assemble a cohesive contract in which the lawyer|coder can then edit before linting, testing, simulating, and deploying.
138
+
139
+ As with the shortform contract definitions, EPM will pull from any repository based on the rules described above. Addresses may point to the entire repository, in which case EPM will pull in all \*.ethereum-provision files. If only one file is wanted for the preface section, that file path can be specified after the repository address. In addition, if only certain line numbers of a certain file are desired to be pulled in then EPM will know to look for that when you add the following string: `REPONAME/FILEPATH:STARTLINE_ENDLINE` where STARTLINE and ENDLINE are the line numbers which you would like to be pulled in.
140
+
141
+ The contract definition file is also a TOML formatted configuration file. There are three sections to the contract definition file (which by convention should be XXXXX.ethereum-definition where XXXX is the name of the contract):
142
+
143
+ 1. `provisions` -- Array of strings denoting the repository addresses which EPM will pull from and formulate into the main provisions of this contract.
144
+ 2. `constants` -- Array of KEY:VALUE pairs which set the constant values after building a contract.
145
+ 3. `tip-amount` -- Integer denoting the amount of ether to be distributed to the infrastructure network which helped you build and deploy this contract or system of contracts.
146
+ 4. `constants` -- Array of KEY:VALUE pairs which set the constant values after building a contract.
147
+ 5. `tip-amount` -- Integer denoting the amount of ether to be distributed to the infrastructure network which helped you build and deploy this contract or system of contracts.
148
+
149
+ # Roadmap / TODO
150
+
151
+ - [ ] Everything
152
+
153
+ # Contributing
154
+
155
+ 1. Fork the repository.
156
+ 2. Create your feature branch (`git checkout -b my-new-feature`).
157
+ 3. Add Tests (and feel free to help here since I don't (yet) really know how to do that.).
158
+ 4. Commit your changes (`git commit -am 'Add some feature'`).
159
+ 5. Push to the branch (`git push origin my-new-feature`).
160
+ 6. Create new Pull Request.
161
+
162
+ # License
163
+
164
+ MIT License - (c) 2014 - Watershed Legal Services, PLLC. All copyrights are owned by [Watershed Legal Services, PLLC](http://watershedlegal.com).
165
+
166
+ See License file.
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
data/bin/epm ADDED
@@ -0,0 +1,90 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # == USAGE
4
+ # epm subcommand [file]
5
+ require '../lib/epm.rb'
6
+ # args = ARGV
7
+ # EPM::parse args
8
+
9
+ require 'commander/import'
10
+
11
+ program :version, EPM.version
12
+ program :description, 'Ethereum Package Manager assists in the management of Ethereum Packages and Tools to ease developers workflows.'
13
+
14
+ ##
15
+ ## Package Workflow Commands
16
+ ##
17
+ command :compile do |c|
18
+ c.syntax = 'epm compile'
19
+ c.description = 'Compile an ethereum contract and return the byte code array.'
20
+ c.action do |args|
21
+ result = EPM.compile(args)
22
+ result.each{|l| print l + "\n"}
23
+ end
24
+ end
25
+
26
+ command :create do |c|
27
+ c.syntax = 'epm create'
28
+ c.description = 'Compile an ethereum contract and deploy to the blockchain.'
29
+ c.action do |args|
30
+ result = EPM.create(args)
31
+ result.each{|l| print l + "\n"}
32
+ end
33
+ end
34
+
35
+ command :deploy do |c|
36
+ c.syntax = 'epm deploy'
37
+ c.description = 'Compile and deploy a system of contracts to the blockchain. See gem README for EPM package-definition file syntax.'
38
+ c.action do |args|
39
+ EPM.deploy(args)
40
+ end
41
+ end
42
+
43
+ ##
44
+ ## EPM Tools
45
+ ##
46
+ command :transact do |c|
47
+ c.syntax = 'epm transact'
48
+ c.description = 'Send a transaction to a contract. Note this is to work with contracts, it will not (by default) send ether.'
49
+ c.action do |args|
50
+ print "Transaction Sent.\n"
51
+ end
52
+ end
53
+
54
+ command :query do |c|
55
+ c.syntax = 'epm query'
56
+ c.description = 'Query a storage position of a contract currently on the blockchain.'
57
+ c.action do |args|
58
+ print EPM.query(args) + "\n"
59
+ end
60
+ end
61
+
62
+ command :start do |c|
63
+ c.syntax = 'epm start'
64
+ c.description = 'Start your default ethereum server.'
65
+ c.action do
66
+ print "Please be patient, this will take a few seconds.\n"
67
+ EPM.start
68
+ print "Server has started.\n"
69
+ end
70
+ end
71
+
72
+ command :stop do |c|
73
+ c.syntax = 'epm stop'
74
+ c.description = 'Stop your default ethereum server.'
75
+ c.action do
76
+ EPM.stop
77
+ print "Server has stopped.\n"
78
+ end
79
+ end
80
+
81
+ command :restart do |c|
82
+ c.syntax = 'epm restart'
83
+ c.summary = ''
84
+ c.description = 'Restart your default ethereum server.'
85
+ c.action do
86
+ print "Please be patient, this will take a few seconds.\n"
87
+ EPM.restart
88
+ print "Server has been restarted.\n"
89
+ end
90
+ end
data/epm.gemspec ADDED
@@ -0,0 +1,28 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'epm/version'
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "epm"
8
+ s.version = VERSION
9
+ s.platform = Gem::Platform::RUBY
10
+ s.summary = "Ethereum Contracts Package Manager."
11
+ s.homepage = "https://github.com/ethereum-package-manager/epm"
12
+ s.authors = [ "Casey Kuhlman" ]
13
+ s.email = "caseykuhlman@watershedlegal.com"
14
+
15
+ s.date = Time.now.strftime('%Y-%m-%d')
16
+ s.has_rdoc = false
17
+
18
+ s.files = `git ls-files`.split($/)
19
+ s.executables = s.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
20
+ s.test_files = s.files.grep(%r{^(test|spec|features)/})
21
+ s.require_paths = ["lib"]
22
+
23
+ s.add_dependency "commander", "~> 4.1.6"
24
+
25
+ s.description = <<desc
26
+ This gem is designed to assist in distribution, dissemination, compilation, and deployment of Ethereum contracts.
27
+ desc
28
+ end
data/lib/epm.rb ADDED
@@ -0,0 +1,81 @@
1
+ #!/usr/bin/env ruby
2
+ # std_lib
3
+ require 'fileutils'
4
+ require 'tempfile'
5
+ require 'shellwords'
6
+ require 'json'
7
+ require 'net/http'
8
+ require 'uri'
9
+ require 'optparse'
10
+
11
+ # this gem
12
+ Dir[File.dirname(__FILE__) + '/epm/*.rb'].each {|file| require file }
13
+
14
+ module EPM
15
+ extend self
16
+
17
+ def compile args
18
+ output = []
19
+ until args.empty?
20
+ file = args.shift
21
+ settings = setup
22
+ output << EPM::Compile.new(file, settings).compile
23
+ end
24
+ output
25
+ end
26
+
27
+ def create args
28
+ output = []
29
+ until args.empty?
30
+ file = args.shift
31
+ settings = setup
32
+ output << EPM::Create.new(file, settings).deploy
33
+ end
34
+ output
35
+ end
36
+
37
+ def deploy args
38
+ output = []
39
+ until args.empty?
40
+ file = args.shift
41
+ settings = setup
42
+ output << EPM::Deploy.new(file, settings).deploy_package
43
+ end
44
+ output
45
+ end
46
+
47
+ def transact args
48
+ recipient = args.shift
49
+ data = args
50
+ settings = setup
51
+ EPM::Transact.new(recipient, data, settings).transact
52
+ end
53
+
54
+ def query args
55
+ address = args.shift
56
+ position = args.shift
57
+ settings = setup
58
+ EPM::Query.new(address, position, settings).query
59
+ end
60
+
61
+ def version
62
+ return VERSION
63
+ end
64
+
65
+ def start
66
+ EPM::Server.start
67
+ end
68
+
69
+ def stop
70
+ EPM::Server.stop
71
+ end
72
+
73
+ def restart
74
+ EPM::Server.stop
75
+ EPM::Server.start
76
+ end
77
+
78
+ def setup
79
+ return EPM::Settings.check
80
+ end
81
+ end
@@ -0,0 +1,41 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ module EPM
4
+ class Compile
5
+ def initialize file, settings={}
6
+ @file = EPM::FileHelpers.file_guard file
7
+ @settings = settings
8
+ end
9
+
10
+ def compile
11
+ if @file
12
+ if File.extname(@file) == '.lll'
13
+ return compile_lll
14
+ elsif File.extname(@file) == ('.mu' || '.mut')
15
+ return compile_mutan
16
+ elsif File.extname(@file) == ('.se' || '.ser')
17
+ return compile_serpent
18
+ end
19
+ end
20
+ end
21
+
22
+ def compile_lll
23
+ contract = `#{@settings["path-to-lllc"]} #{@file}`
24
+ contract.chomp!
25
+ contract = EPM::HexData.hex_guard contract
26
+ return contract
27
+ end
28
+
29
+ def compile_serpent
30
+ contract = `#{@settings['path-to-serpent']} #{Shellwords.escape(@file)}`
31
+ contract.chomp!
32
+ return EPM::HexData.hex_guard contract
33
+ end
34
+
35
+ def compile_mutan
36
+ contract = `#{@settings['path-to-mutan']} #{Shellwords.escape(@file)}`
37
+ contract.chomp!
38
+ return EPM::HexData.hex_guard contract
39
+ end
40
+ end
41
+ end
data/lib/epm/create.rb ADDED
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ module EPM
4
+ class Create
5
+ def initialize file, settings={}
6
+ if file
7
+ @uri = URI.parse "http://localhost:#{settings['json-port']}"
8
+ @settings = settings
9
+ @contract = EPM::Compile.new(file, @settings).compile
10
+ end
11
+ end
12
+
13
+ def deploy
14
+ if @settings['preferred-client'] == 'cpp'
15
+ params = {
16
+ 'sec' => @settings["address-private-key"],
17
+ 'xEndowment' => '',
18
+ 'bCode' => @contract,
19
+ 'xGas' => '100000',
20
+ 'xGasPrice' => '100000000000000'
21
+ }
22
+ post_body = { 'method' => 'create', 'params' => params, 'id' => 'epm-rpc', "jsonrpc" => "2.0" }.to_json
23
+ elsif @settings['preferred-client'] == ('go' || 'ethereal')
24
+ params = {
25
+ 'body' => @contract,
26
+ 'value' => '',
27
+ 'gas' => '100000',
28
+ 'gasprice' => '100000000000000'
29
+ }
30
+ post_body = { 'method' => 'EthereumApi.Create', 'params' => params, 'id' => 'epm-rpc', 'jsonrpc' => '2.0'}.to_json
31
+ end
32
+ return EPM::Server.http_post_request @uri, post_body
33
+ end
34
+ end
35
+ end
data/lib/epm/deploy.rb ADDED
@@ -0,0 +1,126 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ module EPM
4
+ class Deploy
5
+ def initialize def_file, settings={}
6
+ @dirname = File.dirname(File.absolute_path(def_file))
7
+ @log_file = File.join(ENV['HOME'], '.epm', 'deployed-log.csv')
8
+ @settings = settings
9
+ @brain = {}
10
+ @def_file = def_file
11
+ end
12
+
13
+ def deploy_package
14
+ if @def_file
15
+ commands = File.readlines @def_file
16
+ commands = commands.reject{|cmd| cmd[/\A#/] || cmd[/\A$/]}.map{|cmd| cmd.gsub("\n",'')}
17
+ commands = commands.inject([]) do |arr,ele|
18
+ ele[/\A\S+/] ? arr << [ele] : arr[-1] << ele.strip.split(' => ')
19
+ arr
20
+ end
21
+ commands.each do |cmd|
22
+ dowit = cmd.shift
23
+ case dowit
24
+ when 'deploy:'
25
+ deploy cmd.shift
26
+ sleep 1
27
+ when 'modify-deploy:'
28
+ modify_deploy cmd
29
+ sleep 1
30
+ when 'transact:'
31
+ transact cmd.shift
32
+ sleep 1
33
+ when 'query:'
34
+ query cmd.shift
35
+ when 'log:'
36
+ log cmd.shift
37
+ when 'set:'
38
+ set_var cmd.shift
39
+ end
40
+ end
41
+ end
42
+ end
43
+
44
+ def deploy command
45
+ deploy_k = command.shift
46
+ k_name = command.shift
47
+ p "Deploying #{deploy_k} with name of #{k_name.gsub(/(\{|\})/,'')}."
48
+ k_address = EPM::Create.new(File.join(@dirname, deploy_k), @settings).deploy
49
+ @brain[k_name] = k_address
50
+ p "#{k_name} => #{k_address}"
51
+ end
52
+
53
+ def modify_deploy command
54
+ deploy_k = command[0].shift
55
+ deploy_k = EPM::FileHelpers.file_guard(File.join(@dirname, deploy_k))
56
+ k_name = command[0].shift
57
+ dump = command.shift
58
+ until command.empty?
59
+ cmd = command.shift
60
+ to_replace = cmd.shift
61
+ replacer = cmd.shift
62
+ until ! replacer[/(\{\{.*?\}\})/]
63
+ replacer.gsub!($1, @brain[$1])
64
+ end
65
+ k_value = File.read deploy_k
66
+ k_value = k_value.gsub "#{to_replace}", "#{replacer}"
67
+ File.open(deploy_k, 'w'){|f| f.write k_value}
68
+ end
69
+ p "After modifying, am deploying #{deploy_k} with name of #{k_name.gsub(/(\{|\})/,'')}."
70
+ k_address = EPM::Create.new(deploy_k, @settings).deploy
71
+ @brain[k_name] = k_address
72
+ p "#{k_name} => #{k_address}"
73
+ end
74
+
75
+ def transact command
76
+ recipient = command.shift
77
+ until ! recipient[/(\{\{.*?\}\})/]
78
+ recipient.gsub!($1, @brain[$1])
79
+ end
80
+ data = command.shift
81
+ until ! data[/(\{\{.*?\}\})/]
82
+ data.gsub!($1,@brain[$1])
83
+ end
84
+ data = data.split(' ')
85
+ p "Sending #{recipient} the data: #{data}."
86
+ EPM::Transact.new(recipient, data, @settings).transact
87
+ end
88
+
89
+ def query command
90
+ contract = command.shift
91
+ address = command.shift
92
+ name = command.shift
93
+ until ! contract[/(\{\{.*?\}\})/]
94
+ contract.gsub!($1,@brain[$1])
95
+ end
96
+ until ! address[/(\{\{.*?\}\})/]
97
+ address.gsub!($1,@brain[$1])
98
+ end
99
+ p "Querying #{contract} at: #{address}."
100
+ storage = EPM::Query.new(contract, address, @settings).query
101
+ p "#{contract}:#{address} => #{storage}"
102
+ @brain[name] = storage
103
+ end
104
+
105
+ def log command
106
+ address = command.shift
107
+ name = command.shift
108
+ until ! address[/(\{\{.*?\}\})/]
109
+ address.gsub!($1,@brain[$1])
110
+ end
111
+ until ! name[/(\{\{.*?\}\})/]
112
+ name.gsub!($1,@brain[$1])
113
+ end
114
+ log_entry = [address, name].join(',')
115
+ p "Logging [#{address},#{name}]"
116
+ `echo #{log_entry} >> #{@log_file}`
117
+ end
118
+
119
+ def set_var command
120
+ key = command.shift
121
+ value = command.shift
122
+ p "Setting #{key} to #{value}"
123
+ @brain[key] = value
124
+ end
125
+ end
126
+ end
data/lib/epm/query.rb ADDED
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ module EPM
4
+ class Query
5
+ def initialize address, position, settings={}
6
+ @uri = URI.parse "http://localhost:#{settings['json-port']}"
7
+ @settings = settings
8
+ @address = EPM::HexData.hex_guard address
9
+ @position = EPM::HexData.hex_guard position
10
+ end
11
+
12
+ def query
13
+ if @settings['preferred-client'] == 'cpp'
14
+ params = {
15
+ 'a' => @address,
16
+ 'x' => @position
17
+ }
18
+ post_body = { 'method' => 'storageAt', 'params' => params, 'id' => 'epm-rpc', "jsonrpc" => "2.0" }.to_json
19
+ elsif @settings['preferred-client'] == ('go' || 'ethereal')
20
+ params = {
21
+ 'address' => @address,
22
+ 'key' => @position
23
+ }
24
+ post_body = { 'method' => 'EthereumApi.GetStorageAt', 'params' => params, 'id' => 'epm-rpc', "jsonrpc" => "2.0" }.to_json
25
+ end
26
+ return EPM::Server.http_post_request @uri, post_body
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,36 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ module EPM
4
+ class Transact
5
+ def initialize recipient, data, settings={}
6
+ @uri = URI.parse "http://localhost:#{settings['json-port']}"
7
+ @settings = settings
8
+ @recipient = EPM::HexData.hex_guard recipient
9
+ @data = EPM::HexData.construct_data data
10
+ end
11
+
12
+ def transact
13
+ if @settings['preferred-client'] == 'cpp'
14
+ params = {
15
+ 'sec' => @settings["address-private-key"],
16
+ 'xValue' => '',
17
+ 'aDest' => @recipient,
18
+ 'bData' => @data,
19
+ 'xGas' => '100000',
20
+ 'xGasPrice' => '100000000000000'
21
+ }
22
+ post_body = { 'method' => 'transact', 'params' => params, 'id' => 'epm-rpc', "jsonrpc" => "2.0" }.to_json
23
+ elsif @settings['preferred-client'] == ('go' || 'ethereal')
24
+ params = {
25
+ 'recipient' => @recipient,
26
+ 'value' => '',
27
+ 'gas' => '100000',
28
+ 'gasprice' => '100000000000000',
29
+ 'body' => @data,
30
+ }
31
+ post_body = { 'method' => 'EthereumApi.Transact', 'params' => params, 'id' => 'epm-rpc', "jsonrpc" => "2.0" }.to_json
32
+ end
33
+ return EPM::Server.http_post_request @uri, post_body
34
+ end
35
+ end
36
+ end
data/lib/epm/utils.rb ADDED
@@ -0,0 +1,154 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ module EPM
4
+ module Server
5
+ extend self
6
+
7
+ def start debug=false
8
+ settings = EPM::Settings.check
9
+ if debug
10
+ debug = ''
11
+ else
12
+ debug = '>> /dev/null'
13
+ end
14
+
15
+ unless is_eth_running?
16
+ case settings['preferred-client']
17
+ when 'cpp'
18
+ server = "#{settings["path-to-eth"]} --json-rpc-port #{settings['json-port']} -r #{settings["remote"]} -d #{settings["directory"]} -m off -l #{settings["eth-listen-port"]} -c #{settings["name"]} -s #{settings["address-private-key"]} #{debug}"
19
+ when 'go'
20
+ server = "#{settings['path-to-go-ethereum']}"
21
+ when 'ethereal'
22
+ server = "#{settings['path-to-ethereal']}"
23
+ end
24
+ pid = spawn server
25
+ sleep 7
26
+ end
27
+ return pid
28
+ end
29
+
30
+ def stop
31
+ if is_eth_running?
32
+ processes = eth_processes.map{|e| e.split(' ')[1]}
33
+ processes.each{|p| `kill #{p}`}
34
+ end
35
+ end
36
+
37
+ def is_eth_running?
38
+ eth = eth_processes
39
+ return (! eth.empty?)
40
+ end
41
+
42
+ def eth_processes
43
+ a = `ps ux`.split("\n").select{|e| e[/eth --json-rpc-port/]}
44
+ # a << `ps ux`.split("\n").select{|e| e[/ethereum/]}
45
+ a << `ps ux`.split("\n").select{|e| e[/ethereal/]}
46
+ a = a.flatten
47
+ return a
48
+ end
49
+
50
+ def http_post_request uri, post_body
51
+ unless is_eth_running?
52
+ p "Ethereum RPC Server is not running. Starting now. Please be patient for it to load."
53
+ start
54
+ end
55
+ http = Net::HTTP.new uri.host, uri.port
56
+ request = Net::HTTP::Post.new uri.request_uri
57
+ request.content_type = 'application/json'
58
+ request.body = post_body
59
+ result = JSON.parse(http.request(request).body)['result']
60
+ return result
61
+ end
62
+ end
63
+
64
+ module Settings
65
+ extend self
66
+
67
+ def check
68
+ install_setup_file unless have_setup_file
69
+ return load_settings
70
+ end
71
+
72
+ def have_setup_file
73
+ settings_file = File.join(ENV['HOME'], '.epm', 'epm-rpc.json')
74
+ File.exists? settings_file
75
+ end
76
+
77
+ def install_setup_file
78
+ settings_example = File.join(File.dirname(__FILE__), '..', '..', 'settings', 'epm-rpc.json')
79
+ settings_file = File.join(ENV['HOME'], '.epm', 'epm-rpc.json')
80
+ unless Dir.exists? File.dirname settings_file
81
+ FileUtils.mkdir(File.dirname settings_file)
82
+ end
83
+ FileUtils.cp settings_example, settings_file
84
+ end
85
+
86
+ def install_log_file
87
+ log_file = File.join(ENV['HOME'], '.epm', 'deployed-log.csv')
88
+ unless File.exists? log_file
89
+ File.open(log_file, "w") {}
90
+ end
91
+ return log_file
92
+ end
93
+
94
+ def load_settings
95
+ settings_file = File.join(ENV['HOME'], '.epm', 'epm-rpc.json')
96
+ settings = JSON.parse(File.read(settings_file))
97
+ log_file = install_log_file
98
+ settings["log_file"] = log_file
99
+ return settings
100
+ end
101
+ end
102
+
103
+ module HexData
104
+ extend self
105
+
106
+ def hex_guard data
107
+ if data[0..1] != "0x"
108
+ data = "0x" + data
109
+ end
110
+ return data
111
+ end
112
+
113
+ def construct_data deconstructed_data
114
+ data = "0x"
115
+ deconstructed_data.each do |bits|
116
+ if bits[0..1] == "0x"
117
+ piece = bits[2..-1]
118
+ piece = piece.rjust(64,'0')
119
+ else
120
+ piece = bits.unpack('c*').map{|s| s.to_s(16)}.join('')
121
+ piece = piece.ljust(64,'0')
122
+ end
123
+ data << piece
124
+ end
125
+ return data
126
+ end
127
+ end
128
+
129
+ module FileHelpers
130
+ extend self
131
+
132
+ def file_guard file
133
+ contents = File.read file
134
+ dir = File.dirname(File.absolute_path(file))
135
+ unless dir == '/tmp'
136
+ include_pattern = /(\(include \")(\..*)(\"\))/
137
+ if contents[include_pattern]
138
+ included = File.join(dir, $2)
139
+ included = $1 + included + $3
140
+ contents.gsub!(include_pattern, included)
141
+ end
142
+ save_temp_file contents, file
143
+ else
144
+ return file
145
+ end
146
+ end
147
+
148
+ def save_temp_file contents, file
149
+ tmp = Tempfile.new ['epm', File.extname(file)]
150
+ File.open(tmp, 'w'){|f| f.write contents}
151
+ return tmp.path
152
+ end
153
+ end
154
+ end
@@ -0,0 +1 @@
1
+ VERSION = "0.3.1"
@@ -0,0 +1,17 @@
1
+ {
2
+ "path-to-ruby": "ruby",
3
+ "path-to-eth": "/opt/cpp-ethereum/build/eth/eth", // cpp client
4
+ "path-to-ethereal": "ethereal",
5
+ "path-to-go-ethereum": "ethereum",
6
+ "path-to-lllc": "/opt/cpp-ethereum/build/lllc/lllc",
7
+ "path-to-mutan": "mutan",
8
+ "path-to-serpent": "serpent",
9
+ "preferred-client": "cpp", // can also use `go` <- which will run go headless or `ethereal` <- qt go client.
10
+ "json-port": "9090",
11
+ "remote": "remote", // this would typically be the default peer server for your client variant
12
+ "directory": "~/.ethereum", // in cpp world Aleth defaults to this so change to a different directory to run eth headless in
13
+ "eth-listen-port": "30303", // see the comment above
14
+ "name": "name", // this is the client name
15
+ "address-public-key": "0xact",
16
+ "address-private-key": "0xsec"
17
+ }
@@ -0,0 +1,15 @@
1
+ {
2
+ (include "./test2.lll")
3
+ (def 'DOUG 0x9c0182658c9d57928b06d3ee20bb2b619a9cbf7b)
4
+ (def 'BAindicator 0x10)
5
+ [[BAindicator]]0x88554646BA
6
+ [[69]] (caller)
7
+ [[0xDEADBEEF]]DOUG
8
+ (return 0 (lll
9
+ (when (= (caller) @@69)
10
+ (for {} (< @i (calldatasize)) [i](+ @i 64)
11
+ [[ (calldataload @i) ]] (calldataload (+ @i 32))
12
+ )
13
+ )
14
+ 0))
15
+ }
@@ -0,0 +1,16 @@
1
+ # Package Name: EPM Test
2
+ # Package Author: Casey Kuhlman
3
+ # Package Email: casey@projectdouglas.org
4
+ # Package Repository: https://github.com/ethereum-package-manager/epm
5
+
6
+ deploy:
7
+ test.lll => {{DOUG}}
8
+ modify-deploy:
9
+ test.lll => {{rep}}
10
+ (def 'DOUG 0x9c0182658c9d57928b06d3ee20bb2b619a9cbf7b) => (def 'DOUG {{DOUG}})
11
+ transact:
12
+ {{DOUG}} => rep {{rep}}
13
+ query:
14
+ {{DOUG}} => 0x7265700000000000000000000000000000000000000000000000000000000000 => {{KEYVALSTORE}}
15
+ log:
16
+ {{KEYVALSTORE}} => {{rep}}
@@ -0,0 +1,3 @@
1
+ {
2
+ [[0x12]]0xFFFFFFF
3
+ }
metadata ADDED
@@ -0,0 +1,81 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: epm
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.1
5
+ platform: ruby
6
+ authors:
7
+ - Casey Kuhlman
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-06-11 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: commander
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 4.1.6
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 4.1.6
27
+ description: |2
28
+ This gem is designed to assist in distribution, dissemination, compilation, and deployment of Ethereum contracts.
29
+ email: caseykuhlman@watershedlegal.com
30
+ executables:
31
+ - epm
32
+ extensions: []
33
+ extra_rdoc_files: []
34
+ files:
35
+ - ".gitignore"
36
+ - ".travis.yml"
37
+ - Gemfile
38
+ - LICENSE.md
39
+ - README.md
40
+ - Rakefile
41
+ - bin/epm
42
+ - epm.gemspec
43
+ - lib/epm.rb
44
+ - lib/epm/compile.rb
45
+ - lib/epm/create.rb
46
+ - lib/epm/deploy.rb
47
+ - lib/epm/query.rb
48
+ - lib/epm/transact.rb
49
+ - lib/epm/utils.rb
50
+ - lib/epm/version.rb
51
+ - settings/epm-rpc.json
52
+ - spec/fixtures/test.lll
53
+ - spec/fixtures/test.package-definition
54
+ - spec/fixtures/test2.lll
55
+ homepage: https://github.com/ethereum-package-manager/epm
56
+ licenses: []
57
+ metadata: {}
58
+ post_install_message:
59
+ rdoc_options: []
60
+ require_paths:
61
+ - lib
62
+ required_ruby_version: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: '0'
67
+ required_rubygems_version: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ version: '0'
72
+ requirements: []
73
+ rubyforge_project:
74
+ rubygems_version: 2.2.2
75
+ signing_key:
76
+ specification_version: 4
77
+ summary: Ethereum Contracts Package Manager.
78
+ test_files:
79
+ - spec/fixtures/test.lll
80
+ - spec/fixtures/test.package-definition
81
+ - spec/fixtures/test2.lll