universum 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e2c8f33d68ea490e3785c31d1cca9977af498602
4
- data.tar.gz: d7ac8121bc501b8339954fdc0c23111c4c5d60d8
3
+ metadata.gz: db4bf31c857f63ae6e203d9ddcdb718556c6f2a7
4
+ data.tar.gz: 3989ec1e3962f0768a8a3c108e72a76b4c4b969b
5
5
  SHA512:
6
- metadata.gz: fbcfc8ea96b55f557636649078b665554464b5009f411cc6208890a4b4f558a633198321d796093b0b1e0cfa31bd58154064d2112576258ffdbf4ed97b065687
7
- data.tar.gz: 03a36a8c12c2ff2e88789028b4c978c1ed3d60d909d773b1fb79592a9212b819e2712ce3e2dd82682b250d80b608c3d6cc61880ecadd589a1d14722c63f8c36d
6
+ metadata.gz: 276c1b77f06cf0e0dcb10a7a4ca4ef072365f1852c30e5b83279582f4d38447ad178c975c9e169e40aef5871a8d830cd8748d371c9d5846f3fd3211fe251ed07
7
+ data.tar.gz: 7086a5e4984497cc116ee05eb397a34afc7e766474e5aacc802421a37c16c5c4031936dae03fbdecd8b9172c5d990c52391dc3a18b14620d4ae92b26e46405e4
data/Manifest.txt CHANGED
@@ -4,14 +4,30 @@ Manifest.txt
4
4
  README.md
5
5
  Rakefile
6
6
  lib/universum.rb
7
+ lib/universum/account.rb
8
+ lib/universum/address.rb
9
+ lib/universum/contract.rb
7
10
  lib/universum/enum.rb
8
11
  lib/universum/event.rb
12
+ lib/universum/function.rb
13
+ lib/universum/receipt.rb
14
+ lib/universum/safe_array.rb
15
+ lib/universum/safe_hash.rb
16
+ lib/universum/transaction.rb
17
+ lib/universum/type.rb
18
+ lib/universum/units_money.rb
19
+ lib/universum/units_time.rb
9
20
  lib/universum/universum.rb
10
21
  lib/universum/version.rb
11
22
  test/contracts/greeter.rb
12
23
  test/contracts/mytoken.rb
13
24
  test/helper.rb
25
+ test/test_array.rb
14
26
  test/test_enum.rb
15
27
  test/test_event.rb
16
28
  test/test_greeter.rb
