access tests

This commit is contained in:
zsfelfoldi 2015-11-02 04:17:09 +01:00
parent 1c9c96fc3b
commit b1250e2726
9 changed files with 165 additions and 171 deletions

View file

@ -186,7 +186,7 @@ func GetHeader(db ethdb.Database, hash common.Hash) *types.Header {
// GetBodyRLP retrieves the block body (transactions and uncles) in RLP encoding.
func GetBodyRLP(ca *access.ChainAccess, hash common.Hash, ctx *access.OdrContext) rlp.RawValue {
//fmt.Println("request block %v", hash)
r := &BlockAccess{db: ca.Db(), blockHash: hash}
r := NewBlockAccess(ca.Db(), hash)
ca.Retrieve(r, ctx)
return r.rlp
}

View file

@ -35,6 +35,10 @@ type BlockAccess struct {
rlp []byte
}
func NewBlockAccess(db ethdb.Database, blockHash common.Hash) *BlockAccess {
return &BlockAccess{db: db, blockHash: blockHash}
}
func (self *BlockAccess) Request(peer *access.Peer) error {
glog.V(access.LogLevel).Infof("ODR: requesting body of block %08x from peer %v", self.blockHash[:4], peer.Id())
return peer.GetBlockBodies([]common.Hash{self.blockHash})
@ -95,6 +99,10 @@ type ReceiptsAccess struct {
receipts types.Receipts
}
func NewReceiptsAccess(db ethdb.Database, blockHash common.Hash) *ReceiptsAccess {
return &ReceiptsAccess{db: db, blockHash: blockHash}
}
func (self *ReceiptsAccess) Request(peer *access.Peer) error {
glog.V(access.LogLevel).Infof("ODR: requesting receipts for block %08x from peer %v", self.blockHash[:4], peer.Id())
return peer.GetReceipts([]common.Hash{self.blockHash})

View file

@ -45,7 +45,7 @@ func NewTrieAccess(ca *access.ChainAccess, root common.Hash, trieDb trie.Databas
func (self *TrieAccess) RetrieveKey(key []byte, ctx *access.OdrContext) bool {
//fmt.Println("request trie %v key %v", self.root, key)
r := &TrieEntryAccess{root: self.root, trieDb: self.trieDb, key: key}
r := NewTrieEntryAccess(self.root, self.trieDb, key)
return self.ca.Retrieve(r, ctx) == nil
}
@ -62,6 +62,10 @@ type TrieEntryAccess struct {
skipLevels int // set by DbGet() if unsuccessful
}
func NewTrieEntryAccess(root common.Hash, trieDb trie.Database, key []byte) *TrieEntryAccess {
return &TrieEntryAccess{root: root, trieDb: trieDb, key: key}
}
func (self *TrieEntryAccess) Request(peer *access.Peer) error {
glog.V(access.LogLevel).Infof("ODR: requesting trie root %08x key %08x from peer %v", self.root[:4], self.key[:4], peer.Id())
req := &access.ProofReq{
@ -109,6 +113,10 @@ type NodeDataAccess struct {
data []byte
}
func NewNodeDataAccess(db ethdb.Database, hash common.Hash) *NodeDataAccess {
return &NodeDataAccess{db: db, hash: hash}
}
func (self *NodeDataAccess) Request(peer *access.Peer) error {
glog.V(access.LogLevel).Infof("ODR: requesting node data for hash %08x from peer %v", self.hash[:4], peer.Id())
return peer.GetNodeData([]common.Hash{self.hash})
@ -156,7 +164,7 @@ func RetrieveNodeData(ca *access.ChainAccess, hash common.Hash, ctx *access.OdrC
if bytes.Compare(hash[:], sha3_nil) == 0 {
return nil
}
r := &NodeDataAccess{db: ca.Db(), hash: hash}
r := NewNodeDataAccess(ca.Db(), hash)
ca.Retrieve(r, ctx)
return r.data
}

View file

@ -140,7 +140,7 @@ func GetReceipt(ca *access.ChainAccess, txHash common.Hash, ctx *access.OdrConte
// GetBlockReceipts returns the receipts generated by the transactions
// included in block's given hash.
func GetBlockReceipts(ca *access.ChainAccess, hash common.Hash, ctx *access.OdrContext) types.Receipts {
r := &ReceiptsAccess{db: ca.Db(), blockHash: hash}
r := NewReceiptsAccess(ca.Db(), hash)
ca.Retrieve(r, ctx)
return r.receipts
}

84
les/access_test.go Normal file
View file

@ -0,0 +1,84 @@
package les
import (
"testing"
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/access"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/crypto/sha3"
)
var testBankSecureTrieKey = sha3.NewKeccak256().Sum(testBankAddress[:])
type accessTestFn func(ca *access.ChainAccess, bc *core.BlockChain, bhash common.Hash) access.ObjectAccess
func TestBlockAccessLes1(t *testing.T) { testAccess(t, 1, true, tfBlockAccess) }
func tfBlockAccess(ca *access.ChainAccess, bc *core.BlockChain, bhash common.Hash) access.ObjectAccess {
return core.NewBlockAccess(ca.Db(), bhash)
}
func TestReceiptsAccessLes1(t *testing.T) { testAccess(t, 1, true, tfReceiptsAccess) }
func tfReceiptsAccess(ca *access.ChainAccess, bc *core.BlockChain, bhash common.Hash) access.ObjectAccess {
return core.NewReceiptsAccess(ca.Db(), bhash)
}
func TestTrieEntryAccessLes1(t *testing.T) { testAccess(t, 1, false, tfTrieEntryAccess) }
func tfTrieEntryAccess(ca *access.ChainAccess, bc *core.BlockChain, bhash common.Hash) access.ObjectAccess {
return state.NewTrieEntryAccess(bc.GetHeader(bhash).Root, ca.Db(), testBankSecureTrieKey)
}
func TestNodeDataAccessLes1(t *testing.T) { testAccess(t, 1, true, tfNodeDataAccess) }
func tfNodeDataAccess(ca *access.ChainAccess, bc *core.BlockChain, bhash common.Hash) access.ObjectAccess {
return state.NewNodeDataAccess(ca.Db(), bc.GetHeader(bhash).Root)
}
func testAccess(t *testing.T, protocol int, shouldCache bool, fn accessTestFn) {
// Assemble the test environment
pm, ca := newTestProtocolManagerMust(t, false, 4, testChainGen)
lpm, lca := newTestProtocolManagerMust(t, true, 0, nil)
_, _, lpeer, _ := newTestPeerPair("peer", protocol, pm, lpm)
time.Sleep(time.Millisecond * 100)
lpm.synchronise(lpeer)
cid := access.NewChannelID(time.Millisecond * 200)
test := func(expFail uint64) {
for i := uint64(0); i <= pm.blockchain.CurrentBlock().NumberU64(); i++ {
bhash := core.GetCanonicalHash(ca.Db(), i)
req := fn(lca, lpm.blockchain, bhash)
err := lca.Retrieve(req, access.NewContext(cid))
got := err == nil
exp := i < expFail
if exp && !got {
t.Errorf("object retrieval failed")
}
if !exp && got {
t.Errorf("unexpected object retrieval success")
}
}
}
// temporarily remove peer to test odr fails
lca.UnregisterPeer(lpeer.id)
// expect retrievals to fail (except genesis block) without a les peer
if shouldCache {
test(1)
} else {
test(0)
}
lca.RegisterPeer(lpeer.id, lpeer.version, lpeer.Head(), lpeer.RequestBodies, lpeer.RequestNodeData, lpeer.RequestReceipts, lpeer.RequestProofs)
// expect all retrievals to pass
test(5)
lca.UnregisterPeer(lpeer.id)
if shouldCache {
// still expect all retrievals to pass, now data should be cached locally
test(5)
}
}

View file

@ -2,7 +2,6 @@ package les
import (
"fmt"
"math/big"
"math/rand"
"testing"
@ -15,7 +14,6 @@ import (
"github.com/ethereum/go-ethereum/eth/downloader"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/trie"
)
@ -218,42 +216,8 @@ func testGetBlockBodies(t *testing.T, protocol int) {
func TestGetNodeDataLes1(t *testing.T) { testGetNodeData(t, 1) }
func testGetNodeData(t *testing.T, protocol int) {
// Define three accounts to simulate transactions with
acc1Key, _ := crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
acc2Key, _ := crypto.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee")
acc1Addr := crypto.PubkeyToAddress(acc1Key.PublicKey)
acc2Addr := crypto.PubkeyToAddress(acc2Key.PublicKey)
// Create a chain generator with some simple transactions (blatantly stolen from @fjl/chain_makerts_test)
generator := func(i int, block *core.BlockGen) {
switch i {
case 0:
// In block 1, the test bank sends account #1 some ether.
tx, _ := types.NewTransaction(block.TxNonce(testBankAddress), acc1Addr, big.NewInt(10000), params.TxGas, nil, nil).SignECDSA(testBankKey)
block.AddTx(tx)
case 1:
// In block 2, the test bank sends some more ether to account #1.
// acc1Addr passes it on to account #2.
tx1, _ := types.NewTransaction(block.TxNonce(testBankAddress), acc1Addr, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(testBankKey)
tx2, _ := types.NewTransaction(block.TxNonce(acc1Addr), acc2Addr, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(acc1Key)
block.AddTx(tx1)
block.AddTx(tx2)
case 2:
// Block 3 is empty but was mined by account #2.
block.SetCoinbase(acc2Addr)
block.SetExtra([]byte("yeehaw"))
case 3:
// Block 4 includes blocks 2 and 3 as uncle headers (with modified extra data).
b2 := block.PrevBlock(1).Header()
b2.Extra = []byte("foo")
block.AddUncle(b2)
b3 := block.PrevBlock(2).Header()
b3.Extra = []byte("foo")
block.AddUncle(b3)
}
}
// Assemble the test environment
pm, _ := newTestProtocolManagerMust(t, false, 4, generator)
pm, _ := newTestProtocolManagerMust(t, false, 4, testChainGen)
peer, _ := newTestPeer("peer", protocol, pm, true)
defer peer.close()
@ -309,42 +273,8 @@ func testGetNodeData(t *testing.T, protocol int) {
func TestGetReceiptLes1(t *testing.T) { testGetReceipt(t, 1) }
func testGetReceipt(t *testing.T, protocol int) {
// Define three accounts to simulate transactions with
acc1Key, _ := crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
acc2Key, _ := crypto.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee")
acc1Addr := crypto.PubkeyToAddress(acc1Key.PublicKey)
acc2Addr := crypto.PubkeyToAddress(acc2Key.PublicKey)
// Create a chain generator with some simple transactions (blatantly stolen from @fjl/chain_makerts_test)
generator := func(i int, block *core.BlockGen) {
switch i {
case 0:
// In block 1, the test bank sends account #1 some ether.
tx, _ := types.NewTransaction(block.TxNonce(testBankAddress), acc1Addr, big.NewInt(10000), params.TxGas, nil, nil).SignECDSA(testBankKey)
block.AddTx(tx)
case 1:
// In block 2, the test bank sends some more ether to account #1.
// acc1Addr passes it on to account #2.
tx1, _ := types.NewTransaction(block.TxNonce(testBankAddress), acc1Addr, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(testBankKey)
tx2, _ := types.NewTransaction(block.TxNonce(acc1Addr), acc2Addr, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(acc1Key)
block.AddTx(tx1)
block.AddTx(tx2)
case 2:
// Block 3 is empty but was mined by account #2.
block.SetCoinbase(acc2Addr)
block.SetExtra([]byte("yeehaw"))
case 3:
// Block 4 includes blocks 2 and 3 as uncle headers (with modified extra data).
b2 := block.PrevBlock(1).Header()
b2.Extra = []byte("foo")
block.AddUncle(b2)
b3 := block.PrevBlock(2).Header()
b3.Extra = []byte("foo")
block.AddUncle(b3)
}
}
// Assemble the test environment
pm, _ := newTestProtocolManagerMust(t, false, 4, generator)
pm, _ := newTestProtocolManagerMust(t, false, 4, testChainGen)
peer, _ := newTestPeer("peer", protocol, pm, true)
defer peer.close()
@ -367,42 +297,8 @@ func testGetReceipt(t *testing.T, protocol int) {
func TestGetProofsLes1(t *testing.T) { testGetReceipt(t, 1) }
func testGetProofs(t *testing.T, protocol int) {
// Define three accounts to simulate transactions with
acc1Key, _ := crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
acc2Key, _ := crypto.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee")
acc1Addr := crypto.PubkeyToAddress(acc1Key.PublicKey)
acc2Addr := crypto.PubkeyToAddress(acc2Key.PublicKey)
// Create a chain generator with some simple transactions (blatantly stolen from @fjl/chain_makerts_test)
generator := func(i int, block *core.BlockGen) {
switch i {
case 0:
// In block 1, the test bank sends account #1 some ether.
tx, _ := types.NewTransaction(block.TxNonce(testBankAddress), acc1Addr, big.NewInt(10000), params.TxGas, nil, nil).SignECDSA(testBankKey)
block.AddTx(tx)
case 1:
// In block 2, the test bank sends some more ether to account #1.
// acc1Addr passes it on to account #2.
tx1, _ := types.NewTransaction(block.TxNonce(testBankAddress), acc1Addr, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(testBankKey)
tx2, _ := types.NewTransaction(block.TxNonce(acc1Addr), acc2Addr, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(acc1Key)
block.AddTx(tx1)
block.AddTx(tx2)
case 2:
// Block 3 is empty but was mined by account #2.
block.SetCoinbase(acc2Addr)
block.SetExtra([]byte("yeehaw"))
case 3:
// Block 4 includes blocks 2 and 3 as uncle headers (with modified extra data).
b2 := block.PrevBlock(1).Header()
b2.Extra = []byte("foo")
block.AddUncle(b2)
b3 := block.PrevBlock(2).Header()
b3.Extra = []byte("foo")
block.AddUncle(b3)
}
}
// Assemble the test environment
pm, ca := newTestProtocolManagerMust(t, false, 4, generator)
pm, ca := newTestProtocolManagerMust(t, false, 4, testChainGen)
db := ca.Db()
peer, _ := newTestPeer("peer", protocol, pm, true)
defer peer.close()

View file

@ -16,6 +16,7 @@ import (
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/p2p/discover"
)
@ -24,8 +25,53 @@ var (
testBankKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
testBankAddress = crypto.PubkeyToAddress(testBankKey.PublicKey)
testBankFunds = big.NewInt(1000000)
acc1Key, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
acc2Key, _ = crypto.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee")
acc1Addr = crypto.PubkeyToAddress(acc1Key.PublicKey)
acc2Addr = crypto.PubkeyToAddress(acc2Key.PublicKey)
)
func testChainGen(i int, block *core.BlockGen) {
switch i {
case 0:
// In block 1, the test bank sends account #1 some ether.
tx, _ := types.NewTransaction(block.TxNonce(testBankAddress), acc1Addr, big.NewInt(10000), params.TxGas, nil, nil).SignECDSA(testBankKey)
block.AddTx(tx)
case 1:
// In block 2, the test bank sends some more ether to account #1.
// acc1Addr passes it on to account #2.
// acc1Addr creates a test contract.
tx1, _ := types.NewTransaction(block.TxNonce(testBankAddress), acc1Addr, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(testBankKey)
nonce := block.TxNonce(acc1Addr)
tx2, _ := types.NewTransaction(nonce, acc2Addr, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(acc1Key)
nonce++
tx3, _ := types.NewContractCreation(nonce, big.NewInt(0), big.NewInt(100000), big.NewInt(0), testContractCode).SignECDSA(acc1Key)
testContractAddr = crypto.CreateAddress(acc1Addr, nonce)
block.AddTx(tx1)
block.AddTx(tx2)
block.AddTx(tx3)
case 2:
// Block 3 is empty but was mined by account #2.
block.SetCoinbase(acc2Addr)
block.SetExtra([]byte("yeehaw"))
data := common.Hex2Bytes("C16431B900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001")
tx, _ := types.NewTransaction(block.TxNonce(testBankAddress), testContractAddr, big.NewInt(0), big.NewInt(100000), nil, data).SignECDSA(testBankKey)
block.AddTx(tx)
case 3:
// Block 4 includes blocks 2 and 3 as uncle headers (with modified extra data).
b2 := block.PrevBlock(1).Header()
b2.Extra = []byte("foo")
block.AddUncle(b2)
b3 := block.PrevBlock(2).Header()
b3.Extra = []byte("foo")
block.AddUncle(b3)
data := common.Hex2Bytes("C16431B900000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002")
tx, _ := types.NewTransaction(block.TxNonce(testBankAddress), testContractAddr, big.NewInt(0), big.NewInt(100000), nil, data).SignECDSA(testBankKey)
block.AddTx(tx)
}
}
// newTestProtocolManager creates a new protocol manager for testing purposes,
// with the given number of blocks already known, and potential notification
// channels for different events.

View file

@ -10,22 +10,15 @@ import (
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/access"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie"
)
var (
acc1Key, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
acc2Key, _ = crypto.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee")
acc1Addr = crypto.PubkeyToAddress(acc1Key.PublicKey)
acc2Addr = crypto.PubkeyToAddress(acc2Key.PublicKey)
testContractCode = common.Hex2Bytes("606060405260cc8060106000396000f360606040526000357c01000000000000000000000000000000000000000000000000000000009004806360cd2685146041578063c16431b914606b57603f565b005b6055600480803590602001909190505060a9565b6040518082815260200191505060405180910390f35b60886004808035906020019091908035906020019091905050608a565b005b80600060005083606481101560025790900160005b50819055505b5050565b6000600060005082606481101560025790900160005b5054905060c7565b91905056")
testContractAddr common.Address
)
/*
contract test {
@ -138,48 +131,8 @@ func odrContractCall(ca *access.ChainAccess, bc *core.BlockChain, ctx *access.Od
}
func testOdr(t *testing.T, protocol int, expFail uint64, fn odrTestFn) {
// Create a chain generator with some simple transactions (blatantly stolen from @fjl/chain_makerts_test)
generator := func(i int, block *core.BlockGen) {
switch i {
case 0:
// In block 1, the test bank sends account #1 some ether.
tx, _ := types.NewTransaction(block.TxNonce(testBankAddress), acc1Addr, big.NewInt(10000), params.TxGas, nil, nil).SignECDSA(testBankKey)
block.AddTx(tx)
case 1:
// In block 2, the test bank sends some more ether to account #1.
// acc1Addr passes it on to account #2.
// acc1Addr creates a test contract.
tx1, _ := types.NewTransaction(block.TxNonce(testBankAddress), acc1Addr, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(testBankKey)
nonce := block.TxNonce(acc1Addr)
tx2, _ := types.NewTransaction(nonce, acc2Addr, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(acc1Key)
nonce++
tx3, _ := types.NewContractCreation(nonce, big.NewInt(0), big.NewInt(100000), big.NewInt(0), testContractCode).SignECDSA(acc1Key)
testContractAddr = crypto.CreateAddress(acc1Addr, nonce)
block.AddTx(tx1)
block.AddTx(tx2)
block.AddTx(tx3)
case 2:
// Block 3 is empty but was mined by account #2.
block.SetCoinbase(acc2Addr)
block.SetExtra([]byte("yeehaw"))
data := common.Hex2Bytes("C16431B900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001")
tx, _ := types.NewTransaction(block.TxNonce(testBankAddress), testContractAddr, big.NewInt(0), big.NewInt(100000), nil, data).SignECDSA(testBankKey)
block.AddTx(tx)
case 3:
// Block 4 includes blocks 2 and 3 as uncle headers (with modified extra data).
b2 := block.PrevBlock(1).Header()
b2.Extra = []byte("foo")
block.AddUncle(b2)
b3 := block.PrevBlock(2).Header()
b3.Extra = []byte("foo")
block.AddUncle(b3)
data := common.Hex2Bytes("C16431B900000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002")
tx, _ := types.NewTransaction(block.TxNonce(testBankAddress), testContractAddr, big.NewInt(0), big.NewInt(100000), nil, data).SignECDSA(testBankKey)
block.AddTx(tx)
}
}
// Assemble the test environment
pm, ca := newTestProtocolManagerMust(t, false, 4, generator)
pm, ca := newTestProtocolManagerMust(t, false, 4, testChainGen)
lpm, lca := newTestProtocolManagerMust(t, true, 0, nil)
_, _, lpeer, _ := newTestPeerPair("peer", protocol, pm, lpm)
time.Sleep(time.Millisecond * 100)

View file

@ -109,8 +109,7 @@ func StoreProof(db Database, proof MerkleProof) {
sha := sha3.NewKeccak256()
for _, buf := range proof {
sha.Reset()
sha.Write(buf)
hash := sha.Sum(nil)
hash := sha.Sum(buf)
val, _ := db.Get(hash)
if val == nil {
db.Put(hash, buf)