feat(*): construct interchain txs merkle tree
This commit is contained in:
parent
5a866c23eb
commit
c6e48f257d
7
go.mod
7
go.mod
|
@ -3,6 +3,7 @@ module github.com/meshplus/bitxhub
|
|||
require (
|
||||
github.com/Rican7/retry v0.1.0
|
||||
github.com/aristanetworks/goarista v0.0.0-20200310212843-2da4c1f5881b // indirect
|
||||
github.com/cbergoon/merkletree v0.2.0
|
||||
github.com/common-nighthawk/go-figure v0.0.0-20190529165535-67e0ed34491a
|
||||
github.com/coreos/etcd v3.3.18+incompatible
|
||||
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f // indirect
|
||||
|
@ -19,9 +20,9 @@ require (
|
|||
github.com/hokaccha/go-prettyjson v0.0.0-20190818114111-108c894c2c0e
|
||||
github.com/libp2p/go-libp2p-core v0.3.0
|
||||
github.com/magiconair/properties v1.8.1
|
||||
github.com/meshplus/bitxhub-core v0.1.0-rc1.0.20200509070216-b812d490a331
|
||||
github.com/meshplus/bitxhub-kit v1.0.1-0.20200501052627-8bef1d2acc6e
|
||||
github.com/meshplus/bitxhub-model v1.0.0-rc4.0.20200427024612-57b479c1d610
|
||||
github.com/meshplus/bitxhub-core v0.1.0-rc1.0.20200526060151-b0efad4a2046
|
||||
github.com/meshplus/bitxhub-kit v1.0.1-0.20200525060338-39d86f7542ae
|
||||
github.com/meshplus/bitxhub-model v1.0.0-rc4.0.20200514093243-7e8ae60d1c19
|
||||
github.com/mitchellh/go-homedir v1.1.0
|
||||
github.com/multiformats/go-multiaddr v0.2.0
|
||||
github.com/pkg/errors v0.9.1
|
||||
|
|
23
go.sum
23
go.sum
|
@ -501,18 +501,26 @@ github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzp
|
|||
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/meshplus/bitxhub-core v0.1.0-rc1.0.20200509070216-b812d490a331 h1:1G3kkI8YYZTqj9QzfKy51SGgku5Oil2CQCJpdA3xQjI=
|
||||
github.com/meshplus/bitxhub-core v0.1.0-rc1.0.20200509070216-b812d490a331/go.mod h1:0iCI1ACHiEaVpt3C68NcgDq47dH8DI5FI7Lh9eHQAiw=
|
||||
github.com/meshplus/bitxhub-core v0.1.0-rc1.0.20200519073726-194263cfe6ab h1:g1QW8TgqmEu7bRFuinFcNurhuDOStBt/ZbRJhDFgHrk=
|
||||
github.com/meshplus/bitxhub-core v0.1.0-rc1.0.20200519073726-194263cfe6ab/go.mod h1:JAxVCppTLwO6+NG6z0ycK0RuZZvNFavsx5vqrsV2ewM=
|
||||
github.com/meshplus/bitxhub-core v0.1.0-rc1.0.20200525071523-662c6a8b75fa h1:TmMClDcWPfRGQNtTIMt9QdYgq5oJQRgf7uhBjyj82t0=
|
||||
github.com/meshplus/bitxhub-core v0.1.0-rc1.0.20200525071523-662c6a8b75fa/go.mod h1:txnekA7OS4YIixuSCk62BFKkmlqMP2w4R6Em8AR04pg=
|
||||
github.com/meshplus/bitxhub-core v0.1.0-rc1.0.20200526060151-b0efad4a2046 h1:0ZJsnB7alktEYU8XX7LH4h8umkrYA2n8CGPZVwzdjx8=
|
||||
github.com/meshplus/bitxhub-core v0.1.0-rc1.0.20200526060151-b0efad4a2046/go.mod h1:txnekA7OS4YIixuSCk62BFKkmlqMP2w4R6Em8AR04pg=
|
||||
github.com/meshplus/bitxhub-kit v1.0.0-rc1 h1:gNi8IFU5CMHT3KE2I4ACj5alMW9h/4cV8xOxn7wSmtA=
|
||||
github.com/meshplus/bitxhub-kit v1.0.0-rc1/go.mod h1:ra/AhOkPvpElI+wXrB9G6DjdcrdxFU3vMwA5MYKr9D0=
|
||||
github.com/meshplus/bitxhub-kit v1.0.1-0.20200429033154-8736253c8460 h1:bL+s+LBhGr4g+28DNtqyj4WoVkYdZ5CPoGjdF6Ll0sk=
|
||||
github.com/meshplus/bitxhub-kit v1.0.1-0.20200429033154-8736253c8460/go.mod h1:7cWyhXWZfrQ3+EaxkRoXfuiG3Y5R9DXYJomeZKkETW8=
|
||||
github.com/meshplus/bitxhub-kit v1.0.1-0.20200501052627-8bef1d2acc6e h1:venrZxmUu3Wjayb8yNr7+Gh0wyUGCE6f5I8JTePn4d0=
|
||||
github.com/meshplus/bitxhub-kit v1.0.1-0.20200501052627-8bef1d2acc6e/go.mod h1:7cWyhXWZfrQ3+EaxkRoXfuiG3Y5R9DXYJomeZKkETW8=
|
||||
github.com/meshplus/bitxhub-kit v1.0.1-0.20200525050818-198e65fa54c9/go.mod h1:8Pprmnq+2fFi5kJP0qcbwPl/fe22nro0OamjtwD0LJM=
|
||||
github.com/meshplus/bitxhub-kit v1.0.1-0.20200525060338-39d86f7542ae h1:xp8+WxUWiGTiVYE0cAXm1m/A7sEGYLuV5WDMPFisRsQ=
|
||||
github.com/meshplus/bitxhub-kit v1.0.1-0.20200525060338-39d86f7542ae/go.mod h1:8Pprmnq+2fFi5kJP0qcbwPl/fe22nro0OamjtwD0LJM=
|
||||
github.com/meshplus/bitxhub-model v1.0.0-rc3 h1:oTyaDnhmMPKYifkV2Z5fH2OeY2RE7b6Bk6TzoOT9n4c=
|
||||
github.com/meshplus/bitxhub-model v1.0.0-rc3/go.mod h1:ZCctQIYTlE3vJ8Lhkrgs9bWwNA+Dw4JzojOSIzLVU6E=
|
||||
github.com/meshplus/bitxhub-model v1.0.0-rc4.0.20200427024612-57b479c1d610 h1:BOR7Kgllgx8rpJrqiG2NBU5cUn1ec9NoYozquXwLSLM=
|
||||
github.com/meshplus/bitxhub-model v1.0.0-rc4.0.20200427024612-57b479c1d610/go.mod h1:ZCctQIYTlE3vJ8Lhkrgs9bWwNA+Dw4JzojOSIzLVU6E=
|
||||
github.com/meshplus/bitxhub-model v1.0.0-rc4.0.20200429111056-62b55c3d4260/go.mod h1:QK8aACbxtZEA3Hk1BOCirW0uxMWLsMrLDpWz9FweIKM=
|
||||
github.com/meshplus/bitxhub-model v1.0.0-rc4.0.20200514093243-7e8ae60d1c19 h1:D0n0/NqaueI6r+/cJIjYzWwjZ9j/5l36r/c8MYqTdXg=
|
||||
github.com/meshplus/bitxhub-model v1.0.0-rc4.0.20200514093243-7e8ae60d1c19/go.mod h1:QK8aACbxtZEA3Hk1BOCirW0uxMWLsMrLDpWz9FweIKM=
|
||||
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
|
||||
github.com/miekg/dns v1.1.12/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||
github.com/miekg/pkcs11 v1.0.3 h1:iMwmD7I5225wv84WxIG/bmxz9AXjWvTWIbM/TYHvWtw=
|
||||
|
@ -632,8 +640,6 @@ github.com/prometheus/client_golang v1.4.1 h1:FFSuS004yOQEtDdTq+TAOLP5xUq63KqAFY
|
|||
github.com/prometheus/client_golang v1.4.1/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU=
|
||||
github.com/prometheus/client_golang v1.5.0 h1:Ctq0iGpCmr3jeP77kbF2UxgvRwzWWz+4Bh9/vJTyg1A=
|
||||
github.com/prometheus/client_golang v1.5.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU=
|
||||
github.com/prometheus/client_golang v1.6.0 h1:YVPodQOcK15POxhgARIvnDRVpLcuK8mglnMrWfyrw6A=
|
||||
github.com/prometheus/client_golang v1.6.0/go.mod h1:ZLOG9ck3JLRdB5MgO8f+lLTe83AXG6ro35rLTxvnIl4=
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910 h1:idejC8f05m9MGOsuEi1ATq9shN03HrxNkD/luQvxCv8=
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90 h1:S/YWwWx/RA8rT8tKFRuGUZhuA90OyIBpPCXkcbwU8DE=
|
||||
|
@ -656,8 +662,6 @@ github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsT
|
|||
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
|
||||
github.com/prometheus/procfs v0.0.10 h1:QJQN3jYQhkamO4mhfUWqdDH2asK7ONOI9MTWjyAxNKM=
|
||||
github.com/prometheus/procfs v0.0.10/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
|
||||
github.com/prometheus/procfs v0.0.11 h1:DhHlBtkHWPYi8O2y31JkK0TF+DGM+51OopZjH/Ia5qI=
|
||||
github.com/prometheus/procfs v0.0.11/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||
github.com/prometheus/tsdb v0.6.2-0.20190402121629-4f204dcbc150/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20190826022208-cac0b30c2563 h1:dY6ETXrvDG7Sa4vE8ZQG4yqWg6UnOcbqTAahkV813vQ=
|
||||
|
@ -902,13 +906,10 @@ golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191210023423-ac6580df4449 h1:gSbV7h1NRL2G1xTg/owz62CST1oJBmxy4QpMMregXVQ=
|
||||
golang.org/x/sys v0.0.0-20191210023423-ac6580df4449/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200219091948-cb0a6d8edb6c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527 h1:uYVVQ9WP/Ds2ROhcaGPeIdVq0RIXVLwsHlnvJ+cT1So=
|
||||
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f h1:gWF768j/LaZugp8dyS4UwsslYCYz9XgFxvlgsn0n9H8=
|
||||
golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
|
|
|
@ -34,6 +34,7 @@ type BlockExecutor struct {
|
|||
persistC chan *ledger.BlockData
|
||||
pendingBlockQ *cache.Cache
|
||||
interchainCounter map[string][]uint64
|
||||
normalTxs []types.Hash
|
||||
validationEngine validator.Engine
|
||||
currentHeight uint64
|
||||
currentBlockHash types.Hash
|
||||
|
|
|
@ -63,7 +63,7 @@ func TestBlockExecutor_ExecuteBlock(t *testing.T) {
|
|||
mockLedger.EXPECT().GetNonce(gomock.Any()).Return(uint64(0)).AnyTimes()
|
||||
mockLedger.EXPECT().SetCode(gomock.Any(), gomock.Any()).AnyTimes()
|
||||
mockLedger.EXPECT().GetCode(gomock.Any()).Return([]byte("10")).AnyTimes()
|
||||
mockLedger.EXPECT().PersistExecutionResult(gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
|
||||
mockLedger.EXPECT().PersistExecutionResult(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
|
||||
mockLedger.EXPECT().FlushDirtyDataAndComputeJournal().Return(make(map[string]*ledger.Account), &ledger.BlockJournal{}).AnyTimes()
|
||||
mockLedger.EXPECT().PersistBlockData(gomock.Any()).AnyTimes()
|
||||
logger := log.NewWithModule("executor")
|
||||
|
@ -181,7 +181,7 @@ func TestBlockExecutor_ExecuteBlock_Transfer(t *testing.T) {
|
|||
account, journal := ledger.FlushDirtyDataAndComputeJournal()
|
||||
err = ledger.Commit(1, account, journal)
|
||||
require.Nil(t, err)
|
||||
err = ledger.PersistExecutionResult(mockBlock(1, nil), nil)
|
||||
err = ledger.PersistExecutionResult(mockBlock(1, nil), nil, nil)
|
||||
require.Nil(t, err)
|
||||
|
||||
executor, err := New(ledger, log.NewWithModule("executor"))
|
||||
|
@ -269,12 +269,21 @@ func mockTxData(t *testing.T, dataType pb.TransactionData_Type, vmType pb.Transa
|
|||
}
|
||||
|
||||
func mockIBTP(t *testing.T, index uint64, typ pb.IBTP_Type) *pb.IBTP {
|
||||
ibtppd, err := json.Marshal(pb.Payload{
|
||||
content := pb.Content{
|
||||
SrcContractId: from,
|
||||
DstContractId: from,
|
||||
Func: "set",
|
||||
}
|
||||
|
||||
bytes, err := content.Marshal()
|
||||
assert.Nil(t, err)
|
||||
|
||||
ibtppd, err := json.Marshal(pb.Payload{
|
||||
Encrypted: false,
|
||||
Content: bytes,
|
||||
})
|
||||
assert.Nil(t, err)
|
||||
|
||||
return &pb.IBTP{
|
||||
From: from,
|
||||
To: from,
|
||||
|
|
|
@ -1,14 +1,16 @@
|
|||
package executor
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"sort"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/cbergoon/merkletree"
|
||||
"github.com/meshplus/bitxhub-kit/crypto/asym"
|
||||
"github.com/meshplus/bitxhub-kit/merkle/merkletree"
|
||||
"github.com/meshplus/bitxhub-kit/types"
|
||||
"github.com/meshplus/bitxhub-model/pb"
|
||||
"github.com/meshplus/bitxhub/internal/ledger"
|
||||
|
@ -57,12 +59,20 @@ func (exec *BlockExecutor) processExecuteEvent(block *pb.Block) {
|
|||
receipts := exec.applyTransactions(validTxs)
|
||||
receipts = append(receipts, invalidReceipts...)
|
||||
|
||||
root, receiptRoot, err := exec.calcMerkleRoots(block.Transactions, receipts)
|
||||
calcMerkleStart := time.Now()
|
||||
l1Root, l2Roots, err := exec.buildTxMerkleTree(block.Transactions)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
block.BlockHeader.TxRoot = root
|
||||
receiptRoot, err := exec.calcReceiptMerkleRoot(receipts)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
calcMerkleDuration.Observe(float64(time.Since(calcMerkleStart)) / float64(time.Second))
|
||||
|
||||
block.BlockHeader.TxRoot = l1Root
|
||||
block.BlockHeader.ReceiptRoot = receiptRoot
|
||||
block.BlockHeader.ParentHash = exec.currentBlockHash
|
||||
idx, err := json.Marshal(exec.interchainCounter)
|
||||
|
@ -90,13 +100,80 @@ func (exec *BlockExecutor) processExecuteEvent(block *pb.Block) {
|
|||
exec.currentBlockHash = block.BlockHash
|
||||
|
||||
exec.persistC <- &ledger.BlockData{
|
||||
Block: block,
|
||||
Receipts: receipts,
|
||||
Accounts: accounts,
|
||||
Journal: journal,
|
||||
Block: block,
|
||||
Receipts: receipts,
|
||||
Accounts: accounts,
|
||||
Journal: journal,
|
||||
L2TxRoots: l2Roots,
|
||||
}
|
||||
}
|
||||
|
||||
func (exec *BlockExecutor) buildTxMerkleTree(txs []*pb.Transaction) (types.Hash, []types.Hash, error) {
|
||||
var (
|
||||
groupCnt = len(exec.interchainCounter) + 1
|
||||
wg = sync.WaitGroup{}
|
||||
lock = sync.Mutex{}
|
||||
l2Roots = make([]types.Hash, 0, groupCnt)
|
||||
errorCnt = int32(0)
|
||||
)
|
||||
|
||||
wg.Add(groupCnt - 1)
|
||||
for addr, txIndexes := range exec.interchainCounter {
|
||||
go func(addr string, txIndexes []uint64) {
|
||||
defer wg.Done()
|
||||
|
||||
txHashes := make([]merkletree.Content, 0, len(txIndexes))
|
||||
for _, txIndex := range txIndexes {
|
||||
txHashes = append(txHashes, pb.TransactionHash(txs[txIndex].TransactionHash.Bytes()))
|
||||
}
|
||||
|
||||
hash, err := calcMerkleRoot(txHashes)
|
||||
if err != nil {
|
||||
atomic.AddInt32(&errorCnt, 1)
|
||||
return
|
||||
}
|
||||
|
||||
lock.Lock()
|
||||
defer lock.Unlock()
|
||||
l2Roots = append(l2Roots, hash)
|
||||
}(addr, txIndexes)
|
||||
}
|
||||
|
||||
txHashes := make([]merkletree.Content, 0, len(exec.normalTxs))
|
||||
for _, txHash := range exec.normalTxs {
|
||||
txHashes = append(txHashes, pb.TransactionHash(txHash.Bytes()))
|
||||
}
|
||||
|
||||
hash, err := calcMerkleRoot(txHashes)
|
||||
if err != nil {
|
||||
atomic.AddInt32(&errorCnt, 1)
|
||||
}
|
||||
|
||||
lock.Lock()
|
||||
l2Roots = append(l2Roots, hash)
|
||||
lock.Unlock()
|
||||
|
||||
wg.Wait()
|
||||
if errorCnt != 0 {
|
||||
return types.Hash{}, nil, fmt.Errorf("build tx merkle tree error")
|
||||
}
|
||||
|
||||
sort.Slice(l2Roots, func(i, j int) bool {
|
||||
return bytes.Compare(l2Roots[i].Bytes(), l2Roots[j].Bytes()) < 0
|
||||
})
|
||||
|
||||
contents := make([]merkletree.Content, 0, groupCnt)
|
||||
for _, l2Root := range l2Roots {
|
||||
contents = append(contents, pb.TransactionHash(l2Root.Bytes()))
|
||||
}
|
||||
root, err := calcMerkleRoot(contents)
|
||||
if err != nil {
|
||||
return types.Hash{}, nil, err
|
||||
}
|
||||
|
||||
return root, l2Roots, nil
|
||||
}
|
||||
|
||||
func (exec *BlockExecutor) verifySign(block *pb.Block) ([]*pb.Transaction, []*pb.Receipt) {
|
||||
if block.BlockHeader.Number == 1 {
|
||||
return block.Transactions, nil
|
||||
|
@ -161,6 +238,8 @@ func (exec *BlockExecutor) applyTransactions(txs []*pb.Transaction) []*pb.Receip
|
|||
TxHash: tx.TransactionHash,
|
||||
}
|
||||
|
||||
normalTx := true
|
||||
|
||||
ret, err := exec.applyTransaction(i, tx)
|
||||
if err != nil {
|
||||
receipt.Status = pb.Receipt_FAILED
|
||||
|
@ -184,10 +263,15 @@ func (exec *BlockExecutor) applyTransactions(txs []*pb.Transaction) []*pb.Receip
|
|||
for k, v := range m {
|
||||
exec.interchainCounter[k] = append(exec.interchainCounter[k], v)
|
||||
}
|
||||
normalTx = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if normalTx {
|
||||
exec.normalTxs = append(exec.normalTxs, tx.TransactionHash)
|
||||
}
|
||||
|
||||
receipts = append(receipts, receipt)
|
||||
}
|
||||
|
||||
|
@ -247,42 +331,6 @@ func (exec *BlockExecutor) applyTransaction(i int, tx *pb.Transaction) ([]byte,
|
|||
}
|
||||
}
|
||||
|
||||
func (exec *BlockExecutor) calcMerkleRoot(txs []*pb.Transaction) (types.Hash, error) {
|
||||
if len(txs) == 0 {
|
||||
return types.Hash{}, nil
|
||||
}
|
||||
|
||||
hashes := make([]interface{}, 0, len(txs))
|
||||
for _, tx := range txs {
|
||||
hashes = append(hashes, pb.TransactionHash(tx.TransactionHash.Bytes()))
|
||||
}
|
||||
tree := merkletree.NewMerkleTree()
|
||||
err := tree.InitMerkleTree(hashes)
|
||||
if err != nil {
|
||||
return types.Hash{}, err
|
||||
}
|
||||
|
||||
return types.Bytes2Hash(tree.GetMerkleRoot()), nil
|
||||
}
|
||||
|
||||
func (exec *BlockExecutor) calcReceiptMerkleRoot(receipts []*pb.Receipt) (types.Hash, error) {
|
||||
if len(receipts) == 0 {
|
||||
return types.Hash{}, nil
|
||||
}
|
||||
|
||||
hashes := make([]interface{}, 0, len(receipts))
|
||||
for _, receipt := range receipts {
|
||||
hashes = append(hashes, pb.TransactionHash(receipt.Hash().Bytes()))
|
||||
}
|
||||
tree := merkletree.NewMerkleTree()
|
||||
err := tree.InitMerkleTree(hashes)
|
||||
if err != nil {
|
||||
return types.Hash{}, err
|
||||
}
|
||||
|
||||
return types.Bytes2Hash(tree.GetMerkleRoot()), nil
|
||||
}
|
||||
|
||||
func (exec *BlockExecutor) clear() {
|
||||
exec.interchainCounter = make(map[string][]uint64)
|
||||
exec.ledger.Clear()
|
||||
|
@ -306,19 +354,32 @@ func (exec *BlockExecutor) transfer(from, to types.Address, value uint64) error
|
|||
return nil
|
||||
}
|
||||
|
||||
func (exec *BlockExecutor) calcMerkleRoots(txs []*pb.Transaction, receipts []*pb.Receipt) (types.Hash, types.Hash, error) {
|
||||
func (exec *BlockExecutor) calcReceiptMerkleRoot(receipts []*pb.Receipt) (types.Hash, error) {
|
||||
current := time.Now()
|
||||
root, err := exec.calcMerkleRoot(txs)
|
||||
|
||||
receiptHashes := make([]merkletree.Content, 0, len(receipts))
|
||||
for _, receipt := range receipts {
|
||||
receiptHashes = append(receiptHashes, pb.TransactionHash(receipt.Hash().Bytes()))
|
||||
}
|
||||
receiptRoot, err := calcMerkleRoot(receiptHashes)
|
||||
if err != nil {
|
||||
return types.Hash{}, types.Hash{}, err
|
||||
return types.Hash{}, err
|
||||
}
|
||||
|
||||
receiptRoot, err := exec.calcReceiptMerkleRoot(receipts)
|
||||
if err != nil {
|
||||
return types.Hash{}, types.Hash{}, err
|
||||
}
|
||||
exec.logger.WithField("time", time.Since(current)).Debug("Calculate receipt merkle roots")
|
||||
|
||||
exec.logger.WithField("time", time.Since(current)).Debug("calculate merkle roots")
|
||||
calcMerkleDuration.Observe(float64(time.Since(current)) / float64(time.Second))
|
||||
return root, receiptRoot, nil
|
||||
return receiptRoot, nil
|
||||
}
|
||||
|
||||
func calcMerkleRoot(contents []merkletree.Content) (types.Hash, error) {
|
||||
if len(contents) == 0 {
|
||||
return types.Hash{}, nil
|
||||
}
|
||||
|
||||
tree, err := merkletree.NewTree(contents)
|
||||
if err != nil {
|
||||
return types.Hash{}, err
|
||||
}
|
||||
|
||||
return types.Bytes2Hash(tree.MerkleRoot()), nil
|
||||
}
|
||||
|
|
|
@ -118,7 +118,7 @@ func (l *ChainLedger) GetReceipt(hash types.Hash) (*pb.Receipt, error) {
|
|||
}
|
||||
|
||||
// PersistExecutionResult persist the execution result
|
||||
func (l *ChainLedger) PersistExecutionResult(block *pb.Block, receipts []*pb.Receipt) error {
|
||||
func (l *ChainLedger) PersistExecutionResult(block *pb.Block, receipts []*pb.Receipt, l2Roots []types.Hash) error {
|
||||
current := time.Now()
|
||||
|
||||
if block == nil {
|
||||
|
@ -139,6 +139,10 @@ func (l *ChainLedger) PersistExecutionResult(block *pb.Block, receipts []*pb.Rec
|
|||
return err
|
||||
}
|
||||
|
||||
if err := l.persistL2TxRoots(batcher, l2Roots, block.BlockHeader.Number); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// update chain meta in cache
|
||||
count, err := getInterchainTxCount(block.BlockHeader)
|
||||
if err != nil {
|
||||
|
@ -258,6 +262,17 @@ func (l *ChainLedger) persistBlock(batcher storage.Batch, block *pb.Block) error
|
|||
return nil
|
||||
}
|
||||
|
||||
func (l *ChainLedger) persistL2TxRoots(batcher storage.Batch, l2Roots []types.Hash, height uint64) error {
|
||||
roots, err := json.Marshal(l2Roots)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
batcher.Put(compositeKey(l2TxRootsKey, height), roots)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *ChainLedger) persistChainMeta(batcher storage.Batch, meta *pb.ChainMeta) error {
|
||||
data, err := meta.Marshal()
|
||||
if err != nil {
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
const (
|
||||
blockKey = "block-"
|
||||
blockHashKey = "block-hash-"
|
||||
l2TxRootsKey = "l2-tx-roots-"
|
||||
receiptKey = "receipt-"
|
||||
transactionKey = "tx-"
|
||||
transactionMetaKey = "tx-meta-"
|
||||
|
|
|
@ -40,10 +40,11 @@ type ChainLedger struct {
|
|||
}
|
||||
|
||||
type BlockData struct {
|
||||
Block *pb.Block
|
||||
Receipts []*pb.Receipt
|
||||
Accounts map[string]*Account
|
||||
Journal *BlockJournal
|
||||
Block *pb.Block
|
||||
Receipts []*pb.Receipt
|
||||
Accounts map[string]*Account
|
||||
Journal *BlockJournal
|
||||
L2TxRoots []types.Hash
|
||||
}
|
||||
|
||||
// New create a new ledger instance
|
||||
|
@ -98,12 +99,13 @@ func (l *ChainLedger) PersistBlockData(blockData *BlockData) {
|
|||
receipts := blockData.Receipts
|
||||
accounts := blockData.Accounts
|
||||
journal := blockData.Journal
|
||||
l2Roots := blockData.L2TxRoots
|
||||
|
||||
if err := l.Commit(block.BlockHeader.Number, accounts, journal); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if err := l.PersistExecutionResult(block, receipts); err != nil {
|
||||
if err := l.PersistExecutionResult(block, receipts, l2Roots); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
|
|
|
@ -101,7 +101,7 @@ type BlockchainLedger interface {
|
|||
GetReceipt(hash types.Hash) (*pb.Receipt, error)
|
||||
|
||||
// PersistExecutionResult persist the execution result
|
||||
PersistExecutionResult(block *pb.Block, receipts []*pb.Receipt) error
|
||||
PersistExecutionResult(block *pb.Block, receipts []*pb.Receipt, l2Roots []types.Hash) error
|
||||
|
||||
// GetChainMeta get chain meta data
|
||||
GetChainMeta() *pb.ChainMeta
|
||||
|
|
Loading…
Reference in New Issue