29
+ test/test_hash.rb
30
+ test/test_struct.rb
31
+ test/test_units_money.rb
32
+ test/test_units_time.rb
17
33
  test/test_version.rb
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- New to Universum? See the [Universum (World Computer) White Paper](https://github.com/openblockchains/universum/blob/master/WHITEPAPER.md)!
1
+ New to Universum? See the [Universum (World Computer) White Paper](https://github.com/s6ruby/universum/blob/master/WHITEPAPER.md)!
2
2
 
3
3
 
4
4
 
@@ -7,8 +7,8 @@ New to Universum? See the [Universum (World Computer) White Paper](https://githu
7
7
  next generation ethereum 2.0 world computer runtime - run contract scripts / transactions in plain vanilla / standard ruby on the blockchain - update the (contract-protected / isolated) world states with plain vanilla / standard SQL
8
8
 
9
9
 
10
- * home :: [github.com/openblockchains/universum](https://github.com/openblockchains/universum)
11
- * bugs :: [github.com/openblockchains/universum/issues](https://github.com/openblockchains/universum/issues)
10
+ * home :: [github.com/s6ruby/universum](https://github.com/s6ruby/universum)
11
+ * bugs :: [github.com/s6ruby/universum/issues](https://github.com/s6ruby/universum/issues)
12
12
  * gem :: [rubygems.org/gems/universum](https://rubygems.org/gems/universum)
13
13
  * rdoc :: [rubydoc.info/gems/universum](http://rubydoc.info/gems/universum)
14
14
 
@@ -56,21 +56,21 @@ contract Greeter is Mortal {
56
56
  and
57
57
 
58
58
  ``` ruby
59
- class Greeter < Contract
59
+ ##################
60
+ # Greeter Contract
60
61
 
61
- def initialize( greeting )
62
- @owner = msg.sender
63
- @greeting = greeting
64
- end
62
+ def initialize( greeting )
63
+ @owner = msg.sender
64
+ @greeting = greeting
65
+ end
65
66
 
66
- def greet
67
- @greeting
68
- end
67
+ def greet
68
+ @greeting
69
+ end
69
70
 
70
- def kill
71
- selfdestruct( msg.sender ) if msg.sender == @owner
72
- end
73
- end # class Greeter
71
+ def kill
72
+ selfdestruct( msg.sender ) if msg.sender == @owner
73
+ end
74
74
  ```
75
75
 
76
76
  (Source: [`contracts/greeter.rb`](test/contracts/greeter.rb))
@@ -82,18 +82,17 @@ And let's run the greeter with Universum (Uni):
82
82
  ``` ruby
83
83
  require 'universum'
84
84
 
85
- require_relative 'greeter'
86
-
87
-
88
85
  Account['0x1111'] ## setup a test account
89
86
 
90
- tx = Tx.send( from: '0x1111', data: [Greeter, 'Hello World!'] )
87
+ ## create contract (english version)
88
+ tx = Uni.send_transaction( from: '0x1111', data: ['./greeter', 'Hello World!'] )
91
89
  greeter = tx.receipt.contract
92
90
 
93
91
  puts greeter.greet
94
92
  #=> Hello World!
95
93
 
96
- tx = Tx.send( from: '0x1111', data: [Greeter, '¡Hola, mundo!'] )
94
+ ## create contract (spanish version)
95
+ tx = Uni.send_transaction( from: '0x1111', data: ['./greeter', '¡Hola, mundo!'] )
97
96
  greeter_es = Receipt[ tx ].contract
98
97
 
99
98
  puts greeter_es.greet
@@ -141,23 +140,23 @@ contract MyToken {
141
140
  and
142
141
 
143
142
  ``` ruby
144
- class MyToken < Contract
143
+ ############################
144
+ ## My Token Contract
145
145
 
146
- def initialize( initial_supply )
147
- @balance_of = Mapping.of( Address => Money )
148
- @balance_of[ msg.sender] = initial_supply
149
- end
146
+ def initialize( initial_supply )
147
+ @balance_of = Mapping.of( Address => Money )
148
+ @balance_of[ msg.sender] = initial_supply
149
+ end
150
150
 
151
- def transfer( to, value )
152
- assert( @balance_of[ msg.sender ] >= value )
153
- assert( @balance_of[ to ] + value >= @balance_of[ to ] )
151
+ def transfer( to, value )
152
+ assert @balance_of[ msg.sender ] >= value
153
+ assert @balance_of[ to ] + value >= @balance_of[ to ]
154
154
 
155
- @balance_of[ msg.sender ] -= value
156
- @balance_of[ to ] += value
155
+ @balance_of[ msg.sender ] -= value
156
+ @balance_of[ to ] += value
157
157
 
158
- true
159
- end
160
- end # class MyToken
158
+ true
159
+ end
161
160
  ```
162
161
 
163
162
  (Source: [`contracts/mytoken.rb`](test/contracts/mytoken.rb))
@@ -167,12 +166,12 @@ end # class MyToken
167
166
 
168
167
  ## More Contract Samples
169
168
 
170
- See the [`/universum-contracts`](https://github.com/openblockchains/universum-contracts) collection.
169
+ See the [`/universum-contracts`](https://github.com/s6ruby/universum-contracts) collection.
171
170
 
172
171
 
173
172
  ## More Documentation / Articles / Contracts
174
173
 
175
- [Programming Crypto Blockchain Contracts Step-by-Step Book / Guide](https://github.com/openblockchains/programming-cryptocontracts) - Let's Start with Ponzi & Pyramid Schemes. Run Your Own Lotteries, Gambling Casinos and more on the Blockchain World Computer...
174
+ [Programming Crypto Blockchain Contracts Step-by-Step Book / Guide](https://github.com/s6ruby/programming-cryptocontracts) - Let's Start with Ponzi & Pyramid Schemes. Run Your Own Lotteries, Gambling Casinos and more on the Blockchain World Computer...
176
175
 
177
176
 
178
177
 
data/Rakefile CHANGED
@@ -8,7 +8,7 @@ Hoe.spec 'universum' do
8
8
  self.summary = "universum - next generation ethereum 2.0 world computer runtime; run contract scripts / transactions in plain vanilla / standard ruby on the blockchain; update the (contract-protected / isolated) world states with plain vanilla / standard SQL"
9
9
  self.description = summary
10
10
 
11
- self.urls = ['https://github.com/openblockchains/universum']
11
+ self.urls = ['https://github.com/s6ruby/universum']
12
12
 
13
13
  self.author = 'Gerald Bauer'
14
14
  self.email = 'wwwmake@googlegroups.com'
data/lib/universum.rb CHANGED
@@ -4,14 +4,33 @@
4
4
  ## stdlibs
5
5
  require 'pp' ## pretty print (pp)
6
6
  require 'digest'
7
+ require 'date'
8
+ require 'time'
9
+ require 'uri'
10
+
7
11
 
8
12
 
9
13
  ## our own code
10
14
  require 'universum/version' # note: let version always go first
11
15
 
16
+ require 'universum/units_time'
17
+ require 'universum/units_money'
18
+
19
+ require 'universum/safe_array'
20
+ require 'universum/safe_hash'
21
+
12
22
  require 'universum/enum'
13
23
  require 'universum/event'
14
24
 
25
+ require 'universum/function'
26
+ require 'universum/address'
27
+ require 'universum/type'
28
+ require 'universum/account'
29
+ require 'universum/contract'
30
+ require 'universum/transaction'
31
+ require 'universum/receipt'
32
+
33
+
15
34
  require 'universum/universum'
16
35
 
17
36
 
@@ -0,0 +1,52 @@
1
+ # encoding: utf-8
2
+
3
+
4
+ class Account
5
+
6
+ @@directory = {}
7
+ def self.find_by_address( key )
8
+ ## clean key (allow "embedded" name e.g 0x1111 (Alice))
9
+ key = key.gsub(/\(.+\)/, '' ).strip
10
+ @@directory[ key ]
11
+ end
12
+ def self.find( key ) find_by_address( key ); end # make find_by_address the default finder
13
+ def self.at( key) find_by_address( key ); end # another "classic" alias for find_by_address
14
+
15
+ def self.[]( key )
16
+ o = find_by_address( key )
17
+ if o
18
+ o
19
+ else
20
+ o = new( key )
21
+ ## note: auto-register (new) address in (yellow page) directory
22
+ @@directory[ key ] = o
23
+ o
24
+ end
25
+ end
26
+
27
+ def self.all() @@directory.values; end
28
+
29
+
30
+ ####
31
+ # account (builtin) services / transaction methods
32
+ include Address ## includes address + send/transfer/balance
33
+
34
+ ## note: for now allow write access too!!!
35
+ def balance=( value )
36
+ @balance = value
37
+ end
38
+
39
+ attr_reader :tx
40
+ def _auto_inc_tx() @tx += 1; end ## "internal" method - (auto) increment transaction (tx) counter
41
+
42
+ ## note: needed by transfer/send
43
+ def this() Universum.this; end ## returns current contract
44
+
45
+ private
46
+ def initialize( address, balance: 0, tx: 0 )
47
+ @address = address # type address - (hex) string starts with 0x
48
+ @balance = balance # uint
49
+ @tx = tx # transaction (tx) count (used for nonce and replay attack protection)
50
+ end
51
+
52
+ end # class Account
@@ -0,0 +1,75 @@
1
+ # encoding: utf-8
2
+
3
+
4
+ #############
5
+ # FIX/FIX/FIX!!!! - turn Address into a class!!!!
6
+
7
+
8
+ module Address
9
+ def self.zero() '0x0000'; end
10
+
11
+ def address
12
+ if @address
13
+ @address
14
+ else
15
+ if is_a? Contract
16
+ ## fix/todo: use/lookup proper addr from contract
17
+ ## construct address for now from object_id
18
+ "0x#{(object_id << 1).to_s(16)}"
19
+ else ## assume Account
20
+ '0x0000'
21
+ end
22
+ end
23
+ end # method address
24
+
25
+ def transfer( value ) ## @payable @public
26
+ ## todo/fix: throw exception if insufficient funds
27
+ send( value ) # returns true/false
28
+ end
29
+
30
+ def send( value ) ## @payable @public
31
+ ## todo/fix: assert value > 0
32
+ ## todo/fix: add missing -= part in transfer!!!!
33
+
34
+ ## use this (current contract) for debit (-) ammount
35
+ this._sub( value ) # sub(tract) / debit from the sender (current contract)
36
+ _add( value ) # add / credit to the recipient
37
+ end
38
+
39
+ def balance
40
+ @balance ||= 0 ## return 0 if undefined
41
+ end
42
+
43
+ ### private (internal use only) methods - PLEASE do NOT use (use transfer/send)
44
+ def _sub( value )
45
+ @balance ||= 0 ## return 0 if undefined
46
+ @balance -= value
47
+ end
48
+
49
+ def _add( value )
50
+ @balance ||= 0 ## return 0 if undefined
51
+ @balance += value
52
+ end
53
+ end # module Address
54
+
55
+
56
+
57
+ class String
58
+ def transfer( value )
59
+ ## check if self is an address
60
+ if self.start_with?( '0x' )
61
+ Account[self].transfer( value )
62
+ else
63
+ raise "(Auto-)Type Conversion from Address (Hex) String to Account Failed; Expected String Starting with 0x got #{self}; Contract Halted (Stopped)"
64
+ end
65
+ end
66
+
67
+ def send( value )
68
+ ## check if self is an address
69
+ if self.start_with?( '0x' )
70
+ Account[self].send( value )
71
+ else
72
+ raise "(Auto-)Type Conversion from Address (Hex) String to Account Failed; Expected String Starting with 0x got #{self}; Contract Halted (Stopped)"
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,87 @@
1
+ # encoding: utf-8
2
+
3
+
4
+ class Contract
5
+
6
+ #########
7
+ # load "class-less" contract
8
+ # e.g. SathoshiDice = Contract.load( './sathoshi_dice' )
9
+ def self.load( path )
10
+ extname = File.extname( path ) #=> ".rb"
11
+ if extname == '.rb'
12
+ ## do nothing
13
+ else
14
+ ## "convenience" helper - (auto-)add .rb extension
15
+ path = "#{path}.rb"
16
+ end
17
+
18
+ code = File.open( path, 'r:bom|utf-8' ) { |f| f.read }
19
+ klass = Class.new( Contract )
20
+ klass.class_eval( code ) ## note: use class_eval (NOT instance_eval)
21
+ klass
22
+ end
23
+
24
+
25
+ @@directory = {}
26
+ def self.find_by_address( key )
27
+ ## clean key (allow "embedded" class name e.g 0x4de2ee8 (SatoshiDice))
28
+ key = key.gsub(/\(.+\)/, '' ).strip
29
+ @@directory[ key ];
30
+ end
31
+ def self.find( key ) find_by_address( key ); end # make find_by_address the default finder
32
+ def self.at( key) find_by_address( key ); end # another "classic" alias for find_by_address
33
+ def self.[]( key ) find_by_address( key ); end
34
+
35
+ def self.store( key, o ) @@directory.store( key, o ); end ## store (add) new contract object (o) to hash / directory
36
+ def self.all() @@directory.values; end
37
+
38
+
39
+
40
+ ####
41
+ # account (builtin) services / transaction methods
42
+ include Address ## includes address + send/transfer/balance
43
+
44
+ ## function sig(nature) macro for types (dummy for now)
45
+ # e.g. use like
46
+ # payable :process
47
+ # payable :initialize
48
+ # payable :bet, Integer
49
+ # payable :lend_money, Address => Bool ## returns Bool
50
+ def self.payable( *args ); end
51
+
52
+ payable :receive
53
+
54
+ ####
55
+ # todo/double check: auto-add payable default fallback - why? why not?
56
+ def receive ## @payable default fallback - use different name - why? why not? (e.g. handle/process/etc.)
57
+ end
58
+
59
+
60
+ def assert( condition )
61
+ if condition == true
62
+ ## do nothing
63
+ else
64
+ raise 'Contract Assertion Failed; Contract Halted (Stopped)'
65
+ end
66
+ end
67
+
68
+
69
+ def this() Universum.this; end ## returns current contract
70
+ def log( event ) Universum.log( event ); end
71
+ def msg() Universum.msg; end
72
+ def block() Universum.block; end
73
+ def blockhash( number )
74
+ ## todo/fix: only allow going back 255 blocks; check if number is in range!!!
75
+ Universum.blockhash( number )
76
+ end
77
+
78
+ private
79
+ def selfdestruct( owner ) ## todo/check: use a different name e.g. destruct/ delete - why? why not?
80
+ ## selfdestruct function (for clean-up on blockchain)
81
+ owner.send( @balance ) ## send back all funds owned/hold by contract
82
+
83
+ ## fix: does nothing for now - add some code (e.g. cleanup)
84
+ ## mark as destruct - why? why not?
85
+ end
86
+
87
+ end # class Contract
@@ -0,0 +1,10 @@
1
+ # encoding: utf-8
2
+
3
+ ########################################
4
+ # builtin "global" functions
5
+
6
+ def sha256( *args )
7
+ ## note: allow multiple args (string)
8
+ ## all args will get auto-joined (with no padding)
9
+ Digest::SHA256.hexdigest( args.join )
10
+ end
@@ -0,0 +1,52 @@
1
+ # encoding: utf-8
2
+
3
+
4
+ class Receipt ## transaction receipt
5
+
6
+ @@directory = {}
7
+ def self.find( tx )
8
+ key = "#{tx.from}/#{tx.nonce}"
9
+ @@directory[ key ];
10
+ end
11
+ def self.[]( tx ) find( tx ); end
12
+
13
+ def self.store( o )
14
+ key = "#{o.from}/#{o.nonce}"
15
+ @@directory.store( key, o ); end ## store (add) new receipt object (o) to hash / directory
16
+ def self.all() @@directory.values; end
17
+
18
+
19
+ ## required attributes / fields
20
+ attr_reader :nonce, :from, :to, :value,
21
+ :block_number
22
+ ## optional
23
+ attr_reader :contract_address
24
+
25
+ def initialize( tx:,
26
+ block:,
27
+ contract: nil )
28
+ @nonce = tx.nonce
29
+ @from = tx.from
30
+ @to = tx.to
31
+ @value = tx.value
32
+ ## todo/fix: add data too!!!
33
+
34
+ @block_number = block.number
35
+ ## todo/fix: add block_hash
36
+
37
+ if contract
38
+ ## note: for easier debugging add class name in () to address (needs to get stripped away in lookup)
39
+ @contract_address = "#{contract.address} (#{contract.class.name})"
40
+ else
41
+ @contract_address = nil
42
+ end
43
+ end
44
+
45
+ def contract # convenience helper (quick contract lookup)
46
+ if @contract_address
47
+ Contract.find( @contract_address )
48
+ else
49
+ nil
50
+ end
51
+ end
52
+ end