Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
G
Geth-Modification
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
张蕾
Geth-Modification
Commits
9571a512
Commit
9571a512
authored
Jan 11, 2014
by
obscuren
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
gofmt no coding standards
parent
8bbf879c
Changes
14
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
973 additions
and
938 deletions
+973
-938
README.md
README.md
+5
-0
block_manager.go
block_manager.go
+60
-60
dagger.go
dagger.go
+101
-98
dagger_test.go
dagger_test.go
+9
-9
dev_console.go
dev_console.go
+94
-92
ethereum.go
ethereum.go
+66
-66
peer.go
peer.go
+59
-59
rlp.go
rlp.go
+198
-190
rlp_test.go
rlp_test.go
+37
-37
server.go
server.go
+80
-81
test_runner.go
test_runner.go
+15
-15
test_runner_test.go
test_runner_test.go
+14
-14
testing.go
testing.go
+1
-0
vm.go
vm.go
+234
-217
No files found.
README.md
View file @
9571a512
...
@@ -21,3 +21,8 @@ Command line options
...
@@ -21,3 +21,8 @@ Command line options
-c launch the developer console
-c launch the developer console
-m start mining fake blocks and broadcast fake messages to the net
-m start mining fake blocks and broadcast fake messages to the net
Contribution
============
See CONTRIB.md
block_manager.go
View file @
9571a512
package
main
package
main
import
(
import
(
"fmt"
"fmt"
"github.com/ethereum/ethutil-go"
"github.com/ethereum/ethutil-go"
)
)
type
BlockChain
struct
{
type
BlockChain
struct
{
lastBlock
*
ethutil
.
Block
lastBlock
*
ethutil
.
Block
genesisBlock
*
ethutil
.
Block
genesisBlock
*
ethutil
.
Block
}
}
func
NewBlockChain
()
*
BlockChain
{
func
NewBlockChain
()
*
BlockChain
{
bc
:=
&
BlockChain
{}
bc
:=
&
BlockChain
{}
bc
.
genesisBlock
=
ethutil
.
NewBlock
(
ethutil
.
Encode
(
ethutil
.
Genesis
)
)
bc
.
genesisBlock
=
ethutil
.
NewBlock
(
ethutil
.
Encode
(
ethutil
.
Genesis
)
)
return
bc
return
bc
}
}
type
BlockManager
struct
{
type
BlockManager
struct
{
vm
*
Vm
vm
*
Vm
blockChain
*
BlockChain
blockChain
*
BlockChain
}
}
func
NewBlockManager
()
*
BlockManager
{
func
NewBlockManager
()
*
BlockManager
{
bm
:=
&
BlockManager
{
vm
:
NewVm
()}
bm
:=
&
BlockManager
{
vm
:
NewVm
()}
return
bm
return
bm
}
}
// Process a block.
// Process a block.
func
(
bm
*
BlockManager
)
ProcessBlock
(
block
*
ethutil
.
Block
)
error
{
func
(
bm
*
BlockManager
)
ProcessBlock
(
block
*
ethutil
.
Block
)
error
{
// TODO Validation (Or move to other part of the application)
// TODO Validation (Or move to other part of the application)
if
err
:=
bm
.
ValidateBlock
(
block
);
err
!=
nil
{
if
err
:=
bm
.
ValidateBlock
(
block
);
err
!=
nil
{
return
err
return
err
}
}
// Get the tx count. Used to create enough channels to 'join' the go routines
// Get the tx count. Used to create enough channels to 'join' the go routines
txCount
:=
len
(
block
.
Transactions
())
txCount
:=
len
(
block
.
Transactions
())
// Locking channel. When it has been fully buffered this method will return
// Locking channel. When it has been fully buffered this method will return
lockChan
:=
make
(
chan
bool
,
txCount
)
lockChan
:=
make
(
chan
bool
,
txCount
)
// Process each transaction/contract
// Process each transaction/contract
for
_
,
tx
:=
range
block
.
Transactions
()
{
for
_
,
tx
:=
range
block
.
Transactions
()
{
// If there's no recipient, it's a contract
// If there's no recipient, it's a contract
if
tx
.
IsContract
()
{
if
tx
.
IsContract
()
{
go
bm
.
ProcessContract
(
tx
,
block
,
lockChan
)
go
bm
.
ProcessContract
(
tx
,
block
,
lockChan
)
}
else
{
}
else
{
// "finish" tx which isn't a contract
// "finish" tx which isn't a contract
lockChan
<-
true
lockChan
<-
true
}
}
}
}
// Wait for all Tx to finish processing
// Wait for all Tx to finish processing
for
i
:=
0
;
i
<
txCount
;
i
++
{
for
i
:=
0
;
i
<
txCount
;
i
++
{
<-
lockChan
<-
lockChan
}
}
return
nil
return
nil
}
}
func
(
bm
*
BlockManager
)
ValidateBlock
(
block
*
ethutil
.
Block
)
error
{
func
(
bm
*
BlockManager
)
ValidateBlock
(
block
*
ethutil
.
Block
)
error
{
return
nil
return
nil
}
}
func
(
bm
*
BlockManager
)
ProcessContract
(
tx
*
ethutil
.
Transaction
,
block
*
ethutil
.
Block
,
lockChan
chan
bool
)
{
func
(
bm
*
BlockManager
)
ProcessContract
(
tx
*
ethutil
.
Transaction
,
block
*
ethutil
.
Block
,
lockChan
chan
bool
)
{
// Recovering function in case the VM had any errors
// Recovering function in case the VM had any errors
defer
func
()
{
defer
func
()
{
if
r
:=
recover
();
r
!=
nil
{
if
r
:=
recover
();
r
!=
nil
{
fmt
.
Println
(
"Recovered from VM execution with err ="
,
r
)
fmt
.
Println
(
"Recovered from VM execution with err ="
,
r
)
// Let the channel know where done even though it failed (so the execution may resume normally)
// Let the channel know where done even though it failed (so the execution may resume normally)
lockChan
<-
true
lockChan
<-
true
}
}
}()
}()
// Process contract
// Process contract
bm
.
vm
.
ProcContract
(
tx
,
block
,
func
(
opType
OpType
)
bool
{
bm
.
vm
.
ProcContract
(
tx
,
block
,
func
(
opType
OpType
)
bool
{
// TODO turn on once big ints are in place
// TODO turn on once big ints are in place
//if !block.PayFee(tx.Hash(), StepFee.Uint64()) {
//if !block.PayFee(tx.Hash(), StepFee.Uint64()) {
// return false
// return false
//}
//}
return
true
// Continue
return
true
// Continue
})
})
// Broadcast we're done
// Broadcast we're done
lockChan
<-
true
lockChan
<-
true
}
}
dagger.go
View file @
9571a512
package
main
package
main
import
(
import
(
"math/big
"
"github.com/ethereum/ethutil-go
"
"math/rand
"
"github.com/obscuren/sha3
"
"time
"
"hash
"
"github.com/obscuren/sha3
"
"math/big
"
"hash
"
"math/rand
"
"github.com/ethereum/ethutil-go
"
"time
"
)
)
type
Dagger
struct
{
type
Dagger
struct
{
hash
*
big
.
Int
hash
*
big
.
Int
xn
*
big
.
Int
xn
*
big
.
Int
}
}
var
Found
bool
var
Found
bool
func
(
dag
*
Dagger
)
Find
(
obj
*
big
.
Int
,
resChan
chan
int64
)
{
func
(
dag
*
Dagger
)
Find
(
obj
*
big
.
Int
,
resChan
chan
int64
)
{
r
:=
rand
.
New
(
rand
.
NewSource
(
time
.
Now
()
.
UnixNano
()))
r
:=
rand
.
New
(
rand
.
NewSource
(
time
.
Now
()
.
UnixNano
()))
for
i
:=
0
;
i
<
1000
;
i
++
{
for
i
:=
0
;
i
<
1000
;
i
++
{
rnd
:=
r
.
Int63
()
rnd
:=
r
.
Int63
()
if
dag
.
Eval
(
big
.
NewInt
(
rnd
))
.
Cmp
(
obj
)
<
0
{
if
dag
.
Eval
(
big
.
NewInt
(
rnd
))
.
Cmp
(
obj
)
<
0
{
// Post back result on the channel
// Post back result on the channel
resChan
<-
rnd
resChan
<-
rnd
// Notify other threads we've found a valid nonce
// Notify other threads we've found a valid nonce
Found
=
true
Found
=
true
}
}
// Break out if found
// Break out if found
if
Found
{
break
}
if
Found
{
}
break
}
}
resChan
<-
0
resChan
<-
0
}
}
func
(
dag
*
Dagger
)
Search
(
hash
,
diff
*
big
.
Int
)
*
big
.
Int
{
func
(
dag
*
Dagger
)
Search
(
hash
,
diff
*
big
.
Int
)
*
big
.
Int
{
// TODO fix multi threading. Somehow it results in the wrong nonce
// TODO fix multi threading. Somehow it results in the wrong nonce
amountOfRoutines
:=
1
amountOfRoutines
:=
1
dag
.
hash
=
hash
dag
.
hash
=
hash
obj
:=
ethutil
.
BigPow
(
2
,
256
)
obj
:=
ethutil
.
BigPow
(
2
,
256
)
obj
=
obj
.
Div
(
obj
,
diff
)
obj
=
obj
.
Div
(
obj
,
diff
)
Found
=
false
Found
=
false
resChan
:=
make
(
chan
int64
,
3
)
resChan
:=
make
(
chan
int64
,
3
)
var
res
int64
var
res
int64
for
k
:=
0
;
k
<
amountOfRoutines
;
k
++
{
for
k
:=
0
;
k
<
amountOfRoutines
;
k
++
{
go
dag
.
Find
(
obj
,
resChan
)
go
dag
.
Find
(
obj
,
resChan
)
}
}
// Wait for each go routine to finish
// Wait for each go routine to finish
for
k
:=
0
;
k
<
amountOfRoutines
;
k
++
{
for
k
:=
0
;
k
<
amountOfRoutines
;
k
++
{
// Get the result from the channel. 0 = quit
// Get the result from the channel. 0 = quit
if
r
:=
<-
resChan
;
r
!=
0
{
if
r
:=
<-
resChan
;
r
!=
0
{
res
=
r
res
=
r
}
}
}
}
return
big
.
NewInt
(
res
)
return
big
.
NewInt
(
res
)
}
}
func
DaggerVerify
(
hash
,
diff
,
nonce
*
big
.
Int
)
bool
{
func
DaggerVerify
(
hash
,
diff
,
nonce
*
big
.
Int
)
bool
{
dagger
:=
&
Dagger
{}
dagger
:=
&
Dagger
{}
dagger
.
hash
=
hash
dagger
.
hash
=
hash
obj
:=
ethutil
.
BigPow
(
2
,
256
)
obj
:=
ethutil
.
BigPow
(
2
,
256
)
obj
=
obj
.
Div
(
obj
,
diff
)
obj
=
obj
.
Div
(
obj
,
diff
)
return
dagger
.
Eval
(
nonce
)
.
Cmp
(
obj
)
<
0
return
dagger
.
Eval
(
nonce
)
.
Cmp
(
obj
)
<
0
}
}
func
(
dag
*
Dagger
)
Node
(
L
uint64
,
i
uint64
)
*
big
.
Int
{
func
(
dag
*
Dagger
)
Node
(
L
uint64
,
i
uint64
)
*
big
.
Int
{
if
L
==
i
{
if
L
==
i
{
return
dag
.
hash
return
dag
.
hash
}
}
var
m
*
big
.
Int
var
m
*
big
.
Int
if
L
==
9
{
if
L
==
9
{
m
=
big
.
NewInt
(
16
)
m
=
big
.
NewInt
(
16
)
}
else
{
}
else
{
m
=
big
.
NewInt
(
3
)
m
=
big
.
NewInt
(
3
)
}
}
sha
:=
sha3
.
NewKeccak256
()
sha
:=
sha3
.
NewKeccak256
()
sha
.
Reset
()
sha
.
Reset
()
d
:=
sha3
.
NewKeccak256
()
d
:=
sha3
.
NewKeccak256
()
b
:=
new
(
big
.
Int
)
b
:=
new
(
big
.
Int
)
ret
:=
new
(
big
.
Int
)
ret
:=
new
(
big
.
Int
)
for
k
:=
0
;
k
<
int
(
m
.
Uint64
());
k
++
{
for
k
:=
0
;
k
<
int
(
m
.
Uint64
());
k
++
{
d
.
Reset
()
d
.
Reset
()
d
.
Write
(
dag
.
hash
.
Bytes
())
d
.
Write
(
dag
.
hash
.
Bytes
())
d
.
Write
(
dag
.
xn
.
Bytes
())
d
.
Write
(
dag
.
xn
.
Bytes
())
d
.
Write
(
big
.
NewInt
(
int64
(
L
))
.
Bytes
())
d
.
Write
(
big
.
NewInt
(
int64
(
L
))
.
Bytes
())
d
.
Write
(
big
.
NewInt
(
int64
(
i
))
.
Bytes
())
d
.
Write
(
big
.
NewInt
(
int64
(
i
))
.
Bytes
())
d
.
Write
(
big
.
NewInt
(
int64
(
k
))
.
Bytes
())
d
.
Write
(
big
.
NewInt
(
int64
(
k
))
.
Bytes
())
b
.
SetBytes
(
Sum
(
d
))
b
.
SetBytes
(
Sum
(
d
))
pk
:=
b
.
Uint64
()
&
((
1
<<
((
L
-
1
)
*
3
))
-
1
)
pk
:=
b
.
Uint64
()
&
((
1
<<
((
L
-
1
)
*
3
))
-
1
)
sha
.
Write
(
dag
.
Node
(
L
-
1
,
pk
)
.
Bytes
())
sha
.
Write
(
dag
.
Node
(
L
-
1
,
pk
)
.
Bytes
())
}
}
ret
.
SetBytes
(
Sum
(
sha
))
ret
.
SetBytes
(
Sum
(
sha
))
return
ret
return
ret
}
}
func
Sum
(
sha
hash
.
Hash
)
[]
byte
{
func
Sum
(
sha
hash
.
Hash
)
[]
byte
{
in
:=
make
([]
byte
,
32
)
in
:=
make
([]
byte
,
32
)
return
sha
.
Sum
(
in
)
return
sha
.
Sum
(
in
)
}
}
func
(
dag
*
Dagger
)
Eval
(
N
*
big
.
Int
)
*
big
.
Int
{
func
(
dag
*
Dagger
)
Eval
(
N
*
big
.
Int
)
*
big
.
Int
{
pow
:=
ethutil
.
BigPow
(
2
,
26
)
pow
:=
ethutil
.
BigPow
(
2
,
26
)
dag
.
xn
=
N
.
Div
(
N
,
pow
)
dag
.
xn
=
N
.
Div
(
N
,
pow
)
sha
:=
sha3
.
NewKeccak256
()
sha
:=
sha3
.
NewKeccak256
()
sha
.
Reset
()
sha
.
Reset
()
ret
:=
new
(
big
.
Int
)
ret
:=
new
(
big
.
Int
)
for
k
:=
0
;
k
<
4
;
k
++
{
for
k
:=
0
;
k
<
4
;
k
++
{
d
:=
sha3
.
NewKeccak256
()
d
:=
sha3
.
NewKeccak256
()
b
:=
new
(
big
.
Int
)
b
:=
new
(
big
.
Int
)
d
.
Reset
()
d
.
Reset
()
d
.
Write
(
dag
.
hash
.
Bytes
())
d
.
Write
(
dag
.
hash
.
Bytes
())
d
.
Write
(
dag
.
xn
.
Bytes
())
d
.
Write
(
dag
.
xn
.
Bytes
())
d
.
Write
(
N
.
Bytes
())
d
.
Write
(
N
.
Bytes
())
d
.
Write
(
big
.
NewInt
(
int64
(
k
))
.
Bytes
())
d
.
Write
(
big
.
NewInt
(
int64
(
k
))
.
Bytes
())
b
.
SetBytes
(
Sum
(
d
))
b
.
SetBytes
(
Sum
(
d
))
pk
:=
(
b
.
Uint64
()
&
0x1ffffff
)
pk
:=
(
b
.
Uint64
()
&
0x1ffffff
)
sha
.
Write
(
dag
.
Node
(
9
,
pk
)
.
Bytes
())
sha
.
Write
(
dag
.
Node
(
9
,
pk
)
.
Bytes
())
}
}
return
ret
.
SetBytes
(
Sum
(
sha
))
return
ret
.
SetBytes
(
Sum
(
sha
))
}
}
dagger_test.go
View file @
9571a512
package
main
package
main
import
(
import
(
"testin
g"
"math/bi
g"
"math/bi
g"
"testin
g"
)
)
func
BenchmarkDaggerSearch
(
b
*
testing
.
B
)
{
func
BenchmarkDaggerSearch
(
b
*
testing
.
B
)
{
hash
:=
big
.
NewInt
(
0
)
hash
:=
big
.
NewInt
(
0
)
diff
:=
BigPow
(
2
,
36
)
diff
:=
BigPow
(
2
,
36
)
o
:=
big
.
NewInt
(
0
)
// nonce doesn't matter. We're only testing against speed, not validity
o
:=
big
.
NewInt
(
0
)
// nonce doesn't matter. We're only testing against speed, not validity
// Reset timer so the big generation isn't included in the benchmark
// Reset timer so the big generation isn't included in the benchmark
b
.
ResetTimer
()
b
.
ResetTimer
()
// Validate
// Validate
DaggerVerify
(
hash
,
diff
,
o
)
DaggerVerify
(
hash
,
diff
,
o
)
}
}
dev_console.go
View file @
9571a512
package
main
package
main
import
(
import
(
"fmt
"
"bufio
"
"bufio
"
"encoding/hex
"
"string
s"
"error
s"
"os
"
"fmt
"
"errors
"
"github.com/ethereum/ethdb-go
"
"encoding/hex
"
"github.com/ethereum/ethutil-go
"
"github.com/ethereum/ethdb-go
"
"os
"
"github.com/ethereum/ethutil-go
"
"strings
"
)
)
type
Console
struct
{
type
Console
struct
{
db
*
ethdb
.
MemDatabase
db
*
ethdb
.
MemDatabase
trie
*
ethutil
.
Trie
trie
*
ethutil
.
Trie
}
}
func
NewConsole
()
*
Console
{
func
NewConsole
()
*
Console
{
db
,
_
:=
ethdb
.
NewMemDatabase
()
db
,
_
:=
ethdb
.
NewMemDatabase
()
trie
:=
ethutil
.
NewTrie
(
db
,
""
)
trie
:=
ethutil
.
NewTrie
(
db
,
""
)
return
&
Console
{
db
:
db
,
trie
:
trie
}
return
&
Console
{
db
:
db
,
trie
:
trie
}
}
}
func
(
i
*
Console
)
ValidateInput
(
action
string
,
argumentLength
int
)
error
{
func
(
i
*
Console
)
ValidateInput
(
action
string
,
argumentLength
int
)
error
{
err
:=
false
err
:=
false
var
expArgCount
int
var
expArgCount
int
switch
{
switch
{
case
action
==
"update"
&&
argumentLength
!=
2
:
case
action
==
"update"
&&
argumentLength
!=
2
:
err
=
true
err
=
true
expArgCount
=
2
expArgCount
=
2
case
action
==
"get"
&&
argumentLength
!=
1
:
case
action
==
"get"
&&
argumentLength
!=
1
:
err
=
true
err
=
true
expArgCount
=
1
expArgCount
=
1
case
action
==
"dag"
&&
argumentLength
!=
2
:
case
action
==
"dag"
&&
argumentLength
!=
2
:
err
=
true
err
=
true
expArgCount
=
2
expArgCount
=
2
}
}
if
err
{
if
err
{
return
errors
.
New
(
fmt
.
Sprintf
(
"'%s' requires %d args, got %d"
,
action
,
expArgCount
,
argumentLength
))
return
errors
.
New
(
fmt
.
Sprintf
(
"'%s' requires %d args, got %d"
,
action
,
expArgCount
,
argumentLength
))
}
else
{
}
else
{
return
nil
return
nil
}
}
}
}
func
(
i
*
Console
)
ParseInput
(
input
string
)
bool
{
func
(
i
*
Console
)
ParseInput
(
input
string
)
bool
{
scanner
:=
bufio
.
NewScanner
(
strings
.
NewReader
(
input
))
scanner
:=
bufio
.
NewScanner
(
strings
.
NewReader
(
input
))
scanner
.
Split
(
bufio
.
ScanWords
)
scanner
.
Split
(
bufio
.
ScanWords
)
count
:=
0
count
:=
0
var
tokens
[]
string
var
tokens
[]
string
for
scanner
.
Scan
()
{
for
scanner
.
Scan
()
{
count
++
count
++
tokens
=
append
(
tokens
,
scanner
.
Text
())
tokens
=
append
(
tokens
,
scanner
.
Text
())
}
}
if
err
:=
scanner
.
Err
();
err
!=
nil
{
if
err
:=
scanner
.
Err
();
err
!=
nil
{
fmt
.
Fprintln
(
os
.
Stderr
,
"reading input:"
,
err
)
fmt
.
Fprintln
(
os
.
Stderr
,
"reading input:"
,
err
)
}
}
if
len
(
tokens
)
==
0
{
return
true
}
if
len
(
tokens
)
==
0
{
return
true
}
err
:=
i
.
ValidateInput
(
tokens
[
0
],
count
-
1
)
err
:=
i
.
ValidateInput
(
tokens
[
0
],
count
-
1
)
if
err
!=
nil
{
if
err
!=
nil
{
fmt
.
Println
(
err
)
fmt
.
Println
(
err
)
}
else
{
}
else
{
switch
tokens
[
0
]
{
switch
tokens
[
0
]
{
case
"update"
:
case
"update"
:
i
.
trie
.
Update
(
tokens
[
1
],
tokens
[
2
])
i
.
trie
.
Update
(
tokens
[
1
],
tokens
[
2
])
fmt
.
Println
(
hex
.
EncodeToString
([]
byte
(
i
.
trie
.
Root
)))
fmt
.
Println
(
hex
.
EncodeToString
([]
byte
(
i
.
trie
.
Root
)))
case
"get"
:
case
"get"
:
fmt
.
Println
(
i
.
trie
.
Get
(
tokens
[
1
]))
fmt
.
Println
(
i
.
trie
.
Get
(
tokens
[
1
]))
case
"root"
:
case
"root"
:
fmt
.
Println
(
hex
.
EncodeToString
([]
byte
(
i
.
trie
.
Root
)))
fmt
.
Println
(
hex
.
EncodeToString
([]
byte
(
i
.
trie
.
Root
)))
case
"rawroot"
:
case
"rawroot"
:
fmt
.
Println
(
i
.
trie
.
Root
)
fmt
.
Println
(
i
.
trie
.
Root
)
case
"print"
:
case
"print"
:
i
.
db
.
Print
()
i
.
db
.
Print
()
case
"dag"
:
case
"dag"
:
fmt
.
Println
(
DaggerVerify
(
ethutil
.
Big
(
tokens
[
1
]),
// hash
fmt
.
Println
(
DaggerVerify
(
ethutil
.
Big
(
tokens
[
1
]),
// hash
ethutil
.
BigPow
(
2
,
36
),
// diff
ethutil
.
BigPow
(
2
,
36
),
// diff
ethutil
.
Big
(
tokens
[
2
])))
// nonce
ethutil
.
Big
(
tokens
[
2
])))
// nonce
case
"exit"
,
"quit"
,
"q"
:
case
"exit"
,
"quit"
,
"q"
:
return
false
return
false
case
"help"
:
case
"help"
:
fmt
.
Printf
(
"COMMANDS:
\n
"
+
fmt
.
Printf
(
"COMMANDS:
\n
"
+
"
\0
33[1m= DB =
\0
33[0m
\n
"
+
"
\0
33[1m= DB =
\0
33[0m
\n
"
+
"update KEY VALUE - Updates/Creates a new value for the given key
\n
"
+
"update KEY VALUE - Updates/Creates a new value for the given key
\n
"
+
"get KEY - Retrieves the given key
\n
"
+
"get KEY - Retrieves the given key
\n
"
+
"root - Prints the hex encoded merkle root
\n
"
+
"root - Prints the hex encoded merkle root
\n
"
+
"rawroot - Prints the raw merkle root
\n
"
+
"rawroot - Prints the raw merkle root
\n
"
+
"
\0
33[1m= Dagger =
\0
33[0m
\n
"
+
"
\0
33[1m= Dagger =
\0
33[0m
\n
"
+
"dag HASH NONCE - Verifies a nonce with the given hash with dagger
\n
"
)
"dag HASH NONCE - Verifies a nonce with the given hash with dagger
\n
"
)
default
:
default
:
fmt
.
Println
(
"Unknown command:"
,
tokens
[
0
])
fmt
.
Println
(
"Unknown command:"
,
tokens
[
0
])
}
}
}
}
return
true
return
true
}
}
func
(
i
*
Console
)
Start
()
{
func
(
i
*
Console
)
Start
()
{
fmt
.
Printf
(
"Eth Console. Type (help) for help
\n
"
)
fmt
.
Printf
(
"Eth Console. Type (help) for help
\n
"
)
reader
:=
bufio
.
NewReader
(
os
.
Stdin
)
reader
:=
bufio
.
NewReader
(
os
.
Stdin
)
for
{
for
{
fmt
.
Printf
(
"eth >>> "
)
fmt
.
Printf
(
"eth >>> "
)
str
,
_
,
err
:=
reader
.
ReadLine
()
str
,
_
,
err
:=
reader
.
ReadLine
()
if
err
!=
nil
{
if
err
!=
nil
{
fmt
.
Println
(
"Error reading input"
,
err
)
fmt
.
Println
(
"Error reading input"
,
err
)
}
else
{
}
else
{
if
!
i
.
ParseInput
(
string
(
str
))
{
if
!
i
.
ParseInput
(
string
(
str
))
{
return
return
}
}
}
}
}
}
}
}
ethereum.go
View file @
9571a512
package
main
package
main
import
(
import
(
"fmt
"
"flag
"
"os
"
"fmt
"
"os/signal
"
"github.com/ethereum/ethutil-go
"
"fla
g"
"lo
g"
"runtime
"
"os
"
"log
"
"os/signal
"
"github.com/ethereum/ethutil-go
"
"runtime
"
)
)
const
Debug
=
true
const
Debug
=
true
var
StartConsole
bool
var
StartConsole
bool
var
StartMining
bool
var
StartMining
bool
func
Init
()
{
func
Init
()
{
flag
.
BoolVar
(
&
StartConsole
,
"c"
,
false
,
"debug and testing console"
)
flag
.
BoolVar
(
&
StartConsole
,
"c"
,
false
,
"debug and testing console"
)
flag
.
BoolVar
(
&
StartMining
,
"m"
,
false
,
"start dagger mining"
)
flag
.
BoolVar
(
&
StartMining
,
"m"
,
false
,
"start dagger mining"
)
flag
.
Parse
()
flag
.
Parse
()
}
}
// Register interrupt handlers so we can stop the server
// Register interrupt handlers so we can stop the server
func
RegisterInterupts
(
s
*
Server
)
{
func
RegisterInterupts
(
s
*
Server
)
{
// Buffered chan of one is enough
// Buffered chan of one is enough
c
:=
make
(
chan
os
.
Signal
,
1
)
c
:=
make
(
chan
os
.
Signal
,
1
)
// Notify about interrupts for now
// Notify about interrupts for now
signal
.
Notify
(
c
,
os
.
Interrupt
)
signal
.
Notify
(
c
,
os
.
Interrupt
)
go
func
()
{
go
func
()
{
for
sig
:=
range
c
{
for
sig
:=
range
c
{
fmt
.
Printf
(
"Shutting down (%v) ...
\n
"
,
sig
)
fmt
.
Printf
(
"Shutting down (%v) ...
\n
"
,
sig
)
s
.
Stop
()
s
.
Stop
()
}
}
}()
}()
}
}
func
main
()
{
func
main
()
{
runtime
.
GOMAXPROCS
(
runtime
.
NumCPU
())
runtime
.
GOMAXPROCS
(
runtime
.
NumCPU
())
ethutil
.
InitFees
()
ethutil
.
InitFees
()
Init
()
Init
()
if
StartConsole
{
if
StartConsole
{
console
:=
NewConsole
()
console
:=
NewConsole
()
console
.
Start
()
console
.
Start
()
}
else
{
}
else
{
log
.
Println
(
"Starting Ethereum"
)
log
.
Println
(
"Starting Ethereum"
)
server
,
err
:=
NewServer
()
server
,
err
:=
NewServer
()
if
err
!=
nil
{
if
err
!=
nil
{
log
.
Println
(
err
)
log
.
Println
(
err
)
return
return
}
}
RegisterInterupts
(
server
)
RegisterInterupts
(
server
)
if
StartMining
{
if
StartMining
{
log
.
Println
(
"Mining started"
)
log
.
Println
(
"Mining started"
)
dagger
:=
&
Dagger
{}
dagger
:=
&
Dagger
{}
go
func
()
{
go
func
()
{
for
{
for
{
res
:=
dagger
.
Search
(
ethutil
.
Big
(
"0"
),
ethutil
.
BigPow
(
2
,
36
))
res
:=
dagger
.
Search
(
ethutil
.
Big
(
"0"
),
ethutil
.
BigPow
(
2
,
36
))
server
.
Broadcast
(
"block"
,
Encode
(
res
.
String
()))
server
.
Broadcast
(
"block"
,
Encode
(
res
.
String
()))
}
}
}()
}()
}
}
server
.
Start
()
server
.
Start
()
err
=
server
.
ConnectToPeer
(
"localhost:12345"
)
err
=
server
.
ConnectToPeer
(
"localhost:12345"
)
if
err
!=
nil
{
if
err
!=
nil
{
log
.
Println
(
err
)
log
.
Println
(
err
)
server
.
Stop
()
server
.
Stop
()
return
return
}
}
// Wait for shutdown
// Wait for shutdown
server
.
WaitForShutdown
()
server
.
WaitForShutdown
()
}
}
}
}
peer.go
View file @
9571a512
package
main
package
main
import
(
import
(
"net
"
"github.com/ethereum/ethwire-go
"
"log"
"log"
"github.com/ethereum/ethwire-go
"
"net
"
)
)
type
Peer
struct
{
type
Peer
struct
{
// Server interface
// Server interface
server
*
Server
server
*
Server
// Net connection
// Net connection
conn
net
.
Conn
conn
net
.
Conn
// Output queue which is used to communicate and handle messages
// Output queue which is used to communicate and handle messages
outputQueue
chan
ethwire
.
InOutMsg
outputQueue
chan
ethwire
.
InOutMsg
// Quit channel
// Quit channel
quit
chan
bool
quit
chan
bool
}
}
func
NewPeer
(
conn
net
.
Conn
,
server
*
Server
)
*
Peer
{
func
NewPeer
(
conn
net
.
Conn
,
server
*
Server
)
*
Peer
{
return
&
Peer
{
return
&
Peer
{
outputQueue
:
make
(
chan
ethwire
.
InOutMsg
,
1
),
// Buffered chan of 1 is enough
outputQueue
:
make
(
chan
ethwire
.
InOutMsg
,
1
),
// Buffered chan of 1 is enough
quit
:
make
(
chan
bool
),
quit
:
make
(
chan
bool
),
server
:
server
,
server
:
server
,
conn
:
conn
,
conn
:
conn
,
}
}
}
}
// Outputs any RLP encoded data to the peer
// Outputs any RLP encoded data to the peer
func
(
p
*
Peer
)
QueueMessage
(
msgType
string
,
data
[]
byte
)
{
func
(
p
*
Peer
)
QueueMessage
(
msgType
string
,
data
[]
byte
)
{
p
.
outputQueue
<-
ethwire
.
InOutMsg
{
MsgType
:
msgType
,
Data
:
data
}
p
.
outputQueue
<-
ethwire
.
InOutMsg
{
MsgType
:
msgType
,
Data
:
data
}
}
}
// Outbound message handler. Outbound messages are handled here
// Outbound message handler. Outbound messages are handled here
func
(
p
*
Peer
)
HandleOutbound
()
{
func
(
p
*
Peer
)
HandleOutbound
()
{
out
:
out
:
for
{
for
{
select
{
select
{
// Main message queue. All outbound messages are processed through here
// Main message queue. All outbound messages are processed through here
case
msg
:=
<-
p
.
outputQueue
:
case
msg
:=
<-
p
.
outputQueue
:
// TODO Message checking and handle accordingly
// TODO Message checking and handle accordingly
err
:=
ethwire
.
WriteMessage
(
p
.
conn
,
msg
)
err
:=
ethwire
.
WriteMessage
(
p
.
conn
,
msg
)
if
err
!=
nil
{
if
err
!=
nil
{
log
.
Println
(
err
)
log
.
Println
(
err
)
// Stop the client if there was an error writing to it
// Stop the client if there was an error writing to it
p
.
Stop
()
p
.
Stop
()
}
}
// Break out of the for loop if a quit message is posted
// Break out of the for loop if a quit message is posted
case
<-
p
.
quit
:
case
<-
p
.
quit
:
break
out
break
out
}
}
}
}
}
}
// Inbound handler. Inbound messages are received here and passed to the appropriate methods
// Inbound handler. Inbound messages are received here and passed to the appropriate methods
func
(
p
*
Peer
)
HandleInbound
()
{
func
(
p
*
Peer
)
HandleInbound
()
{
defer
p
.
Stop
()
defer
p
.
Stop
()
out
:
out
:
for
{
for
{
// Wait for a message from the peer
// Wait for a message from the peer
msg
,
err
:=
ethwire
.
ReadMessage
(
p
.
conn
)
msg
,
err
:=
ethwire
.
ReadMessage
(
p
.
conn
)
if
err
!=
nil
{
if
err
!=
nil
{
log
.
Println
(
err
)
log
.
Println
(
err
)
break
out
break
out
}
}
// TODO
// TODO
data
,
_
:=
Decode
(
msg
.
Data
,
0
)
data
,
_
:=
Decode
(
msg
.
Data
,
0
)
log
.
Printf
(
"%s, %s
\n
"
,
msg
.
MsgType
,
data
)
log
.
Printf
(
"%s, %s
\n
"
,
msg
.
MsgType
,
data
)
}
}
// Notify the out handler we're quiting
// Notify the out handler we're quiting
p
.
quit
<-
true
p
.
quit
<-
true
}
}
func
(
p
*
Peer
)
Start
()
{
func
(
p
*
Peer
)
Start
()
{
// Run the outbound handler in a new goroutine
// Run the outbound handler in a new goroutine
go
p
.
HandleOutbound
()
go
p
.
HandleOutbound
()
// Run the inbound handler in a new goroutine
// Run the inbound handler in a new goroutine
go
p
.
HandleInbound
()
go
p
.
HandleInbound
()
}
}
func
(
p
*
Peer
)
Stop
()
{
func
(
p
*
Peer
)
Stop
()
{
p
.
conn
.
Close
()
p
.
conn
.
Close
()
p
.
quit
<-
true
p
.
quit
<-
true
}
}
rlp.go
View file @
9571a512
package
main
package
main
import
(
import
(
"fmt
"
"bytes
"
"bytes
"
"fmt
"
"math
"
"github.com/ethereum/ethutil-go
"
"math/big
"
"math
"
"github.com/ethereum/ethutil-go
"
"math/big
"
)
)
type
RlpEncoder
struct
{
type
RlpEncoder
struct
{
rlpData
[]
byte
rlpData
[]
byte
}
}
func
NewRlpEncoder
()
*
RlpEncoder
{
func
NewRlpEncoder
()
*
RlpEncoder
{
encoder
:=
&
RlpEncoder
{}
encoder
:=
&
RlpEncoder
{}
return
encoder
return
encoder
}
}
func
(
coder
*
RlpEncoder
)
EncodeData
(
rlpData
[]
interface
{})
[]
byte
{
func
(
coder
*
RlpEncoder
)
EncodeData
(
rlpData
[]
interface
{})
[]
byte
{
return
nil
return
nil
}
}
// Data attributes are returned by the rlp decoder. The data attributes represents
// Data attributes are returned by the rlp decoder. The data attributes represents
// one item within the rlp data structure. It's responsible for all the casting
// one item within the rlp data structure. It's responsible for all the casting
// It always returns something valid
// It always returns something valid
type
RlpDataAttribute
struct
{
type
RlpDataAttribute
struct
{
dataAttrib
interface
{}
dataAttrib
interface
{}
}
}
func
NewRlpDataAttribute
(
attrib
interface
{})
*
RlpDataAttribute
{
func
NewRlpDataAttribute
(
attrib
interface
{})
*
RlpDataAttribute
{
return
&
RlpDataAttribute
{
dataAttrib
:
attrib
}
return
&
RlpDataAttribute
{
dataAttrib
:
attrib
}
}
}
func
(
attr
*
RlpDataAttribute
)
Length
()
int
{
func
(
attr
*
RlpDataAttribute
)
Length
()
int
{
if
data
,
ok
:=
attr
.
dataAttrib
.
([]
interface
{});
ok
{
if
data
,
ok
:=
attr
.
dataAttrib
.
([]
interface
{});
ok
{
return
len
(
data
)
return
len
(
data
)
}
}
return
0
return
0
}
}
func
(
attr
*
RlpDataAttribute
)
AsUint
()
uint64
{
func
(
attr
*
RlpDataAttribute
)
AsUint
()
uint64
{
if
value
,
ok
:=
attr
.
dataAttrib
.
(
uint8
);
ok
{
if
value
,
ok
:=
attr
.
dataAttrib
.
(
uint8
);
ok
{
return
uint64
(
value
)
return
uint64
(
value
)
}
else
if
value
,
ok
:=
attr
.
dataAttrib
.
(
uint16
);
ok
{
}
else
if
value
,
ok
:=
attr
.
dataAttrib
.
(
uint16
);
ok
{
return
uint64
(
value
)
return
uint64
(
value
)
}
else
if
value
,
ok
:=
attr
.
dataAttrib
.
(
uint32
);
ok
{
}
else
if
value
,
ok
:=
attr
.
dataAttrib
.
(
uint32
);
ok
{
return
uint64
(
value
)
return
uint64
(
value
)
}
else
if
value
,
ok
:=
attr
.
dataAttrib
.
(
uint64
);
ok
{
}
else
if
value
,
ok
:=
attr
.
dataAttrib
.
(
uint64
);
ok
{
return
value
return
value
}
}
return
0
return
0
}
}
func
(
attr
*
RlpDataAttribute
)
AsBigInt
()
*
big
.
Int
{
func
(
attr
*
RlpDataAttribute
)
AsBigInt
()
*
big
.
Int
{
if
a
,
ok
:=
attr
.
dataAttrib
.
([]
byte
);
ok
{
if
a
,
ok
:=
attr
.
dataAttrib
.
([]
byte
);
ok
{
return
ethutil
.
Big
(
string
(
a
))
return
ethutil
.
Big
(
string
(
a
))
}
}
return
big
.
NewInt
(
0
)
return
big
.
NewInt
(
0
)
}
}
func
(
attr
*
RlpDataAttribute
)
AsString
()
string
{
func
(
attr
*
RlpDataAttribute
)
AsString
()
string
{
if
a
,
ok
:=
attr
.
dataAttrib
.
([]
byte
);
ok
{
if
a
,
ok
:=
attr
.
dataAttrib
.
([]
byte
);
ok
{
return
string
(
a
)
return
string
(
a
)
}
}
return
""
return
""
}
}
func
(
attr
*
RlpDataAttribute
)
AsBytes
()
[]
byte
{
func
(
attr
*
RlpDataAttribute
)
AsBytes
()
[]
byte
{
if
a
,
ok
:=
attr
.
dataAttrib
.
([]
byte
);
ok
{
if
a
,
ok
:=
attr
.
dataAttrib
.
([]
byte
);
ok
{
return
a
return
a
}
}
return
make
([]
byte
,
0
)
return
make
([]
byte
,
0
)
}
}
// Threat the attribute as a slice
// Threat the attribute as a slice
func
(
attr
*
RlpDataAttribute
)
Get
(
idx
int
)
*
RlpDataAttribute
{
func
(
attr
*
RlpDataAttribute
)
Get
(
idx
int
)
*
RlpDataAttribute
{
if
d
,
ok
:=
attr
.
dataAttrib
.
([]
interface
{});
ok
{
if
d
,
ok
:=
attr
.
dataAttrib
.
([]
interface
{});
ok
{
// Guard for oob
// Guard for oob
if
len
(
d
)
<
idx
{
if
len
(
d
)
<
idx
{
return
NewRlpDataAttribute
(
nil
)
return
NewRlpDataAttribute
(
nil
)
}
}
return
NewRlpDataAttribute
(
d
[
idx
])
return
NewRlpDataAttribute
(
d
[
idx
])
}
}
// If this wasn't a slice you probably shouldn't be using this function
// If this wasn't a slice you probably shouldn't be using this function
return
NewRlpDataAttribute
(
nil
)
return
NewRlpDataAttribute
(
nil
)
}
}
type
RlpDecoder
struct
{
type
RlpDecoder
struct
{
rlpData
interface
{}
rlpData
interface
{}
}
}
func
NewRlpDecoder
(
rlpData
[]
byte
)
*
RlpDecoder
{
func
NewRlpDecoder
(
rlpData
[]
byte
)
*
RlpDecoder
{
decoder
:=
&
RlpDecoder
{}
decoder
:=
&
RlpDecoder
{}
// Decode the data
// Decode the data
data
,
_
:=
Decode
(
rlpData
,
0
)
data
,
_
:=
Decode
(
rlpData
,
0
)
decoder
.
rlpData
=
data
decoder
.
rlpData
=
data
return
decoder
return
decoder
}
}
func
(
dec
*
RlpDecoder
)
Get
(
idx
int
)
*
RlpDataAttribute
{
func
(
dec
*
RlpDecoder
)
Get
(
idx
int
)
*
RlpDataAttribute
{
return
NewRlpDataAttribute
(
dec
.
rlpData
)
.
Get
(
idx
)
return
NewRlpDataAttribute
(
dec
.
rlpData
)
.
Get
(
idx
)
}
}
/// Raw methods
/// Raw methods
func
BinaryLength
(
n
uint64
)
uint64
{
func
BinaryLength
(
n
uint64
)
uint64
{
if
n
==
0
{
return
0
}
if
n
==
0
{
return
0
}
return
1
+
BinaryLength
(
n
/
256
)
return
1
+
BinaryLength
(
n
/
256
)
}
}
func
ToBinarySlice
(
n
uint64
,
length
uint64
)
[]
uint64
{
func
ToBinarySlice
(
n
uint64
,
length
uint64
)
[]
uint64
{
if
length
==
0
{
if
length
==
0
{
length
=
BinaryLength
(
n
)
length
=
BinaryLength
(
n
)
}
}
if
n
==
0
{
return
make
([]
uint64
,
1
)
}
if
n
==
0
{
return
make
([]
uint64
,
1
)
}
slice
:=
ToBinarySlice
(
n
/
256
,
0
)
slice
:=
ToBinarySlice
(
n
/
256
,
0
)
slice
=
append
(
slice
,
n
%
256
)
slice
=
append
(
slice
,
n
%
256
)
return
slice
return
slice
}
}
func
ToBin
(
n
uint64
,
length
uint64
)
string
{
func
ToBin
(
n
uint64
,
length
uint64
)
string
{
var
buf
bytes
.
Buffer
var
buf
bytes
.
Buffer
for
_
,
val
:=
range
ToBinarySlice
(
n
,
length
)
{
for
_
,
val
:=
range
ToBinarySlice
(
n
,
length
)
{
buf
.
WriteString
(
string
(
val
))
buf
.
WriteString
(
string
(
val
))
}
}
return
buf
.
String
()
return
buf
.
String
()
}
}
func
FromBin
(
data
[]
byte
)
uint64
{
func
FromBin
(
data
[]
byte
)
uint64
{
if
len
(
data
)
==
0
{
return
0
}
if
len
(
data
)
==
0
{
return
0
}
return
FromBin
(
data
[
:
len
(
data
)
-
1
])
*
256
+
uint64
(
data
[
len
(
data
)
-
1
])
return
FromBin
(
data
[
:
len
(
data
)
-
1
])
*
256
+
uint64
(
data
[
len
(
data
)
-
1
])
}
}
func
Decode
(
data
[]
byte
,
pos
int
)
(
interface
{},
int
)
{
func
Decode
(
data
[]
byte
,
pos
int
)
(
interface
{},
int
)
{
if
pos
>
len
(
data
)
-
1
{
if
pos
>
len
(
data
)
-
1
{
panic
(
fmt
.
Sprintf
(
"index out of range %d for data %q, l = %d"
,
pos
,
data
,
len
(
data
)))
panic
(
fmt
.
Sprintf
(
"index out of range %d for data %q, l = %d"
,
pos
,
data
,
len
(
data
)))
}
}
char
:=
int
(
data
[
pos
])
char
:=
int
(
data
[
pos
])
slice
:=
make
([]
interface
{},
0
)
slice
:=
make
([]
interface
{},
0
)
switch
{
switch
{
case
char
<
24
:
case
char
<
24
:
return
data
[
pos
],
pos
+
1
return
data
[
pos
],
pos
+
1
case
char
<
56
:
case
char
<
56
:
b
:=
int
(
data
[
pos
])
-
23
b
:=
int
(
data
[
pos
])
-
23
return
FromBin
(
data
[
pos
+
1
:
pos
+
1
+
b
]),
pos
+
1
+
b
return
FromBin
(
data
[
pos
+
1
:
pos
+
1
+
b
]),
pos
+
1
+
b
case
char
<
64
:
case
char
<
64
:
b
:=
int
(
data
[
pos
])
-
55
b
:=
int
(
data
[
pos
])
-
55
b2
:=
int
(
FromBin
(
data
[
pos
+
1
:
pos
+
1
+
b
]))
b2
:=
int
(
FromBin
(
data
[
pos
+
1
:
pos
+
1
+
b
]))
return
FromBin
(
data
[
pos
+
1
+
b
:
pos
+
1
+
b
+
b2
]),
pos
+
1
+
b
+
b2
return
FromBin
(
data
[
pos
+
1
+
b
:
pos
+
1
+
b
+
b2
]),
pos
+
1
+
b
+
b2
case
char
<
120
:
case
char
<
120
:
b
:=
int
(
data
[
pos
])
-
64
b
:=
int
(
data
[
pos
])
-
64
return
data
[
pos
+
1
:
pos
+
1
+
b
],
pos
+
1
+
b
return
data
[
pos
+
1
:
pos
+
1
+
b
],
pos
+
1
+
b
case
char
<
128
:
case
char
<
128
:
b
:=
int
(
data
[
pos
])
-
119
b
:=
int
(
data
[
pos
])
-
119
b2
:=
int
(
FromBin
(
data
[
pos
+
1
:
pos
+
1
+
b
]))
b2
:=
int
(
FromBin
(
data
[
pos
+
1
:
pos
+
1
+
b
]))
return
data
[
pos
+
1
+
b
:
pos
+
1
+
b
+
b2
],
pos
+
1
+
b
+
b2
return
data
[
pos
+
1
+
b
:
pos
+
1
+
b
+
b2
],
pos
+
1
+
b
+
b2
case
char
<
184
:
case
char
<
184
:
b
:=
int
(
data
[
pos
])
-
128
b
:=
int
(
data
[
pos
])
-
128
pos
++
pos
++
for
i
:=
0
;
i
<
b
;
i
++
{
for
i
:=
0
;
i
<
b
;
i
++
{
var
obj
interface
{}
var
obj
interface
{}
obj
,
pos
=
Decode
(
data
,
pos
)
obj
,
pos
=
Decode
(
data
,
pos
)
slice
=
append
(
slice
,
obj
)
slice
=
append
(
slice
,
obj
)
}
}
return
slice
,
pos
return
slice
,
pos
case
char
<
192
:
case
char
<
192
:
b
:=
int
(
data
[
pos
])
-
183
b
:=
int
(
data
[
pos
])
-
183
//b2 := int(FromBin(data[pos+1 : pos+1+b])) (ref implementation has an unused variable)
//b2 := int(FromBin(data[pos+1 : pos+1+b])) (ref implementation has an unused variable)
pos
=
pos
+
1
+
b
pos
=
pos
+
1
+
b
for
i
:=
0
;
i
<
b
;
i
++
{
for
i
:=
0
;
i
<
b
;
i
++
{
var
obj
interface
{}
var
obj
interface
{}
obj
,
pos
=
Decode
(
data
,
pos
)
obj
,
pos
=
Decode
(
data
,
pos
)
slice
=
append
(
slice
,
obj
)
slice
=
append
(
slice
,
obj
)
}
}
return
slice
,
pos
return
slice
,
pos
default
:
default
:
panic
(
fmt
.
Sprintf
(
"byte not supported: %q"
,
char
))
panic
(
fmt
.
Sprintf
(
"byte not supported: %q"
,
char
))
}
}
return
slice
,
0
return
slice
,
0
}
}
func
Encode
(
object
interface
{})
[]
byte
{
func
Encode
(
object
interface
{})
[]
byte
{
var
buff
bytes
.
Buffer
var
buff
bytes
.
Buffer
switch
t
:=
object
.
(
type
)
{
switch
t
:=
object
.
(
type
)
{
case
uint32
,
uint64
:
case
uint32
,
uint64
:
var
num
uint64
var
num
uint64
if
_num
,
ok
:=
t
.
(
uint64
);
ok
{
if
_num
,
ok
:=
t
.
(
uint64
);
ok
{
num
=
_num
num
=
_num
}
else
if
_num
,
ok
:=
t
.
(
uint32
);
ok
{
}
else
if
_num
,
ok
:=
t
.
(
uint32
);
ok
{
num
=
uint64
(
_num
)
num
=
uint64
(
_num
)
}
}
if
num
>=
0
&&
num
<
24
{
if
num
>=
0
&&
num
<
24
{
buff
.
WriteString
(
string
(
num
))
buff
.
WriteString
(
string
(
num
))
}
else
if
num
<=
uint64
(
math
.
Pow
(
2
,
256
))
{
}
else
if
num
<=
uint64
(
math
.
Pow
(
2
,
256
))
{
b
:=
ToBin
(
num
,
0
)
b
:=
ToBin
(
num
,
0
)
buff
.
WriteString
(
string
(
len
(
b
)
+
23
)
+
b
)
buff
.
WriteString
(
string
(
len
(
b
)
+
23
)
+
b
)
}
else
{
}
else
{
b
:=
ToBin
(
num
,
0
)
b
:=
ToBin
(
num
,
0
)
b2
:=
ToBin
(
uint64
(
len
(
b
)),
0
)
b2
:=
ToBin
(
uint64
(
len
(
b
)),
0
)
buff
.
WriteString
(
string
(
len
(
b2
)
+
55
)
+
b2
+
b
)
buff
.
WriteString
(
string
(
len
(
b2
)
+
55
)
+
b2
+
b
)
}
}
case
*
big
.
Int
:
case
*
big
.
Int
:
buff
.
Write
(
Encode
(
t
.
String
()))
buff
.
Write
(
Encode
(
t
.
String
()))
case
string
:
case
string
:
if
len
(
t
)
<
56
{
if
len
(
t
)
<
56
{
buff
.
WriteString
(
string
(
len
(
t
)
+
64
)
+
t
)
buff
.
WriteString
(
string
(
len
(
t
)
+
64
)
+
t
)
}
else
{
}
else
{
b2
:=
ToBin
(
uint64
(
len
(
t
)),
0
)
b2
:=
ToBin
(
uint64
(
len
(
t
)),
0
)
buff
.
WriteString
(
string
(
len
(
b2
)
+
119
)
+
b2
+
t
)
buff
.
WriteString
(
string
(
len
(
b2
)
+
119
)
+
b2
+
t
)
}
}
case
[]
byte
:
case
[]
byte
:
// Cast the byte slice to a string
// Cast the byte slice to a string
buff
.
Write
(
Encode
(
string
(
t
)))
buff
.
Write
(
Encode
(
string
(
t
)))
case
[]
interface
{},
[]
string
:
case
[]
interface
{},
[]
string
:
// Inline function for writing the slice header
// Inline function for writing the slice header
WriteSliceHeader
:=
func
(
length
int
)
{
WriteSliceHeader
:=
func
(
length
int
)
{
if
length
<
56
{
if
length
<
56
{
buff
.
WriteByte
(
byte
(
length
+
128
))
buff
.
WriteByte
(
byte
(
length
+
128
))
}
else
{
}
else
{
b2
:=
ToBin
(
uint64
(
length
),
0
)
b2
:=
ToBin
(
uint64
(
length
),
0
)
buff
.
WriteByte
(
byte
(
len
(
b2
)
+
183
))
buff
.
WriteByte
(
byte
(
len
(
b2
)
+
183
))
buff
.
WriteString
(
b2
)
buff
.
WriteString
(
b2
)
}
}
}
}
// FIXME How can I do this "better"?
// FIXME How can I do this "better"?
if
interSlice
,
ok
:=
t
.
([]
interface
{});
ok
{
if
interSlice
,
ok
:=
t
.
([]
interface
{});
ok
{
WriteSliceHeader
(
len
(
interSlice
))
WriteSliceHeader
(
len
(
interSlice
))
for
_
,
val
:=
range
interSlice
{
for
_
,
val
:=
range
interSlice
{
buff
.
Write
(
Encode
(
val
))
buff
.
Write
(
Encode
(
val
))
}
}
}
else
if
stringSlice
,
ok
:=
t
.
([]
string
);
ok
{
}
else
if
stringSlice
,
ok
:=
t
.
([]
string
);
ok
{
WriteSliceHeader
(
len
(
stringSlice
))
WriteSliceHeader
(
len
(
stringSlice
))
for
_
,
val
:=
range
stringSlice
{
for
_
,
val
:=
range
stringSlice
{
buff
.
Write
(
Encode
(
val
))
buff
.
Write
(
Encode
(
val
))
}
}
}
}
}
}
return
buff
.
Bytes
()
return
buff
.
Bytes
()
}
}
rlp_test.go
View file @
9571a512
package
main
package
main
import
(
import
(
"testing
"
"fmt
"
"fmt
"
"testing
"
)
)
func
TestEncode
(
t
*
testing
.
T
)
{
func
TestEncode
(
t
*
testing
.
T
)
{
strRes
:=
"Cdog"
strRes
:=
"Cdog"
bytes
:=
Encode
(
"dog"
)
bytes
:=
Encode
(
"dog"
)
str
:=
string
(
bytes
)
str
:=
string
(
bytes
)
if
str
!=
strRes
{
if
str
!=
strRes
{
t
.
Error
(
fmt
.
Sprintf
(
"Expected %q, got %q"
,
strRes
,
str
))
t
.
Error
(
fmt
.
Sprintf
(
"Expected %q, got %q"
,
strRes
,
str
))
}
}
//dec,_ := Decode(bytes, 0)
//dec,_ := Decode(bytes, 0)
sliceRes
:=
"
\x83
CdogCgodCcat"
sliceRes
:=
"
\x83
CdogCgodCcat"
strs
:=
[]
string
{
"dog"
,
"god"
,
"cat"
}
strs
:=
[]
string
{
"dog"
,
"god"
,
"cat"
}
bytes
=
Encode
(
strs
)
bytes
=
Encode
(
strs
)
slice
:=
string
(
bytes
)
slice
:=
string
(
bytes
)
if
slice
!=
sliceRes
{
if
slice
!=
sliceRes
{
t
.
Error
(
fmt
.
Sprintf
(
"Expected %q, got %q"
,
sliceRes
,
slice
))
t
.
Error
(
fmt
.
Sprintf
(
"Expected %q, got %q"
,
sliceRes
,
slice
))
}
}
//dec,_ = Decode(bytes, 0)
//dec,_ = Decode(bytes, 0)
}
}
func
TestMultiEncode
(
t
*
testing
.
T
)
{
func
TestMultiEncode
(
t
*
testing
.
T
)
{
inter
:=
[]
interface
{}{
inter
:=
[]
interface
{}{
[]
interface
{}{
[]
interface
{}{
"1"
,
"2"
,
"3"
,
"1"
,
"2"
,
"3"
,
},
},
[]
string
{
[]
string
{
"string"
,
"string"
,
"string2"
,
"string2"
,
"
\x86
A0J1234567890A
\x00
B20A0
\x82
F395843F657986"
,
"
\x86
A0J1234567890A
\x00
B20A0
\x82
F395843F657986"
,
"
\x86
A0J1234567890A
\x00
B20A0
\x8c
F395843F657986I335612448F524099H16716881A0H13114947G2039362G1507139H16719697G1048387E65360"
,
"
\x86
A0J1234567890A
\x00
B20A0
\x8c
F395843F657986I335612448F524099H16716881A0H13114947G2039362G1507139H16719697G1048387E65360"
,
},
},
"test"
,
"test"
,
}
}
bytes
:=
Encode
(
inter
)
bytes
:=
Encode
(
inter
)
Decode
(
bytes
,
0
)
Decode
(
bytes
,
0
)
}
}
func
BenchmarkEncodeDecode
(
b
*
testing
.
B
)
{
func
BenchmarkEncodeDecode
(
b
*
testing
.
B
)
{
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
bytes
:=
Encode
([]
string
{
"dog"
,
"god"
,
"cat"
})
bytes
:=
Encode
([]
string
{
"dog"
,
"god"
,
"cat"
})
Decode
(
bytes
,
0
)
Decode
(
bytes
,
0
)
}
}
}
}
server.go
View file @
9571a512
package
main
package
main
import
(
import
(
"container/list"
"container/list"
"net
"
"github.com/ethereum/ethdb-go
"
"log
"
"github.com/ethereum/ethutil-go
"
_
"time
"
"log
"
"github.com/ethereum/ethdb-go
"
"net
"
"github.com/ethereum/ethutil-go
"
_
"time
"
)
)
type
Server
struct
{
type
Server
struct
{
// Channel for shutting down the server
// Channel for shutting down the server
shutdownChan
chan
bool
shutdownChan
chan
bool
// DB interface
// DB interface
db
*
ethdb
.
LDBDatabase
db
*
ethdb
.
LDBDatabase
// Block manager for processing new blocks and managing the block chain
// Block manager for processing new blocks and managing the block chain
blockManager
*
BlockManager
blockManager
*
BlockManager
// Peers (NYI)
// Peers (NYI)
peers
*
list
.
List
peers
*
list
.
List
}
}
func
NewServer
()
(
*
Server
,
error
)
{
func
NewServer
()
(
*
Server
,
error
)
{
db
,
err
:=
ethdb
.
NewLDBDatabase
()
db
,
err
:=
ethdb
.
NewLDBDatabase
()
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
ethutil
.
SetConfig
(
db
)
ethutil
.
SetConfig
(
db
)
server
:=
&
Server
{
server
:=
&
Server
{
shutdownChan
:
make
(
chan
bool
),
shutdownChan
:
make
(
chan
bool
),
blockManager
:
NewBlockManager
(),
blockManager
:
NewBlockManager
(),
db
:
db
,
db
:
db
,
peers
:
list
.
New
(),
peers
:
list
.
New
(),
}
}
return
server
,
nil
return
server
,
nil
}
}
func
(
s
*
Server
)
AddPeer
(
conn
net
.
Conn
)
{
func
(
s
*
Server
)
AddPeer
(
conn
net
.
Conn
)
{
peer
:=
NewPeer
(
conn
,
s
)
peer
:=
NewPeer
(
conn
,
s
)
s
.
peers
.
PushBack
(
peer
)
s
.
peers
.
PushBack
(
peer
)
peer
.
Start
()
peer
.
Start
()
log
.
Println
(
"Peer connected ::"
,
conn
.
RemoteAddr
())
log
.
Println
(
"Peer connected ::"
,
conn
.
RemoteAddr
())
}
}
func
(
s
*
Server
)
ConnectToPeer
(
addr
string
)
error
{
func
(
s
*
Server
)
ConnectToPeer
(
addr
string
)
error
{
conn
,
err
:=
net
.
Dial
(
"tcp"
,
addr
)
conn
,
err
:=
net
.
Dial
(
"tcp"
,
addr
)
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
peer
:=
NewPeer
(
conn
,
s
)
peer
:=
NewPeer
(
conn
,
s
)
s
.
peers
.
PushBack
(
peer
)
s
.
peers
.
PushBack
(
peer
)
peer
.
Start
()
peer
.
Start
()
log
.
Println
(
"Connected to peer ::"
,
conn
.
RemoteAddr
())
log
.
Println
(
"Connected to peer ::"
,
conn
.
RemoteAddr
())
return
nil
return
nil
}
}
func
(
s
*
Server
)
Broadcast
(
msgType
string
,
data
[]
byte
)
{
func
(
s
*
Server
)
Broadcast
(
msgType
string
,
data
[]
byte
)
{
for
e
:=
s
.
peers
.
Front
();
e
!=
nil
;
e
=
e
.
Next
()
{
for
e
:=
s
.
peers
.
Front
();
e
!=
nil
;
e
=
e
.
Next
()
{
if
peer
,
ok
:=
e
.
Value
.
(
*
Peer
);
ok
{
if
peer
,
ok
:=
e
.
Value
.
(
*
Peer
);
ok
{
peer
.
QueueMessage
(
msgType
,
data
)
peer
.
QueueMessage
(
msgType
,
data
)
}
}
}
}
}
}
// Start the server
// Start the server
func
(
s
*
Server
)
Start
()
{
func
(
s
*
Server
)
Start
()
{
// For now this function just blocks the main thread
// For now this function just blocks the main thread
ln
,
err
:=
net
.
Listen
(
"tcp"
,
":12345"
)
ln
,
err
:=
net
.
Listen
(
"tcp"
,
":12345"
)
if
err
!=
nil
{
if
err
!=
nil
{
log
.
Fatal
(
err
)
log
.
Fatal
(
err
)
}
}
go
func
()
{
go
func
()
{
for
{
for
{
conn
,
err
:=
ln
.
Accept
()
conn
,
err
:=
ln
.
Accept
()
if
err
!=
nil
{
if
err
!=
nil
{
log
.
Println
(
err
)
log
.
Println
(
err
)
continue
continue
}
}
go
s
.
AddPeer
(
conn
)
go
s
.
AddPeer
(
conn
)
}
}
}()
}()
// TMP
// TMP
//go func() {
//go func() {
// for {
// for {
// s.Broadcast("block", Encode("blockdata"))
// s.Broadcast("block", Encode("blockdata"))
//
//
// time.Sleep(100 * time.Millisecond)
// time.Sleep(100 * time.Millisecond)
// }
// }
// }()
// }()
}
}
func
(
s
*
Server
)
Stop
()
{
func
(
s
*
Server
)
Stop
()
{
// Close the database
// Close the database
defer
s
.
db
.
Close
()
defer
s
.
db
.
Close
()
// Loop thru the peers and close them (if we had them)
// Loop thru the peers and close them (if we had them)
for
e
:=
s
.
peers
.
Front
();
e
!=
nil
;
e
=
e
.
Next
()
{
for
e
:=
s
.
peers
.
Front
();
e
!=
nil
;
e
=
e
.
Next
()
{
if
peer
,
ok
:=
e
.
Value
.
(
*
Peer
);
ok
{
if
peer
,
ok
:=
e
.
Value
.
(
*
Peer
);
ok
{
peer
.
Stop
()
peer
.
Stop
()
}
}
}
}
s
.
shutdownChan
<-
true
s
.
shutdownChan
<-
true
}
}
// This function will wait for a shutdown and resumes main thread execution
// This function will wait for a shutdown and resumes main thread execution
func
(
s
*
Server
)
WaitForShutdown
()
{
func
(
s
*
Server
)
WaitForShutdown
()
{
<-
s
.
shutdownChan
<-
s
.
shutdownChan
}
}
test_runner.go
View file @
9571a512
package
main
package
main
import
(
import
(
"fmt
"
"encoding/json
"
"testing
"
"fmt
"
"encoding/json
"
"testing
"
)
)
type
TestSource
struct
{
type
TestSource
struct
{
Inputs
map
[
string
]
string
Inputs
map
[
string
]
string
Expectation
string
Expectation
string
}
}
func
NewTestSource
(
source
string
)
*
TestSource
{
func
NewTestSource
(
source
string
)
*
TestSource
{
s
:=
&
TestSource
{}
s
:=
&
TestSource
{}
err
:=
json
.
Unmarshal
([]
byte
(
source
),
s
)
err
:=
json
.
Unmarshal
([]
byte
(
source
),
s
)
if
err
!=
nil
{
if
err
!=
nil
{
fmt
.
Println
(
err
)
fmt
.
Println
(
err
)
}
}
return
s
return
s
}
}
type
TestRunner
struct
{
type
TestRunner
struct
{
source
*
TestSource
source
*
TestSource
}
}
func
NewTestRunner
(
t
*
testing
.
T
)
*
TestRunner
{
func
NewTestRunner
(
t
*
testing
.
T
)
*
TestRunner
{
return
&
TestRunner
{}
return
&
TestRunner
{}
}
}
func
(
runner
*
TestRunner
)
RunFromString
(
input
string
,
Cb
func
(
*
TestSource
))
{
func
(
runner
*
TestRunner
)
RunFromString
(
input
string
,
Cb
func
(
*
TestSource
))
{
source
:=
NewTestSource
(
input
)
source
:=
NewTestSource
(
input
)
Cb
(
source
)
Cb
(
source
)
}
}
test_runner_test.go
View file @
9571a512
package
main
package
main
import
(
import
(
_
"fmt
"
"encoding/hex
"
"testing
"
_
"fmt
"
"encoding/hex
"
"testing
"
)
)
var
testsource
=
`{"Inputs":{
var
testsource
=
`{"Inputs":{
...
@@ -15,17 +15,17 @@ var testsource = `{"Inputs":{
...
@@ -15,17 +15,17 @@ var testsource = `{"Inputs":{
}`
}`
func
TestTestRunner
(
t
*
testing
.
T
)
{
func
TestTestRunner
(
t
*
testing
.
T
)
{
db
,
_
:=
NewMemDatabase
()
db
,
_
:=
NewMemDatabase
()
trie
:=
NewTrie
(
db
,
""
)
trie
:=
NewTrie
(
db
,
""
)
runner
:=
NewTestRunner
(
t
)
runner
:=
NewTestRunner
(
t
)
runner
.
RunFromString
(
testsource
,
func
(
source
*
TestSource
)
{
runner
.
RunFromString
(
testsource
,
func
(
source
*
TestSource
)
{
for
key
,
value
:=
range
source
.
Inputs
{
for
key
,
value
:=
range
source
.
Inputs
{
trie
.
Update
(
key
,
value
)
trie
.
Update
(
key
,
value
)
}
}
if
hex
.
EncodeToString
([]
byte
(
trie
.
root
))
!=
source
.
Expectation
{
if
hex
.
EncodeToString
([]
byte
(
trie
.
root
))
!=
source
.
Expectation
{
t
.
Error
(
"trie root did not match"
)
t
.
Error
(
"trie root did not match"
)
}
}
})
})
}
}
testing.go
View file @
9571a512
package
main
package
main
/*
/*
import (
import (
...
...
vm.go
View file @
9571a512
package
main
package
main
import
(
import
(
"math/big
"
"fmt
"
"fmt
"
"github.com/ethereum/ethutil-go
"
"strconv
"
"math/big
"
"github.com/ethereum/ethutil-go
"
"strconv
"
)
)
// Op codes
// Op codes
const
(
const
(
oSTOP
int
=
0x00
oSTOP
int
=
0x00
oADD
int
=
0x01
oADD
int
=
0x01
oMUL
int
=
0x02
oMUL
int
=
0x02
oSUB
int
=
0x03
oSUB
int
=
0x03
oDIV
int
=
0x04
oDIV
int
=
0x04
oSDIV
int
=
0x05
oSDIV
int
=
0x05
oMOD
int
=
0x06
oMOD
int
=
0x06
oSMOD
int
=
0x07
oSMOD
int
=
0x07
oEXP
int
=
0x08
oEXP
int
=
0x08
oNEG
int
=
0x09
oNEG
int
=
0x09
oLT
int
=
0x0a
oLT
int
=
0x0a
oLE
int
=
0x0b
oLE
int
=
0x0b
oGT
int
=
0x0c
oGT
int
=
0x0c
oGE
int
=
0x0d
oGE
int
=
0x0d
oEQ
int
=
0x0e
oEQ
int
=
0x0e
oNOT
int
=
0x0f
oNOT
int
=
0x0f
oMYADDRESS
int
=
0x10
oMYADDRESS
int
=
0x10
oTXSENDER
int
=
0x11
oTXSENDER
int
=
0x11
oTXVALUE
int
=
0x12
oTXVALUE
int
=
0x12
oTXFEE
int
=
0x13
oTXFEE
int
=
0x13
oTXDATAN
int
=
0x14
oTXDATAN
int
=
0x14
oTXDATA
int
=
0x15
oTXDATA
int
=
0x15
oBLK_PREVHASH
int
=
0x16
oBLK_PREVHASH
int
=
0x16
oBLK_COINBASE
int
=
0x17
oBLK_COINBASE
int
=
0x17
oBLK_TIMESTAMP
int
=
0x18
oBLK_TIMESTAMP
int
=
0x18
oBLK_NUMBER
int
=
0x19
oBLK_NUMBER
int
=
0x19
oBLK_DIFFICULTY
int
=
0x1a
oBLK_DIFFICULTY
int
=
0x1a
oSHA256
int
=
0x20
oSHA256
int
=
0x20
oRIPEMD160
int
=
0x21
oRIPEMD160
int
=
0x21
oECMUL
int
=
0x22
oECMUL
int
=
0x22
oECADD
int
=
0x23
oECADD
int
=
0x23
oECSIGN
int
=
0x24
oECSIGN
int
=
0x24
oECRECOVER
int
=
0x25
oECRECOVER
int
=
0x25
oECVALID
int
=
0x26
oECVALID
int
=
0x26
oPUSH
int
=
0x30
oPUSH
int
=
0x30
oPOP
int
=
0x31
oPOP
int
=
0x31
oDUP
int
=
0x32
oDUP
int
=
0x32
oDUPN
int
=
0x33
oDUPN
int
=
0x33
oSWAP
int
=
0x34
oSWAP
int
=
0x34
oSWAPN
int
=
0x35
oSWAPN
int
=
0x35
oLOAD
int
=
0x36
oLOAD
int
=
0x36
oSTORE
int
=
0x37
oSTORE
int
=
0x37
oJMP
int
=
0x40
oJMP
int
=
0x40
oJMPI
int
=
0x41
oJMPI
int
=
0x41
oIND
int
=
0x42
oIND
int
=
0x42
oEXTRO
int
=
0x50
oEXTRO
int
=
0x50
oBALANCE
int
=
0x51
oBALANCE
int
=
0x51
oMKTX
int
=
0x60
oMKTX
int
=
0x60
oSUICIDE
int
=
0xff
oSUICIDE
int
=
0xff
)
)
type
OpType
int
type
OpType
int
const
(
const
(
tNorm
=
iota
tNorm
=
iota
tData
tData
tExtro
tExtro
tCrypto
tCrypto
)
)
type
TxCallback
func
(
opType
OpType
)
bool
type
TxCallback
func
(
opType
OpType
)
bool
// Simple push/pop stack mechanism
// Simple push/pop stack mechanism
type
Stack
struct
{
type
Stack
struct
{
data
[]
string
data
[]
string
}
}
func
NewStack
()
*
Stack
{
func
NewStack
()
*
Stack
{
return
&
Stack
{}
return
&
Stack
{}
}
}
func
(
st
*
Stack
)
Pop
()
string
{
func
(
st
*
Stack
)
Pop
()
string
{
s
:=
len
(
st
.
data
)
s
:=
len
(
st
.
data
)
str
:=
st
.
data
[
s
-
1
]
str
:=
st
.
data
[
s
-
1
]
st
.
data
=
st
.
data
[
:
s
-
1
]
st
.
data
=
st
.
data
[
:
s
-
1
]
return
str
return
str
}
}
func
(
st
*
Stack
)
Popn
()
(
*
big
.
Int
,
*
big
.
Int
)
{
func
(
st
*
Stack
)
Popn
()
(
*
big
.
Int
,
*
big
.
Int
)
{
s
:=
len
(
st
.
data
)
s
:=
len
(
st
.
data
)
strs
:=
st
.
data
[
s
-
2
:
]
strs
:=
st
.
data
[
s
-
2
:
]
st
.
data
=
st
.
data
[
:
s
-
2
]
st
.
data
=
st
.
data
[
:
s
-
2
]
return
ethutil
.
Big
(
strs
[
0
]),
ethutil
.
Big
(
strs
[
1
])
return
ethutil
.
Big
(
strs
[
0
]),
ethutil
.
Big
(
strs
[
1
])
}
}
func
(
st
*
Stack
)
Push
(
d
string
)
{
func
(
st
*
Stack
)
Push
(
d
string
)
{
st
.
data
=
append
(
st
.
data
,
d
)
st
.
data
=
append
(
st
.
data
,
d
)
}
}
func
(
st
*
Stack
)
Print
()
{
func
(
st
*
Stack
)
Print
()
{
fmt
.
Println
(
st
.
data
)
fmt
.
Println
(
st
.
data
)
}
}
type
Vm
struct
{
type
Vm
struct
{
// Stack
// Stack
stack
*
Stack
stack
*
Stack
}
}
func
NewVm
()
*
Vm
{
func
NewVm
()
*
Vm
{
return
&
Vm
{
return
&
Vm
{
stack
:
NewStack
(),
stack
:
NewStack
(),
}
}
}
}
func
(
vm
*
Vm
)
ProcContract
(
tx
*
ethutil
.
Transaction
,
func
(
vm
*
Vm
)
ProcContract
(
tx
*
ethutil
.
Transaction
,
block
*
ethutil
.
Block
,
cb
TxCallback
)
{
block
*
ethutil
.
Block
,
cb
TxCallback
)
{
// Instruction pointer
// Instruction pointer
pc
:=
0
pc
:=
0
contract
:=
block
.
GetContract
(
tx
.
Hash
())
contract
:=
block
.
GetContract
(
tx
.
Hash
())
if
contract
==
nil
{
if
contract
==
nil
{
fmt
.
Println
(
"Contract not found"
)
fmt
.
Println
(
"Contract not found"
)
return
return
}
}
Pow256
:=
ethutil
.
BigPow
(
2
,
256
)
Pow256
:=
ethutil
.
BigPow
(
2
,
256
)
//fmt.Printf("# op arg\n")
//fmt.Printf("# op arg\n")
out
:
out
:
for
{
for
{
// The base big int for all calculations. Use this for any results.
// The base big int for all calculations. Use this for any results.
base
:=
new
(
big
.
Int
)
base
:=
new
(
big
.
Int
)
// XXX Should Instr return big int slice instead of string slice?
// XXX Should Instr return big int slice instead of string slice?
// Get the next instruction from the contract
// Get the next instruction from the contract
//op, _, _ := Instr(contract.state.Get(string(Encode(uint32(pc)))))
//op, _, _ := Instr(contract.state.Get(string(Encode(uint32(pc)))))
nb
:=
ethutil
.
NumberToBytes
(
uint64
(
pc
),
32
)
nb
:=
ethutil
.
NumberToBytes
(
uint64
(
pc
),
32
)
op
,
_
,
_
:=
ethutil
.
Instr
(
contract
.
State
()
.
Get
(
string
(
nb
)))
op
,
_
,
_
:=
ethutil
.
Instr
(
contract
.
State
()
.
Get
(
string
(
nb
)))
if
!
cb
(
0
)
{
break
}
if
!
cb
(
0
)
{
break
}
if
Debug
{
if
Debug
{
//fmt.Printf("%-3d %-4d\n", pc, op)
//fmt.Printf("%-3d %-4d\n", pc, op)
}
}
switch
op
{
switch
op
{
case
oADD
:
case
oADD
:
x
,
y
:=
vm
.
stack
.
Popn
()
x
,
y
:=
vm
.
stack
.
Popn
()
// (x + y) % 2 ** 256
// (x + y) % 2 ** 256
base
.
Add
(
x
,
y
)
base
.
Add
(
x
,
y
)
base
.
Mod
(
base
,
Pow256
)
base
.
Mod
(
base
,
Pow256
)
// Pop result back on the stack
// Pop result back on the stack
vm
.
stack
.
Push
(
base
.
String
())
vm
.
stack
.
Push
(
base
.
String
())
case
oSUB
:
case
oSUB
:
x
,
y
:=
vm
.
stack
.
Popn
()
x
,
y
:=
vm
.
stack
.
Popn
()
// (x - y) % 2 ** 256
// (x - y) % 2 ** 256
base
.
Sub
(
x
,
y
)
base
.
Sub
(
x
,
y
)
base
.
Mod
(
base
,
Pow256
)
base
.
Mod
(
base
,
Pow256
)
// Pop result back on the stack
// Pop result back on the stack
vm
.
stack
.
Push
(
base
.
String
())
vm
.
stack
.
Push
(
base
.
String
())
case
oMUL
:
case
oMUL
:
x
,
y
:=
vm
.
stack
.
Popn
()
x
,
y
:=
vm
.
stack
.
Popn
()
// (x * y) % 2 ** 256
// (x * y) % 2 ** 256
base
.
Mul
(
x
,
y
)
base
.
Mul
(
x
,
y
)
base
.
Mod
(
base
,
Pow256
)
base
.
Mod
(
base
,
Pow256
)
// Pop result back on the stack
// Pop result back on the stack
vm
.
stack
.
Push
(
base
.
String
())
vm
.
stack
.
Push
(
base
.
String
())
case
oDIV
:
case
oDIV
:
x
,
y
:=
vm
.
stack
.
Popn
()
x
,
y
:=
vm
.
stack
.
Popn
()
// floor(x / y)
// floor(x / y)
base
.
Div
(
x
,
y
)
base
.
Div
(
x
,
y
)
// Pop result back on the stack
// Pop result back on the stack
vm
.
stack
.
Push
(
base
.
String
())
vm
.
stack
.
Push
(
base
.
String
())
case
oSDIV
:
case
oSDIV
:
x
,
y
:=
vm
.
stack
.
Popn
()
x
,
y
:=
vm
.
stack
.
Popn
()
// n > 2**255
// n > 2**255
if
x
.
Cmp
(
Pow256
)
>
0
{
x
.
Sub
(
Pow256
,
x
)
}
if
x
.
Cmp
(
Pow256
)
>
0
{
if
y
.
Cmp
(
Pow256
)
>
0
{
y
.
Sub
(
Pow256
,
y
)
}
x
.
Sub
(
Pow256
,
x
)
z
:=
new
(
big
.
Int
)
}
z
.
Div
(
x
,
y
)
if
y
.
Cmp
(
Pow256
)
>
0
{
if
z
.
Cmp
(
Pow256
)
>
0
{
z
.
Sub
(
Pow256
,
z
)
}
y
.
Sub
(
Pow256
,
y
)
// Push result on to the stack
}
vm
.
stack
.
Push
(
z
.
String
())
z
:=
new
(
big
.
Int
)
case
oMOD
:
z
.
Div
(
x
,
y
)
x
,
y
:=
vm
.
stack
.
Popn
()
if
z
.
Cmp
(
Pow256
)
>
0
{
base
.
Mod
(
x
,
y
)
z
.
Sub
(
Pow256
,
z
)
vm
.
stack
.
Push
(
base
.
String
())
}
case
oSMOD
:
// Push result on to the stack
x
,
y
:=
vm
.
stack
.
Popn
()
vm
.
stack
.
Push
(
z
.
String
())
// n > 2**255
case
oMOD
:
if
x
.
Cmp
(
Pow256
)
>
0
{
x
.
Sub
(
Pow256
,
x
)
}
x
,
y
:=
vm
.
stack
.
Popn
()
if
y
.
Cmp
(
Pow256
)
>
0
{
y
.
Sub
(
Pow256
,
y
)
}
base
.
Mod
(
x
,
y
)
z
:=
new
(
big
.
Int
)
vm
.
stack
.
Push
(
base
.
String
())
z
.
Mod
(
x
,
y
)
case
oSMOD
:
if
z
.
Cmp
(
Pow256
)
>
0
{
z
.
Sub
(
Pow256
,
z
)
}
x
,
y
:=
vm
.
stack
.
Popn
()
// Push result on to the stack
// n > 2**255
vm
.
stack
.
Push
(
z
.
String
())
if
x
.
Cmp
(
Pow256
)
>
0
{
case
oEXP
:
x
.
Sub
(
Pow256
,
x
)
x
,
y
:=
vm
.
stack
.
Popn
()
}
base
.
Exp
(
x
,
y
,
Pow256
)
if
y
.
Cmp
(
Pow256
)
>
0
{
y
.
Sub
(
Pow256
,
y
)
}
z
:=
new
(
big
.
Int
)
z
.
Mod
(
x
,
y
)
if
z
.
Cmp
(
Pow256
)
>
0
{
z
.
Sub
(
Pow256
,
z
)
}
// Push result on to the stack
vm
.
stack
.
Push
(
z
.
String
())
case
oEXP
:
x
,
y
:=
vm
.
stack
.
Popn
()
base
.
Exp
(
x
,
y
,
Pow256
)
vm
.
stack
.
Push
(
base
.
String
())
vm
.
stack
.
Push
(
base
.
String
())
case
oNEG
:
case
oNEG
:
base
.
Sub
(
Pow256
,
ethutil
.
Big
(
vm
.
stack
.
Pop
()))
base
.
Sub
(
Pow256
,
ethutil
.
Big
(
vm
.
stack
.
Pop
()))
vm
.
stack
.
Push
(
base
.
String
())
vm
.
stack
.
Push
(
base
.
String
())
case
oLT
:
case
oLT
:
x
,
y
:=
vm
.
stack
.
Popn
()
x
,
y
:=
vm
.
stack
.
Popn
()
// x < y
// x < y
if
x
.
Cmp
(
y
)
<
0
{
if
x
.
Cmp
(
y
)
<
0
{
vm
.
stack
.
Push
(
"1"
)
vm
.
stack
.
Push
(
"1"
)
}
else
{
}
else
{
vm
.
stack
.
Push
(
"0"
)
vm
.
stack
.
Push
(
"0"
)
}
}
case
oLE
:
case
oLE
:
x
,
y
:=
vm
.
stack
.
Popn
()
x
,
y
:=
vm
.
stack
.
Popn
()
// x <= y
// x <= y
if
x
.
Cmp
(
y
)
<
1
{
if
x
.
Cmp
(
y
)
<
1
{
vm
.
stack
.
Push
(
"1"
)
vm
.
stack
.
Push
(
"1"
)
}
else
{
}
else
{
vm
.
stack
.
Push
(
"0"
)
vm
.
stack
.
Push
(
"0"
)
}
}
case
oGT
:
case
oGT
:
x
,
y
:=
vm
.
stack
.
Popn
()
x
,
y
:=
vm
.
stack
.
Popn
()
// x > y
// x > y
if
x
.
Cmp
(
y
)
>
0
{
if
x
.
Cmp
(
y
)
>
0
{
vm
.
stack
.
Push
(
"1"
)
vm
.
stack
.
Push
(
"1"
)
}
else
{
}
else
{
vm
.
stack
.
Push
(
"0"
)
vm
.
stack
.
Push
(
"0"
)
}
}
case
oGE
:
case
oGE
:
x
,
y
:=
vm
.
stack
.
Popn
()
x
,
y
:=
vm
.
stack
.
Popn
()
// x >= y
// x >= y
if
x
.
Cmp
(
y
)
>
-
1
{
if
x
.
Cmp
(
y
)
>
-
1
{
vm
.
stack
.
Push
(
"1"
)
vm
.
stack
.
Push
(
"1"
)
}
else
{
}
else
{
vm
.
stack
.
Push
(
"0"
)
vm
.
stack
.
Push
(
"0"
)
}
}
case
oNOT
:
case
oNOT
:
x
,
y
:=
vm
.
stack
.
Popn
()
x
,
y
:=
vm
.
stack
.
Popn
()
// x != y
// x != y
if
x
.
Cmp
(
y
)
!=
0
{
if
x
.
Cmp
(
y
)
!=
0
{
vm
.
stack
.
Push
(
"1"
)
vm
.
stack
.
Push
(
"1"
)
}
else
{
}
else
{
vm
.
stack
.
Push
(
"0"
)
vm
.
stack
.
Push
(
"0"
)
}
}
case
oMYADDRESS
:
case
oMYADDRESS
:
vm
.
stack
.
Push
(
string
(
tx
.
Hash
()))
vm
.
stack
.
Push
(
string
(
tx
.
Hash
()))
case
oTXSENDER
:
case
oTXSENDER
:
vm
.
stack
.
Push
(
string
(
tx
.
Sender
()))
vm
.
stack
.
Push
(
string
(
tx
.
Sender
()))
case
oPUSH
:
case
oPUSH
:
// Get the next entry and pushes the value on the stack
// Get the next entry and pushes the value on the stack
pc
++
pc
++
vm
.
stack
.
Push
(
contract
.
State
()
.
Get
(
string
(
ethutil
.
NumberToBytes
(
uint64
(
pc
),
32
))))
vm
.
stack
.
Push
(
contract
.
State
()
.
Get
(
string
(
ethutil
.
NumberToBytes
(
uint64
(
pc
),
32
))))
case
oPOP
:
case
oPOP
:
// Pop current value of the stack
// Pop current value of the stack
vm
.
stack
.
Pop
()
vm
.
stack
.
Pop
()
case
oLOAD
:
case
oLOAD
:
// Load instruction X on the stack
// Load instruction X on the stack
i
,
_
:=
strconv
.
Atoi
(
vm
.
stack
.
Pop
())
i
,
_
:=
strconv
.
Atoi
(
vm
.
stack
.
Pop
())
vm
.
stack
.
Push
(
contract
.
State
()
.
Get
(
string
(
ethutil
.
NumberToBytes
(
uint64
(
i
),
32
))))
vm
.
stack
.
Push
(
contract
.
State
()
.
Get
(
string
(
ethutil
.
NumberToBytes
(
uint64
(
i
),
32
))))
case
oSTOP
:
case
oSTOP
:
break
out
break
out
}
}
pc
++
pc
++
}
}
vm
.
stack
.
Print
()
vm
.
stack
.
Print
()
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment