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
4d0ae8b0
Commit
4d0ae8b0
authored
Mar 18, 2015
by
obscuren
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'conversion' of github.com-obscure:ethereum/go-ethereum into conversion
parents
48dd601d
064279c0
Changes
15
Show whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
216 additions
and
114 deletions
+216
-114
admin.go
cmd/ethereum/admin.go
+1
-4
cmd.go
cmd/utils/cmd.go
+21
-15
block_processor_test.go
core/block_processor_test.go
+3
-2
chain_manager.go
core/chain_manager.go
+12
-15
chain_manager_test.go
core/chain_manager_test.go
+4
-5
genesis.go
core/genesis.go
+0
-4
transaction_pool.go
core/transaction_pool.go
+1
-1
transaction_pool_test.go
core/transaction_pool_test.go
+5
-7
block.go
core/types/block.go
+77
-22
block_test.go
core/types/block_test.go
+49
-8
derive_sha.go
core/types/derive_sha.go
+3
-1
transaction.go
core/types/transaction.go
+26
-29
decode.go
rlp/decode.go
+7
-0
encode.go
rlp/encode.go
+6
-1
encode_test.go
rlp/encode_test.go
+1
-0
No files found.
cmd/ethereum/admin.go
View file @
4d0ae8b0
...
@@ -221,13 +221,10 @@ func (js *jsre) exportChain(call otto.FunctionCall) otto.Value {
...
@@ -221,13 +221,10 @@ func (js *jsre) exportChain(call otto.FunctionCall) otto.Value {
fmt
.
Println
(
err
)
fmt
.
Println
(
err
)
return
otto
.
FalseValue
()
return
otto
.
FalseValue
()
}
}
if
err
:=
utils
.
ExportChain
(
js
.
ethereum
.
ChainManager
(),
fn
);
err
!=
nil
{
data
:=
js
.
ethereum
.
ChainManager
()
.
Export
()
if
err
:=
common
.
WriteFile
(
fn
,
data
);
err
!=
nil
{
fmt
.
Println
(
err
)
fmt
.
Println
(
err
)
return
otto
.
FalseValue
()
return
otto
.
FalseValue
()
}
}
return
otto
.
TrueValue
()
return
otto
.
TrueValue
()
}
}
...
...
cmd/utils/cmd.go
View file @
4d0ae8b0
...
@@ -23,14 +23,15 @@ package utils
...
@@ -23,14 +23,15 @@ package utils
import
(
import
(
"fmt"
"fmt"
"io"
"os"
"os"
"os/signal"
"os/signal"
"regexp"
"regexp"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rlp"
)
)
...
@@ -152,29 +153,34 @@ func ImportChain(chainmgr *core.ChainManager, fn string) error {
...
@@ -152,29 +153,34 @@ func ImportChain(chainmgr *core.ChainManager, fn string) error {
}
}
defer
fh
.
Close
()
defer
fh
.
Close
()
var
blocks
types
.
Blocks
if
err
:=
rlp
.
Decode
(
fh
,
&
blocks
);
err
!=
nil
{
return
err
}
chainmgr
.
Reset
()
chainmgr
.
Reset
()
if
err
:=
chainmgr
.
InsertChain
(
blocks
);
err
!=
nil
{
stream
:=
rlp
.
NewStream
(
fh
)
return
err
var
i
int
for
;
;
i
++
{
var
b
types
.
Block
if
err
:=
stream
.
Decode
(
&
b
);
err
==
io
.
EOF
{
break
}
else
if
err
!=
nil
{
return
fmt
.
Errorf
(
"at block %d: %v"
,
i
,
err
)
}
}
fmt
.
Printf
(
"imported %d blocks
\n
"
,
len
(
blocks
))
if
err
:=
chainmgr
.
InsertChain
(
types
.
Blocks
{
&
b
});
err
!=
nil
{
return
fmt
.
Errorf
(
"invalid block %d: %v"
,
i
,
err
)
}
}
fmt
.
Printf
(
"imported %d blocks
\n
"
,
i
)
return
nil
return
nil
}
}
func
ExportChain
(
chainmgr
*
core
.
ChainManager
,
fn
string
)
error
{
func
ExportChain
(
chainmgr
*
core
.
ChainManager
,
fn
string
)
error
{
fmt
.
Printf
(
"exporting blockchain '%s'
\n
"
,
fn
)
fmt
.
Printf
(
"exporting blockchain '%s'
\n
"
,
fn
)
fh
,
err
:=
os
.
OpenFile
(
fn
,
os
.
O_CREATE
|
os
.
O_WRONLY
|
os
.
O_TRUNC
,
os
.
ModePerm
)
data
:=
chainmgr
.
Export
()
if
err
!=
nil
{
return
err
if
err
:=
common
.
WriteFile
(
fn
,
data
);
err
!=
nil
{
}
defer
fh
.
Close
()
if
err
:=
chainmgr
.
Export
(
fh
);
err
!=
nil
{
return
err
return
err
}
}
fmt
.
Printf
(
"exported blockchain
\n
"
)
fmt
.
Printf
(
"exported blockchain
\n
"
)
return
nil
return
nil
}
}
core/block_processor_test.go
View file @
4d0ae8b0
...
@@ -4,6 +4,7 @@ import (
...
@@ -4,6 +4,7 @@ import (
"math/big"
"math/big"
"testing"
"testing"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/pow/ezp"
"github.com/ethereum/go-ethereum/pow/ezp"
...
@@ -19,7 +20,7 @@ func proc() (*BlockProcessor, *ChainManager) {
...
@@ -19,7 +20,7 @@ func proc() (*BlockProcessor, *ChainManager) {
func
TestNumber
(
t
*
testing
.
T
)
{
func
TestNumber
(
t
*
testing
.
T
)
{
bp
,
chain
:=
proc
()
bp
,
chain
:=
proc
()
block1
:=
chain
.
NewBlock
(
nil
)
block1
:=
chain
.
NewBlock
(
common
.
Address
{}
)
block1
.
Header
()
.
Number
=
big
.
NewInt
(
3
)
block1
.
Header
()
.
Number
=
big
.
NewInt
(
3
)
err
:=
bp
.
ValidateHeader
(
block1
.
Header
(),
chain
.
Genesis
()
.
Header
())
err
:=
bp
.
ValidateHeader
(
block1
.
Header
(),
chain
.
Genesis
()
.
Header
())
...
@@ -27,7 +28,7 @@ func TestNumber(t *testing.T) {
...
@@ -27,7 +28,7 @@ func TestNumber(t *testing.T) {
t
.
Errorf
(
"expected block number error"
)
t
.
Errorf
(
"expected block number error"
)
}
}
block1
=
chain
.
NewBlock
(
nil
)
block1
=
chain
.
NewBlock
(
common
.
Address
{}
)
err
=
bp
.
ValidateHeader
(
block1
.
Header
(),
chain
.
Genesis
()
.
Header
())
err
=
bp
.
ValidateHeader
(
block1
.
Header
(),
chain
.
Genesis
()
.
Header
())
if
err
==
BlockNumberErr
{
if
err
==
BlockNumberErr
{
t
.
Errorf
(
"didn't expect block number error"
)
t
.
Errorf
(
"didn't expect block number error"
)
...
...
core/chain_manager.go
View file @
4d0ae8b0
...
@@ -3,6 +3,7 @@ package core
...
@@ -3,6 +3,7 @@ package core
import
(
import
(
"bytes"
"bytes"
"fmt"
"fmt"
"io"
"math/big"
"math/big"
"sync"
"sync"
...
@@ -254,22 +255,20 @@ func (bc *ChainManager) ResetWithGenesisBlock(gb *types.Block) {
...
@@ -254,22 +255,20 @@ func (bc *ChainManager) ResetWithGenesisBlock(gb *types.Block) {
bc
.
currentBlock
=
bc
.
genesisBlock
bc
.
currentBlock
=
bc
.
genesisBlock
}
}
func
(
self
*
ChainManager
)
Export
()
[]
byte
{
// Export writes the active chain to the given writer.
func
(
self
*
ChainManager
)
Export
(
w
io
.
Writer
)
error
{
self
.
mu
.
RLock
()
self
.
mu
.
RLock
()
defer
self
.
mu
.
RUnlock
()
defer
self
.
mu
.
RUnlock
()
chainlogger
.
Infof
(
"exporting %v blocks...
\n
"
,
self
.
currentBlock
.
Header
()
.
Number
)
chainlogger
.
Infof
(
"exporting %v blocks...
\n
"
,
self
.
currentBlock
.
Header
()
.
Number
)
blocks
:=
make
([]
*
types
.
Block
,
int
(
self
.
currentBlock
.
NumberU64
())
+
1
)
for
block
:=
self
.
currentBlock
;
block
!=
nil
;
block
=
self
.
GetBlock
(
block
.
Header
()
.
ParentHash
)
{
for
block
:=
self
.
currentBlock
;
block
!=
nil
;
block
=
self
.
GetBlock
(
block
.
Header
()
.
ParentHash
)
{
blocks
[
block
.
NumberU64
()]
=
block
if
err
:=
block
.
EncodeRLP
(
w
);
err
!=
nil
{
return
err
}
}
}
return
common
.
Encode
(
blocks
)
return
nil
}
}
func
(
bc
*
ChainManager
)
insert
(
block
*
types
.
Block
)
{
func
(
bc
*
ChainManager
)
insert
(
block
*
types
.
Block
)
{
//encodedBlock := common.Encode(block)
bc
.
blockDb
.
Put
([]
byte
(
"LastBlock"
),
block
.
Hash
()
.
Bytes
())
bc
.
blockDb
.
Put
([]
byte
(
"LastBlock"
),
block
.
Hash
()
.
Bytes
())
bc
.
currentBlock
=
block
bc
.
currentBlock
=
block
bc
.
lastBlockHash
=
block
.
Hash
()
bc
.
lastBlockHash
=
block
.
Hash
()
...
@@ -279,10 +278,9 @@ func (bc *ChainManager) insert(block *types.Block) {
...
@@ -279,10 +278,9 @@ func (bc *ChainManager) insert(block *types.Block) {
}
}
func
(
bc
*
ChainManager
)
write
(
block
*
types
.
Block
)
{
func
(
bc
*
ChainManager
)
write
(
block
*
types
.
Block
)
{
encodedBlock
:=
common
.
Encode
(
block
.
RlpDataForStorage
())
enc
,
_
:=
rlp
.
EncodeToBytes
((
*
types
.
StorageBlock
)(
block
))
key
:=
append
(
blockHashPre
,
block
.
Hash
()
.
Bytes
()
...
)
key
:=
append
(
blockHashPre
,
block
.
Hash
()
.
Bytes
()
...
)
bc
.
blockDb
.
Put
(
key
,
enc
odedBlock
)
bc
.
blockDb
.
Put
(
key
,
enc
)
}
}
// Accessors
// Accessors
...
@@ -324,13 +322,12 @@ func (self *ChainManager) GetBlock(hash common.Hash) *types.Block {
...
@@ -324,13 +322,12 @@ func (self *ChainManager) GetBlock(hash common.Hash) *types.Block {
if
len
(
data
)
==
0
{
if
len
(
data
)
==
0
{
return
nil
return
nil
}
}
var
block
types
.
Block
var
block
types
.
Storage
Block
if
err
:=
rlp
.
Decode
(
bytes
.
NewReader
(
data
),
&
block
);
err
!=
nil
{
if
err
:=
rlp
.
Decode
(
bytes
.
NewReader
(
data
),
&
block
);
err
!=
nil
{
fmt
.
Println
(
err
)
chainlogger
.
Errorf
(
"invalid block RLP for hash %x: %v"
,
hash
,
err
)
return
nil
return
nil
}
}
return
(
*
types
.
Block
)(
&
block
)
return
&
block
}
}
func
(
self
*
ChainManager
)
GetBlockByNumber
(
num
uint64
)
*
types
.
Block
{
func
(
self
*
ChainManager
)
GetBlockByNumber
(
num
uint64
)
*
types
.
Block
{
...
...
core/chain_manager_test.go
View file @
4d0ae8b0
package
core
package
core
import
(
import
(
"bytes"
"fmt"
"fmt"
"math/big"
"math/big"
"os"
"os"
...
@@ -35,7 +34,7 @@ func testFork(t *testing.T, bman *BlockProcessor, i, N int, f func(td1, td2 *big
...
@@ -35,7 +34,7 @@ func testFork(t *testing.T, bman *BlockProcessor, i, N int, f func(td1, td2 *big
// asert the bmans have the same block at i
// asert the bmans have the same block at i
bi1
:=
bman
.
bc
.
GetBlockByNumber
(
uint64
(
i
))
.
Hash
()
bi1
:=
bman
.
bc
.
GetBlockByNumber
(
uint64
(
i
))
.
Hash
()
bi2
:=
bman2
.
bc
.
GetBlockByNumber
(
uint64
(
i
))
.
Hash
()
bi2
:=
bman2
.
bc
.
GetBlockByNumber
(
uint64
(
i
))
.
Hash
()
if
b
ytes
.
Compare
(
bi1
,
bi2
)
!=
0
{
if
b
i1
!=
bi2
{
t
.
Fatal
(
"chains do not have the same hash at height"
,
i
)
t
.
Fatal
(
"chains do not have the same hash at height"
,
i
)
}
}
...
@@ -270,11 +269,11 @@ func TestChainInsertions(t *testing.T) {
...
@@ -270,11 +269,11 @@ func TestChainInsertions(t *testing.T) {
<-
done
<-
done
}
}
if
bytes
.
Equal
(
chain2
[
len
(
chain2
)
-
1
]
.
Hash
(),
chainMan
.
CurrentBlock
()
.
Hash
()
)
{
if
chain2
[
len
(
chain2
)
-
1
]
.
Hash
()
!=
chainMan
.
CurrentBlock
()
.
Hash
(
)
{
t
.
Error
(
"chain2 is canonical and shouldn't be"
)
t
.
Error
(
"chain2 is canonical and shouldn't be"
)
}
}
if
!
bytes
.
Equal
(
chain1
[
len
(
chain1
)
-
1
]
.
Hash
(),
chainMan
.
CurrentBlock
()
.
Hash
()
)
{
if
chain1
[
len
(
chain1
)
-
1
]
.
Hash
()
!=
chainMan
.
CurrentBlock
()
.
Hash
(
)
{
t
.
Error
(
"chain1 isn't canonical and should be"
)
t
.
Error
(
"chain1 isn't canonical and should be"
)
}
}
}
}
...
@@ -320,7 +319,7 @@ func TestChainMultipleInsertions(t *testing.T) {
...
@@ -320,7 +319,7 @@ func TestChainMultipleInsertions(t *testing.T) {
<-
done
<-
done
}
}
if
!
bytes
.
Equal
(
chains
[
longest
][
len
(
chains
[
longest
])
-
1
]
.
Hash
(),
chainMan
.
CurrentBlock
()
.
Hash
()
)
{
if
chains
[
longest
][
len
(
chains
[
longest
])
-
1
]
.
Hash
()
!=
chainMan
.
CurrentBlock
()
.
Hash
(
)
{
t
.
Error
(
"Invalid canonical chain"
)
t
.
Error
(
"Invalid canonical chain"
)
}
}
}
}
...
...
core/genesis.go
View file @
4d0ae8b0
...
@@ -8,7 +8,6 @@ import (
...
@@ -8,7 +8,6 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/state"
"github.com/ethereum/go-ethereum/state"
)
)
...
@@ -19,9 +18,6 @@ import (
...
@@ -19,9 +18,6 @@ import (
var
ZeroHash256
=
make
([]
byte
,
32
)
var
ZeroHash256
=
make
([]
byte
,
32
)
var
ZeroHash160
=
make
([]
byte
,
20
)
var
ZeroHash160
=
make
([]
byte
,
20
)
var
ZeroHash512
=
make
([]
byte
,
64
)
var
ZeroHash512
=
make
([]
byte
,
64
)
var
EmptyShaList
=
crypto
.
Sha3
(
common
.
Encode
([]
interface
{}{}))
var
EmptyListRoot
=
crypto
.
Sha3
(
common
.
Encode
(
""
))
var
GenesisDiff
=
big
.
NewInt
(
131072
)
var
GenesisDiff
=
big
.
NewInt
(
131072
)
var
GenesisGasLimit
=
big
.
NewInt
(
3141592
)
var
GenesisGasLimit
=
big
.
NewInt
(
3141592
)
...
...
core/transaction_pool.go
View file @
4d0ae8b0
...
@@ -63,7 +63,7 @@ func NewTxPool(eventMux *event.TypeMux) *TxPool {
...
@@ -63,7 +63,7 @@ func NewTxPool(eventMux *event.TypeMux) *TxPool {
func
(
pool
*
TxPool
)
ValidateTransaction
(
tx
*
types
.
Transaction
)
error
{
func
(
pool
*
TxPool
)
ValidateTransaction
(
tx
*
types
.
Transaction
)
error
{
// Validate sender
// Validate sender
if
_
,
err
:=
tx
.
From
();
err
!=
nil
{
if
_
,
err
:=
tx
.
From
();
err
!=
nil
{
return
er
r
return
ErrInvalidSende
r
}
}
// Validate curve param
// Validate curve param
v
,
_
,
_
:=
tx
.
Curve
()
v
,
_
,
_
:=
tx
.
Curve
()
...
...
core/transaction_pool_test.go
View file @
4d0ae8b0
...
@@ -4,10 +4,10 @@ import (
...
@@ -4,10 +4,10 @@ import (
"crypto/ecdsa"
"crypto/ecdsa"
"testing"
"testing"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/state"
"github.com/ethereum/go-ethereum/state"
)
)
...
@@ -21,11 +21,11 @@ func SQ() stateQuery {
...
@@ -21,11 +21,11 @@ func SQ() stateQuery {
}
}
func
(
self
stateQuery
)
GetAccount
(
addr
[]
byte
)
*
state
.
StateObject
{
func
(
self
stateQuery
)
GetAccount
(
addr
[]
byte
)
*
state
.
StateObject
{
return
state
.
NewStateObject
(
addr
,
self
.
db
)
return
state
.
NewStateObject
(
common
.
BytesToAddress
(
addr
)
,
self
.
db
)
}
}
func
transaction
()
*
types
.
Transaction
{
func
transaction
()
*
types
.
Transaction
{
return
types
.
NewTransactionMessage
(
make
([]
byte
,
20
)
,
common
.
Big0
,
common
.
Big0
,
common
.
Big0
,
nil
)
return
types
.
NewTransactionMessage
(
common
.
Address
{}
,
common
.
Big0
,
common
.
Big0
,
common
.
Big0
,
nil
)
}
}
func
setup
()
(
*
TxPool
,
*
ecdsa
.
PrivateKey
)
{
func
setup
()
(
*
TxPool
,
*
ecdsa
.
PrivateKey
)
{
...
@@ -88,10 +88,8 @@ func TestRemoveInvalid(t *testing.T) {
...
@@ -88,10 +88,8 @@ func TestRemoveInvalid(t *testing.T) {
func
TestInvalidSender
(
t
*
testing
.
T
)
{
func
TestInvalidSender
(
t
*
testing
.
T
)
{
pool
,
_
:=
setup
()
pool
,
_
:=
setup
()
tx
:=
new
(
types
.
Transaction
)
err
:=
pool
.
ValidateTransaction
(
new
(
types
.
Transaction
))
tx
.
V
=
28
err
:=
pool
.
ValidateTransaction
(
tx
)
if
err
!=
ErrInvalidSender
{
if
err
!=
ErrInvalidSender
{
t
.
Error
(
"expected %v, got %v"
,
ErrInvalidSender
,
err
)
t
.
Error
f
(
"expected %v, got %v"
,
ErrInvalidSender
,
err
)
}
}
}
}
core/types/block.go
View file @
4d0ae8b0
...
@@ -3,12 +3,13 @@ package types
...
@@ -3,12 +3,13 @@ package types
import
(
import
(
"encoding/binary"
"encoding/binary"
"fmt"
"fmt"
"io"
"math/big"
"math/big"
"sort"
"sort"
"time"
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/crypto
/sha3
"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rlp"
)
)
...
@@ -45,6 +46,14 @@ type Header struct {
...
@@ -45,6 +46,14 @@ type Header struct {
Nonce
[
8
]
byte
Nonce
[
8
]
byte
}
}
func
(
self
*
Header
)
Hash
()
common
.
Hash
{
return
rlpHash
(
self
.
rlpData
(
true
))
}
func
(
self
*
Header
)
HashNoNonce
()
common
.
Hash
{
return
rlpHash
(
self
.
rlpData
(
false
))
}
func
(
self
*
Header
)
rlpData
(
withNonce
bool
)
[]
interface
{}
{
func
(
self
*
Header
)
rlpData
(
withNonce
bool
)
[]
interface
{}
{
fields
:=
[]
interface
{}{
fields
:=
[]
interface
{}{
self
.
ParentHash
,
self
.
ParentHash
,
...
@@ -64,7 +73,6 @@ func (self *Header) rlpData(withNonce bool) []interface{} {
...
@@ -64,7 +73,6 @@ func (self *Header) rlpData(withNonce bool) []interface{} {
if
withNonce
{
if
withNonce
{
fields
=
append
(
fields
,
self
.
MixDigest
,
self
.
Nonce
)
fields
=
append
(
fields
,
self
.
MixDigest
,
self
.
Nonce
)
}
}
return
fields
return
fields
}
}
...
@@ -72,12 +80,11 @@ func (self *Header) RlpData() interface{} {
...
@@ -72,12 +80,11 @@ func (self *Header) RlpData() interface{} {
return
self
.
rlpData
(
true
)
return
self
.
rlpData
(
true
)
}
}
func
(
self
*
Header
)
Hash
()
common
.
Hash
{
func
rlpHash
(
x
interface
{})
(
h
common
.
Hash
)
{
return
common
.
BytesToHash
(
crypto
.
Sha3
(
common
.
Encode
(
self
.
rlpData
(
true
))))
hw
:=
sha3
.
NewKeccak256
()
}
rlp
.
Encode
(
hw
,
x
)
hw
.
Sum
(
h
[
:
0
])
func
(
self
*
Header
)
HashNoNonce
()
common
.
Hash
{
return
h
return
common
.
BytesToHash
(
crypto
.
Sha3
(
common
.
Encode
(
self
.
rlpData
(
false
))))
}
}
type
Block
struct
{
type
Block
struct
{
...
@@ -95,6 +102,26 @@ type Block struct {
...
@@ -95,6 +102,26 @@ type Block struct {
Reward
*
big
.
Int
Reward
*
big
.
Int
}
}
// StorageBlock defines the RLP encoding of a Block stored in the
// state database. The StorageBlock encoding contains fields that
// would otherwise need to be recomputed.
type
StorageBlock
Block
// "external" block encoding. used for eth protocol, etc.
type
extblock
struct
{
Header
*
Header
Txs
[]
*
Transaction
Uncles
[]
*
Header
}
// "storage" block encoding. used for database.
type
storageblock
struct
{
Header
*
Header
Txs
[]
*
Transaction
Uncles
[]
*
Header
TD
*
big
.
Int
}
func
NewBlock
(
parentHash
common
.
Hash
,
coinbase
common
.
Address
,
root
common
.
Hash
,
difficulty
*
big
.
Int
,
nonce
uint64
,
extra
string
)
*
Block
{
func
NewBlock
(
parentHash
common
.
Hash
,
coinbase
common
.
Address
,
root
common
.
Hash
,
difficulty
*
big
.
Int
,
nonce
uint64
,
extra
string
)
*
Block
{
header
:=
&
Header
{
header
:=
&
Header
{
Root
:
root
,
Root
:
root
,
...
@@ -107,9 +134,7 @@ func NewBlock(parentHash common.Hash, coinbase common.Address, root common.Hash,
...
@@ -107,9 +134,7 @@ func NewBlock(parentHash common.Hash, coinbase common.Address, root common.Hash,
GasLimit
:
new
(
big
.
Int
),
GasLimit
:
new
(
big
.
Int
),
}
}
header
.
SetNonce
(
nonce
)
header
.
SetNonce
(
nonce
)
block
:=
&
Block
{
header
:
header
,
Reward
:
new
(
big
.
Int
)}
block
:=
&
Block
{
header
:
header
,
Reward
:
new
(
big
.
Int
)}
return
block
return
block
}
}
...
@@ -122,22 +147,40 @@ func NewBlockWithHeader(header *Header) *Block {
...
@@ -122,22 +147,40 @@ func NewBlockWithHeader(header *Header) *Block {
}
}
func
(
self
*
Block
)
DecodeRLP
(
s
*
rlp
.
Stream
)
error
{
func
(
self
*
Block
)
DecodeRLP
(
s
*
rlp
.
Stream
)
error
{
var
extblock
struct
{
var
eb
extblock
Header
*
Header
if
err
:=
s
.
Decode
(
&
eb
);
err
!=
nil
{
Txs
[]
*
Transaction
return
err
Uncles
[]
*
Header
TD
*
big
.
Int
// optional
}
}
if
err
:=
s
.
Decode
(
&
extblock
);
err
!=
nil
{
self
.
header
,
self
.
uncles
,
self
.
transactions
=
eb
.
Header
,
eb
.
Uncles
,
eb
.
Txs
return
nil
}
func
(
self
Block
)
EncodeRLP
(
w
io
.
Writer
)
error
{
return
rlp
.
Encode
(
w
,
extblock
{
Header
:
self
.
header
,
Txs
:
self
.
transactions
,
Uncles
:
self
.
uncles
,
})
}
func
(
self
*
StorageBlock
)
DecodeRLP
(
s
*
rlp
.
Stream
)
error
{
var
sb
storageblock
if
err
:=
s
.
Decode
(
&
sb
);
err
!=
nil
{
return
err
return
err
}
}
self
.
header
=
extblock
.
Header
self
.
header
,
self
.
uncles
,
self
.
transactions
,
self
.
Td
=
sb
.
Header
,
sb
.
Uncles
,
sb
.
Txs
,
sb
.
TD
self
.
uncles
=
extblock
.
Uncles
self
.
transactions
=
extblock
.
Txs
self
.
Td
=
extblock
.
TD
return
nil
return
nil
}
}
func
(
self
StorageBlock
)
EncodeRLP
(
w
io
.
Writer
)
error
{
return
rlp
.
Encode
(
w
,
storageblock
{
Header
:
self
.
header
,
Txs
:
self
.
transactions
,
Uncles
:
self
.
uncles
,
TD
:
self
.
Td
,
})
}
func
(
self
*
Block
)
Header
()
*
Header
{
func
(
self
*
Block
)
Header
()
*
Header
{
return
self
.
header
return
self
.
header
}
}
...
@@ -148,7 +191,7 @@ func (self *Block) Uncles() []*Header {
...
@@ -148,7 +191,7 @@ func (self *Block) Uncles() []*Header {
func
(
self
*
Block
)
SetUncles
(
uncleHeaders
[]
*
Header
)
{
func
(
self
*
Block
)
SetUncles
(
uncleHeaders
[]
*
Header
)
{
self
.
uncles
=
uncleHeaders
self
.
uncles
=
uncleHeaders
self
.
header
.
UncleHash
=
common
.
BytesToHash
(
crypto
.
Sha3
(
common
.
Encode
(
uncleHeaders
))
)
self
.
header
.
UncleHash
=
rlpHash
(
uncleHeaders
)
}
}
func
(
self
*
Block
)
Transactions
()
Transactions
{
func
(
self
*
Block
)
Transactions
()
Transactions
{
...
@@ -213,7 +256,6 @@ func (self *Block) GasLimit() *big.Int { return self.header.GasLimit }
...
@@ -213,7 +256,6 @@ func (self *Block) GasLimit() *big.Int { return self.header.GasLimit }
func
(
self
*
Block
)
GasUsed
()
*
big
.
Int
{
return
self
.
header
.
GasUsed
}
func
(
self
*
Block
)
GasUsed
()
*
big
.
Int
{
return
self
.
header
.
GasUsed
}
func
(
self
*
Block
)
Root
()
common
.
Hash
{
return
self
.
header
.
Root
}
func
(
self
*
Block
)
Root
()
common
.
Hash
{
return
self
.
header
.
Root
}
func
(
self
*
Block
)
SetRoot
(
root
common
.
Hash
)
{
self
.
header
.
Root
=
root
}
func
(
self
*
Block
)
SetRoot
(
root
common
.
Hash
)
{
self
.
header
.
Root
=
root
}
func
(
self
*
Block
)
Size
()
common
.
StorageSize
{
return
common
.
StorageSize
(
len
(
common
.
Encode
(
self
)))
}
func
(
self
*
Block
)
GetTransaction
(
i
int
)
*
Transaction
{
func
(
self
*
Block
)
GetTransaction
(
i
int
)
*
Transaction
{
if
len
(
self
.
transactions
)
>
i
{
if
len
(
self
.
transactions
)
>
i
{
return
self
.
transactions
[
i
]
return
self
.
transactions
[
i
]
...
@@ -227,6 +269,19 @@ func (self *Block) GetUncle(i int) *Header {
...
@@ -227,6 +269,19 @@ func (self *Block) GetUncle(i int) *Header {
return
nil
return
nil
}
}
func
(
self
*
Block
)
Size
()
common
.
StorageSize
{
c
:=
writeCounter
(
0
)
rlp
.
Encode
(
&
c
,
self
)
return
common
.
StorageSize
(
c
)
}
type
writeCounter
common
.
StorageSize
func
(
c
*
writeCounter
)
Write
(
b
[]
byte
)
(
int
,
error
)
{
*
c
+=
writeCounter
(
len
(
b
))
return
len
(
b
),
nil
}
// Implement pow.Block
// Implement pow.Block
func
(
self
*
Block
)
Difficulty
()
*
big
.
Int
{
return
self
.
header
.
Difficulty
}
func
(
self
*
Block
)
Difficulty
()
*
big
.
Int
{
return
self
.
header
.
Difficulty
}
func
(
self
*
Block
)
HashNoNonce
()
common
.
Hash
{
return
self
.
header
.
HashNoNonce
()
}
func
(
self
*
Block
)
HashNoNonce
()
common
.
Hash
{
return
self
.
header
.
HashNoNonce
()
}
...
...
core/types/block_test.go
View file @
4d0ae8b0
package
types
package
types
import
(
import
(
"bytes"
"math/big"
"math/big"
"reflect"
"testing"
"testing"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/rlp"
)
)
// XXX Tests doesn't really do anything. This tests exists while working on the fixed size conversions
// from bcValidBlockTest.json, "SimpleTx"
func
TestConversion
(
t
*
testing
.
T
)
{
func
TestBlockEncoding
(
t
*
testing
.
T
)
{
var
(
blockEnc
:=
common
.
FromHex
(
"f90260f901f9a083cafc574e1f51ba9dc0568fc617a08ea2429fb384059c972f13b19fa1c8dd55a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0ef1552a40b7165c3cd773806b9e0c165b75356e0314bf0706f279c729f51e017a05fe50b260da6308036625b850b5d6ced6d0a9f814c0688bc91ffb7b7a3a54b67a0bc37d79753ad738a6dac4921e57392f145d8887476de3f783dfa7edae9283e52b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000001832fefd8825208845506eb0780a0bd4472abb6659ebe3ee06ee4d7b72a00a9f4d001caca51342001075469aff49888a13a5a8c8f2bb1c4f861f85f800a82c35094095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba09bea4c4daac7c7c52e093e6a4c35dbbcf8856f1af7b059ba20253e70848d094fa08a8fae537ce25ed8cb5af9adac3f141af69bd515bd2ba031522df09b97dd72b1c0"
)
parent
common
.
Hash
coinbase
common
.
Address
hash
common
.
Hash
)
NewBlock
(
parent
,
coinbase
,
hash
,
big
.
NewInt
(
0
),
0
,
""
)
var
block
Block
if
err
:=
rlp
.
DecodeBytes
(
blockEnc
,
&
block
);
err
!=
nil
{
t
.
Fatal
(
"decode error: "
,
err
)
}
check
:=
func
(
f
string
,
got
,
want
interface
{})
{
if
!
reflect
.
DeepEqual
(
got
,
want
)
{
t
.
Errorf
(
"%s mismatch: got %v, want %v"
,
f
,
got
,
want
)
}
}
check
(
"Difficulty"
,
block
.
Difficulty
(),
big
.
NewInt
(
131072
))
check
(
"GasLimit"
,
block
.
GasLimit
(),
big
.
NewInt
(
3141592
))
check
(
"GasUsed"
,
block
.
GasUsed
(),
big
.
NewInt
(
21000
))
check
(
"Coinbase"
,
block
.
Coinbase
(),
common
.
HexToAddress
(
"8888f1f195afa192cfee860698584c030f4c9db1"
))
check
(
"MixDigest"
,
block
.
MixDigest
(),
common
.
HexToHash
(
"bd4472abb6659ebe3ee06ee4d7b72a00a9f4d001caca51342001075469aff498"
))
check
(
"Root"
,
block
.
Root
(),
common
.
HexToHash
(
"ef1552a40b7165c3cd773806b9e0c165b75356e0314bf0706f279c729f51e017"
))
check
(
"Hash"
,
block
.
Hash
(),
common
.
HexToHash
(
"0a5843ac1cb04865017cb35a57b50b07084e5fcee39b5acadade33149f4fff9e"
))
check
(
"Nonce"
,
block
.
Nonce
(),
uint64
(
0xa13a5a8c8f2bb1c4
))
check
(
"Time"
,
block
.
Time
(),
int64
(
1426516743
))
check
(
"Size"
,
block
.
Size
(),
common
.
StorageSize
(
len
(
blockEnc
)))
to
:=
common
.
HexToAddress
(
"095e7baea6a6c7c4c2dfeb977efac326af552d87"
)
check
(
"Transactions"
,
block
.
Transactions
(),
Transactions
{
{
Payload
:
[]
byte
{},
Amount
:
big
.
NewInt
(
10
),
Price
:
big
.
NewInt
(
10
),
GasLimit
:
big
.
NewInt
(
50000
),
AccountNonce
:
0
,
V
:
27
,
R
:
common
.
FromHex
(
"9bea4c4daac7c7c52e093e6a4c35dbbcf8856f1af7b059ba20253e70848d094f"
),
S
:
common
.
FromHex
(
"8a8fae537ce25ed8cb5af9adac3f141af69bd515bd2ba031522df09b97dd72b1"
),
Recipient
:
&
to
,
},
})
ourBlockEnc
,
err
:=
rlp
.
EncodeToBytes
(
&
block
)
if
err
!=
nil
{
t
.
Fatal
(
"encode error: "
,
err
)
}
if
!
bytes
.
Equal
(
ourBlockEnc
,
blockEnc
)
{
t
.
Errorf
(
"encoded block mismatch:
\n
got: %x
\n
want: %x"
,
ourBlockEnc
,
blockEnc
)
}
}
}
core/types/derive_sha.go
View file @
4d0ae8b0
...
@@ -3,6 +3,7 @@ package types
...
@@ -3,6 +3,7 @@ package types
import
(
import
(
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie"
"github.com/ethereum/go-ethereum/trie"
)
)
...
@@ -15,7 +16,8 @@ func DeriveSha(list DerivableList) common.Hash {
...
@@ -15,7 +16,8 @@ func DeriveSha(list DerivableList) common.Hash {
db
,
_
:=
ethdb
.
NewMemDatabase
()
db
,
_
:=
ethdb
.
NewMemDatabase
()
trie
:=
trie
.
New
(
nil
,
db
)
trie
:=
trie
.
New
(
nil
,
db
)
for
i
:=
0
;
i
<
list
.
Len
();
i
++
{
for
i
:=
0
;
i
<
list
.
Len
();
i
++
{
trie
.
Update
(
common
.
Encode
(
i
),
list
.
GetRlp
(
i
))
key
,
_
:=
rlp
.
EncodeToBytes
(
i
)
trie
.
Update
(
key
,
list
.
GetRlp
(
i
))
}
}
return
common
.
BytesToHash
(
trie
.
Root
())
return
common
.
BytesToHash
(
trie
.
Root
())
...
...
core/types/transaction.go
View file @
4d0ae8b0
package
types
package
types
import
(
import
(
"
bytes
"
"
crypto/ecdsa
"
"errors"
"errors"
"fmt"
"fmt"
"io"
"math/big"
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/crypto/secp256k1"
"github.com/ethereum/go-ethereum/crypto/secp256k1"
"github.com/ethereum/go-ethereum/crypto/sha3"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rlp"
)
)
...
@@ -38,16 +36,18 @@ func NewTransactionMessage(to common.Address, amount, gasAmount, gasPrice *big.I
...
@@ -38,16 +36,18 @@ func NewTransactionMessage(to common.Address, amount, gasAmount, gasPrice *big.I
}
}
func
NewTransactionFromBytes
(
data
[]
byte
)
*
Transaction
{
func
NewTransactionFromBytes
(
data
[]
byte
)
*
Transaction
{
// TODO: remove this function if possible. callers would
// much better off decoding into transaction directly.
// it's not that hard.
tx
:=
new
(
Transaction
)
tx
:=
new
(
Transaction
)
rlp
.
Decode
(
bytes
.
NewReader
(
data
)
,
tx
)
rlp
.
Decode
Bytes
(
data
,
tx
)
return
tx
return
tx
}
}
func
(
tx
*
Transaction
)
Hash
()
(
a
common
.
Hash
)
{
func
(
tx
*
Transaction
)
Hash
()
common
.
Hash
{
h
:=
sha3
.
NewKeccak256
()
return
rlpHash
([]
interface
{}{
rlp
.
Encode
(
h
,
[]
interface
{}{
tx
.
AccountNonce
,
tx
.
Price
,
tx
.
GasLimit
,
tx
.
Recipient
,
tx
.
Amount
,
tx
.
Payload
})
tx
.
AccountNonce
,
tx
.
Price
,
tx
.
GasLimit
,
tx
.
Recipient
,
tx
.
Amount
,
tx
.
Payload
,
h
.
Sum
(
a
[
:
0
])
})
return
a
}
}
func
(
self
*
Transaction
)
Data
()
[]
byte
{
func
(
self
*
Transaction
)
Data
()
[]
byte
{
...
@@ -122,17 +122,14 @@ func (tx *Transaction) SetSignatureValues(sig []byte) error {
...
@@ -122,17 +122,14 @@ func (tx *Transaction) SetSignatureValues(sig []byte) error {
return
nil
return
nil
}
}
func
(
tx
Transaction
)
EncodeRLP
(
w
io
.
Writer
)
error
{
func
(
tx
*
Transaction
)
SignECDSA
(
prv
*
ecdsa
.
PrivateKey
)
error
{
return
rlp
.
Encode
(
w
,
[]
interface
{}{
h
:=
tx
.
Hash
()
tx
.
AccountNonce
,
sig
,
err
:=
crypto
.
Sign
(
h
[
:
],
prv
)
tx
.
Price
,
tx
.
GasLimit
,
if
err
!=
nil
{
tx
.
Recipient
,
return
err
tx
.
Amount
,
}
tx
.
Payload
,
tx
.
SetSignatureValues
(
sig
)
tx
.
V
,
return
nil
tx
.
R
,
tx
.
S
,
})
}
}
// TODO: remove
// TODO: remove
...
@@ -141,11 +138,6 @@ func (tx *Transaction) RlpData() interface{} {
...
@@ -141,11 +138,6 @@ func (tx *Transaction) RlpData() interface{} {
return
append
(
data
,
tx
.
V
,
new
(
big
.
Int
)
.
SetBytes
(
tx
.
R
)
.
Bytes
(),
new
(
big
.
Int
)
.
SetBytes
(
tx
.
S
)
.
Bytes
())
return
append
(
data
,
tx
.
V
,
new
(
big
.
Int
)
.
SetBytes
(
tx
.
R
)
.
Bytes
(),
new
(
big
.
Int
)
.
SetBytes
(
tx
.
S
)
.
Bytes
())
}
}
// TODO: remove
func
(
tx
*
Transaction
)
RlpEncode
()
[]
byte
{
return
common
.
Encode
(
tx
)
}
func
(
tx
*
Transaction
)
String
()
string
{
func
(
tx
*
Transaction
)
String
()
string
{
var
from
,
to
string
var
from
,
to
string
if
f
,
err
:=
tx
.
From
();
err
!=
nil
{
if
f
,
err
:=
tx
.
From
();
err
!=
nil
{
...
@@ -158,6 +150,7 @@ func (tx *Transaction) String() string {
...
@@ -158,6 +150,7 @@ func (tx *Transaction) String() string {
}
else
{
}
else
{
to
=
fmt
.
Sprintf
(
"%x"
,
t
[
:
])
to
=
fmt
.
Sprintf
(
"%x"
,
t
[
:
])
}
}
enc
,
_
:=
rlp
.
EncodeToBytes
(
tx
)
return
fmt
.
Sprintf
(
`
return
fmt
.
Sprintf
(
`
TX(%x)
TX(%x)
Contract: %v
Contract: %v
...
@@ -185,7 +178,7 @@ func (tx *Transaction) String() string {
...
@@ -185,7 +178,7 @@ func (tx *Transaction) String() string {
tx
.
V
,
tx
.
V
,
tx
.
R
,
tx
.
R
,
tx
.
S
,
tx
.
S
,
common
.
Encode
(
tx
)
,
enc
,
)
)
}
}
...
@@ -206,7 +199,11 @@ func (self Transactions) RlpData() interface{} {
...
@@ -206,7 +199,11 @@ func (self Transactions) RlpData() interface{} {
func
(
s
Transactions
)
Len
()
int
{
return
len
(
s
)
}
func
(
s
Transactions
)
Len
()
int
{
return
len
(
s
)
}
func
(
s
Transactions
)
Swap
(
i
,
j
int
)
{
s
[
i
],
s
[
j
]
=
s
[
j
],
s
[
i
]
}
func
(
s
Transactions
)
Swap
(
i
,
j
int
)
{
s
[
i
],
s
[
j
]
=
s
[
j
],
s
[
i
]
}
func
(
s
Transactions
)
GetRlp
(
i
int
)
[]
byte
{
return
common
.
Rlp
(
s
[
i
])
}
func
(
s
Transactions
)
GetRlp
(
i
int
)
[]
byte
{
enc
,
_
:=
rlp
.
EncodeToBytes
(
s
[
i
])
return
enc
}
type
TxByNonce
struct
{
Transactions
}
type
TxByNonce
struct
{
Transactions
}
...
...
rlp/decode.go
View file @
4d0ae8b0
...
@@ -2,6 +2,7 @@ package rlp
...
@@ -2,6 +2,7 @@ package rlp
import
(
import
(
"bufio"
"bufio"
"bytes"
"encoding/binary"
"encoding/binary"
"errors"
"errors"
"fmt"
"fmt"
...
@@ -73,6 +74,12 @@ func Decode(r io.Reader, val interface{}) error {
...
@@ -73,6 +74,12 @@ func Decode(r io.Reader, val interface{}) error {
return
NewStream
(
r
)
.
Decode
(
val
)
return
NewStream
(
r
)
.
Decode
(
val
)
}
}
// DecodeBytes parses RLP data from b into val.
// Please see the documentation of Decode for the decoding rules.
func
DecodeBytes
(
b
[]
byte
,
val
interface
{})
error
{
return
NewStream
(
bytes
.
NewReader
(
b
))
.
Decode
(
val
)
}
type
decodeError
struct
{
type
decodeError
struct
{
msg
string
msg
string
typ
reflect
.
Type
typ
reflect
.
Type
...
...
rlp/encode.go
View file @
4d0ae8b0
...
@@ -386,7 +386,12 @@ func writeUint(val reflect.Value, w *encbuf) error {
...
@@ -386,7 +386,12 @@ func writeUint(val reflect.Value, w *encbuf) error {
}
}
func
writeBigIntPtr
(
val
reflect
.
Value
,
w
*
encbuf
)
error
{
func
writeBigIntPtr
(
val
reflect
.
Value
,
w
*
encbuf
)
error
{
return
writeBigInt
(
val
.
Interface
()
.
(
*
big
.
Int
),
w
)
ptr
:=
val
.
Interface
()
.
(
*
big
.
Int
)
if
ptr
==
nil
{
w
.
str
=
append
(
w
.
str
,
0x80
)
return
nil
}
return
writeBigInt
(
ptr
,
w
)
}
}
func
writeBigIntNoPtr
(
val
reflect
.
Value
,
w
*
encbuf
)
error
{
func
writeBigIntNoPtr
(
val
reflect
.
Value
,
w
*
encbuf
)
error
{
...
...
rlp/encode_test.go
View file @
4d0ae8b0
...
@@ -196,6 +196,7 @@ var encTests = []encTest{
...
@@ -196,6 +196,7 @@ var encTests = []encTest{
{
val
:
(
*
uint
)(
nil
),
output
:
"80"
},
{
val
:
(
*
uint
)(
nil
),
output
:
"80"
},
{
val
:
(
*
string
)(
nil
),
output
:
"80"
},
{
val
:
(
*
string
)(
nil
),
output
:
"80"
},
{
val
:
(
*
[]
byte
)(
nil
),
output
:
"80"
},
{
val
:
(
*
[]
byte
)(
nil
),
output
:
"80"
},
{
val
:
(
*
big
.
Int
)(
nil
),
output
:
"80"
},
{
val
:
(
*
[]
string
)(
nil
),
output
:
"C0"
},
{
val
:
(
*
[]
string
)(
nil
),
output
:
"C0"
},
{
val
:
(
*
[]
interface
{})(
nil
),
output
:
"C0"
},
{
val
:
(
*
[]
interface
{})(
nil
),
output
:
"C0"
},
{
val
:
(
*
[]
struct
{
uint
})(
nil
),
output
:
"C0"
},
{
val
:
(
*
[]
struct
{
uint
})(
nil
),
output
:
"C0"
},
...
...
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