-
Notifications
You must be signed in to change notification settings - Fork 39
/
mock_l1_network.go
115 lines (93 loc) · 3.16 KB
/
mock_l1_network.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
package ethereummock
import (
"context"
"fmt"
"time"
"github.com/ten-protocol/go-ten/go/common/async"
"github.com/ten-protocol/go-ten/go/common/log"
"github.com/ten-protocol/go-ten/integration/simulation/stats"
"github.com/ten-protocol/go-ten/integration/common/testlog"
testcommon "github.com/ten-protocol/go-ten/integration/common"
"github.com/ten-protocol/go-ten/go/common"
"github.com/ethereum/go-ethereum/core/types"
)
// MockEthNetwork - models a full network including artificial random latencies
// This is the gateway through which the mock L1 nodes communicate with each other
type MockEthNetwork struct {
CurrentNode *Node
AllNodes []*Node
// config
avgLatency time.Duration
avgBlockDuration time.Duration
Stats *stats.Stats
}
// NewMockEthNetwork returns an instance of a configured L1 Network (no nodes)
func NewMockEthNetwork(avgBlockDuration time.Duration, avgLatency time.Duration, stats *stats.Stats) *MockEthNetwork {
return &MockEthNetwork{
Stats: stats,
avgLatency: avgLatency,
avgBlockDuration: avgBlockDuration,
}
}
// BroadcastBlock broadcast a block to the l1 nodes
func (n *MockEthNetwork) BroadcastBlock(b common.EncodedL1Block, p common.EncodedL1Block) {
bl, _ := b.DecodeBlock()
for _, m := range n.AllNodes {
if m.Info().L2ID != n.CurrentNode.Info().L2ID {
t := m
async.Schedule(n.delay(), func() { t.P2PReceiveBlock(b, p) })
} else {
m.logger.Info(printBlock(bl, m))
}
}
n.Stats.NewBlock(bl)
}
// BroadcastTx Broadcasts the L1 tx containing the rollup to the L1 network
func (n *MockEthNetwork) BroadcastTx(tx *types.Transaction) {
for _, m := range n.AllNodes {
if m.Info().L2ID != n.CurrentNode.Info().L2ID {
t := m
// the time to broadcast a tx is half that of a L1 block, because it is smaller.
// todo - find a better way to express this
d := n.delay() / 2
async.Schedule(d, func() { t.P2PGossipTx(tx) })
}
}
}
// delay returns an expected delay on the l1 network
func (n *MockEthNetwork) delay() time.Duration {
return testcommon.RndBtwTime(n.avgLatency/10, 2*n.avgLatency)
}
func printBlock(b *types.Block, m *Node) string {
// This is just for printing
var txs []string
for _, tx := range b.Transactions() {
t := m.erc20ContractLib.DecodeTx(tx)
if t == nil {
t = m.mgmtContractLib.DecodeTx(tx)
}
if t == nil {
continue
}
switch l1Tx := t.(type) {
case *common.L1RollupTx:
r, err := common.DecodeRollup(l1Tx.Rollup)
if err != nil {
testlog.Logger().Crit("failed to decode rollup")
}
txs = append(txs, fmt.Sprintf("r_%d(nonce=%d)", common.ShortHash(r.Hash()), tx.Nonce()))
case *common.L1DepositTx:
var to uint64
if l1Tx.To != nil {
to = common.ShortAddress(*l1Tx.To)
}
txs = append(txs, fmt.Sprintf("deposit(%d=%d)", to, l1Tx.Amount))
}
}
p, err := m.BlockResolver.FetchBlock(context.Background(), b.ParentHash())
if err != nil {
testlog.Logger().Crit("Should not happen. Could not retrieve parent", log.ErrKey, err)
}
return fmt.Sprintf(" create b_%d(Height=%d, RollupNonce=%d)[parent=b_%d]. Txs: %v",
common.ShortHash(b.Hash()), b.NumberU64(), common.ShortNonce(b.Header().Nonce), common.ShortHash(p.Hash()), txs)
}