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
Expand all
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
-c launch the developer console
-m start mining fake blocks and broadcast fake messages to the net
Contribution
============
See CONTRIB.md
block_manager.go
View file @
9571a512
package
main
import
(
"fmt"
"github.com/ethereum/ethutil-go"
"fmt"
"github.com/ethereum/ethutil-go"
)
type
BlockChain
struct
{
lastBlock
*
ethutil
.
Block
lastBlock
*
ethutil
.
Block
genesisBlock
*
ethutil
.
Block
genesisBlock
*
ethutil
.
Block
}
func
NewBlockChain
()
*
BlockChain
{
bc
:=
&
BlockChain
{}
bc
.
genesisBlock
=
ethutil
.
NewBlock
(
ethutil
.
Encode
(
ethutil
.
Genesis
)
)
bc
:=
&
BlockChain
{}
bc
.
genesisBlock
=
ethutil
.
NewBlock
(
ethutil
.
Encode
(
ethutil
.
Genesis
)
)
return
bc
return
bc
}
type
BlockManager
struct
{
vm
*
Vm
vm
*
Vm
blockChain
*
BlockChain
blockChain
*
BlockChain
}
func
NewBlockManager
()
*
BlockManager
{
bm
:=
&
BlockManager
{
vm
:
NewVm
()}
bm
:=
&
BlockManager
{
vm
:
NewVm
()}
return
bm
return
bm
}
// Process a block.
func
(
bm
*
BlockManager
)
ProcessBlock
(
block
*
ethutil
.
Block
)
error
{
// TODO Validation (Or move to other part of the application)
if
err
:=
bm
.
ValidateBlock
(
block
);
err
!=
nil
{
return
err
}
// Get the tx count. Used to create enough channels to 'join' the go routines
txCount
:=
len
(
block
.
Transactions
())
// Locking channel. When it has been fully buffered this method will return
lockChan
:=
make
(
chan
bool
,
txCount
)
// Process each transaction/contract
for
_
,
tx
:=
range
block
.
Transactions
()
{
// If there's no recipient, it's a contract
if
tx
.
IsContract
()
{
go
bm
.
ProcessContract
(
tx
,
block
,
lockChan
)
}
else
{
// "finish" tx which isn't a contract
lockChan
<-
true
}
}
// Wait for all Tx to finish processing
for
i
:=
0
;
i
<
txCount
;
i
++
{
<-
lockChan
}
return
nil
// TODO Validation (Or move to other part of the application)
if
err
:=
bm
.
ValidateBlock
(
block
);
err
!=
nil
{
return
err
}
// Get the tx count. Used to create enough channels to 'join' the go routines
txCount
:=
len
(
block
.
Transactions
())
// Locking channel. When it has been fully buffered this method will return
lockChan
:=
make
(
chan
bool
,
txCount
)
// Process each transaction/contract
for
_
,
tx
:=
range
block
.
Transactions
()
{
// If there's no recipient, it's a contract
if
tx
.
IsContract
()
{
go
bm
.
ProcessContract
(
tx
,
block
,
lockChan
)
}
else
{
// "finish" tx which isn't a contract
lockChan
<-
true
}
}
// Wait for all Tx to finish processing
for
i
:=
0
;
i
<
txCount
;
i
++
{
<-
lockChan
}
return
nil
}
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
)
{
// Recovering function in case the VM had any errors
defer
func
()
{
if
r
:=
recover
();
r
!=
nil
{
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)
lockChan
<-
true
}
}()
// Process contract
bm
.
vm
.
ProcContract
(
tx
,
block
,
func
(
opType
OpType
)
bool
{
// TODO turn on once big ints are in place
//if !block.PayFee(tx.Hash(), StepFee.Uint64()) {
// return false
//}
return
true
// Continue
})
// Broadcast we're done
lockChan
<-
true
// Recovering function in case the VM had any errors
defer
func
()
{
if
r
:=
recover
();
r
!=
nil
{
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)
lockChan
<-
true
}
}()
// Process contract
bm
.
vm
.
ProcContract
(
tx
,
block
,
func
(
opType
OpType
)
bool
{
// TODO turn on once big ints are in place
//if !block.PayFee(tx.Hash(), StepFee.Uint64()) {
// return false
//}
return
true
// Continue
})
// Broadcast we're done
lockChan
<-
true
}
dagger.go
View file @
9571a512
package
main
import
(
"math/big
"
"math/rand
"
"time
"
"github.com/obscuren/sha3
"
"hash
"
"github.com/ethereum/ethutil-go
"
"github.com/ethereum/ethutil-go
"
"github.com/obscuren/sha3
"
"hash
"
"math/big
"
"math/rand
"
"time
"
)
type
Dagger
struct
{
hash
*
big
.
Int
xn
*
big
.
Int
hash
*
big
.
Int
xn
*
big
.
Int
}
var
Found
bool
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
++
{
rnd
:=
r
.
Int63
()
for
i
:=
0
;
i
<
1000
;
i
++
{
rnd
:=
r
.
Int63
()
if
dag
.
Eval
(
big
.
NewInt
(
rnd
))
.
Cmp
(
obj
)
<
0
{
// Post back result on the channel
resChan
<-
rnd
// Notify other threads we've found a valid nonce
Found
=
true
}
if
dag
.
Eval
(
big
.
NewInt
(
rnd
))
.
Cmp
(
obj
)
<
0
{
// Post back result on the channel
resChan
<-
rnd
// Notify other threads we've found a valid nonce
Found
=
true
}
// Break out if found
if
Found
{
break
}
}
// Break out if found
if
Found
{
break
}
}
resChan
<-
0
resChan
<-
0
}
func
(
dag
*
Dagger
)
Search
(
hash
,
diff
*
big
.
Int
)
*
big
.
Int
{
// TODO fix multi threading. Somehow it results in the wrong nonce
amountOfRoutines
:=
1
// TODO fix multi threading. Somehow it results in the wrong nonce
amountOfRoutines
:=
1
dag
.
hash
=
hash
dag
.
hash
=
hash
obj
:=
ethutil
.
BigPow
(
2
,
256
)
obj
=
obj
.
Div
(
obj
,
diff
)
obj
:=
ethutil
.
BigPow
(
2
,
256
)
obj
=
obj
.
Div
(
obj
,
diff
)
Found
=
false
resChan
:=
make
(
chan
int64
,
3
)
var
res
int64
Found
=
false
resChan
:=
make
(
chan
int64
,
3
)
var
res
int64
for
k
:=
0
;
k
<
amountOfRoutines
;
k
++
{
go
dag
.
Find
(
obj
,
resChan
)
}
for
k
:=
0
;
k
<
amountOfRoutines
;
k
++
{
go
dag
.
Find
(
obj
,
resChan
)
}
// Wait for each go routine to finish
for
k
:=
0
;
k
<
amountOfRoutines
;
k
++
{
// Get the result from the channel. 0 = quit
if
r
:=
<-
resChan
;
r
!=
0
{
res
=
r
}
}
// Wait for each go routine to finish
for
k
:=
0
;
k
<
amountOfRoutines
;
k
++
{
// Get the result from the channel. 0 = quit
if
r
:=
<-
resChan
;
r
!=
0
{
res
=
r
}
}
return
big
.
NewInt
(
res
)
return
big
.
NewInt
(
res
)
}
func
DaggerVerify
(
hash
,
diff
,
nonce
*
big
.
Int
)
bool
{
dagger
:=
&
Dagger
{}
dagger
.
hash
=
hash
dagger
:=
&
Dagger
{}
dagger
.
hash
=
hash
obj
:=
ethutil
.
BigPow
(
2
,
256
)
obj
=
obj
.
Div
(
obj
,
diff
)
obj
:=
ethutil
.
BigPow
(
2
,
256
)
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
{
if
L
==
i
{
return
dag
.
hash
}
var
m
*
big
.
Int
if
L
==
9
{
m
=
big
.
NewInt
(
16
)
}
else
{
m
=
big
.
NewInt
(
3
)
}
sha
:=
sha3
.
NewKeccak256
()
sha
.
Reset
()
d
:=
sha3
.
NewKeccak256
()
b
:=
new
(
big
.
Int
)
ret
:=
new
(
big
.
Int
)
for
k
:=
0
;
k
<
int
(
m
.
Uint64
());
k
++
{
d
.
Reset
()
d
.
Write
(
dag
.
hash
.
Bytes
())
d
.
Write
(
dag
.
xn
.
Bytes
())
d
.
Write
(
big
.
NewInt
(
int64
(
L
))
.
Bytes
())
d
.
Write
(
big
.
NewInt
(
int64
(
i
))
.
Bytes
())
d
.
Write
(
big
.
NewInt
(
int64
(
k
))
.
Bytes
())
b
.
SetBytes
(
Sum
(
d
))
pk
:=
b
.
Uint64
()
&
((
1
<<
((
L
-
1
)
*
3
))
-
1
)
sha
.
Write
(
dag
.
Node
(
L
-
1
,
pk
)
.
Bytes
())
}
ret
.
SetBytes
(
Sum
(
sha
))
return
ret
if
L
==
i
{
return
dag
.
hash
}
var
m
*
big
.
Int
if
L
==
9
{
m
=
big
.
NewInt
(
16
)
}
else
{
m
=
big
.
NewInt
(
3
)
}
sha
:=
sha3
.
NewKeccak256
()
sha
.
Reset
()
d
:=
sha3
.
NewKeccak256
()
b
:=
new
(
big
.
Int
)
ret
:=
new
(
big
.
Int
)
for
k
:=
0
;
k
<
int
(
m
.
Uint64
());
k
++
{
d
.
Reset
()
d
.
Write
(
dag
.
hash
.
Bytes
())
d
.
Write
(
dag
.
xn
.
Bytes
())
d
.
Write
(
big
.
NewInt
(
int64
(
L
))
.
Bytes
())
d
.
Write
(
big
.
NewInt
(
int64
(
i
))
.
Bytes
())
d
.
Write
(
big
.
NewInt
(
int64
(
k
))
.
Bytes
())
b
.
SetBytes
(
Sum
(
d
))
pk
:=
b
.
Uint64
()
&
((
1
<<
((
L
-
1
)
*
3
))
-
1
)
sha
.
Write
(
dag
.
Node
(
L
-
1
,
pk
)
.
Bytes
())
}
ret
.
SetBytes
(
Sum
(
sha
))
return
ret
}
func
Sum
(
sha
hash
.
Hash
)
[]
byte
{
in
:=
make
([]
byte
,
32
)
return
sha
.
Sum
(
in
)
in
:=
make
([]
byte
,
32
)
return
sha
.
Sum
(
in
)
}
func
(
dag
*
Dagger
)
Eval
(
N
*
big
.
Int
)
*
big
.
Int
{
pow
:=
ethutil
.
BigPow
(
2
,
26
)
dag
.
xn
=
N
.
Div
(
N
,
pow
)
pow
:=
ethutil
.
BigPow
(
2
,
26
)
dag
.
xn
=
N
.
Div
(
N
,
pow
)
sha
:=
sha3
.
NewKeccak256
()
sha
.
Reset
()
ret
:=
new
(
big
.
Int
)
sha
:=
sha3
.
NewKeccak256
()
sha
.
Reset
()
ret
:=
new
(
big
.
Int
)
for
k
:=
0
;
k
<
4
;
k
++
{
d
:=
sha3
.
NewKeccak256
()
b
:=
new
(
big
.
Int
)
for
k
:=
0
;
k
<
4
;
k
++
{
d
:=
sha3
.
NewKeccak256
()
b
:=
new
(
big
.
Int
)
d
.
Reset
()
d
.
Write
(
dag
.
hash
.
Bytes
())
d
.
Write
(
dag
.
xn
.
Bytes
())
d
.
Write
(
N
.
Bytes
())
d
.
Write
(
big
.
NewInt
(
int64
(
k
))
.
Bytes
())
d
.
Reset
()
d
.
Write
(
dag
.
hash
.
Bytes
())
d
.
Write
(
dag
.
xn
.
Bytes
())
d
.
Write
(
N
.
Bytes
())
d
.
Write
(
big
.
NewInt
(
int64
(
k
))
.
Bytes
())
b
.
SetBytes
(
Sum
(
d
))
pk
:=
(
b
.
Uint64
()
&
0x1ffffff
)
b
.
SetBytes
(
Sum
(
d
))
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
import
(
"testin
g"
"math/bi
g"
"math/bi
g"
"testin
g"
)
func
BenchmarkDaggerSearch
(
b
*
testing
.
B
)
{
hash
:=
big
.
NewInt
(
0
)
diff
:=
BigPow
(
2
,
36
)
o
:=
big
.
NewInt
(
0
)
// nonce doesn't matter. We're only testing against speed, not validity
hash
:=
big
.
NewInt
(
0
)
diff
:=
BigPow
(
2
,
36
)
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
b
.
ResetTimer
()
// Validate
DaggerVerify
(
hash
,
diff
,
o
)
// Reset timer so the big generation isn't included in the benchmark
b
.
ResetTimer
()
// Validate
DaggerVerify
(
hash
,
diff
,
o
)
}
dev_console.go
View file @
9571a512
package
main
import
(
"fmt
"
"bufio
"
"string
s"
"os
"
"errors
"
"encoding/hex
"
"github.com/ethereum/ethdb-go
"
"github.com/ethereum/ethutil-go
"
"bufio
"
"encoding/hex
"
"error
s"
"fmt
"
"github.com/ethereum/ethdb-go
"
"github.com/ethereum/ethutil-go
"
"os
"
"strings
"
)
type
Console
struct
{
db
*
ethdb
.
MemDatabase
trie
*
ethutil
.
Trie
db
*
ethdb
.
MemDatabase
trie
*
ethutil
.
Trie
}
func
NewConsole
()
*
Console
{
db
,
_
:=
ethdb
.
NewMemDatabase
()
trie
:=
ethutil
.
NewTrie
(
db
,
""
)
db
,
_
:=
ethdb
.
NewMemDatabase
()
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
{
err
:=
false
var
expArgCount
int
err
:=
false
var
expArgCount
int
switch
{
case
action
==
"update"
&&
argumentLength
!=
2
:
err
=
true
expArgCount
=
2
case
action
==
"get"
&&
argumentLength
!=
1
:
err
=
true
expArgCount
=
1
case
action
==
"dag"
&&
argumentLength
!=
2
:
err
=
true
expArgCount
=
2
}
switch
{
case
action
==
"update"
&&
argumentLength
!=
2
:
err
=
true
expArgCount
=
2
case
action
==
"get"
&&
argumentLength
!=
1
:
err
=
true
expArgCount
=
1
case
action
==
"dag"
&&
argumentLength
!=
2
:
err
=
true
expArgCount
=
2
}
if
err
{
return
errors
.
New
(
fmt
.
Sprintf
(
"'%s' requires %d args, got %d"
,
action
,
expArgCount
,
argumentLength
))
}
else
{
return
nil
}
if
err
{
return
errors
.
New
(
fmt
.
Sprintf
(
"'%s' requires %d args, got %d"
,
action
,
expArgCount
,
argumentLength
))
}
else
{
return
nil
}
}
func
(
i
*
Console
)
ParseInput
(
input
string
)
bool
{
scanner
:=
bufio
.
NewScanner
(
strings
.
NewReader
(
input
))
scanner
.
Split
(
bufio
.
ScanWords
)
scanner
:=
bufio
.
NewScanner
(
strings
.
NewReader
(
input
))
scanner
.
Split
(
bufio
.
ScanWords
)
count
:=
0
var
tokens
[]
string
for
scanner
.
Scan
()
{
count
++
tokens
=
append
(
tokens
,
scanner
.
Text
())
}
if
err
:=
scanner
.
Err
();
err
!=
nil
{
fmt
.
Fprintln
(
os
.
Stderr
,
"reading input:"
,
err
)
}
count
:=
0
var
tokens
[]
string
for
scanner
.
Scan
()
{
count
++
tokens
=
append
(
tokens
,
scanner
.
Text
())
}
if
err
:=
scanner
.
Err
();
err
!=
nil
{
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
)
if
err
!=
nil
{
fmt
.
Println
(
err
)
}
else
{
switch
tokens
[
0
]
{
case
"update"
:
i
.
trie
.
Update
(
tokens
[
1
],
tokens
[
2
])
err
:=
i
.
ValidateInput
(
tokens
[
0
],
count
-
1
)
if
err
!=
nil
{
fmt
.
Println
(
err
)
}
else
{
switch
tokens
[
0
]
{
case
"update"
:
i
.
trie
.
Update
(
tokens
[
1
],
tokens
[
2
])
fmt
.
Println
(
hex
.
EncodeToString
([]
byte
(
i
.
trie
.
Root
)))
case
"get"
:
fmt
.
Println
(
i
.
trie
.
Get
(
tokens
[
1
]))
case
"root"
:
fmt
.
Println
(
hex
.
EncodeToString
([]
byte
(
i
.
trie
.
Root
)))
case
"rawroot"
:
fmt
.
Println
(
i
.
trie
.
Root
)
case
"print"
:
i
.
db
.
Print
()
case
"dag"
:
fmt
.
Println
(
DaggerVerify
(
ethutil
.
Big
(
tokens
[
1
]),
// hash
ethutil
.
BigPow
(
2
,
36
),
// diff
ethutil
.
Big
(
tokens
[
2
])))
// nonce
case
"exit"
,
"quit"
,
"q"
:
return
false
case
"help"
:
fmt
.
Printf
(
"COMMANDS:
\n
"
+
"
\0
33[1m= DB =
\0
33[0m
\n
"
+
"update KEY VALUE - Updates/Creates a new value for the given key
\n
"
+
"get KEY - Retrieves the given key
\n
"
+
"root - Prints the hex encoded merkle root
\n
"
+
"rawroot - Prints the raw merkle root
\n
"
+
"
\0
33[1m= Dagger =
\0
33[0m
\n
"
+
"dag HASH NONCE - Verifies a nonce with the given hash with dagger
\n
"
)
default
:
fmt
.
Println
(
"Unknown command:"
,
tokens
[
0
])
}
}
fmt
.
Println
(
hex
.
EncodeToString
([]
byte
(
i
.
trie
.
Root
)))
case
"get"
:
fmt
.
Println
(
i
.
trie
.
Get
(
tokens
[
1
]))
case
"root"
:
fmt
.
Println
(
hex
.
EncodeToString
([]
byte
(
i
.
trie
.
Root
)))
case
"rawroot"
:
fmt
.
Println
(
i
.
trie
.
Root
)
case
"print"
:
i
.
db
.
Print
()
case
"dag"
:
fmt
.
Println
(
DaggerVerify
(
ethutil
.
Big
(
tokens
[
1
]),
// hash
ethutil
.
BigPow
(
2
,
36
),
// diff
ethutil
.
Big
(
tokens
[
2
])))
// nonce
case
"exit"
,
"quit"
,
"q"
:
return
false
case
"help"
:
fmt
.
Printf
(
"COMMANDS:
\n
"
+
"
\0
33[1m= DB =
\0
33[0m
\n
"
+
"update KEY VALUE - Updates/Creates a new value for the given key
\n
"
+
"get KEY - Retrieves the given key
\n
"
+
"root - Prints the hex encoded merkle root
\n
"
+
"rawroot - Prints the raw merkle root
\n
"
+
"
\0
33[1m= Dagger =
\0
33[0m
\n
"
+
"dag HASH NONCE - Verifies a nonce with the given hash with dagger
\n
"
)
default
:
fmt
.
Println
(
"Unknown command:"
,
tokens
[
0
])
}
}
return
true
return
true
}
func
(
i
*
Console
)
Start
()
{
fmt
.
Printf
(
"Eth Console. Type (help) for help
\n
"
)
reader
:=
bufio
.
NewReader
(
os
.
Stdin
)
for
{
fmt
.
Printf
(
"eth >>> "
)
str
,
_
,
err
:=
reader
.
ReadLine
()
if
err
!=
nil
{
fmt
.
Println
(
"Error reading input"
,
err
)
}
else
{
if
!
i
.
ParseInput
(
string
(
str
))
{
return
}
}
}
fmt
.
Printf
(
"Eth Console. Type (help) for help
\n
"
)
reader
:=
bufio
.
NewReader
(
os
.
Stdin
)
for
{
fmt
.
Printf
(
"eth >>> "
)
str
,
_
,
err
:=
reader
.
ReadLine
()
if
err
!=
nil
{
fmt
.
Println
(
"Error reading input"
,
err
)
}
else
{
if
!
i
.
ParseInput
(
string
(
str
))
{
return
}
}
}
}
ethereum.go
View file @
9571a512
package
main
import
(
"fmt
"
"os
"
"os/signal
"
"fla
g"
"runtime
"
"log
"
"github.com/ethereum/ethutil-go
"
"flag
"
"fmt
"
"github.com/ethereum/ethutil-go
"
"lo
g"
"os
"
"os/signal
"
"runtime
"
)
const
Debug
=
true
var
StartConsole
bool
var
StartMining
bool
func
Init
()
{
flag
.
BoolVar
(
&
StartConsole
,
"c"
,
false
,
"debug and testing console"
)
flag
.
BoolVar
(
&
StartMining
,
"m"
,
false
,
"start dagger mining"
)
flag
.
BoolVar
(
&
StartConsole
,
"c"
,
false
,
"debug and testing console"
)
flag
.
BoolVar
(
&
StartMining
,
"m"
,
false
,
"start dagger mining"
)
flag
.
Parse
()
flag
.
Parse
()
}
// Register interrupt handlers so we can stop the server
func
RegisterInterupts
(
s
*
Server
)
{
// Buffered chan of one is enough
c
:=
make
(
chan
os
.
Signal
,
1
)
// Notify about interrupts for now
signal
.
Notify
(
c
,
os
.
Interrupt
)
go
func
()
{
for
sig
:=
range
c
{
fmt
.
Printf
(
"Shutting down (%v) ...
\n
"
,
sig
)
s
.
Stop
()
}
}()
// Buffered chan of one is enough
c
:=
make
(
chan
os
.
Signal
,
1
)
// Notify about interrupts for now
signal
.
Notify
(
c
,
os
.
Interrupt
)
go
func
()
{
for
sig
:=
range
c
{
fmt
.
Printf
(
"Shutting down (%v) ...
\n
"
,
sig
)
s
.
Stop
()
}
}()
}
func
main
()
{
runtime
.
GOMAXPROCS
(
runtime
.
NumCPU
())
ethutil
.
InitFees
()
Init
()
if
StartConsole
{
console
:=
NewConsole
()
console
.
Start
()
}
else
{
log
.
Println
(
"Starting Ethereum"
)
server
,
err
:=
NewServer
()
if
err
!=
nil
{
log
.
Println
(
err
)
return
}
RegisterInterupts
(
server
)
if
StartMining
{
log
.
Println
(
"Mining started"
)
dagger
:=
&
Dagger
{}
go
func
()
{
for
{
res
:=
dagger
.
Search
(
ethutil
.
Big
(
"0"
),
ethutil
.
BigPow
(
2
,
36
))
server
.
Broadcast
(
"block"
,
Encode
(
res
.
String
()))
}
}()
}
server
.
Start
()
err
=
server
.
ConnectToPeer
(
"localhost:12345"
)
if
err
!=
nil
{
log
.
Println
(
err
)
server
.
Stop
()
return
}
// Wait for shutdown
server
.
WaitForShutdown
()
}
runtime
.
GOMAXPROCS
(
runtime
.
NumCPU
())
ethutil
.
InitFees
()
Init
()
if
StartConsole
{
console
:=
NewConsole
()
console
.
Start
()
}
else
{
log
.
Println
(
"Starting Ethereum"
)
server
,
err
:=
NewServer
()
if
err
!=
nil
{
log
.
Println
(
err
)
return
}
RegisterInterupts
(
server
)
if
StartMining
{
log
.
Println
(
"Mining started"
)
dagger
:=
&
Dagger
{}
go
func
()
{
for
{
res
:=
dagger
.
Search
(
ethutil
.
Big
(
"0"
),
ethutil
.
BigPow
(
2
,
36
))
server
.
Broadcast
(
"block"
,
Encode
(
res
.
String
()))
}
}()
}
server
.
Start
()
err
=
server
.
ConnectToPeer
(
"localhost:12345"
)
if
err
!=
nil
{
log
.
Println
(
err
)
server
.
Stop
()
return
}
// Wait for shutdown
server
.
WaitForShutdown
()
}
}
peer.go
View file @
9571a512
package
main
import
(
"net
"
"log"
"github.com/ethereum/ethwire-go
"
"github.com/ethereum/ethwire-go
"
"log"
"net
"
)
type
Peer
struct
{
// Server interface
server
*
Server
// Net connection
conn
net
.
Conn
// Output queue which is used to communicate and handle messages
outputQueue
chan
ethwire
.
InOutMsg
// Quit channel
quit
chan
bool
// Server interface
server
*
Server
// Net connection
conn
net
.
Conn
// Output queue which is used to communicate and handle messages
outputQueue
chan
ethwire
.
InOutMsg
// Quit channel
quit
chan
bool
}
func
NewPeer
(
conn
net
.
Conn
,
server
*
Server
)
*
Peer
{
return
&
Peer
{
outputQueue
:
make
(
chan
ethwire
.
InOutMsg
,
1
),
// Buffered chan of 1 is enough
quit
:
make
(
chan
bool
),
return
&
Peer
{
outputQueue
:
make
(
chan
ethwire
.
InOutMsg
,
1
),
// Buffered chan of 1 is enough
quit
:
make
(
chan
bool
),
server
:
server
,
conn
:
conn
,
}
server
:
server
,
conn
:
conn
,
}
}
// Outputs any RLP encoded data to the peer
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
func
(
p
*
Peer
)
HandleOutbound
()
{
out
:
for
{
select
{
// Main message queue. All outbound messages are processed through here
case
msg
:=
<-
p
.
outputQueue
:
// TODO Message checking and handle accordingly
err
:=
ethwire
.
WriteMessage
(
p
.
conn
,
msg
)
if
err
!=
nil
{
log
.
Println
(
err
)
// Stop the client if there was an error writing to it
p
.
Stop
()
}
// Break out of the for loop if a quit message is posted
case
<-
p
.
quit
:
break
out
}
}
for
{
select
{
// Main message queue. All outbound messages are processed through here
case
msg
:=
<-
p
.
outputQueue
:
// TODO Message checking and handle accordingly
err
:=
ethwire
.
WriteMessage
(
p
.
conn
,
msg
)
if
err
!=
nil
{
log
.
Println
(
err
)
// Stop the client if there was an error writing to it
p
.
Stop
()
}
// Break out of the for loop if a quit message is posted
case
<-
p
.
quit
:
break
out
}
}
}
// Inbound handler. Inbound messages are received here and passed to the appropriate methods
func
(
p
*
Peer
)
HandleInbound
()
{
defer
p
.
Stop
()
defer
p
.
Stop
()
out
:
for
{
// Wait for a message from the peer
msg
,
err
:=
ethwire
.
ReadMessage
(
p
.
conn
)
if
err
!=
nil
{
log
.
Println
(
err
)
break
out
}
// TODO
data
,
_
:=
Decode
(
msg
.
Data
,
0
)
log
.
Printf
(
"%s, %s
\n
"
,
msg
.
MsgType
,
data
)
}
// Notify the out handler we're quiting
p
.
quit
<-
true
for
{
// Wait for a message from the peer
msg
,
err
:=
ethwire
.
ReadMessage
(
p
.
conn
)
if
err
!=
nil
{
log
.
Println
(
err
)
break
out
}
// TODO
data
,
_
:=
Decode
(
msg
.
Data
,
0
)
log
.
Printf
(
"%s, %s
\n
"
,
msg
.
MsgType
,
data
)
}
// Notify the out handler we're quiting
p
.
quit
<-
true
}
func
(
p
*
Peer
)
Start
()
{
// Run the outbound handler in a new goroutine
go
p
.
HandleOutbound
()
// Run the inbound handler in a new goroutine
go
p
.
HandleInbound
()
// Run the outbound handler in a new goroutine
go
p
.
HandleOutbound
()
// Run the inbound handler in a new goroutine
go
p
.
HandleInbound
()
}
func
(
p
*
Peer
)
Stop
()
{
p
.
conn
.
Close
()
p
.
conn
.
Close
()
p
.
quit
<-
true
p
.
quit
<-
true
}
rlp.go
View file @
9571a512
This diff is collapsed.
Click to expand it.
rlp_test.go
View file @
9571a512
package
main
import
(
"testing
"
"fmt
"
"fmt
"
"testing
"
)
func
TestEncode
(
t
*
testing
.
T
)
{
strRes
:=
"Cdog"
strRes
:=
"Cdog"
bytes
:=
Encode
(
"dog"
)
bytes
:=
Encode
(
"dog"
)
str
:=
string
(
bytes
)
if
str
!=
strRes
{
t
.
Error
(
fmt
.
Sprintf
(
"Expected %q, got %q"
,
strRes
,
str
))
}
//dec,_ := Decode(bytes, 0)
str
:=
string
(
bytes
)
if
str
!=
strRes
{
t
.
Error
(
fmt
.
Sprintf
(
"Expected %q, got %q"
,
strRes
,
str
))
}
//dec,_ := Decode(bytes, 0)
sliceRes
:=
"
\x83
CdogCgodCcat"
strs
:=
[]
string
{
"dog"
,
"god"
,
"cat"
}
bytes
=
Encode
(
strs
)
slice
:=
string
(
bytes
)
if
slice
!=
sliceRes
{
t
.
Error
(
fmt
.
Sprintf
(
"Expected %q, got %q"
,
sliceRes
,
slice
))
}
sliceRes
:=
"
\x83
CdogCgodCcat"
strs
:=
[]
string
{
"dog"
,
"god"
,
"cat"
}
bytes
=
Encode
(
strs
)
slice
:=
string
(
bytes
)
if
slice
!=
sliceRes
{
t
.
Error
(
fmt
.
Sprintf
(
"Expected %q, got %q"
,
sliceRes
,
slice
))
}
//dec,_ = Decode(bytes, 0)
//dec,_ = Decode(bytes, 0)
}
func
TestMultiEncode
(
t
*
testing
.
T
)
{
inter
:=
[]
interface
{}{
[]
interface
{}{
"1"
,
"2"
,
"3"
,
},
[]
string
{
"string"
,
"string2"
,
"
\x86
A0J1234567890A
\x00
B20A0
\x82
F395843F657986"
,
"
\x86
A0J1234567890A
\x00
B20A0
\x8c
F395843F657986I335612448F524099H16716881A0H13114947G2039362G1507139H16719697G1048387E65360"
,
},
"test"
,
}
bytes
:=
Encode
(
inter
)
Decode
(
bytes
,
0
)
inter
:=
[]
interface
{}{
[]
interface
{}{
"1"
,
"2"
,
"3"
,
},
[]
string
{
"string"
,
"string2"
,
"
\x86
A0J1234567890A
\x00
B20A0
\x82
F395843F657986"
,
"
\x86
A0J1234567890A
\x00
B20A0
\x8c
F395843F657986I335612448F524099H16716881A0H13114947G2039362G1507139H16719697G1048387E65360"
,
},
"test"
,
}
bytes
:=
Encode
(
inter
)
Decode
(
bytes
,
0
)
}
func
BenchmarkEncodeDecode
(
b
*
testing
.
B
)
{
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
bytes
:=
Encode
([]
string
{
"dog"
,
"god"
,
"cat"
})
Decode
(
bytes
,
0
)
}
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
bytes
:=
Encode
([]
string
{
"dog"
,
"god"
,
"cat"
})
Decode
(
bytes
,
0
)
}
}
server.go
View file @
9571a512
package
main
import
(
"container/list"
"net
"
"log
"
_
"time
"
"github.com/ethereum/ethdb-go
"
"github.com/ethereum/ethutil-go
"
"container/list"
"github.com/ethereum/ethdb-go
"
"github.com/ethereum/ethutil-go
"
"log
"
"net
"
_
"time
"
)
type
Server
struct
{
// Channel for shutting down the server
shutdownChan
chan
bool
// DB interface
db
*
ethdb
.
LDBDatabase
// Block manager for processing new blocks and managing the block chain
blockManager
*
BlockManager
// Peers (NYI)
peers
*
list
.
List
// Channel for shutting down the server
shutdownChan
chan
bool
// DB interface
db
*
ethdb
.
LDBDatabase
// Block manager for processing new blocks and managing the block chain
blockManager
*
BlockManager
// Peers (NYI)
peers
*
list
.
List
}
func
NewServer
()
(
*
Server
,
error
)
{
db
,
err
:=
ethdb
.
NewLDBDatabase
()
if
err
!=
nil
{
return
nil
,
err
}
db
,
err
:=
ethdb
.
NewLDBDatabase
()
if
err
!=
nil
{
return
nil
,
err
}
ethutil
.
SetConfig
(
db
)
ethutil
.
SetConfig
(
db
)
server
:=
&
Server
{
shutdownChan
:
make
(
chan
bool
),
blockManager
:
NewBlockManager
(),
db
:
db
,
peers
:
list
.
New
(),
}
server
:=
&
Server
{
shutdownChan
:
make
(
chan
bool
),
blockManager
:
NewBlockManager
(),
db
:
db
,
peers
:
list
.
New
(),
}
return
server
,
nil
return
server
,
nil
}
func
(
s
*
Server
)
AddPeer
(
conn
net
.
Conn
)
{
peer
:=
NewPeer
(
conn
,
s
)
s
.
peers
.
PushBack
(
peer
)
peer
.
Start
()
peer
:=
NewPeer
(
conn
,
s
)
s
.
peers
.
PushBack
(
peer
)
peer
.
Start
()
log
.
Println
(
"Peer connected ::"
,
conn
.
RemoteAddr
())
log
.
Println
(
"Peer connected ::"
,
conn
.
RemoteAddr
())
}
func
(
s
*
Server
)
ConnectToPeer
(
addr
string
)
error
{
conn
,
err
:=
net
.
Dial
(
"tcp"
,
addr
)
conn
,
err
:=
net
.
Dial
(
"tcp"
,
addr
)
if
err
!=
nil
{
return
err
}
if
err
!=
nil
{
return
err
}
peer
:=
NewPeer
(
conn
,
s
)
s
.
peers
.
PushBack
(
peer
)
peer
.
Start
()
peer
:=
NewPeer
(
conn
,
s
)
s
.
peers
.
PushBack
(
peer
)
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
)
{
for
e
:=
s
.
peers
.
Front
();
e
!=
nil
;
e
=
e
.
Next
()
{
if
peer
,
ok
:=
e
.
Value
.
(
*
Peer
);
ok
{
peer
.
QueueMessage
(
msgType
,
data
)
}
}
for
e
:=
s
.
peers
.
Front
();
e
!=
nil
;
e
=
e
.
Next
()
{
if
peer
,
ok
:=
e
.
Value
.
(
*
Peer
);
ok
{
peer
.
QueueMessage
(
msgType
,
data
)
}
}
}
// Start the server
func
(
s
*
Server
)
Start
()
{
// For now this function just blocks the main thread
ln
,
err
:=
net
.
Listen
(
"tcp"
,
":12345"
)
if
err
!=
nil
{
log
.
Fatal
(
err
)
}
go
func
()
{
for
{
conn
,
err
:=
ln
.
Accept
()
if
err
!=
nil
{
log
.
Println
(
err
)
continue
}
go
s
.
AddPeer
(
conn
)
}
}()
// TMP
//go func() {
// for {
// s.Broadcast("block", Encode("blockdata"))
//
// time.Sleep(100 * time.Millisecond)
// }
// }()
// For now this function just blocks the main thread
ln
,
err
:=
net
.
Listen
(
"tcp"
,
":12345"
)
if
err
!=
nil
{
log
.
Fatal
(
err
)
}
go
func
()
{
for
{
conn
,
err
:=
ln
.
Accept
()
if
err
!=
nil
{
log
.
Println
(
err
)
continue
}
go
s
.
AddPeer
(
conn
)
}
}()
// TMP
//go func() {
// for {
// s.Broadcast("block", Encode("blockdata"))
//
// time.Sleep(100 * time.Millisecond)
// }
// }()
}
func
(
s
*
Server
)
Stop
()
{
// Close the database
defer
s
.
db
.
Close
()
// Close the database
defer
s
.
db
.
Close
()
// Loop thru the peers and close them (if we had them)
for
e
:=
s
.
peers
.
Front
();
e
!=
nil
;
e
=
e
.
Next
()
{
if
peer
,
ok
:=
e
.
Value
.
(
*
Peer
);
ok
{
peer
.
Stop
()
}
}
// Loop thru the peers and close them (if we had them)
for
e
:=
s
.
peers
.
Front
();
e
!=
nil
;
e
=
e
.
Next
()
{
if
peer
,
ok
:=
e
.
Value
.
(
*
Peer
);
ok
{
peer
.
Stop
()
}
}
s
.
shutdownChan
<-
true
s
.
shutdownChan
<-
true
}
// This function will wait for a shutdown and resumes main thread execution
func
(
s
*
Server
)
WaitForShutdown
()
{
<-
s
.
shutdownChan
<-
s
.
shutdownChan
}
test_runner.go
View file @
9571a512
package
main
import
(
"fmt
"
"testing
"
"encoding/json
"
"encoding/json
"
"fmt
"
"testing
"
)
type
TestSource
struct
{
Inputs
map
[
string
]
string
Expectation
string
Inputs
map
[
string
]
string
Expectation
string
}
func
NewTestSource
(
source
string
)
*
TestSource
{
s
:=
&
TestSource
{}
err
:=
json
.
Unmarshal
([]
byte
(
source
),
s
)
if
err
!=
nil
{
fmt
.
Println
(
err
)
}
s
:=
&
TestSource
{}
err
:=
json
.
Unmarshal
([]
byte
(
source
),
s
)
if
err
!=
nil
{
fmt
.
Println
(
err
)
}
return
s
return
s
}
type
TestRunner
struct
{
source
*
TestSource
source
*
TestSource
}
func
NewTestRunner
(
t
*
testing
.
T
)
*
TestRunner
{
return
&
TestRunner
{}
return
&
TestRunner
{}
}
func
(
runner
*
TestRunner
)
RunFromString
(
input
string
,
Cb
func
(
*
TestSource
))
{
source
:=
NewTestSource
(
input
)
Cb
(
source
)
source
:=
NewTestSource
(
input
)
Cb
(
source
)
}
test_runner_test.go
View file @
9571a512
package
main
import
(
_
"fmt
"
"testing
"
"encoding/hex
"
"encoding/hex
"
_
"fmt
"
"testing
"
)
var
testsource
=
`{"Inputs":{
...
...
@@ -15,17 +15,17 @@ var testsource = `{"Inputs":{
}`
func
TestTestRunner
(
t
*
testing
.
T
)
{
db
,
_
:=
NewMemDatabase
()
trie
:=
NewTrie
(
db
,
""
)
db
,
_
:=
NewMemDatabase
()
trie
:=
NewTrie
(
db
,
""
)
runner
:=
NewTestRunner
(
t
)
runner
.
RunFromString
(
testsource
,
func
(
source
*
TestSource
)
{
for
key
,
value
:=
range
source
.
Inputs
{
trie
.
Update
(
key
,
value
)
}
runner
:=
NewTestRunner
(
t
)
runner
.
RunFromString
(
testsource
,
func
(
source
*
TestSource
)
{
for
key
,
value
:=
range
source
.
Inputs
{
trie
.
Update
(
key
,
value
)
}
if
hex
.
EncodeToString
([]
byte
(
trie
.
root
))
!=
source
.
Expectation
{
t
.
Error
(
"trie root did not match"
)
}
})
if
hex
.
EncodeToString
([]
byte
(
trie
.
root
))
!=
source
.
Expectation
{
t
.
Error
(
"trie root did not match"
)
}
})
}
testing.go
View file @
9571a512
package
main
/*
import (
...
...
vm.go
View file @
9571a512
This diff is collapsed.
Click to expand it.
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