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
8c4eca24
Commit
8c4eca24
authored
Jan 16, 2014
by
obscuren
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Moved the vm code the block manager and added more opcodes
parent
33004d70
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
78 additions
and
375 deletions
+78
-375
block_manager.go
block_manager.go
+78
-15
vm.go
vm.go
+0
-284
vm_test.go
vm_test.go
+0
-76
No files found.
block_manager.go
View file @
8c4eca24
...
...
@@ -6,14 +6,14 @@ import (
"github.com/ethereum/ethutil-go"
"log"
"math/big"
"strconv"
)
type
BlockChain
struct
{
// Last block
LastBlock
*
ethutil
.
Block
// The famous, the fabulous Mister GENESIIIIIIS (block)
genesisBlock
*
ethutil
.
Block
// Last known total difficulty
TD
*
big
.
Int
}
...
...
@@ -22,11 +22,10 @@ func NewBlockChain() *BlockChain {
bc
.
genesisBlock
=
ethutil
.
NewBlock
(
ethutil
.
Encode
(
ethutil
.
Genesis
))
// Set the last know difficulty (might be 0x0 as initial value, Genesis)
bc
.
TD
=
new
(
big
.
Int
)
bc
.
TD
.
SetBytes
(
ethutil
.
Config
.
Db
.
LastKnownTD
())
bc
.
TD
=
ethutil
.
BigD
(
ethutil
.
Config
.
Db
.
LastKnownTD
())
// TODO get last block from the database
//
bc.LastBlock = bc.genesisBlock
bc
.
LastBlock
=
bc
.
genesisBlock
return
bc
}
...
...
@@ -46,6 +45,9 @@ type BlockManager struct {
// Stack for processing contracts
stack
*
Stack
// Last known block number
LastBlockNumber
*
big
.
Int
}
func
NewBlockManager
()
*
BlockManager
{
...
...
@@ -54,6 +56,10 @@ func NewBlockManager() *BlockManager {
stack
:
NewStack
(),
}
// Set the last known block number based on the blockchains last
// block
bm
.
LastBlockNumber
=
bm
.
BlockInfo
(
bm
.
bc
.
LastBlock
)
.
Number
return
bm
}
...
...
@@ -99,6 +105,20 @@ func (bm *BlockManager) ProcessBlock(block *ethutil.Block) error {
return
nil
}
func
(
bm
*
BlockManager
)
writeBlockInfo
(
block
*
ethutil
.
Block
)
{
bi
:=
ethutil
.
BlockInfo
{
Number
:
bm
.
LastBlockNumber
.
Add
(
bm
.
LastBlockNumber
,
big
.
NewInt
(
1
))}
ethutil
.
Config
.
Db
.
Put
(
append
(
block
.
Hash
(),
[]
byte
(
"Info"
)
...
),
bi
.
MarshalRlp
())
}
func
(
bm
*
BlockManager
)
BlockInfo
(
block
*
ethutil
.
Block
)
ethutil
.
BlockInfo
{
bi
:=
ethutil
.
BlockInfo
{}
data
,
_
:=
ethutil
.
Config
.
Db
.
Get
(
append
(
block
.
Hash
(),
[]
byte
(
"Info"
)
...
))
bi
.
UnmarshalRlp
(
data
)
return
bi
}
func
(
bm
*
BlockManager
)
CalculateTD
(
block
*
ethutil
.
Block
)
bool
{
uncleDiff
:=
new
(
big
.
Int
)
for
_
,
uncle
:=
range
block
.
Uncles
{
...
...
@@ -204,10 +224,11 @@ func (bm *BlockManager) ProcessContract(tx *ethutil.Transaction, block *ethutil.
lockChan
<-
true
}
func
(
bm
*
BlockManager
)
ProcContract
(
tx
*
ethutil
.
Transaction
,
block
*
ethutil
.
Block
,
cb
TxCallback
)
{
// Contract evaluation is done here.
func
(
bm
*
BlockManager
)
ProcContract
(
tx
*
ethutil
.
Transaction
,
block
*
ethutil
.
Block
,
cb
TxCallback
)
{
// Instruction pointer
pc
:=
0
blockInfo
:=
bm
.
BlockInfo
(
block
)
contract
:=
block
.
GetContract
(
tx
.
Hash
())
if
contract
==
nil
{
...
...
@@ -238,6 +259,8 @@ out:
}
switch
op
{
case
oSTOP
:
break
out
case
oADD
:
x
,
y
:=
bm
.
stack
.
Popn
()
// (x + y) % 2 ** 256
...
...
@@ -378,7 +401,34 @@ out:
case
oBLK_TIMESTAMP
:
bm
.
stack
.
Push
(
big
.
NewInt
(
block
.
Time
)
.
String
())
case
oBLK_NUMBER
:
bm
.
stack
.
Push
(
blockInfo
.
Number
.
String
())
case
oBLK_DIFFICULTY
:
bm
.
stack
.
Push
(
block
.
Difficulty
.
String
())
case
oBASEFEE
:
// e = 10^21
e
:=
big
.
NewInt
(
0
)
.
Exp
(
big
.
NewInt
(
10
),
big
.
NewInt
(
21
),
big
.
NewInt
(
0
))
d
:=
new
(
big
.
Rat
)
d
.
SetInt
(
block
.
Difficulty
)
c
:=
new
(
big
.
Rat
)
c
.
SetFloat64
(
0.5
)
// d = diff / 0.5
d
.
Quo
(
d
,
c
)
// base = floor(d)
base
.
Div
(
d
.
Num
(),
d
.
Denom
())
x
:=
new
(
big
.
Int
)
x
.
Div
(
e
,
base
)
// x = floor(10^21 / floor(diff^0.5))
bm
.
stack
.
Push
(
x
.
String
())
case
oSHA256
:
case
oRIPEMD160
:
case
oECMUL
:
case
oECADD
:
case
oECSIGN
:
case
oECRECOVER
:
case
oECVALID
:
case
oSHA3
:
case
oPUSH
:
// Get the next entry and pushes the value on the stack
pc
++
...
...
@@ -386,12 +436,25 @@ out:
case
oPOP
:
// Pop current value of the stack
bm
.
stack
.
Pop
()
case
oLOAD
:
// Load instruction X on the stack
i
,
_
:=
strconv
.
Atoi
(
bm
.
stack
.
Pop
())
bm
.
stack
.
Push
(
contract
.
State
()
.
Get
(
string
(
ethutil
.
NumberToBytes
(
uint64
(
i
),
32
))))
case
oSTOP
:
break
out
case
oDUP
:
case
oSWAP
:
case
oMLOAD
:
case
oMSTORE
:
case
oSLOAD
:
case
oSSTORE
:
case
oJMP
:
case
oJMPI
:
case
oIND
:
case
oEXTRO
:
case
oBALANCE
:
case
oMKTX
:
case
oSUICIDE
:
/*
case oLOAD:
// Load instruction X on the stack
i, _ := strconv.Atoi(bm.stack.Pop())
bm.stack.Push(contract.State().Get(string(ethutil.NumberToBytes(uint64(i), 32))))
*/
}
pc
++
}
...
...
vm.go
deleted
100644 → 0
View file @
33004d70
package
main
import
(
"fmt"
"github.com/ethereum/ethutil-go"
"math/big"
"strconv"
)
// Op codes
const
(
oSTOP
int
=
0x00
oADD
int
=
0x01
oMUL
int
=
0x02
oSUB
int
=
0x03
oDIV
int
=
0x04
oSDIV
int
=
0x05
oMOD
int
=
0x06
oSMOD
int
=
0x07
oEXP
int
=
0x08
oNEG
int
=
0x09
oLT
int
=
0x0a
oLE
int
=
0x0b
oGT
int
=
0x0c
oGE
int
=
0x0d
oEQ
int
=
0x0e
oNOT
int
=
0x0f
oMYADDRESS
int
=
0x10
oTXSENDER
int
=
0x11
oTXVALUE
int
=
0x12
oTXFEE
int
=
0x13
oTXDATAN
int
=
0x14
oTXDATA
int
=
0x15
oBLK_PREVHASH
int
=
0x16
oBLK_COINBASE
int
=
0x17
oBLK_TIMESTAMP
int
=
0x18
oBLK_NUMBER
int
=
0x19
oBLK_DIFFICULTY
int
=
0x1a
oSHA256
int
=
0x20
oRIPEMD160
int
=
0x21
oECMUL
int
=
0x22
oECADD
int
=
0x23
oECSIGN
int
=
0x24
oECRECOVER
int
=
0x25
oECVALID
int
=
0x26
oPUSH
int
=
0x30
oPOP
int
=
0x31
oDUP
int
=
0x32
oDUPN
int
=
0x33
oSWAP
int
=
0x34
oSWAPN
int
=
0x35
oLOAD
int
=
0x36
oSTORE
int
=
0x37
oJMP
int
=
0x40
oJMPI
int
=
0x41
oIND
int
=
0x42
oEXTRO
int
=
0x50
oBALANCE
int
=
0x51
oMKTX
int
=
0x60
oSUICIDE
int
=
0xff
)
type
OpType
int
const
(
tNorm
=
iota
tData
tExtro
tCrypto
)
type
TxCallback
func
(
opType
OpType
)
bool
// Simple push/pop stack mechanism
type
Stack
struct
{
data
[]
string
}
func
NewStack
()
*
Stack
{
return
&
Stack
{}
}
func
(
st
*
Stack
)
Pop
()
string
{
s
:=
len
(
st
.
data
)
str
:=
st
.
data
[
s
-
1
]
st
.
data
=
st
.
data
[
:
s
-
1
]
return
str
}
func
(
st
*
Stack
)
Popn
()
(
*
big
.
Int
,
*
big
.
Int
)
{
s
:=
len
(
st
.
data
)
strs
:=
st
.
data
[
s
-
2
:
]
st
.
data
=
st
.
data
[
:
s
-
2
]
return
ethutil
.
Big
(
strs
[
0
]),
ethutil
.
Big
(
strs
[
1
])
}
func
(
st
*
Stack
)
Push
(
d
string
)
{
st
.
data
=
append
(
st
.
data
,
d
)
}
func
(
st
*
Stack
)
Print
()
{
fmt
.
Println
(
st
.
data
)
}
type
Vm
struct
{
// Stack
stack
*
Stack
}
func
NewVm
()
*
Vm
{
return
&
Vm
{
stack
:
NewStack
(),
}
}
func
(
vm
*
Vm
)
ProcContract
(
tx
*
ethutil
.
Transaction
,
block
*
ethutil
.
Block
,
cb
TxCallback
)
{
// Instruction pointer
pc
:=
0
contract
:=
block
.
GetContract
(
tx
.
Hash
())
if
contract
==
nil
{
fmt
.
Println
(
"Contract not found"
)
return
}
Pow256
:=
ethutil
.
BigPow
(
2
,
256
)
//fmt.Printf("# op arg\n")
out
:
for
{
// The base big int for all calculations. Use this for any results.
base
:=
new
(
big
.
Int
)
// XXX Should Instr return big int slice instead of string slice?
// Get the next instruction from the contract
//op, _, _ := Instr(contract.state.Get(string(Encode(uint32(pc)))))
nb
:=
ethutil
.
NumberToBytes
(
uint64
(
pc
),
32
)
op
,
_
,
_
:=
ethutil
.
Instr
(
contract
.
State
()
.
Get
(
string
(
nb
)))
if
!
cb
(
0
)
{
break
}
if
Debug
{
//fmt.Printf("%-3d %-4d\n", pc, op)
}
switch
op
{
case
oADD
:
x
,
y
:=
vm
.
stack
.
Popn
()
// (x + y) % 2 ** 256
base
.
Add
(
x
,
y
)
base
.
Mod
(
base
,
Pow256
)
// Pop result back on the stack
vm
.
stack
.
Push
(
base
.
String
())
case
oSUB
:
x
,
y
:=
vm
.
stack
.
Popn
()
// (x - y) % 2 ** 256
base
.
Sub
(
x
,
y
)
base
.
Mod
(
base
,
Pow256
)
// Pop result back on the stack
vm
.
stack
.
Push
(
base
.
String
())
case
oMUL
:
x
,
y
:=
vm
.
stack
.
Popn
()
// (x * y) % 2 ** 256
base
.
Mul
(
x
,
y
)
base
.
Mod
(
base
,
Pow256
)
// Pop result back on the stack
vm
.
stack
.
Push
(
base
.
String
())
case
oDIV
:
x
,
y
:=
vm
.
stack
.
Popn
()
// floor(x / y)
base
.
Div
(
x
,
y
)
// Pop result back on the stack
vm
.
stack
.
Push
(
base
.
String
())
case
oSDIV
:
x
,
y
:=
vm
.
stack
.
Popn
()
// n > 2**255
if
x
.
Cmp
(
Pow256
)
>
0
{
x
.
Sub
(
Pow256
,
x
)
}
if
y
.
Cmp
(
Pow256
)
>
0
{
y
.
Sub
(
Pow256
,
y
)
}
z
:=
new
(
big
.
Int
)
z
.
Div
(
x
,
y
)
if
z
.
Cmp
(
Pow256
)
>
0
{
z
.
Sub
(
Pow256
,
z
)
}
// Push result on to the stack
vm
.
stack
.
Push
(
z
.
String
())
case
oMOD
:
x
,
y
:=
vm
.
stack
.
Popn
()
base
.
Mod
(
x
,
y
)
vm
.
stack
.
Push
(
base
.
String
())
case
oSMOD
:
x
,
y
:=
vm
.
stack
.
Popn
()
// n > 2**255
if
x
.
Cmp
(
Pow256
)
>
0
{
x
.
Sub
(
Pow256
,
x
)
}
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
())
case
oNEG
:
base
.
Sub
(
Pow256
,
ethutil
.
Big
(
vm
.
stack
.
Pop
()))
vm
.
stack
.
Push
(
base
.
String
())
case
oLT
:
x
,
y
:=
vm
.
stack
.
Popn
()
// x < y
if
x
.
Cmp
(
y
)
<
0
{
vm
.
stack
.
Push
(
"1"
)
}
else
{
vm
.
stack
.
Push
(
"0"
)
}
case
oLE
:
x
,
y
:=
vm
.
stack
.
Popn
()
// x <= y
if
x
.
Cmp
(
y
)
<
1
{
vm
.
stack
.
Push
(
"1"
)
}
else
{
vm
.
stack
.
Push
(
"0"
)
}
case
oGT
:
x
,
y
:=
vm
.
stack
.
Popn
()
// x > y
if
x
.
Cmp
(
y
)
>
0
{
vm
.
stack
.
Push
(
"1"
)
}
else
{
vm
.
stack
.
Push
(
"0"
)
}
case
oGE
:
x
,
y
:=
vm
.
stack
.
Popn
()
// x >= y
if
x
.
Cmp
(
y
)
>
-
1
{
vm
.
stack
.
Push
(
"1"
)
}
else
{
vm
.
stack
.
Push
(
"0"
)
}
case
oNOT
:
x
,
y
:=
vm
.
stack
.
Popn
()
// x != y
if
x
.
Cmp
(
y
)
!=
0
{
vm
.
stack
.
Push
(
"1"
)
}
else
{
vm
.
stack
.
Push
(
"0"
)
}
case
oMYADDRESS
:
vm
.
stack
.
Push
(
string
(
tx
.
Hash
()))
case
oTXSENDER
:
vm
.
stack
.
Push
(
string
(
tx
.
Sender
()))
case
oPUSH
:
// Get the next entry and pushes the value on the stack
pc
++
vm
.
stack
.
Push
(
contract
.
State
()
.
Get
(
string
(
ethutil
.
NumberToBytes
(
uint64
(
pc
),
32
))))
case
oPOP
:
// Pop current value of the stack
vm
.
stack
.
Pop
()
case
oLOAD
:
// Load instruction X on the stack
i
,
_
:=
strconv
.
Atoi
(
vm
.
stack
.
Pop
())
vm
.
stack
.
Push
(
contract
.
State
()
.
Get
(
string
(
ethutil
.
NumberToBytes
(
uint64
(
i
),
32
))))
case
oSTOP
:
break
out
}
pc
++
}
vm
.
stack
.
Print
()
}
vm_test.go
deleted
100644 → 0
View file @
33004d70
package
main
/*
import (
_"fmt"
"testing"
)
func TestVm(t *testing.T) {
InitFees()
db, _ := NewMemDatabase()
Db = db
ctrct := NewTransaction("", 200000000, []string{
"PUSH", "1a2f2e",
"PUSH", "hallo",
"POP", // POP hallo
"PUSH", "3",
"LOAD", // Load hallo back on the stack
"PUSH", "1",
"PUSH", "2",
"ADD",
"PUSH", "2",
"PUSH", "1",
"SUB",
"PUSH", "100000000000000000000000",
"PUSH", "10000000000000",
"SDIV",
"PUSH", "105",
"PUSH", "200",
"MOD",
"PUSH", "100000000000000000000000",
"PUSH", "10000000000000",
"SMOD",
"PUSH", "5",
"PUSH", "10",
"LT",
"PUSH", "5",
"PUSH", "5",
"LE",
"PUSH", "50",
"PUSH", "5",
"GT",
"PUSH", "5",
"PUSH", "5",
"GE",
"PUSH", "10",
"PUSH", "10",
"NOT",
"MYADDRESS",
"TXSENDER",
"STOP",
})
tx := NewTransaction("1e8a42ea8cce13", 100, []string{})
block := CreateBlock("", 0, "", "c014ba53", 0, 0, "", []*Transaction{ctrct, tx})
db.Put(block.Hash(), block.MarshalRlp())
bm := NewBlockManager()
bm.ProcessBlock( block )
}
*/
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