From 3c0ef7b6ac5040cd53cebcb457bdddc0adce0b2a Mon Sep 17 00:00:00 2001 From: Somnath Date: Mon, 9 Dec 2024 17:20:16 +0400 Subject: [PATCH 01/24] chore: Re-gen mocks, abi, and contract builds (#13034) - Re-gen with `gencodec`, `abigen` and `mockgen` since there have been some changes in the generators and token replacements - Also fix `gofmt` in the process - issues introduced by recent PRs to refactor imports of erigon-lib --- .../mock_services/aggregation_pool_mock.go | 17 +- cmd/devnet/contracts/gen.go | 2 +- cmd/devnet/contracts/gen_childreceiver.go | 18 +- cmd/devnet/contracts/gen_childsender.go | 18 +- cmd/devnet/contracts/gen_faucet.go | 22 +- cmd/devnet/contracts/gen_rootreceiver.go | 18 +- cmd/devnet/contracts/gen_rootsender.go | 14 +- cmd/devnet/contracts/gen_testrootchain.go | 52 ++-- cmd/devnet/contracts/gen_teststatesender.go | 36 ++- cmd/evm/internal/t8ntool/gen_stenv.go | 7 +- cmd/pics/contracts/gen_token.go | 90 ++++++- consensus/aura/auraabi/gen_block_reward.go | 19 +- consensus/aura/auraabi/gen_validator_set.go | 10 +- core/state/contracts/gen.go | 5 + core/state/contracts/gen_changer.go | 12 +- core/state/contracts/gen_phoenix.go | 12 +- core/state/contracts/gen_poly.go | 54 +++- core/state/contracts/gen_revive.go | 54 +++- core/state/contracts/gen_revive2.go | 54 +++- core/state/contracts/gen_selfdestruct.go | 12 +- core/types/gen_genesis.go | 77 +++--- eth/ethconfig/gen_config.go | 39 +-- polygon/bor/state_receiver_mock.go | 2 +- tests/contracts/gen.go | 2 +- tests/contracts/gen_selfDestructor.go | 12 +- tests/contracts/gen_testcontract.go | 236 +++++++++++++++++- tests/difficulty_test_util.go | 2 +- tests/gen_stenv.go | 36 ++- turbo/jsonrpc/contracts/gen.go | 4 + turbo/jsonrpc/contracts/gen_poly.go | 91 ++++++- turbo/jsonrpc/contracts/gen_token.go | 90 ++++++- 31 files changed, 877 insertions(+), 240 deletions(-) diff --git a/cl/aggregation/mock_services/aggregation_pool_mock.go b/cl/aggregation/mock_services/aggregation_pool_mock.go index 7946cc7d9ec..15e3404fdc3 100644 --- a/cl/aggregation/mock_services/aggregation_pool_mock.go +++ b/cl/aggregation/mock_services/aggregation_pool_mock.go @@ -21,6 +21,7 @@ import ( type MockAggregationPool struct { ctrl *gomock.Controller recorder *MockAggregationPoolMockRecorder + isgomock struct{} } // MockAggregationPoolMockRecorder is the mock recorder for MockAggregationPool. @@ -41,17 +42,17 @@ func (m *MockAggregationPool) EXPECT() *MockAggregationPoolMockRecorder { } // AddAttestation mocks base method. -func (m *MockAggregationPool) AddAttestation(arg0 *solid.Attestation) error { +func (m *MockAggregationPool) AddAttestation(att *solid.Attestation) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "AddAttestation", arg0) + ret := m.ctrl.Call(m, "AddAttestation", att) ret0, _ := ret[0].(error) return ret0 } // AddAttestation indicates an expected call of AddAttestation. -func (mr *MockAggregationPoolMockRecorder) AddAttestation(arg0 any) *MockAggregationPoolAddAttestationCall { +func (mr *MockAggregationPoolMockRecorder) AddAttestation(att any) *MockAggregationPoolAddAttestationCall { mr.mock.ctrl.T.Helper() - call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddAttestation", reflect.TypeOf((*MockAggregationPool)(nil).AddAttestation), arg0) + call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddAttestation", reflect.TypeOf((*MockAggregationPool)(nil).AddAttestation), att) return &MockAggregationPoolAddAttestationCall{Call: call} } @@ -79,17 +80,17 @@ func (c *MockAggregationPoolAddAttestationCall) DoAndReturn(f func(*solid.Attest } // GetAggregatationByRoot mocks base method. -func (m *MockAggregationPool) GetAggregatationByRoot(arg0 common.Hash) *solid.Attestation { +func (m *MockAggregationPool) GetAggregatationByRoot(root common.Hash) *solid.Attestation { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetAggregatationByRoot", arg0) + ret := m.ctrl.Call(m, "GetAggregatationByRoot", root) ret0, _ := ret[0].(*solid.Attestation) return ret0 } // GetAggregatationByRoot indicates an expected call of GetAggregatationByRoot. -func (mr *MockAggregationPoolMockRecorder) GetAggregatationByRoot(arg0 any) *MockAggregationPoolGetAggregatationByRootCall { +func (mr *MockAggregationPoolMockRecorder) GetAggregatationByRoot(root any) *MockAggregationPoolGetAggregatationByRootCall { mr.mock.ctrl.T.Helper() - call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAggregatationByRoot", reflect.TypeOf((*MockAggregationPool)(nil).GetAggregatationByRoot), arg0) + call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAggregatationByRoot", reflect.TypeOf((*MockAggregationPool)(nil).GetAggregatationByRoot), root) return &MockAggregationPoolGetAggregatationByRootCall{Call: call} } diff --git a/cmd/devnet/contracts/gen.go b/cmd/devnet/contracts/gen.go index 964f8498ed1..f9da61a64fa 100644 --- a/cmd/devnet/contracts/gen.go +++ b/cmd/devnet/contracts/gen.go @@ -42,4 +42,4 @@ package contracts // faucet.sol //go:generate solc --evm-version paris --allow-paths ., --abi --bin --overwrite --optimize -o build faucet.sol -//go:generate abigen -abi build/Faucet.abi -bin build/Faucet.bin -pkg contracts -type Faucet -out ./gen_faucet.go +//go:generate abigen -abi build/faucet.abi -bin build/faucet.bin -pkg contracts -type Faucet -out ./gen_faucet.go diff --git a/cmd/devnet/contracts/gen_childreceiver.go b/cmd/devnet/contracts/gen_childreceiver.go index 55b39a483bf..3dffdb0a1c4 100644 --- a/cmd/devnet/contracts/gen_childreceiver.go +++ b/cmd/devnet/contracts/gen_childreceiver.go @@ -1,4 +1,4 @@ -// Code generated - DO NOT EDIT. +// Code generated by abigen. DO NOT EDIT. // This file is a generated binding and any manual changes will be lost. package contracts @@ -26,6 +26,8 @@ var ( _ = libcommon.Big1 _ = types.BloomLookup _ = event.NewSubscription + _ = fmt.Errorf + _ = reflect.ValueOf ) // ChildReceiverABI is the input ABI used to generate the binding from. @@ -242,8 +244,8 @@ func (_ChildReceiver *ChildReceiverTransactorSession) OnStateReceive(arg0 *big.I return _ChildReceiver.Contract.OnStateReceive(&_ChildReceiver.TransactOpts, arg0, data) } -// OnStateReceiveParams is an auto generated read-only Go binding of transcaction calldata params -type OnStateReceiveParams struct { +// ChildReceiverOnStateReceiveParams is an auto generated read-only Go binding of transcaction calldata params +type ChildReceiverOnStateReceiveParams struct { Param_arg0 *big.Int Param_data []byte } @@ -251,7 +253,7 @@ type OnStateReceiveParams struct { // Parse OnStateReceive method from calldata of a transaction // // Solidity: function onStateReceive(uint256 , bytes data) returns() -func ParseOnStateReceive(calldata []byte) (*OnStateReceiveParams, error) { +func ParseChildReceiverOnStateReceiveParams(calldata []byte) (*ChildReceiverOnStateReceiveParams, error) { if len(calldata) <= 4 { return nil, fmt.Errorf("invalid calldata input") } @@ -266,7 +268,7 @@ func ParseOnStateReceive(calldata []byte) (*OnStateReceiveParams, error) { return nil, fmt.Errorf("failed to unpack onStateReceive params data: %w", err) } - var paramsResult = new(OnStateReceiveParams) + var paramsResult = new(ChildReceiverOnStateReceiveParams) value := reflect.ValueOf(paramsResult).Elem() if value.NumField() != len(out) { @@ -276,7 +278,7 @@ func ParseOnStateReceive(calldata []byte) (*OnStateReceiveParams, error) { out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) out1 := *abi.ConvertType(out[1], new([]byte)).(*[]byte) - return &OnStateReceiveParams{ + return &ChildReceiverOnStateReceiveParams{ Param_arg0: out0, Param_data: out1, }, nil } @@ -355,6 +357,10 @@ type ChildReceiverReceived struct { Raw types.Log // Blockchain specific contextual infos } +func (_ChildReceiver *ChildReceiverFilterer) ReceivedEventID() libcommon.Hash { + return libcommon.HexToHash("0xf11e547d796cc64acdf758e7cee90439494fd886a19159454aa61e473fdbafef") +} + // FilterReceived is a free log retrieval operation binding the contract event 0xf11e547d796cc64acdf758e7cee90439494fd886a19159454aa61e473fdbafef. // // Solidity: event received(address _source, uint256 _amount) diff --git a/cmd/devnet/contracts/gen_childsender.go b/cmd/devnet/contracts/gen_childsender.go index e0924f63bc0..8690c85a9db 100644 --- a/cmd/devnet/contracts/gen_childsender.go +++ b/cmd/devnet/contracts/gen_childsender.go @@ -1,4 +1,4 @@ -// Code generated - DO NOT EDIT. +// Code generated by abigen. DO NOT EDIT. // This file is a generated binding and any manual changes will be lost. package contracts @@ -26,6 +26,8 @@ var ( _ = libcommon.Big1 _ = types.BloomLookup _ = event.NewSubscription + _ = fmt.Errorf + _ = reflect.ValueOf ) // ChildSenderABI is the input ABI used to generate the binding from. @@ -242,15 +244,15 @@ func (_ChildSender *ChildSenderTransactorSession) SendToRoot(amount *big.Int) (t return _ChildSender.Contract.SendToRoot(&_ChildSender.TransactOpts, amount) } -// SendToRootParams is an auto generated read-only Go binding of transcaction calldata params -type SendToRootParams struct { +// ChildSenderSendToRootParams is an auto generated read-only Go binding of transcaction calldata params +type ChildSenderSendToRootParams struct { Param_amount *big.Int } // Parse SendToRoot method from calldata of a transaction // // Solidity: function sendToRoot(uint256 amount) returns() -func ParseSendToRoot(calldata []byte) (*SendToRootParams, error) { +func ParseChildSenderSendToRootParams(calldata []byte) (*ChildSenderSendToRootParams, error) { if len(calldata) <= 4 { return nil, fmt.Errorf("invalid calldata input") } @@ -265,7 +267,7 @@ func ParseSendToRoot(calldata []byte) (*SendToRootParams, error) { return nil, fmt.Errorf("failed to unpack sendToRoot params data: %w", err) } - var paramsResult = new(SendToRootParams) + var paramsResult = new(ChildSenderSendToRootParams) value := reflect.ValueOf(paramsResult).Elem() if value.NumField() != len(out) { @@ -274,7 +276,7 @@ func ParseSendToRoot(calldata []byte) (*SendToRootParams, error) { out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - return &SendToRootParams{ + return &ChildSenderSendToRootParams{ Param_amount: out0, }, nil } @@ -352,6 +354,10 @@ type ChildSenderMessageSent struct { Raw types.Log // Blockchain specific contextual infos } +func (_ChildSender *ChildSenderFilterer) MessageSentEventID() libcommon.Hash { + return libcommon.HexToHash("0x8c5261668696ce22758910d05bab8f186d6eb247ceac2af2e82c7dc17669b036") +} + // FilterMessageSent is a free log retrieval operation binding the contract event 0x8c5261668696ce22758910d05bab8f186d6eb247ceac2af2e82c7dc17669b036. // // Solidity: event MessageSent(bytes message) diff --git a/cmd/devnet/contracts/gen_faucet.go b/cmd/devnet/contracts/gen_faucet.go index fcd3741da20..69a3482bb68 100644 --- a/cmd/devnet/contracts/gen_faucet.go +++ b/cmd/devnet/contracts/gen_faucet.go @@ -1,4 +1,4 @@ -// Code generated - DO NOT EDIT. +// Code generated by abigen. DO NOT EDIT. // This file is a generated binding and any manual changes will be lost. package contracts @@ -26,6 +26,8 @@ var ( _ = libcommon.Big1 _ = types.BloomLookup _ = event.NewSubscription + _ = fmt.Errorf + _ = reflect.ValueOf ) // FaucetABI is the input ABI used to generate the binding from. @@ -273,8 +275,8 @@ func (_Faucet *FaucetTransactorSession) Send(_destination libcommon.Address, _re return _Faucet.Contract.Send(&_Faucet.TransactOpts, _destination, _requested) } -// SendParams is an auto generated read-only Go binding of transcaction calldata params -type SendParams struct { +// FaucetSendParams is an auto generated read-only Go binding of transcaction calldata params +type FaucetSendParams struct { Param__destination libcommon.Address Param__requested *big.Int } @@ -282,7 +284,7 @@ type SendParams struct { // Parse Send method from calldata of a transaction // // Solidity: function send(address _destination, uint256 _requested) payable returns() -func ParseSend(calldata []byte) (*SendParams, error) { +func ParseFaucetSendParams(calldata []byte) (*FaucetSendParams, error) { if len(calldata) <= 4 { return nil, fmt.Errorf("invalid calldata input") } @@ -297,7 +299,7 @@ func ParseSend(calldata []byte) (*SendParams, error) { return nil, fmt.Errorf("failed to unpack send params data: %w", err) } - var paramsResult = new(SendParams) + var paramsResult = new(FaucetSendParams) value := reflect.ValueOf(paramsResult).Elem() if value.NumField() != len(out) { @@ -307,7 +309,7 @@ func ParseSend(calldata []byte) (*SendParams, error) { out0 := *abi.ConvertType(out[0], new(libcommon.Address)).(*libcommon.Address) out1 := *abi.ConvertType(out[1], new(*big.Int)).(**big.Int) - return &SendParams{ + return &FaucetSendParams{ Param__destination: out0, Param__requested: out1, }, nil } @@ -407,6 +409,10 @@ type FaucetReceived struct { Raw types.Log // Blockchain specific contextual infos } +func (_Faucet *FaucetFilterer) ReceivedEventID() libcommon.Hash { + return libcommon.HexToHash("0xf11e547d796cc64acdf758e7cee90439494fd886a19159454aa61e473fdbafef") +} + // FilterReceived is a free log retrieval operation binding the contract event 0xf11e547d796cc64acdf758e7cee90439494fd886a19159454aa61e473fdbafef. // // Solidity: event received(address _source, uint256 _amount) @@ -542,6 +548,10 @@ type FaucetSent struct { Raw types.Log // Blockchain specific contextual infos } +func (_Faucet *FaucetFilterer) SentEventID() libcommon.Hash { + return libcommon.HexToHash("0x3bcb2e664d8f57273201bc888e82d6549f8308a52a9fcd7702b2ea8387f769a9") +} + // FilterSent is a free log retrieval operation binding the contract event 0x3bcb2e664d8f57273201bc888e82d6549f8308a52a9fcd7702b2ea8387f769a9. // // Solidity: event sent(address _destination, uint256 _amount) diff --git a/cmd/devnet/contracts/gen_rootreceiver.go b/cmd/devnet/contracts/gen_rootreceiver.go index f7c12822f37..6c0a817a4e4 100644 --- a/cmd/devnet/contracts/gen_rootreceiver.go +++ b/cmd/devnet/contracts/gen_rootreceiver.go @@ -1,4 +1,4 @@ -// Code generated - DO NOT EDIT. +// Code generated by abigen. DO NOT EDIT. // This file is a generated binding and any manual changes will be lost. package contracts @@ -26,6 +26,8 @@ var ( _ = libcommon.Big1 _ = types.BloomLookup _ = event.NewSubscription + _ = fmt.Errorf + _ = reflect.ValueOf ) // RootReceiverABI is the input ABI used to generate the binding from. @@ -335,15 +337,15 @@ func (_RootReceiver *RootReceiverTransactorSession) ReceiveMessage(inputData []b return _RootReceiver.Contract.ReceiveMessage(&_RootReceiver.TransactOpts, inputData) } -// ReceiveMessageParams is an auto generated read-only Go binding of transcaction calldata params -type ReceiveMessageParams struct { +// RootReceiverReceiveMessageParams is an auto generated read-only Go binding of transcaction calldata params +type RootReceiverReceiveMessageParams struct { Param_inputData []byte } // Parse ReceiveMessage method from calldata of a transaction // // Solidity: function receiveMessage(bytes inputData) returns() -func ParseReceiveMessage(calldata []byte) (*ReceiveMessageParams, error) { +func ParseRootReceiverReceiveMessageParams(calldata []byte) (*RootReceiverReceiveMessageParams, error) { if len(calldata) <= 4 { return nil, fmt.Errorf("invalid calldata input") } @@ -358,7 +360,7 @@ func ParseReceiveMessage(calldata []byte) (*ReceiveMessageParams, error) { return nil, fmt.Errorf("failed to unpack receiveMessage params data: %w", err) } - var paramsResult = new(ReceiveMessageParams) + var paramsResult = new(RootReceiverReceiveMessageParams) value := reflect.ValueOf(paramsResult).Elem() if value.NumField() != len(out) { @@ -367,7 +369,7 @@ func ParseReceiveMessage(calldata []byte) (*ReceiveMessageParams, error) { out0 := *abi.ConvertType(out[0], new([]byte)).(*[]byte) - return &ReceiveMessageParams{ + return &RootReceiverReceiveMessageParams{ Param_inputData: out0, }, nil } @@ -446,6 +448,10 @@ type RootReceiverReceived struct { Raw types.Log // Blockchain specific contextual infos } +func (_RootReceiver *RootReceiverFilterer) ReceivedEventID() libcommon.Hash { + return libcommon.HexToHash("0xf11e547d796cc64acdf758e7cee90439494fd886a19159454aa61e473fdbafef") +} + // FilterReceived is a free log retrieval operation binding the contract event 0xf11e547d796cc64acdf758e7cee90439494fd886a19159454aa61e473fdbafef. // // Solidity: event received(address _source, uint256 _amount) diff --git a/cmd/devnet/contracts/gen_rootsender.go b/cmd/devnet/contracts/gen_rootsender.go index 5aba6c02b1c..3bdd34c1689 100644 --- a/cmd/devnet/contracts/gen_rootsender.go +++ b/cmd/devnet/contracts/gen_rootsender.go @@ -1,4 +1,4 @@ -// Code generated - DO NOT EDIT. +// Code generated by abigen. DO NOT EDIT. // This file is a generated binding and any manual changes will be lost. package contracts @@ -26,6 +26,8 @@ var ( _ = libcommon.Big1 _ = types.BloomLookup _ = event.NewSubscription + _ = fmt.Errorf + _ = reflect.ValueOf ) // RootSenderABI is the input ABI used to generate the binding from. @@ -242,15 +244,15 @@ func (_RootSender *RootSenderTransactorSession) SendToChild(amount *big.Int) (ty return _RootSender.Contract.SendToChild(&_RootSender.TransactOpts, amount) } -// SendToChildParams is an auto generated read-only Go binding of transcaction calldata params -type SendToChildParams struct { +// RootSenderSendToChildParams is an auto generated read-only Go binding of transcaction calldata params +type RootSenderSendToChildParams struct { Param_amount *big.Int } // Parse SendToChild method from calldata of a transaction // // Solidity: function sendToChild(uint256 amount) returns() -func ParseSendToChild(calldata []byte) (*SendToChildParams, error) { +func ParseRootSenderSendToChildParams(calldata []byte) (*RootSenderSendToChildParams, error) { if len(calldata) <= 4 { return nil, fmt.Errorf("invalid calldata input") } @@ -265,7 +267,7 @@ func ParseSendToChild(calldata []byte) (*SendToChildParams, error) { return nil, fmt.Errorf("failed to unpack sendToChild params data: %w", err) } - var paramsResult = new(SendToChildParams) + var paramsResult = new(RootSenderSendToChildParams) value := reflect.ValueOf(paramsResult).Elem() if value.NumField() != len(out) { @@ -274,7 +276,7 @@ func ParseSendToChild(calldata []byte) (*SendToChildParams, error) { out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - return &SendToChildParams{ + return &RootSenderSendToChildParams{ Param_amount: out0, }, nil } diff --git a/cmd/devnet/contracts/gen_testrootchain.go b/cmd/devnet/contracts/gen_testrootchain.go index b9150eb1f50..4ea3688cc20 100644 --- a/cmd/devnet/contracts/gen_testrootchain.go +++ b/cmd/devnet/contracts/gen_testrootchain.go @@ -1,4 +1,4 @@ -// Code generated - DO NOT EDIT. +// Code generated by abigen. DO NOT EDIT. // This file is a generated binding and any manual changes will be lost. package contracts @@ -26,6 +26,8 @@ var ( _ = libcommon.Big1 _ = types.BloomLookup _ = event.NewSubscription + _ = fmt.Errorf + _ = reflect.ValueOf ) // TestRootChainABI is the input ABI used to generate the binding from. @@ -601,15 +603,15 @@ func (_TestRootChain *TestRootChainTransactorSession) UpdateDepositId(numDeposit return _TestRootChain.Contract.UpdateDepositId(&_TestRootChain.TransactOpts, numDeposits) } -// SetHeimdallIdParams is an auto generated read-only Go binding of transcaction calldata params -type SetHeimdallIdParams struct { +// TestRootChainSetHeimdallIdParams is an auto generated read-only Go binding of transcaction calldata params +type TestRootChainSetHeimdallIdParams struct { Param__heimdallId string } // Parse SetHeimdallId method from calldata of a transaction // // Solidity: function setHeimdallId(string _heimdallId) returns() -func ParseSetHeimdallId(calldata []byte) (*SetHeimdallIdParams, error) { +func ParseTestRootChainSetHeimdallIdParams(calldata []byte) (*TestRootChainSetHeimdallIdParams, error) { if len(calldata) <= 4 { return nil, fmt.Errorf("invalid calldata input") } @@ -624,7 +626,7 @@ func ParseSetHeimdallId(calldata []byte) (*SetHeimdallIdParams, error) { return nil, fmt.Errorf("failed to unpack setHeimdallId params data: %w", err) } - var paramsResult = new(SetHeimdallIdParams) + var paramsResult = new(TestRootChainSetHeimdallIdParams) value := reflect.ValueOf(paramsResult).Elem() if value.NumField() != len(out) { @@ -633,20 +635,20 @@ func ParseSetHeimdallId(calldata []byte) (*SetHeimdallIdParams, error) { out0 := *abi.ConvertType(out[0], new(string)).(*string) - return &SetHeimdallIdParams{ + return &TestRootChainSetHeimdallIdParams{ Param__heimdallId: out0, }, nil } -// SetNextHeaderBlockParams is an auto generated read-only Go binding of transcaction calldata params -type SetNextHeaderBlockParams struct { +// TestRootChainSetNextHeaderBlockParams is an auto generated read-only Go binding of transcaction calldata params +type TestRootChainSetNextHeaderBlockParams struct { Param__value *big.Int } // Parse SetNextHeaderBlock method from calldata of a transaction // // Solidity: function setNextHeaderBlock(uint256 _value) returns() -func ParseSetNextHeaderBlock(calldata []byte) (*SetNextHeaderBlockParams, error) { +func ParseTestRootChainSetNextHeaderBlockParams(calldata []byte) (*TestRootChainSetNextHeaderBlockParams, error) { if len(calldata) <= 4 { return nil, fmt.Errorf("invalid calldata input") } @@ -661,7 +663,7 @@ func ParseSetNextHeaderBlock(calldata []byte) (*SetNextHeaderBlockParams, error) return nil, fmt.Errorf("failed to unpack setNextHeaderBlock params data: %w", err) } - var paramsResult = new(SetNextHeaderBlockParams) + var paramsResult = new(TestRootChainSetNextHeaderBlockParams) value := reflect.ValueOf(paramsResult).Elem() if value.NumField() != len(out) { @@ -670,13 +672,13 @@ func ParseSetNextHeaderBlock(calldata []byte) (*SetNextHeaderBlockParams, error) out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - return &SetNextHeaderBlockParams{ + return &TestRootChainSetNextHeaderBlockParams{ Param__value: out0, }, nil } -// SubmitCheckpointParams is an auto generated read-only Go binding of transcaction calldata params -type SubmitCheckpointParams struct { +// TestRootChainSubmitCheckpointParams is an auto generated read-only Go binding of transcaction calldata params +type TestRootChainSubmitCheckpointParams struct { Param_data []byte Param_arg1 [][3]*big.Int } @@ -684,7 +686,7 @@ type SubmitCheckpointParams struct { // Parse SubmitCheckpoint method from calldata of a transaction // // Solidity: function submitCheckpoint(bytes data, uint256[3][] ) returns() -func ParseSubmitCheckpoint(calldata []byte) (*SubmitCheckpointParams, error) { +func ParseTestRootChainSubmitCheckpointParams(calldata []byte) (*TestRootChainSubmitCheckpointParams, error) { if len(calldata) <= 4 { return nil, fmt.Errorf("invalid calldata input") } @@ -699,7 +701,7 @@ func ParseSubmitCheckpoint(calldata []byte) (*SubmitCheckpointParams, error) { return nil, fmt.Errorf("failed to unpack submitCheckpoint params data: %w", err) } - var paramsResult = new(SubmitCheckpointParams) + var paramsResult = new(TestRootChainSubmitCheckpointParams) value := reflect.ValueOf(paramsResult).Elem() if value.NumField() != len(out) { @@ -709,20 +711,20 @@ func ParseSubmitCheckpoint(calldata []byte) (*SubmitCheckpointParams, error) { out0 := *abi.ConvertType(out[0], new([]byte)).(*[]byte) out1 := *abi.ConvertType(out[1], new([][3]*big.Int)).(*[][3]*big.Int) - return &SubmitCheckpointParams{ + return &TestRootChainSubmitCheckpointParams{ Param_data: out0, Param_arg1: out1, }, nil } -// UpdateDepositIdParams is an auto generated read-only Go binding of transcaction calldata params -type UpdateDepositIdParams struct { +// TestRootChainUpdateDepositIdParams is an auto generated read-only Go binding of transcaction calldata params +type TestRootChainUpdateDepositIdParams struct { Param_numDeposits *big.Int } // Parse UpdateDepositId method from calldata of a transaction // // Solidity: function updateDepositId(uint256 numDeposits) returns(uint256 depositId) -func ParseUpdateDepositId(calldata []byte) (*UpdateDepositIdParams, error) { +func ParseTestRootChainUpdateDepositIdParams(calldata []byte) (*TestRootChainUpdateDepositIdParams, error) { if len(calldata) <= 4 { return nil, fmt.Errorf("invalid calldata input") } @@ -737,7 +739,7 @@ func ParseUpdateDepositId(calldata []byte) (*UpdateDepositIdParams, error) { return nil, fmt.Errorf("failed to unpack updateDepositId params data: %w", err) } - var paramsResult = new(UpdateDepositIdParams) + var paramsResult = new(TestRootChainUpdateDepositIdParams) value := reflect.ValueOf(paramsResult).Elem() if value.NumField() != len(out) { @@ -746,7 +748,7 @@ func ParseUpdateDepositId(calldata []byte) (*UpdateDepositIdParams, error) { out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - return &UpdateDepositIdParams{ + return &TestRootChainUpdateDepositIdParams{ Param_numDeposits: out0, }, nil } @@ -829,6 +831,10 @@ type TestRootChainNewHeaderBlock struct { Raw types.Log // Blockchain specific contextual infos } +func (_TestRootChain *TestRootChainFilterer) NewHeaderBlockEventID() libcommon.Hash { + return libcommon.HexToHash("0xba5de06d22af2685c6c7765f60067f7d2b08c2d29f53cdf14d67f6d1c9bfb527") +} + // FilterNewHeaderBlock is a free log retrieval operation binding the contract event 0xba5de06d22af2685c6c7765f60067f7d2b08c2d29f53cdf14d67f6d1c9bfb527. // // Solidity: event NewHeaderBlock(address indexed proposer, uint256 indexed headerBlockId, uint256 indexed reward, uint256 start, uint256 end, bytes32 root) @@ -990,6 +996,10 @@ type TestRootChainResetHeaderBlock struct { Raw types.Log // Blockchain specific contextual infos } +func (_TestRootChain *TestRootChainFilterer) ResetHeaderBlockEventID() libcommon.Hash { + return libcommon.HexToHash("0xca1d8316287f938830e225956a7bb10fd5a1a1506dd2eb3a476751a488117205") +} + // FilterResetHeaderBlock is a free log retrieval operation binding the contract event 0xca1d8316287f938830e225956a7bb10fd5a1a1506dd2eb3a476751a488117205. // // Solidity: event ResetHeaderBlock(address indexed proposer, uint256 indexed headerBlockId) diff --git a/cmd/devnet/contracts/gen_teststatesender.go b/cmd/devnet/contracts/gen_teststatesender.go index eb18a91b283..b64c9971c6c 100644 --- a/cmd/devnet/contracts/gen_teststatesender.go +++ b/cmd/devnet/contracts/gen_teststatesender.go @@ -1,4 +1,4 @@ -// Code generated - DO NOT EDIT. +// Code generated by abigen. DO NOT EDIT. // This file is a generated binding and any manual changes will be lost. package contracts @@ -26,6 +26,8 @@ var ( _ = libcommon.Big1 _ = types.BloomLookup _ = event.NewSubscription + _ = fmt.Errorf + _ = reflect.ValueOf ) // TestStateSenderABI is the input ABI used to generate the binding from. @@ -294,8 +296,8 @@ func (_TestStateSender *TestStateSenderTransactorSession) SyncState(receiver lib return _TestStateSender.Contract.SyncState(&_TestStateSender.TransactOpts, receiver, data) } -// RegisterParams is an auto generated read-only Go binding of transcaction calldata params -type RegisterParams struct { +// TestStateSenderRegisterParams is an auto generated read-only Go binding of transcaction calldata params +type TestStateSenderRegisterParams struct { Param_sender libcommon.Address Param_receiver libcommon.Address } @@ -303,7 +305,7 @@ type RegisterParams struct { // Parse Register method from calldata of a transaction // // Solidity: function register(address sender, address receiver) returns() -func ParseRegister(calldata []byte) (*RegisterParams, error) { +func ParseTestStateSenderRegisterParams(calldata []byte) (*TestStateSenderRegisterParams, error) { if len(calldata) <= 4 { return nil, fmt.Errorf("invalid calldata input") } @@ -318,7 +320,7 @@ func ParseRegister(calldata []byte) (*RegisterParams, error) { return nil, fmt.Errorf("failed to unpack register params data: %w", err) } - var paramsResult = new(RegisterParams) + var paramsResult = new(TestStateSenderRegisterParams) value := reflect.ValueOf(paramsResult).Elem() if value.NumField() != len(out) { @@ -328,13 +330,13 @@ func ParseRegister(calldata []byte) (*RegisterParams, error) { out0 := *abi.ConvertType(out[0], new(libcommon.Address)).(*libcommon.Address) out1 := *abi.ConvertType(out[1], new(libcommon.Address)).(*libcommon.Address) - return &RegisterParams{ + return &TestStateSenderRegisterParams{ Param_sender: out0, Param_receiver: out1, }, nil } -// SyncStateParams is an auto generated read-only Go binding of transcaction calldata params -type SyncStateParams struct { +// TestStateSenderSyncStateParams is an auto generated read-only Go binding of transcaction calldata params +type TestStateSenderSyncStateParams struct { Param_receiver libcommon.Address Param_data []byte } @@ -342,7 +344,7 @@ type SyncStateParams struct { // Parse SyncState method from calldata of a transaction // // Solidity: function syncState(address receiver, bytes data) returns() -func ParseSyncState(calldata []byte) (*SyncStateParams, error) { +func ParseTestStateSenderSyncStateParams(calldata []byte) (*TestStateSenderSyncStateParams, error) { if len(calldata) <= 4 { return nil, fmt.Errorf("invalid calldata input") } @@ -357,7 +359,7 @@ func ParseSyncState(calldata []byte) (*SyncStateParams, error) { return nil, fmt.Errorf("failed to unpack syncState params data: %w", err) } - var paramsResult = new(SyncStateParams) + var paramsResult = new(TestStateSenderSyncStateParams) value := reflect.ValueOf(paramsResult).Elem() if value.NumField() != len(out) { @@ -367,7 +369,7 @@ func ParseSyncState(calldata []byte) (*SyncStateParams, error) { out0 := *abi.ConvertType(out[0], new(libcommon.Address)).(*libcommon.Address) out1 := *abi.ConvertType(out[1], new([]byte)).(*[]byte) - return &SyncStateParams{ + return &TestStateSenderSyncStateParams{ Param_receiver: out0, Param_data: out1, }, nil } @@ -447,6 +449,10 @@ type TestStateSenderNewRegistration struct { Raw types.Log // Blockchain specific contextual infos } +func (_TestStateSender *TestStateSenderFilterer) NewRegistrationEventID() libcommon.Hash { + return libcommon.HexToHash("0x3f4512aacd7a664fdb321a48e8340120d63253a91c6367a143abd19ecf68aedd") +} + // FilterNewRegistration is a free log retrieval operation binding the contract event 0x3f4512aacd7a664fdb321a48e8340120d63253a91c6367a143abd19ecf68aedd. // // Solidity: event NewRegistration(address indexed user, address indexed sender, address indexed receiver) @@ -609,6 +615,10 @@ type TestStateSenderRegistrationUpdated struct { Raw types.Log // Blockchain specific contextual infos } +func (_TestStateSender *TestStateSenderFilterer) RegistrationUpdatedEventID() libcommon.Hash { + return libcommon.HexToHash("0xc51cb1a93ec91e927852b3445875ec77b148271953e5c0b43698c968ad6fc47d") +} + // FilterRegistrationUpdated is a free log retrieval operation binding the contract event 0xc51cb1a93ec91e927852b3445875ec77b148271953e5c0b43698c968ad6fc47d. // // Solidity: event RegistrationUpdated(address indexed user, address indexed sender, address indexed receiver) @@ -771,6 +781,10 @@ type TestStateSenderStateSynced struct { Raw types.Log // Blockchain specific contextual infos } +func (_TestStateSender *TestStateSenderFilterer) StateSyncedEventID() libcommon.Hash { + return libcommon.HexToHash("0x103fed9db65eac19c4d870f49ab7520fe03b99f1838e5996caf47e9e43308392") +} + // FilterStateSynced is a free log retrieval operation binding the contract event 0x103fed9db65eac19c4d870f49ab7520fe03b99f1838e5996caf47e9e43308392. // // Solidity: event StateSynced(uint256 indexed id, address indexed contractAddress, bytes data) diff --git a/cmd/evm/internal/t8ntool/gen_stenv.go b/cmd/evm/internal/t8ntool/gen_stenv.go index c47122401a6..a7dc4fc02ab 100644 --- a/cmd/evm/internal/t8ntool/gen_stenv.go +++ b/cmd/evm/internal/t8ntool/gen_stenv.go @@ -9,7 +9,6 @@ import ( "github.com/erigontech/erigon-lib/common" "github.com/erigontech/erigon-lib/common/math" - common0 "github.com/erigontech/erigon-lib/common" "github.com/erigontech/erigon/core/types" ) @@ -18,7 +17,7 @@ var _ = (*stEnvMarshaling)(nil) // MarshalJSON marshals as JSON. func (s stEnv) MarshalJSON() ([]byte, error) { type stEnv struct { - Coinbase common0.UnprefixedAddress `json:"currentCoinbase" gencodec:"required"` + Coinbase common.UnprefixedAddress `json:"currentCoinbase" gencodec:"required"` Difficulty *math.HexOrDecimal256 `json:"currentDifficulty"` Random *math.HexOrDecimal256 `json:"currentRandom"` MixDigest common.Hash `json:"mixHash,omitempty"` @@ -37,7 +36,7 @@ func (s stEnv) MarshalJSON() ([]byte, error) { RequestsHash *common.Hash `json:"requestsHash,omitempty"` } var enc stEnv - enc.Coinbase = common0.UnprefixedAddress(s.Coinbase) + enc.Coinbase = common.UnprefixedAddress(s.Coinbase) enc.Difficulty = (*math.HexOrDecimal256)(s.Difficulty) enc.Random = (*math.HexOrDecimal256)(s.Random) enc.MixDigest = s.MixDigest @@ -60,7 +59,7 @@ func (s stEnv) MarshalJSON() ([]byte, error) { // UnmarshalJSON unmarshals from JSON. func (s *stEnv) UnmarshalJSON(input []byte) error { type stEnv struct { - Coinbase *common0.UnprefixedAddress `json:"currentCoinbase" gencodec:"required"` + Coinbase *common.UnprefixedAddress `json:"currentCoinbase" gencodec:"required"` Difficulty *math.HexOrDecimal256 `json:"currentDifficulty"` Random *math.HexOrDecimal256 `json:"currentRandom"` MixDigest *common.Hash `json:"mixHash,omitempty"` diff --git a/cmd/pics/contracts/gen_token.go b/cmd/pics/contracts/gen_token.go index 124fcb5f587..e12ee0af782 100644 --- a/cmd/pics/contracts/gen_token.go +++ b/cmd/pics/contracts/gen_token.go @@ -1,18 +1,18 @@ -// Code generated - DO NOT EDIT. +// Code generated by abigen. DO NOT EDIT. // This file is a generated binding and any manual changes will be lost. package contracts import ( + "fmt" "math/big" + "reflect" "strings" - libcommon "github.com/erigontech/erigon-lib/common" - ethereum "github.com/erigontech/erigon" + libcommon "github.com/erigontech/erigon-lib/common" "github.com/erigontech/erigon/accounts/abi" "github.com/erigontech/erigon/accounts/abi/bind" - "github.com/erigontech/erigon-lib/common" "github.com/erigontech/erigon/core/types" "github.com/erigontech/erigon/event" ) @@ -26,6 +26,8 @@ var ( _ = libcommon.Big1 _ = types.BloomLookup _ = event.NewSubscription + _ = fmt.Errorf + _ = reflect.ValueOf ) // TokenABI is the input ABI used to generate the binding from. @@ -41,7 +43,7 @@ func DeployToken(auth *bind.TransactOpts, backend bind.ContractBackend, _minter return libcommon.Address{}, nil, nil, err } - address, tx, contract, err := bind.DeployContract(auth, parsed, common.FromHex(TokenBin), backend, _minter) + address, tx, contract, err := bind.DeployContract(auth, parsed, libcommon.FromHex(TokenBin), backend, _minter) if err != nil { return libcommon.Address{}, nil, nil, err } @@ -324,3 +326,81 @@ func (_Token *TokenSession) Transfer(_to libcommon.Address, _value *big.Int) (ty func (_Token *TokenTransactorSession) Transfer(_to libcommon.Address, _value *big.Int) (types.Transaction, error) { return _Token.Contract.Transfer(&_Token.TransactOpts, _to, _value) } + +// TokenMintParams is an auto generated read-only Go binding of transcaction calldata params +type TokenMintParams struct { + Param__to libcommon.Address + Param__value *big.Int +} + +// Parse Mint method from calldata of a transaction +// +// Solidity: function mint(address _to, uint256 _value) returns(bool) +func ParseTokenMintParams(calldata []byte) (*TokenMintParams, error) { + if len(calldata) <= 4 { + return nil, fmt.Errorf("invalid calldata input") + } + + _abi, err := abi.JSON(strings.NewReader(TokenABI)) + if err != nil { + return nil, fmt.Errorf("failed to get abi of registry metadata: %w", err) + } + + out, err := _abi.Methods["mint"].Inputs.Unpack(calldata[4:]) + if err != nil { + return nil, fmt.Errorf("failed to unpack mint params data: %w", err) + } + + var paramsResult = new(TokenMintParams) + value := reflect.ValueOf(paramsResult).Elem() + + if value.NumField() != len(out) { + return nil, fmt.Errorf("failed to match calldata with param field number") + } + + out0 := *abi.ConvertType(out[0], new(libcommon.Address)).(*libcommon.Address) + out1 := *abi.ConvertType(out[1], new(*big.Int)).(**big.Int) + + return &TokenMintParams{ + Param__to: out0, Param__value: out1, + }, nil +} + +// TokenTransferParams is an auto generated read-only Go binding of transcaction calldata params +type TokenTransferParams struct { + Param__to libcommon.Address + Param__value *big.Int +} + +// Parse Transfer method from calldata of a transaction +// +// Solidity: function transfer(address _to, uint256 _value) returns(bool) +func ParseTokenTransferParams(calldata []byte) (*TokenTransferParams, error) { + if len(calldata) <= 4 { + return nil, fmt.Errorf("invalid calldata input") + } + + _abi, err := abi.JSON(strings.NewReader(TokenABI)) + if err != nil { + return nil, fmt.Errorf("failed to get abi of registry metadata: %w", err) + } + + out, err := _abi.Methods["transfer"].Inputs.Unpack(calldata[4:]) + if err != nil { + return nil, fmt.Errorf("failed to unpack transfer params data: %w", err) + } + + var paramsResult = new(TokenTransferParams) + value := reflect.ValueOf(paramsResult).Elem() + + if value.NumField() != len(out) { + return nil, fmt.Errorf("failed to match calldata with param field number") + } + + out0 := *abi.ConvertType(out[0], new(libcommon.Address)).(*libcommon.Address) + out1 := *abi.ConvertType(out[1], new(*big.Int)).(**big.Int) + + return &TokenTransferParams{ + Param__to: out0, Param__value: out1, + }, nil +} diff --git a/consensus/aura/auraabi/gen_block_reward.go b/consensus/aura/auraabi/gen_block_reward.go index 0b1918fd00c..48b3e61129e 100644 --- a/consensus/aura/auraabi/gen_block_reward.go +++ b/consensus/aura/auraabi/gen_block_reward.go @@ -1,14 +1,13 @@ -// Code generated - DO NOT EDIT. +// Code generated by abigen. DO NOT EDIT. // This file is a generated binding and any manual changes will be lost. package auraabi import ( - "math/big" - "strings" - "fmt" + "math/big" "reflect" + "strings" ethereum "github.com/erigontech/erigon" libcommon "github.com/erigontech/erigon-lib/common" @@ -27,6 +26,8 @@ var ( _ = libcommon.Big1 _ = types.BloomLookup _ = event.NewSubscription + _ = fmt.Errorf + _ = reflect.ValueOf ) // BlockRewardABI is the input ABI used to generate the binding from. @@ -195,8 +196,8 @@ func (_BlockReward *BlockRewardTransactorSession) Reward(benefactors []libcommon return _BlockReward.Contract.Reward(&_BlockReward.TransactOpts, benefactors, kind) } -// RewardParams is an auto generated read-only Go binding of transcaction calldata params -type RewardParams struct { +// BlockRewardRewardParams is an auto generated read-only Go binding of transcaction calldata params +type BlockRewardRewardParams struct { Param_benefactors []libcommon.Address Param_kind []uint16 } @@ -204,7 +205,7 @@ type RewardParams struct { // Parse Reward method from calldata of a transaction // // Solidity: function reward(address[] benefactors, uint16[] kind) returns(address[], uint256[]) -func ParseReward(calldata []byte) (*RewardParams, error) { +func ParseBlockRewardRewardParams(calldata []byte) (*BlockRewardRewardParams, error) { if len(calldata) <= 4 { return nil, fmt.Errorf("invalid calldata input") } @@ -219,7 +220,7 @@ func ParseReward(calldata []byte) (*RewardParams, error) { return nil, fmt.Errorf("failed to unpack reward params data: %w", err) } - var paramsResult = new(RewardParams) + var paramsResult = new(BlockRewardRewardParams) value := reflect.ValueOf(paramsResult).Elem() if value.NumField() != len(out) { @@ -229,7 +230,7 @@ func ParseReward(calldata []byte) (*RewardParams, error) { out0 := *abi.ConvertType(out[0], new([]libcommon.Address)).(*[]libcommon.Address) out1 := *abi.ConvertType(out[1], new([]uint16)).(*[]uint16) - return &RewardParams{ + return &BlockRewardRewardParams{ Param_benefactors: out0, Param_kind: out1, }, nil } diff --git a/consensus/aura/auraabi/gen_validator_set.go b/consensus/aura/auraabi/gen_validator_set.go index 4e73d18f816..42fdbacb6f5 100644 --- a/consensus/aura/auraabi/gen_validator_set.go +++ b/consensus/aura/auraabi/gen_validator_set.go @@ -1,10 +1,12 @@ -// Code generated - DO NOT EDIT. +// Code generated by abigen. DO NOT EDIT. // This file is a generated binding and any manual changes will be lost. package auraabi import ( + "fmt" "math/big" + "reflect" "strings" ethereum "github.com/erigontech/erigon" @@ -24,6 +26,8 @@ var ( _ = libcommon.Big1 _ = types.BloomLookup _ = event.NewSubscription + _ = fmt.Errorf + _ = reflect.ValueOf ) // ValidatorSetABI is the input ABI used to generate the binding from. @@ -380,6 +384,10 @@ type ValidatorSetInitiateChange struct { Raw types.Log // Blockchain specific contextual infos } +func (_ValidatorSet *ValidatorSetFilterer) InitiateChangeEventID() libcommon.Hash { + return libcommon.HexToHash("0x55252fa6eee4741b4e24a74a70e9c11fd2c2281df8d6ea13126ff845f7825c89") +} + // FilterInitiateChange is a free log retrieval operation binding the contract event 0x55252fa6eee4741b4e24a74a70e9c11fd2c2281df8d6ea13126ff845f7825c89. // // Solidity: event InitiateChange(bytes32 indexed _parent_hash, address[] _new_set) diff --git a/core/state/contracts/gen.go b/core/state/contracts/gen.go index a8acdf7cd65..059acc37f11 100644 --- a/core/state/contracts/gen.go +++ b/core/state/contracts/gen.go @@ -31,3 +31,8 @@ package contracts // poly.sol //go:generate solc --allow-paths ., --abi --bin --overwrite --optimize -o build poly.sol //go:generate abigen -abi build/Poly.abi -bin build/Poly.bin -pkg contracts -type poly -out ./gen_poly.go + +// revive2.sol +//go:generate solc --allow-paths ., --abi --bin --overwrite --optimize -o build revive2.sol +//go:generate abigen -abi build/Revive2.abi -bin build/Revive2.bin -pkg contracts -type revive2 -out ./gen_revive2.go +//go:generate abigen -abi build/Phoenix.abi -bin build/Phoenix.bin -pkg contracts -type phoenix -out ./gen_phoenix.go diff --git a/core/state/contracts/gen_changer.go b/core/state/contracts/gen_changer.go index 26e66ba0adc..a33f61616cd 100644 --- a/core/state/contracts/gen_changer.go +++ b/core/state/contracts/gen_changer.go @@ -1,18 +1,18 @@ -// Code generated - DO NOT EDIT. +// Code generated by abigen. DO NOT EDIT. // This file is a generated binding and any manual changes will be lost. package contracts import ( + "fmt" "math/big" + "reflect" "strings" - libcommon "github.com/erigontech/erigon-lib/common" - ethereum "github.com/erigontech/erigon" + libcommon "github.com/erigontech/erigon-lib/common" "github.com/erigontech/erigon/accounts/abi" "github.com/erigontech/erigon/accounts/abi/bind" - "github.com/erigontech/erigon-lib/common" "github.com/erigontech/erigon/core/types" "github.com/erigontech/erigon/event" ) @@ -26,6 +26,8 @@ var ( _ = libcommon.Big1 _ = types.BloomLookup _ = event.NewSubscription + _ = fmt.Errorf + _ = reflect.ValueOf ) // ChangerABI is the input ABI used to generate the binding from. @@ -41,7 +43,7 @@ func DeployChanger(auth *bind.TransactOpts, backend bind.ContractBackend) (libco return libcommon.Address{}, nil, nil, err } - address, tx, contract, err := bind.DeployContract(auth, parsed, common.FromHex(ChangerBin), backend) + address, tx, contract, err := bind.DeployContract(auth, parsed, libcommon.FromHex(ChangerBin), backend) if err != nil { return libcommon.Address{}, nil, nil, err } diff --git a/core/state/contracts/gen_phoenix.go b/core/state/contracts/gen_phoenix.go index 9ba545f3357..91265f207d6 100644 --- a/core/state/contracts/gen_phoenix.go +++ b/core/state/contracts/gen_phoenix.go @@ -1,18 +1,18 @@ -// Code generated - DO NOT EDIT. +// Code generated by abigen. DO NOT EDIT. // This file is a generated binding and any manual changes will be lost. package contracts import ( + "fmt" "math/big" + "reflect" "strings" - libcommon "github.com/erigontech/erigon-lib/common" - ethereum "github.com/erigontech/erigon" + libcommon "github.com/erigontech/erigon-lib/common" "github.com/erigontech/erigon/accounts/abi" "github.com/erigontech/erigon/accounts/abi/bind" - "github.com/erigontech/erigon-lib/common" "github.com/erigontech/erigon/core/types" "github.com/erigontech/erigon/event" ) @@ -26,6 +26,8 @@ var ( _ = libcommon.Big1 _ = types.BloomLookup _ = event.NewSubscription + _ = fmt.Errorf + _ = reflect.ValueOf ) // PhoenixABI is the input ABI used to generate the binding from. @@ -41,7 +43,7 @@ func DeployPhoenix(auth *bind.TransactOpts, backend bind.ContractBackend) (libco return libcommon.Address{}, nil, nil, err } - address, tx, contract, err := bind.DeployContract(auth, parsed, common.FromHex(PhoenixBin), backend) + address, tx, contract, err := bind.DeployContract(auth, parsed, libcommon.FromHex(PhoenixBin), backend) if err != nil { return libcommon.Address{}, nil, nil, err } diff --git a/core/state/contracts/gen_poly.go b/core/state/contracts/gen_poly.go index d19fabe2014..a1e16977c3a 100644 --- a/core/state/contracts/gen_poly.go +++ b/core/state/contracts/gen_poly.go @@ -1,18 +1,18 @@ -// Code generated - DO NOT EDIT. +// Code generated by abigen. DO NOT EDIT. // This file is a generated binding and any manual changes will be lost. package contracts import ( + "fmt" "math/big" + "reflect" "strings" - libcommon "github.com/erigontech/erigon-lib/common" - ethereum "github.com/erigontech/erigon" + libcommon "github.com/erigontech/erigon-lib/common" "github.com/erigontech/erigon/accounts/abi" "github.com/erigontech/erigon/accounts/abi/bind" - "github.com/erigontech/erigon-lib/common" "github.com/erigontech/erigon/core/types" "github.com/erigontech/erigon/event" ) @@ -26,6 +26,8 @@ var ( _ = libcommon.Big1 _ = types.BloomLookup _ = event.NewSubscription + _ = fmt.Errorf + _ = reflect.ValueOf ) // PolyABI is the input ABI used to generate the binding from. @@ -41,7 +43,7 @@ func DeployPoly(auth *bind.TransactOpts, backend bind.ContractBackend) (libcommo return libcommon.Address{}, nil, nil, err } - address, tx, contract, err := bind.DeployContract(auth, parsed, common.FromHex(PolyBin), backend) + address, tx, contract, err := bind.DeployContract(auth, parsed, libcommon.FromHex(PolyBin), backend) if err != nil { return libcommon.Address{}, nil, nil, err } @@ -211,6 +213,43 @@ func (_Poly *PolyTransactorSession) Deploy(salt *big.Int) (types.Transaction, er return _Poly.Contract.Deploy(&_Poly.TransactOpts, salt) } +// PolyDeployParams is an auto generated read-only Go binding of transcaction calldata params +type PolyDeployParams struct { + Param_salt *big.Int +} + +// Parse Deploy method from calldata of a transaction +// +// Solidity: function deploy(uint256 salt) returns() +func ParsePolyDeployParams(calldata []byte) (*PolyDeployParams, error) { + if len(calldata) <= 4 { + return nil, fmt.Errorf("invalid calldata input") + } + + _abi, err := abi.JSON(strings.NewReader(PolyABI)) + if err != nil { + return nil, fmt.Errorf("failed to get abi of registry metadata: %w", err) + } + + out, err := _abi.Methods["deploy"].Inputs.Unpack(calldata[4:]) + if err != nil { + return nil, fmt.Errorf("failed to unpack deploy params data: %w", err) + } + + var paramsResult = new(PolyDeployParams) + value := reflect.ValueOf(paramsResult).Elem() + + if value.NumField() != len(out) { + return nil, fmt.Errorf("failed to match calldata with param field number") + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return &PolyDeployParams{ + Param_salt: out0, + }, nil +} + // PolyDeployEventIterator is returned from FilterDeployEvent and is used to iterate over the raw logs and unpacked data for DeployEvent events raised by the Poly contract. type PolyDeployEventIterator struct { Event *PolyDeployEvent // Event containing the contract specifics and raw log @@ -284,6 +323,10 @@ type PolyDeployEvent struct { Raw types.Log // Blockchain specific contextual infos } +func (_Poly *PolyFilterer) DeployEventEventID() libcommon.Hash { + return libcommon.HexToHash("0x68f6a0f063c25c6678c443b9a484086f15ba8f91f60218695d32a5251f2050eb") +} + // FilterDeployEvent is a free log retrieval operation binding the contract event 0x68f6a0f063c25c6678c443b9a484086f15ba8f91f60218695d32a5251f2050eb. // // Solidity: event DeployEvent(address d) @@ -341,5 +384,6 @@ func (_Poly *PolyFilterer) ParseDeployEvent(log types.Log) (*PolyDeployEvent, er if err := _Poly.contract.UnpackLog(event, "DeployEvent", log); err != nil { return nil, err } + event.Raw = log return event, nil } diff --git a/core/state/contracts/gen_revive.go b/core/state/contracts/gen_revive.go index af48b7bf9c6..3ff550781d0 100644 --- a/core/state/contracts/gen_revive.go +++ b/core/state/contracts/gen_revive.go @@ -1,18 +1,18 @@ -// Code generated - DO NOT EDIT. +// Code generated by abigen. DO NOT EDIT. // This file is a generated binding and any manual changes will be lost. package contracts import ( + "fmt" "math/big" + "reflect" "strings" - libcommon "github.com/erigontech/erigon-lib/common" - ethereum "github.com/erigontech/erigon" + libcommon "github.com/erigontech/erigon-lib/common" "github.com/erigontech/erigon/accounts/abi" "github.com/erigontech/erigon/accounts/abi/bind" - "github.com/erigontech/erigon-lib/common" "github.com/erigontech/erigon/core/types" "github.com/erigontech/erigon/event" ) @@ -26,6 +26,8 @@ var ( _ = libcommon.Big1 _ = types.BloomLookup _ = event.NewSubscription + _ = fmt.Errorf + _ = reflect.ValueOf ) // ReviveABI is the input ABI used to generate the binding from. @@ -41,7 +43,7 @@ func DeployRevive(auth *bind.TransactOpts, backend bind.ContractBackend) (libcom return libcommon.Address{}, nil, nil, err } - address, tx, contract, err := bind.DeployContract(auth, parsed, common.FromHex(ReviveBin), backend) + address, tx, contract, err := bind.DeployContract(auth, parsed, libcommon.FromHex(ReviveBin), backend) if err != nil { return libcommon.Address{}, nil, nil, err } @@ -211,6 +213,43 @@ func (_Revive *ReviveTransactorSession) Deploy(salt *big.Int) (types.Transaction return _Revive.Contract.Deploy(&_Revive.TransactOpts, salt) } +// ReviveDeployParams is an auto generated read-only Go binding of transcaction calldata params +type ReviveDeployParams struct { + Param_salt *big.Int +} + +// Parse Deploy method from calldata of a transaction +// +// Solidity: function deploy(uint256 salt) returns() +func ParseReviveDeployParams(calldata []byte) (*ReviveDeployParams, error) { + if len(calldata) <= 4 { + return nil, fmt.Errorf("invalid calldata input") + } + + _abi, err := abi.JSON(strings.NewReader(ReviveABI)) + if err != nil { + return nil, fmt.Errorf("failed to get abi of registry metadata: %w", err) + } + + out, err := _abi.Methods["deploy"].Inputs.Unpack(calldata[4:]) + if err != nil { + return nil, fmt.Errorf("failed to unpack deploy params data: %w", err) + } + + var paramsResult = new(ReviveDeployParams) + value := reflect.ValueOf(paramsResult).Elem() + + if value.NumField() != len(out) { + return nil, fmt.Errorf("failed to match calldata with param field number") + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return &ReviveDeployParams{ + Param_salt: out0, + }, nil +} + // ReviveDeployEventIterator is returned from FilterDeployEvent and is used to iterate over the raw logs and unpacked data for DeployEvent events raised by the Revive contract. type ReviveDeployEventIterator struct { Event *ReviveDeployEvent // Event containing the contract specifics and raw log @@ -284,6 +323,10 @@ type ReviveDeployEvent struct { Raw types.Log // Blockchain specific contextual infos } +func (_Revive *ReviveFilterer) DeployEventEventID() libcommon.Hash { + return libcommon.HexToHash("0x68f6a0f063c25c6678c443b9a484086f15ba8f91f60218695d32a5251f2050eb") +} + // FilterDeployEvent is a free log retrieval operation binding the contract event 0x68f6a0f063c25c6678c443b9a484086f15ba8f91f60218695d32a5251f2050eb. // // Solidity: event DeployEvent(address d) @@ -341,5 +384,6 @@ func (_Revive *ReviveFilterer) ParseDeployEvent(log types.Log) (*ReviveDeployEve if err := _Revive.contract.UnpackLog(event, "DeployEvent", log); err != nil { return nil, err } + event.Raw = log return event, nil } diff --git a/core/state/contracts/gen_revive2.go b/core/state/contracts/gen_revive2.go index 588bba45b9b..f3f880f2dd4 100644 --- a/core/state/contracts/gen_revive2.go +++ b/core/state/contracts/gen_revive2.go @@ -1,18 +1,18 @@ -// Code generated - DO NOT EDIT. +// Code generated by abigen. DO NOT EDIT. // This file is a generated binding and any manual changes will be lost. package contracts import ( + "fmt" "math/big" + "reflect" "strings" - libcommon "github.com/erigontech/erigon-lib/common" - ethereum "github.com/erigontech/erigon" + libcommon "github.com/erigontech/erigon-lib/common" "github.com/erigontech/erigon/accounts/abi" "github.com/erigontech/erigon/accounts/abi/bind" - "github.com/erigontech/erigon-lib/common" "github.com/erigontech/erigon/core/types" "github.com/erigontech/erigon/event" ) @@ -26,6 +26,8 @@ var ( _ = libcommon.Big1 _ = types.BloomLookup _ = event.NewSubscription + _ = fmt.Errorf + _ = reflect.ValueOf ) // Revive2ABI is the input ABI used to generate the binding from. @@ -41,7 +43,7 @@ func DeployRevive2(auth *bind.TransactOpts, backend bind.ContractBackend) (libco return libcommon.Address{}, nil, nil, err } - address, tx, contract, err := bind.DeployContract(auth, parsed, common.FromHex(Revive2Bin), backend) + address, tx, contract, err := bind.DeployContract(auth, parsed, libcommon.FromHex(Revive2Bin), backend) if err != nil { return libcommon.Address{}, nil, nil, err } @@ -211,6 +213,43 @@ func (_Revive2 *Revive2TransactorSession) Deploy(salt [32]byte) (types.Transacti return _Revive2.Contract.Deploy(&_Revive2.TransactOpts, salt) } +// Revive2DeployParams is an auto generated read-only Go binding of transcaction calldata params +type Revive2DeployParams struct { + Param_salt [32]byte +} + +// Parse Deploy method from calldata of a transaction +// +// Solidity: function deploy(bytes32 salt) returns() +func ParseRevive2DeployParams(calldata []byte) (*Revive2DeployParams, error) { + if len(calldata) <= 4 { + return nil, fmt.Errorf("invalid calldata input") + } + + _abi, err := abi.JSON(strings.NewReader(Revive2ABI)) + if err != nil { + return nil, fmt.Errorf("failed to get abi of registry metadata: %w", err) + } + + out, err := _abi.Methods["deploy"].Inputs.Unpack(calldata[4:]) + if err != nil { + return nil, fmt.Errorf("failed to unpack deploy params data: %w", err) + } + + var paramsResult = new(Revive2DeployParams) + value := reflect.ValueOf(paramsResult).Elem() + + if value.NumField() != len(out) { + return nil, fmt.Errorf("failed to match calldata with param field number") + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return &Revive2DeployParams{ + Param_salt: out0, + }, nil +} + // Revive2DeployEventIterator is returned from FilterDeployEvent and is used to iterate over the raw logs and unpacked data for DeployEvent events raised by the Revive2 contract. type Revive2DeployEventIterator struct { Event *Revive2DeployEvent // Event containing the contract specifics and raw log @@ -284,6 +323,10 @@ type Revive2DeployEvent struct { Raw types.Log // Blockchain specific contextual infos } +func (_Revive2 *Revive2Filterer) DeployEventEventID() libcommon.Hash { + return libcommon.HexToHash("0x68f6a0f063c25c6678c443b9a484086f15ba8f91f60218695d32a5251f2050eb") +} + // FilterDeployEvent is a free log retrieval operation binding the contract event 0x68f6a0f063c25c6678c443b9a484086f15ba8f91f60218695d32a5251f2050eb. // // Solidity: event DeployEvent(address d) @@ -341,5 +384,6 @@ func (_Revive2 *Revive2Filterer) ParseDeployEvent(log types.Log) (*Revive2Deploy if err := _Revive2.contract.UnpackLog(event, "DeployEvent", log); err != nil { return nil, err } + event.Raw = log return event, nil } diff --git a/core/state/contracts/gen_selfdestruct.go b/core/state/contracts/gen_selfdestruct.go index cea4977b7d9..92178b14ef1 100644 --- a/core/state/contracts/gen_selfdestruct.go +++ b/core/state/contracts/gen_selfdestruct.go @@ -1,18 +1,18 @@ -// Code generated - DO NOT EDIT. +// Code generated by abigen. DO NOT EDIT. // This file is a generated binding and any manual changes will be lost. package contracts import ( + "fmt" "math/big" + "reflect" "strings" - libcommon "github.com/erigontech/erigon-lib/common" - ethereum "github.com/erigontech/erigon" + libcommon "github.com/erigontech/erigon-lib/common" "github.com/erigontech/erigon/accounts/abi" "github.com/erigontech/erigon/accounts/abi/bind" - "github.com/erigontech/erigon-lib/common" "github.com/erigontech/erigon/core/types" "github.com/erigontech/erigon/event" ) @@ -26,6 +26,8 @@ var ( _ = libcommon.Big1 _ = types.BloomLookup _ = event.NewSubscription + _ = fmt.Errorf + _ = reflect.ValueOf ) // SelfdestructABI is the input ABI used to generate the binding from. @@ -41,7 +43,7 @@ func DeploySelfdestruct(auth *bind.TransactOpts, backend bind.ContractBackend) ( return libcommon.Address{}, nil, nil, err } - address, tx, contract, err := bind.DeployContract(auth, parsed, common.FromHex(SelfdestructBin), backend) + address, tx, contract, err := bind.DeployContract(auth, parsed, libcommon.FromHex(SelfdestructBin), backend) if err != nil { return libcommon.Address{}, nil, nil, err } diff --git a/core/types/gen_genesis.go b/core/types/gen_genesis.go index d6ff602976e..3e3dba283e0 100644 --- a/core/types/gen_genesis.go +++ b/core/types/gen_genesis.go @@ -11,7 +11,6 @@ import ( "github.com/erigontech/erigon-lib/common" "github.com/erigontech/erigon-lib/common/hexutility" "github.com/erigontech/erigon-lib/common/math" - common0 "github.com/erigontech/erigon-lib/common" ) var _ = (*genesisSpecMarshaling)(nil) @@ -19,24 +18,24 @@ var _ = (*genesisSpecMarshaling)(nil) // MarshalJSON marshals as JSON. func (g Genesis) MarshalJSON() ([]byte, error) { type Genesis struct { - Config *chain.Config `json:"config"` - Nonce math.HexOrDecimal64 `json:"nonce"` - Timestamp math.HexOrDecimal64 `json:"timestamp"` - ExtraData hexutility.Bytes `json:"extraData"` - GasLimit math.HexOrDecimal64 `json:"gasLimit" gencodec:"required"` - Difficulty *math.HexOrDecimal256 `json:"difficulty" gencodec:"required"` - Mixhash common.Hash `json:"mixHash"` - Coinbase common.Address `json:"coinbase"` - Alloc map[common0.UnprefixedAddress]GenesisAccount `json:"alloc" gencodec:"required"` - AuRaSeal *AuRaSeal `json:"seal"` - Number math.HexOrDecimal64 `json:"number"` - GasUsed math.HexOrDecimal64 `json:"gasUsed"` - ParentHash common.Hash `json:"parentHash"` - BaseFee *math.HexOrDecimal256 `json:"baseFeePerGas"` - BlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed"` - ExcessBlobGas *math.HexOrDecimal64 `json:"excessBlobGas"` - ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot"` - RequestsHash *common.Hash `json:"requestsHash"` + Config *chain.Config `json:"config"` + Nonce math.HexOrDecimal64 `json:"nonce"` + Timestamp math.HexOrDecimal64 `json:"timestamp"` + ExtraData hexutility.Bytes `json:"extraData"` + GasLimit math.HexOrDecimal64 `json:"gasLimit" gencodec:"required"` + Difficulty *math.HexOrDecimal256 `json:"difficulty" gencodec:"required"` + Mixhash common.Hash `json:"mixHash"` + Coinbase common.Address `json:"coinbase"` + Alloc map[common.UnprefixedAddress]GenesisAccount `json:"alloc" gencodec:"required"` + AuRaSeal *AuRaSeal `json:"seal"` + Number math.HexOrDecimal64 `json:"number"` + GasUsed math.HexOrDecimal64 `json:"gasUsed"` + ParentHash common.Hash `json:"parentHash"` + BaseFee *math.HexOrDecimal256 `json:"baseFeePerGas"` + BlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed"` + ExcessBlobGas *math.HexOrDecimal64 `json:"excessBlobGas"` + ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot"` + RequestsHash *common.Hash `json:"requestsHash"` } var enc Genesis enc.Config = g.Config @@ -48,9 +47,9 @@ func (g Genesis) MarshalJSON() ([]byte, error) { enc.Mixhash = g.Mixhash enc.Coinbase = g.Coinbase if g.Alloc != nil { - enc.Alloc = make(map[common0.UnprefixedAddress]GenesisAccount, len(g.Alloc)) + enc.Alloc = make(map[common.UnprefixedAddress]GenesisAccount, len(g.Alloc)) for k, v := range g.Alloc { - enc.Alloc[common0.UnprefixedAddress(k)] = v + enc.Alloc[common.UnprefixedAddress(k)] = v } } enc.AuRaSeal = g.AuRaSeal @@ -68,24 +67,24 @@ func (g Genesis) MarshalJSON() ([]byte, error) { // UnmarshalJSON unmarshals from JSON. func (g *Genesis) UnmarshalJSON(input []byte) error { type Genesis struct { - Config *chain.Config `json:"config"` - Nonce *math.HexOrDecimal64 `json:"nonce"` - Timestamp *math.HexOrDecimal64 `json:"timestamp"` - ExtraData *hexutility.Bytes `json:"extraData"` - GasLimit *math.HexOrDecimal64 `json:"gasLimit" gencodec:"required"` - Difficulty *math.HexOrDecimal256 `json:"difficulty" gencodec:"required"` - Mixhash *common.Hash `json:"mixHash"` - Coinbase *common.Address `json:"coinbase"` - Alloc map[common0.UnprefixedAddress]GenesisAccount `json:"alloc" gencodec:"required"` - AuRaSeal *AuRaSeal `json:"seal"` - Number *math.HexOrDecimal64 `json:"number"` - GasUsed *math.HexOrDecimal64 `json:"gasUsed"` - ParentHash *common.Hash `json:"parentHash"` - BaseFee *math.HexOrDecimal256 `json:"baseFeePerGas"` - BlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed"` - ExcessBlobGas *math.HexOrDecimal64 `json:"excessBlobGas"` - ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot"` - RequestsHash *common.Hash `json:"requestsHash"` + Config *chain.Config `json:"config"` + Nonce *math.HexOrDecimal64 `json:"nonce"` + Timestamp *math.HexOrDecimal64 `json:"timestamp"` + ExtraData *hexutility.Bytes `json:"extraData"` + GasLimit *math.HexOrDecimal64 `json:"gasLimit" gencodec:"required"` + Difficulty *math.HexOrDecimal256 `json:"difficulty" gencodec:"required"` + Mixhash *common.Hash `json:"mixHash"` + Coinbase *common.Address `json:"coinbase"` + Alloc map[common.UnprefixedAddress]GenesisAccount `json:"alloc" gencodec:"required"` + AuRaSeal *AuRaSeal `json:"seal"` + Number *math.HexOrDecimal64 `json:"number"` + GasUsed *math.HexOrDecimal64 `json:"gasUsed"` + ParentHash *common.Hash `json:"parentHash"` + BaseFee *math.HexOrDecimal256 `json:"baseFeePerGas"` + BlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed"` + ExcessBlobGas *math.HexOrDecimal64 `json:"excessBlobGas"` + ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot"` + RequestsHash *common.Hash `json:"requestsHash"` } var dec Genesis if err := json.Unmarshal(input, &dec); err != nil { diff --git a/eth/ethconfig/gen_config.go b/eth/ethconfig/gen_config.go index a37d863d34c..1f493779d15 100644 --- a/eth/ethconfig/gen_config.go +++ b/eth/ethconfig/gen_config.go @@ -10,14 +10,13 @@ import ( "github.com/erigontech/erigon-lib/common" "github.com/erigontech/erigon-lib/common/datadir" "github.com/erigontech/erigon-lib/downloader/downloadercfg" - "github.com/erigontech/erigon/txnprovider/txpool/txpoolcfg" - "github.com/erigontech/erigon/cl/beacon/beacon_router_configuration" "github.com/erigontech/erigon/cl/clparams" "github.com/erigontech/erigon/consensus/ethash/ethashcfg" "github.com/erigontech/erigon/core/types" "github.com/erigontech/erigon/eth/gasprice/gaspricecfg" "github.com/erigontech/erigon/ethdb/prune" "github.com/erigontech/erigon/params" + "github.com/erigontech/erigon/txnprovider/txpool/txpoolcfg" ) // MarshalTOML marshals as TOML. @@ -32,7 +31,6 @@ func (c Config) MarshalTOML() (interface{}, error) { BadBlockHash common.Hash Snapshot BlocksFreezing Downloader *downloadercfg.Cfg - BeaconRouter beacon_router_configuration.RouterConfiguration CaplinConfig clparams.CaplinConfig Dirs datadir.Dirs ExternalSnapshotDownloaderAddr string @@ -55,11 +53,6 @@ func (c Config) MarshalTOML() (interface{}, error) { PolygonSyncStage bool Ethstats string InternalCL bool - CaplinDiscoveryAddr string - CaplinDiscoveryPort uint64 - CaplinDiscoveryTCPPort uint64 - SentinelAddr string - SentinelPort uint64 OverridePragueTime *big.Int `toml:",omitempty"` SilkwormExecution bool SilkwormRpcDaemon bool @@ -85,7 +78,6 @@ func (c Config) MarshalTOML() (interface{}, error) { enc.BadBlockHash = c.BadBlockHash enc.Snapshot = c.Snapshot enc.Downloader = c.Downloader - enc.CaplinConfig.BeaconAPIRouter = c.CaplinConfig.BeaconAPIRouter enc.CaplinConfig = c.CaplinConfig enc.Dirs = c.Dirs enc.ExternalSnapshotDownloaderAddr = c.ExternalSnapshotDownloaderAddr @@ -108,11 +100,6 @@ func (c Config) MarshalTOML() (interface{}, error) { enc.PolygonSyncStage = c.PolygonSyncStage enc.Ethstats = c.Ethstats enc.InternalCL = c.InternalCL - enc.CaplinConfig.CaplinDiscoveryAddr = c.CaplinConfig.CaplinDiscoveryAddr - enc.CaplinConfig.CaplinDiscoveryPort = c.CaplinConfig.CaplinDiscoveryPort - enc.CaplinConfig.CaplinDiscoveryTCPPort = c.CaplinConfig.CaplinDiscoveryTCPPort - enc.CaplinConfig.SentinelAddr = c.CaplinConfig.SentinelAddr - enc.CaplinConfig.SentinelPort = c.CaplinConfig.SentinelPort enc.OverridePragueTime = c.OverridePragueTime enc.SilkwormExecution = c.SilkwormExecution enc.SilkwormRpcDaemon = c.SilkwormRpcDaemon @@ -142,7 +129,6 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error { BadBlockHash *common.Hash Snapshot *BlocksFreezing Downloader *downloadercfg.Cfg - BeaconRouter *beacon_router_configuration.RouterConfiguration CaplinConfig *clparams.CaplinConfig Dirs *datadir.Dirs ExternalSnapshotDownloaderAddr *string @@ -165,11 +151,6 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error { PolygonSyncStage *bool Ethstats *string InternalCL *bool - CaplinDiscoveryAddr *string - CaplinDiscoveryPort *uint64 - CaplinDiscoveryTCPPort *uint64 - SentinelAddr *string - SentinelPort *uint64 OverridePragueTime *big.Int `toml:",omitempty"` SilkwormExecution *bool SilkwormRpcDaemon *bool @@ -216,9 +197,6 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error { if dec.Downloader != nil { c.Downloader = dec.Downloader } - if dec.BeaconRouter != nil { - c.CaplinConfig.BeaconAPIRouter = *dec.BeaconRouter - } if dec.CaplinConfig != nil { c.CaplinConfig = *dec.CaplinConfig } @@ -285,21 +263,6 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error { if dec.InternalCL != nil { c.InternalCL = *dec.InternalCL } - if dec.CaplinDiscoveryAddr != nil { - c.CaplinConfig.CaplinDiscoveryAddr = *dec.CaplinDiscoveryAddr - } - if dec.CaplinDiscoveryPort != nil { - c.CaplinConfig.CaplinDiscoveryPort = *dec.CaplinDiscoveryPort - } - if dec.CaplinDiscoveryTCPPort != nil { - c.CaplinConfig.CaplinDiscoveryTCPPort = *dec.CaplinDiscoveryTCPPort - } - if dec.SentinelAddr != nil { - c.CaplinConfig.SentinelAddr = *dec.SentinelAddr - } - if dec.SentinelPort != nil { - c.CaplinConfig.SentinelPort = *dec.SentinelPort - } if dec.OverridePragueTime != nil { c.OverridePragueTime = dec.OverridePragueTime } diff --git a/polygon/bor/state_receiver_mock.go b/polygon/bor/state_receiver_mock.go index 37d68a31cc1..3ac48289159 100644 --- a/polygon/bor/state_receiver_mock.go +++ b/polygon/bor/state_receiver_mock.go @@ -12,8 +12,8 @@ package bor import ( reflect "reflect" - consensus "github.com/erigontech/erigon/consensus" rlp "github.com/erigontech/erigon-lib/rlp" + consensus "github.com/erigontech/erigon/consensus" gomock "go.uber.org/mock/gomock" ) diff --git a/tests/contracts/gen.go b/tests/contracts/gen.go index 1f74de20eb2..a35d5623d42 100644 --- a/tests/contracts/gen.go +++ b/tests/contracts/gen.go @@ -6,4 +6,4 @@ package contracts // selfDestructor.sol //go:generate solc --allow-paths ., --abi --bin --overwrite --optimize -o build selfDestructor.sol -//go:generate abigen -abi build/selfdestructor.abi -bin build/selfdestructor.bin -pkg contracts -type selfDestructor -out ./gen_selfDestructor.go +//go:generate abigen -abi build/selfDestructor.abi -bin build/selfDestructor.bin -pkg contracts -type selfDestructor -out ./gen_selfDestructor.go diff --git a/tests/contracts/gen_selfDestructor.go b/tests/contracts/gen_selfDestructor.go index d6639e8c0b4..657d06ada33 100644 --- a/tests/contracts/gen_selfDestructor.go +++ b/tests/contracts/gen_selfDestructor.go @@ -1,18 +1,18 @@ -// Code generated - DO NOT EDIT. +// Code generated by abigen. DO NOT EDIT. // This file is a generated binding and any manual changes will be lost. package contracts import ( + "fmt" "math/big" + "reflect" "strings" - libcommon "github.com/erigontech/erigon-lib/common" - ethereum "github.com/erigontech/erigon" + libcommon "github.com/erigontech/erigon-lib/common" "github.com/erigontech/erigon/accounts/abi" "github.com/erigontech/erigon/accounts/abi/bind" - "github.com/erigontech/erigon-lib/common" "github.com/erigontech/erigon/core/types" "github.com/erigontech/erigon/event" ) @@ -26,6 +26,8 @@ var ( _ = libcommon.Big1 _ = types.BloomLookup _ = event.NewSubscription + _ = fmt.Errorf + _ = reflect.ValueOf ) // SelfDestructorABI is the input ABI used to generate the binding from. @@ -41,7 +43,7 @@ func DeploySelfDestructor(auth *bind.TransactOpts, backend bind.ContractBackend) return libcommon.Address{}, nil, nil, err } - address, tx, contract, err := bind.DeployContract(auth, parsed, common.FromHex(SelfDestructorBin), backend) + address, tx, contract, err := bind.DeployContract(auth, parsed, libcommon.FromHex(SelfDestructorBin), backend) if err != nil { return libcommon.Address{}, nil, nil, err } diff --git a/tests/contracts/gen_testcontract.go b/tests/contracts/gen_testcontract.go index 544f65b6c3b..f6fe4b0bda7 100644 --- a/tests/contracts/gen_testcontract.go +++ b/tests/contracts/gen_testcontract.go @@ -1,18 +1,18 @@ -// Code generated - DO NOT EDIT. +// Code generated by abigen. DO NOT EDIT. // This file is a generated binding and any manual changes will be lost. package contracts import ( + "fmt" "math/big" + "reflect" "strings" - libcommon "github.com/erigontech/erigon-lib/common" - ethereum "github.com/erigontech/erigon" + libcommon "github.com/erigontech/erigon-lib/common" "github.com/erigontech/erigon/accounts/abi" "github.com/erigontech/erigon/accounts/abi/bind" - "github.com/erigontech/erigon-lib/common" "github.com/erigontech/erigon/core/types" "github.com/erigontech/erigon/event" ) @@ -26,13 +26,15 @@ var ( _ = libcommon.Big1 _ = types.BloomLookup _ = event.NewSubscription + _ = fmt.Errorf + _ = reflect.ValueOf ) // TestcontractABI is the input ABI used to generate the binding from. const TestcontractABI = "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"balances\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newBalance\",\"type\":\"uint256\"}],\"name\":\"create\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newBalance\",\"type\":\"uint256\"}],\"name\":\"createAndException\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newBalance\",\"type\":\"uint256\"}],\"name\":\"createAndRevert\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"remove\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"removeAndException\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"removeAndRevert\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newBalance\",\"type\":\"uint256\"}],\"name\":\"update\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newBalance\",\"type\":\"uint256\"}],\"name\":\"updateAndException\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newBalance\",\"type\":\"uint256\"}],\"name\":\"updateAndRevert\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]" // TestcontractBin is the compiled bytecode used for deploying new contracts. -var TestcontractBin = "0x608060405234801561001057600080fd5b5033600090815260208190526040902060649055610208806100336000396000f3fe608060405234801561001057600080fd5b506004361061009e5760003560e01c8063c2ce0ef711610066578063c2ce0ef71461010a578063c53e5ae314610127578063cb946a0714610127578063d592ed1f14610144578063f64c050d1461010a5761009e565b806327e235e3146100a3578063660cc200146100db578063780900dc146100e557806382ab890a146100e5578063a7f4377914610102575b600080fd5b6100c9600480360360208110156100b957600080fd5b50356001600160a01b031661014c565b60408051918252519081900360200190f35b6100e361015e565b005b6100e3600480360360208110156100fb57600080fd5b5035610170565b6100e3610182565b6100e36004803603602081101561012057600080fd5b5035610194565b6100e36004803603602081101561013d57600080fd5b50356101a8565b6100e36101bd565b60006020819052908152604090205481565b33600090815260208190526040812055fe5b33600090815260208190526040902055565b33600090815260208190526040812055565b336000908152602081905260409020819055fe5b33600090815260208190526040812082905580fd5b33600090815260208190526040812081905580fdfea2646970667358221220c40698b47133056d15d4a84d769c07a1f24008b50347105be970e1f0191ca44f64736f6c63430007020033" +var TestcontractBin = "0x608060405234801561001057600080fd5b503360009081526020819052604090206064905561023a806100336000396000f3fe608060405234801561001057600080fd5b506004361061009e5760003560e01c8063c2ce0ef711610066578063c2ce0ef714610114578063c53e5ae314610127578063cb946a0714610127578063d592ed1f1461013a578063f64c050d1461011457600080fd5b806327e235e3146100a3578063660cc200146100d5578063780900dc146100df57806382ab890a146100df578063a7f43779146100ff575b600080fd5b6100c36100b13660046101a5565b60006020819052908152604090205481565b60405190815260200160405180910390f35b6100dd610142565b005b6100dd6100ed3660046101d5565b33600090815260208190526040902055565b6100dd33600090815260208190526040812055565b6100dd6101223660046101d5565b61015c565b6100dd6101353660046101d5565b610179565b6100dd610190565b3360009081526020819052604081205561015a6101ee565b565b3360009081526020819052604090208190556101766101ee565b50565b336000908152602081905260408120829055819080fd5b33600090815260208190526040812081905580fd5b6000602082840312156101b757600080fd5b81356001600160a01b03811681146101ce57600080fd5b9392505050565b6000602082840312156101e757600080fd5b5035919050565b634e487b7160e01b600052600160045260246000fdfea2646970667358221220cbc0ec1bd2504a9e5d6a3f3a8b92de36a1af219062eec962f407d937d0acadc664736f6c63430008130033" // DeployTestcontract deploys a new Ethereum contract, binding an instance of Testcontract to it. func DeployTestcontract(auth *bind.TransactOpts, backend bind.ContractBackend) (libcommon.Address, types.Transaction, *Testcontract, error) { @@ -41,7 +43,7 @@ func DeployTestcontract(auth *bind.TransactOpts, backend bind.ContractBackend) ( return libcommon.Address{}, nil, nil, err } - address, tx, contract, err := bind.DeployContract(auth, parsed, common.FromHex(TestcontractBin), backend) + address, tx, contract, err := bind.DeployContract(auth, parsed, libcommon.FromHex(TestcontractBin), backend) if err != nil { return libcommon.Address{}, nil, nil, err } @@ -409,3 +411,225 @@ func (_Testcontract *TestcontractSession) UpdateAndRevert(newBalance *big.Int) ( func (_Testcontract *TestcontractTransactorSession) UpdateAndRevert(newBalance *big.Int) (types.Transaction, error) { return _Testcontract.Contract.UpdateAndRevert(&_Testcontract.TransactOpts, newBalance) } + +// TestcontractCreateParams is an auto generated read-only Go binding of transcaction calldata params +type TestcontractCreateParams struct { + Param_newBalance *big.Int +} + +// Parse Create method from calldata of a transaction +// +// Solidity: function create(uint256 newBalance) returns() +func ParseTestcontractCreateParams(calldata []byte) (*TestcontractCreateParams, error) { + if len(calldata) <= 4 { + return nil, fmt.Errorf("invalid calldata input") + } + + _abi, err := abi.JSON(strings.NewReader(TestcontractABI)) + if err != nil { + return nil, fmt.Errorf("failed to get abi of registry metadata: %w", err) + } + + out, err := _abi.Methods["create"].Inputs.Unpack(calldata[4:]) + if err != nil { + return nil, fmt.Errorf("failed to unpack create params data: %w", err) + } + + var paramsResult = new(TestcontractCreateParams) + value := reflect.ValueOf(paramsResult).Elem() + + if value.NumField() != len(out) { + return nil, fmt.Errorf("failed to match calldata with param field number") + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return &TestcontractCreateParams{ + Param_newBalance: out0, + }, nil +} + +// TestcontractCreateAndExceptionParams is an auto generated read-only Go binding of transcaction calldata params +type TestcontractCreateAndExceptionParams struct { + Param_newBalance *big.Int +} + +// Parse CreateAndException method from calldata of a transaction +// +// Solidity: function createAndException(uint256 newBalance) returns() +func ParseTestcontractCreateAndExceptionParams(calldata []byte) (*TestcontractCreateAndExceptionParams, error) { + if len(calldata) <= 4 { + return nil, fmt.Errorf("invalid calldata input") + } + + _abi, err := abi.JSON(strings.NewReader(TestcontractABI)) + if err != nil { + return nil, fmt.Errorf("failed to get abi of registry metadata: %w", err) + } + + out, err := _abi.Methods["createAndException"].Inputs.Unpack(calldata[4:]) + if err != nil { + return nil, fmt.Errorf("failed to unpack createAndException params data: %w", err) + } + + var paramsResult = new(TestcontractCreateAndExceptionParams) + value := reflect.ValueOf(paramsResult).Elem() + + if value.NumField() != len(out) { + return nil, fmt.Errorf("failed to match calldata with param field number") + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return &TestcontractCreateAndExceptionParams{ + Param_newBalance: out0, + }, nil +} + +// TestcontractCreateAndRevertParams is an auto generated read-only Go binding of transcaction calldata params +type TestcontractCreateAndRevertParams struct { + Param_newBalance *big.Int +} + +// Parse CreateAndRevert method from calldata of a transaction +// +// Solidity: function createAndRevert(uint256 newBalance) returns() +func ParseTestcontractCreateAndRevertParams(calldata []byte) (*TestcontractCreateAndRevertParams, error) { + if len(calldata) <= 4 { + return nil, fmt.Errorf("invalid calldata input") + } + + _abi, err := abi.JSON(strings.NewReader(TestcontractABI)) + if err != nil { + return nil, fmt.Errorf("failed to get abi of registry metadata: %w", err) + } + + out, err := _abi.Methods["createAndRevert"].Inputs.Unpack(calldata[4:]) + if err != nil { + return nil, fmt.Errorf("failed to unpack createAndRevert params data: %w", err) + } + + var paramsResult = new(TestcontractCreateAndRevertParams) + value := reflect.ValueOf(paramsResult).Elem() + + if value.NumField() != len(out) { + return nil, fmt.Errorf("failed to match calldata with param field number") + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return &TestcontractCreateAndRevertParams{ + Param_newBalance: out0, + }, nil +} + +// TestcontractUpdateParams is an auto generated read-only Go binding of transcaction calldata params +type TestcontractUpdateParams struct { + Param_newBalance *big.Int +} + +// Parse Update method from calldata of a transaction +// +// Solidity: function update(uint256 newBalance) returns() +func ParseTestcontractUpdateParams(calldata []byte) (*TestcontractUpdateParams, error) { + if len(calldata) <= 4 { + return nil, fmt.Errorf("invalid calldata input") + } + + _abi, err := abi.JSON(strings.NewReader(TestcontractABI)) + if err != nil { + return nil, fmt.Errorf("failed to get abi of registry metadata: %w", err) + } + + out, err := _abi.Methods["update"].Inputs.Unpack(calldata[4:]) + if err != nil { + return nil, fmt.Errorf("failed to unpack update params data: %w", err) + } + + var paramsResult = new(TestcontractUpdateParams) + value := reflect.ValueOf(paramsResult).Elem() + + if value.NumField() != len(out) { + return nil, fmt.Errorf("failed to match calldata with param field number") + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return &TestcontractUpdateParams{ + Param_newBalance: out0, + }, nil +} + +// TestcontractUpdateAndExceptionParams is an auto generated read-only Go binding of transcaction calldata params +type TestcontractUpdateAndExceptionParams struct { + Param_newBalance *big.Int +} + +// Parse UpdateAndException method from calldata of a transaction +// +// Solidity: function updateAndException(uint256 newBalance) returns() +func ParseTestcontractUpdateAndExceptionParams(calldata []byte) (*TestcontractUpdateAndExceptionParams, error) { + if len(calldata) <= 4 { + return nil, fmt.Errorf("invalid calldata input") + } + + _abi, err := abi.JSON(strings.NewReader(TestcontractABI)) + if err != nil { + return nil, fmt.Errorf("failed to get abi of registry metadata: %w", err) + } + + out, err := _abi.Methods["updateAndException"].Inputs.Unpack(calldata[4:]) + if err != nil { + return nil, fmt.Errorf("failed to unpack updateAndException params data: %w", err) + } + + var paramsResult = new(TestcontractUpdateAndExceptionParams) + value := reflect.ValueOf(paramsResult).Elem() + + if value.NumField() != len(out) { + return nil, fmt.Errorf("failed to match calldata with param field number") + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return &TestcontractUpdateAndExceptionParams{ + Param_newBalance: out0, + }, nil +} + +// TestcontractUpdateAndRevertParams is an auto generated read-only Go binding of transcaction calldata params +type TestcontractUpdateAndRevertParams struct { + Param_newBalance *big.Int +} + +// Parse UpdateAndRevert method from calldata of a transaction +// +// Solidity: function updateAndRevert(uint256 newBalance) returns() +func ParseTestcontractUpdateAndRevertParams(calldata []byte) (*TestcontractUpdateAndRevertParams, error) { + if len(calldata) <= 4 { + return nil, fmt.Errorf("invalid calldata input") + } + + _abi, err := abi.JSON(strings.NewReader(TestcontractABI)) + if err != nil { + return nil, fmt.Errorf("failed to get abi of registry metadata: %w", err) + } + + out, err := _abi.Methods["updateAndRevert"].Inputs.Unpack(calldata[4:]) + if err != nil { + return nil, fmt.Errorf("failed to unpack updateAndRevert params data: %w", err) + } + + var paramsResult = new(TestcontractUpdateAndRevertParams) + value := reflect.ValueOf(paramsResult).Elem() + + if value.NumField() != len(out) { + return nil, fmt.Errorf("failed to match calldata with param field number") + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return &TestcontractUpdateAndRevertParams{ + Param_newBalance: out0, + }, nil +} diff --git a/tests/difficulty_test_util.go b/tests/difficulty_test_util.go index 7fcc1f09b8b..5cf7f86a5ec 100644 --- a/tests/difficulty_test_util.go +++ b/tests/difficulty_test_util.go @@ -47,7 +47,7 @@ type difficultyTestMarshaling struct { ParentDifficulty *math.HexOrDecimal256 CurrentTimestamp math.HexOrDecimal64 CurrentDifficulty *math.HexOrDecimal256 - ParentUncles uint64 + ParentUncles math.HexOrDecimal64 CurrentBlockNumber math.HexOrDecimal64 } diff --git a/tests/gen_stenv.go b/tests/gen_stenv.go index 02bbd20fa1c..f911db30eac 100644 --- a/tests/gen_stenv.go +++ b/tests/gen_stenv.go @@ -9,8 +9,6 @@ import ( "github.com/erigontech/erigon-lib/common" "github.com/erigontech/erigon-lib/common/math" - - common0 "github.com/erigontech/erigon-lib/common" ) var _ = (*stEnvMarshaling)(nil) @@ -18,17 +16,17 @@ var _ = (*stEnvMarshaling)(nil) // MarshalJSON marshals as JSON. func (s stEnv) MarshalJSON() ([]byte, error) { type stEnv struct { - Coinbase common0.UnprefixedAddress `json:"currentCoinbase" gencodec:"required"` - Difficulty *math.HexOrDecimal256 `json:"currentDifficulty" gencodec:"required"` - Random *math.HexOrDecimal256 `json:"currentRandom" gencodec:"optional"` - GasLimit math.HexOrDecimal64 `json:"currentGasLimit" gencodec:"required"` - Number math.HexOrDecimal64 `json:"currentNumber" gencodec:"required"` - Timestamp math.HexOrDecimal64 `json:"currentTimestamp" gencodec:"required"` - BaseFee *math.HexOrDecimal256 `json:"currentBaseFee" gencodec:"optional"` - ExcessBlobGas *math.HexOrDecimal64 `json:"currentExcessBlobGas" gencodec:"optional"` + Coinbase common.UnprefixedAddress `json:"currentCoinbase" gencodec:"required"` + Difficulty *math.HexOrDecimal256 `json:"currentDifficulty" gencodec:"required"` + Random *math.HexOrDecimal256 `json:"currentRandom" gencodec:"optional"` + GasLimit math.HexOrDecimal64 `json:"currentGasLimit" gencodec:"required"` + Number math.HexOrDecimal64 `json:"currentNumber" gencodec:"required"` + Timestamp math.HexOrDecimal64 `json:"currentTimestamp" gencodec:"required"` + BaseFee *math.HexOrDecimal256 `json:"currentBaseFee" gencodec:"optional"` + ExcessBlobGas *math.HexOrDecimal64 `json:"currentExcessBlobGas" gencodec:"optional"` } var enc stEnv - enc.Coinbase = common0.UnprefixedAddress(s.Coinbase) + enc.Coinbase = common.UnprefixedAddress(s.Coinbase) enc.Difficulty = (*math.HexOrDecimal256)(s.Difficulty) enc.Random = (*math.HexOrDecimal256)(s.Random) enc.GasLimit = math.HexOrDecimal64(s.GasLimit) @@ -42,14 +40,14 @@ func (s stEnv) MarshalJSON() ([]byte, error) { // UnmarshalJSON unmarshals from JSON. func (s *stEnv) UnmarshalJSON(input []byte) error { type stEnv struct { - Coinbase *common0.UnprefixedAddress `json:"currentCoinbase" gencodec:"required"` - Difficulty *math.HexOrDecimal256 `json:"currentDifficulty" gencodec:"required"` - Random *math.HexOrDecimal256 `json:"currentRandom" gencodec:"optional"` - GasLimit *math.HexOrDecimal64 `json:"currentGasLimit" gencodec:"required"` - Number *math.HexOrDecimal64 `json:"currentNumber" gencodec:"required"` - Timestamp *math.HexOrDecimal64 `json:"currentTimestamp" gencodec:"required"` - BaseFee *math.HexOrDecimal256 `json:"currentBaseFee" gencodec:"optional"` - ExcessBlobGas *math.HexOrDecimal64 `json:"currentExcessBlobGas" gencodec:"optional"` + Coinbase *common.UnprefixedAddress `json:"currentCoinbase" gencodec:"required"` + Difficulty *math.HexOrDecimal256 `json:"currentDifficulty" gencodec:"required"` + Random *math.HexOrDecimal256 `json:"currentRandom" gencodec:"optional"` + GasLimit *math.HexOrDecimal64 `json:"currentGasLimit" gencodec:"required"` + Number *math.HexOrDecimal64 `json:"currentNumber" gencodec:"required"` + Timestamp *math.HexOrDecimal64 `json:"currentTimestamp" gencodec:"required"` + BaseFee *math.HexOrDecimal256 `json:"currentBaseFee" gencodec:"optional"` + ExcessBlobGas *math.HexOrDecimal64 `json:"currentExcessBlobGas" gencodec:"optional"` } var dec stEnv if err := json.Unmarshal(input, &dec); err != nil { diff --git a/turbo/jsonrpc/contracts/gen.go b/turbo/jsonrpc/contracts/gen.go index d0c8616de30..89046154b84 100644 --- a/turbo/jsonrpc/contracts/gen.go +++ b/turbo/jsonrpc/contracts/gen.go @@ -18,3 +18,7 @@ package contracts //go:generate solc --allow-paths ., --abi --bin --overwrite --optimize -o build token.sol //go:generate abigen -abi build/Token.abi -bin build/Token.bin -pkg contracts -type token -out ./gen_token.go + +// poly.sol +//go:generate solc --allow-paths ., --abi --bin --overwrite --optimize -o build poly.sol +//go:generate abigen -abi build/Poly.abi -bin build/Poly.bin -pkg contracts -type poly -out ./gen_poly.go diff --git a/turbo/jsonrpc/contracts/gen_poly.go b/turbo/jsonrpc/contracts/gen_poly.go index dd984a87a22..3d5a287d4da 100644 --- a/turbo/jsonrpc/contracts/gen_poly.go +++ b/turbo/jsonrpc/contracts/gen_poly.go @@ -1,18 +1,18 @@ -// Code generated - DO NOT EDIT. +// Code generated by abigen. DO NOT EDIT. // This file is a generated binding and any manual changes will be lost. package contracts import ( + "fmt" "math/big" + "reflect" "strings" - libcommon "github.com/erigontech/erigon-lib/common" - ethereum "github.com/erigontech/erigon" + libcommon "github.com/erigontech/erigon-lib/common" "github.com/erigontech/erigon/accounts/abi" "github.com/erigontech/erigon/accounts/abi/bind" - "github.com/erigontech/erigon-lib/common" "github.com/erigontech/erigon/core/types" "github.com/erigontech/erigon/event" ) @@ -26,6 +26,8 @@ var ( _ = libcommon.Big1 _ = types.BloomLookup _ = event.NewSubscription + _ = fmt.Errorf + _ = reflect.ValueOf ) // PolyABI is the input ABI used to generate the binding from. @@ -41,7 +43,7 @@ func DeployPoly(auth *bind.TransactOpts, backend bind.ContractBackend) (libcommo return libcommon.Address{}, nil, nil, err } - address, tx, contract, err := bind.DeployContract(auth, parsed, common.FromHex(PolyBin), backend) + address, tx, contract, err := bind.DeployContract(auth, parsed, libcommon.FromHex(PolyBin), backend) if err != nil { return libcommon.Address{}, nil, nil, err } @@ -232,6 +234,80 @@ func (_Poly *PolyTransactorSession) DeployAndDestruct(salt *big.Int) (types.Tran return _Poly.Contract.DeployAndDestruct(&_Poly.TransactOpts, salt) } +// PolyDeployParams is an auto generated read-only Go binding of transcaction calldata params +type PolyDeployParams struct { + Param_salt *big.Int +} + +// Parse Deploy method from calldata of a transaction +// +// Solidity: function deploy(uint256 salt) returns() +func ParsePolyDeployParams(calldata []byte) (*PolyDeployParams, error) { + if len(calldata) <= 4 { + return nil, fmt.Errorf("invalid calldata input") + } + + _abi, err := abi.JSON(strings.NewReader(PolyABI)) + if err != nil { + return nil, fmt.Errorf("failed to get abi of registry metadata: %w", err) + } + + out, err := _abi.Methods["deploy"].Inputs.Unpack(calldata[4:]) + if err != nil { + return nil, fmt.Errorf("failed to unpack deploy params data: %w", err) + } + + var paramsResult = new(PolyDeployParams) + value := reflect.ValueOf(paramsResult).Elem() + + if value.NumField() != len(out) { + return nil, fmt.Errorf("failed to match calldata with param field number") + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return &PolyDeployParams{ + Param_salt: out0, + }, nil +} + +// PolyDeployAndDestructParams is an auto generated read-only Go binding of transcaction calldata params +type PolyDeployAndDestructParams struct { + Param_salt *big.Int +} + +// Parse DeployAndDestruct method from calldata of a transaction +// +// Solidity: function deployAndDestruct(uint256 salt) returns() +func ParsePolyDeployAndDestructParams(calldata []byte) (*PolyDeployAndDestructParams, error) { + if len(calldata) <= 4 { + return nil, fmt.Errorf("invalid calldata input") + } + + _abi, err := abi.JSON(strings.NewReader(PolyABI)) + if err != nil { + return nil, fmt.Errorf("failed to get abi of registry metadata: %w", err) + } + + out, err := _abi.Methods["deployAndDestruct"].Inputs.Unpack(calldata[4:]) + if err != nil { + return nil, fmt.Errorf("failed to unpack deployAndDestruct params data: %w", err) + } + + var paramsResult = new(PolyDeployAndDestructParams) + value := reflect.ValueOf(paramsResult).Elem() + + if value.NumField() != len(out) { + return nil, fmt.Errorf("failed to match calldata with param field number") + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return &PolyDeployAndDestructParams{ + Param_salt: out0, + }, nil +} + // PolyDeployEventIterator is returned from FilterDeployEvent and is used to iterate over the raw logs and unpacked data for DeployEvent events raised by the Poly contract. type PolyDeployEventIterator struct { Event *PolyDeployEvent // Event containing the contract specifics and raw log @@ -305,6 +381,10 @@ type PolyDeployEvent struct { Raw types.Log // Blockchain specific contextual infos } +func (_Poly *PolyFilterer) DeployEventEventID() libcommon.Hash { + return libcommon.HexToHash("0x68f6a0f063c25c6678c443b9a484086f15ba8f91f60218695d32a5251f2050eb") +} + // FilterDeployEvent is a free log retrieval operation binding the contract event 0x68f6a0f063c25c6678c443b9a484086f15ba8f91f60218695d32a5251f2050eb. // // Solidity: event DeployEvent(address d) @@ -362,5 +442,6 @@ func (_Poly *PolyFilterer) ParseDeployEvent(log types.Log) (*PolyDeployEvent, er if err := _Poly.contract.UnpackLog(event, "DeployEvent", log); err != nil { return nil, err } + event.Raw = log return event, nil } diff --git a/turbo/jsonrpc/contracts/gen_token.go b/turbo/jsonrpc/contracts/gen_token.go index 124fcb5f587..e12ee0af782 100644 --- a/turbo/jsonrpc/contracts/gen_token.go +++ b/turbo/jsonrpc/contracts/gen_token.go @@ -1,18 +1,18 @@ -// Code generated - DO NOT EDIT. +// Code generated by abigen. DO NOT EDIT. // This file is a generated binding and any manual changes will be lost. package contracts import ( + "fmt" "math/big" + "reflect" "strings" - libcommon "github.com/erigontech/erigon-lib/common" - ethereum "github.com/erigontech/erigon" + libcommon "github.com/erigontech/erigon-lib/common" "github.com/erigontech/erigon/accounts/abi" "github.com/erigontech/erigon/accounts/abi/bind" - "github.com/erigontech/erigon-lib/common" "github.com/erigontech/erigon/core/types" "github.com/erigontech/erigon/event" ) @@ -26,6 +26,8 @@ var ( _ = libcommon.Big1 _ = types.BloomLookup _ = event.NewSubscription + _ = fmt.Errorf + _ = reflect.ValueOf ) // TokenABI is the input ABI used to generate the binding from. @@ -41,7 +43,7 @@ func DeployToken(auth *bind.TransactOpts, backend bind.ContractBackend, _minter return libcommon.Address{}, nil, nil, err } - address, tx, contract, err := bind.DeployContract(auth, parsed, common.FromHex(TokenBin), backend, _minter) + address, tx, contract, err := bind.DeployContract(auth, parsed, libcommon.FromHex(TokenBin), backend, _minter) if err != nil { return libcommon.Address{}, nil, nil, err } @@ -324,3 +326,81 @@ func (_Token *TokenSession) Transfer(_to libcommon.Address, _value *big.Int) (ty func (_Token *TokenTransactorSession) Transfer(_to libcommon.Address, _value *big.Int) (types.Transaction, error) { return _Token.Contract.Transfer(&_Token.TransactOpts, _to, _value) } + +// TokenMintParams is an auto generated read-only Go binding of transcaction calldata params +type TokenMintParams struct { + Param__to libcommon.Address + Param__value *big.Int +} + +// Parse Mint method from calldata of a transaction +// +// Solidity: function mint(address _to, uint256 _value) returns(bool) +func ParseTokenMintParams(calldata []byte) (*TokenMintParams, error) { + if len(calldata) <= 4 { + return nil, fmt.Errorf("invalid calldata input") + } + + _abi, err := abi.JSON(strings.NewReader(TokenABI)) + if err != nil { + return nil, fmt.Errorf("failed to get abi of registry metadata: %w", err) + } + + out, err := _abi.Methods["mint"].Inputs.Unpack(calldata[4:]) + if err != nil { + return nil, fmt.Errorf("failed to unpack mint params data: %w", err) + } + + var paramsResult = new(TokenMintParams) + value := reflect.ValueOf(paramsResult).Elem() + + if value.NumField() != len(out) { + return nil, fmt.Errorf("failed to match calldata with param field number") + } + + out0 := *abi.ConvertType(out[0], new(libcommon.Address)).(*libcommon.Address) + out1 := *abi.ConvertType(out[1], new(*big.Int)).(**big.Int) + + return &TokenMintParams{ + Param__to: out0, Param__value: out1, + }, nil +} + +// TokenTransferParams is an auto generated read-only Go binding of transcaction calldata params +type TokenTransferParams struct { + Param__to libcommon.Address + Param__value *big.Int +} + +// Parse Transfer method from calldata of a transaction +// +// Solidity: function transfer(address _to, uint256 _value) returns(bool) +func ParseTokenTransferParams(calldata []byte) (*TokenTransferParams, error) { + if len(calldata) <= 4 { + return nil, fmt.Errorf("invalid calldata input") + } + + _abi, err := abi.JSON(strings.NewReader(TokenABI)) + if err != nil { + return nil, fmt.Errorf("failed to get abi of registry metadata: %w", err) + } + + out, err := _abi.Methods["transfer"].Inputs.Unpack(calldata[4:]) + if err != nil { + return nil, fmt.Errorf("failed to unpack transfer params data: %w", err) + } + + var paramsResult = new(TokenTransferParams) + value := reflect.ValueOf(paramsResult).Elem() + + if value.NumField() != len(out) { + return nil, fmt.Errorf("failed to match calldata with param field number") + } + + out0 := *abi.ConvertType(out[0], new(libcommon.Address)).(*libcommon.Address) + out1 := *abi.ConvertType(out[1], new(*big.Int)).(**big.Int) + + return &TokenTransferParams{ + Param__to: out0, Param__value: out1, + }, nil +} From dbbd68ae87a48d490e5d7edb9d8cecb801b04b90 Mon Sep 17 00:00:00 2001 From: Giulio rebuffo Date: Mon, 9 Dec 2024 14:29:17 +0100 Subject: [PATCH 02/24] Caplin: get public keys from head view rather than db view (#13030) basically just a massive simplification of how we handle public keys. I just use the head state now for that instead of the DB. this made me remove a bunch of tables and routines --- cl/antiquary/antiquary.go | 5 +- cl/antiquary/state_antiquary.go | 5 +- cl/antiquary/state_antiquary_test.go | 6 +- cl/antiquary/tests/tests.go | 2 - cl/beacon/handler/attestation_rewards.go | 2 +- cl/beacon/handler/duties_attester.go | 3 +- cl/beacon/handler/duties_proposer.go | 2 +- cl/beacon/handler/duties_sync.go | 9 +- cl/beacon/handler/lighthouse.go | 2 +- cl/beacon/handler/rewards.go | 10 +- cl/beacon/handler/rewards_test.go | 2 +- cl/beacon/handler/states.go | 7 +- cl/beacon/handler/states_test.go | 4 +- cl/beacon/handler/utils_test.go | 18 +- cl/beacon/handler/validators.go | 24 +-- cl/beacon/synced_data/interface.go | 5 + .../mock_services/synced_data_mock.go | 183 ++++++++++++++++-- cl/beacon/synced_data/synced_data.go | 52 +++++ .../historical_states_reader.go | 28 ++- .../historical_states_reader_test.go | 7 +- cl/persistence/state/state_accessors.go | 167 ---------------- .../db_public_keys_registry.go | 32 ++- cl/phase1/stages/forkchoice.go | 26 --- cl/sentinel/sentinel.go | 11 +- cl/sentinel/sentinel_requests_test.go | 6 +- cmd/capcli/cli.go | 13 +- cmd/caplin/caplin1/run.go | 9 +- cmd/utils/flags.go | 2 +- erigon-lib/kv/tables.go | 6 - 29 files changed, 335 insertions(+), 313 deletions(-) diff --git a/cl/antiquary/antiquary.go b/cl/antiquary/antiquary.go index 1f36f508969..da1a6f97c83 100644 --- a/cl/antiquary/antiquary.go +++ b/cl/antiquary/antiquary.go @@ -32,6 +32,7 @@ import ( "github.com/erigontech/erigon-lib/downloader/snaptype" proto_downloader "github.com/erigontech/erigon-lib/gointerfaces/downloaderproto" "github.com/erigontech/erigon-lib/kv" + "github.com/erigontech/erigon/cl/beacon/synced_data" "github.com/erigontech/erigon/cl/clparams" "github.com/erigontech/erigon/cl/persistence/beacon_indicies" "github.com/erigontech/erigon/cl/persistence/blob_storage" @@ -62,12 +63,13 @@ type Antiquary struct { validatorsTable *state_accessors.StaticValidatorTable genesisState *state.CachingBeaconState + syncedData synced_data.SyncedData // set to nil currentState *state.CachingBeaconState balances32 []byte } -func NewAntiquary(ctx context.Context, blobStorage blob_storage.BlobStorage, genesisState *state.CachingBeaconState, validatorsTable *state_accessors.StaticValidatorTable, cfg *clparams.BeaconChainConfig, dirs datadir.Dirs, downloader proto_downloader.DownloaderClient, mainDB kv.RwDB, stateSn *snapshotsync.CaplinStateSnapshots, sn *freezeblocks.CaplinSnapshots, reader freezeblocks.BeaconSnapshotReader, logger log.Logger, states, blocks, blobs, snapgen bool, snBuildSema *semaphore.Weighted) *Antiquary { +func NewAntiquary(ctx context.Context, blobStorage blob_storage.BlobStorage, genesisState *state.CachingBeaconState, validatorsTable *state_accessors.StaticValidatorTable, cfg *clparams.BeaconChainConfig, dirs datadir.Dirs, downloader proto_downloader.DownloaderClient, mainDB kv.RwDB, stateSn *snapshotsync.CaplinStateSnapshots, sn *freezeblocks.CaplinSnapshots, reader freezeblocks.BeaconSnapshotReader, syncedData synced_data.SyncedData, logger log.Logger, states, blocks, blobs, snapgen bool, snBuildSema *semaphore.Weighted) *Antiquary { backfilled := &atomic.Bool{} blobBackfilled := &atomic.Bool{} backfilled.Store(false) @@ -92,6 +94,7 @@ func NewAntiquary(ctx context.Context, blobStorage blob_storage.BlobStorage, gen blobs: blobs, snapgen: snapgen, stateSn: stateSn, + syncedData: syncedData, } } diff --git a/cl/antiquary/state_antiquary.go b/cl/antiquary/state_antiquary.go index 253b5d9aeb3..c30ad6892d5 100644 --- a/cl/antiquary/state_antiquary.go +++ b/cl/antiquary/state_antiquary.go @@ -86,6 +86,9 @@ func (s *Antiquary) loopStates(ctx context.Context) { continue } beforeFinalized = finalized + if s.sn == nil || s.syncedData.Syncing() { + continue + } if err := s.IncrementBeaconState(ctx, finalized); err != nil { if s.currentState != nil { s.logger.Warn("Could not to increment beacon state, trying again later", "err", err, "slot", s.currentState.Slot()) @@ -574,7 +577,7 @@ func (s *Antiquary) initializeStateAntiquaryIfNeeded(ctx context.Context, tx kv. backoffStrides := uint64(10) backoffStep := backoffStrides - historicalReader := historical_states_reader.NewHistoricalStatesReader(s.cfg, s.snReader, s.validatorsTable, s.genesisState, s.stateSn) + historicalReader := historical_states_reader.NewHistoricalStatesReader(s.cfg, s.snReader, s.validatorsTable, s.genesisState, s.stateSn, s.syncedData) for { attempt, err := computeSlotToBeRequested(tx, s.cfg, s.genesisState.Slot(), targetSlot, backoffStep) diff --git a/cl/antiquary/state_antiquary_test.go b/cl/antiquary/state_antiquary_test.go index 4be4b442302..4dc4538c952 100644 --- a/cl/antiquary/state_antiquary_test.go +++ b/cl/antiquary/state_antiquary_test.go @@ -30,6 +30,7 @@ import ( "github.com/erigontech/erigon-lib/kv/memdb" "github.com/erigontech/erigon-lib/log/v3" "github.com/erigontech/erigon/cl/antiquary/tests" + "github.com/erigontech/erigon/cl/beacon/synced_data" "github.com/erigontech/erigon/cl/clparams" "github.com/erigontech/erigon/cl/cltypes" state_accessors "github.com/erigontech/erigon/cl/persistence/state" @@ -39,10 +40,11 @@ import ( func runTest(t *testing.T, blocks []*cltypes.SignedBeaconBlock, preState, postState *state.CachingBeaconState) { db := memdb.NewTestDB(t, kv.ChainDB) reader := tests.LoadChain(blocks, postState, db, t) - + sn := synced_data.NewSyncedDataManager(&clparams.MainnetBeaconConfig, true) + sn.OnHeadState(postState) ctx := context.Background() vt := state_accessors.NewStaticValidatorTable() - a := NewAntiquary(ctx, nil, preState, vt, &clparams.MainnetBeaconConfig, datadir.New("/tmp"), nil, db, nil, nil, reader, log.New(), true, true, true, false, nil) + a := NewAntiquary(ctx, nil, preState, vt, &clparams.MainnetBeaconConfig, datadir.New("/tmp"), nil, db, nil, nil, reader, sn, log.New(), true, true, true, false, nil) require.NoError(t, a.IncrementBeaconState(ctx, blocks[len(blocks)-1].Block.Slot+33)) } diff --git a/cl/antiquary/tests/tests.go b/cl/antiquary/tests/tests.go index 454e04209bf..425ffc0de9b 100644 --- a/cl/antiquary/tests/tests.go +++ b/cl/antiquary/tests/tests.go @@ -28,7 +28,6 @@ import ( "github.com/erigontech/erigon/cl/clparams" "github.com/erigontech/erigon/cl/cltypes" "github.com/erigontech/erigon/cl/persistence/beacon_indicies" - state_accessors "github.com/erigontech/erigon/cl/persistence/state" "github.com/erigontech/erigon/cl/phase1/core/state" "github.com/erigontech/erigon/cl/utils" "github.com/stretchr/testify/require" @@ -122,7 +121,6 @@ func LoadChain(blocks []*cltypes.SignedBeaconBlock, s *state.CachingBeaconState, require.NoError(t, beacon_indicies.WriteBeaconBlockAndIndicies(context.Background(), tx, block, true)) require.NoError(t, beacon_indicies.WriteHighestFinalized(tx, block.Block.Slot+64)) } - require.NoError(t, state_accessors.InitializeStaticTables(tx, s)) require.NoError(t, tx.Commit()) return m diff --git a/cl/beacon/handler/attestation_rewards.go b/cl/beacon/handler/attestation_rewards.go index 2c175c9f4c1..1ab76118e8b 100644 --- a/cl/beacon/handler/attestation_rewards.go +++ b/cl/beacon/handler/attestation_rewards.go @@ -88,7 +88,7 @@ func (a *ApiHandler) PostEthV1BeaconRewardsAttestations(w http.ResponseWriter, r } } - filterIndicies, err := parseQueryValidatorIndicies(tx, req) + filterIndicies, err := parseQueryValidatorIndicies(a.syncedData, req) if err != nil { return nil, err } diff --git a/cl/beacon/handler/duties_attester.go b/cl/beacon/handler/duties_attester.go index 31040bdbab2..fcf24ff7f6c 100644 --- a/cl/beacon/handler/duties_attester.go +++ b/cl/beacon/handler/duties_attester.go @@ -194,7 +194,8 @@ func (a *ApiHandler) getAttesterDuties(w http.ResponseWriter, r *http.Request) ( if _, ok := idxSet[int(idx)]; !ok { continue } - publicKey, err := state_accessors.ReadPublicKeyByIndex(tx, idx) + + publicKey, err := a.syncedData.ValidatorPublicKeyByIndex(int(idx)) if err != nil { return nil, err } diff --git a/cl/beacon/handler/duties_proposer.go b/cl/beacon/handler/duties_proposer.go index 24c3399d6a9..4aefcd81186 100644 --- a/cl/beacon/handler/duties_proposer.go +++ b/cl/beacon/handler/duties_proposer.go @@ -67,7 +67,7 @@ func (a *ApiHandler) getDutiesProposer(w http.ResponseWriter, r *http.Request) ( duties := make([]proposerDuties, len(indicies)) for i, validatorIndex := range indicies { var pk libcommon.Bytes48 - pk, err := state_accessors.ReadPublicKeyByIndex(tx, validatorIndex) + pk, err := a.syncedData.ValidatorPublicKeyByIndex(int(validatorIndex)) if err != nil { return nil, err } diff --git a/cl/beacon/handler/duties_sync.go b/cl/beacon/handler/duties_sync.go index bc4e7cc082a..9a6443d978a 100644 --- a/cl/beacon/handler/duties_sync.go +++ b/cl/beacon/handler/duties_sync.go @@ -103,7 +103,7 @@ func (a *ApiHandler) getSyncDuties(w http.ResponseWriter, r *http.Request) (*bea // Now we have the sync committee, we can initialize our response set dutiesSet := map[uint64]*syncDutyResponse{} for _, idx := range idxs { - publicKey, err := state_accessors.ReadPublicKeyByIndex(tx, idx) + publicKey, err := a.syncedData.ValidatorPublicKeyByIndex(int(idx)) if err != nil { return nil, err } @@ -117,12 +117,9 @@ func (a *ApiHandler) getSyncDuties(w http.ResponseWriter, r *http.Request) (*bea } // Now we can iterate over the sync committee and fill the response for idx, committeeParticipantPublicKey := range syncCommittee.GetCommittee() { - committeeParticipantIndex, ok, err := state_accessors.ReadValidatorIndexByPublicKey(tx, committeeParticipantPublicKey) + committeeParticipantIndex, _, err := a.syncedData.ValidatorIndexByPublicKey(committeeParticipantPublicKey) if err != nil { - return nil, err - } - if !ok { - return nil, beaconhttp.NewEndpointError(http.StatusNotFound, fmt.Errorf("could not find validator with public key %x", committeeParticipantPublicKey)) + return nil, beaconhttp.NewEndpointError(http.StatusNotFound, fmt.Errorf("could not find validator with public key %x: %s", committeeParticipantPublicKey, err)) } if _, ok := dutiesSet[committeeParticipantIndex]; !ok { continue diff --git a/cl/beacon/handler/lighthouse.go b/cl/beacon/handler/lighthouse.go index f2e978f5e56..4a6dc1a7f6f 100644 --- a/cl/beacon/handler/lighthouse.go +++ b/cl/beacon/handler/lighthouse.go @@ -228,7 +228,7 @@ func (a *ApiHandler) GetLighthouseValidatorInclusion(w http.ResponseWriter, r *h return nil, beaconhttp.NewEndpointError(http.StatusBadRequest, err) } - validatorIndex, err := parseQueryValidatorIndex(tx, validatorId) + validatorIndex, err := parseQueryValidatorIndex(a.syncedData, validatorId) if err != nil { return nil, err } diff --git a/cl/beacon/handler/rewards.go b/cl/beacon/handler/rewards.go index 6a302207020..dbfe400027c 100644 --- a/cl/beacon/handler/rewards.go +++ b/cl/beacon/handler/rewards.go @@ -19,6 +19,7 @@ package handler import ( "encoding/json" "errors" + "fmt" "io" "net/http" "sort" @@ -128,7 +129,7 @@ func (a *ApiHandler) PostEthV1BeaconRewardsSyncCommittees(w http.ResponseWriter, return nil, beaconhttp.NewEndpointError(http.StatusBadRequest, err) } } - filterIndicies, err := parseQueryValidatorIndicies(tx, req) + filterIndicies, err := parseQueryValidatorIndicies(a.syncedData, req) if err != nil { return nil, err } @@ -217,12 +218,9 @@ func (a *ApiHandler) PostEthV1BeaconRewardsSyncCommittees(w http.ResponseWriter, participantReward := int64(a.syncParticipantReward(totalActiveBalance)) for committeeIdx, v := range committee { - idx, ok, err := state_accessors.ReadValidatorIndexByPublicKey(tx, v) + idx, _, err := a.syncedData.ValidatorIndexByPublicKey(v) if err != nil { - return nil, err - } - if !ok { - return nil, beaconhttp.NewEndpointError(http.StatusNotFound, errors.New("sync committee public key not found")) + return nil, beaconhttp.NewEndpointError(http.StatusNotFound, fmt.Errorf("sync committee public key not found: %s", err)) } if len(filterIndiciesSet) > 0 { if _, ok := filterIndiciesSet[idx]; !ok { diff --git a/cl/beacon/handler/rewards_test.go b/cl/beacon/handler/rewards_test.go index 07bc6bbe769..3dc8d78b85c 100644 --- a/cl/beacon/handler/rewards_test.go +++ b/cl/beacon/handler/rewards_test.go @@ -89,7 +89,7 @@ func TestGetBlockRewards(t *testing.T) { } func TestPostSyncCommitteeRewards(t *testing.T) { - _, blocks, _, _, _, handler, _, _, fcu, _ := setupTestingHandler(t, clparams.BellatrixVersion, log.Root(), false) + _, blocks, _, _, _, handler, _, _, fcu, _ := setupTestingHandler(t, clparams.BellatrixVersion, log.Root(), true) var err error fcu.HeadVal, err = blocks[len(blocks)-1].Block.HashSSZ() require.NoError(t, err) diff --git a/cl/beacon/handler/states.go b/cl/beacon/handler/states.go index e781433c74a..b63deedd626 100644 --- a/cl/beacon/handler/states.go +++ b/cl/beacon/handler/states.go @@ -365,12 +365,9 @@ func (a *ApiHandler) getSyncCommittees(w http.ResponseWriter, r *http.Request) ( } for i, publicKey := range committee { // get the validator index of the committee - validatorIndex, ok, err := state_accessors.ReadValidatorIndexByPublicKey(tx, publicKey) + validatorIndex, _, err := a.syncedData.ValidatorIndexByPublicKey(publicKey) if err != nil { - return nil, err - } - if !ok { - return nil, fmt.Errorf("could not read validator index: %x", publicKey) + return nil, fmt.Errorf("could not read validator index: %x. %s", publicKey, err) } idx := strconv.FormatInt(int64(validatorIndex), 10) response.Validators[i] = idx diff --git a/cl/beacon/handler/states_test.go b/cl/beacon/handler/states_test.go index 5222c291fa0..42eaa00dba7 100644 --- a/cl/beacon/handler/states_test.go +++ b/cl/beacon/handler/states_test.go @@ -320,7 +320,7 @@ func TestGetStateFullForkchoice(t *testing.T) { func TestGetStateSyncCommittees(t *testing.T) { // setupTestingHandler(t, clparams.Phase0Version) - _, blocks, _, _, postState, handler, _, _, fcu, _ := setupTestingHandler(t, clparams.BellatrixVersion, log.Root(), false) + _, blocks, _, _, postState, handler, _, _, fcu, _ := setupTestingHandler(t, clparams.BellatrixVersion, log.Root(), true) postRoot, err := postState.HashSSZ() require.NoError(t, err) @@ -385,7 +385,7 @@ func TestGetStateSyncCommittees(t *testing.T) { func TestGetStateSyncCommitteesHistorical(t *testing.T) { // setupTestingHandler(t, clparams.Phase0Version) - _, blocks, _, _, postState, handler, _, _, fcu, _ := setupTestingHandler(t, clparams.BellatrixVersion, log.Root(), false) + _, blocks, _, _, postState, handler, _, _, fcu, _ := setupTestingHandler(t, clparams.BellatrixVersion, log.Root(), true) postRoot, err := postState.HashSSZ() require.NoError(t, err) diff --git a/cl/beacon/handler/utils_test.go b/cl/beacon/handler/utils_test.go index 5b3c57b2d79..16e403388c0 100644 --- a/cl/beacon/handler/utils_test.go +++ b/cl/beacon/handler/utils_test.go @@ -69,27 +69,27 @@ func setupTestingHandler(t *testing.T, v clparams.StateVersion, logger log.Logge fcu = mock_services2.NewForkChoiceStorageMock(t) db = memdb.NewTestDB(t, kv.ChainDB) blobDb := memdb.NewTestDB(t, kv.ChainDB) - var reader *tests.MockBlockReader - reader = tests.LoadChain(blocks, postState, db, t) + reader := tests.LoadChain(blocks, postState, db, t) firstBlockRoot, _ := blocks[0].Block.HashSSZ() firstBlockHeader := blocks[0].SignedBeaconBlockHeader() bcfg.InitializeForkSchedule() + if useRealSyncDataMgr { + syncedData = synced_data.NewSyncedDataManager(&bcfg, true) + syncedData.OnHeadState(postState) + } else { + syncedData = sync_mock_services.NewMockSyncedData(ctrl) + } ctx := context.Background() vt := state_accessors.NewStaticValidatorTable() - a := antiquary.NewAntiquary(ctx, nil, preState, vt, &bcfg, datadir.New("/tmp"), nil, db, nil, nil, reader, logger, true, true, false, false, nil) + a := antiquary.NewAntiquary(ctx, nil, preState, vt, &bcfg, datadir.New("/tmp"), nil, db, nil, nil, reader, syncedData, logger, true, true, false, false, nil) require.NoError(t, a.IncrementBeaconState(ctx, blocks[len(blocks)-1].Block.Slot+33)) // historical states reader below - statesReader := historical_states_reader.NewHistoricalStatesReader(&bcfg, reader, vt, preState, nil) + statesReader := historical_states_reader.NewHistoricalStatesReader(&bcfg, reader, vt, preState, nil, syncedData) opPool = pool.NewOperationsPool(&bcfg) fcu.Pool = opPool - if useRealSyncDataMgr { - syncedData = synced_data.NewSyncedDataManager(&bcfg, true) - } else { - syncedData = sync_mock_services.NewMockSyncedData(ctrl) - } genesis, err := initial_state.GetGenesisState(clparams.MainnetNetwork) require.NoError(t, err) ethClock := eth_clock.NewEthereumClock(genesis.GenesisTime(), genesis.GenesisValidatorsRoot(), &bcfg) diff --git a/cl/beacon/handler/validators.go b/cl/beacon/handler/validators.go index e9952d006f1..c30134e356d 100644 --- a/cl/beacon/handler/validators.go +++ b/cl/beacon/handler/validators.go @@ -35,6 +35,7 @@ import ( "github.com/erigontech/erigon-lib/kv" "github.com/erigontech/erigon-lib/log/v3" "github.com/erigontech/erigon/cl/beacon/beaconhttp" + "github.com/erigontech/erigon/cl/beacon/synced_data" "github.com/erigontech/erigon/cl/cltypes/solid" "github.com/erigontech/erigon/cl/persistence/beacon_indicies" state_accessors "github.com/erigontech/erigon/cl/persistence/state" @@ -305,7 +306,7 @@ func (a *ApiHandler) writeValidatorsResponse( queryFilters []string, ) { isOptimistic := a.forkchoiceStore.IsRootOptimistic(blockRoot) - filterIndicies, err := parseQueryValidatorIndicies(tx, validatorIds) + filterIndicies, err := parseQueryValidatorIndicies(a.syncedData, validatorIds) if err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return @@ -381,7 +382,7 @@ func (a *ApiHandler) writeValidatorsResponse( responseValidators(w, filterIndicies, statusFilters, stateEpoch, balances, validators, *slot <= a.forkchoiceStore.FinalizedSlot(), isOptimistic) } -func parseQueryValidatorIndex(tx kv.Tx, id string) (uint64, error) { +func parseQueryValidatorIndex(syncedData synced_data.SyncedData, id string) (uint64, error) { isPublicKey, err := checkValidValidatorId(id) if err != nil { return 0, err @@ -391,20 +392,13 @@ func parseQueryValidatorIndex(tx kv.Tx, id string) (uint64, error) { if err := b48.UnmarshalText([]byte(id)); err != nil { return 0, beaconhttp.NewEndpointError(http.StatusBadRequest, err) } - has, err := tx.Has(kv.InvertedValidatorPublicKeys, b48[:]) + idx, has, err := syncedData.ValidatorIndexByPublicKey(b48) if err != nil { - return 0, err + return 0, beaconhttp.NewEndpointError(http.StatusNotFound, fmt.Errorf("validator not found: %s", err)) } if !has { return math.MaxUint64, nil } - idx, ok, err := state_accessors.ReadValidatorIndexByPublicKey(tx, b48) - if err != nil { - return 0, err - } - if !ok { - return 0, beaconhttp.NewEndpointError(http.StatusNotFound, errors.New("validator not found")) - } return idx, nil } idx, err := strconv.ParseUint(id, 10, 64) @@ -415,11 +409,11 @@ func parseQueryValidatorIndex(tx kv.Tx, id string) (uint64, error) { } -func parseQueryValidatorIndicies(tx kv.Tx, ids []string) ([]uint64, error) { +func parseQueryValidatorIndicies(syncedData synced_data.SyncedData, ids []string) ([]uint64, error) { filterIndicies := make([]uint64, 0, len(ids)) for _, id := range ids { - idx, err := parseQueryValidatorIndex(tx, id) + idx, err := parseQueryValidatorIndex(syncedData, id) if err != nil { return nil, err } @@ -454,7 +448,7 @@ func (a *ApiHandler) GetEthV1BeaconStatesValidator(w http.ResponseWriter, r *htt return nil, beaconhttp.NewEndpointError(http.StatusBadRequest, err) } - validatorIndex, err := parseQueryValidatorIndex(tx, validatorId) + validatorIndex, err := parseQueryValidatorIndex(a.syncedData, validatorId) if err != nil { return nil, err } @@ -585,7 +579,7 @@ func (a *ApiHandler) getValidatorBalances(ctx context.Context, w http.ResponseWr return } - filterIndicies, err := parseQueryValidatorIndicies(tx, validatorIds) + filterIndicies, err := parseQueryValidatorIndicies(a.syncedData, validatorIds) if err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return diff --git a/cl/beacon/synced_data/interface.go b/cl/beacon/synced_data/interface.go index 0cb84905d2a..304ac4be2a7 100644 --- a/cl/beacon/synced_data/interface.go +++ b/cl/beacon/synced_data/interface.go @@ -18,6 +18,7 @@ package synced_data import ( "github.com/erigontech/erigon-lib/common" + "github.com/erigontech/erigon/cl/cltypes" "github.com/erigontech/erigon/cl/phase1/core/state" ) @@ -33,4 +34,8 @@ type SyncedData interface { HeadSlot() uint64 HeadRoot() common.Hash CommitteeCount(epoch uint64) uint64 + ValidatorPublicKeyByIndex(index int) (common.Bytes48, error) + ValidatorIndexByPublicKey(pubkey common.Bytes48) (uint64, bool, error) + HistoricalRootElementAtIndex(index int) (common.Hash, error) + HistoricalSummaryElementAtIndex(index int) (*cltypes.HistoricalSummary, error) } diff --git a/cl/beacon/synced_data/mock_services/synced_data_mock.go b/cl/beacon/synced_data/mock_services/synced_data_mock.go index 5a37152a15b..6eebd97dbf0 100644 --- a/cl/beacon/synced_data/mock_services/synced_data_mock.go +++ b/cl/beacon/synced_data/mock_services/synced_data_mock.go @@ -14,6 +14,7 @@ import ( common "github.com/erigontech/erigon-lib/common" synced_data "github.com/erigontech/erigon/cl/beacon/synced_data" + cltypes "github.com/erigontech/erigon/cl/cltypes" state "github.com/erigontech/erigon/cl/phase1/core/state" gomock "go.uber.org/mock/gomock" ) @@ -22,7 +23,6 @@ import ( type MockSyncedData struct { ctrl *gomock.Controller recorder *MockSyncedDataMockRecorder - isgomock struct{} } // MockSyncedDataMockRecorder is the mock recorder for MockSyncedData. @@ -43,17 +43,17 @@ func (m *MockSyncedData) EXPECT() *MockSyncedDataMockRecorder { } // CommitteeCount mocks base method. -func (m *MockSyncedData) CommitteeCount(epoch uint64) uint64 { +func (m *MockSyncedData) CommitteeCount(arg0 uint64) uint64 { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "CommitteeCount", epoch) + ret := m.ctrl.Call(m, "CommitteeCount", arg0) ret0, _ := ret[0].(uint64) return ret0 } // CommitteeCount indicates an expected call of CommitteeCount. -func (mr *MockSyncedDataMockRecorder) CommitteeCount(epoch any) *MockSyncedDataCommitteeCountCall { +func (mr *MockSyncedDataMockRecorder) CommitteeCount(arg0 any) *MockSyncedDataCommitteeCountCall { mr.mock.ctrl.T.Helper() - call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CommitteeCount", reflect.TypeOf((*MockSyncedData)(nil).CommitteeCount), epoch) + call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CommitteeCount", reflect.TypeOf((*MockSyncedData)(nil).CommitteeCount), arg0) return &MockSyncedDataCommitteeCountCall{Call: call} } @@ -156,18 +156,96 @@ func (c *MockSyncedDataHeadSlotCall) DoAndReturn(f func() uint64) *MockSyncedDat return c } +// HistoricalRootElementAtIndex mocks base method. +func (m *MockSyncedData) HistoricalRootElementAtIndex(arg0 int) (common.Hash, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "HistoricalRootElementAtIndex", arg0) + ret0, _ := ret[0].(common.Hash) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// HistoricalRootElementAtIndex indicates an expected call of HistoricalRootElementAtIndex. +func (mr *MockSyncedDataMockRecorder) HistoricalRootElementAtIndex(arg0 any) *MockSyncedDataHistoricalRootElementAtIndexCall { + mr.mock.ctrl.T.Helper() + call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HistoricalRootElementAtIndex", reflect.TypeOf((*MockSyncedData)(nil).HistoricalRootElementAtIndex), arg0) + return &MockSyncedDataHistoricalRootElementAtIndexCall{Call: call} +} + +// MockSyncedDataHistoricalRootElementAtIndexCall wrap *gomock.Call +type MockSyncedDataHistoricalRootElementAtIndexCall struct { + *gomock.Call +} + +// Return rewrite *gomock.Call.Return +func (c *MockSyncedDataHistoricalRootElementAtIndexCall) Return(arg0 common.Hash, arg1 error) *MockSyncedDataHistoricalRootElementAtIndexCall { + c.Call = c.Call.Return(arg0, arg1) + return c +} + +// Do rewrite *gomock.Call.Do +func (c *MockSyncedDataHistoricalRootElementAtIndexCall) Do(f func(int) (common.Hash, error)) *MockSyncedDataHistoricalRootElementAtIndexCall { + c.Call = c.Call.Do(f) + return c +} + +// DoAndReturn rewrite *gomock.Call.DoAndReturn +func (c *MockSyncedDataHistoricalRootElementAtIndexCall) DoAndReturn(f func(int) (common.Hash, error)) *MockSyncedDataHistoricalRootElementAtIndexCall { + c.Call = c.Call.DoAndReturn(f) + return c +} + +// HistoricalSummaryElementAtIndex mocks base method. +func (m *MockSyncedData) HistoricalSummaryElementAtIndex(arg0 int) (*cltypes.HistoricalSummary, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "HistoricalSummaryElementAtIndex", arg0) + ret0, _ := ret[0].(*cltypes.HistoricalSummary) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// HistoricalSummaryElementAtIndex indicates an expected call of HistoricalSummaryElementAtIndex. +func (mr *MockSyncedDataMockRecorder) HistoricalSummaryElementAtIndex(arg0 any) *MockSyncedDataHistoricalSummaryElementAtIndexCall { + mr.mock.ctrl.T.Helper() + call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HistoricalSummaryElementAtIndex", reflect.TypeOf((*MockSyncedData)(nil).HistoricalSummaryElementAtIndex), arg0) + return &MockSyncedDataHistoricalSummaryElementAtIndexCall{Call: call} +} + +// MockSyncedDataHistoricalSummaryElementAtIndexCall wrap *gomock.Call +type MockSyncedDataHistoricalSummaryElementAtIndexCall struct { + *gomock.Call +} + +// Return rewrite *gomock.Call.Return +func (c *MockSyncedDataHistoricalSummaryElementAtIndexCall) Return(arg0 *cltypes.HistoricalSummary, arg1 error) *MockSyncedDataHistoricalSummaryElementAtIndexCall { + c.Call = c.Call.Return(arg0, arg1) + return c +} + +// Do rewrite *gomock.Call.Do +func (c *MockSyncedDataHistoricalSummaryElementAtIndexCall) Do(f func(int) (*cltypes.HistoricalSummary, error)) *MockSyncedDataHistoricalSummaryElementAtIndexCall { + c.Call = c.Call.Do(f) + return c +} + +// DoAndReturn rewrite *gomock.Call.DoAndReturn +func (c *MockSyncedDataHistoricalSummaryElementAtIndexCall) DoAndReturn(f func(int) (*cltypes.HistoricalSummary, error)) *MockSyncedDataHistoricalSummaryElementAtIndexCall { + c.Call = c.Call.DoAndReturn(f) + return c +} + // OnHeadState mocks base method. -func (m *MockSyncedData) OnHeadState(newState *state.CachingBeaconState) error { +func (m *MockSyncedData) OnHeadState(arg0 *state.CachingBeaconState) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "OnHeadState", newState) + ret := m.ctrl.Call(m, "OnHeadState", arg0) ret0, _ := ret[0].(error) return ret0 } // OnHeadState indicates an expected call of OnHeadState. -func (mr *MockSyncedDataMockRecorder) OnHeadState(newState any) *MockSyncedDataOnHeadStateCall { +func (mr *MockSyncedDataMockRecorder) OnHeadState(arg0 any) *MockSyncedDataOnHeadStateCall { mr.mock.ctrl.T.Helper() - call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "OnHeadState", reflect.TypeOf((*MockSyncedData)(nil).OnHeadState), newState) + call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "OnHeadState", reflect.TypeOf((*MockSyncedData)(nil).OnHeadState), arg0) return &MockSyncedDataOnHeadStateCall{Call: call} } @@ -268,18 +346,97 @@ func (c *MockSyncedDataUnsetHeadStateCall) DoAndReturn(f func()) *MockSyncedData return c } +// ValidatorIndexByPublicKey mocks base method. +func (m *MockSyncedData) ValidatorIndexByPublicKey(arg0 common.Bytes48) (uint64, bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ValidatorIndexByPublicKey", arg0) + ret0, _ := ret[0].(uint64) + ret1, _ := ret[1].(bool) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 +} + +// ValidatorIndexByPublicKey indicates an expected call of ValidatorIndexByPublicKey. +func (mr *MockSyncedDataMockRecorder) ValidatorIndexByPublicKey(arg0 any) *MockSyncedDataValidatorIndexByPublicKeyCall { + mr.mock.ctrl.T.Helper() + call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ValidatorIndexByPublicKey", reflect.TypeOf((*MockSyncedData)(nil).ValidatorIndexByPublicKey), arg0) + return &MockSyncedDataValidatorIndexByPublicKeyCall{Call: call} +} + +// MockSyncedDataValidatorIndexByPublicKeyCall wrap *gomock.Call +type MockSyncedDataValidatorIndexByPublicKeyCall struct { + *gomock.Call +} + +// Return rewrite *gomock.Call.Return +func (c *MockSyncedDataValidatorIndexByPublicKeyCall) Return(arg0 uint64, arg1 bool, arg2 error) *MockSyncedDataValidatorIndexByPublicKeyCall { + c.Call = c.Call.Return(arg0, arg1, arg2) + return c +} + +// Do rewrite *gomock.Call.Do +func (c *MockSyncedDataValidatorIndexByPublicKeyCall) Do(f func(common.Bytes48) (uint64, bool, error)) *MockSyncedDataValidatorIndexByPublicKeyCall { + c.Call = c.Call.Do(f) + return c +} + +// DoAndReturn rewrite *gomock.Call.DoAndReturn +func (c *MockSyncedDataValidatorIndexByPublicKeyCall) DoAndReturn(f func(common.Bytes48) (uint64, bool, error)) *MockSyncedDataValidatorIndexByPublicKeyCall { + c.Call = c.Call.DoAndReturn(f) + return c +} + +// ValidatorPublicKeyByIndex mocks base method. +func (m *MockSyncedData) ValidatorPublicKeyByIndex(arg0 int) (common.Bytes48, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ValidatorPublicKeyByIndex", arg0) + ret0, _ := ret[0].(common.Bytes48) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ValidatorPublicKeyByIndex indicates an expected call of ValidatorPublicKeyByIndex. +func (mr *MockSyncedDataMockRecorder) ValidatorPublicKeyByIndex(arg0 any) *MockSyncedDataValidatorPublicKeyByIndexCall { + mr.mock.ctrl.T.Helper() + call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ValidatorPublicKeyByIndex", reflect.TypeOf((*MockSyncedData)(nil).ValidatorPublicKeyByIndex), arg0) + return &MockSyncedDataValidatorPublicKeyByIndexCall{Call: call} +} + +// MockSyncedDataValidatorPublicKeyByIndexCall wrap *gomock.Call +type MockSyncedDataValidatorPublicKeyByIndexCall struct { + *gomock.Call +} + +// Return rewrite *gomock.Call.Return +func (c *MockSyncedDataValidatorPublicKeyByIndexCall) Return(arg0 common.Bytes48, arg1 error) *MockSyncedDataValidatorPublicKeyByIndexCall { + c.Call = c.Call.Return(arg0, arg1) + return c +} + +// Do rewrite *gomock.Call.Do +func (c *MockSyncedDataValidatorPublicKeyByIndexCall) Do(f func(int) (common.Bytes48, error)) *MockSyncedDataValidatorPublicKeyByIndexCall { + c.Call = c.Call.Do(f) + return c +} + +// DoAndReturn rewrite *gomock.Call.DoAndReturn +func (c *MockSyncedDataValidatorPublicKeyByIndexCall) DoAndReturn(f func(int) (common.Bytes48, error)) *MockSyncedDataValidatorPublicKeyByIndexCall { + c.Call = c.Call.DoAndReturn(f) + return c +} + // ViewHeadState mocks base method. -func (m *MockSyncedData) ViewHeadState(fn synced_data.ViewHeadStateFn) error { +func (m *MockSyncedData) ViewHeadState(arg0 synced_data.ViewHeadStateFn) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ViewHeadState", fn) + ret := m.ctrl.Call(m, "ViewHeadState", arg0) ret0, _ := ret[0].(error) return ret0 } // ViewHeadState indicates an expected call of ViewHeadState. -func (mr *MockSyncedDataMockRecorder) ViewHeadState(fn any) *MockSyncedDataViewHeadStateCall { +func (mr *MockSyncedDataMockRecorder) ViewHeadState(arg0 any) *MockSyncedDataViewHeadStateCall { mr.mock.ctrl.T.Helper() - call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ViewHeadState", reflect.TypeOf((*MockSyncedData)(nil).ViewHeadState), fn) + call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ViewHeadState", reflect.TypeOf((*MockSyncedData)(nil).ViewHeadState), arg0) return &MockSyncedDataViewHeadStateCall{Call: call} } diff --git a/cl/beacon/synced_data/synced_data.go b/cl/beacon/synced_data/synced_data.go index ec24524eb8f..ef79ac49194 100644 --- a/cl/beacon/synced_data/synced_data.go +++ b/cl/beacon/synced_data/synced_data.go @@ -26,6 +26,7 @@ import ( "github.com/erigontech/erigon-lib/common" "github.com/erigontech/erigon-lib/common/dbg" "github.com/erigontech/erigon/cl/clparams" + "github.com/erigontech/erigon/cl/cltypes" "github.com/erigontech/erigon/cl/phase1/core/state" ) @@ -44,6 +45,8 @@ type SyncedDataManager struct { headState *state.CachingBeaconState + accessLock sync.RWMutex // lock used for accessing atomic methods + mu sync.RWMutex } @@ -61,6 +64,8 @@ func (s *SyncedDataManager) OnHeadState(newState *state.CachingBeaconState) (err s.mu.Lock() defer s.mu.Unlock() + s.accessLock.Lock() + defer s.accessLock.Unlock() var blkRoot common.Hash @@ -137,7 +142,54 @@ func (s *SyncedDataManager) CommitteeCount(epoch uint64) uint64 { func (s *SyncedDataManager) UnsetHeadState() { s.mu.Lock() defer s.mu.Unlock() + s.accessLock.Lock() + defer s.accessLock.Unlock() s.headRoot = atomic.Value{} s.headSlot.Store(uint64(0)) s.headState = nil } + +func (s *SyncedDataManager) ValidatorPublicKeyByIndex(index int) (common.Bytes48, error) { + s.accessLock.RLock() + defer s.accessLock.RUnlock() + if s.headState == nil { + return common.Bytes48{}, ErrNotSynced + } + return s.headState.ValidatorPublicKey(index) +} + +func (s *SyncedDataManager) ValidatorIndexByPublicKey(pubkey common.Bytes48) (uint64, bool, error) { + s.accessLock.RLock() + defer s.accessLock.RUnlock() + if s.headState == nil { + return 0, false, ErrNotSynced + } + ret, found := s.headState.ValidatorIndexByPubkey(pubkey) + return ret, found, nil +} + +func (s *SyncedDataManager) HistoricalRootElementAtIndex(index int) (common.Hash, error) { + s.accessLock.RLock() + defer s.accessLock.RUnlock() + if s.headState == nil { + return common.Hash{}, ErrNotSynced + } + if s.headState.HistoricalRootsLength() <= uint64(index) { + return common.Hash{}, errors.New("HistoricalRootElementAtIndex: index out of range") + } + + return s.headState.HistoricalRoot(index), nil +} + +func (s *SyncedDataManager) HistoricalSummaryElementAtIndex(index int) (*cltypes.HistoricalSummary, error) { + s.accessLock.RLock() + defer s.accessLock.RUnlock() + if s.headState == nil { + return nil, ErrNotSynced + } + if s.headState.HistoricalSummariesLength() <= uint64(index) { + return nil, errors.New("HistoricalSummaryElementAtIndex: index out of range") + } + + return s.headState.HistoricalSummary(index), nil +} diff --git a/cl/persistence/state/historical_states_reader/historical_states_reader.go b/cl/persistence/state/historical_states_reader/historical_states_reader.go index 7f6b9821b84..d2e7d3ba268 100644 --- a/cl/persistence/state/historical_states_reader/historical_states_reader.go +++ b/cl/persistence/state/historical_states_reader/historical_states_reader.go @@ -28,6 +28,7 @@ import ( "github.com/erigontech/erigon-lib/common" "github.com/erigontech/erigon-lib/kv" "github.com/erigontech/erigon-lib/log/v3" + "github.com/erigontech/erigon/cl/beacon/synced_data" "github.com/erigontech/erigon/cl/clparams" "github.com/erigontech/erigon/cl/cltypes" "github.com/erigontech/erigon/cl/cltypes/solid" @@ -50,6 +51,7 @@ type HistoricalStatesReader struct { blockReader freezeblocks.BeaconSnapshotReader stateSn *snapshotsync.CaplinStateSnapshots genesisState *state.CachingBeaconState + syncedData synced_data.SyncedData shuffledIndiciesCache *lru.CacheWithTTL[uint64, []uint64] } @@ -58,7 +60,8 @@ func NewHistoricalStatesReader( cfg *clparams.BeaconChainConfig, blockReader freezeblocks.BeaconSnapshotReader, validatorTable *state_accessors.StaticValidatorTable, - genesisState *state.CachingBeaconState, stateSn *snapshotsync.CaplinStateSnapshots) *HistoricalStatesReader { + genesisState *state.CachingBeaconState, stateSn *snapshotsync.CaplinStateSnapshots, + syncedData synced_data.SyncedData) *HistoricalStatesReader { shuffledIndiciesCache := lru.NewWithTTL[uint64, []uint64]("shuffledIndiciesCacheReader", 64, 2*time.Minute) return &HistoricalStatesReader{ @@ -68,6 +71,7 @@ func NewHistoricalStatesReader( validatorTable: validatorTable, stateSn: stateSn, shuffledIndiciesCache: shuffledIndiciesCache, + syncedData: syncedData, } } @@ -150,12 +154,14 @@ func (r *HistoricalStatesReader) ReadHistoricalState(ctx context.Context, tx kv. ret.SetStateRoots(stateRoots) historicalRoots := solid.NewHashList(int(r.cfg.HistoricalRootsLimit)) - if err := state_accessors.ReadHistoricalRoots(tx, epochData.HistoricalRootsLength, func(idx int, root common.Hash) error { - historicalRoots.Append(root) - return nil - }); err != nil { - return nil, fmt.Errorf("failed to read historical roots: %w", err) + for i := 0; i < int(epochData.HistoricalRootsLength); i++ { + historicalRoot, err := r.syncedData.HistoricalRootElementAtIndex(i) + if err != nil { + return nil, fmt.Errorf("failed to read historical root at index %d: %w", i, err) + } + historicalRoots.Append(historicalRoot) } + ret.SetHistoricalRoots(historicalRoots) // Eth1 @@ -277,11 +283,13 @@ func (r *HistoricalStatesReader) ReadHistoricalState(ctx context.Context, tx kv. ret.SetNextWithdrawalValidatorIndex(slotData.NextWithdrawalValidatorIndex) // Deep history valid from Capella onwards historicalSummaries := solid.NewStaticListSSZ[*cltypes.HistoricalSummary](int(r.cfg.HistoricalRootsLimit), 64) - if err := state_accessors.ReadHistoricalSummaries(tx, epochData.HistoricalSummariesLength, func(idx int, historicalSummary *cltypes.HistoricalSummary) error { + + for i := 0; i < int(epochData.HistoricalSummariesLength); i++ { + historicalSummary, err := r.syncedData.HistoricalSummaryElementAtIndex(i) + if err != nil { + return nil, fmt.Errorf("failed to read historical summary at index %d: %w", i, err) + } historicalSummaries.Append(historicalSummary) - return nil - }); err != nil { - return nil, fmt.Errorf("failed to read historical summaries: %w", err) } ret.SetHistoricalSummaries(historicalSummaries) return ret, nil diff --git a/cl/persistence/state/historical_states_reader/historical_states_reader_test.go b/cl/persistence/state/historical_states_reader/historical_states_reader_test.go index 5a2052a546c..7d21448db2b 100644 --- a/cl/persistence/state/historical_states_reader/historical_states_reader_test.go +++ b/cl/persistence/state/historical_states_reader/historical_states_reader_test.go @@ -29,6 +29,7 @@ import ( "github.com/erigontech/erigon-lib/log/v3" "github.com/erigontech/erigon/cl/antiquary" "github.com/erigontech/erigon/cl/antiquary/tests" + "github.com/erigontech/erigon/cl/beacon/synced_data" "github.com/erigontech/erigon/cl/clparams" "github.com/erigontech/erigon/cl/cltypes" state_accessors "github.com/erigontech/erigon/cl/persistence/state" @@ -40,9 +41,11 @@ func runTest(t *testing.T, blocks []*cltypes.SignedBeaconBlock, preState, postSt db := memdb.NewTestDB(t, kv.ChainDB) reader := tests.LoadChain(blocks, postState, db, t) + sn := synced_data.NewSyncedDataManager(&clparams.MainnetBeaconConfig, true) + sn.OnHeadState(postState) ctx := context.Background() vt := state_accessors.NewStaticValidatorTable() - a := antiquary.NewAntiquary(ctx, nil, preState, vt, &clparams.MainnetBeaconConfig, datadir.New("/tmp"), nil, db, nil, nil, reader, log.New(), true, true, true, false, nil) + a := antiquary.NewAntiquary(ctx, nil, preState, vt, &clparams.MainnetBeaconConfig, datadir.New("/tmp"), nil, db, nil, nil, reader, sn, log.New(), true, true, true, false, nil) require.NoError(t, a.IncrementBeaconState(ctx, blocks[len(blocks)-1].Block.Slot+33)) // Now lets test it against the reader tx, err := db.BeginRw(ctx) @@ -51,7 +54,7 @@ func runTest(t *testing.T, blocks []*cltypes.SignedBeaconBlock, preState, postSt vt = state_accessors.NewStaticValidatorTable() require.NoError(t, state_accessors.ReadValidatorsTable(tx, vt)) - hr := historical_states_reader.NewHistoricalStatesReader(&clparams.MainnetBeaconConfig, reader, vt, preState, nil) + hr := historical_states_reader.NewHistoricalStatesReader(&clparams.MainnetBeaconConfig, reader, vt, preState, nil, sn) s, err := hr.ReadHistoricalState(ctx, tx, blocks[len(blocks)-1].Block.Slot) require.NoError(t, err) diff --git a/cl/persistence/state/state_accessors.go b/cl/persistence/state/state_accessors.go index 6292484e518..a34fd1645e2 100644 --- a/cl/persistence/state/state_accessors.go +++ b/cl/persistence/state/state_accessors.go @@ -21,13 +21,9 @@ import ( "encoding/binary" "github.com/erigontech/erigon-lib/kv" - "github.com/erigontech/erigon/cl/cltypes" "github.com/erigontech/erigon/cl/cltypes/solid" "github.com/erigontech/erigon/cl/persistence/base_encoding" - "github.com/erigontech/erigon/cl/phase1/core/state" "github.com/erigontech/erigon/turbo/snapshotsync" - - libcommon "github.com/erigontech/erigon-lib/common" ) type GetValFn func(table string, key []byte) ([]byte, error) @@ -45,137 +41,6 @@ func GetValFnTxAndSnapshot(tx kv.Tx, snapshotRoTx *snapshotsync.CaplinStateView) } } -// InitializeValidatorTable initializes the validator table in the database. -func InitializeStaticTables(tx kv.RwTx, state *state.CachingBeaconState) error { - var err error - if err = tx.ClearBucket(kv.ValidatorPublicKeys); err != nil { - return err - } - if err = tx.ClearBucket(kv.HistoricalRoots); err != nil { - return err - } - if err = tx.ClearBucket(kv.HistoricalSummaries); err != nil { - return err - } - state.ForEachValidator(func(v solid.Validator, idx, total int) bool { - key := base_encoding.Encode64ToBytes4(uint64(idx)) - if err = tx.Append(kv.ValidatorPublicKeys, key, v.PublicKeyBytes()); err != nil { - return false - } - if err = tx.Put(kv.InvertedValidatorPublicKeys, v.PublicKeyBytes(), key); err != nil { - return false - } - return true - }) - if err != nil { - return err - } - for i := 0; i < int(state.HistoricalRootsLength()); i++ { - key := base_encoding.Encode64ToBytes4(uint64(i)) - root := state.HistoricalRoot(i) - if err = tx.Append(kv.HistoricalRoots, key, root[:]); err != nil { - return err - } - } - var temp []byte - for i := 0; i < int(state.HistoricalSummariesLength()); i++ { - temp = temp[:0] - key := base_encoding.Encode64ToBytes4(uint64(i)) - summary := state.HistoricalSummary(i) - temp, err = summary.EncodeSSZ(temp) - if err != nil { - return err - } - if err = tx.Append(kv.HistoricalSummaries, key, temp); err != nil { - return err - } - } - return err -} - -// IncrementValidatorTable increments the validator table in the database, by ignoring all the preverified indices. -func IncrementPublicKeyTable(tx kv.RwTx, state *state.CachingBeaconState, preverifiedIndicies uint64) error { - valLength := state.ValidatorLength() - for i := preverifiedIndicies; i < uint64(valLength); i++ { - key := base_encoding.Encode64ToBytes4(i) - pubKey, err := state.ValidatorPublicKey(int(i)) - if err != nil { - return err - } - // We put as there could be reorgs and thus some of overwriting - if err := tx.Put(kv.ValidatorPublicKeys, key, pubKey[:]); err != nil { - return err - } - if err := tx.Put(kv.InvertedValidatorPublicKeys, pubKey[:], key); err != nil { - return err - } - } - return nil -} - -func IncrementHistoricalRootsTable(tx kv.RwTx, state *state.CachingBeaconState, preverifiedIndicies uint64) error { - for i := preverifiedIndicies; i < state.HistoricalRootsLength(); i++ { - key := base_encoding.Encode64ToBytes4(i) - root := state.HistoricalRoot(int(i)) - if err := tx.Put(kv.HistoricalRoots, key, root[:]); err != nil { - return err - } - } - return nil -} - -func IncrementHistoricalSummariesTable(tx kv.RwTx, state *state.CachingBeaconState, preverifiedIndicies uint64) error { - var temp []byte - var err error - for i := preverifiedIndicies; i < state.HistoricalSummariesLength(); i++ { - temp = temp[:0] - key := base_encoding.Encode64ToBytes4(i) - summary := state.HistoricalSummary(int(i)) - temp, err = summary.EncodeSSZ(temp) - if err != nil { - return err - } - if err = tx.Put(kv.HistoricalSummaries, key, temp); err != nil { - return err - } - } - return nil -} - -func ReadPublicKeyByIndexNoCopy(tx kv.Tx, index uint64) ([]byte, error) { - var pks []byte - var err error - key := base_encoding.Encode64ToBytes4(index) - if pks, err = tx.GetOne(kv.ValidatorPublicKeys, key); err != nil { - return nil, err - } - return pks, err -} - -func ReadPublicKeyByIndex(tx kv.Tx, index uint64) (libcommon.Bytes48, error) { - var pks []byte - var err error - key := base_encoding.Encode64ToBytes4(index) - if pks, err = tx.GetOne(kv.ValidatorPublicKeys, key); err != nil { - return libcommon.Bytes48{}, err - } - var ret libcommon.Bytes48 - copy(ret[:], pks) - return ret, err -} - -func ReadValidatorIndexByPublicKey(tx kv.Tx, key libcommon.Bytes48) (uint64, bool, error) { - var index []byte - var err error - if index, err = tx.GetOne(kv.InvertedValidatorPublicKeys, key[:]); err != nil { - return 0, false, err - } - if len(index) == 0 { - return 0, false, nil - } - return base_encoding.Decode64FromBytes4(index), true, nil -} - func GetStateProcessingProgress(tx kv.Tx) (uint64, error) { progressByytes, err := tx.GetOne(kv.StatesProcessingProgress, kv.StatesProcessingKey) if err != nil { @@ -266,38 +131,6 @@ func ReadCurrentSyncCommittee(getFn GetValFn, slot uint64) (committee *solid.Syn return } -func ReadHistoricalRoots(tx kv.Tx, l uint64, fn func(idx int, root libcommon.Hash) error) error { - for i := 0; i < int(l); i++ { - key := base_encoding.Encode64ToBytes4(uint64(i)) - v, err := tx.GetOne(kv.HistoricalRoots, key) - if err != nil { - return err - } - if err := fn(i, libcommon.BytesToHash(v)); err != nil { - return err - } - } - return nil -} - -func ReadHistoricalSummaries(tx kv.Tx, l uint64, fn func(idx int, historicalSummary *cltypes.HistoricalSummary) error) error { - for i := 0; i < int(l); i++ { - key := base_encoding.Encode64ToBytes4(uint64(i)) - v, err := tx.GetOne(kv.HistoricalSummaries, key) - if err != nil { - return err - } - historicalSummary := &cltypes.HistoricalSummary{} - if err := historicalSummary.DecodeSSZ(v, 0); err != nil { - return err - } - if err := fn(i, historicalSummary); err != nil { - return err - } - } - return nil -} - func ReadValidatorsTable(tx kv.Tx, out *StaticValidatorTable) error { cursor, err := tx.Cursor(kv.StaticValidators) if err != nil { diff --git a/cl/phase1/forkchoice/public_keys_registry/db_public_keys_registry.go b/cl/phase1/forkchoice/public_keys_registry/db_public_keys_registry.go index c6822ddb42b..a986933114f 100644 --- a/cl/phase1/forkchoice/public_keys_registry/db_public_keys_registry.go +++ b/cl/phase1/forkchoice/public_keys_registry/db_public_keys_registry.go @@ -1,22 +1,19 @@ package public_keys_registry import ( - "context" - "github.com/Giulio2002/bls" "github.com/erigontech/erigon-lib/common" - "github.com/erigontech/erigon-lib/kv" "github.com/erigontech/erigon/cl/abstract" + "github.com/erigontech/erigon/cl/beacon/synced_data" "github.com/erigontech/erigon/cl/cltypes/solid" - state_accessors "github.com/erigontech/erigon/cl/persistence/state" ) type DBPublicKeysRegistry struct { - db kv.RoDB + headView synced_data.SyncedData } -func NewDBPublicKeysRegistry(db kv.RoDB) *DBPublicKeysRegistry { - return &DBPublicKeysRegistry{db: db} +func NewHeadViewPublicKeysRegistry(headView synced_data.SyncedData) *DBPublicKeysRegistry { + return &DBPublicKeysRegistry{headView: headView} } // ResetAnchor resets the public keys registry to the anchor state @@ -28,19 +25,14 @@ func (r *DBPublicKeysRegistry) ResetAnchor(s abstract.BeaconState) { func (r *DBPublicKeysRegistry) VerifyAggregateSignature(checkpoint solid.Checkpoint, pubkeysIdxs *solid.RawUint64List, message []byte, signature common.Bytes96) (bool, error) { pks := make([][]byte, 0, pubkeysIdxs.Length()) - if err := r.db.View(context.TODO(), func(tx kv.Tx) error { - pubkeysIdxs.Range(func(_ int, value uint64, length int) bool { - pk, err := state_accessors.ReadPublicKeyByIndexNoCopy(tx, value) - if err != nil { - return false - } - pks = append(pks, pk) - return true - }) - return nil - }); err != nil { - return false, err - } + pubkeysIdxs.Range(func(_ int, value uint64, length int) bool { + pk, err := r.headView.ValidatorPublicKeyByIndex(int(value)) + if err != nil { + return false + } + pks = append(pks, pk[:]) + return true + }) return bls.VerifyAggregate(signature[:], message, pks) } diff --git a/cl/phase1/stages/forkchoice.go b/cl/phase1/stages/forkchoice.go index e4d51ccaed5..03d3e6c3cc2 100644 --- a/cl/phase1/stages/forkchoice.go +++ b/cl/phase1/stages/forkchoice.go @@ -20,7 +20,6 @@ import ( "github.com/erigontech/erigon/cl/monitor" "github.com/erigontech/erigon/cl/monitor/shuffling_metrics" "github.com/erigontech/erigon/cl/persistence/beacon_indicies" - state_accessors "github.com/erigontech/erigon/cl/persistence/state" "github.com/erigontech/erigon/cl/phase1/core/caches" "github.com/erigontech/erigon/cl/phase1/core/state" "github.com/erigontech/erigon/cl/phase1/core/state/shuffling" @@ -194,24 +193,6 @@ func updateCanonicalChainInTheDatabase(ctx context.Context, tx kv.RwTx, headSlot return nil } -// runIndexingRoutines runs the indexing routines for the database. -func runIndexingRoutines(ctx context.Context, tx kv.RwTx, cfg *Cfg, headState *state.CachingBeaconState) error { - preverifiedValidators := cfg.forkChoice.PreverifiedValidator(headState.FinalizedCheckpoint().Root) - preverifiedHistoricalSummary := cfg.forkChoice.PreverifiedHistoricalSummaries(headState.FinalizedCheckpoint().Root) - preverifiedHistoricalRoots := cfg.forkChoice.PreverifiedHistoricalRoots(headState.FinalizedCheckpoint().Root) - - if err := state_accessors.IncrementPublicKeyTable(tx, headState, preverifiedValidators); err != nil { - return fmt.Errorf("failed to increment public key table: %w", err) - } - if err := state_accessors.IncrementHistoricalSummariesTable(tx, headState, preverifiedHistoricalSummary); err != nil { - return fmt.Errorf("failed to increment historical summaries table: %w", err) - } - if err := state_accessors.IncrementHistoricalRootsTable(tx, headState, preverifiedHistoricalRoots); err != nil { - return fmt.Errorf("failed to increment historical roots table: %w", err) - } - return nil -} - // emitHeadEvent emits the head event with the given head slot, head root, and head state. func emitHeadEvent(cfg *Cfg, headSlot uint64, headRoot common.Hash, headState *state.CachingBeaconState) error { headEpoch := headSlot / cfg.beaconCfg.SlotsPerEpoch @@ -337,13 +318,6 @@ func postForkchoiceOperations(ctx context.Context, tx kv.RwTx, logger log.Logger }() return cfg.syncedData.ViewHeadState(func(headState *state.CachingBeaconState) error { - // Produce and cache attestation data for validator node (this is not an expensive operation so we can do it for all nodes) - - // Run indexing routines for the database - if err := runIndexingRoutines(ctx, tx, cfg, headState); err != nil { - return fmt.Errorf("failed to run indexing routines: %w", err) - } - // Dump the head state on disk for ease of chain reorgs if err := cfg.forkChoice.DumpBeaconStateOnDisk(headState); err != nil { return fmt.Errorf("failed to dump beacon state on disk: %w", err) diff --git a/cl/sentinel/sentinel.go b/cl/sentinel/sentinel.go index d79283c1f49..8a0b94f85b3 100644 --- a/cl/sentinel/sentinel.go +++ b/cl/sentinel/sentinel.go @@ -273,7 +273,6 @@ func New( } func (s *Sentinel) observeBandwidth(ctx context.Context, bwc *metrics.BandwidthCounter) { - ticker := time.NewTicker(200 * time.Millisecond) for { countSubnetsSubscribed := func() int { @@ -286,7 +285,7 @@ func (s *Sentinel) observeBandwidth(ctx context.Context, bwc *metrics.BandwidthC if sub.topic == nil { return true } - if strings.Contains(sub.topic.String(), "beacon_attestation") { + if strings.Contains(sub.topic.String(), "beacon_attestation") && sub.subscribed.Load() { count++ } return true @@ -294,8 +293,10 @@ func (s *Sentinel) observeBandwidth(ctx context.Context, bwc *metrics.BandwidthC return count }() - multiplierForAdaptableTraffic := (float64(countSubnetsSubscribed) / float64(s.cfg.NetworkConfig.AttestationSubnetCount)) * 8 - + multiplierForAdaptableTraffic := 1.0 + if s.cfg.AdaptableTrafficRequirements { + multiplierForAdaptableTraffic = ((float64(countSubnetsSubscribed) / float64(s.cfg.NetworkConfig.AttestationSubnetCount)) * 8) + 1 + } select { case <-ctx.Done(): return @@ -308,7 +309,7 @@ func (s *Sentinel) observeBandwidth(ctx context.Context, bwc *metrics.BandwidthC maxRateIn := float64(max(s.cfg.MaxInboundTrafficPerPeer, minBound)) * multiplierForAdaptableTraffic maxRateOut := float64(max(s.cfg.MaxOutboundTrafficPerPeer, minBound)) * multiplierForAdaptableTraffic peers := s.host.Network().Peers() - maxPeersToBan := int(s.cfg.MaxPeerCount) / 8 + maxPeersToBan := 16 // do not ban peers if we have less than 1/8 of max peer count if len(peers) <= maxPeersToBan { continue diff --git a/cl/sentinel/sentinel_requests_test.go b/cl/sentinel/sentinel_requests_test.go index 99545961640..c2eac7403c7 100644 --- a/cl/sentinel/sentinel_requests_test.go +++ b/cl/sentinel/sentinel_requests_test.go @@ -37,6 +37,7 @@ import ( "github.com/erigontech/erigon-lib/kv/memdb" "github.com/erigontech/erigon/cl/antiquary" "github.com/erigontech/erigon/cl/antiquary/tests" + "github.com/erigontech/erigon/cl/beacon/synced_data" "github.com/erigontech/erigon/cl/clparams" "github.com/erigontech/erigon/cl/cltypes" "github.com/erigontech/erigon/cl/cltypes/solid" @@ -53,9 +54,12 @@ func loadChain(t *testing.T) (db kv.RwDB, blocks []*cltypes.SignedBeaconBlock, f db = memdb.NewTestDB(t, kv.ChainDB) reader = tests.LoadChain(blocks, postState, db, t) + sn := synced_data.NewSyncedDataManager(&clparams.MainnetBeaconConfig, true) + sn.OnHeadState(postState) + ctx := context.Background() vt := state_accessors.NewStaticValidatorTable() - a := antiquary.NewAntiquary(ctx, nil, preState, vt, &clparams.MainnetBeaconConfig, datadir.New("/tmp"), nil, db, nil, nil, reader, log.New(), true, true, false, false, nil) + a := antiquary.NewAntiquary(ctx, nil, preState, vt, &clparams.MainnetBeaconConfig, datadir.New("/tmp"), nil, db, nil, nil, reader, sn, log.New(), true, true, false, false, nil) require.NoError(t, a.IncrementBeaconState(ctx, blocks[len(blocks)-1].Block.Slot+33)) return } diff --git a/cmd/capcli/cli.go b/cmd/capcli/cli.go index a5563dad5c4..ae5250199be 100644 --- a/cmd/capcli/cli.go +++ b/cmd/capcli/cli.go @@ -45,6 +45,7 @@ import ( "github.com/erigontech/erigon-lib/metrics" "github.com/erigontech/erigon/cl/antiquary" + "github.com/erigontech/erigon/cl/beacon/synced_data" "github.com/erigontech/erigon/cl/clparams" "github.com/erigontech/erigon/cl/clparams/initial_state" "github.com/erigontech/erigon/cl/cltypes" @@ -152,6 +153,7 @@ func (c *Chain) Run(ctx *Context) error { if err != nil { return err } + ethClock := eth_clock.NewEthereumClock(bs.GenesisTime(), bs.GenesisValidatorsRoot(), beaconConfig) db, blobStorage, err := caplin1.OpenCaplinDatabase(ctx, beaconConfig, ethClock, dirs.CaplinIndexing, dirs.CaplinBlobs, nil, false, 0) if err != nil { @@ -182,7 +184,7 @@ func (c *Chain) Run(ctx *Context) error { } downloader := network.NewBackwardBeaconDownloader(ctx, beacon, nil, nil, db) - cfg := stages.StageHistoryReconstruction(downloader, antiquary.NewAntiquary(ctx, nil, nil, nil, nil, dirs, nil, nil, nil, nil, nil, nil, false, false, false, false, nil), csn, db, nil, beaconConfig, true, false, true, bRoot, bs.Slot(), "/tmp", 300*time.Millisecond, nil, nil, blobStorage, log.Root()) + cfg := stages.StageHistoryReconstruction(downloader, antiquary.NewAntiquary(ctx, nil, nil, nil, nil, dirs, nil, nil, nil, nil, nil, nil, nil, false, false, false, false, nil), csn, db, nil, beaconConfig, true, false, true, bRoot, bs.Slot(), "/tmp", 300*time.Millisecond, nil, nil, blobStorage, log.Root()) return stages.SpawnStageHistoryDownload(cfg, ctx, log.Root()) } @@ -599,8 +601,15 @@ func (r *RetrieveHistoricalState) Run(ctx *Context) error { return err } + bs, err := checkpoint_sync.NewRemoteCheckpointSync(beaconConfig, t).GetLatestBeaconState(ctx) + if err != nil { + return err + } + sn := synced_data.NewSyncedDataManager(beaconConfig, true) + sn.OnHeadState(bs) + r.withPPROF.withProfile() - hr := historical_states_reader.NewHistoricalStatesReader(beaconConfig, snr, vt, gSpot, stateSn) + hr := historical_states_reader.NewHistoricalStatesReader(beaconConfig, snr, vt, gSpot, stateSn, sn) start := time.Now() haveState, err := hr.ReadHistoricalState(ctx, tx, r.CompareSlot) if err != nil { diff --git a/cmd/caplin/caplin1/run.go b/cmd/caplin/caplin1/run.go index 5d389247af5..99877a288a2 100644 --- a/cmd/caplin/caplin1/run.go +++ b/cmd/caplin/caplin1/run.go @@ -273,7 +273,7 @@ func RunCaplinService(ctx context.Context, engine execution_client.ExecutionEngi doLMDSampling := len(state.GetActiveValidatorsIndices(state.Slot()/beaconConfig.SlotsPerEpoch)) >= 20_000 // create the public keys registry - pksRegistry := public_keys_registry.NewDBPublicKeysRegistry(indexDB) + pksRegistry := public_keys_registry.NewHeadViewPublicKeysRegistry(syncedDataManager) forkChoice, err := forkchoice.NewForkChoiceStore( ethClock, state, engine, pool, fork_graph.NewForkGraphDisk(state, fcuFs, config.BeaconAPIRouter, emitters), @@ -385,9 +385,6 @@ func RunCaplinService(ctx context.Context, engine execution_client.ExecutionEngi } defer tx.Rollback() - if err := state_accessors.InitializeStaticTables(tx, state); err != nil { - return err - } if err := beacon_indicies.WriteHighestFinalized(tx, 0); err != nil { return err } @@ -403,7 +400,7 @@ func RunCaplinService(ctx context.Context, engine execution_client.ExecutionEngi if err := stateSnapshots.OpenFolder(); err != nil { return err } - antiq := antiquary.NewAntiquary(ctx, blobStorage, genesisState, vTables, beaconConfig, dirs, snDownloader, indexDB, stateSnapshots, csn, rcsn, logger, states, backfilling, blobBackfilling, config.SnapshotGenerationEnabled, snBuildSema) + antiq := antiquary.NewAntiquary(ctx, blobStorage, genesisState, vTables, beaconConfig, dirs, snDownloader, indexDB, stateSnapshots, csn, rcsn, syncedDataManager, logger, states, backfilling, blobBackfilling, config.SnapshotGenerationEnabled, snBuildSema) // Create the antiquary go func() { if err := antiq.Loop(); err != nil { @@ -415,7 +412,7 @@ func RunCaplinService(ctx context.Context, engine execution_client.ExecutionEngi return err } - statesReader := historical_states_reader.NewHistoricalStatesReader(beaconConfig, rcsn, vTables, genesisState, stateSnapshots) + statesReader := historical_states_reader.NewHistoricalStatesReader(beaconConfig, rcsn, vTables, genesisState, stateSnapshots, syncedDataManager) validatorParameters := validator_params.NewValidatorParams() if config.BeaconAPIRouter.Active { apiHandler := handler.NewApiHandler( diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 88c3a71b8a2..259ce2d6dfb 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -885,7 +885,7 @@ var ( CaplinMaxPeerCount = cli.Uint64Flag{ Name: "caplin.max-peer-count", Usage: "Max number of peers to connect", - Value: 64, + Value: 80, } SentinelAddrFlag = cli.StringFlag{ diff --git a/erigon-lib/kv/tables.go b/erigon-lib/kv/tables.go index baa140747a0..00a8ab968d0 100644 --- a/erigon-lib/kv/tables.go +++ b/erigon-lib/kv/tables.go @@ -287,8 +287,6 @@ const ( InactivityScores = "InactivityScores" NextSyncCommittee = "NextSyncCommittee" CurrentSyncCommittee = "CurrentSyncCommittee" - HistoricalRoots = "HistoricalRoots" - HistoricalSummaries = "HistoricalSummaries" Eth1DataVotes = "Eth1DataVotes" IntraRandaoMixes = "IntraRandaoMixes" // [validator_index+slot] => [randao_mix] @@ -430,8 +428,6 @@ var ChaindataTables = []string{ // Blob Storage BlockRootToKzgCommitments, // State Reconstitution - ValidatorPublicKeys, - InvertedValidatorPublicKeys, ValidatorEffectiveBalance, ValidatorBalance, ValidatorSlashings, @@ -448,8 +444,6 @@ var ChaindataTables = []string{ InactivityScores, NextSyncCommittee, CurrentSyncCommittee, - HistoricalRoots, - HistoricalSummaries, Eth1DataVotes, IntraRandaoMixes, ActiveValidatorIndicies, From 8f7a0a20ec25bb07a1afd9d7e286b9e45d5efb10 Mon Sep 17 00:00:00 2001 From: Giulio rebuffo Date: Mon, 9 Dec 2024 14:35:36 +0100 Subject: [PATCH 03/24] Caplin: Speedup in block production (#13051) fixed missing orphans on holesky. this way to retrieve head state to build the block on is much faster --- cl/beacon/handler/block_production.go | 50 +++++++++++++++++-- .../freezeblocks/caplin_snapshots.go | 4 +- 2 files changed, 48 insertions(+), 6 deletions(-) diff --git a/cl/beacon/handler/block_production.go b/cl/beacon/handler/block_production.go index 8dac0adeeb4..c34f62abc96 100644 --- a/cl/beacon/handler/block_production.go +++ b/cl/beacon/handler/block_production.go @@ -265,6 +265,7 @@ func (a *ApiHandler) GetEthV3ValidatorBlock( ) } + log.Debug("[Beacon API] Producing block", "slot", targetSlot) // builder boost factor controls block choice between local execution node or builder var builderBoostFactor uint64 builderBoostFactorStr := r.URL.Query().Get("builder_boost_factor") @@ -285,6 +286,8 @@ func (a *ApiHandler) GetEthV3ValidatorBlock( errors.New("node is syncing"), ) } + + start := time.Now() sourceBlock, err := a.blockReader.ReadBlockByRoot(ctx, tx, baseBlockRoot) if err != nil { log.Warn("Failed to get source block", "err", err, "root", baseBlockRoot) @@ -296,10 +299,19 @@ func (a *ApiHandler) GetEthV3ValidatorBlock( fmt.Errorf("block not found %x", baseBlockRoot), ) } - baseState, err := a.forkchoiceStore.GetStateAtBlockRoot( - baseBlockRoot, - true, - ) // we start the block production from this state + + // make a simple copy to the current head state + var baseState *state.CachingBeaconState + if err := a.syncedData.ViewHeadState(func(headState *state.CachingBeaconState) error { + baseState, err = headState.Copy() + if err != nil { + return err + } + return nil + }); err != nil { + return nil, err + } + if err != nil { return nil, err } @@ -312,22 +324,27 @@ func (a *ApiHandler) GetEthV3ValidatorBlock( if err := transition.DefaultMachine.ProcessSlots(baseState, targetSlot); err != nil { return nil, err } + log.Info("[Beacon API] Found BeaconState object for block production", "slot", targetSlot, "duration", time.Since(start)) block, err := a.produceBlock(ctx, builderBoostFactor, sourceBlock.Block, baseState, targetSlot, randaoReveal, graffiti) if err != nil { log.Warn("Failed to produce block", "err", err, "slot", targetSlot) return nil, err } + startConsensusProcessing := time.Now() // do state transition if err := machine.ProcessBlock(transition.DefaultMachine, baseState, block.ToGeneric()); err != nil { log.Warn("Failed to process execution block", "err", err, "slot", targetSlot) return nil, err } + log.Info("[Beacon API] Built block consensus-state", "slot", targetSlot, "duration", time.Since(startConsensusProcessing)) + startConsensusProcessing = time.Now() block.StateRoot, err = baseState.HashSSZ() if err != nil { log.Warn("Failed to get state root", "err", err) return nil, err } + log.Info("[Beacon API] Computed state root while producing slot", "slot", targetSlot, "duration", time.Since(startConsensusProcessing)) log.Info("BlockProduction: Block produced", "proposerIndex", block.ProposerIndex, @@ -336,6 +353,7 @@ func (a *ApiHandler) GetEthV3ValidatorBlock( "execution_value", block.GetExecutionValue().Uint64(), "version", block.Version(), "blinded", block.IsBlinded(), + "took", time.Since(start), ) // todo: consensusValue @@ -380,6 +398,10 @@ func (a *ApiHandler) produceBlock( kzgProofs []libcommon.Bytes48 ) go func() { + start := time.Now() + defer func() { + a.logger.Debug("Produced BeaconBody", "slot", targetSlot, "duration", time.Since(start)) + }() defer wg.Done() beaconBody, localExecValue, localErr = a.produceBeaconBody(ctx, 3, baseBlock, baseState, targetSlot, randaoReveal, graffiti) // collect blobs @@ -407,6 +429,10 @@ func (a *ApiHandler) produceBlock( builderErr error ) go func() { + start := time.Now() + defer func() { + a.logger.Debug("MevBoost", "slot", targetSlot, "duration", time.Since(start)) + }() defer wg.Done() if a.routerCfg.Builder && a.builderClient != nil { builderHeader, builderErr = a.getBuilderPayload(ctx, baseBlock, baseState, targetSlot) @@ -1161,6 +1187,22 @@ func (a *ApiHandler) storeBlockAndBlobs( if _, err := a.engine.ForkChoiceUpdate(ctx, a.forkchoiceStore.GetEth1Hash(finalizedBlockRoot), a.forkchoiceStore.GetEth1Hash(blockRoot), nil); err != nil { return err } + headState, err := a.forkchoiceStore.GetStateAtBlockRoot(blockRoot, false) + if err != nil { + return err + } + if headState == nil { + return errors.New("failed to get head state") + } + a.syncedData.OnHeadState(headState) + + if err := a.indiciesDB.View(ctx, func(tx kv.Tx) error { + _, err := a.attestationProducer.ProduceAndCacheAttestationData(tx, headState, blockRoot, block.Block.Slot, 0) + return err + }); err != nil { + return err + } + return nil } diff --git a/turbo/snapshotsync/freezeblocks/caplin_snapshots.go b/turbo/snapshotsync/freezeblocks/caplin_snapshots.go index 2288ec40b47..6fd0708ff17 100644 --- a/turbo/snapshotsync/freezeblocks/caplin_snapshots.go +++ b/turbo/snapshotsync/freezeblocks/caplin_snapshots.go @@ -194,7 +194,7 @@ Loop: snaptype.BeaconBlocks, f.Version, f.From, f.To, - snapcfg.IsFrozen(s.cfg.ChainName, f)) + true) } if err := sn.Open(s.dir); err != nil { if errors.Is(err, os.ErrNotExist) { @@ -250,7 +250,7 @@ Loop: snaptype.BlobSidecars, f.Version, f.From, f.To, - snapcfg.IsFrozen(s.cfg.ChainName, f)) + true) } if err := sn.Open(s.dir); err != nil { if errors.Is(err, os.ErrNotExist) { From ab258ff1ac1181ca45f756dca5ebe01f8ce3fccd Mon Sep 17 00:00:00 2001 From: Cypher Pepe <125112044+cypherpepe@users.noreply.github.com> Date: Mon, 9 Dec 2024 16:57:47 +0300 Subject: [PATCH 04/24] Fix: Typographical Errors and Improve Documentation Clarity (#13006) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Description: This pull request addresses several typographical errors and improves the clarity of documentation across multiple files. The following changes were made: - **`docs/DEV_CHAIN.md`**: Fixed typos such as "blocn_num" → "block_num" and improved sentence structure. - **`erigon-lib/downloader/README.md`**: Corrected the word "reacreated" to "recreated" and made other minor text improvements. - **`erigon-lib/etl/README.md`**: Fixed "Tranform" → "Transform" and refined the wording for better clarity. --- docs/DEV_CHAIN.md | 4 ++-- erigon-lib/downloader/README.md | 2 +- erigon-lib/etl/README.md | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/DEV_CHAIN.md b/docs/DEV_CHAIN.md index ad3ec3ebc68..57c7db3ee8c 100644 --- a/docs/DEV_CHAIN.md +++ b/docs/DEV_CHAIN.md @@ -33,7 +33,7 @@ Or, you could start the rpcdaemon internally together Argument notes: * datadir : Tells where the data is stored, default level is dev folder. * chain : Tells that we want to run Erigon in the dev chain. - * private.api.addr=localhost:9090 : Tells where Eigon is going to listen for connections. + * private.api.addr=localhost:9090 : Tells where Erigon is going to listen for connections. * mine : Add this if you want the node to mine. * dev.period : Add this to specify the timing interval among blocks. Number of seconds MUST be > 0 (if you want empty blocks) otherwise the default value 0 does not allow mining of empty blocks. * http.api: List of services to start on http (rpc) access @@ -150,7 +150,7 @@ From the RPC daemon terminal, you will see something like this Now we want to check the creation of a new block and that all the nodes sync. -Below we can see that block 1 is created (blocn_num=1) and that the next block to be proposed increments from 1 to 2 ( block=2). The other nodes will see the same update. +Below we can see that block 1 is created (block_num=1) and that the next block to be proposed increments from 1 to 2 ( block=2). The other nodes will see the same update. Block diff --git a/erigon-lib/downloader/README.md b/erigon-lib/downloader/README.md index 515fc0f6d21..d262447af52 100644 --- a/erigon-lib/downloader/README.md +++ b/erigon-lib/downloader/README.md @@ -53,7 +53,7 @@ When a `snapshot-lock` file exists it is used rather than the chain.toml file to ### Deleting snapshot-lock.json -If the snapshot-lock file is deleted it will be reacreated from the `chain.toml` file embeded in the Erigon process. If the hashes change then the associated files will be re-downloaded. +If the snapshot-lock file is deleted it will be recreated from the `chain.toml` file embedded in the Erigon process. If the hashes change then the associated files will be re-downloaded. ### How to override downloads diff --git a/erigon-lib/etl/README.md b/erigon-lib/etl/README.md index 8813501a42f..7d796282c79 100644 --- a/erigon-lib/etl/README.md +++ b/erigon-lib/etl/README.md @@ -8,7 +8,7 @@ Inserting entries into our KV storage sorted by keys helps to minimize write amplification, hence it is much faster, even considering additional I/O that is generated by storing files. -It behaves similarly to enterprise [Extract, Tranform, Load](https://en.wikipedia.org/wiki/Extract,_transform,_load) frameworks, hence the name. +It behaves similarly to enterprise [Extract, Transform, Load](https://en.wikipedia.org/wiki/Extract,_transform,_load) frameworks, hence the name. We use temporary files because that helps keep RAM usage predictable and allows using ETL on large amounts of data. From 75cf7b8701cedb85a70a79238e39c5ef85edf15c Mon Sep 17 00:00:00 2001 From: lfg2 Date: Mon, 9 Dec 2024 21:58:46 +0800 Subject: [PATCH 05/24] cmd: fix flag message (#13049) --- cmd/diag/downloader/diag_downloader.go | 2 +- cmd/utils/flags.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/diag/downloader/diag_downloader.go b/cmd/diag/downloader/diag_downloader.go index 3e5577c4073..cc50a46636c 100644 --- a/cmd/diag/downloader/diag_downloader.go +++ b/cmd/diag/downloader/diag_downloader.go @@ -34,7 +34,7 @@ var ( FileFilterFlag = cli.StringFlag{ Name: "downloader.file.filter", Aliases: []string{"dff"}, - Usage: "Filter files list [all|active|inactive|downloaded|queued], dafault value is all", + Usage: "Filter files list [all|active|inactive|downloaded|queued], default value is all", Required: false, Value: "all", } diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 259ce2d6dfb..b6e63c7e184 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -868,7 +868,7 @@ var ( Value: cli.NewStringSlice(), } CaplinSubscribeAllTopicsFlag = cli.BoolFlag{ - Name: "caplin.subscibe-all-topics", + Name: "caplin.subscribe-all-topics", Usage: "Subscribe to all gossip topics", Value: false, } From d30324caa7df669145c58f15661ac3a7c2d46ad1 Mon Sep 17 00:00:00 2001 From: Dmytro Vovk Date: Mon, 9 Dec 2024 15:35:37 +0000 Subject: [PATCH 06/24] txpool: nil pointer fix #13033 (#13055) Cherry pick https://github.com/erigontech/erigon/pull/13033 --- txnprovider/txpool/pool.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/txnprovider/txpool/pool.go b/txnprovider/txpool/pool.go index 089cba73bca..d0600b3476a 100644 --- a/txnprovider/txpool/pool.go +++ b/txnprovider/txpool/pool.go @@ -1955,6 +1955,9 @@ func (p *TxPool) flush(ctx context.Context) (written uint64, err error) { func (p *TxPool) flushLocked(tx kv.RwTx) (err error) { for i, mt := range p.deletedTxns { + if mt == nil { + continue + } id := mt.TxnSlot.SenderID idHash := mt.TxnSlot.IDHash[:] if !p.all.hasTxns(id) { From 9703b4c896c148dfa3418bb66b9f620a3a8f6925 Mon Sep 17 00:00:00 2001 From: Mark Holt <135143369+mh0lt@users.noreply.github.com> Date: Mon, 9 Dec 2024 15:46:21 +0000 Subject: [PATCH 07/24] Redo ibs errors (PR 12926) (#13039) This re-applies https://github.com/erigontech/erigon/pull/12926, with fixed spec tests For reference the regression was fixed here: https://github.com/erigontech/erigon/pull/13039/commits/ed4d5b03a3ee9f104c0a3705966b6d3ef9d984f9 --- accounts/abi/bind/backends/simulated.go | 25 +- accounts/abi/bind/backends/simulated_test.go | 5 +- cl/beacon/handler/subscription.go | 1 + cl/phase1/forkchoice/on_attestation.go | 1 - cl/phase1/forkchoice/on_attester_slashing.go | 1 - cl/phase1/network/services/block_service.go | 1 - cmd/state/exec3/state.go | 1 + consensus/consensus.go | 9 +- consensus/misc/dao.go | 15 +- consensus/misc/eip2935.go | 18 +- core/chain_makers.go | 12 +- core/evm.go | 8 +- core/genesis_test.go | 6 +- core/state/database_test.go | 202 +++++++++--- core/state/intra_block_state.go | 304 ++++++++++++------ core/state/intra_block_state_logger_test.go | 6 +- core/state/intra_block_state_test.go | 82 ++++- core/state/journal.go | 85 +++-- core/state/state_test.go | 45 ++- core/state/txtask.go | 5 +- core/state_transition.go | 97 ++++-- core/vm/eips.go | 5 +- core/vm/errors.go | 4 + core/vm/evm.go | 52 ++- core/vm/evmtypes/evmtypes.go | 50 +-- core/vm/gas_table.go | 42 ++- core/vm/gas_table_test.go | 12 +- core/vm/instructions.go | 47 ++- core/vm/operations_acl.go | 35 +- core/vm/runtime/runtime.go | 5 +- eth/stagedsync/exec3.go | 290 +++++++++-------- eth/stagedsync/exec3_parallel.go | 190 ++++++----- eth/stagedsync/exec3_serial.go | 49 +-- eth/tracers/js/goja.go | 28 +- eth/tracers/js/tracer_test.go | 6 +- eth/tracers/logger/access_list_tracer.go | 3 +- eth/tracers/native/prestate.go | 22 +- polygon/bor/bor.go | 40 ++- tests/block_test_util.go | 15 +- tests/statedb_chain_test.go | 30 +- .../statedb_insert_chain_transaction_test.go | 205 ++++++++++-- turbo/jsonrpc/eth_call.go | 5 +- turbo/jsonrpc/eth_call_test.go | 8 +- turbo/jsonrpc/overlay_api.go | 16 +- turbo/jsonrpc/overlay_create_tracer.go | 6 +- turbo/jsonrpc/trace_adhoc.go | 81 ++++- turbo/stages/blockchain_test.go | 85 ++++- turbo/stages/chain_makers_test.go | 24 +- 48 files changed, 1605 insertions(+), 679 deletions(-) diff --git a/accounts/abi/bind/backends/simulated.go b/accounts/abi/bind/backends/simulated.go index 667309affa4..3645d0cc824 100644 --- a/accounts/abi/bind/backends/simulated.go +++ b/accounts/abi/bind/backends/simulated.go @@ -207,7 +207,7 @@ func (b *SimulatedBackend) CodeAt(ctx context.Context, contract libcommon.Addres } defer tx.Rollback() stateDB := b.stateByBlockNumber(tx, blockNumber) - return stateDB.GetCode(contract), nil + return stateDB.GetCode(contract) } // BalanceAt returns the wei balance of a certain account in the blockchain. @@ -220,7 +220,7 @@ func (b *SimulatedBackend) BalanceAt(ctx context.Context, contract libcommon.Add } defer tx.Rollback() stateDB := b.stateByBlockNumber(tx, blockNumber) - return stateDB.GetBalance(contract), nil + return stateDB.GetBalance(contract) } // NonceAt returns the nonce of a certain account in the blockchain. @@ -234,7 +234,7 @@ func (b *SimulatedBackend) NonceAt(ctx context.Context, contract libcommon.Addre defer tx.Rollback() stateDB := b.stateByBlockNumber(tx, blockNumber) - return stateDB.GetNonce(contract), nil + return stateDB.GetNonce(contract) } // StorageAt returns the value of key in the storage of an account in the blockchain. @@ -518,7 +518,7 @@ func (b *SimulatedBackend) PendingCodeAt(ctx context.Context, contract libcommon b.mu.Lock() defer b.mu.Unlock() - return b.pendingState.GetCode(contract), nil + return b.pendingState.GetCode(contract) } func newRevertError(result *evmtypes.ExecutionResult) *revertError { @@ -600,7 +600,7 @@ func (b *SimulatedBackend) PendingNonceAt(ctx context.Context, account libcommon b.mu.Lock() defer b.mu.Unlock() - return b.pendingState.GetNonce(account), nil + return b.pendingState.GetNonce(account) } // SuggestGasPrice implements ContractTransactor.SuggestGasPrice. Since the simulated @@ -628,7 +628,10 @@ func (b *SimulatedBackend) EstimateGas(ctx context.Context, call ethereum.CallMs } // Recap the highest gas allowance with account's balance. if call.GasPrice != nil && !call.GasPrice.IsZero() { - balance := b.pendingState.GetBalance(call.From) // from can't be nil + balance, err := b.pendingState.GetBalance(call.From) // from can't be nil + if err != nil { + return 0, err + } available := balance.ToBig() if call.Value != nil { if call.Value.ToBig().Cmp(available) >= 0 { @@ -724,7 +727,10 @@ func (b *SimulatedBackend) callContract(_ context.Context, call ethereum.CallMsg call.Value = new(uint256.Int) } // Set infinite balance to the fake caller account. - from := statedb.GetOrNewStateObject(call.From) + from, err := statedb.GetOrNewStateObject(call.From) + if err != nil { + return nil, err + } from.SetBalance(uint256.NewInt(0).SetAllOne(), tracing.BalanceChangeUnspecified) // Execute the call. msg := callMsg{call} @@ -752,7 +758,10 @@ func (b *SimulatedBackend) SendTransaction(ctx context.Context, txn types.Transa if senderErr != nil { return fmt.Errorf("invalid transaction: %w", senderErr) } - nonce := b.pendingState.GetNonce(sender) + nonce, err := b.pendingState.GetNonce(sender) + if err != nil { + return err + } if txn.GetNonce() != nonce { return fmt.Errorf("invalid transaction nonce: got %d, want %d", txn.GetNonce(), nonce) } diff --git a/accounts/abi/bind/backends/simulated_test.go b/accounts/abi/bind/backends/simulated_test.go index 48f057912d3..2882c933316 100644 --- a/accounts/abi/bind/backends/simulated_test.go +++ b/accounts/abi/bind/backends/simulated_test.go @@ -152,7 +152,10 @@ func TestNewSimulatedBackend(t *testing.T) { } statedb := sim.stateByBlockNumber(tx, new(big.Int).SetUint64(num+1)) - bal := statedb.GetBalance(testAddr) + bal, err := statedb.GetBalance(testAddr) + if err != nil { + t.Fatal(err) + } if !bal.Eq(expectedBal) { t.Errorf("expected balance for test address not received. expected: %v actual: %v", expectedBal, bal) } diff --git a/cl/beacon/handler/subscription.go b/cl/beacon/handler/subscription.go index 63e187fd79c..caa4041f32c 100644 --- a/cl/beacon/handler/subscription.go +++ b/cl/beacon/handler/subscription.go @@ -84,6 +84,7 @@ func (a *ApiHandler) PostEthV1ValidatorSyncCommitteeSubscriptions(w http.Respons http.Error(w, err.Error(), http.StatusInternalServerError) return } + //cn() } // subscribe to subnets diff --git a/cl/phase1/forkchoice/on_attestation.go b/cl/phase1/forkchoice/on_attestation.go index 7544509b311..deeb757442a 100644 --- a/cl/phase1/forkchoice/on_attestation.go +++ b/cl/phase1/forkchoice/on_attestation.go @@ -56,7 +56,6 @@ func (f *ForkChoiceStore) OnAttestation( return err } } - var attestationIndicies []uint64 var err error target := data.Target diff --git a/cl/phase1/forkchoice/on_attester_slashing.go b/cl/phase1/forkchoice/on_attester_slashing.go index 9879ffece91..38263819d06 100644 --- a/cl/phase1/forkchoice/on_attester_slashing.go +++ b/cl/phase1/forkchoice/on_attester_slashing.go @@ -60,7 +60,6 @@ func (f *ForkChoiceStore) onProcessAttesterSlashing(attesterSlashing *cltypes.At if !cltypes.IsSlashableAttestationData(attestation1.Data, attestation2.Data) { return errors.New("attestation data is not slashable") } - attestation1PublicKeys, err := getIndexedAttestationPublicKeys(s, attestation1) if err != nil { return err diff --git a/cl/phase1/network/services/block_service.go b/cl/phase1/network/services/block_service.go index 56ed8be96e8..a7fab891c70 100644 --- a/cl/phase1/network/services/block_service.go +++ b/cl/phase1/network/services/block_service.go @@ -156,7 +156,6 @@ func (b *blockService) ProcessMessage(ctx context.Context, _ *uint64, msg *cltyp if msg.Block.Body.BlobKzgCommitments.Len() > int(b.beaconCfg.MaxBlobsPerBlock) { return ErrInvalidCommitmentsCount } - b.publishBlockGossipEvent(msg) // the rest of the validation is done in the forkchoice store if err := b.processAndStoreBlock(ctx, msg); err != nil { diff --git a/cmd/state/exec3/state.go b/cmd/state/exec3/state.go index 75868c51130..43b12c7ea94 100644 --- a/cmd/state/exec3/state.go +++ b/cmd/state/exec3/state.go @@ -132,6 +132,7 @@ func (rw *Worker) ResetTx(chainTx kv.Tx) { func (rw *Worker) Run() error { for txTask, ok := rw.in.Next(rw.ctx); ok; txTask, ok = rw.in.Next(rw.ctx) { + //fmt.Println("RTX", txTask.BlockNum, txTask.TxIndex, txTask.TxNum, txTask.Final) rw.RunTxTask(txTask, rw.isMining) if err := rw.resultCh.Add(rw.ctx, txTask); err != nil { return err diff --git a/consensus/consensus.go b/consensus/consensus.go index 0429f57e335..0ed3552cfbd 100644 --- a/consensus/consensus.go +++ b/consensus/consensus.go @@ -205,9 +205,12 @@ type PoW interface { } // Transfer subtracts amount from sender and adds amount to recipient using the given Db -func Transfer(db evmtypes.IntraBlockState, sender, recipient libcommon.Address, amount *uint256.Int, bailout bool) { +func Transfer(db evmtypes.IntraBlockState, sender, recipient libcommon.Address, amount *uint256.Int, bailout bool) error { if !bailout { - db.SubBalance(sender, amount, tracing.BalanceChangeTransfer) + err := db.SubBalance(sender, amount, tracing.BalanceChangeTransfer) + if err != nil { + return err + } } - db.AddBalance(recipient, amount, tracing.BalanceChangeTransfer) + return db.AddBalance(recipient, amount, tracing.BalanceChangeTransfer) } diff --git a/consensus/misc/dao.go b/consensus/misc/dao.go index fd02f56bfdc..c5671bb08b6 100644 --- a/consensus/misc/dao.go +++ b/consensus/misc/dao.go @@ -73,15 +73,24 @@ func VerifyDAOHeaderExtraData(config *chain.Config, header *types.Header) error // ApplyDAOHardFork modifies the state database according to the DAO hard-fork // rules, transferring all balances of a set of DAO accounts to a single refund // contract. -func ApplyDAOHardFork(statedb *state.IntraBlockState) { +func ApplyDAOHardFork(statedb *state.IntraBlockState) error { // Retrieve the contract to refund balances into - if !statedb.Exist(params.DAORefundContract) { + exist, err := statedb.Exist(params.DAORefundContract) + if err != nil { + return err + } + if !exist { statedb.CreateAccount(params.DAORefundContract, false) } // Move every DAO account and extra-balance account funds into the refund contract for _, addr := range params.DAODrainList() { - statedb.AddBalance(params.DAORefundContract, statedb.GetBalance(addr), tracing.BalanceIncreaseDaoContract) + balance, err := statedb.GetBalance(addr) + if err != nil { + return err + } + statedb.AddBalance(params.DAORefundContract, balance, tracing.BalanceIncreaseDaoContract) statedb.SetBalance(addr, new(uint256.Int), tracing.BalanceDecreaseDaoAccount) } + return nil } diff --git a/consensus/misc/eip2935.go b/consensus/misc/eip2935.go index 460c95f4b39..de3078e0a34 100644 --- a/consensus/misc/eip2935.go +++ b/consensus/misc/eip2935.go @@ -29,21 +29,25 @@ import ( "github.com/erigontech/erigon/params" ) -func StoreBlockHashesEip2935(header *types.Header, state *state.IntraBlockState, config *chain.Config, headerReader consensus.ChainHeaderReader) { - if state.GetCodeSize(params.HistoryStorageAddress) == 0 { +func StoreBlockHashesEip2935(header *types.Header, state *state.IntraBlockState, config *chain.Config, headerReader consensus.ChainHeaderReader) error { + codeSize, err := state.GetCodeSize(params.HistoryStorageAddress) + if err != nil { + return err + } + if codeSize == 0 { log.Debug("[EIP-2935] No code deployed to HistoryStorageAddress before call to store EIP-2935 history") - return + return nil } headerNum := header.Number.Uint64() if headerNum == 0 { // Activation of fork at Genesis - return + return nil } - storeHash(headerNum-1, header.ParentHash, state) + return storeHash(headerNum-1, header.ParentHash, state) } -func storeHash(num uint64, hash libcommon.Hash, state *state.IntraBlockState) { +func storeHash(num uint64, hash libcommon.Hash, state *state.IntraBlockState) error { slotNum := num % params.BlockHashHistoryServeWindow storageSlot := libcommon.BytesToHash(uint256.NewInt(slotNum).Bytes()) parentHashInt := uint256.NewInt(0).SetBytes32(hash.Bytes()) - state.SetState(params.HistoryStorageAddress, &storageSlot, *parentHashInt) + return state.SetState(params.HistoryStorageAddress, &storageSlot, *parentHashInt) } diff --git a/core/chain_makers.go b/core/chain_makers.go index b2c50c9de7d..9c1d9aba3a7 100644 --- a/core/chain_makers.go +++ b/core/chain_makers.go @@ -176,10 +176,18 @@ func (b *BlockGen) AddUncheckedReceipt(receipt *types.Receipt) { // TxNonce returns the next valid transaction nonce for the // account at addr. It panics if the account does not exist. func (b *BlockGen) TxNonce(addr libcommon.Address) uint64 { - if !b.ibs.Exist(addr) { + exist, err := b.ibs.Exist(addr) + if err != nil { + panic(fmt.Sprintf("can't get account: %s", err)) + } + if !exist { panic("account does not exist") } - return b.ibs.GetNonce(addr) + nonce, err := b.ibs.GetNonce(addr) + if err != nil { + panic(fmt.Sprintf("can't get account: %s", err)) + } + return nonce } // AddUncle adds an uncle header to the generated block. diff --git a/core/evm.go b/core/evm.go index 34dcd500316..2f6dc320a5d 100644 --- a/core/evm.go +++ b/core/evm.go @@ -138,6 +138,10 @@ func GetHashFn(ref *types.Header, getHeader func(hash libcommon.Hash, number uin // CanTransfer checks whether there are enough funds in the address' account to make a transfer. // This does not take the necessary gas in to account to make the transfer valid. -func CanTransfer(db evmtypes.IntraBlockState, addr libcommon.Address, amount *uint256.Int) bool { - return !db.GetBalance(addr).Lt(amount) +func CanTransfer(db evmtypes.IntraBlockState, addr libcommon.Address, amount *uint256.Int) (bool, error) { + balance, err := db.GetBalance(addr) + if err != nil { + return false, err + } + return !balance.Lt(amount), nil } diff --git a/core/genesis_test.go b/core/genesis_test.go index e6639d98fce..f060a32d4f8 100644 --- a/core/genesis_test.go +++ b/core/genesis_test.go @@ -154,9 +154,11 @@ func TestAllocConstructor(t *testing.T) { reader, err := rpchelper.CreateHistoryStateReader(tx, rawdbv3.TxNums, 1, 0, genSpec.Config.ChainName) require.NoError(err) state := state.New(reader) - balance := state.GetBalance(address) + balance, err := state.GetBalance(address) + assert.NoError(err) assert.Equal(funds, balance.ToBig()) - code := state.GetCode(address) + code, err := state.GetCode(address) + assert.NoError(err) assert.Equal(libcommon.FromHex("5f355f55"), code) key0 := libcommon.HexToHash("0000000000000000000000000000000000000000000000000000000000000000") diff --git a/core/state/database_test.go b/core/state/database_test.go index 9f019f49fba..4ca21c21839 100644 --- a/core/state/database_test.go +++ b/core/state/database_test.go @@ -31,6 +31,7 @@ import ( "github.com/stretchr/testify/require" "github.com/erigontech/erigon-lib/chain" + "github.com/erigontech/erigon-lib/common" libcommon "github.com/erigontech/erigon-lib/common" "github.com/erigontech/erigon-lib/crypto" "github.com/erigontech/erigon-lib/kv" @@ -132,10 +133,14 @@ func TestCreate2Revive(t *testing.T) { err = m.DB.View(context.Background(), func(tx kv.Tx) error { st := state.New(m.NewStateReader(tx)) - if !st.Exist(address) { + if exist, err := st.Exist(address); err != nil { + t.Error(err) + } else if !exist { t.Error("expected account to exist") } - if st.Exist(contractAddress) { + if exist, err := st.Exist(contractAddress); err != nil { + t.Error(err) + } else if exist { t.Error("expected contractAddress to not exist before block 0", contractAddress.String()) } return nil @@ -149,7 +154,9 @@ func TestCreate2Revive(t *testing.T) { err = m.DB.View(context.Background(), func(tx kv.Tx) error { st := state.New(m.NewStateReader(tx)) - if !st.Exist(contractAddress) { + if exist, err := st.Exist(contractAddress); err != nil { + t.Error(err) + } else if !exist { t.Error("expected contractAddress to exist at the block 1", contractAddress.String()) } return nil @@ -165,7 +172,9 @@ func TestCreate2Revive(t *testing.T) { var check2 uint256.Int err = m.DB.View(context.Background(), func(tx kv.Tx) error { st := state.New(m.NewStateReader(tx)) - if !st.Exist(create2address) { + if exist, err := st.Exist(create2address); err != nil { + t.Error(err) + } else if !exist { t.Error("expected create2address to exist at the block 2", create2address.String()) } // We expect number 0x42 in the position [2], because it is the block number 2 @@ -184,7 +193,9 @@ func TestCreate2Revive(t *testing.T) { } err = m.DB.View(context.Background(), func(tx kv.Tx) error { st := state.New(m.NewStateReader(tx)) - if st.Exist(create2address) { + if exist, err := st.Exist(create2address); err != nil { + t.Error(err) + } else if exist { t.Error("expected create2address to be self-destructed at the block 3", create2address.String()) } return nil @@ -197,7 +208,9 @@ func TestCreate2Revive(t *testing.T) { } err = m.DB.View(context.Background(), func(tx kv.Tx) error { st := state.New(m.NewStateReader(tx)) - if !st.Exist(create2address) { + if exist, err := st.Exist(create2address); err != nil { + t.Error(err) + } else if !exist { t.Error("expected create2address to exist at the block 2", create2address.String()) } // We expect number 0x42 in the position [4], because it is the block number 4 @@ -338,10 +351,14 @@ func TestCreate2Polymorth(t *testing.T) { err = m.DB.View(context.Background(), func(tx kv.Tx) error { st := state.New(m.NewStateReader(tx)) - if !st.Exist(address) { + if exist, err := st.Exist(address); err != nil { + t.Error(err) + } else if !exist { t.Error("expected account to exist") } - if st.Exist(contractAddress) { + if exist, err := st.Exist(contractAddress); err != nil { + t.Error(err) + } else if exist { t.Error("expected contractAddress to not exist before block 0", contractAddress.String()) } return nil @@ -354,9 +371,10 @@ func TestCreate2Polymorth(t *testing.T) { } err = m.DB.View(context.Background(), func(tx kv.Tx) error { - st := state.New(m.NewStateReader(tx)) - if !st.Exist(contractAddress) { + if exist, err := st.Exist(contractAddress); err != nil { + t.Error(err) + } else if !exist { t.Error("expected contractAddress to exist at the block 1", contractAddress.String()) } return nil @@ -370,15 +388,25 @@ func TestCreate2Polymorth(t *testing.T) { err = m.DB.View(context.Background(), func(tx kv.Tx) error { st := state.New(m.NewStateReader(tx)) - if !st.Exist(create2address) { + if exist, err := st.Exist(create2address); err != nil { + t.Error(err) + } else if !exist { t.Error("expected create2address to exist at the block 2", create2address.String()) } - if !bytes.Equal(st.GetCode(create2address), libcommon.FromHex("6002ff")) { - t.Errorf("Expected CREATE2 deployed code 6002ff, got %x", st.GetCode(create2address)) + code, err := st.GetCode(create2address) + if err != nil { + return err + } + if !bytes.Equal(code, common.FromHex("6002ff")) { + t.Errorf("Expected CREATE2 deployed code 6002ff, got %x", code) } if !m.HistoryV3 { //AccountsDomain: has no "incarnation" concept - if st.GetIncarnation(create2address) != 1 { - t.Errorf("expected incarnation 1, got %d", st.GetIncarnation(create2address)) + incarnation, err := st.GetIncarnation(create2address) + if err != nil { + return err + } + if incarnation != 1 { + t.Errorf("expected incarnation 1, got %d", incarnation) } } return nil @@ -391,7 +419,9 @@ func TestCreate2Polymorth(t *testing.T) { } err = m.DB.View(context.Background(), func(tx kv.Tx) error { st := state.New(m.NewStateReader(tx)) - if st.Exist(create2address) { + if exist, err := st.Exist(create2address); err != nil { + t.Error(err) + } else if exist { t.Error("expected create2address to be self-destructed at the block 3", create2address.String()) } return nil @@ -404,15 +434,25 @@ func TestCreate2Polymorth(t *testing.T) { } err = m.DB.View(context.Background(), func(tx kv.Tx) error { st := state.New(m.NewStateReader(tx)) - if !st.Exist(create2address) { + if exist, err := st.Exist(create2address); err != nil { + t.Error(err) + } else if !exist { t.Error("expected create2address to exist at the block 4", create2address.String()) } - if !bytes.Equal(st.GetCode(create2address), libcommon.FromHex("6004ff")) { - t.Errorf("Expected CREATE2 deployed code 6004ff, got %x", st.GetCode(create2address)) + code, err := st.GetCode(create2address) + if err != nil { + return err + } + if !bytes.Equal(code, common.FromHex("6004ff")) { + t.Errorf("Expected CREATE2 deployed code 6004ff, got %x", code) } if !m.HistoryV3 { //AccountsDomain: has no "incarnation" concept - if st.GetIncarnation(create2address) != 2 { - t.Errorf("expected incarnation 2, got %d", st.GetIncarnation(create2address)) + incarnation, err := st.GetIncarnation(create2address) + if err != nil { + return err + } + if incarnation != 2 { + t.Errorf("expected incarnation 2, got %d", incarnation) } } return nil @@ -425,16 +465,26 @@ func TestCreate2Polymorth(t *testing.T) { } err = m.DB.View(context.Background(), func(tx kv.Tx) error { st := state.New(m.NewStateReader(tx)) - if !st.Exist(create2address) { + if exist, err := st.Exist(create2address); err != nil { + t.Error(err) + } else if !exist { t.Error("expected create2address to exist at the block 5", create2address.String()) } - if !bytes.Equal(st.GetCode(create2address), libcommon.FromHex("6005ff")) { - t.Errorf("Expected CREATE2 deployed code 6005ff, got %x", st.GetCode(create2address)) + code, err := st.GetCode(create2address) + if err != nil { + return err + } + if !bytes.Equal(code, common.FromHex("6005ff")) { + t.Errorf("Expected CREATE2 deployed code 6005ff, got %x", code) } if !m.HistoryV3 { //AccountsDomain: has no "incarnation" concept - if st.GetIncarnation(create2address) != 4 { - t.Errorf("expected incarnation 4 (two self-destructs and two-recreations within a block), got %d", st.GetIncarnation(create2address)) + incarnation, err := st.GetIncarnation(create2address) + if err != nil { + return err + } + if incarnation != 4 { + t.Errorf("expected incarnation 4 (two self-destructs and two-recreations within a block), got %d", incarnation) } } return nil @@ -531,10 +581,14 @@ func TestReorgOverSelfDestruct(t *testing.T) { err = m.DB.View(context.Background(), func(tx kv.Tx) error { st := state.New(m.NewStateReader(tx)) - if !st.Exist(address) { + if exist, err := st.Exist(address); err != nil { + t.Error(err) + } else if !exist { t.Error("expected account to exist") } - if st.Exist(contractAddress) { + if exist, err := st.Exist(contractAddress); err != nil { + t.Error(err) + } else if exist { t.Error("expected contractAddress to not exist before block 0", contractAddress.String()) } return nil @@ -549,7 +603,10 @@ func TestReorgOverSelfDestruct(t *testing.T) { var correctValueX uint256.Int err = m.DB.View(context.Background(), func(tx kv.Tx) error { st := state.New(m.NewStateReader(tx)) - if !st.Exist(contractAddress) { + if exist, err := st.Exist(contractAddress); err != nil { + t.Error(err) + } else if !exist { + t.Error("expected contractAddress to exist at the block 1", contractAddress.String()) } @@ -566,7 +623,9 @@ func TestReorgOverSelfDestruct(t *testing.T) { err = m.DB.View(context.Background(), func(tx kv.Tx) error { st := state.New(m.NewStateReader(tx)) - if st.Exist(contractAddress) { + if exist, err := st.Exist(contractAddress); err != nil { + t.Error(err) + } else if exist { t.Error("expected contractAddress to not exist at the block 3", contractAddress.String()) } return nil @@ -578,7 +637,9 @@ func TestReorgOverSelfDestruct(t *testing.T) { } err = m.DB.View(context.Background(), func(tx kv.Tx) error { st := state.New(m.NewStateReader(tx)) - if !st.Exist(contractAddress) { + if exist, err := st.Exist(contractAddress); err != nil { + t.Error(err) + } else if !exist { t.Error("expected contractAddress to exist at the block 4", contractAddress.String()) } var valueX uint256.Int @@ -671,10 +732,15 @@ func TestReorgOverStateChange(t *testing.T) { err = m.DB.View(context.Background(), func(tx kv.Tx) error { st := state.New(m.NewStateReader(tx)) - if !st.Exist(address) { + if exist, err := st.Exist(address); err != nil { + t.Error(err) + } else if !exist { t.Error("expected account to exist") } - if st.Exist(contractAddress) { + if exist, err := st.Exist(contractAddress); err != nil { + t.Error(err) + } else if exist { + t.Error("expected contractAddress to not exist before block 0", contractAddress.String()) } return nil @@ -690,7 +756,10 @@ func TestReorgOverStateChange(t *testing.T) { var correctValueX uint256.Int err = m.DB.View(context.Background(), func(tx kv.Tx) error { st := state.New(m.NewStateReader(tx)) - if !st.Exist(contractAddress) { + if exist, err := st.Exist(contractAddress); err != nil { + t.Error(err) + } else if !exist { + t.Error("expected contractAddress to exist at the block 1", contractAddress.String()) } @@ -711,7 +780,9 @@ func TestReorgOverStateChange(t *testing.T) { } err = m.DB.View(context.Background(), func(tx kv.Tx) error { st := state.New(m.NewStateReader(tx)) - if !st.Exist(contractAddress) { + if exist, err := st.Exist(contractAddress); err != nil { + t.Error(err) + } else if !exist { t.Error("expected contractAddress to exist at the block 4", contractAddress.String()) } @@ -801,7 +872,9 @@ func TestCreateOnExistingStorage(t *testing.T) { err = m.DB.View(context.Background(), func(tx kv.Tx) error { st := state.New(m.NewStateReader(tx)) - if !st.Exist(address) { + if exist, err := st.Exist(address); err != nil { + t.Error(err) + } else if !exist { t.Error("expected account to exist") } if contractAddress != contractAddr { @@ -820,7 +893,9 @@ func TestCreateOnExistingStorage(t *testing.T) { var check0 uint256.Int err = m.DB.View(context.Background(), func(tx kv.Tx) error { st := state.New(m.NewStateReader(tx)) - if !st.Exist(contractAddress) { + if exist, err := st.Exist(contractAddress); err != nil { + t.Error(err) + } else if !exist { t.Error("expected contractAddress to exist at the block 1", contractAddress.String()) } @@ -947,14 +1022,18 @@ func TestEip2200Gas(t *testing.T) { var balanceBefore *uint256.Int err = m.DB.View(context.Background(), func(tx kv.Tx) error { st := state.New(m.NewStateReader(tx)) - if !st.Exist(address) { + if exist, err := st.Exist(address); err != nil { + t.Error(err) + } else if !exist { t.Error("expected account to exist") } - if st.Exist(contractAddress) { + if exist, err := st.Exist(contractAddress); err != nil { + t.Error(err) + } else if exist { t.Error("expected contractAddress to not exist before block 0", contractAddress.String()) } - balanceBefore = st.GetBalance(address) - return nil + balanceBefore, err = st.GetBalance(address) + return err }) require.NoError(t, err) @@ -965,10 +1044,15 @@ func TestEip2200Gas(t *testing.T) { err = m.DB.View(context.Background(), func(tx kv.Tx) error { st := state.New(m.NewStateReader(tx)) - if !st.Exist(contractAddress) { + if exist, err := st.Exist(contractAddress); err != nil { + t.Error(err) + } else if !exist { t.Error("expected contractAddress to exist at the block 1", contractAddress.String()) } - balanceAfter := st.GetBalance(address) + balanceAfter, err := st.GetBalance(address) + if err != nil { + return err + } gasSpent := big.NewInt(0).Sub(balanceBefore.ToBig(), balanceAfter.ToBig()) expectedGasSpent := big.NewInt(190373) //(192245) // In the incorrect version, it is 179645 if gasSpent.Cmp(expectedGasSpent) != 0 { @@ -1035,10 +1119,14 @@ func TestWrongIncarnation(t *testing.T) { err = m.DB.View(context.Background(), func(tx kv.Tx) error { st := state.New(m.NewStateReader(tx)) - if !st.Exist(address) { + if exist, err := st.Exist(address); err != nil { + t.Error(err) + } else if !exist { t.Error("expected account to exist") } - if st.Exist(contractAddress) { + if exist, err := st.Exist(contractAddress); err != nil { + t.Error(err) + } else if exist { t.Error("expected contractAddress to not exist before block 0", contractAddress.String()) } return nil @@ -1065,7 +1153,9 @@ func TestWrongIncarnation(t *testing.T) { } st := state.New(stateReader) - if !st.Exist(contractAddress) { + if exist, err := st.Exist(contractAddress); err != nil { + t.Error(err) + } else if !exist { t.Error("expected contractAddress to exist at the block 1", contractAddress.String()) } return nil @@ -1185,7 +1275,9 @@ func TestWrongIncarnation2(t *testing.T) { err = m.DB.View(context.Background(), func(tx kv.Tx) error { st := state.New(m.NewStateReader(tx)) - if !st.Exist(address) { + if exist, err := st.Exist(address); err != nil { + t.Error(err) + } else if !exist { t.Error("expected account to exist") } return nil @@ -1204,7 +1296,9 @@ func TestWrongIncarnation2(t *testing.T) { err = m.DB.View(context.Background(), func(tx kv.Tx) error { st := state.New(m.NewStateReader(tx)) - if !st.Exist(contractAddress) { + if exist, err := st.Exist(contractAddress); err != nil { + t.Error(err) + } else if !exist { t.Error("expected contractAddress to exist at the block 1", contractAddress.String()) } @@ -1529,7 +1623,9 @@ func TestRecreateAndRewind(t *testing.T) { var check0 uint256.Int err = m.DB.View(context.Background(), func(tx kv.Tx) error { st := state.New(m.NewStateReader(tx)) - if !st.Exist(phoenixAddress) { + if exist, err := st.Exist(phoenixAddress); err != nil { + t.Error(err) + } else if !exist { t.Errorf("expected phoenix %x to exist after first insert", phoenixAddress) } @@ -1548,7 +1644,9 @@ func TestRecreateAndRewind(t *testing.T) { err = m.DB.View(context.Background(), func(tx kv.Tx) error { st := state.New(m.NewStateReader(tx)) - if !st.Exist(phoenixAddress) { + if exist, err := st.Exist(phoenixAddress); err != nil { + t.Error(err) + } else if !exist { t.Errorf("expected phoenix %x to exist after second insert", phoenixAddress) } @@ -1566,7 +1664,9 @@ func TestRecreateAndRewind(t *testing.T) { } err = m.DB.View(context.Background(), func(tx kv.Tx) error { st := state.New(m.NewStateReader(tx)) - if !st.Exist(phoenixAddress) { + if exist, err := st.Exist(phoenixAddress); err != nil { + t.Error(err) + } else if !exist { t.Errorf("expected phoenix %x to exist after second insert", phoenixAddress) } diff --git a/core/state/intra_block_state.go b/core/state/intra_block_state.go index 030a630bdea..dbd3ee0fbfd 100644 --- a/core/state/intra_block_state.go +++ b/core/state/intra_block_state.go @@ -126,12 +126,14 @@ func (sdb *IntraBlockState) SetTrace(trace bool) { } // setErrorUnsafe sets error but should be called in medhods that already have locks +// Deprecated: The IBS api now returns errors directly func (sdb *IntraBlockState) setErrorUnsafe(err error) { if sdb.savedErr == nil { sdb.savedErr = err } } +// Deprecated: The IBS api now returns errors directly func (sdb *IntraBlockState) Error() error { return sdb.savedErr } @@ -230,36 +232,47 @@ func (sdb *IntraBlockState) SubRefund(gas uint64) { // Exist reports whether the given account address exists in the state. // Notably this also returns true for suicided accounts. -func (sdb *IntraBlockState) Exist(addr libcommon.Address) bool { - s := sdb.getStateObject(addr) - return s != nil && !s.deleted +func (sdb *IntraBlockState) Exist(addr libcommon.Address) (bool, error) { + s, err := sdb.getStateObject(addr) + if err != nil { + return false, err + } + return s != nil && !s.deleted, err } // Empty returns whether the state object is either non-existent // or empty according to the EIP161 specification (balance = nonce = code = 0) -func (sdb *IntraBlockState) Empty(addr libcommon.Address) bool { - so := sdb.getStateObject(addr) - return so == nil || so.deleted || so.empty() +func (sdb *IntraBlockState) Empty(addr libcommon.Address) (bool, error) { + so, err := sdb.getStateObject(addr) + if err != nil { + return false, err + } + return so == nil || so.deleted || so.empty(), nil } // GetBalance retrieves the balance from the given address or 0 if object not found // DESCRIBED: docs/programmers_guide/guide.md#address---identifier-of-an-account -func (sdb *IntraBlockState) GetBalance(addr libcommon.Address) *uint256.Int { - stateObject := sdb.getStateObject(addr) +func (sdb *IntraBlockState) GetBalance(addr libcommon.Address) (*uint256.Int, error) { + stateObject, err := sdb.getStateObject(addr) + if err != nil { + return nil, err + } if stateObject != nil && !stateObject.deleted { - return stateObject.Balance() + return stateObject.Balance(), nil } - return u256.Num0 + return u256.Num0, nil } // DESCRIBED: docs/programmers_guide/guide.md#address---identifier-of-an-account -func (sdb *IntraBlockState) GetNonce(addr libcommon.Address) uint64 { - stateObject := sdb.getStateObject(addr) +func (sdb *IntraBlockState) GetNonce(addr libcommon.Address) (uint64, error) { + stateObject, err := sdb.getStateObject(addr) + if err != nil { + return 0, err + } if stateObject != nil && !stateObject.deleted { - return stateObject.Nonce() + return stateObject.Nonce(), nil } - - return 0 + return 0, nil } // TxIndex returns the current transaction index set by Prepare. @@ -268,120 +281,160 @@ func (sdb *IntraBlockState) TxnIndex() int { } // DESCRIBED: docs/programmers_guide/guide.md#address---identifier-of-an-account -func (sdb *IntraBlockState) GetCode(addr libcommon.Address) []byte { - stateObject := sdb.getStateObject(addr) +func (sdb *IntraBlockState) GetCode(addr libcommon.Address) ([]byte, error) { + stateObject, err := sdb.getStateObject(addr) + if err != nil { + return nil, err + } if stateObject != nil && !stateObject.deleted { if sdb.trace { fmt.Printf("GetCode %x, returned %d\n", addr, len(stateObject.Code())) } - return stateObject.Code() + return stateObject.Code(), nil } if sdb.trace { fmt.Printf("GetCode %x, returned nil\n", addr) } - return nil + return nil, nil } // DESCRIBED: docs/programmers_guide/guide.md#address---identifier-of-an-account -func (sdb *IntraBlockState) GetCodeSize(addr libcommon.Address) int { - stateObject := sdb.getStateObject(addr) +func (sdb *IntraBlockState) GetCodeSize(addr libcommon.Address) (int, error) { + stateObject, err := sdb.getStateObject(addr) + if err != nil { + return 0, err + } if stateObject == nil || stateObject.deleted { - return 0 + return 0, nil } if stateObject.code != nil { - return len(stateObject.code) + return len(stateObject.code), nil } if stateObject.data.CodeHash == emptyCodeHashH { - return 0 + return 0, nil } l, err := sdb.stateReader.ReadAccountCodeSize(addr, stateObject.data.Incarnation) if err != nil { sdb.setErrorUnsafe(err) + return l, err } - return l + return l, err } // DESCRIBED: docs/programmers_guide/guide.md#address---identifier-of-an-account -func (sdb *IntraBlockState) GetCodeHash(addr libcommon.Address) libcommon.Hash { - stateObject := sdb.getStateObject(addr) +func (sdb *IntraBlockState) GetCodeHash(addr libcommon.Address) (libcommon.Hash, error) { + stateObject, err := sdb.getStateObject(addr) + if err != nil { + return libcommon.Hash{}, err + } if stateObject == nil || stateObject.deleted { - return libcommon.Hash{} + return libcommon.Hash{}, nil } - return stateObject.data.CodeHash + return stateObject.data.CodeHash, nil } -func (sdb *IntraBlockState) ResolveCodeHash(addr libcommon.Address) libcommon.Hash { +func (sdb *IntraBlockState) ResolveCodeHash(addr libcommon.Address) (libcommon.Hash, error) { // eip-7702 - if dd, ok := sdb.GetDelegatedDesignation(addr); ok { + dd, ok, err := sdb.GetDelegatedDesignation(addr) + + if ok { return sdb.GetCodeHash(dd) } + if err != nil { + return libcommon.Hash{}, err + } + return sdb.GetCodeHash(addr) } -func (sdb *IntraBlockState) ResolveCode(addr libcommon.Address) []byte { +func (sdb *IntraBlockState) ResolveCode(addr libcommon.Address) ([]byte, error) { // eip-7702 - if dd, ok := sdb.GetDelegatedDesignation(addr); ok { + dd, ok, err := sdb.GetDelegatedDesignation(addr) + if ok { return sdb.GetCode(dd) } - + if err != nil { + return nil, err + } return sdb.GetCode(addr) } -func (sdb *IntraBlockState) ResolveCodeSize(addr libcommon.Address) int { +func (sdb *IntraBlockState) ResolveCodeSize(addr libcommon.Address) (int, error) { // eip-7702 - size := sdb.GetCodeSize(addr) + size, err := sdb.GetCodeSize(addr) + if err != nil { + return 0, err + } if size == types.DelegateDesignationCodeSize { // might be delegated designation - return len(sdb.ResolveCode(addr)) + code, err := sdb.ResolveCode(addr) + if err != nil { + return 0, err + } + return len(code), nil } - return size + return size, nil } -func (sdb *IntraBlockState) GetDelegatedDesignation(addr libcommon.Address) (libcommon.Address, bool) { +func (sdb *IntraBlockState) GetDelegatedDesignation(addr libcommon.Address) (libcommon.Address, bool, error) { // eip-7702 - code := sdb.GetCode(addr) + code, err := sdb.GetCode(addr) + if err != nil { + return EmptyAddress, false, err + } if delegation, ok := types.ParseDelegation(code); ok { - return delegation, true + return delegation, true, nil } - return EmptyAddress, false + return EmptyAddress, false, nil } // GetState retrieves a value from the given account's storage trie. // DESCRIBED: docs/programmers_guide/guide.md#address---identifier-of-an-account -func (sdb *IntraBlockState) GetState(addr libcommon.Address, key *libcommon.Hash, value *uint256.Int) { - stateObject := sdb.getStateObject(addr) +func (sdb *IntraBlockState) GetState(addr libcommon.Address, key *libcommon.Hash, value *uint256.Int) error { + stateObject, err := sdb.getStateObject(addr) + if err != nil { + return err + } if stateObject != nil && !stateObject.deleted { stateObject.GetState(key, value) } else { value.Clear() } + return nil } // GetCommittedState retrieves a value from the given account's committed storage trie. // DESCRIBED: docs/programmers_guide/guide.md#address---identifier-of-an-account -func (sdb *IntraBlockState) GetCommittedState(addr libcommon.Address, key *libcommon.Hash, value *uint256.Int) { - stateObject := sdb.getStateObject(addr) +func (sdb *IntraBlockState) GetCommittedState(addr libcommon.Address, key *libcommon.Hash, value *uint256.Int) error { + stateObject, err := sdb.getStateObject(addr) + if err != nil { + return err + } if stateObject != nil && !stateObject.deleted { stateObject.GetCommittedState(key, value) } else { value.Clear() } + return nil } -func (sdb *IntraBlockState) HasSelfdestructed(addr libcommon.Address) bool { - stateObject := sdb.getStateObject(addr) +func (sdb *IntraBlockState) HasSelfdestructed(addr libcommon.Address) (bool, error) { + stateObject, err := sdb.getStateObject(addr) + if err != nil { + return false, err + } if stateObject == nil { - return false + return false, nil } if stateObject.deleted { - return false + return false, nil } if stateObject.createdContract { - return false + return false, nil } - return stateObject.selfdestructed + return stateObject.selfdestructed, nil } /* @@ -390,7 +443,7 @@ func (sdb *IntraBlockState) HasSelfdestructed(addr libcommon.Address) bool { // AddBalance adds amount to the account associated with addr. // DESCRIBED: docs/programmers_guide/guide.md#address---identifier-of-an-account -func (sdb *IntraBlockState) AddBalance(addr libcommon.Address, amount *uint256.Int, reason tracing.BalanceChangeReason) { +func (sdb *IntraBlockState) AddBalance(addr libcommon.Address, amount *uint256.Int, reason tracing.BalanceChangeReason) error { if sdb.trace { fmt.Printf("AddBalance %x, %d\n", addr, amount) } @@ -427,82 +480,117 @@ func (sdb *IntraBlockState) AddBalance(addr libcommon.Address, amount *uint256.I bi.increase.Add(&bi.increase, amount) bi.count++ - return + return nil } - stateObject := sdb.GetOrNewStateObject(addr) + stateObject, err := sdb.GetOrNewStateObject(addr) + if err != nil { + return err + } stateObject.AddBalance(amount, reason) + return nil } // SubBalance subtracts amount from the account associated with addr. // DESCRIBED: docs/programmers_guide/guide.md#address---identifier-of-an-account -func (sdb *IntraBlockState) SubBalance(addr libcommon.Address, amount *uint256.Int, reason tracing.BalanceChangeReason) { +func (sdb *IntraBlockState) SubBalance(addr libcommon.Address, amount *uint256.Int, reason tracing.BalanceChangeReason) error { if sdb.trace { fmt.Printf("SubBalance %x, %d\n", addr, amount) } - stateObject := sdb.GetOrNewStateObject(addr) + stateObject, err := sdb.GetOrNewStateObject(addr) + if err != nil { + return err + } if stateObject != nil { stateObject.SubBalance(amount, reason) } + return nil } // DESCRIBED: docs/programmers_guide/guide.md#address---identifier-of-an-account -func (sdb *IntraBlockState) SetBalance(addr libcommon.Address, amount *uint256.Int, reason tracing.BalanceChangeReason) { - stateObject := sdb.GetOrNewStateObject(addr) +func (sdb *IntraBlockState) SetBalance(addr libcommon.Address, amount *uint256.Int, reason tracing.BalanceChangeReason) error { + stateObject, err := sdb.GetOrNewStateObject(addr) + if err != nil { + return err + } if stateObject != nil { stateObject.SetBalance(amount, reason) } + return nil } // DESCRIBED: docs/programmers_guide/guide.md#address---identifier-of-an-account -func (sdb *IntraBlockState) SetNonce(addr libcommon.Address, nonce uint64) { - stateObject := sdb.GetOrNewStateObject(addr) +func (sdb *IntraBlockState) SetNonce(addr libcommon.Address, nonce uint64) error { + stateObject, err := sdb.GetOrNewStateObject(addr) + if err != nil { + return err + } if stateObject != nil { stateObject.SetNonce(nonce) } + return nil } // DESCRIBED: docs/programmers_guide/guide.md#code-hash // DESCRIBED: docs/programmers_guide/guide.md#address---identifier-of-an-account -func (sdb *IntraBlockState) SetCode(addr libcommon.Address, code []byte) { - stateObject := sdb.GetOrNewStateObject(addr) +func (sdb *IntraBlockState) SetCode(addr libcommon.Address, code []byte) error { + stateObject, err := sdb.GetOrNewStateObject(addr) + if err != nil { + return err + } if stateObject != nil { stateObject.SetCode(crypto.Keccak256Hash(code), code) } + return nil } // DESCRIBED: docs/programmers_guide/guide.md#address---identifier-of-an-account -func (sdb *IntraBlockState) SetState(addr libcommon.Address, key *libcommon.Hash, value uint256.Int) { - stateObject := sdb.GetOrNewStateObject(addr) +func (sdb *IntraBlockState) SetState(addr libcommon.Address, key *libcommon.Hash, value uint256.Int) error { + stateObject, err := sdb.GetOrNewStateObject(addr) + if err != nil { + return err + } if stateObject != nil { stateObject.SetState(key, value) } + return nil } // SetStorage replaces the entire storage for the specified account with given // storage. This function should only be used for debugging. -func (sdb *IntraBlockState) SetStorage(addr libcommon.Address, storage Storage) { - stateObject := sdb.GetOrNewStateObject(addr) +func (sdb *IntraBlockState) SetStorage(addr libcommon.Address, storage Storage) error { + stateObject, err := sdb.GetOrNewStateObject(addr) + if err != nil { + return err + } if stateObject != nil { stateObject.SetStorage(storage) } + return nil } // SetIncarnation sets incarnation for account if account exists -func (sdb *IntraBlockState) SetIncarnation(addr libcommon.Address, incarnation uint64) { - stateObject := sdb.GetOrNewStateObject(addr) +func (sdb *IntraBlockState) SetIncarnation(addr libcommon.Address, incarnation uint64) error { + stateObject, err := sdb.GetOrNewStateObject(addr) + if err != nil { + return err + } if stateObject != nil { stateObject.setIncarnation(incarnation) } + return nil } -func (sdb *IntraBlockState) GetIncarnation(addr libcommon.Address) uint64 { - stateObject := sdb.getStateObject(addr) +func (sdb *IntraBlockState) GetIncarnation(addr libcommon.Address) (uint64, error) { + stateObject, err := sdb.getStateObject(addr) + if err != nil { + return 0, err + } if stateObject != nil { - return stateObject.data.Incarnation + return stateObject.data.Incarnation, nil } - return 0 + return 0, nil } // Selfdestruct marks the given account as suicided. @@ -510,10 +598,13 @@ func (sdb *IntraBlockState) GetIncarnation(addr libcommon.Address) uint64 { // // The account's state object is still available until the state is committed, // getStateObject will return a non-nil account after Suicide. -func (sdb *IntraBlockState) Selfdestruct(addr libcommon.Address) bool { - stateObject := sdb.getStateObject(addr) +func (sdb *IntraBlockState) Selfdestruct(addr libcommon.Address) (bool, error) { + stateObject, err := sdb.getStateObject(addr) + if err != nil { + return false, err + } if stateObject == nil || stateObject.deleted { - return false + return false, nil } prevBalance := *stateObject.Balance() @@ -531,19 +622,27 @@ func (sdb *IntraBlockState) Selfdestruct(addr libcommon.Address) bool { stateObject.createdContract = false stateObject.data.Balance.Clear() - return true + return true, nil } -func (sdb *IntraBlockState) Selfdestruct6780(addr libcommon.Address) { - stateObject := sdb.getStateObject(addr) +func (sdb *IntraBlockState) Selfdestruct6780(addr libcommon.Address) error { + stateObject, err := sdb.getStateObject(addr) + if err != nil { + return err + } if stateObject == nil { - return + return nil } if stateObject.newlyCreated { - if _, ok := types.ParseDelegation(sdb.GetCode(addr)); !ok { + code, err := sdb.GetCode(addr) + if err != nil { + return err + } + if _, ok := types.ParseDelegation(code); !ok { sdb.Selfdestruct(addr) } } + return nil } // SetTransientState sets transient storage for a given account. It @@ -575,36 +674,36 @@ func (sdb *IntraBlockState) GetTransientState(addr libcommon.Address, key libcom return sdb.transientStorage.Get(addr, key) } -func (sdb *IntraBlockState) getStateObject(addr libcommon.Address) (stateObject *stateObject) { +func (sdb *IntraBlockState) getStateObject(addr libcommon.Address) (stateObject *stateObject, err error) { // Prefer 'live' objects. if obj := sdb.stateObjects[addr]; obj != nil { - return obj + return obj, nil } // Load the object from the database. if _, ok := sdb.nilAccounts[addr]; ok { if bi, ok := sdb.balanceInc[addr]; ok && !bi.transferred { - return sdb.createObject(addr, nil) + return sdb.createObject(addr, nil), nil } - return nil + return nil, nil } account, err := sdb.stateReader.ReadAccountData(addr) if err != nil { sdb.setErrorUnsafe(err) - return nil + return nil, err } if account == nil { sdb.nilAccounts[addr] = struct{}{} if bi, ok := sdb.balanceInc[addr]; ok && !bi.transferred { - return sdb.createObject(addr, nil) + return sdb.createObject(addr, nil), nil } - return nil + return nil, nil } // Insert into the live set. obj := newObject(sdb, addr, account, account) sdb.setStateObject(addr, obj) - return obj + return obj, nil } func (sdb *IntraBlockState) setStateObject(addr libcommon.Address, object *stateObject) { @@ -617,12 +716,15 @@ func (sdb *IntraBlockState) setStateObject(addr libcommon.Address, object *state } // Retrieve a state object or create a new state object if nil. -func (sdb *IntraBlockState) GetOrNewStateObject(addr libcommon.Address) *stateObject { - stateObject := sdb.getStateObject(addr) +func (sdb *IntraBlockState) GetOrNewStateObject(addr libcommon.Address) (*stateObject, error) { + stateObject, err := sdb.getStateObject(addr) + if err != nil { + return nil, err + } if stateObject == nil || stateObject.deleted { stateObject = sdb.createObject(addr, stateObject /* previous */) } - return stateObject + return stateObject, nil } // createObject creates a new state object. If there is an existing account with @@ -658,9 +760,12 @@ func (sdb *IntraBlockState) createObject(addr libcommon.Address, previous *state // 2. tx_create(sha(account ++ nonce)) (note that this gets the address of 1) // // Carrying over the balance ensures that Ether doesn't disappear. -func (sdb *IntraBlockState) CreateAccount(addr libcommon.Address, contractCreation bool) { +func (sdb *IntraBlockState) CreateAccount(addr libcommon.Address, contractCreation bool) error { var prevInc uint64 - previous := sdb.getStateObject(addr) + previous, err := sdb.getStateObject(addr) + if err != nil { + return err + } if previous != nil && previous.selfdestructed { prevInc = previous.data.Incarnation } else { @@ -668,6 +773,7 @@ func (sdb *IntraBlockState) CreateAccount(addr libcommon.Address, contractCreati prevInc = inc } else { sdb.savedErr = err + return err } } if previous != nil && prevInc < previous.data.PrevIncarnation { @@ -687,6 +793,7 @@ func (sdb *IntraBlockState) CreateAccount(addr libcommon.Address, contractCreati } else { newObj.selfdestructed = false } + return nil } // Snapshot returns an identifier for the current revision of the state. @@ -910,7 +1017,7 @@ func (sdb *IntraBlockState) clearJournalAndRefund() { // - Add authorities to access list (EIP-7702) // - Add delegated designation (if it exists for dst) to access list (EIP-7702) func (sdb *IntraBlockState) Prepare(rules *chain.Rules, sender, coinbase libcommon.Address, dst *libcommon.Address, - precompiles []libcommon.Address, list types.AccessList, authorities []libcommon.Address) { + precompiles []libcommon.Address, list types.AccessList, authorities []libcommon.Address) error { if sdb.trace { fmt.Printf("ibs.Prepare %x, %x, %x, %x, %v, %v, %v\n", sender, coinbase, dst, precompiles, list, rules, authorities) } @@ -945,13 +1052,18 @@ func (sdb *IntraBlockState) Prepare(rules *chain.Rules, sender, coinbase libcomm } if dst != nil { - if dd, ok := sdb.GetDelegatedDesignation(*dst); ok { + dd, ok, err := sdb.GetDelegatedDesignation(*dst) + if err != nil { + return err + } + if ok { sdb.AddAddressToAccessList(dd) } } } // Reset transient storage at the beginning of transaction execution sdb.transientStorage = newTransientStorage() + return nil } // AddAddressToAccessList adds the given address to the access list diff --git a/core/state/intra_block_state_logger_test.go b/core/state/intra_block_state_logger_test.go index 11c5023c940..cc5fed21804 100644 --- a/core/state/intra_block_state_logger_test.go +++ b/core/state/intra_block_state_logger_test.go @@ -86,7 +86,8 @@ func TestStateLogger(t *testing.T) { } } - so := stateDB.GetOrNewStateObject(libcommon.Address{}) + so, err := stateDB.GetOrNewStateObject(libcommon.Address{}) + require.NoError(t, err) if !reflect.DeepEqual(so.Balance(), uint256.NewInt(3)) { t.Errorf("Incorrect Balance for %s expectedBalance: %s, got:%s", libcommon.Address{}, uint256.NewInt(3), so.Balance()) } @@ -103,7 +104,8 @@ func TestStateLogger(t *testing.T) { state.SubBalance(libcommon.Address{}, uint256.NewInt(1), tracing.BalanceChangeUnspecified) }, checker: func(t *testing.T, stateDB *IntraBlockState) { - so := stateDB.GetOrNewStateObject(libcommon.Address{}) + so, err := stateDB.GetOrNewStateObject(libcommon.Address{}) + require.NoError(t, err) if !reflect.DeepEqual(so.Balance(), uint256.NewInt(1)) { t.Errorf("Incorrect Balance for %s expectedBalance: %s, got:%s", libcommon.Address{}, uint256.NewInt(1), so.Balance()) } diff --git a/core/state/intra_block_state_test.go b/core/state/intra_block_state_test.go index b2c1c5321e6..f7d0767015c 100644 --- a/core/state/intra_block_state_test.go +++ b/core/state/intra_block_state_test.go @@ -323,17 +323,77 @@ func (test *snapshotTest) checkEqual(state, checkstate *IntraBlockState) error { return true } // Check basic accessor methods. - if !checkeq("Exist", state.Exist(addr), checkstate.Exist(addr)) { + se, err := state.Exist(addr) + if err != nil { return err } - checkeq("HasSelfdestructed", state.HasSelfdestructed(addr), checkstate.HasSelfdestructed(addr)) - checkeqBigInt("GetBalance", state.GetBalance(addr).ToBig(), checkstate.GetBalance(addr).ToBig()) - checkeq("GetNonce", state.GetNonce(addr), checkstate.GetNonce(addr)) - checkeq("GetCode", state.GetCode(addr), checkstate.GetCode(addr)) - checkeq("GetCodeHash", state.GetCodeHash(addr), checkstate.GetCodeHash(addr)) - checkeq("GetCodeSize", state.GetCodeSize(addr), checkstate.GetCodeSize(addr)) + ce, err := checkstate.Exist(addr) + if err != nil { + return err + } + if !checkeq("Exist", se, ce) { + return err + } + ssd, err := state.HasSelfdestructed(addr) + if err != nil { + return err + } + csd, err := checkstate.HasSelfdestructed(addr) + if err != nil { + return err + } + checkeq("HasSelfdestructed", ssd, csd) + sb, err := state.GetBalance(addr) + if err != nil { + return err + } + cb, err := checkstate.GetBalance(addr) + if err != nil { + return err + } + checkeqBigInt("GetBalance", sb.ToBig(), cb.ToBig()) + sn, err := state.GetNonce(addr) + if err != nil { + return err + } + cn, err := checkstate.GetNonce(addr) + if err != nil { + return err + } + checkeq("GetNonce", sn, cn) + sc, err := state.GetCode(addr) + if err != nil { + return err + } + cc, err := checkstate.GetCode(addr) + if err != nil { + return err + } + checkeq("GetCode", sc, cc) + sch, err := state.GetCodeHash(addr) + if err != nil { + return err + } + cch, err := checkstate.GetCodeHash(addr) + if err != nil { + return err + } + checkeq("GetCodeHash", sch, cch) + scs, err := state.GetCodeSize(addr) + if err != nil { + return err + } + ccs, err := checkstate.GetCodeSize(addr) + if err != nil { + return err + } + checkeq("GetCodeSize", scs, ccs) // Check storage. - if obj := state.getStateObject(addr); obj != nil { + obj, err := state.getStateObject(addr) + if err != nil { + return err + } + if obj != nil { for key, value := range obj.dirtyStorage { var out uint256.Int checkstate.GetState(addr, &key, &out) @@ -342,7 +402,11 @@ func (test *snapshotTest) checkEqual(state, checkstate *IntraBlockState) error { } } } - if obj := checkstate.getStateObject(addr); obj != nil { + obj, err = checkstate.getStateObject(addr) + if err != nil { + return err + } + if obj != nil { for key, value := range obj.dirtyStorage { var out uint256.Int state.GetState(addr, &key, &out) diff --git a/core/state/journal.go b/core/state/journal.go index 663f70baeb9..fd7dc7fa13a 100644 --- a/core/state/journal.go +++ b/core/state/journal.go @@ -29,7 +29,7 @@ import ( // reverted on demand. type journalEntry interface { // revert undoes the changes introduced by this journal entry. - revert(*IntraBlockState) + revert(*IntraBlockState) error // dirtied returns the Ethereum address modified by this journal entry. dirtied() *libcommon.Address @@ -172,29 +172,35 @@ type ( // refundChange | addLogChange | touchChange | accessListAddAccountChange | accessListAddSlotChange | transientStorageChange //} -func (ch createObjectChange) revert(s *IntraBlockState) { +func (ch createObjectChange) revert(s *IntraBlockState) error { delete(s.stateObjects, *ch.account) delete(s.stateObjectsDirty, *ch.account) + return nil } func (ch createObjectChange) dirtied() *libcommon.Address { return ch.account } -func (ch resetObjectChange) revert(s *IntraBlockState) { +func (ch resetObjectChange) revert(s *IntraBlockState) error { s.setStateObject(*ch.account, ch.prev) + return nil } func (ch resetObjectChange) dirtied() *libcommon.Address { return nil } -func (ch selfdestructChange) revert(s *IntraBlockState) { - obj := s.getStateObject(*ch.account) +func (ch selfdestructChange) revert(s *IntraBlockState) error { + obj, err := s.getStateObject(*ch.account) + if err != nil { + return err + } if obj != nil { obj.selfdestructed = ch.prev obj.setBalance(&ch.prevbalance) } + return nil } func (ch selfdestructChange) dirtied() *libcommon.Address { @@ -203,22 +209,28 @@ func (ch selfdestructChange) dirtied() *libcommon.Address { var ripemd = libcommon.HexToAddress("0000000000000000000000000000000000000003") -func (ch touchChange) revert(s *IntraBlockState) { +func (ch touchChange) revert(s *IntraBlockState) error { + return nil } func (ch touchChange) dirtied() *libcommon.Address { return ch.account } -func (ch balanceChange) revert(s *IntraBlockState) { - s.getStateObject(*ch.account).setBalance(&ch.prev) +func (ch balanceChange) revert(s *IntraBlockState) error { + obj, err := s.getStateObject(*ch.account) + if err != nil { + return err + } + obj.setBalance(&ch.prev) + return nil } func (ch balanceChange) dirtied() *libcommon.Address { return ch.account } -func (ch balanceIncrease) revert(s *IntraBlockState) { +func (ch balanceIncrease) revert(s *IntraBlockState) error { if bi, ok := s.balanceInc[*ch.account]; ok { bi.increase.Sub(&bi.increase, &ch.increase) bi.count-- @@ -226,6 +238,7 @@ func (ch balanceIncrease) revert(s *IntraBlockState) { delete(s.balanceInc, *ch.account) } } + return nil } func (ch balanceIncrease) dirtied() *libcommon.Address { @@ -236,71 +249,95 @@ func (ch balanceIncreaseTransfer) dirtied() *libcommon.Address { return nil } -func (ch balanceIncreaseTransfer) revert(s *IntraBlockState) { +func (ch balanceIncreaseTransfer) revert(s *IntraBlockState) error { ch.bi.transferred = false + return nil } -func (ch nonceChange) revert(s *IntraBlockState) { - s.getStateObject(*ch.account).setNonce(ch.prev) +func (ch nonceChange) revert(s *IntraBlockState) error { + obj, err := s.getStateObject(*ch.account) + if err != nil { + return err + } + obj.setNonce(ch.prev) + return nil } func (ch nonceChange) dirtied() *libcommon.Address { return ch.account } -func (ch codeChange) revert(s *IntraBlockState) { - s.getStateObject(*ch.account).setCode(ch.prevhash, ch.prevcode) +func (ch codeChange) revert(s *IntraBlockState) error { + obj, err := s.getStateObject(*ch.account) + if err != nil { + return err + } + obj.setCode(ch.prevhash, ch.prevcode) + return nil } func (ch codeChange) dirtied() *libcommon.Address { return ch.account } -func (ch storageChange) revert(s *IntraBlockState) { - s.getStateObject(*ch.account).setState(&ch.key, ch.prevalue) +func (ch storageChange) revert(s *IntraBlockState) error { + obj, err := s.getStateObject(*ch.account) + if err != nil { + return err + } + obj.setState(&ch.key, ch.prevalue) + return nil } func (ch storageChange) dirtied() *libcommon.Address { return ch.account } -func (ch fakeStorageChange) revert(s *IntraBlockState) { - s.getStateObject(*ch.account).fakeStorage[ch.key] = ch.prevalue +func (ch fakeStorageChange) revert(s *IntraBlockState) error { + obj, err := s.getStateObject(*ch.account) + if err != nil { + return err + } + obj.fakeStorage[ch.key] = ch.prevalue + return nil } func (ch fakeStorageChange) dirtied() *libcommon.Address { return ch.account } -func (ch transientStorageChange) revert(s *IntraBlockState) { +func (ch transientStorageChange) revert(s *IntraBlockState) error { s.setTransientState(*ch.account, ch.key, ch.prevalue) + return nil } func (ch transientStorageChange) dirtied() *libcommon.Address { return nil } -func (ch refundChange) revert(s *IntraBlockState) { +func (ch refundChange) revert(s *IntraBlockState) error { s.refund = ch.prev + return nil } func (ch refundChange) dirtied() *libcommon.Address { return nil } -func (ch addLogChange) revert(s *IntraBlockState) { +func (ch addLogChange) revert(s *IntraBlockState) error { txnLogs := s.logs[ch.txIndex] s.logs[ch.txIndex] = txnLogs[:len(txnLogs)-1] // revert 1 log if len(s.logs[ch.txIndex]) == 0 { s.logs = s.logs[:len(s.logs)-1] // revert txn } s.logSize-- + return nil } func (ch addLogChange) dirtied() *libcommon.Address { return nil } -func (ch accessListAddAccountChange) revert(s *IntraBlockState) { +func (ch accessListAddAccountChange) revert(s *IntraBlockState) error { /* One important invariant here, is that whenever a (addr, slot) is added, if the addr is not already present, the add causes two journal entries: @@ -311,14 +348,16 @@ func (ch accessListAddAccountChange) revert(s *IntraBlockState) { a single (addr) change. */ s.accessList.DeleteAddress(*ch.address) + return nil } func (ch accessListAddAccountChange) dirtied() *libcommon.Address { return nil } -func (ch accessListAddSlotChange) revert(s *IntraBlockState) { +func (ch accessListAddSlotChange) revert(s *IntraBlockState) error { s.accessList.DeleteSlot(*ch.address, *ch.slot) + return nil } func (ch accessListAddSlotChange) dirtied() *libcommon.Address { diff --git a/core/state/state_test.go b/core/state/state_test.go index 3a5665b359b..6ca1639a8f2 100644 --- a/core/state/state_test.go +++ b/core/state/state_test.go @@ -57,15 +57,18 @@ var _ = checker.Suite(&StateSuite{}) func (s *StateSuite) TestDump(c *checker.C) { // generate a few entries - obj1 := s.state.GetOrNewStateObject(toAddr([]byte{0x01})) + obj1, err := s.state.GetOrNewStateObject(toAddr([]byte{0x01})) + c.Check(err, checker.IsNil) obj1.AddBalance(uint256.NewInt(22), tracing.BalanceChangeUnspecified) - obj2 := s.state.GetOrNewStateObject(toAddr([]byte{0x01, 0x02})) + obj2, err := s.state.GetOrNewStateObject(toAddr([]byte{0x01, 0x02})) + c.Check(err, checker.IsNil) obj2.SetCode(crypto.Keccak256Hash([]byte{3, 3, 3, 3, 3, 3, 3}), []byte{3, 3, 3, 3, 3, 3, 3}) - obj3 := s.state.GetOrNewStateObject(toAddr([]byte{0x02})) + obj3, err := s.state.GetOrNewStateObject(toAddr([]byte{0x02})) + c.Check(err, checker.IsNil) obj3.SetBalance(uint256.NewInt(44), tracing.BalanceChangeUnspecified) // write some of them to the trie - err := s.w.UpdateAccountData(obj1.address, &obj1.data, new(accounts.Account)) + err = s.w.UpdateAccountData(obj1.address, &obj1.data, new(accounts.Account)) c.Check(err, checker.IsNil) err = s.w.UpdateAccountData(obj2.address, &obj2.data, new(accounts.Account)) c.Check(err, checker.IsNil) @@ -273,7 +276,10 @@ func TestSnapshot2(t *testing.T) { state.SetState(stateobjaddr1, &storageaddr, *data1) // db, trie are already non-empty values - so0 := state.getStateObject(stateobjaddr0) + so0, err := state.getStateObject(stateobjaddr0) + if err != nil { + t.Fatal("getting state", err) + } so0.SetBalance(uint256.NewInt(42), tracing.BalanceChangeUnspecified) so0.SetNonce(43) so0.SetCode(crypto.Keccak256Hash([]byte{'c', 'a', 'f', 'e'}), []byte{'c', 'a', 'f', 'e'}) @@ -292,7 +298,10 @@ func TestSnapshot2(t *testing.T) { } // and one with deleted == true - so1 := state.getStateObject(stateobjaddr1) + so1, err := state.getStateObject(stateobjaddr1) + if err != nil { + t.Fatal("getting state", err) + } so1.SetBalance(uint256.NewInt(52), tracing.BalanceChangeUnspecified) so1.SetNonce(53) so1.SetCode(crypto.Keccak256Hash([]byte{'c', 'a', 'f', 'e', '2'}), []byte{'c', 'a', 'f', 'e', '2'}) @@ -300,7 +309,10 @@ func TestSnapshot2(t *testing.T) { so1.deleted = true state.setStateObject(stateobjaddr1, so1) - so1 = state.getStateObject(stateobjaddr1) + so1, err = state.getStateObject(stateobjaddr1) + if err != nil { + t.Fatal("getting state", err) + } if so1 != nil && !so1.deleted { t.Fatalf("deleted object not nil when getting") } @@ -308,7 +320,10 @@ func TestSnapshot2(t *testing.T) { snapshot := state.Snapshot() state.RevertToSnapshot(snapshot) - so0Restored := state.getStateObject(stateobjaddr0) + so0Restored, err := state.getStateObject(stateobjaddr0) + if err != nil { + t.Fatal("getting restored state", err) + } // Update lazily-loaded values before comparing. var tmp uint256.Int so0Restored.GetState(&storageaddr, &tmp) @@ -317,7 +332,10 @@ func TestSnapshot2(t *testing.T) { compareStateObjects(so0Restored, so0, t) // deleted should be nil, both before and after restore of state copy - so1Restored := state.getStateObject(stateobjaddr1) + so1Restored, err := state.getStateObject(stateobjaddr1) + if err != nil { + t.Fatal("getting restored state", err) + } if so1Restored != nil && !so1Restored.deleted { t.Fatalf("deleted object not nil after restoring snapshot: %+v", so1Restored) } @@ -410,12 +428,15 @@ func TestDump(t *testing.T) { st := New(NewReaderV3(domains)) // generate a few entries - obj1 := st.GetOrNewStateObject(toAddr([]byte{0x01})) + obj1, err := st.GetOrNewStateObject(toAddr([]byte{0x01})) + require.NoError(t, err) obj1.AddBalance(uint256.NewInt(22), tracing.BalanceChangeUnspecified) - obj2 := st.GetOrNewStateObject(toAddr([]byte{0x01, 0x02})) + obj2, err := st.GetOrNewStateObject(toAddr([]byte{0x01, 0x02})) + require.NoError(t, err) obj2.SetCode(crypto.Keccak256Hash([]byte{3, 3, 3, 3, 3, 3, 3}), []byte{3, 3, 3, 3, 3, 3, 3}) obj2.setIncarnation(1) - obj3 := st.GetOrNewStateObject(toAddr([]byte{0x02})) + obj3, err := st.GetOrNewStateObject(toAddr([]byte{0x02})) + require.NoError(t, err) obj3.SetBalance(uint256.NewInt(44), tracing.BalanceChangeUnspecified) w := NewWriterV4(domains) diff --git a/core/state/txtask.go b/core/state/txtask.go index 8604c3a38d4..6ea205cbeff 100644 --- a/core/state/txtask.go +++ b/core/state/txtask.go @@ -140,7 +140,7 @@ func (t *TxTask) createReceipt(cumulativeGasUsed uint64) *types.Receipt { //} return receipt } -func (t *TxTask) Reset() { +func (t *TxTask) Reset() *TxTask { t.BalanceIncreaseSet = nil returnReadList(t.ReadLists) t.ReadLists = nil @@ -149,6 +149,9 @@ func (t *TxTask) Reset() { t.Logs = nil t.TraceFroms = nil t.TraceTos = nil + t.Error = nil + t.Failed = false + return t } // TxTaskQueue non-thread-safe priority-queue diff --git a/core/state_transition.go b/core/state_transition.go index fdda38bd87c..52141f37dbe 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -62,6 +62,9 @@ The state transitioning model does all the necessary work to work out a valid ne 5) Run Script section 6) Derive new state root */ + +var ErrStateTransitionFailed = errors.New("state transitaion failed") + type StateTransition struct { gp *GasPool msg Message @@ -209,7 +212,11 @@ func (st *StateTransition) buyGas(gasBailout bool) error { } } } - if have, want := st.state.GetBalance(st.msg.From()), balanceCheck; have.Cmp(want) < 0 { + balance, err := st.state.GetBalance(st.msg.From()) + if err != nil { + return err + } + if have, want := balance, balanceCheck; have.Cmp(want) < 0 { return fmt.Errorf("%w: address %v have %v want %v", ErrInsufficientFunds, st.msg.From().Hex(), have, want) } st.state.SubBalance(st.msg.From(), gasVal, tracing.BalanceDecreaseGasBuy) @@ -241,7 +248,10 @@ func CheckEip1559TxGasFeeCap(from libcommon.Address, gasFeeCap, tip, baseFee *ui func (st *StateTransition) preCheck(gasBailout bool) error { // Make sure this transaction's nonce is correct. if st.msg.CheckNonce() { - stNonce := st.state.GetNonce(st.msg.From()) + stNonce, err := st.state.GetNonce(st.msg.From()) + if err != nil { + return fmt.Errorf("%w: %w", ErrStateTransitionFailed, err) + } if msgNonce := st.msg.Nonce(); stNonce < msgNonce { return fmt.Errorf("%w: address %v, tx: %d state: %d", ErrNonceTooHigh, st.msg.From().Hex(), msgNonce, stNonce) @@ -254,13 +264,21 @@ func (st *StateTransition) preCheck(gasBailout bool) error { } // Make sure the sender is an EOA (EIP-3607) - if codeHash := st.state.GetCodeHash(st.msg.From()); codeHash != emptyCodeHash && codeHash != (libcommon.Hash{}) { + codeHash, err := st.state.GetCodeHash(st.msg.From()) + if err != nil { + return fmt.Errorf("%w: %w", ErrStateTransitionFailed, err) + } + if codeHash != emptyCodeHash && codeHash != (libcommon.Hash{}) { // libcommon.Hash{} means that the sender is not in the state. // Historically there were transactions with 0 gas price and non-existing sender, // so we have to allow that. // eip-7702 allows tx origination from accounts having delegated designation code. - if _, ok := st.state.GetDelegatedDesignation(st.msg.From()); !ok { + _, ok, err := st.state.GetDelegatedDesignation(st.msg.From()) + if err != nil { + return fmt.Errorf("%w: %w", ErrStateTransitionFailed, err) + } + if !ok { return fmt.Errorf("%w: address %v, codehash: %s", ErrSenderNoEOA, st.msg.From().Hex(), codeHash) } @@ -307,8 +325,16 @@ func (st *StateTransition) preCheck(gasBailout bool) error { // nil evm execution result. func (st *StateTransition) TransitionDb(refunds bool, gasBailout bool) (*evmtypes.ExecutionResult, error) { coinbase := st.evm.Context.Coinbase - senderInitBalance := st.state.GetBalance(st.msg.From()).Clone() - coinbaseInitBalance := st.state.GetBalance(coinbase).Clone() + senderInitBalance, err := st.state.GetBalance(st.msg.From()) + if err != nil { + return nil, fmt.Errorf("%w: %w", ErrStateTransitionFailed, err) + } + senderInitBalance = senderInitBalance.Clone() + coinbaseInitBalance, err := st.state.GetBalance(coinbase) + if err != nil { + return nil, fmt.Errorf("%w: %w", ErrStateTransitionFailed, err) + } + coinbaseInitBalance = coinbaseInitBalance.Clone() // First check this message satisfies all consensus rules before // applying the message. The rules include these clauses @@ -341,7 +367,11 @@ func (st *StateTransition) TransitionDb(refunds bool, gasBailout bool) (*evmtype if !contractCreation { // Increment the nonce for the next transaction - st.state.SetNonce(msg.From(), st.state.GetNonce(sender.Address())+1) + nonce, err := st.state.GetNonce(sender.Address()) + if err != nil { + return nil, fmt.Errorf("%w: %w", ErrStateTransitionFailed, err) + } + st.state.SetNonce(msg.From(), nonce+1) } // set code tx @@ -375,37 +405,57 @@ func (st *StateTransition) TransitionDb(refunds bool, gasBailout bool) (*evmtype // authority is added to accessed_address in prepare step // 4. authority code should be empty or already delegated - if codeHash := st.state.GetCodeHash(authority); codeHash != emptyCodeHash && codeHash != (libcommon.Hash{}) { + codeHash, err := st.state.GetCodeHash(authority) + if err != nil { + return nil, fmt.Errorf("%w: %w", ErrStateTransitionFailed, err) + } + if codeHash != emptyCodeHash && codeHash != (libcommon.Hash{}) { // check for delegation - if _, ok := st.state.GetDelegatedDesignation(authority); ok { - // noop: has delegated designation - } else { + _, ok, err := st.state.GetDelegatedDesignation(authority) + if err != nil { + return nil, fmt.Errorf("%w: %w", ErrStateTransitionFailed, err) + } + if !ok { log.Debug("authority code is not empty or not delegated, skipping", "auth index", i) continue } + // noop: has delegated designation } // 5. nonce check - authorityNonce := st.state.GetNonce(authority) + authorityNonce, err := st.state.GetNonce(authority) + if err != nil { + return nil, fmt.Errorf("%w: %w", ErrStateTransitionFailed, err) + } if authorityNonce != auth.Nonce { log.Debug("invalid nonce, skipping", "auth index", i) continue } // 6. Add PER_EMPTY_ACCOUNT_COST - PER_AUTH_BASE_COST gas to the global refund counter if authority exists in the trie. - if st.state.Exist(authority) { + exists, err := st.state.Exist(authority) + if err != nil { + return nil, fmt.Errorf("%w: %w", ErrStateTransitionFailed, err) + } + if exists { st.state.AddRefund(fixedgas.PerEmptyAccountCost - fixedgas.PerAuthBaseCost) } // 7. set authority code if auth.Address == (libcommon.Address{}) { - st.state.SetCode(authority, nil) + if err := st.state.SetCode(authority, nil); err != nil { + return nil, fmt.Errorf("%w: %w", ErrStateTransitionFailed, err) + } } else { - st.state.SetCode(authority, types.AddressToDelegation(auth.Address)) + if err := st.state.SetCode(authority, types.AddressToDelegation(auth.Address)); err != nil { + return nil, fmt.Errorf("%w: %w", ErrStateTransitionFailed, err) + } } // 8. increase the nonce of authority - st.state.SetNonce(authority, authorityNonce+1) + if err := st.state.SetNonce(authority, authorityNonce+1); err != nil { + return nil, fmt.Errorf("%w: %w", ErrStateTransitionFailed, err) + } } } @@ -422,7 +472,11 @@ func (st *StateTransition) TransitionDb(refunds bool, gasBailout bool) (*evmtype var bailout bool // Gas bailout (for trace_call) should only be applied if there is not sufficient balance to perform value transfer if gasBailout { - if !msg.Value().IsZero() && !st.evm.Context.CanTransfer(st.state, msg.From(), msg.Value()) { + canTransfer, err := st.evm.Context.CanTransfer(st.state, msg.From(), msg.Value()) + if err != nil { + return nil, fmt.Errorf("%w: %w", ErrStateTransitionFailed, err) + } + if !msg.Value().IsZero() && !canTransfer { bailout = true } } @@ -435,8 +489,9 @@ func (st *StateTransition) TransitionDb(refunds bool, gasBailout bool) (*evmtype // Execute the preparatory steps for state transition which includes: // - prepare accessList(post-berlin; eip-7702) // - reset transient storage(eip 1153) - st.state.Prepare(rules, msg.From(), coinbase, msg.To(), vm.ActivePrecompiles(rules), accessTuples, verifiedAuthorities) - + if err = st.state.Prepare(rules, msg.From(), coinbase, msg.To(), vm.ActivePrecompiles(rules), accessTuples, verifiedAuthorities); err != nil { + return nil, fmt.Errorf("%w: %w", ErrStateTransitionFailed, err) + } var ( ret []byte vmerr error // vm errors do not effect consensus and are therefore not assigned to err @@ -469,7 +524,9 @@ func (st *StateTransition) TransitionDb(refunds bool, gasBailout bool) (*evmtype } amount := new(uint256.Int).SetUint64(st.gasUsed()) amount.Mul(amount, effectiveTip) // gasUsed * effectiveTip = how much goes to the block producer (miner, validator) - st.state.AddBalance(coinbase, amount, tracing.BalanceIncreaseRewardTransactionFee) + if err := st.state.AddBalance(coinbase, amount, tracing.BalanceIncreaseRewardTransactionFee); err != nil { + return nil, fmt.Errorf("%w: %w", ErrStateTransitionFailed, err) + } if !msg.IsFree() && rules.IsLondon { burntContractAddress := st.evm.ChainConfig().GetBurntContract(st.evm.Context.BlockNumber) if burntContractAddress != nil { diff --git a/core/vm/eips.go b/core/vm/eips.go index e2d17673e21..0625ba8a8d5 100644 --- a/core/vm/eips.go +++ b/core/vm/eips.go @@ -95,7 +95,10 @@ func enable1884(jt *JumpTable) { } func opSelfBalance(pc *uint64, interpreter *EVMInterpreter, callContext *ScopeContext) ([]byte, error) { - balance := interpreter.evm.IntraBlockState().GetBalance(callContext.Contract.Address()) + balance, err := interpreter.evm.IntraBlockState().GetBalance(callContext.Contract.Address()) + if err != nil { + return nil, err + } callContext.Stack.Push(balance) return nil, nil } diff --git a/core/vm/errors.go b/core/vm/errors.go index ce8ff51f1eb..b8fbee9adc8 100644 --- a/core/vm/errors.go +++ b/core/vm/errors.go @@ -49,6 +49,10 @@ var ( // errStopToken is an internal token indicating interpreter loop termination, // never returned to outside callers. errStopToken = errors.New("stop token") + // + // ErrIntraBlockStateFailed indicates a fatal error when processing IBS + // requests + ErrIntraBlockStateFailed = errors.New("ibs fatal error") ) // ErrStackUnderflow wraps an evm error when the items on the stack less diff --git a/core/vm/evm.go b/core/vm/evm.go index a01a97d8a2a..4b85d8c70f1 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -20,6 +20,7 @@ package vm import ( + "fmt" "sync/atomic" "github.com/holiman/uint256" @@ -189,7 +190,11 @@ func (evm *EVM) call(typ OpCode, caller ContractRef, addr libcommon.Address, inp } if typ == CALL || typ == CALLCODE { // Fail if we're trying to transfer more than the available balance - if !value.IsZero() && !evm.Context.CanTransfer(evm.intraBlockState, caller.Address(), value) { + canTransfer, err := evm.Context.CanTransfer(evm.intraBlockState, caller.Address(), value) + if err != nil { + return nil, 0, err + } + if !value.IsZero() && !canTransfer { if !bailout { return nil, gas, ErrInsufficientBalance } @@ -198,13 +203,20 @@ func (evm *EVM) call(typ OpCode, caller ContractRef, addr libcommon.Address, inp p, isPrecompile := evm.precompile(addr) var code []byte if !isPrecompile { - code = evm.intraBlockState.ResolveCode(addr) + code, err = evm.intraBlockState.ResolveCode(addr) + if err != nil { + return nil, 0, fmt.Errorf("%w: %w", ErrIntraBlockStateFailed, err) + } } snapshot := evm.intraBlockState.Snapshot() if typ == CALL { - if !evm.intraBlockState.Exist(addr) { + exist, err := evm.intraBlockState.Exist(addr) + if err != nil { + return nil, 0, fmt.Errorf("%w: %w", ErrIntraBlockStateFailed, err) + } + if !exist { if !isPrecompile && evm.chainRules.IsSpuriousDragon && value.IsZero() { if evm.config.Debug { v := value @@ -270,7 +282,11 @@ func (evm *EVM) call(typ OpCode, caller ContractRef, addr libcommon.Address, inp addrCopy := addr // Initialise a new contract and set the code that is to be used by the EVM. // The contract is a scoped environment for this execution context only. - codeHash := evm.intraBlockState.ResolveCodeHash(addrCopy) + var codeHash libcommon.Hash + codeHash, err = evm.intraBlockState.ResolveCodeHash(addrCopy) + if err != nil { + return nil, 0, fmt.Errorf("%w: %w", ErrIntraBlockStateFailed, err) + } var contract *Contract if typ == CALLCODE { contract = NewContract(caller, caller.Address(), value, gas, evm.config.SkipAnalysis, evm.JumpDestCache) @@ -385,14 +401,21 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gasRemainin err = ErrDepth return nil, libcommon.Address{}, gasRemaining, err } - if !evm.Context.CanTransfer(evm.intraBlockState, caller.Address(), value) { + canTransfer, err := evm.Context.CanTransfer(evm.intraBlockState, caller.Address(), value) + if err != nil { + return nil, libcommon.Address{}, 0, err + } + if !canTransfer { if !bailout { err = ErrInsufficientBalance return nil, libcommon.Address{}, gasRemaining, err } } if incrementNonce { - nonce := evm.intraBlockState.GetNonce(caller.Address()) + nonce, err := evm.intraBlockState.GetNonce(caller.Address()) + if err != nil { + return nil, libcommon.Address{}, 0, fmt.Errorf("%w: %w", ErrIntraBlockStateFailed, err) + } if nonce+1 < nonce { err = ErrNonceUintOverflow return nil, libcommon.Address{}, gasRemaining, err @@ -405,8 +428,15 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gasRemainin evm.intraBlockState.AddAddressToAccessList(address) } // Ensure there's no existing contract already at the designated address - contractHash := evm.intraBlockState.ResolveCodeHash(address) - if evm.intraBlockState.GetNonce(address) != 0 || (contractHash != (libcommon.Hash{}) && contractHash != trie.EmptyCodeHash) { + contractHash, err := evm.intraBlockState.ResolveCodeHash(address) + if err != nil { + return nil, libcommon.Address{}, 0, fmt.Errorf("%w: %w", ErrIntraBlockStateFailed, err) + } + nonce, err := evm.intraBlockState.GetNonce(address) + if err != nil { + return nil, libcommon.Address{}, 0, fmt.Errorf("%w: %w", ErrIntraBlockStateFailed, err) + } + if nonce != 0 || (contractHash != (libcommon.Hash{}) && contractHash != trie.EmptyCodeHash) { err = ErrContractAddressCollision return nil, libcommon.Address{}, 0, err } @@ -481,7 +511,11 @@ func (evm *EVM) maxCodeSize() int { // Create creates a new contract using code as deployment code. // DESCRIBED: docs/programmers_guide/guide.md#nonce func (evm *EVM) Create(caller ContractRef, code []byte, gasRemaining uint64, endowment *uint256.Int, bailout bool) (ret []byte, contractAddr libcommon.Address, leftOverGas uint64, err error) { - contractAddr = crypto.CreateAddress(caller.Address(), evm.intraBlockState.GetNonce(caller.Address())) + nonce, err := evm.intraBlockState.GetNonce(caller.Address()) + if err != nil { + return nil, libcommon.Address{}, 0, err + } + contractAddr = crypto.CreateAddress(caller.Address(), nonce) return evm.create(caller, &codeAndHash{code: code}, gasRemaining, endowment, contractAddr, CREATE, true /* incrementNonce */, bailout) } diff --git a/core/vm/evmtypes/evmtypes.go b/core/vm/evmtypes/evmtypes.go index 775c4600acd..8e1e46fd271 100644 --- a/core/vm/evmtypes/evmtypes.go +++ b/core/vm/evmtypes/evmtypes.go @@ -103,10 +103,10 @@ func (result *ExecutionResult) Revert() []byte { type ( // CanTransferFunc is the signature of a transfer guard function - CanTransferFunc func(IntraBlockState, common.Address, *uint256.Int) bool + CanTransferFunc func(IntraBlockState, common.Address, *uint256.Int) (bool, error) // TransferFunc is the signature of a transfer function - TransferFunc func(IntraBlockState, common.Address, common.Address, *uint256.Int, bool) + TransferFunc func(IntraBlockState, common.Address, common.Address, *uint256.Int, bool) error // GetHashFunc returns the nth block hash in the blockchain // and is used by the BLOCKHASH EVM op code. @@ -119,50 +119,50 @@ type ( // IntraBlockState is an EVM database for full state querying. type IntraBlockState interface { - CreateAccount(common.Address, bool) + CreateAccount(common.Address, bool) error - SubBalance(common.Address, *uint256.Int, tracing.BalanceChangeReason) - AddBalance(common.Address, *uint256.Int, tracing.BalanceChangeReason) - GetBalance(common.Address) *uint256.Int + SubBalance(common.Address, *uint256.Int, tracing.BalanceChangeReason) error + AddBalance(common.Address, *uint256.Int, tracing.BalanceChangeReason) error + GetBalance(common.Address) (*uint256.Int, error) - GetNonce(common.Address) uint64 - SetNonce(common.Address, uint64) + GetNonce(common.Address) (uint64, error) + SetNonce(common.Address, uint64) error - GetCodeHash(common.Address) common.Hash - GetCode(common.Address) []byte - SetCode(common.Address, []byte) - GetCodeSize(common.Address) int + GetCodeHash(common.Address) (common.Hash, error) + GetCode(common.Address) ([]byte, error) + SetCode(common.Address, []byte) error + GetCodeSize(common.Address) (int, error) // eip-7702; delegated designations - ResolveCodeHash(common.Address) common.Hash - ResolveCode(common.Address) []byte - ResolveCodeSize(common.Address) int - GetDelegatedDesignation(common.Address) (common.Address, bool) + ResolveCodeHash(common.Address) (common.Hash, error) + ResolveCode(common.Address) ([]byte, error) + ResolveCodeSize(common.Address) (int, error) + GetDelegatedDesignation(common.Address) (common.Address, bool, error) AddRefund(uint64) SubRefund(uint64) GetRefund() uint64 - GetCommittedState(common.Address, *common.Hash, *uint256.Int) - GetState(address common.Address, slot *common.Hash, outValue *uint256.Int) - SetState(common.Address, *common.Hash, uint256.Int) + GetCommittedState(common.Address, *common.Hash, *uint256.Int) error + GetState(address common.Address, slot *common.Hash, outValue *uint256.Int) error + SetState(common.Address, *common.Hash, uint256.Int) error GetTransientState(addr common.Address, key common.Hash) uint256.Int SetTransientState(addr common.Address, key common.Hash, value uint256.Int) - Selfdestruct(common.Address) bool - HasSelfdestructed(common.Address) bool - Selfdestruct6780(common.Address) + Selfdestruct(common.Address) (bool, error) + HasSelfdestructed(common.Address) (bool, error) + Selfdestruct6780(common.Address) error // Exist reports whether the given account exists in state. // Notably this should also return true for suicided accounts. - Exist(common.Address) bool + Exist(common.Address) (bool, error) // Empty returns whether the given account is empty. Empty // is defined according to EIP161 (balance = nonce = code = 0). - Empty(common.Address) bool + Empty(common.Address) (bool, error) Prepare(rules *chain.Rules, sender, coinbase common.Address, dest *common.Address, - precompiles []common.Address, txAccesses types.AccessList, authorities []common.Address) + precompiles []common.Address, txAccesses types.AccessList, authorities []common.Address) error AddressInAccessList(addr common.Address) bool // AddAddressToAccessList adds the given address to the access list. This operation is safe to perform diff --git a/core/vm/gas_table.go b/core/vm/gas_table.go index ef38856ccfc..7d98f49529c 100644 --- a/core/vm/gas_table.go +++ b/core/vm/gas_table.go @@ -391,11 +391,21 @@ func gasCall(evm *EVM, contract *Contract, stack *stack.Stack, mem *Memory, memo address = libcommon.Address(stack.Back(1).Bytes20()) ) if evm.ChainRules().IsSpuriousDragon { - if transfersValue && evm.IntraBlockState().Empty(address) { + empty, err := evm.IntraBlockState().Empty(address) + if err != nil { + return 0, err + } + if transfersValue && empty { + gas += params.CallNewAccountGas + } + } else { + exists, err := evm.IntraBlockState().Exist(address) + if err != nil { + return 0, err + } + if !exists { gas += params.CallNewAccountGas } - } else if !evm.IntraBlockState().Exist(address) { - gas += params.CallNewAccountGas } if transfersValue { gas += params.CallValueTransferGas @@ -499,15 +509,33 @@ func gasSelfdestruct(evm *EVM, contract *Contract, stack *stack.Stack, mem *Memo if evm.ChainRules().IsSpuriousDragon { // if empty and transfers value - if evm.IntraBlockState().Empty(address) && !evm.IntraBlockState().GetBalance(contract.Address()).IsZero() { + empty, err := evm.IntraBlockState().Empty(address) + if err != nil { + return 0, err + } + balance, err := evm.IntraBlockState().GetBalance(contract.Address()) + if err != nil { + return 0, err + } + if empty && !balance.IsZero() { + gas += params.CreateBySelfdestructGas + } + } else { + exist, err := evm.IntraBlockState().Exist(address) + if err != nil { + return 0, err + } + if !exist { gas += params.CreateBySelfdestructGas } - } else if !evm.IntraBlockState().Exist(address) { - gas += params.CreateBySelfdestructGas } } - if !evm.IntraBlockState().HasSelfdestructed(contract.Address()) { + hasSelfdestructed, err := evm.IntraBlockState().HasSelfdestructed(contract.Address()) + if err != nil { + return 0, err + } + if !hasSelfdestructed { evm.IntraBlockState().AddRefund(params.SelfdestructRefundGas) } return gas, nil diff --git a/core/vm/gas_table_test.go b/core/vm/gas_table_test.go index 4703b81f87f..fc33308a2eb 100644 --- a/core/vm/gas_table_test.go +++ b/core/vm/gas_table_test.go @@ -144,8 +144,10 @@ func TestEIP2200(t *testing.T) { _ = s.CommitBlock(params.AllProtocolChanges.Rules(0, 0), w) vmctx := evmtypes.BlockContext{ - CanTransfer: func(evmtypes.IntraBlockState, libcommon.Address, *uint256.Int) bool { return true }, - Transfer: func(evmtypes.IntraBlockState, libcommon.Address, libcommon.Address, *uint256.Int, bool) {}, + CanTransfer: func(evmtypes.IntraBlockState, libcommon.Address, *uint256.Int) (bool, error) { return true, nil }, + Transfer: func(evmtypes.IntraBlockState, libcommon.Address, libcommon.Address, *uint256.Int, bool) error { + return nil + }, } vmenv := vm.NewEVM(vmctx, evmtypes.TxContext{}, s, params.AllProtocolChanges, vm.Config{ExtraEips: []int{2200}}) @@ -207,8 +209,10 @@ func TestCreateGas(t *testing.T) { _ = s.CommitBlock(params.TestChainConfig.Rules(0, 0), stateWriter) vmctx := evmtypes.BlockContext{ - CanTransfer: func(evmtypes.IntraBlockState, libcommon.Address, *uint256.Int) bool { return true }, - Transfer: func(evmtypes.IntraBlockState, libcommon.Address, libcommon.Address, *uint256.Int, bool) {}, + CanTransfer: func(evmtypes.IntraBlockState, libcommon.Address, *uint256.Int) (bool, error) { return true, nil }, + Transfer: func(evmtypes.IntraBlockState, libcommon.Address, libcommon.Address, *uint256.Int, bool) error { + return nil + }, } config := vm.Config{} if tt.eip3860 { diff --git a/core/vm/instructions.go b/core/vm/instructions.go index 1cd62cfa7ee..e0b602323ff 100644 --- a/core/vm/instructions.go +++ b/core/vm/instructions.go @@ -287,7 +287,11 @@ func opAddress(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([] func opBalance(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { slot := scope.Stack.Peek() address := libcommon.Address(slot.Bytes20()) - slot.Set(interpreter.evm.IntraBlockState().GetBalance(address)) + balance, err := interpreter.evm.IntraBlockState().GetBalance(address) + if err != nil { + return nil, fmt.Errorf("%w: %w", ErrIntraBlockStateFailed, err) + } + slot.Set(balance) return nil, nil } @@ -371,7 +375,11 @@ func opReturnDataCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeConte func opExtCodeSize(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { slot := scope.Stack.Peek() - slot.SetUint64(uint64(interpreter.evm.IntraBlockState().ResolveCodeSize(slot.Bytes20()))) + codeSize, err := interpreter.evm.IntraBlockState().ResolveCodeSize(slot.Bytes20()) + if err != nil { + return nil, fmt.Errorf("%w: %w", ErrIntraBlockStateFailed, err) + } + slot.SetUint64(uint64(codeSize)) return nil, nil } @@ -408,7 +416,11 @@ func opExtCodeCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) addr := libcommon.Address(a.Bytes20()) len64 := length.Uint64() - codeCopy := getDataBig(interpreter.evm.IntraBlockState().ResolveCode(addr), &codeOffset, len64) + code, err := interpreter.evm.IntraBlockState().ResolveCode(addr) + if err != nil { + return nil, fmt.Errorf("%w: %w", ErrIntraBlockStateFailed, err) + } + codeCopy := getDataBig(code, &codeOffset, len64) scope.Memory.Set(memOffset.Uint64(), len64, codeCopy) return nil, nil } @@ -454,10 +466,18 @@ func opExtCodeHash(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) slot := scope.Stack.Peek() address := libcommon.Address(slot.Bytes20()) - if interpreter.evm.IntraBlockState().Empty(address) { + empty, err := interpreter.evm.IntraBlockState().Empty(address) + if err != nil { + return nil, err + } + if empty { slot.Clear() } else { - slot.SetBytes(interpreter.evm.IntraBlockState().ResolveCodeHash(address).Bytes()) + codeHash, err := interpreter.evm.IntraBlockState().ResolveCodeHash(address) + if err != nil { + return nil, err + } + slot.SetBytes(codeHash.Bytes()) } return nil, nil } @@ -559,8 +579,7 @@ func opMstore8(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([] func opSload(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { loc := scope.Stack.Peek() interpreter.hasherBuf = loc.Bytes32() - interpreter.evm.IntraBlockState().GetState(scope.Contract.Address(), &interpreter.hasherBuf, loc) - return nil, nil + return nil, interpreter.evm.IntraBlockState().GetState(scope.Contract.Address(), &interpreter.hasherBuf, loc) } func opSstore(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { @@ -570,8 +589,7 @@ func opSstore(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]b loc := scope.Stack.Pop() val := scope.Stack.Pop() interpreter.hasherBuf = loc.Bytes32() - interpreter.evm.IntraBlockState().SetState(scope.Contract.Address(), &interpreter.hasherBuf, val) - return nil, nil + return nil, interpreter.evm.IntraBlockState().SetState(scope.Contract.Address(), &interpreter.hasherBuf, val) } func opJump(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { @@ -879,7 +897,10 @@ func opSelfdestruct(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext beneficiary := scope.Stack.Pop() callerAddr := scope.Contract.Address() beneficiaryAddr := libcommon.Address(beneficiary.Bytes20()) - balance := interpreter.evm.IntraBlockState().GetBalance(callerAddr) + balance, err := interpreter.evm.IntraBlockState().GetBalance(callerAddr) + if err != nil { + return nil, err + } if interpreter.evm.Config().Debug { if interpreter.cfg.Debug { interpreter.cfg.Tracer.CaptureEnter(SELFDESTRUCT, callerAddr, beneficiaryAddr, false /* precompile */, false /* create */, []byte{}, 0, balance, nil /* code */) @@ -898,7 +919,11 @@ func opSelfdestruct6780(pc *uint64, interpreter *EVMInterpreter, scope *ScopeCon beneficiary := scope.Stack.Pop() callerAddr := scope.Contract.Address() beneficiaryAddr := libcommon.Address(beneficiary.Bytes20()) - balance := *interpreter.evm.IntraBlockState().GetBalance(callerAddr) + pbalance, err := interpreter.evm.IntraBlockState().GetBalance(callerAddr) + if err != nil { + return nil, err + } + balance := *pbalance interpreter.evm.IntraBlockState().SubBalance(callerAddr, &balance, tracing.BalanceDecreaseSelfdestruct) interpreter.evm.IntraBlockState().AddBalance(beneficiaryAddr, &balance, tracing.BalanceIncreaseSelfdestruct) interpreter.evm.IntraBlockState().Selfdestruct6780(callerAddr) diff --git a/core/vm/operations_acl.go b/core/vm/operations_acl.go index a8c3fec9b33..fe1817e8013 100644 --- a/core/vm/operations_acl.go +++ b/core/vm/operations_acl.go @@ -231,10 +231,22 @@ func makeSelfdestructGasFn(refundsEnabled bool) gasFunc { gas = params.ColdAccountAccessCostEIP2929 } // if empty and transfers value - if evm.IntraBlockState().Empty(address) && !evm.IntraBlockState().GetBalance(contract.Address()).IsZero() { + empty, err := evm.IntraBlockState().Empty(address) + if err != nil { + return 0, err + } + balance, err := evm.IntraBlockState().GetBalance(contract.Address()) + if err != nil { + return 0, err + } + if empty && !balance.IsZero() { gas += params.CreateBySelfdestructGas } - if refundsEnabled && !evm.IntraBlockState().HasSelfdestructed(contract.Address()) { + hasSelfdestructed, err := evm.IntraBlockState().HasSelfdestructed(contract.Address()) + if err != nil { + return 0, err + } + if refundsEnabled && !hasSelfdestructed { evm.IntraBlockState().AddRefund(params.SelfdestructRefundGas) } return gas, nil @@ -266,7 +278,11 @@ func makeCallVariantGasCallEIP7702(oldCalculator gasFunc) gasFunc { } // Check if code is a delegation and if so, charge for resolution. - if dd, ok := evm.intraBlockState.GetDelegatedDesignation(addr); ok { + dd, ok, err := evm.intraBlockState.GetDelegatedDesignation(addr) + if err != nil { + return 0, err + } + if ok { var ddCost uint64 if evm.intraBlockState.AddAddressToAccessList(dd) { ddCost = params.ColdAccountAccessCostEIP2929 @@ -311,8 +327,11 @@ func gasEip7702CodeCheck(evm *EVM, contract *Contract, stack *stack.Stack, mem * // Check if code is a delegation and if so, charge for resolution cost = params.ColdAccountAccessCostEIP2929 - params.WarmStorageReadCostEIP2929 } - - if dd, ok := evm.intraBlockState.GetDelegatedDesignation(addr); ok { + dd, ok, err := evm.intraBlockState.GetDelegatedDesignation(addr) + if err != nil { + return 0, err + } + if ok { if evm.intraBlockState.AddAddressToAccessList(dd) { cost += params.ColdAccountAccessCostEIP2929 } else { @@ -340,7 +359,11 @@ func gasExtCodeCopyEIP7702(evm *EVM, contract *Contract, stack *stack.Stack, mem } // Check if addr has a delegation and if so, charge for resolution - if dd, ok := evm.intraBlockState.GetDelegatedDesignation(addr); ok { + dd, ok, err := evm.intraBlockState.GetDelegatedDesignation(addr) + if err != nil { + return 0, err + } + if ok { var overflow bool if evm.intraBlockState.AddAddressToAccessList(dd) { if gas, overflow = math.SafeAdd(gas, params.ColdAccountAccessCostEIP2929); overflow { diff --git a/core/vm/runtime/runtime.go b/core/vm/runtime/runtime.go index 5515933f389..77748306170 100644 --- a/core/vm/runtime/runtime.go +++ b/core/vm/runtime/runtime.go @@ -244,7 +244,10 @@ func Call(address libcommon.Address, input []byte, cfg *Config) ([]byte, uint64, vmenv := NewEnv(cfg) - sender := cfg.State.GetOrNewStateObject(cfg.Origin) + sender, err := cfg.State.GetOrNewStateObject(cfg.Origin) + if err != nil { + return nil, 0, err + } statedb := cfg.State rules := vmenv.ChainRules() statedb.Prepare(rules, cfg.Origin, cfg.Coinbase, &address, vm.ActivePrecompiles(rules), nil, nil) diff --git a/eth/stagedsync/exec3.go b/eth/stagedsync/exec3.go index c632b188631..d148f3a249d 100644 --- a/eth/stagedsync/exec3.go +++ b/eth/stagedsync/exec3.go @@ -132,6 +132,71 @@ func (p *Progress) Log(suffix string, rs *state.StateV3, in *state.QueueWithRetr p.prevRepeatCount = repeatCount } +// Cases: +// 1. Snapshots > ExecutionStage: snapshots can have half-block data `10.4`. Get right txNum from SharedDomains (after SeekCommitment) +// 2. ExecutionStage > Snapshots: no half-block data possible. Rely on DB. +func restoreTxNum(ctx context.Context, cfg *ExecuteBlockCfg, applyTx kv.Tx, doms *state2.SharedDomains, maxBlockNum uint64) ( + inputTxNum uint64, maxTxNum uint64, offsetFromBlockBeginning uint64, err error) { + + txNumsReader := rawdbv3.TxNums.WithCustomReadTxNumFunc(freezeblocks.ReadTxNumFuncFromBlockReader(ctx, cfg.blockReader)) + + inputTxNum = doms.TxNum() + + if nothing, err := nothingToExec(applyTx, txNumsReader, inputTxNum); err != nil { + return 0, 0, 0, err + } else if nothing { + return 0, 0, 0, err + } + + maxTxNum, err = txNumsReader.Max(applyTx, maxBlockNum) + if err != nil { + return 0, 0, 0, err + } + + ok, _blockNum, err := txNumsReader.FindBlockNum(applyTx, doms.TxNum()) + if err != nil { + return 0, 0, 0, err + } + if !ok { + _lb, _lt, _ := txNumsReader.Last(applyTx) + _fb, _ft, _ := txNumsReader.First(applyTx) + return 0, 0, 0, fmt.Errorf("seems broken TxNums index not filled. can't find blockNum of txNum=%d; in db: (%d-%d, %d-%d)", inputTxNum, _fb, _lb, _ft, _lt) + } + { + _max, _ := txNumsReader.Max(applyTx, _blockNum) + if doms.TxNum() == _max { + _blockNum++ + } + } + + _min, err := txNumsReader.Min(applyTx, _blockNum) + if err != nil { + return 0, 0, 0, err + } + + if doms.TxNum() > _min { + // if stopped in the middle of the block: start from beginning of block. + // first part will be executed in HistoryExecution mode + offsetFromBlockBeginning = doms.TxNum() - _min + } + + inputTxNum = _min + + //_max, _ := txNumsReader.Max(applyTx, blockNum) + //fmt.Printf("[commitment] found domain.txn %d, inputTxn %d, offset %d. DB found block %d {%d, %d}\n", doms.TxNum(), inputTxNum, offsetFromBlockBeginning, blockNum, _min, _max) + doms.SetBlockNum(_blockNum) + doms.SetTxNum(inputTxNum) + return inputTxNum, maxTxNum, offsetFromBlockBeginning, nil +} + +func nothingToExec(applyTx kv.Tx, txNumsReader rawdbv3.TxNumsReader, inputTxNum uint64) (bool, error) { + _, lastTxNum, err := txNumsReader.Last(applyTx) + if err != nil { + return false, err + } + return lastTxNum == inputTxNum, nil +} + func ExecV3(ctx context.Context, execStage *StageState, u Unwinder, workerCount int, cfg ExecuteBlockCfg, txc wrap.TxContainer, parallel bool, //nolint @@ -198,100 +263,17 @@ func ExecV3(ctx context.Context, } txNumInDB := doms.TxNum() - txNumsReader := rawdbv3.TxNums.WithCustomReadTxNumFunc(freezeblocks.ReadTxNumFuncFromBlockReader(ctx, cfg.blockReader)) - var ( - inputTxNum = doms.TxNum() - stageProgress = execStage.BlockNumber - outputTxNum = atomic.Uint64{} - blockComplete = atomic.Bool{} - + inputTxNum = doms.TxNum() + stageProgress = execStage.BlockNumber + outputTxNum = atomic.Uint64{} + blockComplete = atomic.Bool{} + outputBlockNum = stages.SyncMetrics[stages.Execution] + inputBlockNum = &atomic.Uint64{} offsetFromBlockBeginning uint64 blockNum, maxTxNum uint64 ) - blockComplete.Store(true) - nothingToExec := func(applyTx kv.Tx) (bool, error) { - _, lastTxNum, err := txNumsReader.Last(applyTx) - if err != nil { - return false, err - } - return lastTxNum == inputTxNum, nil - } - // Cases: - // 1. Snapshots > ExecutionStage: snapshots can have half-block data `10.4`. Get right txNum from SharedDomains (after SeekCommitment) - // 2. ExecutionStage > Snapshots: no half-block data possible. Rely on DB. - restoreTxNum := func(applyTx kv.Tx) error { - var err error - maxTxNum, err = txNumsReader.Max(applyTx, maxBlockNum) - if err != nil { - return err - } - ok, _blockNum, err := txNumsReader.FindBlockNum(applyTx, doms.TxNum()) - if err != nil { - return err - } - if !ok { - _lb, _lt, _ := txNumsReader.Last(applyTx) - _fb, _ft, _ := txNumsReader.First(applyTx) - return fmt.Errorf("seems broken TxNums index not filled. can't find blockNum of txNum=%d; in db: (%d-%d, %d-%d)", inputTxNum, _fb, _lb, _ft, _lt) - } - { - _max, _ := txNumsReader.Max(applyTx, _blockNum) - if doms.TxNum() == _max { - _blockNum++ - } - } - - _min, err := txNumsReader.Min(applyTx, _blockNum) - if err != nil { - return err - } - - if doms.TxNum() > _min { - // if stopped in the middle of the block: start from beginning of block. - // first part will be executed in HistoryExecution mode - offsetFromBlockBeginning = doms.TxNum() - _min - } - - inputTxNum = _min - outputTxNum.Store(inputTxNum) - - //_max, _ := txNumsReader.Max(applyTx, blockNum) - //fmt.Printf("[commitment] found domain.txn %d, inputTxn %d, offset %d. DB found block %d {%d, %d}\n", doms.TxNum(), inputTxNum, offsetFromBlockBeginning, blockNum, _min, _max) - doms.SetBlockNum(_blockNum) - doms.SetTxNum(inputTxNum) - return nil - } - if applyTx != nil { - if _nothing, err := nothingToExec(applyTx); err != nil { - return err - } else if _nothing { - return nil - } - - if err := restoreTxNum(applyTx); err != nil { - return err - } - } else { - var _nothing bool - if err := cfg.db.View(ctx, func(tx kv.Tx) (err error) { - if _nothing, err = nothingToExec(applyTx); err != nil { - return err - } else if _nothing { - return nil - } - - return restoreTxNum(applyTx) - }); err != nil { - return err - } - if _nothing { - return nil - } - } - - ts := time.Duration(0) blockNum = doms.BlockNum() outputTxNum.Store(doms.TxNum()) @@ -311,8 +293,6 @@ func ExecV3(ctx context.Context, agg.BuildFilesInBackground(outputTxNum.Load()) - var outputBlockNum = stages.SyncMetrics[stages.Execution] - inputBlockNum := &atomic.Uint64{} var count uint64 shouldReportToTxPool := cfg.notifications != nil && !isMining && maxBlockNum <= blockNum+64 @@ -329,22 +309,37 @@ func ExecV3(ctx context.Context, // Now rwLoop closing both (because applyLoop we completely restart) // Maybe need split channels? Maybe don't exit from ApplyLoop? Maybe current way is also ok? - // input queue - in := state.NewQueueWithRetry(100_000) - defer in.Close() + if applyTx != nil { + if inputTxNum, maxTxNum, offsetFromBlockBeginning, err = restoreTxNum(ctx, &cfg, applyTx, doms, maxBlockNum); err != nil { + return err + } + } else { + if err := cfg.db.View(ctx, func(tx kv.Tx) (err error) { + inputTxNum, maxTxNum, offsetFromBlockBeginning, err = restoreTxNum(ctx, &cfg, tx, doms, maxBlockNum) + return err + }); err != nil { + return err + } + } - rwsConsumed := make(chan struct{}, 1) - defer close(rwsConsumed) + if maxTxNum == 0 { + return nil + } applyWorker := cfg.applyWorker if isMining { applyWorker = cfg.applyWorkerMining } - applyWorker.ResetState(rs, accumulator) defer applyWorker.LogLRUStats() + applyWorker.ResetState(rs, accumulator) + commitThreshold := cfg.batchSize.Bytes() + + // TODO are these dups ? + processed := NewProgress(blockNum, commitThreshold, workerCount, true, execStage.LogPrefix(), logger) progress := NewProgress(blockNum, commitThreshold, workerCount, false, execStage.LogPrefix(), logger) + logEvery := time.NewTicker(20 * time.Second) defer logEvery.Stop() pruneEvery := time.NewTicker(2 * time.Second) @@ -352,27 +347,27 @@ func ExecV3(ctx context.Context, var logGas uint64 var stepsInDB float64 - - processed := NewProgress(blockNum, commitThreshold, workerCount, true, execStage.LogPrefix(), logger) - var executor executor if parallel { pe := ¶llelExecutor{ - execStage: execStage, - chainDb: cfg.db, - applyWorker: applyWorker, - applyTx: applyTx, - outputTxNum: &outputTxNum, - in: in, - rs: rs, - agg: agg, - rwsConsumed: rwsConsumed, - isMining: isMining, - inMemExec: inMemExec, + txExecutor: txExecutor{ + cfg: cfg, + execStage: execStage, + rs: rs, + doms: doms, + agg: agg, + accumulator: accumulator, + isMining: isMining, + inMemExec: inMemExec, + applyTx: applyTx, + applyWorker: applyWorker, + outputTxNum: &outputTxNum, + outputBlockNum: stages.SyncMetrics[stages.Execution], + logger: logger, + }, shouldGenerateChangesets: shouldGenerateChangesets, workerCount: workerCount, - accumulator: accumulator, pruneEvery: pruneEvery, logEvery: logEvery, progress: progress, @@ -382,7 +377,7 @@ func ExecV3(ctx context.Context, defer executorCancel() defer func() { - processed.Log("Done", executor.readState(), in, pe.rws, 0 /*txCount - TODO*/, logGas, inputBlockNum.Load(), outputBlockNum.GetValueUint64(), outputTxNum.Load(), mxExecRepeats.GetValueUint64(), stepsInDB, shouldGenerateChangesets, inMemExec) + processed.Log("Done", executor.readState(), nil, pe.rws, 0 /*txCount - TODO*/, logGas, inputBlockNum.Load(), outputBlockNum.GetValueUint64(), outputTxNum.Load(), mxExecRepeats.GetValueUint64(), stepsInDB, shouldGenerateChangesets, inMemExec) }() executor = pe @@ -391,31 +386,47 @@ func ExecV3(ctx context.Context, doms.SetTx(applyTx) se := &serialExecutor{ - cfg: cfg, - execStage: execStage, - rs: rs, - doms: doms, - agg: agg, - u: u, - isMining: isMining, - inMemExec: inMemExec, - applyTx: applyTx, - worker: applyWorker, - outputTxNum: &outputTxNum, - logger: logger, + txExecutor: txExecutor{ + cfg: cfg, + execStage: execStage, + rs: rs, + doms: doms, + agg: agg, + u: u, + isMining: isMining, + inMemExec: inMemExec, + applyTx: applyTx, + applyWorker: applyWorker, + outputTxNum: &outputTxNum, + outputBlockNum: stages.SyncMetrics[stages.Execution], + logger: logger, + }, } defer func() { - processed.Log("Done", executor.readState(), in, nil, se.txCount, logGas, inputBlockNum.Load(), outputBlockNum.GetValueUint64(), outputTxNum.Load(), mxExecRepeats.GetValueUint64(), stepsInDB, shouldGenerateChangesets, inMemExec) + processed.Log("Done", executor.readState(), nil, nil, se.txCount, logGas, inputBlockNum.Load(), outputBlockNum.GetValueUint64(), outputTxNum.Load(), mxExecRepeats.GetValueUint64(), stepsInDB, shouldGenerateChangesets, inMemExec) }() executor = se } - getHeaderFunc := func(hash common.Hash, number uint64) (h *types.Header) { - return executor.getHeader(ctx, hash, number) + blockComplete.Store(true) + + ts := time.Duration(0) + blockNum = executor.domains().BlockNum() + outputTxNum.Store(executor.domains().TxNum()) + + if maxBlockNum < blockNum { + return nil } + if maxBlockNum > blockNum+16 { + log.Info(fmt.Sprintf("[%s] starting", execStage.LogPrefix()), + "from", blockNum, "to", maxBlockNum, "fromTxNum", executor.domains().TxNum(), "offsetFromBlockBeginning", offsetFromBlockBeginning, "initialCycle", initialCycle, "useExternalTx", useExternalTx) + } + + agg.BuildFilesInBackground(outputTxNum.Load()) + var readAhead chan uint64 if !parallel { // snapshots are often stored on chaper drives. don't expect low-read-latency and manually read-ahead. @@ -478,13 +489,12 @@ Loop: skipAnalysis := core.SkipAnalysis(chainConfig, blockNum) signer := *types.MakeSigner(chainConfig, blockNum, header.Time) - f := core.GetHashFn(header, getHeaderFunc) getHashFnMute := &sync.Mutex{} - getHashFn := func(n uint64) common.Hash { + getHashFn := core.GetHashFn(header, func(hash common.Hash, number uint64) (h *types.Header) { getHashFnMute.Lock() defer getHashFnMute.Unlock() - return f(n) - } + return executor.getHeader(ctx, hash, number) + }) totalGasUsed += b.GasUsed() blockContext := core.NewEVMBlockContext(header, getHashFn, cfg.engine, cfg.author /* author */, chainConfig) // print type of engine @@ -492,7 +502,7 @@ Loop: if err := executor.status(ctx, commitThreshold); err != nil { return err } - } else if shouldReportToTxPool { + } else if accumulator != nil { txs, err := blockReader.RawTransactions(context.Background(), executor.tx(), b.NumberU64(), b.NumberU64()) if err != nil { return err @@ -610,9 +620,16 @@ Loop: aggTx := executor.tx().(state2.HasAggTx).AggTx().(*state2.AggregatorRoTx) aggTx.RestrictSubsetFileDeletions(true) start := time.Now() - if _, err := executor.domains().ComputeCommitment(ctx, true, blockNum, execStage.LogPrefix()); err != nil { + _ /*rh*/, err := executor.domains().ComputeCommitment(ctx, true, blockNum, execStage.LogPrefix()) + if err != nil { return err } + + //if !bytes.Equal(rh, header.Root.Bytes()) { + // logger.Error(fmt.Sprintf("[%s] Wrong trie root of block %d: %x, expected (from header): %x. Block hash: %x", execStage.LogPrefix(), header.Number.Uint64(), rh, header.Root.Bytes(), header.Hash())) + // return errors.New("wrong trie root") + //} + ts += time.Since(start) aggTx.RestrictSubsetFileDeletions(false) executor.domains().SavePastChangesetAccumulator(b.Hash(), blockNum, changeset) @@ -637,8 +654,6 @@ Loop: metrics2.UpdateBlockConsumerPostExecutionDelay(b.Time(), blockNum, logger) } - outputBlockNum.SetUint64(blockNum) - select { case <-logEvery.C: if inMemExec || isMining { @@ -646,7 +661,7 @@ Loop: } stepsInDB := rawdbhelpers.IdxStepsCountV3(executor.tx()) - progress.Log("", executor.readState(), in, nil, count, logGas, inputBlockNum.Load(), outputBlockNum.GetValueUint64(), outputTxNum.Load(), mxExecRepeats.GetValueUint64(), stepsInDB, shouldGenerateChangesets, inMemExec) + progress.Log("", executor.readState(), nil, nil, count, logGas, inputBlockNum.Load(), outputBlockNum.GetValueUint64(), outputTxNum.Load(), mxExecRepeats.GetValueUint64(), stepsInDB, shouldGenerateChangesets, inMemExec) //TODO: https://github.com/erigontech/erigon/issues/10724 //if executor.tx().(state2.HasAggTx).AggTx().(*state2.AggregatorRoTx).CanPrune(executor.tx(), outputTxNum.Load()) { @@ -712,6 +727,7 @@ Loop: //log.Info("Executed", "blocks", inputBlockNum.Load(), "txs", outputTxNum.Load(), "repeats", mxExecRepeats.GetValueUint64()) + //fmt.Println("WAIT") executor.wait() if u != nil && !u.HasUnwindPoint() { diff --git a/eth/stagedsync/exec3_parallel.go b/eth/stagedsync/exec3_parallel.go index 4ca19d50142..26d06c369f5 100644 --- a/eth/stagedsync/exec3_parallel.go +++ b/eth/stagedsync/exec3_parallel.go @@ -13,14 +13,16 @@ import ( "github.com/erigontech/erigon-lib/common" "github.com/erigontech/erigon-lib/kv" "github.com/erigontech/erigon-lib/log/v3" + "github.com/erigontech/erigon-lib/metrics" state2 "github.com/erigontech/erigon-lib/state" "github.com/erigontech/erigon/cmd/state/exec3" "github.com/erigontech/erigon/consensus" + "github.com/erigontech/erigon/core" "github.com/erigontech/erigon/core/rawdb" "github.com/erigontech/erigon/core/rawdb/rawdbhelpers" "github.com/erigontech/erigon/core/state" "github.com/erigontech/erigon/core/types" - "github.com/erigontech/erigon/eth/stagedsync/stages" + "github.com/erigontech/erigon/core/vm" "github.com/erigontech/erigon/turbo/shards" "golang.org/x/sync/errgroup" ) @@ -78,54 +80,48 @@ type executor interface { domains() *state2.SharedDomains } -type parallelExecutor struct { +type txExecutor struct { sync.RWMutex - rwLoopErrCh chan error - rwLoopG *errgroup.Group - applyLoopWg sync.WaitGroup - chainDb kv.RwDB - applyTx kv.RwTx - applyWorker *exec3.Worker - execWorkers []*exec3.Worker - stopWorkers func() - waitWorkers func() - execStage *StageState - cfg ExecuteBlockCfg - lastBlockNum atomic.Uint64 - outputTxNum *atomic.Uint64 - in *state.QueueWithRetry - rws *state.ResultsQueue - rs *state.StateV3 - doms *state2.SharedDomains - agg *state2.Aggregator - rwsConsumed chan struct{} - isMining bool - inMemExec bool - shouldGenerateChangesets bool - accumulator *shards.Accumulator - workerCount int - pruneEvery *time.Ticker - logEvery *time.Ticker - slowDownLimit *time.Ticker - progress *Progress + cfg ExecuteBlockCfg + execStage *StageState + agg *state2.Aggregator + rs *state.StateV3 + doms *state2.SharedDomains + accumulator *shards.Accumulator + u Unwinder + isMining bool + inMemExec bool + applyTx kv.RwTx + applyWorker *exec3.Worker + outputTxNum *atomic.Uint64 + outputBlockNum metrics.Gauge + logger log.Logger } -func (pe *parallelExecutor) tx() kv.RwTx { - return pe.applyTx +func (te *txExecutor) tx() kv.RwTx { + return te.applyTx } -func (pe *parallelExecutor) readState() *state.StateV3 { - return pe.rs +func (te *txExecutor) readState() *state.StateV3 { + return te.rs } -func (pe *parallelExecutor) domains() *state2.SharedDomains { - return pe.doms +func (te *txExecutor) domains() *state2.SharedDomains { + return te.doms } -func (pe *parallelExecutor) getHeader(ctx context.Context, hash common.Hash, number uint64) (h *types.Header) { +func (te *txExecutor) getHeader(ctx context.Context, hash common.Hash, number uint64) (h *types.Header) { var err error - if err = pe.chainDb.View(ctx, func(tx kv.Tx) error { - h, err = pe.cfg.blockReader.Header(ctx, tx, hash, number) + if te.applyTx != nil { + h, err = te.cfg.blockReader.Header(ctx, te.applyTx, hash, number) + if err != nil { + panic(err) + } + return h + } + + if err = te.cfg.db.View(ctx, func(tx kv.Tx) error { + h, err = te.cfg.blockReader.Header(ctx, tx, hash, number) if err != nil { return err } @@ -136,19 +132,39 @@ func (pe *parallelExecutor) getHeader(ctx context.Context, hash common.Hash, num return h } +type parallelExecutor struct { + txExecutor + rwLoopErrCh chan error + rwLoopG *errgroup.Group + applyLoopWg sync.WaitGroup + execWorkers []*exec3.Worker + stopWorkers func() + waitWorkers func() + lastBlockNum atomic.Uint64 + in *state.QueueWithRetry + rws *state.ResultsQueue + rwsConsumed chan struct{} + shouldGenerateChangesets bool + workerCount int + pruneEvery *time.Ticker + logEvery *time.Ticker + slowDownLimit *time.Ticker + progress *Progress +} + func (pe *parallelExecutor) applyLoop(ctx context.Context, maxTxNum uint64, blockComplete *atomic.Bool, errCh chan error) { defer pe.applyLoopWg.Done() defer func() { if rec := recover(); rec != nil { - log.Warn("[dbg] apply loop panic", "rec", rec) + pe.logger.Warn("[dbg] apply loop panic", "rec", rec) } - log.Warn("[dbg] apply loop exit") + pe.logger.Warn("[dbg] apply loop exit") }() - - outputBlockNum := stages.SyncMetrics[stages.Execution] + //fmt.Println("applyLoop started") + //defer fmt.Println("applyLoop done") applyLoopInner := func(ctx context.Context) error { - tx, err := pe.chainDb.BeginRo(ctx) + tx, err := pe.cfg.db.BeginRo(ctx) if err != nil { return err } @@ -161,18 +177,15 @@ func (pe *parallelExecutor) applyLoop(ctx context.Context, maxTxNum uint64, bloc return err } - processedTxNum, conflicts, triggers, processedBlockNum, stoppedAtBlockEnd, err := - pe.processResultQueue(ctx, pe.outputTxNum.Load(), tx, pe.rwsConsumed, true, false) + processedTxNum, conflicts, triggers, _ /*processedBlockNum*/, stoppedAtBlockEnd, err := + pe.processResultQueue(ctx, pe.outputTxNum.Load(), pe.rwsConsumed, true, false) if err != nil { return err } - + //fmt.Println("QR", processedTxNum, conflicts, triggers, processedBlockNum, stoppedAtBlockEnd, err) mxExecRepeats.AddInt(conflicts) mxExecTriggers.AddInt(triggers) - if processedBlockNum > pe.lastBlockNum.Load() { - outputBlockNum.SetUint64(processedBlockNum) - pe.lastBlockNum.Store(processedBlockNum) - } + if processedTxNum > 0 { pe.outputTxNum.Store(processedTxNum) blockComplete.Store(stoppedAtBlockEnd) @@ -195,11 +208,17 @@ func (pe *parallelExecutor) applyLoop(ctx context.Context, maxTxNum uint64, bloc // Maybe need split channels? Maybe don't exit from ApplyLoop? Maybe current way is also ok? func (pe *parallelExecutor) rwLoop(ctx context.Context, maxTxNum uint64, logger log.Logger) error { - tx, err := pe.chainDb.BeginRw(ctx) - if err != nil { - return err + //fmt.Println("rwLoop started", maxTxNum) + //defer fmt.Println("rwLoop done") + + tx := pe.applyTx + if tx == nil { + tx, err := pe.cfg.db.BeginRw(ctx) + if err != nil { + return err + } + defer tx.Rollback() } - defer tx.Rollback() pe.doms.SetTx(tx) @@ -213,8 +232,6 @@ func (pe *parallelExecutor) rwLoop(ctx context.Context, maxTxNum uint64, logger go pe.applyLoop(applyCtx, maxTxNum, &blockComplete, pe.rwLoopErrCh) - outputBlockNum := stages.SyncMetrics[stages.Execution] - for pe.outputTxNum.Load() <= maxTxNum { select { case <-ctx.Done(): @@ -222,16 +239,16 @@ func (pe *parallelExecutor) rwLoop(ctx context.Context, maxTxNum uint64, logger case <-pe.logEvery.C: stepsInDB := rawdbhelpers.IdxStepsCountV3(tx) - pe.progress.Log("", pe.rs, pe.in, pe.rws, pe.rs.DoneCount(), 0 /* TODO logGas*/, pe.lastBlockNum.Load(), outputBlockNum.GetValueUint64(), pe.outputTxNum.Load(), mxExecRepeats.GetValueUint64(), stepsInDB, pe.shouldGenerateChangesets, pe.inMemExec) + pe.progress.Log("", pe.rs, pe.in, pe.rws, pe.rs.DoneCount(), 0 /* TODO logGas*/, pe.lastBlockNum.Load(), pe.outputBlockNum.GetValueUint64(), pe.outputTxNum.Load(), mxExecRepeats.GetValueUint64(), stepsInDB, pe.shouldGenerateChangesets, pe.inMemExec) if pe.agg.HasBackgroundFilesBuild() { logger.Info(fmt.Sprintf("[%s] Background files build", pe.execStage.LogPrefix()), "progress", pe.agg.BackgroundProgress()) } case <-pe.pruneEvery.C: if pe.rs.SizeEstimate() < pe.cfg.batchSize.Bytes() { - if pe.doms.BlockNum() != outputBlockNum.GetValueUint64() { - panic(fmt.Errorf("%d != %d", pe.doms.BlockNum(), outputBlockNum.GetValueUint64())) + if pe.doms.BlockNum() != pe.outputBlockNum.GetValueUint64() { + panic(fmt.Errorf("%d != %d", pe.doms.BlockNum(), pe.outputBlockNum.GetValueUint64())) } - _, err := pe.doms.ComputeCommitment(ctx, true, outputBlockNum.GetValueUint64(), pe.execStage.LogPrefix()) + _, err := pe.doms.ComputeCommitment(ctx, true, pe.outputBlockNum.GetValueUint64(), pe.execStage.LogPrefix()) if err != nil { return err } @@ -264,7 +281,7 @@ func (pe *parallelExecutor) rwLoop(ctx context.Context, maxTxNum uint64, logger pe.applyWorker.ResetTx(tx) processedTxNum, conflicts, triggers, processedBlockNum, stoppedAtBlockEnd, err := - pe.processResultQueue(ctx, pe.outputTxNum.Load(), tx, nil, false, true) + pe.processResultQueue(ctx, pe.outputTxNum.Load(), nil, false, true) if err != nil { return err } @@ -272,7 +289,7 @@ func (pe *parallelExecutor) rwLoop(ctx context.Context, maxTxNum uint64, logger mxExecRepeats.AddInt(conflicts) mxExecTriggers.AddInt(triggers) if processedBlockNum > 0 { - outputBlockNum.SetUint64(processedBlockNum) + pe.outputBlockNum.SetUint64(processedBlockNum) } if processedTxNum > 0 { pe.outputTxNum.Store(processedTxNum) @@ -309,16 +326,16 @@ func (pe *parallelExecutor) rwLoop(ctx context.Context, maxTxNum uint64, logger pe.doms.ClearRam(true) t3 = time.Since(tt) - if err = pe.execStage.Update(tx, outputBlockNum.GetValueUint64()); err != nil { + if err := pe.execStage.Update(tx, pe.outputBlockNum.GetValueUint64()); err != nil { return err } - if _, err = rawdb.IncrementStateVersion(pe.applyTx); err != nil { + if _, err := rawdb.IncrementStateVersion(tx); err != nil { return fmt.Errorf("writing plain state version: %w", err) } tx.CollectMetrics() tt = time.Now() - if err = tx.Commit(); err != nil { + if err := tx.Commit(); err != nil { return err } t4 = time.Since(tt) @@ -330,7 +347,8 @@ func (pe *parallelExecutor) rwLoop(ctx context.Context, maxTxNum uint64, logger }(); err != nil { return err } - if tx, err = pe.chainDb.BeginRw(ctx); err != nil { + var err error + if tx, err = pe.cfg.db.BeginRw(ctx); err != nil { return err } defer tx.Rollback() @@ -344,29 +362,35 @@ func (pe *parallelExecutor) rwLoop(ctx context.Context, maxTxNum uint64, logger logger.Info("Committed", "time", time.Since(commitStart), "drain", t0, "drain_and_lock", t1, "rs.flush", t2, "agg.flush", t3, "tx.commit", t4) } } - if err = pe.doms.Flush(ctx, tx); err != nil { + if err := pe.doms.Flush(ctx, tx); err != nil { return err } - if err = pe.execStage.Update(tx, outputBlockNum.GetValueUint64()); err != nil { + if err := pe.execStage.Update(tx, pe.outputBlockNum.GetValueUint64()); err != nil { return err } - if err = tx.Commit(); err != nil { + if err := tx.Commit(); err != nil { return err } return nil } -func (pe *parallelExecutor) processResultQueue(ctx context.Context, inputTxNum uint64, applyTx kv.Tx, backPressure chan<- struct{}, canRetry, forceStopAtBlockEnd bool) (outputTxNum uint64, conflicts, triggers int, processedBlockNum uint64, stopedAtBlockEnd bool, err error) { +func (pe *parallelExecutor) processResultQueue(ctx context.Context, inputTxNum uint64, backPressure chan<- struct{}, canRetry, forceStopAtBlockEnd bool) (outputTxNum uint64, conflicts, triggers int, processedBlockNum uint64, stopedAtBlockEnd bool, err error) { rwsIt := pe.rws.Iter() defer rwsIt.Close() + //defer fmt.Println("PRQ", "Done") var i int outputTxNum = inputTxNum for rwsIt.HasNext(outputTxNum) { txTask := rwsIt.PopNext() + //fmt.Println("PRQ", txTask.BlockNum, txTask.TxIndex, txTask.TxNum) if txTask.Error != nil || !pe.rs.ReadsValid(txTask.ReadLists) { conflicts++ - + //fmt.Println(txTask.TxNum, txTask.Error) + if errors.Is(txTask.Error, vm.ErrIntraBlockStateFailed) || + errors.Is(txTask.Error, core.ErrStateTransitionFailed) { + return outputTxNum, conflicts, triggers, processedBlockNum, false, fmt.Errorf("%w: %v", consensus.ErrInvalidBlock, txTask.Error) + } if i > 0 && canRetry { //send to re-exex pe.rs.ReTry(txTask, pe.in) @@ -374,8 +398,9 @@ func (pe *parallelExecutor) processResultQueue(ctx context.Context, inputTxNum u } // resolve first conflict right here: it's faster and conflict-free - pe.applyWorker.RunTxTask(txTask, pe.isMining) + pe.applyWorker.RunTxTaskNoLock(txTask.Reset(), pe.isMining) if txTask.Error != nil { + //fmt.Println("RETRY", txTask.TxNum, txTask.Error) return outputTxNum, conflicts, triggers, processedBlockNum, false, fmt.Errorf("%w: %v", consensus.ErrInvalidBlock, txTask.Error) } if pe.cfg.syncCfg.ChaosMonkey { @@ -395,6 +420,11 @@ func (pe *parallelExecutor) processResultQueue(ctx context.Context, inputTxNum u if err != nil { return outputTxNum, conflicts, triggers, processedBlockNum, false, fmt.Errorf("StateV3.Apply: %w", err) } + + if processedBlockNum > pe.lastBlockNum.Load() { + pe.outputBlockNum.SetUint64(processedBlockNum) + pe.lastBlockNum.Store(processedBlockNum) + } //if !bytes.Equal(rh, txTask.BlockRoot[:]) { // log.Error("block hash mismatch", "rh", hex.EncodeToString(rh), "blockRoot", hex.EncodeToString(txTask.BlockRoot[:]), "bn", txTask.BlockNum, "txn", txTask.TxNum) // return outputTxNum, conflicts, triggers, processedBlockNum, false, fmt.Errorf("block hashk mismatch: %x != %x bn =%d, txn= %d", rh, txTask.BlockRoot[:], txTask.BlockNum, txTask.TxNum) @@ -412,7 +442,9 @@ func (pe *parallelExecutor) processResultQueue(ctx context.Context, inputTxNum u return outputTxNum, conflicts, triggers, processedBlockNum, false, fmt.Errorf("StateV3.Apply: %w", err) } processedBlockNum = txTask.BlockNum - stopedAtBlockEnd = txTask.Final + if !stopedAtBlockEnd { + stopedAtBlockEnd = txTask.Final + } if forceStopAtBlockEnd && txTask.Final { break } @@ -422,8 +454,12 @@ func (pe *parallelExecutor) processResultQueue(ctx context.Context, inputTxNum u func (pe *parallelExecutor) run(ctx context.Context, maxTxNum uint64, logger log.Logger) context.CancelFunc { pe.slowDownLimit = time.NewTicker(time.Second) + pe.rwsConsumed = make(chan struct{}, 1) + pe.rwLoopErrCh = make(chan error) + pe.in = state.NewQueueWithRetry(100_000) + pe.execWorkers, _, pe.rws, pe.stopWorkers, pe.waitWorkers = exec3.NewWorkersPool( - pe.RWMutex.RLocker(), pe.accumulator, logger, ctx, true, pe.chainDb, pe.rs, pe.in, + pe.RWMutex.RLocker(), pe.accumulator, logger, ctx, true, pe.cfg.db, pe.rs, pe.in, pe.cfg.blockReader, pe.cfg.chainConfig, pe.cfg.genesis, pe.cfg.engine, pe.workerCount+1, pe.cfg.dirs, pe.isMining) rwLoopCtx, rwLoopCtxCancel := context.WithCancel(ctx) @@ -433,7 +469,7 @@ func (pe *parallelExecutor) run(ctx context.Context, maxTxNum uint64, logger log defer pe.in.Close() defer pe.applyLoopWg.Wait() defer func() { - log.Warn("[dbg] rwloop exit") + logger.Warn("[dbg] rwloop exit") }() return pe.rwLoop(rwLoopCtx, maxTxNum, logger) }) @@ -443,6 +479,8 @@ func (pe *parallelExecutor) run(ctx context.Context, maxTxNum uint64, logger log pe.slowDownLimit.Stop() pe.wait() pe.stopWorkers() + close(pe.rwsConsumed) + pe.in.Close() } } diff --git a/eth/stagedsync/exec3_serial.go b/eth/stagedsync/exec3_serial.go index 2a59dc12099..cb271284533 100644 --- a/eth/stagedsync/exec3_serial.go +++ b/eth/stagedsync/exec3_serial.go @@ -4,40 +4,22 @@ import ( "context" "errors" "fmt" - "sync/atomic" "time" chaos_monkey "github.com/erigontech/erigon/tests/chaos-monkey" - "github.com/erigontech/erigon-lib/common" - "github.com/erigontech/erigon-lib/kv" "github.com/erigontech/erigon-lib/log/v3" state2 "github.com/erigontech/erigon-lib/state" - "github.com/erigontech/erigon/cmd/state/exec3" "github.com/erigontech/erigon/consensus" "github.com/erigontech/erigon/core" "github.com/erigontech/erigon/core/rawdb/rawtemporaldb" "github.com/erigontech/erigon/core/state" "github.com/erigontech/erigon/core/types" - "github.com/erigontech/erigon/turbo/shards" ) type serialExecutor struct { - cfg ExecuteBlockCfg - execStage *StageState - agg *state2.Aggregator - rs *state.StateV3 - doms *state2.SharedDomains - accumulator *shards.Accumulator - u Unwinder - isMining bool - inMemExec bool + txExecutor skipPostEvaluation bool - applyTx kv.RwTx - worker *exec3.Worker - outputTxNum *atomic.Uint64 - logger log.Logger - // outputs txCount uint64 usedGas uint64 @@ -58,7 +40,7 @@ func (se *serialExecutor) execute(ctx context.Context, tasks []*state.TxTask) (c return false, nil } - se.worker.RunTxTaskNoLock(txTask, se.isMining) + se.applyWorker.RunTxTaskNoLock(txTask, se.isMining) if err := func() error { if errors.Is(txTask.Error, context.Canceled) { return txTask.Error @@ -91,6 +73,8 @@ func (se *serialExecutor) execute(ctx context.Context, tasks []*state.TxTask) (c return fmt.Errorf("%w, txnIdx=%d, %v", consensus.ErrInvalidBlock, txTask.TxIndex, err) //same as in stage_exec.go } } + + se.outputBlockNum.SetUint64(txTask.BlockNum) } if se.cfg.syncCfg.ChaosMonkey { chaosErr := chaos_monkey.ThrowRandomConsensusError(se.execStage.CurrentSyncCycle.IsInitialCycle, txTask.TxIndex, se.cfg.badBlockHalt, txTask.Error) @@ -149,27 +133,6 @@ func (se *serialExecutor) execute(ctx context.Context, tasks []*state.TxTask) (c return true, nil } -func (se *serialExecutor) tx() kv.RwTx { - return se.applyTx -} - -func (se *serialExecutor) readState() *state.StateV3 { - return se.rs -} - -func (se *serialExecutor) domains() *state2.SharedDomains { - return se.doms -} - -func (se *serialExecutor) getHeader(ctx context.Context, hash common.Hash, number uint64) (h *types.Header) { - var err error - h, err = se.cfg.blockReader.Header(ctx, se.applyTx, hash, number) - if err != nil { - panic(err) - } - return h -} - func (se *serialExecutor) commit(ctx context.Context, txNum uint64, blockNum uint64, useExternalTx bool) (t2 time.Duration, err error) { se.doms.Close() if err = se.execStage.Update(se.applyTx, blockNum); err != nil { @@ -199,8 +162,8 @@ func (se *serialExecutor) commit(ctx context.Context, txNum uint64, blockNum uin se.doms.SetTxNum(txNum) se.rs = state.NewStateV3(se.doms, se.logger) - se.worker.ResetTx(se.applyTx) - se.worker.ResetState(se.rs, se.accumulator) + se.applyWorker.ResetTx(se.applyTx) + se.applyWorker.ResetState(se.rs, se.accumulator) return t2, nil } diff --git a/eth/tracers/js/goja.go b/eth/tracers/js/goja.go index ac530454f68..7421136864e 100644 --- a/eth/tracers/js/goja.go +++ b/eth/tracers/js/goja.go @@ -675,8 +675,12 @@ func (do *dbObj) GetBalance(addrSlice goja.Value) goja.Value { return nil } addr := libcommon.BytesToAddress(a) - value := do.ibs.GetBalance(addr).ToBig() - res, err := do.toBig(do.vm, value.String()) + value, err := do.ibs.GetBalance(addr) + if err != nil { + do.vm.Interrupt(err) + return nil + } + res, err := do.toBig(do.vm, value.ToBig().String()) if err != nil { do.vm.Interrupt(err) return nil @@ -691,7 +695,12 @@ func (do *dbObj) GetNonce(addrSlice goja.Value) uint64 { return 0 } addr := libcommon.BytesToAddress(a) - return do.ibs.GetNonce(addr) + nonce, err := do.ibs.GetNonce(addr) + if err != nil { + do.vm.Interrupt(err) + return 0 + } + return nonce } func (do *dbObj) GetCode(addrSlice goja.Value) goja.Value { @@ -701,7 +710,11 @@ func (do *dbObj) GetCode(addrSlice goja.Value) goja.Value { return nil } addr := libcommon.BytesToAddress(a) - code := do.ibs.GetCode(addr) + code, err := do.ibs.GetCode(addr) + if err != nil { + do.vm.Interrupt(err) + return nil + } res, err := do.toBuf(do.vm, code) if err != nil { do.vm.Interrupt(err) @@ -740,7 +753,12 @@ func (do *dbObj) Exists(addrSlice goja.Value) bool { return false } addr := libcommon.BytesToAddress(a) - return do.ibs.Exist(addr) + exists, err := do.ibs.Exist(addr) + if err != nil { + do.vm.Interrupt(err) + return false + } + return exists } func (do *dbObj) setupObject() *goja.Object { diff --git a/eth/tracers/js/tracer_test.go b/eth/tracers/js/tracer_test.go index 96624bca385..8e43dd6a44a 100644 --- a/eth/tracers/js/tracer_test.go +++ b/eth/tracers/js/tracer_test.go @@ -56,8 +56,10 @@ type dummyStatedb struct { state.IntraBlockState } -func (*dummyStatedb) GetRefund() uint64 { return 1337 } -func (*dummyStatedb) GetBalance(addr libcommon.Address) *uint256.Int { return &uint256.Int{} } +func (*dummyStatedb) GetRefund() uint64 { return 1337 } +func (*dummyStatedb) GetBalance(addr libcommon.Address) (*uint256.Int, error) { + return &uint256.Int{}, nil +} type vmContext struct { blockCtx evmtypes.BlockContext diff --git a/eth/tracers/logger/access_list_tracer.go b/eth/tracers/logger/access_list_tracer.go index 882bb51955b..9dbfe7d8ebc 100644 --- a/eth/tracers/logger/access_list_tracer.go +++ b/eth/tracers/logger/access_list_tracer.go @@ -222,7 +222,7 @@ func (a *AccessListTracer) CaptureState(pc uint64, op vm.OpCode, gas, cost uint6 if op == vm.CREATE { // contract address for CREATE can only be generated with state if a.state != nil { - nonce := a.state.GetNonce(caller) + nonce, _ := a.state.GetNonce(caller) addr := crypto.CreateAddress(caller, nonce) if _, ok := a.excl[addr]; !ok { a.createdContracts[addr] = struct{}{} @@ -240,7 +240,6 @@ func (a *AccessListTracer) CaptureState(pc uint64, op vm.OpCode, gas, cost uint6 a.createdContracts[addr] = struct{}{} } } - } func (*AccessListTracer) CaptureFault(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, depth int, err error) { diff --git a/eth/tracers/native/prestate.go b/eth/tracers/native/prestate.go index e32084d263f..0a896748906 100644 --- a/eth/tracers/native/prestate.go +++ b/eth/tracers/native/prestate.go @@ -171,7 +171,7 @@ func (t *prestateTracer) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, addr := libcommon.Address(stackData[stackLen-2].Bytes20()) t.lookupAccount(addr) case op == vm.CREATE: - nonce := t.env.IntraBlockState().GetNonce(caller) + nonce, _ := t.env.IntraBlockState().GetNonce(caller) addr := crypto.CreateAddress(caller, nonce) t.lookupAccount(addr) t.created[addr] = true @@ -203,12 +203,12 @@ func (t *prestateTracer) CaptureTxEnd(restGas uint64) { } modified := false postAccount := &account{Storage: make(map[libcommon.Hash]libcommon.Hash)} - newBalance := t.env.IntraBlockState().GetBalance(addr).ToBig() - newNonce := t.env.IntraBlockState().GetNonce(addr) + newBalance, _ := t.env.IntraBlockState().GetBalance(addr) + newNonce, _ := t.env.IntraBlockState().GetNonce(addr) - if newBalance.Cmp(t.pre[addr].Balance) != 0 { + if newBalance.ToBig().Cmp(t.pre[addr].Balance) != 0 { modified = true - postAccount.Balance = newBalance + postAccount.Balance = newBalance.ToBig() } if newNonce != t.pre[addr].Nonce { modified = true @@ -216,7 +216,7 @@ func (t *prestateTracer) CaptureTxEnd(restGas uint64) { } if !t.config.DisableCode { - newCode := t.env.IntraBlockState().GetCode(addr) + newCode, _ := t.env.IntraBlockState().GetCode(addr) if !bytes.Equal(newCode, t.pre[addr].Code) { modified = true postAccount.Code = newCode @@ -292,13 +292,17 @@ func (t *prestateTracer) lookupAccount(addr libcommon.Address) { return } + balance, _ := t.env.IntraBlockState().GetBalance(addr) + nonce, _ := t.env.IntraBlockState().GetNonce(addr) + code, _ := t.env.IntraBlockState().GetCode(addr) + t.pre[addr] = &account{ - Balance: t.env.IntraBlockState().GetBalance(addr).ToBig(), - Nonce: t.env.IntraBlockState().GetNonce(addr), + Balance: balance.ToBig(), + Nonce: nonce, } if !t.config.DisableCode { - t.pre[addr].Code = t.env.IntraBlockState().GetCode(addr) + t.pre[addr].Code = code } if !t.config.DisableStorage { t.pre[addr].Storage = make(map[libcommon.Hash]libcommon.Hash) diff --git a/polygon/bor/bor.go b/polygon/bor/bor.go index 36337ac941c..1bba50d515d 100644 --- a/polygon/bor/bor.go +++ b/polygon/bor/bor.go @@ -1673,22 +1673,42 @@ func (c *Bor) getNextHeimdallSpanForTest( } // BorTransfer transfer in Bor -func BorTransfer(db evmtypes.IntraBlockState, sender, recipient libcommon.Address, amount *uint256.Int, bailout bool) { +func BorTransfer(db evmtypes.IntraBlockState, sender, recipient libcommon.Address, amount *uint256.Int, bailout bool) error { // get inputs before - input1 := db.GetBalance(sender).Clone() - input2 := db.GetBalance(recipient).Clone() - + input1, err := db.GetBalance(sender) + if err != nil { + return err + } + input1 = input1.Clone() + input2, err := db.GetBalance(recipient) + if err != nil { + return err + } + input2 = input2.Clone() if !bailout { - db.SubBalance(sender, amount, tracing.BalanceChangeTransfer) + err := db.SubBalance(sender, amount, tracing.BalanceChangeTransfer) + if err != nil { + return err + } + } + err = db.AddBalance(recipient, amount, tracing.BalanceChangeTransfer) + if err != nil { + return err } - db.AddBalance(recipient, amount, tracing.BalanceChangeTransfer) - // get outputs after - output1 := db.GetBalance(sender).Clone() - output2 := db.GetBalance(recipient).Clone() - + output1, err := db.GetBalance(sender) + if err != nil { + return err + } + output1 = output1.Clone() + output2, err := db.GetBalance(recipient) + if err != nil { + return err + } + output2 = output2.Clone() // add transfer log into state addTransferLog(db, transferLogSig, sender, recipient, amount, input1, input2, output1, output2) + return nil } func (c *Bor) GetTransferFunc() evmtypes.TransferFunc { diff --git a/tests/block_test_util.go b/tests/block_test_util.go index f2822f97f66..b945526201e 100644 --- a/tests/block_test_util.go +++ b/tests/block_test_util.go @@ -319,9 +319,18 @@ func (bt *BlockTest) validatePostState(statedb *state.IntraBlockState) error { // validate post state accounts in test file against what we have in state db for addr, acct := range bt.json.Post { // address is indirectly verified by the other fields, as it's the db key - code2 := statedb.GetCode(addr) - balance2 := statedb.GetBalance(addr) - nonce2 := statedb.GetNonce(addr) + code2, err := statedb.GetCode(addr) + if err != nil { + return err + } + balance2, err := statedb.GetBalance(addr) + if err != nil { + return err + } + nonce2, err := statedb.GetNonce(addr) + if err != nil { + return err + } if nonce2 != acct.Nonce { return fmt.Errorf("account nonce mismatch for addr: %x want: %d have: %d", addr, acct.Nonce, nonce2) } diff --git a/tests/statedb_chain_test.go b/tests/statedb_chain_test.go index 7449ea92215..525b3c0f12c 100644 --- a/tests/statedb_chain_test.go +++ b/tests/statedb_chain_test.go @@ -105,10 +105,18 @@ func TestSelfDestructReceive(t *testing.T) { if err := m.DB.View(context.Background(), func(tx kv.Tx) error { st := state.New(m.NewStateReader(tx)) - if !st.Exist(address) { + exist, err := st.Exist(address) + if err != nil { + return err + } + if !exist { t.Error("expected account to exist") } - if st.Exist(contractAddress) { + exist, err = st.Exist(contractAddress) + if err != nil { + return err + } + if exist { t.Error("expected contractAddress to not exist before block 0", contractAddress.String()) } return nil @@ -131,13 +139,25 @@ func TestSelfDestructReceive(t *testing.T) { // and that means that the state of the accounts written in the first block was correct. // This test checks that the storage root of the account is properly set to the root of the empty tree st := state.New(m.NewStateReader(tx)) - if !st.Exist(address) { + exist, err := st.Exist(address) + if err != nil { + t.Error(err) + } + if !exist { t.Error("expected account to exist") } - if !st.Exist(contractAddress) { + exist, err = st.Exist(contractAddress) + if err != nil { + t.Error(err) + } + if !exist { t.Error("expected contractAddress to exist at the block 2", contractAddress.String()) } - if len(st.GetCode(contractAddress)) != 0 { + code, err := st.GetCode(contractAddress) + if err != nil { + t.Error(err) + } + if len(code) != 0 { t.Error("expected empty code in contract at block 2", contractAddress.String()) } return nil diff --git a/tests/statedb_insert_chain_transaction_test.go b/tests/statedb_insert_chain_transaction_test.go index e9f28a610d2..a2d3eddd264 100644 --- a/tests/statedb_insert_chain_transaction_test.go +++ b/tests/statedb_insert_chain_transaction_test.go @@ -93,17 +93,33 @@ func TestInsertIncorrectStateRootDifferentAccounts(t *testing.T) { defer tx.Rollback() st := state.New(m.NewStateReader(tx)) - if !st.Exist(to) { + exist, err := st.Exist(to) + if err != nil { + t.Error(err) + } + if !exist { t.Error("expected account to exist") } - if balance := st.GetBalance(from); balance.Uint64() != 1000000000 { + balance, err := st.GetBalance(from) + if err != nil { + t.Error(err) + } + if balance.Uint64() != 1000000000 { t.Fatalf("got %v, expected %v", balance, 1000000000) } - if balance := st.GetBalance(data.addresses[1]); balance.Uint64() != 999995000 { + balance, err = st.GetBalance(data.addresses[1]) + if err != nil { + t.Error(err) + } + if balance.Uint64() != 999995000 { t.Fatalf("got %v, expected %v", balance, 999995000) } - if balance := st.GetBalance(to); balance.Uint64() != 5000 { + balance, err = st.GetBalance(to) + if err != nil { + t.Error(err) + } + if balance.Uint64() != 5000 { t.Fatalf("got %v, expected %v", balance, 5000) } } @@ -161,14 +177,26 @@ func TestInsertIncorrectStateRootSameAccount(t *testing.T) { defer tx.Rollback() st := state.New(m.NewStateReader(tx)) - if !st.Exist(to) { + exist, err := st.Exist(to) + if err != nil { + t.Error(err) + } + if !exist { t.Error("expected account to exist") } - if balance := st.GetBalance(from); balance.Uint64() != 999995000 { + balance, err := st.GetBalance(from) + if err != nil { + t.Error(err) + } + if balance.Uint64() != 999995000 { t.Fatalf("got %v, expected %v", balance, 999995000) } - if balance := st.GetBalance(to); balance.Uint64() != 5000 { + balance, err = st.GetBalance(to) + if err != nil { + t.Error(err) + } + if balance.Uint64() != 5000 { t.Fatalf("got %v, expected %v", balance, 5000) } } @@ -223,14 +251,26 @@ func TestInsertIncorrectStateRootSameAccountSameAmount(t *testing.T) { defer tx.Rollback() st := state.New(m.NewStateReader(tx)) - if !st.Exist(to) { + exist, err := st.Exist(to) + if err != nil { + t.Error(err) + } + if !exist { t.Error("expected account to exist") } - if balance := st.GetBalance(from); balance.Uint64() != 999999000 { + balance, err := st.GetBalance(from) + if err != nil { + t.Error(err) + } + if balance.Uint64() != 999999000 { t.Fatalf("got %v, expected %v", balance, 999999000) } - if balance := st.GetBalance(to); balance.Uint64() != 1000 { + balance, err = st.GetBalance(to) + if err != nil { + t.Error(err) + } + if balance.Uint64() != 1000 { t.Fatalf("got %v, expected %v", balance, 1000) } } @@ -285,14 +325,26 @@ func TestInsertIncorrectStateRootAllFundsRoot(t *testing.T) { defer tx.Rollback() st := state.New(m.NewStateReader(tx)) - if !st.Exist(to) { + exist, err := st.Exist(to) + if err != nil { + t.Error(err) + } + if !exist { t.Error("expected account to exist") } - if balance := st.GetBalance(from); balance.Uint64() != 2000 { + balance, err := st.GetBalance(from) + if err != nil { + t.Error(err) + } + if balance.Uint64() != 2000 { t.Fatalf("got %v, expected %v", balance, 2000) } - if balance := st.GetBalance(to); balance.Uint64() != 1000 { + balance, err = st.GetBalance(to) + if err != nil { + t.Error(err) + } + if balance.Uint64() != 1000 { t.Fatalf("got %v, expected %v", balance, 1000) } } @@ -347,14 +399,26 @@ func TestInsertIncorrectStateRootAllFunds(t *testing.T) { defer tx.Rollback() st := state.New(m.NewStateReader(tx)) - if !st.Exist(to) { + exist, err := st.Exist(to) + if err != nil { + t.Error(err) + } + if !exist { t.Error("expected account to exist") } - if balance := st.GetBalance(from); balance.Uint64() != 2000 { + balance, err := st.GetBalance(from) + if err != nil { + t.Error(err) + } + if balance.Uint64() != 2000 { t.Fatalf("got %v, expected %v", balance, 2000) } - if balance := st.GetBalance(to); balance.Uint64() != 1000 { + balance, err = st.GetBalance(to) + if err != nil { + t.Error(err) + } + if balance.Uint64() != 1000 { t.Fatalf("got %v, expected %v", balance, 1000) } } @@ -388,11 +452,18 @@ func TestAccountDeployIncorrectRoot(t *testing.T) { } err = m.DB.View(context.Background(), func(tx kv.Tx) error { st := state.New(m.NewStateReader(tx)) - if !st.Exist(from) { + exist, err := st.Exist(from) + if err != nil { + return err + } + if !exist { t.Error("expected account to exist") } - - if st.Exist(contractAddress) { + exist, err = st.Exist(contractAddress) + if err != nil { + return err + } + if exist { t.Error("expected contractAddress to not exist at the block 0", contractAddress.Hash().String()) } return nil @@ -411,11 +482,19 @@ func TestAccountDeployIncorrectRoot(t *testing.T) { err = m.DB.View(context.Background(), func(tx kv.Tx) error { st := state.New(m.NewStateReader(tx)) - if !st.Exist(from) { + exist, err := st.Exist(from) + if err != nil { + return err + } + if !exist { t.Error("expected account to exist") } - if st.Exist(contractAddress) { + exist, err = st.Exist(contractAddress) + if err != nil { + return err + } + if exist { t.Error("expected contractAddress to not exist at the block 1", contractAddress.Hash().String()) } return nil @@ -429,11 +508,19 @@ func TestAccountDeployIncorrectRoot(t *testing.T) { err = m.DB.View(context.Background(), func(tx kv.Tx) error { st := state.New(m.NewStateReader(tx)) - if !st.Exist(from) { + exist, err := st.Exist(from) + if err != nil { + return err + } + if !exist { t.Error("expected account to exist") } - if !st.Exist(contractAddress) { + exist, err = st.Exist(contractAddress) + if err != nil { + return err + } + if !exist { t.Error("expected contractAddress to not exist at the block 1", contractAddress.Hash().String()) } return nil @@ -475,11 +562,19 @@ func TestAccountCreateIncorrectRoot(t *testing.T) { err = m.DB.View(context.Background(), func(tx kv.Tx) error { st := state.New(m.NewStateReader(tx)) - if !st.Exist(from) { + exist, err := st.Exist(from) + if err != nil { + return err + } + if !exist { t.Error("expected account to exist") } - if st.Exist(contractAddress) { + exist, err = st.Exist(contractAddress) + if err != nil { + return err + } + if exist { t.Error("expected contractAddress to not exist at the block 0", contractAddress.Hash().String()) } @@ -493,11 +588,19 @@ func TestAccountCreateIncorrectRoot(t *testing.T) { } err = m.DB.View(context.Background(), func(tx kv.Tx) error { st := state.New(m.NewStateReader(tx)) - if !st.Exist(from) { + exist, err := st.Exist(from) + if err != nil { + return err + } + if !exist { t.Error("expected account to exist") } - if !st.Exist(contractAddress) { + exist, err = st.Exist(contractAddress) + if err != nil { + return err + } + if !exist { t.Error("expected contractAddress to exist at the block 2", contractAddress.Hash().String()) } @@ -559,11 +662,19 @@ func TestAccountUpdateIncorrectRoot(t *testing.T) { err = m.DB.View(context.Background(), func(tx kv.Tx) error { st := state.New(m.NewStateReader(tx)) - if !st.Exist(from) { + exist, err := st.Exist(from) + if err != nil { + return err + } + if !exist { t.Error("expected account to exist") } - if st.Exist(contractAddress) { + exist, err = st.Exist(contractAddress) + if err != nil { + return err + } + if exist { t.Error("expected contractAddress to not exist at the block 0", contractAddress.Hash().String()) } @@ -578,11 +689,19 @@ func TestAccountUpdateIncorrectRoot(t *testing.T) { err = m.DB.View(context.Background(), func(tx kv.Tx) error { st := state.New(m.NewStateReader(tx)) - if !st.Exist(from) { + exist, err := st.Exist(from) + if err != nil { + return err + } + if !exist { t.Error("expected account to exist") } - if !st.Exist(contractAddress) { + exist, err = st.Exist(contractAddress) + if err != nil { + return err + } + if !exist { t.Error("expected contractAddress to exist at the block 2", contractAddress.Hash().String()) } return nil @@ -648,11 +767,19 @@ func TestAccountDeleteIncorrectRoot(t *testing.T) { err = m.DB.View(context.Background(), func(tx kv.Tx) error { st := state.New(m.NewStateReader(tx)) - if !st.Exist(from) { + exist, err := st.Exist(from) + if err != nil { + return err + } + if !exist { t.Error("expected account to exist") } - if st.Exist(contractAddress) { + exist, err = st.Exist(contractAddress) + if err != nil { + return err + } + if exist { t.Error("expected contractAddress to not exist at the block 0", contractAddress.Hash().String()) } return nil @@ -666,11 +793,19 @@ func TestAccountDeleteIncorrectRoot(t *testing.T) { err = m.DB.View(context.Background(), func(tx kv.Tx) error { st := state.New(m.NewStateReader(tx)) - if !st.Exist(from) { + exist, err := st.Exist(from) + if err != nil { + return err + } + if !exist { t.Error("expected account to exist") } - if !st.Exist(contractAddress) { + exist, err = st.Exist(contractAddress) + if err != nil { + return err + } + if !exist { t.Error("expected contractAddress to exist at the block 1", contractAddress.Hash().String()) } return nil diff --git a/turbo/jsonrpc/eth_call.go b/turbo/jsonrpc/eth_call.go index cc6d8dc748a..2f9cd154068 100644 --- a/turbo/jsonrpc/eth_call.go +++ b/turbo/jsonrpc/eth_call.go @@ -205,7 +205,10 @@ func (api *APIImpl) EstimateGas(ctx context.Context, argsOrNil *ethapi2.CallArgs return 0, errors.New("can't get the current state") } - balance := state.GetBalance(*args.From) // from can't be nil + balance, err := state.GetBalance(*args.From) // from can't be nil + if err != nil { + return 0, err + } available := balance.ToBig() if args.Value != nil { if args.Value.ToInt().Cmp(available) >= 0 { diff --git a/turbo/jsonrpc/eth_call_test.go b/turbo/jsonrpc/eth_call_test.go index b78c18a4a02..c8dfee1d378 100644 --- a/turbo/jsonrpc/eth_call_test.go +++ b/turbo/jsonrpc/eth_call_test.go @@ -553,13 +553,17 @@ func chainWithDeployedContract(t *testing.T) (*mock.MockSentry, libcommon.Addres assert.NoError(t, err) st := state.New(stateReader) assert.NoError(t, err) - assert.False(t, st.Exist(contractAddr), "Contract should not exist at block #1") + exist, err := st.Exist(contractAddr) + assert.NoError(t, err) + assert.False(t, exist, "Contract should not exist at block #1") stateReader, err = rpchelper.CreateHistoryStateReader(tx, rawdbv3.TxNums, 2, 0, "") assert.NoError(t, err) st = state.New(stateReader) assert.NoError(t, err) - assert.True(t, st.Exist(contractAddr), "Contract should exist at block #2") + exist, err = st.Exist(contractAddr) + assert.NoError(t, err) + assert.True(t, exist, "Contract should exist at block #2") return m, bankAddress, contractAddr } diff --git a/turbo/jsonrpc/overlay_api.go b/turbo/jsonrpc/overlay_api.go index ba4e970f01b..dead2ff8405 100644 --- a/turbo/jsonrpc/overlay_api.go +++ b/turbo/jsonrpc/overlay_api.go @@ -237,7 +237,10 @@ func (api *OverlayAPIImpl) CallConstructor(ctx context.Context, address common.A if err != nil { return nil, err } - code := evm.IntraBlockState().GetCode(address) + code, err := evm.IntraBlockState().GetCode(address) + if err != nil { + return nil, err + } if len(code) > 0 { c := hexutility.Bytes(code) resultCode.Code = &c @@ -506,7 +509,16 @@ func (api *OverlayAPIImpl) replayBlock(ctx context.Context, blockNum uint64, sta if !contractCreation { // bump the nonce of the sender sender := vm.AccountRef(msg.From()) - statedb.SetNonce(msg.From(), statedb.GetNonce(sender.Address())+1) + nonce, err := statedb.GetNonce(sender.Address()) + if err != nil { + log.Error(err.Error()) + return nil, err + } + err = statedb.SetNonce(msg.From(), nonce+1) + if err != nil { + log.Error(err.Error()) + return nil, err + } continue } } diff --git a/turbo/jsonrpc/overlay_create_tracer.go b/turbo/jsonrpc/overlay_create_tracer.go index 29be53228a8..c80641a5465 100644 --- a/turbo/jsonrpc/overlay_create_tracer.go +++ b/turbo/jsonrpc/overlay_create_tracer.go @@ -55,7 +55,11 @@ func (ct *OverlayCreateTracer) CaptureEnter(typ vm.OpCode, from libcommon.Addres if err != nil { ct.err = err } else { - ct.resultCode = ct.evm.IntraBlockState().GetCode(ct.contractAddress) + if result, err := ct.evm.IntraBlockState().GetCode(ct.contractAddress); err != nil { + ct.resultCode = result + } else { + ct.err = err + } } } } diff --git a/turbo/jsonrpc/trace_adhoc.go b/turbo/jsonrpc/trace_adhoc.go index 86c2ba0db9d..0a24f0beca4 100644 --- a/turbo/jsonrpc/trace_adhoc.go +++ b/turbo/jsonrpc/trace_adhoc.go @@ -662,16 +662,30 @@ func (sd *StateDiff) CreateContract(address libcommon.Address) error { } // CompareStates uses the addresses accumulated in the sdMap and compares balances, nonces, and codes of the accounts, and fills the rest of the sdMap -func (sd *StateDiff) CompareStates(initialIbs, ibs *state.IntraBlockState) { +func (sd *StateDiff) CompareStates(initialIbs, ibs *state.IntraBlockState) error { var toRemove []libcommon.Address for addr, accountDiff := range sd.sdMap { - initialExist := initialIbs.Exist(addr) - exist := ibs.Exist(addr) + initialExist, err := initialIbs.Exist(addr) + if err != nil { + return err + } + exist, err := ibs.Exist(addr) + if err != nil { + return err + } if initialExist { if exist { var allEqual = len(accountDiff.Storage) == 0 - fromBalance := initialIbs.GetBalance(addr).ToBig() - toBalance := ibs.GetBalance(addr).ToBig() + ifromBalance, err := initialIbs.GetBalance(addr) + if err != nil { + return err + } + fromBalance := ifromBalance.ToBig() + itoBalance, err := ibs.GetBalance(addr) + if err != nil { + return err + } + toBalance := itoBalance.ToBig() if fromBalance.Cmp(toBalance) == 0 { accountDiff.Balance = "=" } else { @@ -680,8 +694,14 @@ func (sd *StateDiff) CompareStates(initialIbs, ibs *state.IntraBlockState) { accountDiff.Balance = m allEqual = false } - fromCode := initialIbs.GetCode(addr) - toCode := ibs.GetCode(addr) + fromCode, err := initialIbs.GetCode(addr) + if err != nil { + return err + } + toCode, err := ibs.GetCode(addr) + if err != nil { + return err + } if bytes.Equal(fromCode, toCode) { accountDiff.Code = "=" } else { @@ -690,8 +710,14 @@ func (sd *StateDiff) CompareStates(initialIbs, ibs *state.IntraBlockState) { accountDiff.Code = m allEqual = false } - fromNonce := initialIbs.GetNonce(addr) - toNonce := ibs.GetNonce(addr) + fromNonce, err := initialIbs.GetNonce(addr) + if err != nil { + return err + } + toNonce, err := ibs.GetNonce(addr) + if err != nil { + return err + } if fromNonce == toNonce { accountDiff.Nonce = "=" } else { @@ -705,35 +731,59 @@ func (sd *StateDiff) CompareStates(initialIbs, ibs *state.IntraBlockState) { } } else { { + balance, err := initialIbs.GetBalance(addr) + if err != nil { + return err + } m := make(map[string]*hexutil.Big) - m["-"] = (*hexutil.Big)(initialIbs.GetBalance(addr).ToBig()) + m["-"] = (*hexutil.Big)(balance.ToBig()) accountDiff.Balance = m } { + code, err := initialIbs.GetCode(addr) + if err != nil { + return err + } m := make(map[string]hexutility.Bytes) - m["-"] = initialIbs.GetCode(addr) + m["-"] = code accountDiff.Code = m } { + nonce, err := initialIbs.GetNonce(addr) + if err != nil { + return err + } m := make(map[string]hexutil.Uint64) - m["-"] = hexutil.Uint64(initialIbs.GetNonce(addr)) + m["-"] = hexutil.Uint64(nonce) accountDiff.Nonce = m } } } else if exist { { + balance, err := ibs.GetBalance(addr) + if err != nil { + return err + } m := make(map[string]*hexutil.Big) - m["+"] = (*hexutil.Big)(ibs.GetBalance(addr).ToBig()) + m["+"] = (*hexutil.Big)(balance.ToBig()) accountDiff.Balance = m } { + code, err := ibs.GetCode(addr) + if err != nil { + return err + } m := make(map[string]hexutility.Bytes) - m["+"] = ibs.GetCode(addr) + m["+"] = code accountDiff.Code = m } { + nonce, err := ibs.GetNonce(addr) + if err != nil { + return err + } m := make(map[string]hexutil.Uint64) - m["+"] = hexutil.Uint64(ibs.GetNonce(addr)) + m["+"] = hexutil.Uint64(nonce) accountDiff.Nonce = m } // Transform storage @@ -749,6 +799,7 @@ func (sd *StateDiff) CompareStates(initialIbs, ibs *state.IntraBlockState) { for _, addr := range toRemove { delete(sd.sdMap, addr) } + return nil } func (api *TraceAPIImpl) ReplayTransaction(ctx context.Context, txHash libcommon.Hash, traceTypes []string, gasBailOut *bool, traceConfig *config.TraceConfig) (*TraceCallResult, error) { diff --git a/turbo/stages/blockchain_test.go b/turbo/stages/blockchain_test.go index 3c58f35a1b4..a37243413bc 100644 --- a/turbo/stages/blockchain_test.go +++ b/turbo/stages/blockchain_test.go @@ -1015,7 +1015,11 @@ func TestEIP161AccountRemoval(t *testing.T) { return } defer tx.Rollback() - if st := state.New(m.NewStateReader(tx)); !st.Exist(theAddr) { + exist, err := state.New(m.NewStateReader(tx)).Exist(theAddr) + if err != nil { + t.Fatal(err) + } + if !exist { t.Error("expected account to exist") } tx.Rollback() @@ -1025,7 +1029,11 @@ func TestEIP161AccountRemoval(t *testing.T) { t.Fatal(err) } if err = m.DB.View(m.Ctx, func(tx kv.Tx) error { - if st := state.New(m.NewStateReader(tx)); st.Exist(theAddr) { + exist, err := state.New(m.NewStateReader(tx)).Exist(theAddr) + if err != nil { + return err + } + if exist { t.Error("account should not exist") } return nil @@ -1038,7 +1046,11 @@ func TestEIP161AccountRemoval(t *testing.T) { t.Fatal(err) } if err = m.DB.View(m.Ctx, func(tx kv.Tx) error { - if st := state.New(m.NewStateReader(tx)); st.Exist(theAddr) { + exist, err := state.New(m.NewStateReader(tx)).Exist(theAddr) + if err != nil { + return err + } + if exist { t.Error("account should not exist") } return nil @@ -1104,19 +1116,27 @@ func TestDoubleAccountRemoval(t *testing.T) { st := state.New(m.NewStateReader(tx)) assert.NoError(t, err) - assert.False(t, st.Exist(theAddr), "Contract should've been removed") + exist, err := st.Exist(theAddr) + assert.NoError(t, err) + assert.False(t, exist, "Contract should've been removed") st = state.New(m.NewHistoryStateReader(1, tx)) assert.NoError(t, err) - assert.False(t, st.Exist(theAddr), "Contract should not exist at block #0") + exist, err = st.Exist(theAddr) + assert.NoError(t, err) + assert.False(t, exist, "Contract should not exist at block #0") st = state.New(m.NewHistoryStateReader(2, tx)) assert.NoError(t, err) - assert.True(t, st.Exist(theAddr), "Contract should exist at block #1") + exist, err = st.Exist(theAddr) + assert.NoError(t, err) + assert.True(t, exist, "Contract should exist at block #1") st = state.New(m.NewHistoryStateReader(3, tx)) assert.NoError(t, err) - assert.True(t, st.Exist(theAddr), "Contract should exist at block #2") + exist, err = st.Exist(theAddr) + assert.NoError(t, err) + assert.True(t, exist, "Contract should exist at block #2") } // This is a regression test (i.e. as weird as it is, don't delete it ever), which @@ -1608,7 +1628,10 @@ func TestCVE2020_26265(t *testing.T) { reader := m.NewHistoryStateReader(2, tx) statedb := state.New(reader) - got := statedb.GetBalance(aa) + got, err := statedb.GetBalance(aa) + if err != nil { + t.Fatal(err) + } if !got.Eq(new(uint256.Int).SetUint64(5)) { t.Errorf("got %x exp %x", got, 5) } @@ -1870,7 +1893,11 @@ func TestDeleteRecreateSlotsAcrossManyBlocks(t *testing.T) { } exp := expectations[i] if exp.exist { - if !statedb.Exist(aa) { + exist, err := statedb.Exist(aa) + if err != nil { + t.Fatal(err) + } + if !exist { t.Fatalf("block %d, expected %x to exist, it did not", blockNum, aa) } for slot, val := range exp.values { @@ -1882,7 +1909,11 @@ func TestDeleteRecreateSlotsAcrossManyBlocks(t *testing.T) { } } } else { - if statedb.Exist(aa) { + exist, err := statedb.Exist(aa) + if err != nil { + t.Fatal(err) + } + if exist { t.Fatalf("block %d, expected %x to not exist, it did", blockNum, aa) } } @@ -1988,7 +2019,11 @@ func TestInitThenFailCreateContract(t *testing.T) { // Import the canonical chain statedb := state.New(m.NewHistoryStateReader(2, tx)) - if got, exp := statedb.GetBalance(aa), uint64(100000); got.Uint64() != exp { + got, err := statedb.GetBalance(aa) + if err != nil { + return err + } + if exp := uint64(100000); got.Uint64() != exp { t.Fatalf("Genesis err, got %v exp %v", got, exp) } // First block tries to create, but fails @@ -1998,7 +2033,11 @@ func TestInitThenFailCreateContract(t *testing.T) { t.Fatalf("block %d: failed to insert into chain: %v", block.NumberU64(), err) } statedb = state.New(m.NewHistoryStateReader(1, tx)) - if got, exp := statedb.GetBalance(aa), uint64(100000); got.Uint64() != exp { + got, err := statedb.GetBalance(aa) + if err != nil { + return err + } + if exp := uint64(100000); got.Uint64() != exp { t.Fatalf("block %d: got %v exp %v", block.NumberU64(), got, exp) } } @@ -2198,7 +2237,10 @@ func TestEIP1559Transition(t *testing.T) { statedb := state.New(m.NewHistoryStateReader(1, tx)) // 3: Ensure that miner received only the tx's tip. - actual := statedb.GetBalance(block.Coinbase()) + actual, err := statedb.GetBalance(block.Coinbase()) + if err != nil { + return err + } expected := new(uint256.Int).Add( new(uint256.Int).SetUint64(block.GasUsed()*block.Transactions()[0].GetPrice().Uint64()), ethash.ConstantinopleBlockReward, @@ -2208,7 +2250,11 @@ func TestEIP1559Transition(t *testing.T) { } // 4: Ensure the txn sender paid for the gasUsed * (tip + block baseFee). - actual = new(uint256.Int).Sub(funds, statedb.GetBalance(addr1)) + balance, err := statedb.GetBalance(addr1) + if err != nil { + return err + } + actual = new(uint256.Int).Sub(funds, balance) expected = new(uint256.Int).SetUint64(block.GasUsed() * (block.Transactions()[0].GetPrice().Uint64() + block.BaseFee().Uint64())) if actual.Cmp(expected) != 0 { t.Fatalf("sender expenditure incorrect: expected %d, got %d", expected, actual) @@ -2240,7 +2286,10 @@ func TestEIP1559Transition(t *testing.T) { effectiveTip := block.Transactions()[0].GetPrice().Uint64() - block.BaseFee().Uint64() // 6+5: Ensure that miner received only the tx's effective tip. - actual := statedb.GetBalance(block.Coinbase()) + actual, err := statedb.GetBalance(block.Coinbase()) + if err != nil { + return err + } expected := new(uint256.Int).Add( new(uint256.Int).SetUint64(block.GasUsed()*effectiveTip), ethash.ConstantinopleBlockReward, @@ -2250,7 +2299,11 @@ func TestEIP1559Transition(t *testing.T) { } // 4: Ensure the txn sender paid for the gasUsed * (effectiveTip + block baseFee). - actual = new(uint256.Int).Sub(funds, statedb.GetBalance(addr2)) + balance, err := statedb.GetBalance(addr2) + if err != nil { + return err + } + actual = new(uint256.Int).Sub(funds, balance) expected = new(uint256.Int).SetUint64(block.GasUsed() * (effectiveTip + block.BaseFee().Uint64())) if actual.Cmp(expected) != 0 { t.Fatalf("sender balance incorrect: expected %d, got %d", expected, actual) diff --git a/turbo/stages/chain_makers_test.go b/turbo/stages/chain_makers_test.go index 08dcd772cc2..e33f34ef5dd 100644 --- a/turbo/stages/chain_makers_test.go +++ b/turbo/stages/chain_makers_test.go @@ -118,14 +118,26 @@ func TestGenerateChain(t *testing.T) { if big.NewInt(5).Cmp(current(m, tx).Number()) != 0 { t.Errorf("wrong block number: %d", current(m, tx).Number()) } - if !uint256.NewInt(989000).Eq(st.GetBalance(addr1)) { - t.Errorf("wrong balance of addr1: %s", st.GetBalance(addr1)) + balance, err := st.GetBalance(addr1) + if err != nil { + t.Error(err) + } + if !uint256.NewInt(989000).Eq(balance) { + t.Errorf("wrong balance of addr1: %s", balance) + } + balance, err = st.GetBalance(addr2) + if err != nil { + t.Error(err) + } + if !uint256.NewInt(10000).Eq(balance) { + t.Errorf("wrong balance of addr2: %s", balance) } - if !uint256.NewInt(10000).Eq(st.GetBalance(addr2)) { - t.Errorf("wrong balance of addr2: %s", st.GetBalance(addr2)) + balance, err = st.GetBalance(addr3) + if err != nil { + t.Error(err) } - if fmt.Sprintf("%s", st.GetBalance(addr3)) != "19687500000000001000" { //nolint - t.Errorf("wrong balance of addr3: %s", st.GetBalance(addr3)) + if fmt.Sprintf("%s", balance) != "19687500000000001000" { //nolint + t.Errorf("wrong balance of addr3: %s", balance) } if sentry_multi_client.EnableP2PReceipts { From 1d1fe4ccda2de4d7c62c9eefde83ba018574c5c1 Mon Sep 17 00:00:00 2001 From: Giulio rebuffo Date: Mon, 9 Dec 2024 17:12:08 +0100 Subject: [PATCH 08/24] Caplin: better fix for orphaned blocks (#13056) so the issues is that decoding caches from disk was too IO intensive. this does one batch read and calls it a day. --- cl/beacon/handler/block_production.go | 18 +++++++----------- .../fork_graph/fork_graph_disk_fs.go | 9 ++++++++- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/cl/beacon/handler/block_production.go b/cl/beacon/handler/block_production.go index c34f62abc96..750ae290b12 100644 --- a/cl/beacon/handler/block_production.go +++ b/cl/beacon/handler/block_production.go @@ -301,16 +301,10 @@ func (a *ApiHandler) GetEthV3ValidatorBlock( } // make a simple copy to the current head state - var baseState *state.CachingBeaconState - if err := a.syncedData.ViewHeadState(func(headState *state.CachingBeaconState) error { - baseState, err = headState.Copy() - if err != nil { - return err - } - return nil - }); err != nil { - return nil, err - } + baseState, err := a.forkchoiceStore.GetStateAtBlockRoot( + baseBlockRoot, + true, + ) // we start the block production from this state if err != nil { return nil, err @@ -1194,7 +1188,6 @@ func (a *ApiHandler) storeBlockAndBlobs( if headState == nil { return errors.New("failed to get head state") } - a.syncedData.OnHeadState(headState) if err := a.indiciesDB.View(ctx, func(tx kv.Tx) error { _, err := a.attestationProducer.ProduceAndCacheAttestationData(tx, headState, blockRoot, block.Block.Slot, 0) @@ -1202,6 +1195,9 @@ func (a *ApiHandler) storeBlockAndBlobs( }); err != nil { return err } + if err := a.syncedData.OnHeadState(headState); err != nil { + return fmt.Errorf("failed to update synced data: %w", err) + } return nil } diff --git a/cl/phase1/forkchoice/fork_graph/fork_graph_disk_fs.go b/cl/phase1/forkchoice/fork_graph/fork_graph_disk_fs.go index 51b7ca140ff..d6871893689 100644 --- a/cl/phase1/forkchoice/fork_graph/fork_graph_disk_fs.go +++ b/cl/phase1/forkchoice/fork_graph/fork_graph_disk_fs.go @@ -86,6 +86,7 @@ func (f *forkGraphDisk) readBeaconStateFromDisk(blockRoot libcommon.Hash, out *s if err = bs.DecodeSSZ(f.sszBuffer, int(v[0])); err != nil { return nil, fmt.Errorf("failed to decode beacon state: %w, root: %x, len: %d, decLen: %d, bs: %+v", err, blockRoot, n, len(f.sszBuffer), bs) } + // decode the cache file cacheFile, err := f.fs.Open(getBeaconStateCacheFilename(blockRoot)) if err != nil { @@ -93,7 +94,13 @@ func (f *forkGraphDisk) readBeaconStateFromDisk(blockRoot libcommon.Hash, out *s } defer cacheFile.Close() - if err := bs.DecodeCaches(cacheFile); err != nil { + f.sszBuffer = f.sszBuffer[:0] + b := bytes.NewBuffer(f.sszBuffer) + if _, err := io.Copy(b, cacheFile); err != nil { + return nil, err + } + + if err := bs.DecodeCaches(b); err != nil { return nil, err } From 03ef2b6fb42cc47dfb649fe403542c0358a6d27a Mon Sep 17 00:00:00 2001 From: antonis19 Date: Mon, 9 Dec 2024 18:04:19 +0100 Subject: [PATCH 09/24] experimental: MPT block witness for Erigon 3 (#12847) Experimental `eth_getWitness` RPC call implementation that computes the block witness for the MPT. This works roughly along the following lines: - unwind execution to the start of given blockNr - execute the block ephemerally and record touched account and storage keys using a custom StateWriter - Load each of these keys from the state trie at blockNr-1 and from the resulting grid create a merkle path for each of these keys - Merge all the merkle paths to obtain the witness trie - Verification step: execute the block "statelessly" by using the witness trie as state and check that the resulting state root matches the state root in the header of the block - return the serialized witness This implementation is currently incomplete and still lacks support for the following cases which will be future work: - witness for keys not in the current state trie (often resulting in wrong witness trie root) - edge cases where extension, account and storage are fused into one cell in the grid (needs "de-fusing" into multiple expanded trie nodes) - unit tests The code currently works correctly in 85% of the blocks of a small test chain of 161 blocks, for the unsupported cases mentioned above the RPC method will throw a root hash mismatch error. I am proposing to merge the current PR even though the implementation is incomplete, so that we can incrementally add these features, and to avoid arduous merges or rebasing with main. --------- Co-authored-by: antonis19 --- cmd/state/commands/opcode_tracer.go | 2 +- core/blockchain.go | 22 +- core/chain_makers.go | 2 +- core/state/stateless.go | 366 +++++++ core/state/triedb_state.go | 920 ++++++++++++++++++ docs/programmers_guide/witness_formal_spec.md | 598 ++++++++++++ docs/programmers_guide/witness_format.md | 96 ++ erigon-lib/commitment/commitment.go | 2 +- erigon-lib/commitment/hex_patricia_hashed.go | 589 ++++++++++- .../hex_patricia_hashed_bench_test.go | 2 +- .../hex_patricia_hashed_fuzz_test.go | 10 +- .../commitment/hex_patricia_hashed_test.go | 46 +- erigon-lib/go.mod | 1 + erigon-lib/go.sum | 2 + erigon-lib/kv/dbutils/composite_keys.go | 113 +++ erigon-lib/kv/tables.go | 5 +- erigon-lib/state/domain.go | 3 +- erigon-lib/state/domain_shared.go | 4 + erigon-lib/trie/debug.go | 107 +- erigon-lib/trie/hack.go | 46 +- erigon-lib/trie/hashbuilder.go | 45 +- erigon-lib/trie/hasher.go | 59 +- erigon-lib/trie/hasher_test.go | 2 +- erigon-lib/trie/node.go | 128 +-- erigon-lib/trie/proof.go | 52 +- erigon-lib/trie/retain_list.go | 67 +- erigon-lib/trie/retain_list_builder.go | 101 ++ erigon-lib/trie/retain_list_test.go | 4 +- erigon-lib/trie/stream.go | 58 +- erigon-lib/trie/structural_test.go | 4 +- erigon-lib/trie/sub_trie_loader.go | 2 +- erigon-lib/trie/trie.go | 553 +++++++---- erigon-lib/trie/trie_from_witness.go | 95 ++ erigon-lib/trie/trie_root.go | 4 +- erigon-lib/trie/trie_test.go | 98 +- erigon-lib/trie/trie_witness.go | 55 ++ erigon-lib/trie/witness.go | 238 +++++ erigon-lib/trie/witness_builder.go | 287 ++++++ erigon-lib/trie/witness_builder_test.go | 80 ++ erigon-lib/trie/witness_marshalling.go | 224 +++++ erigon-lib/trie/witness_operators.go | 283 ++++++ erigon-lib/trie/witness_operators_test.go | 263 +++++ erigon-lib/trie/witness_stats.go | 41 + erigon-lib/trie/witness_test.go | 96 ++ erigon-lib/types/accounts/account.go | 7 + erigon-lib/types/witness/types.go | 16 + eth/stagedsync/stage_witness.go | 146 +++ eth/stagedsync/witness_util.go | 247 +++++ turbo/jsonrpc/eth_call.go | 221 +++++ turbo/jsonrpc/trace_filtering.go | 2 +- 50 files changed, 5926 insertions(+), 488 deletions(-) create mode 100644 core/state/stateless.go create mode 100644 core/state/triedb_state.go create mode 100644 docs/programmers_guide/witness_formal_spec.md create mode 100644 docs/programmers_guide/witness_format.md create mode 100644 erigon-lib/trie/retain_list_builder.go create mode 100644 erigon-lib/trie/trie_from_witness.go create mode 100644 erigon-lib/trie/trie_witness.go create mode 100644 erigon-lib/trie/witness.go create mode 100644 erigon-lib/trie/witness_builder.go create mode 100644 erigon-lib/trie/witness_builder_test.go create mode 100644 erigon-lib/trie/witness_marshalling.go create mode 100644 erigon-lib/trie/witness_operators.go create mode 100644 erigon-lib/trie/witness_operators_test.go create mode 100644 erigon-lib/trie/witness_stats.go create mode 100644 erigon-lib/trie/witness_test.go create mode 100644 erigon-lib/types/witness/types.go create mode 100644 eth/stagedsync/stage_witness.go create mode 100644 eth/stagedsync/witness_util.go diff --git a/cmd/state/commands/opcode_tracer.go b/cmd/state/commands/opcode_tracer.go index 1a82ee5a17c..c5f6887e853 100644 --- a/cmd/state/commands/opcode_tracer.go +++ b/cmd/state/commands/opcode_tracer.go @@ -725,7 +725,7 @@ func runBlock(engine consensus.Engine, ibs *state.IntraBlockState, txnWriter sta usedGas := new(uint64) usedBlobGas := new(uint64) var receipts types.Receipts - core.InitializeBlockExecution(engine, nil, header, chainConfig, ibs, logger, nil) + core.InitializeBlockExecution(engine, nil, header, chainConfig, ibs, nil, logger, nil) rules := chainConfig.Rules(block.NumberU64(), block.Time()) for i, txn := range block.Transactions() { ibs.SetTxContext(i) diff --git a/core/blockchain.go b/core/blockchain.go index 8d86276b636..d34605b3104 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -103,14 +103,14 @@ func ExecuteBlockEphemerally( gp.AddGas(block.GasLimit()).AddBlobGas(chainConfig.GetMaxBlobGasPerBlock()) // TODO: send the new tracer once we switch to the tracing.Hook - if err := InitializeBlockExecution(engine, chainReader, block.Header(), chainConfig, ibs, logger, nil); err != nil { + if err := InitializeBlockExecution(engine, chainReader, block.Header(), chainConfig, ibs, stateWriter, logger, nil); err != nil { return nil, err } var rejectedTxs []*RejectedTx includedTxs := make(types.Transactions, 0, block.Transactions().Len()) receipts := make(types.Receipts, 0, block.Transactions().Len()) - noop := state.NewNoopWriter() + // noop := state.NewNoopWriter() for i, txn := range block.Transactions() { ibs.SetTxContext(i) writeTrace := false @@ -122,7 +122,7 @@ func ExecuteBlockEphemerally( vmConfig.Tracer = tracer writeTrace = true } - receipt, _, err := ApplyTransaction(chainConfig, blockHashFunc, engine, nil, gp, ibs, noop, header, txn, usedGas, usedBlobGas, *vmConfig) + receipt, _, err := ApplyTransaction(chainConfig, blockHashFunc, engine, nil, gp, ibs, stateWriter, header, txn, usedGas, usedBlobGas, *vmConfig) if writeTrace { if ftracer, ok := vmConfig.Tracer.(vm.FlushableTracer); ok { ftracer.Flush(txn) @@ -167,15 +167,19 @@ func ExecuteBlockEphemerally( return nil, fmt.Errorf("bloom computed by execution: %x, in header: %x", bloom, header.Bloom) } } - + var newBlock *types.Block + var err error if !vmConfig.ReadOnly { txs := block.Transactions() - if _, _, _, _, err := FinalizeBlockExecution(engine, stateReader, block.Header(), txs, block.Uncles(), stateWriter, chainConfig, ibs, receipts, block.Withdrawals(), chainReader, false, logger); err != nil { + newBlock, _, _, _, err = FinalizeBlockExecution(engine, stateReader, block.Header(), txs, block.Uncles(), stateWriter, chainConfig, ibs, receipts, block.Withdrawals(), chainReader, true, logger) + if err != nil { return nil, err } } blockLogs := ibs.Logs() + newRoot := newBlock.Root() execRs := &EphemeralExecResult{ + StateRoot: newRoot, TxRoot: types.DeriveSha(includedTxs), ReceiptRoot: receiptSha, Bloom: bloom, @@ -353,13 +357,15 @@ func FinalizeBlockExecution( } func InitializeBlockExecution(engine consensus.Engine, chain consensus.ChainHeaderReader, header *types.Header, - cc *chain.Config, ibs *state.IntraBlockState, logger log.Logger, tracer *tracing.Hooks, + cc *chain.Config, ibs *state.IntraBlockState, stateWriter state.StateWriter, logger log.Logger, tracer *tracing.Hooks, ) error { engine.Initialize(cc, chain, header, ibs, func(contract libcommon.Address, data []byte, ibState *state.IntraBlockState, header *types.Header, constCall bool) ([]byte, error) { return SysCallContract(contract, data, cc, ibState, header, engine, constCall) }, logger, tracer) - noop := state.NewNoopWriter() - ibs.FinalizeTx(cc.Rules(header.Number.Uint64(), header.Time), noop) + if stateWriter == nil { + stateWriter = state.NewNoopWriter() + } + ibs.FinalizeTx(cc.Rules(header.Number.Uint64(), header.Time), stateWriter) return nil } diff --git a/core/chain_makers.go b/core/chain_makers.go index 9c1d9aba3a7..778ba06009f 100644 --- a/core/chain_makers.go +++ b/core/chain_makers.go @@ -366,7 +366,7 @@ func GenerateChain(config *chain.Config, parent *types.Block, engine consensus.E } } if b.engine != nil { - err := InitializeBlockExecution(b.engine, nil, b.header, config, ibs, logger, nil) + err := InitializeBlockExecution(b.engine, nil, b.header, config, ibs, nil, logger, nil) if err != nil { return nil, nil, fmt.Errorf("call to InitializeBlockExecution: %w", err) } diff --git a/core/state/stateless.go b/core/state/stateless.go new file mode 100644 index 00000000000..81c43cf423a --- /dev/null +++ b/core/state/stateless.go @@ -0,0 +1,366 @@ +// Copyright 2019 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package state + +import ( + "fmt" + "os" + + "github.com/holiman/uint256" + + "github.com/erigontech/erigon-lib/common" + "github.com/erigontech/erigon-lib/kv/dbutils" + "github.com/erigontech/erigon-lib/trie" + "github.com/erigontech/erigon-lib/types/accounts" +) + +var ( + _ StateReader = (*Stateless)(nil) + _ StateWriter = (*Stateless)(nil) +) + +// Stateless is the inter-block cache for stateless client prototype, iteration 2 +// It creates the initial state trie during the construction, and then updates it +// during the execution of block(s) +type Stateless struct { + t *trie.Trie // State trie + codeUpdates map[common.Hash][]byte // Lookup index from code hashes to corresponding bytecode + blockNr uint64 // Current block number + storageUpdates map[common.Hash]map[common.Hash][]byte + accountUpdates map[common.Hash]*accounts.Account + deleted map[common.Hash]struct{} + created map[common.Hash]struct{} + trace bool +} + +// NewStateless creates a new instance of Stateless +// It deserialises the block witness and creates the state trie out of it, checking that the root of the constructed +// state trie matches the value of `stateRoot` parameter +func NewStateless(stateRoot common.Hash, blockWitness *trie.Witness, blockNr uint64, trace bool, isBinary bool) (*Stateless, error) { + t, err := trie.BuildTrieFromWitness(blockWitness, trace) + if err != nil { + return nil, err + } + + if !isBinary { + if t.Hash() != stateRoot { + filename := fmt.Sprintf("root_%d.txt", blockNr) + f, err := os.Create(filename) + if err == nil { + defer f.Close() + t.Print(f) + } + return nil, fmt.Errorf("state root mistmatch when creating Stateless2, got %x, expected %x", t.Hash(), stateRoot) + } + } + return &Stateless{ + t: t, + codeUpdates: make(map[common.Hash][]byte), + storageUpdates: make(map[common.Hash]map[common.Hash][]byte), + accountUpdates: make(map[common.Hash]*accounts.Account), + deleted: make(map[common.Hash]struct{}), + created: make(map[common.Hash]struct{}), + blockNr: blockNr, + trace: trace, + }, nil +} + +// SetBlockNr changes the block number associated with this +func (s *Stateless) SetBlockNr(blockNr uint64) { + s.blockNr = blockNr +} + +func (s *Stateless) SetStrictHash(strict bool) { + s.t.SetStrictHash(strict) +} + +func (s *Stateless) ReadAccountDataForDebug(address common.Address) (*accounts.Account, error) { + return s.ReadAccountData(address) +} + +// ReadAccountData is a part of the StateReader interface +// This implementation attempts to look up account data in the state trie, and fails if it is not found +func (s *Stateless) ReadAccountData(address common.Address) (*accounts.Account, error) { + addrHash, err := common.HashData(address[:]) + if err != nil { + return nil, err + } + acc, ok := s.t.GetAccount(addrHash[:]) + if s.trace { + fmt.Printf("Stateless: ReadAccountData(address=%x) --> %v\n", address.Bytes(), acc) + } + if ok { + return acc, nil + } + return nil, nil +} + +// ReadAccountStorage is a part of the StateReader interface +// This implementation attempts to look up the storage in the state trie, and fails if it is not found +func (s *Stateless) ReadAccountStorage(address common.Address, incarnation uint64, key *common.Hash) ([]byte, error) { + if s.trace { + fmt.Printf("Stateless: ReadAccountStorage(address=%x, incarnation=%d, key=%x)\n", address.Bytes(), incarnation, key.Bytes()) + } + seckey, err := common.HashData(key[:]) + if err != nil { + return nil, err + } + + addrHash, err := common.HashData(address[:]) + if err != nil { + return nil, err + } + + if enc, ok := s.t.Get(dbutils.GenerateCompositeTrieKey(addrHash, seckey)); ok { + return enc, nil + } + + return nil, nil +} + +// ReadAccountCode is a part of the StateReader interface +func (s *Stateless) ReadAccountCode(address common.Address, incarnation uint64) (code []byte, err error) { + if s.trace { + fmt.Printf("Getting code for address %x\n", address) + } + + addrHash, err := common.HashData(address[:]) + if err != nil { + return nil, err + } + + if code, ok := s.codeUpdates[addrHash]; ok { + return code, nil + } + + if code, ok := s.t.GetAccountCode(addrHash[:]); ok { + return code, nil + } + return nil, nil +} + +// ReadAccountCodeSize is a part of the StateReader interface +// This implementation looks the code up in the codeMap, and returns its size +// It fails if the code is not found in the map +func (s *Stateless) ReadAccountCodeSize(address common.Address, incarnation uint64) (codeSize int, err error) { + addrHash, err := common.HashData(address[:]) + if err != nil { + return 0, err + } + + if code, ok := s.codeUpdates[addrHash]; ok { + return len(code), nil + } + + if code, ok := s.t.GetAccountCode(addrHash[:]); ok { + return len(code), nil + } + + if codeSize, ok := s.t.GetAccountCodeSize(addrHash[:]); ok { + return codeSize, nil + } + + return 0, nil +} + +func (s *Stateless) ReadAccountIncarnation(address common.Address) (uint64, error) { + return 0, nil +} + +// UpdateAccountData is a part of the StateWriter interface +// This implementation registers the account update in the `accountUpdates` map +func (s *Stateless) UpdateAccountData(address common.Address, original, account *accounts.Account) error { + addrHash, err := common.HashData(address[:]) + if err != nil { + return err + } + if s.trace { + fmt.Printf("Stateless: UpdateAccountData for address %x, addrHash %x\n", address, addrHash) + } + s.accountUpdates[addrHash] = account + return nil +} + +// DeleteAccount is a part of the StateWriter interface +// This implementation registers the deletion of the account in two internal maps +func (s *Stateless) DeleteAccount(address common.Address, original *accounts.Account) error { + addrHash, err := common.HashData(address[:]) + if err != nil { + return err + } + s.accountUpdates[addrHash] = nil + s.deleted[addrHash] = struct{}{} + if s.trace { + fmt.Printf("Stateless: DeleteAccount %x hash %x\n", address, addrHash) + } + return nil +} + +// UpdateAccountCode is a part of the StateWriter interface +// This implementation adds the code to the codeMap to make it available for further accesses +func (s *Stateless) UpdateAccountCode(address common.Address, incarnation uint64, codeHash common.Hash, code []byte) error { + s.codeUpdates[codeHash] = code + + if s.trace { + fmt.Printf("Stateless: UpdateAccountCode %x codeHash %x\n", address, codeHash) + } + return nil +} + +// WriteAccountStorage is a part of the StateWriter interface +// This implementation registeres the change of the account's storage in the internal double map `storageUpdates` +func (s *Stateless) WriteAccountStorage(address common.Address, incarnation uint64, key *common.Hash, original, value *uint256.Int) error { + addrHash, err := common.HashData(address[:]) + if err != nil { + return err + } + + v := value.Bytes() + m, ok := s.storageUpdates[addrHash] + if !ok { + m = make(map[common.Hash][]byte) + s.storageUpdates[addrHash] = m + } + seckey, err := common.HashData(key[:]) + if err != nil { + return err + } + if len(v) > 0 { + m[seckey] = v + } else { + m[seckey] = nil + } + if s.trace { + fmt.Printf("Stateless: WriteAccountStorage %x key %x val %x\n", address, *key, *value) + } + return nil +} + +// CreateContract is a part of StateWriter interface +// This implementation registers given address in the internal map `created` +func (s *Stateless) CreateContract(address common.Address) error { + addrHash, err := common.HashData(address[:]) + if err != nil { + return err + } + if s.trace { + fmt.Printf("Stateless: CreateContract %x hash %x\n", address, addrHash) + } + s.created[addrHash] = struct{}{} + return nil +} + +func (s *Stateless) WriteChangeSets() error { return nil } + +func (s *Stateless) WriteHistory() error { return nil } + +// CheckRoot finalises the execution of a block and computes the resulting state root +func (s *Stateless) CheckRoot(expected common.Hash) error { + h := s.Finalize() + fmt.Printf("trie root after stateless exec : %x , expected trie root: %x\n", h, expected) + if h != expected { + filename := fmt.Sprintf("root_%d.txt", s.blockNr) + f, err := os.Create(filename) + if err == nil { + defer f.Close() + s.t.Print(f) + } + return fmt.Errorf("final root: %x, expected: %x", h, expected) + } + + return nil +} + +// Finalize the execution of a block and computes the resulting state root +func (s *Stateless) Finalize() common.Hash { + // The following map is to prevent repeated clearouts of the storage + alreadyCreated := make(map[common.Hash]struct{}) + // New contracts are being created at these addresses. Therefore, we need to clear the storage items + // that might be remaining in the trie and figure out the next incarnations + for addrHash := range s.created { + // Prevent repeated storage clearouts + if _, ok := alreadyCreated[addrHash]; ok { + continue + } + alreadyCreated[addrHash] = struct{}{} + if account, ok := s.accountUpdates[addrHash]; ok && account != nil { + account.Root = trie.EmptyRoot + } + // The only difference between Delete and DeleteSubtree is that Delete would delete accountNode too, + // wherewas DeleteSubtree will keep the accountNode, but will make the storage sub-trie empty + s.t.DeleteSubtree(addrHash[:]) + } + for addrHash, account := range s.accountUpdates { + if account != nil { + s.t.UpdateAccount(addrHash[:], account) + } else { + s.t.Delete(addrHash[:]) + } + } + for addrHash, m := range s.storageUpdates { + if _, ok := s.deleted[addrHash]; ok { + // Deleted contracts will be dealth with later, in the next loop + continue + } + + for keyHash, v := range m { + cKey := dbutils.GenerateCompositeTrieKey(addrHash, keyHash) + if len(v) > 0 { + s.t.Update(cKey, v) + } else { + s.t.Delete(cKey) + } + } + if account, ok := s.accountUpdates[addrHash]; ok && account != nil { + ok, root := s.t.DeepHash(addrHash[:]) + if ok { + account.Root = root + } else { + account.Root = trie.EmptyRoot + } + } + } + // For the contracts that got deleted + for addrHash := range s.deleted { + if _, ok := s.created[addrHash]; ok { + // In some rather artificial circumstances, an account can be recreated after having been self-destructed + // in the same block. It can only happen when contract is introduced in the genesis state with nonce 0 + // rather than created by a transaction (in that case, its starting nonce is 1). The self-destructed + // contract actually gets removed from the state only at the end of the block, so if its nonce is not 0, + // it will prevent any re-creation within the same block. However, if the contract is introduced in + // the genesis state, its nonce is 0, and that means it can be self-destructed, and then re-created, + // all in the same block. In such cases, we must preserve storage modifications happening after the + // self-destruction + continue + } + if account, ok := s.accountUpdates[addrHash]; ok && account != nil { + account.Root = trie.EmptyRoot + } + s.t.DeleteSubtree(addrHash[:]) + } + + s.storageUpdates = make(map[common.Hash]map[common.Hash][]byte) + s.accountUpdates = make(map[common.Hash]*accounts.Account) + s.deleted = make(map[common.Hash]struct{}) + s.created = make(map[common.Hash]struct{}) + + return s.t.Hash() +} + +func (s *Stateless) GetTrie() *trie.Trie { + return s.t +} diff --git a/core/state/triedb_state.go b/core/state/triedb_state.go new file mode 100644 index 00000000000..6148ffeedd8 --- /dev/null +++ b/core/state/triedb_state.go @@ -0,0 +1,920 @@ +package state + +import ( + "bytes" + "encoding/binary" + "io" + "sort" + "sync" + "sync/atomic" + + "github.com/erigontech/erigon-lib/common" + libcommon "github.com/erigontech/erigon-lib/common" + "github.com/erigontech/erigon-lib/common/length" + "github.com/erigontech/erigon-lib/crypto" + "github.com/erigontech/erigon-lib/kv/dbutils" + "github.com/erigontech/erigon-lib/trie" + "github.com/erigontech/erigon-lib/types/accounts" + witnesstypes "github.com/erigontech/erigon-lib/types/witness" + "github.com/holiman/uint256" +) + +// Buffer is a structure holding updates, deletes, and reads registered within one change period +// A change period can be transaction within a block, or a block within group of blocks +type Buffer struct { + codeReads map[libcommon.Hash]witnesstypes.CodeWithHash + codeSizeReads map[libcommon.Hash]libcommon.Hash + codeUpdates map[libcommon.Hash][]byte + // storageUpdates structure collects the effects of the block (or transaction) execution. It does not necessarily + // include all the intermediate reads and write that happened. For example, if the storage of some contract has + // been modified, and then the contract has subsequently self-destructed, this structure will not contain any + // keys related to the storage of this contract, because they are irrelevant for the final state + storageUpdates map[libcommon.Hash]map[libcommon.Hash][]byte + storageIncarnation map[libcommon.Hash]uint64 + // storageReads structure collects all the keys of items that have been modified (or also just read, if the + // tds.resolveReads flag is turned on, which happens during the generation of block witnesses). + // Even if the final results of the execution do not include some items, they will still be present in this structure. + // For example, if the storage of some contract has been modified, and then the contract has subsequently self-destructed, + // this structure will contain all the keys that have been modified or deleted prior to the self-destruction. + // It is important to keep them because they will be used to apply changes to the trie one after another. + // There is a potential for optimisation - we may actually skip all the intermediate modification of the trie if + // we know that in the end, the entire storage will be dropped. However, this optimisation has not yet been + // implemented. + storageReads map[common.StorageKey][]byte + // accountUpdates structure collects the effects of the block (or transaxction) execution. + accountUpdates map[libcommon.Hash]witnesstypes.AccountWithAddress + // accountReads structure collects all the address hashes of the accounts that have been modified (or also just read, + // if tds.resolveReads flag is turned on, which happens during the generation of block witnesses). + accountReads map[libcommon.Hash]libcommon.Address + accountReadsIncarnation map[libcommon.Hash]uint64 + deleted map[libcommon.Hash]libcommon.Address + created map[libcommon.Hash]libcommon.Address +} + +// Prepares buffer for work or clears previous data +func (b *Buffer) initialise() { + b.codeReads = make(map[libcommon.Hash]witnesstypes.CodeWithHash) + b.codeSizeReads = make(map[libcommon.Hash]libcommon.Hash) + b.codeUpdates = make(map[libcommon.Hash][]byte) + b.storageUpdates = make(map[libcommon.Hash]map[libcommon.Hash][]byte) + b.storageIncarnation = make(map[libcommon.Hash]uint64) + b.storageReads = make(map[common.StorageKey][]byte) + b.accountUpdates = make(map[libcommon.Hash]witnesstypes.AccountWithAddress) + b.accountReads = make(map[libcommon.Hash]libcommon.Address) + b.accountReadsIncarnation = make(map[libcommon.Hash]uint64) + b.deleted = make(map[libcommon.Hash]libcommon.Address) + b.created = make(map[libcommon.Hash]libcommon.Address) +} + +// Replaces account pointer with pointers to the copies +func (b *Buffer) detachAccounts() { + for addrHash, accountWithAddress := range b.accountUpdates { + address := accountWithAddress.Address + account := accountWithAddress.Account + if account != nil { + b.accountUpdates[addrHash] = witnesstypes.AccountWithAddress{Address: address, Account: account.SelfCopy()} + } + } +} + +// Merges the content of another buffer into this one +func (b *Buffer) merge(other *Buffer) { + for addrHash, codeWithHash := range other.codeReads { + b.codeReads[addrHash] = codeWithHash + } + + for addrHash, code := range other.codeUpdates { + b.codeUpdates[addrHash] = code + } + + for address, codeHash := range other.codeSizeReads { + b.codeSizeReads[address] = codeHash + } + + for addrHash := range other.deleted { + b.deleted[addrHash] = other.deleted[addrHash] + delete(b.storageUpdates, addrHash) + delete(b.storageIncarnation, addrHash) + delete(b.codeUpdates, addrHash) + } + for addrHash := range other.created { + b.created[addrHash] = other.created[addrHash] + delete(b.storageUpdates, addrHash) + delete(b.storageIncarnation, addrHash) + } + for addrHash, om := range other.storageUpdates { + m, ok := b.storageUpdates[addrHash] + if !ok { + m = make(map[libcommon.Hash][]byte) + b.storageUpdates[addrHash] = m + } + for keyHash, v := range om { + m[keyHash] = v + } + } + for addrHash, incarnation := range other.storageIncarnation { + b.storageIncarnation[addrHash] = incarnation + } + for storageKey := range other.storageReads { + b.storageReads[storageKey] = other.storageReads[storageKey] + } + for addrHash, accountAddr := range other.accountUpdates { + b.accountUpdates[addrHash] = accountAddr + } + for addrHash := range other.accountReads { + b.accountReads[addrHash] = other.accountReads[addrHash] + } + for addrHash, incarnation := range other.accountReadsIncarnation { + b.accountReadsIncarnation[addrHash] = incarnation + } +} + +// TrieDbState implements StateReader by wrapping a trie and a database, where trie acts as a cache for the database +type TrieDbState struct { + t *trie.Trie + tMu *sync.Mutex + StateReader StateReader + rl *trie.RetainList + blockNr uint64 + buffers []*Buffer + aggregateBuffer *Buffer // Merge of all buffers + currentBuffer *Buffer + resolveReads bool + retainListBuilder *trie.RetainListBuilder + hashBuilder *trie.HashBuilder + incarnationMap map[libcommon.Address]uint64 // Temporary map of incarnation for the cases when contracts are deleted and recreated within 1 block +} + +func NewTrieDbState(root libcommon.Hash, blockNr uint64, stateReader StateReader) *TrieDbState { + t := trie.New(root) + tds := &TrieDbState{ + t: t, + tMu: new(sync.Mutex), + StateReader: stateReader, + blockNr: blockNr, + retainListBuilder: trie.NewRetainListBuilder(), + hashBuilder: trie.NewHashBuilder(false), + incarnationMap: make(map[libcommon.Address]uint64), + } + return tds +} + +func (tds *TrieDbState) SetRetainList(rl *trie.RetainList) { + tds.rl = rl +} + +func (tds *TrieDbState) SetTrie(tr *trie.Trie) { + tds.t = tr +} + +func (tds *TrieDbState) SetResolveReads(rr bool) { + tds.resolveReads = rr +} + +func (tds *TrieDbState) Copy() *TrieDbState { + tds.tMu.Lock() + tcopy := *tds.t + tds.tMu.Unlock() + + n := tds.getBlockNr() + cpy := TrieDbState{ + t: &tcopy, + tMu: new(sync.Mutex), + blockNr: n, + hashBuilder: trie.NewHashBuilder(false), + incarnationMap: make(map[libcommon.Address]uint64), + } + return &cpy +} + +func (tds *TrieDbState) Trie() *trie.Trie { + return tds.t +} + +func (tds *TrieDbState) StartNewBuffer() { + if tds.currentBuffer != nil { + if tds.aggregateBuffer == nil { + tds.aggregateBuffer = &Buffer{} + tds.aggregateBuffer.initialise() + } + tds.aggregateBuffer.merge(tds.currentBuffer) + tds.currentBuffer.detachAccounts() + } + tds.currentBuffer = &Buffer{} + tds.currentBuffer.initialise() + tds.buffers = append(tds.buffers, tds.currentBuffer) +} + +func (tds *TrieDbState) WithNewBuffer() *TrieDbState { + aggregateBuffer := &Buffer{} + aggregateBuffer.initialise() + + currentBuffer := &Buffer{} + currentBuffer.initialise() + + buffers := []*Buffer{currentBuffer} + + tds.tMu.Lock() + t := &TrieDbState{ + t: tds.t, + tMu: tds.tMu, + blockNr: tds.getBlockNr(), + buffers: buffers, + aggregateBuffer: aggregateBuffer, + currentBuffer: currentBuffer, + resolveReads: tds.resolveReads, + retainListBuilder: tds.retainListBuilder, + hashBuilder: trie.NewHashBuilder(false), + incarnationMap: make(map[libcommon.Address]uint64), + } + tds.tMu.Unlock() + + return t +} + +func (tds *TrieDbState) WithLastBuffer() *TrieDbState { + tds.tMu.Lock() + aggregateBuffer := &Buffer{} + aggregateBuffer.initialise() + currentBuffer := tds.currentBuffer + buffers := []*Buffer{currentBuffer} + tds.tMu.Unlock() + + return &TrieDbState{ + t: tds.t, + tMu: tds.tMu, + blockNr: tds.getBlockNr(), + buffers: buffers, + aggregateBuffer: aggregateBuffer, + currentBuffer: currentBuffer, + resolveReads: tds.resolveReads, + retainListBuilder: tds.retainListBuilder.Copy(), + hashBuilder: trie.NewHashBuilder(false), + incarnationMap: make(map[libcommon.Address]uint64), + } +} + +func (tds *TrieDbState) LastRoot() libcommon.Hash { + if tds == nil || tds.tMu == nil { + return libcommon.Hash{} + } + tds.tMu.Lock() + defer tds.tMu.Unlock() + return tds.t.Hash() +} + +// UpdateStateTrie assumes that the state trie is already fully resolved, i.e. any operations +// will find necessary data inside the trie. +func (tds *TrieDbState) UpdateStateTrie() ([]libcommon.Hash, error) { + tds.tMu.Lock() + defer tds.tMu.Unlock() + + roots, err := tds.updateTrieRoots(true) + tds.ClearUpdates() + return roots, err +} + +func (tds *TrieDbState) PrintTrie(w io.Writer) { + tds.tMu.Lock() + defer tds.tMu.Unlock() + tds.t.Print(w) +} + +func (tds *TrieDbState) buildPlainStorageReads() ([][]byte, [][]byte) { + storagePlainKeys := make([][]byte, 0, len(tds.aggregateBuffer.storageReads)) + storageHashedKeys := make([][]byte, 0, len(tds.aggregateBuffer.storageReads)) + + for storageHashedKey, storagePlainKey := range tds.aggregateBuffer.storageReads { + // to prevent variable capture in Go 1.21 + storagePlainKeyCopy := make([]byte, len(storagePlainKey)) + copy(storagePlainKeyCopy, storagePlainKey) + storageHashedKeyCopy := make([]byte, len(storageHashedKey)) + copy(storageHashedKeyCopy, storageHashedKey[:]) + storagePlainKeys = append(storagePlainKeys, storagePlainKeyCopy) + storageHashedKeys = append(storageHashedKeys, storageHashedKeyCopy) + } + + // Create a slice of indices to track original positions + indices := make([]int, len(storagePlainKeys)) + for i := range indices { + indices[i] = i + } + + // Sort indices based on accountAddresses + sort.SliceStable(indices, func(i, j int) bool { + return bytes.Compare(storagePlainKeys[indices[i]], storagePlainKeys[indices[j]]) < 0 + }) + + // Apply the sorted order to accountAddresses and accountAddressHashes + sortedStoragePlainKeys := make([][]byte, len(storagePlainKeys)) + sortedStorageHashedKeys := make([][]byte, len(storageHashedKeys)) + for i, idx := range indices { + sortedStoragePlainKeys[i] = storagePlainKeys[idx] + sortedStorageHashedKeys[i] = storageHashedKeys[idx] + } + return sortedStorageHashedKeys, sortedStoragePlainKeys +} + +// BuildStorageReads builds a sorted list of all storage key hashes that were modified +// (or also just read, if tds.resolveReads flag is turned on) within the +// period for which we are aggregating updates. It includes the keys of items that +// were nullified by subsequent updates - best example is the +// self-destruction of a contract, which nullifies all previous +// modifications of the contract's storage. In such case, all previously modified storage +// item updates would be inclided. +func (tds *TrieDbState) BuildStorageReads() common.StorageKeys { + storageTouches := common.StorageKeys{} + for storageKey := range tds.aggregateBuffer.storageReads { + storageTouches = append(storageTouches, storageKey) + } + sort.Sort(storageTouches) + return storageTouches +} + +// buildStorageWrites builds a sorted list of all storage key hashes that were modified within the +// period for which we are aggregating updates. It skips the updates that +// were nullified by subsequent updates - best example is the +// self-destruction of a contract, which nullifies all previous +// modifications of the contract's storage. In such case, no storage +// item updates would be inclided. +func (tds *TrieDbState) buildStorageWrites() (common.StorageKeys, [][]byte) { + storageTouches := common.StorageKeys{} + for addrHash, m := range tds.aggregateBuffer.storageUpdates { + for keyHash := range m { + var storageKey common.StorageKey + copy(storageKey[:], addrHash[:]) + binary.BigEndian.PutUint64(storageKey[length.Hash:], tds.aggregateBuffer.storageIncarnation[addrHash]) + copy(storageKey[length.Hash+length.Incarnation:], keyHash[:]) + storageTouches = append(storageTouches, storageKey) + } + } + sort.Sort(storageTouches) + var addrHash libcommon.Hash + var keyHash libcommon.Hash + var values = make([][]byte, len(storageTouches)) + for i, storageKey := range storageTouches { + copy(addrHash[:], storageKey[:]) + copy(keyHash[:], storageKey[length.Hash+length.Incarnation:]) + values[i] = tds.aggregateBuffer.storageUpdates[addrHash][keyHash] + } + return storageTouches, values +} + +// Populate pending block proof so that it will be sufficient for accessing all storage slots in storageTouches +func (tds *TrieDbState) PopulateStorageBlockProof(storageTouches common.StorageKeys) error { //nolint + for _, storageKey := range storageTouches { + addr, _, hash := dbutils.ParseCompositeStorageKey(storageKey[:]) + key := dbutils.GenerateCompositeTrieKey(addr, hash) + tds.retainListBuilder.AddStorageTouch(key) + } + return nil +} + +func (tds *TrieDbState) BuildCodeTouches() map[libcommon.Hash]witnesstypes.CodeWithHash { + return tds.aggregateBuffer.codeReads +} + +func (tds *TrieDbState) buildCodeSizeTouches() map[libcommon.Hash]libcommon.Hash { + return tds.aggregateBuffer.codeSizeReads +} + +// BuildAccountReads builds a sorted list of all address hashes that were modified +// (or also just read, if tds.resolveReads flags is turned one) within the +// period for which we are aggregating update +func (tds *TrieDbState) BuildAccountReads() common.Hashes { + accountTouches := common.Hashes{} + for addrHash := range tds.aggregateBuffer.accountReads { + accountTouches = append(accountTouches, addrHash) + } + sort.Sort(accountTouches) + return accountTouches +} + +func (tds *TrieDbState) buildAccountAddressReads() ([][]byte, [][]byte) { + accountAddressHashes := make([][]byte, 0, len(tds.aggregateBuffer.accountReads)) + accountAddresses := make([][]byte, 0, len(tds.aggregateBuffer.accountReads)) + for addrHash, address := range tds.aggregateBuffer.accountReads { + computedAddrHash := crypto.Keccak256(address.Bytes()) + if !bytes.Equal(addrHash[:], computedAddrHash) { + panic("could not reproduce addrHash found in the map") + } + accountAddresses = append(accountAddresses, address.Bytes()) + accountAddressHashes = append(accountAddressHashes, addrHash.Bytes()) + } + + // Create a slice of indices to track original positions + indices := make([]int, len(accountAddresses)) + for i := range indices { + indices[i] = i + } + + // Sort indices based on accountAddresses + sort.SliceStable(indices, func(i, j int) bool { + return bytes.Compare(accountAddresses[indices[i]], accountAddresses[indices[j]]) < 0 + }) + + // Apply the sorted order to accountAddresses and accountAddressHashes + sortedAccountAddresses := make([][]byte, len(accountAddresses)) + sortedAccountAddressHashes := make([][]byte, len(accountAddressHashes)) + for i, idx := range indices { + sortedAccountAddresses[i] = accountAddresses[idx] + sortedAccountAddressHashes[i] = accountAddressHashes[idx] + } + + // Check if sorting is correct + for i := 0; i < len(sortedAccountAddresses); i++ { + addrHash := sortedAccountAddressHashes[i] + accountAddress := sortedAccountAddresses[i] + computedHash := crypto.Keccak256(accountAddress) + if !bytes.Equal(addrHash, computedHash) { + panic("sorting is not correct, this should not happen") + } + } + + return sortedAccountAddressHashes, sortedAccountAddresses +} + +// buildAccountWrites builds a sorted list of all address hashes that were modified within the +// period for which we are aggregating updates. +func (tds *TrieDbState) buildAccountWrites() (common.Hashes, []*accounts.Account, [][]byte) { + accountTouches := common.Hashes{} + for addrHash := range tds.aggregateBuffer.accountUpdates { + if _, ok := tds.aggregateBuffer.deleted[addrHash]; ok { + // This adds an extra entry that wipes out the storage of the accout in the stream + accountTouches = append(accountTouches, addrHash) + } else if _, ok1 := tds.aggregateBuffer.created[addrHash]; ok1 { + // This adds an extra entry that wipes out the storage of the accout in the stream + accountTouches = append(accountTouches, addrHash) + } + accountTouches = append(accountTouches, addrHash) + } + sort.Sort(accountTouches) + aValues := make([]*accounts.Account, len(accountTouches)) + aCodes := make([][]byte, len(accountTouches)) + for i, addrHash := range accountTouches { + if i < len(accountTouches)-1 && addrHash == accountTouches[i+1] { + aValues[i] = nil // Entry that would wipe out existing storage + } else { + a := tds.aggregateBuffer.accountUpdates[addrHash] + if a.Account != nil { + if _, ok := tds.aggregateBuffer.storageUpdates[addrHash]; ok { + var ac accounts.Account + ac.Copy(a.Account) + ac.Root = trie.EmptyRoot + a.Account = &ac + } + } + aValues[i] = a.Account + if code, ok := tds.aggregateBuffer.codeUpdates[addrHash]; ok { + aCodes[i] = code + } + } + } + return accountTouches, aValues, aCodes +} + +func (tds *TrieDbState) PopulateAccountBlockProof(accountTouches common.Hashes) { + for _, addrHash := range accountTouches { + a := addrHash + tds.retainListBuilder.AddTouch(a[:]) + } +} + +// ExtractTouches returns two lists of keys - for accounts and storage items correspondingly +// Each list is the collection of keys that have been "touched" (inserted, updated, or simply accessed) +// since the last invocation of `ExtractTouches`. +func (tds *TrieDbState) ExtractTouches() (accountTouches [][]byte, storageTouches [][]byte) { + return tds.retainListBuilder.ExtractTouches() +} + +func (tds *TrieDbState) GetRetainList() *trie.RetainList { + return tds.retainListBuilder.Build(false) +} + +// Get list of account and storage touches +// First come the account touches then the storage touches +func (tds *TrieDbState) GetTouchedPlainKeys() (plainKeys [][]byte, hashedKeys [][]byte) { + // Aggregating the current buffer, if any + if tds.currentBuffer != nil { + if tds.aggregateBuffer == nil { + tds.aggregateBuffer = &Buffer{} + tds.aggregateBuffer.initialise() + } + tds.aggregateBuffer.merge(tds.currentBuffer) + } + if tds.aggregateBuffer == nil { + return nil, nil + } + accountHashTouches, accountAddressTouches := tds.buildAccountAddressReads() + storageHashTouches, storagePlainKeyTouches := tds.buildPlainStorageReads() + plainKeys = append(accountAddressTouches, storagePlainKeyTouches...) + hashedKeys = append(accountHashTouches, storageHashTouches...) + return plainKeys, hashedKeys + +} + +func (tds *TrieDbState) ResolveBuffer() { + if tds.currentBuffer != nil { + if tds.aggregateBuffer == nil { + tds.aggregateBuffer = &Buffer{} + tds.aggregateBuffer.initialise() + } + tds.aggregateBuffer.merge(tds.currentBuffer) + } +} + +// forward is `true` if the function is used to progress the state forward (by adding blocks) +// forward is `false` if the function is used to rewind the state (for reorgs, for example) +func (tds *TrieDbState) updateTrieRoots(forward bool) ([]libcommon.Hash, error) { + // Perform actual updates on the tries, and compute one trie root per buffer + // These roots can be used to populate receipt.PostState on pre-Byzantium + roots := make([]libcommon.Hash, len(tds.buffers)) + for i, b := range tds.buffers { + // For the contracts that got deleted, we clear the storage + for addrHash := range b.deleted { + // The only difference between Delete and DeleteSubtree is that Delete would delete accountNode too, + // wherewas DeleteSubtree will keep the accountNode, but will make the storage sub-trie empty + tds.t.DeleteSubtree(addrHash[:]) + } + // New contracts are being created at these addresses. Therefore, we need to clear the storage items + // that might be remaining in the trie and figure out the next incarnations + for addrHash := range b.created { + // The only difference between Delete and DeleteSubtree is that Delete would delete accountNode too, + // wherewas DeleteSubtree will keep the accountNode, but will make the storage sub-trie empty + tds.t.DeleteSubtree(addrHash[:]) + } + + for addrHash, accountWithAddress := range b.accountUpdates { + if accountWithAddress.Account != nil { + //fmt.Println("updateTrieRoots b.accountUpdates", addrHash.String(), account.Incarnation) + tds.t.UpdateAccount(addrHash[:], accountWithAddress.Account) + } else { + tds.t.Delete(addrHash[:]) + } + } + + for addrHash, newCode := range b.codeUpdates { + if err := tds.t.UpdateAccountCode(addrHash[:], newCode); err != nil { + return nil, err + } + } + for addrHash, m := range b.storageUpdates { + for keyHash, v := range m { + cKey := dbutils.GenerateCompositeTrieKey(addrHash, keyHash) + if len(v) > 0 { + //fmt.Printf("Update storage trie addrHash %x, keyHash %x: %x\n", addrHash, keyHash, v) + if forward { + tds.t.Update(cKey, v) + } else { + // If rewinding, it might not be possible to execute storage item update. + // If we rewind from the state where a contract does not exist anymore (it was self-destructed) + // to the point where it existed (with storage), then rewinding to the point of existence + // will not bring back the full storage trie. Instead there will be one hashNode. + // So we probe for this situation first + if _, ok := tds.t.Get(cKey); ok { + tds.t.Update(cKey, v) + } + } + } else { + if forward { + tds.t.Delete(cKey) + } else { + // If rewinding, it might not be possible to execute storage item update. + // If we rewind from the state where a contract does not exist anymore (it was self-destructed) + // to the point where it existed (with storage), then rewinding to the point of existence + // will not bring back the full storage trie. Instead there will be one hashNode. + // So we probe for this situation first + if _, ok := tds.t.Get(cKey); ok { + tds.t.Delete(cKey) + } + } + } + } + + if accountWithAddress, ok := b.accountUpdates[addrHash]; ok && accountWithAddress.Account != nil { + ok, root := tds.t.DeepHash(addrHash[:]) + if ok { + accountWithAddress.Account.Root = root + //fmt.Printf("(b)Set %x root for addrHash %x\n", root, addrHash) + } else { + //fmt.Printf("(b)Set empty root for addrHash %x\n", addrHash) + accountWithAddress.Account.Root = trie.EmptyRoot + } + } + } + roots[i] = tds.t.Hash() + } + + return roots, nil +} + +func (tds *TrieDbState) ClearUpdates() { + tds.buffers = nil + tds.currentBuffer = nil + tds.aggregateBuffer = nil +} + +func (tds *TrieDbState) SetBlockNr(blockNr uint64) { + tds.setBlockNr(blockNr) +} + +func (tds *TrieDbState) GetBlockNr() uint64 { + return tds.getBlockNr() +} + +func (tds *TrieDbState) GetAccount(addrHash libcommon.Hash) (*accounts.Account, bool) { + tds.tMu.Lock() + defer tds.tMu.Unlock() + acc, ok := tds.t.GetAccount(addrHash[:]) + return acc, ok +} + +func (tds *TrieDbState) ReadAccountDataForDebug(address libcommon.Address) (*accounts.Account, error) { + return tds.ReadAccountData(address) +} + +func (tds *TrieDbState) ReadAccountData(address libcommon.Address) (*accounts.Account, error) { + var account *accounts.Account + + addrHash, err := libcommon.HashData(address[:]) + if err != nil { + return nil, err + } + + account, ok := tds.GetAccount(addrHash) + if !ok { + account, err = tds.StateReader.ReadAccountData(address) + if err != nil { + return nil, err + } + } + + if tds.resolveReads { + tds.currentBuffer.accountReads[addrHash] = address + if account != nil { + tds.currentBuffer.accountReadsIncarnation[addrHash] = account.Incarnation + } + } + return account, nil +} + +func (tds *TrieDbState) ReadAccountStorage(address libcommon.Address, incarnation uint64, key *libcommon.Hash) ([]byte, error) { + addrHash := libcommon.Hash(crypto.Keccak256(address.Bytes())) + if tds.currentBuffer != nil { + if _, ok := tds.currentBuffer.deleted[addrHash]; ok { + return nil, nil + } + } + if tds.aggregateBuffer != nil { + if _, ok := tds.aggregateBuffer.deleted[addrHash]; ok { + return nil, nil + } + } + seckey, err := libcommon.HashData(key.Bytes()) + if err != nil { + return nil, err + } + + storagePlainKey := dbutils.GenerateStoragePlainKey(address, *key) + + if tds.resolveReads { + var storageKey common.StorageKey + copy(storageKey[:], dbutils.GenerateCompositeStorageKey(addrHash, incarnation, seckey)) + tds.currentBuffer.storageReads[storageKey] = storagePlainKey + } + + tds.tMu.Lock() + defer tds.tMu.Unlock() + enc, ok := tds.t.Get(dbutils.GenerateCompositeTrieKey(addrHash, seckey)) + if !ok { + enc, err := tds.StateReader.ReadAccountStorage(address, incarnation, key) + if err != nil { + return nil, err + } + return enc, nil + } + + return enc, nil +} + +func (tds *TrieDbState) readAccountCodeFromTrie(addrHash []byte) ([]byte, bool) { + tds.tMu.Lock() + defer tds.tMu.Unlock() + return tds.t.GetAccountCode(addrHash) +} + +func (tds *TrieDbState) readAccountCodeSizeFromTrie(addrHash []byte) (int, bool) { + tds.tMu.Lock() + defer tds.tMu.Unlock() + return tds.t.GetAccountCodeSize(addrHash) +} + +func (tds *TrieDbState) ReadAccountCode(address libcommon.Address, incarnation uint64) (code []byte, err error) { + addrHash := libcommon.Hash(crypto.Keccak256(address.Bytes())) + + if cached, ok := tds.readAccountCodeFromTrie(addrHash[:]); ok { + code, err = cached, nil + } else { + code, err = tds.StateReader.ReadAccountCode(address, incarnation) + } + if tds.resolveReads { + addrHash, err1 := libcommon.HashData(address[:]) + if err1 != nil { + return nil, err + } + tds.currentBuffer.accountReads[addrHash] = address + // we have to be careful, because the code might change + // during the block executuion, so we are always + // storing the latest code hash + codeHash := crypto.Keccak256Hash(code) + tds.currentBuffer.codeReads[addrHash] = witnesstypes.CodeWithHash{Code: code, CodeHash: codeHash} + tds.retainListBuilder.ReadCode(codeHash, code) + } + return code, err +} + +func (tds *TrieDbState) ReadAccountCodeSize(address libcommon.Address, incarnation uint64) (codeSize int, err error) { + addrHash := libcommon.Hash(crypto.Keccak256(address.Bytes())) + if cached, ok := tds.readAccountCodeSizeFromTrie(addrHash[:]); ok { + return cached, nil + } else { + codeSize, err = tds.StateReader.ReadAccountCodeSize(address, incarnation) + if err != nil { + return 0, err + } + } + if tds.resolveReads { + // We will need to read the code explicitly to make sure code is in the witness + code, err := tds.ReadAccountCode(address, incarnation) + if err != nil { + return 0, err + } + + codeHash := crypto.Keccak256Hash(code) + + addrHash, err1 := libcommon.HashData(address[:]) + if err1 != nil { + return 0, err1 + } + tds.currentBuffer.accountReads[addrHash] = address + // we have to be careful, because the code might change + // during the block executuion, so we are always + // storing the latest code hash + tds.currentBuffer.codeSizeReads[addrHash] = codeHash + // FIXME: support codeSize in witnesses if makes sense + tds.retainListBuilder.ReadCode(codeHash, code) + } + return codeSize, nil +} + +func (tds *TrieDbState) ReadAccountIncarnation(address libcommon.Address) (uint64, error) { + if inc, ok := tds.incarnationMap[address]; ok { + return inc, nil + } + inc, err := tds.StateReader.ReadAccountIncarnation(address) + if err != nil { + return 0, err + } else { + return inc, nil + } +} + +type TrieStateWriter struct { + tds *TrieDbState +} + +func (tds *TrieDbState) TrieStateWriter() *TrieStateWriter { + return &TrieStateWriter{tds: tds} +} + +func (tds *TrieStateWriter) WriteChangeSets() error { return nil } + +func (tds *TrieStateWriter) WriteHistory() error { return nil } + +func (tsw *TrieStateWriter) UpdateAccountData(address libcommon.Address, original, account *accounts.Account) error { + addrHash := libcommon.Hash(crypto.Keccak256(address.Bytes())) + tsw.tds.currentBuffer.accountUpdates[addrHash] = witnesstypes.AccountWithAddress{Address: address, Account: account} + tsw.tds.currentBuffer.accountReads[addrHash] = address + if original != nil { + tsw.tds.currentBuffer.accountReadsIncarnation[addrHash] = original.Incarnation + } + return nil +} + +func (tsw *TrieStateWriter) DeleteAccount(address libcommon.Address, original *accounts.Account) error { + addrHash := libcommon.Hash(crypto.Keccak256(address.Bytes())) + tsw.tds.currentBuffer.accountUpdates[addrHash] = witnesstypes.AccountWithAddress{Address: address, Account: original} // TODO: might be needed to use *AccountWithAddress to point to nil + tsw.tds.currentBuffer.accountReads[addrHash] = address + if original != nil { + tsw.tds.currentBuffer.accountReadsIncarnation[addrHash] = original.Incarnation + } + delete(tsw.tds.currentBuffer.storageUpdates, addrHash) + delete(tsw.tds.currentBuffer.storageIncarnation, addrHash) + delete(tsw.tds.currentBuffer.codeUpdates, addrHash) + tsw.tds.currentBuffer.deleted[addrHash] = address + if original.Incarnation > 0 { + tsw.tds.incarnationMap[address] = original.Incarnation + } + return nil +} + +func (tsw *TrieStateWriter) UpdateAccountCode(address libcommon.Address, incarnation uint64, codeHash libcommon.Hash, code []byte) error { + if tsw.tds.resolveReads { + tsw.tds.retainListBuilder.CreateCode(codeHash) + } + addrHash, err := libcommon.HashData(address.Bytes()) + if err != nil { + return err + } + tsw.tds.currentBuffer.codeUpdates[addrHash] = code + return nil +} + +func (tsw *TrieStateWriter) WriteAccountStorage(address libcommon.Address, incarnation uint64, key *libcommon.Hash, original, value *uint256.Int) error { + addrHash := libcommon.Hash(crypto.Keccak256(address.Bytes())) + + v := value.Bytes() + m, ok := tsw.tds.currentBuffer.storageUpdates[addrHash] + if !ok { + m = make(map[libcommon.Hash][]byte) + tsw.tds.currentBuffer.storageUpdates[addrHash] = m + } + tsw.tds.currentBuffer.storageIncarnation[addrHash] = incarnation + seckey, err := libcommon.HashData(key.Bytes()) + if err != nil { + return err + } + var storageKey common.StorageKey + copy(storageKey[:], dbutils.GenerateCompositeStorageKey(addrHash, incarnation, seckey)) + + storagePlainKey := dbutils.GenerateStoragePlainKey(address, *key) + tsw.tds.currentBuffer.storageReads[storageKey] = storagePlainKey + if len(v) > 0 { + m[seckey] = v + } else { + m[seckey] = nil + } + //fmt.Printf("WriteAccountStorage %x %x: %x, buffer %d\n", addrHash, seckey, value, len(tsw.tds.buffers)) + return nil +} + +// ExtractWitness produces block witness for the block just been processed, in a serialised form +func (tds *TrieDbState) ExtractWitness(trace bool, isBinary bool) (*trie.Witness, error) { + rs := tds.retainListBuilder.Build(isBinary) + + return tds.makeBlockWitness(trace, rs, isBinary) +} + +// ExtractWitness produces block witness for the block just been processed, in a serialised form +func (tds *TrieDbState) ExtractWitnessForPrefix(prefix []byte, trace bool, isBinary bool) (*trie.Witness, error) { + rs := tds.retainListBuilder.Build(isBinary) + + return tds.makeBlockWitnessForPrefix(prefix, trace, rs, isBinary) +} + +func (tds *TrieDbState) makeBlockWitnessForPrefix(prefix []byte, trace bool, rl trie.RetainDecider, isBinary bool) (*trie.Witness, error) { + tds.tMu.Lock() + defer tds.tMu.Unlock() + + t := tds.t + // if isBinary { + // t = trie.HexToBin(tds.t).Trie() + // } + + return t.ExtractWitnessForPrefix(prefix, trace, rl) +} + +func (tds *TrieDbState) makeBlockWitness(trace bool, rl trie.RetainDecider, isBinary bool) (*trie.Witness, error) { + tds.tMu.Lock() + defer tds.tMu.Unlock() + + t := tds.t + // if isBinary { + // t = trie.HexToBin(tds.t).Trie() + // } + + return t.ExtractWitness(trace, rl) +} + +func (tsw *TrieStateWriter) CreateContract(address libcommon.Address) error { + addrHash := libcommon.Hash(crypto.Keccak256(address.Bytes())) + tsw.tds.currentBuffer.created[addrHash] = address + tsw.tds.currentBuffer.accountReads[addrHash] = address + delete(tsw.tds.currentBuffer.storageUpdates, addrHash) + delete(tsw.tds.currentBuffer.storageIncarnation, addrHash) + return nil +} + +func (tds *TrieDbState) getBlockNr() uint64 { + return atomic.LoadUint64(&tds.blockNr) +} + +func (tds *TrieDbState) setBlockNr(n uint64) { + atomic.StoreUint64(&tds.blockNr, n) +} + +func (tds *TrieDbState) GetTrieHash() libcommon.Hash { + tds.tMu.Lock() + defer tds.tMu.Unlock() + return tds.t.Hash() +} diff --git a/docs/programmers_guide/witness_formal_spec.md b/docs/programmers_guide/witness_formal_spec.md new file mode 100644 index 00000000000..bcd8346bb3d --- /dev/null +++ b/docs/programmers_guide/witness_formal_spec.md @@ -0,0 +1,598 @@ +# Block Witness Formal Specification + +The keywords "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC 2119](https://tools.ietf.org/html/rfc2119). + +## Data Types + +### Basic + +`nil` - an empty value. + +`Any` - any data type. MUST NOT be `nil`. + +`Int` - an integer value. We treat the domain of integers as infinite, +the overflow behaviour or mapping to the actual data types is undefined +in this spec and should be up to implementation. + +`Byte` - a single byte. + +`Hash` - 32 byte value, representing a result of Keccak256 hashing. + +### Composite + +`()` - an empty array of arbitrary type. + +`(Type...)` - an array of a type `Type`. MUST NOT be empty. + +`{field:Type}` - an object with a field `field` of type `Type`. + + - full notation: `type T = {field:Type}` + + - inline `type TBase = T1{field:Type}|T2{field2:Type2}` + +### Type Definitions + +The type definitions are a bit similar to [Haskell](https://en.wikibooks.org/wiki/Haskell/Type_declarations). +The key differences are how the arrays and type fields are defined. + +### Nodes + +``` +type Node = HashNode{raw_hash:Hash} + | ValueNode{raw_value:(Byte...)} + | AccountNode{nonce:Int balance:Int storage:nil|Node code:nil|CodeNode|HashNode} + | LeafNode{key:(Byte...) value:ValueNode|AccountNode} + | ExtensionNode{key:(Byte...) child:Node} + | BranchNode{child0:nil|Node child1:nil|Node child3:nil|Node ... child15:nil|Node} + | CodeNode{code:(Byte... )} +``` + +### Witness + +Witness MUST have at least 1 element. + +``` +type WitnessHeader = {version:Int} +type Instruction = {code:Int parameter:Any...} +type Witness = (Node|Instruction...) +``` + + +## Execution Environment + +The witness execution environment MUST contain the following 2 elements: + +- **WitnessHeader** -- a header containing the version of the witness. The `version` MUST be 1. + +- **Witness** -- a witness to be executed; + +- **Substitution Rules** -- a list of all possible substitution rules. + + +## Execution process + +Initially, the Witness MUST BE an array of `Instruction`s. + +Then, as substitution rules are applied to the witness, some elements of the +array are replaced with `Node`s. + +The execution continues until there are no substitution rules left to execute. + +Here is how the execution code might look like in Go for building a single trie. + +```go +witness := GetInitialWitness() +rules := GetSubstitutionRules() +numberOfRulesApplied := 1 // initial state + +for numberOfRulesApplied > 0 { + witness, numberOfRulesApplied := ApplyRules(witness, rules) +} + +if len(witness) == 1 { + trie.root = witness[0] +} else { + panic("witness execution failed") +} + +``` + + +And here is an example of the execution process (we will use the set of rules +form the **Substitution Rules** section of this document): + +* **Step 1**. Witness: `(HASH h1 HASH h2 BRANCH 0b101 HASH h3 BRANCH 0b11)` + +* **Step 2**. Apply `HASH` substitution rules. +Witness: `(HashNode{h1} HashNode{h2} BRANCH 0b101 HashNode{h3} BRANCH 0b11)` + +* **Step 3**. Apply `BRANCH` substitution rules (only once, because `BRANCH 0b11` +doesn't pass its `GUARD` statements just yet). +Witness: `(BranchNode{0: HashNode{h1} 2:HashNode{h2}} HashNode{h3} BRANCH 0b11)` + +* **Step 4**. Apply `BRANCH` substitution rules again. +Witness: `(BranchNode{0: BranchNode{0: HashNode{h1} 2:HashNode{h2}} 1:HashNode{h3}})` + +* **Step 5**. No more rules are applicable, the witness contains only one + element, the execution ends successfully. + + +## End Criteria + +The execution ends when there are no substitution rules applicable for this +witness. + +### Building a single trie from the witness + +If we are building a single trie from the witness, then the only SUCCESS +execution is when the following are true: + +- The execution state MUST match the End Criteria +- There MUST be only one item left in the witness +- This item MUST be of the type `Node` + +In that case, this last item will be the root of the built trie. + +Every other end state is considered a FAILURE. + + +### Building a Forest + +We also can build a forest of tries with this approach, by adding a new +Instruction `NEW_TRIE` and adjusting the success criteria a bit: + +- The execution state MUST match the End Criteria; +- The items that are left in the witness MUST follow this pattern: `(Node + NEW_TRIE ... Node)` +- Each `Node` element will be a root of a trie. + +Every other end state is considered a FAILURE. + + +## Instructions & Parameters + +A single instruction consists of substitution rules and parameters. + +Each instruction MAY have one or more parameters. +The parameters values MUST be encoded in the witness. + +That makes it different from the helper function parameters that MAY come from the stack or MAY come from the witness. + + +## Substitution rules + +A substitution rule consists of 3 parts: + +`[GUARD] PATTERN |=> RESULT` + +- to the left of the `|=>` sign: + + - optional `GUARD` statements; + + - the pattern to match against; + +- result, to the right of the `|=>` sign. + + +### `GUARD`s + +Each substitution rule can have zero, one or multiple `GUARD` statements. +Each `GUARD` statement looks like this: + +``` +GUARD +``` + +For a substitution rule to be applicable, the `` in its `GUARD` statement MUST be true. + +If a substitution rule has multiple `GUARD` statements, all of them MUST BE satisfied. + +If there are no `GUARD` statements, the substitution rule's applicability is +only defined by the PATTERN. + +Example: +``` + GUARD NBITSET(mask) == 2 +|---- GUARD STATEMENT ---| + + Node(n0) Node(n1) BRANCH(mask) |=> + BranchNode{MAKE_VALUES_ARRAY(mask, n0, n1)} +``` + +For the example rule to be applicable both facts MUST be true: + +1. `mask` contains only 2 bits set to 1 (the rest are set to 0); + +2. to the left of `BRANCH` instruction there is at least 2 `Node`s. + +Fact (1) comes from the `GUARD` statement. + + +### PATTERN + +`[NodeType(boundVar1)... NodeType(boundVarN)] Instruction[(param1... paramN)]` + +A pattern MUST contain a single instruction. +A pattern MAY contain one or more `Node`s to the left of the instruction to +match. +An instruction MAY have one or more parameters. + +Pattern matching is happening by the types. `Node` type means any node is +matched, some specific node type will require a specific match. + +Pattern can have bound variable names for both matched nodes and instruction +parameters (if present). + +Match: + +``` +HASH h0 HashNode{h1} HashNode{h2} BRANCH 0b11 + |------------------- MATCH -----------| + +HASH h0 BranchNode{0: HashNode{h1} 1: HashNode{h2}} + |----------- SUBSTITUTED -------------------| +``` + +No match (not enough nodes to the left of the instruction): + +``` +HASH h0 HASH h1 HashNode{h2} BRANCH 0b11 +``` + +### Result + +`NodeType(HELPER_FUNCTION(arguments))` + +The result is a single `Node` statement that replaces the pattern in the +witness if it matches and the guards are passed. + +The result MAY contain helper functions or might have in-line computation. +The result MUST have a specific node type. No generic `Node` is allowed. + +Helper functions or inline computations might use bound variables from the +pattern. + +Example + +``` + +Node(n0) Node(n1) BRANCH(mask) |=> +BranchNode{MAKE_VALUES_ARRAY(mask, n0, n1)} + ^ ^-- ^--- BOUND NODES + |---- BOUND INSTRUCTION PARAM + |------ HELPER CALL ------------| +|----------------- RESULT ------------------| + +``` + +### Bringing it all together + + +So the full syntax is this: + +``` +[GUARD ...] [ NodeType(bound_variable1)... ] INSTRUCTION[(param1 ...)] |=> +Node() +``` + +`NodeType` is one of the types of nodes to match. Can also be `Node` to match +any non-nil node. + +Substitution rules MUST be non-ambiguous. Even though, there can be multiple +substitution rules applicable to the whole witness at the same time, there MUST +be only one rule that is applicable to a certain position in the witness. + +So, the minimal substitution rule is the one for the `HASH` instruction that pushes one hash to the stack: +``` +HASH(hashValue) |=> HashNode{hashValue} +``` + + +## Helper functions + +Helper functions are functions that are used in GUARDs or substitution rules. + +Helper functions MUST be pure. +Helper functions MUST have at least one argument. +Helper functions MAY have variadic parameters: `HELPER_EXAMPLE(arg1, arg2, list...)`. +Helper functions MAY contain recursion. + +## Instructions + +### `LEAF key raw_value` + +**Substitution rules** + +Replaces the instruction with a `ValueNode` wrapped with a `LeafNode`. + +``` +LEAF(key, raw_value) |=> LeafNode{key, ValueNode(raw_value)} +``` + +### `EXTENSION key` + +Wraps a node to the left of the instruction with an `ExtensionNode`. + +**Substitution rules** + +``` +Node(node) EXTENSION(key) |=> ExtensionNode{key, node} +``` + +### `HASH raw_hash` + +Replaces the instruction with a `HashNode`. + +**Substitution rules** + +``` +HASH(hash_value) |=> HashNode{hash_value} +``` + +### `CODE raw_code` + +Replaces the instruction with a `CodeNode`. + +``` +CODE(raw_code) |=> CodeNode{raw_code} +``` + +### `ACCOUNT_LEAF key nonce balance has_code has_storage` + +Replaces the instruction and, optionally, up to 2 nodes to the left of the +instruction with a single `AccountNode` wrapped with a `LeafNode`. + +**Substitution rules** + +``` +GUARD has_code == true +GUARD has_storage == true + +CodeNode(code) Node(storage_hash_node) ACCOUNT_LEAF(key, nonce, balance, has_code, has_storage) |=> +LeafNode{key, AccountNode{nonce, balance, storage_root, code}} + +--- + +GUARD has_code == true +GUARD has_storage == true + +HashNode(code) Node(storage_hash_node) ACCOUNT_LEAF(key, nonce, balance, has_code, has_storage) |=> +LeafNode{key, AccountNode{nonce, balance, storage_root, code}} + +--- + +GUARD has_code == false +GUARD has_storage == true + +Node(storage_root) ACCOUNT_LEAF(key, nonce, balance, has_code, has_storage) |=> +LeafNode{key, AccountNode{nonce, balance, storage_root, nil}} + +--- + +GUARD has_code == true +GUARD has_storage == false + +CodeNode(code) ACCOUNT_LEAF(key, nonce, balance, has_code, has_storage) |=> +LeafNode{key, AccountNode{nonce, balance, nil, nil, code}} + +--- + +GUARD has_code == true +GUARD has_storage == false + +HashNode(code) ACCOUNT_LEAF(key, nonce, balance, has_code, has_storage) |=> +LeafNode{key, AccountNode{nonce, balance, nil, nil, code}} + +--- + +GUARD has_code == false +GUARD has_storage == false + +ACCOUNT_LEAF(key, nonce, balance, has_code, has_storage) |=> +LeafNode{key, AccountNode{nonce, balance, nil, nil, nil}} + +``` + +### `NEW_TRIE` + +No substitution rules. This instruction is used as a "divider" when building +a forest of tries. + +### `BRANCH mask` + +Replaces `NBITSET(mask)` `Node`s to the left of the instruction with a single +`BranchNode` with these nodes as children according to `mask`. + +**Substitution rules** +``` + +GUARD NBITSET(mask) == 2 + +Node(n0) Node(n1) BRANCH(mask) |=> +BranchNode{MAKE_VALUES_ARRAY(mask, n0, n1)} + +--- + +GUARD NBITSET(mask) == 3 + +Node(n0) Node(n1) Node(n2) BRANCH(mask) |=> +BranchNode{MAKE_VALUES_ARRAY(mask, n0, n1, n2)} + +--- + +... + +--- + +GUARD NBITSET(mask) == 16 + +Node(n0) Node(n1) ... Node(n15) BRANCH(mask) |=> +BranchNode{MAKE_VALUES_ARRAY(mask, n0, n1, ..., n15)} +``` + +## Helper functions + +### `MAKE_VALUES_ARRAY` + +returns an array of 16 elements, where values from `values` are set to the indices where `mask` has bits set to 1. Every other place has `nil` value there. + +**Example**: `MAKE_VALUES_ARRAY(5, [a, b])` returns `[a, nil, b, nil, nil, ..., nil]` (binary representation of 5 is `0000000000000101`) + +``` +MAKE_VALUES_ARRAY(mask, values...) { + return MAKE_VALUES_ARRAY(mask, 0, values) +} + +MAKE_VALUES_ARRAY(mask, idx, values...) { + if idx > 16 { + return [] + } + + if BIT_TEST(mask, idx) { + return PREPEND(FIRST(values), (MAKE_VALUES_ARRAY mask, INC(idx), REST(values))) + } else { + return PREPEND(nil, (MAKE_VALUES_ARRAY mask, INC(idx), values)) + } +} +``` + + +### `RLP(value)` + +returns the RLP encoding of a value + + +### `NBITSET(number)` + +returns number of bits set in the binary representation of `number`. + +### `BIT_TEST(number, n)` + +`n` MUST NOT be negative. + +returns `true` if bit `n` in `number` is set, `false` otherwise. + +### `PREPEND(value, array)` + +returns a new array with the `value` at index 0 and `array` values starting from index 1 + +### `INC(value)` + +increments `value` by 1 + +### `FIRST(array)` + +returns the first value in the specified array + +### `REST(array)` + +returns the array w/o the first item + +### `KECCAK(bytes)` + +returns a keccak-256 hash of `bytes` + + +## Serialization + +The format for serialization of everything except hashes (that we know the +length of) is [CBOR](https://cbor.io). It is RFC-specified and concise. + +For hashes we use the optimization of knowing the lengths, so we just read 32 +bytes + +### Block Witness Format + +Each block witness consists of a header followed by a list of instructions. + +There is no length of witness specified anywhere, the code expects to just reach `EOF`. + +Serialized Witness: `(HEADER, OP1, OP2, ..., OPn-1, OPn, EOF)` + +#### Encoding + +##### CBOR + +The parts of the key that are encoded with CBOR are marked by the `CBOR` function. + +##### Keys + +Keys are also using custom encryption to make them more compact. + +The nibbles of a key are encoded in a following way `[FLAGS NIBBLE1+NIBBLE2 NIBBLE3+NIBBLE4 NIBBLE5... ]` + +*FLAGS* +* bit 0 -- 1 if the number of nibbles were odd +* bit 1 -- 1 if the nibbles end with 0x10 (the terminator byte) + +This is shown later as `ENCODE_KEY` function. + +#### Header + +format: `version:byte` + +encoded as `[ version ]` + +the current version is 1. + +#### Instructions + +Each instruction starts with an opcode (`uint`). + +Then it might contain some data. + +##### `LEAF` + +format: `LEAF key:[]byte value:[]byte` + +encoded as `[ 0x00 CBOR(ENCODE_KEY(key))... CBOR(value)... ]` + + +##### `EXTENSION` + +format: `EXTENSION key:[]byte` + +encoded as `[ 0x01 CBOR(ENCODE_KEY(key))... ]` + + +##### `BRANCH` + +format: `BRANCH mask:uint32` + +*mask* defines which children are present +(e.g. `0000000000001011` means that children 0, 1 and 3 are present and the other ones are not) + +encoded as `[ 0x02 CBOR(mask)...]` + + +##### `HASH` + +format: `HASH hash:[32]byte` + +encoded as `[ 0x03 hash_byte_1 ... hash_byte_32 ]` + + +##### `CODE` + +format: `CODE code:[]byte` + +encoded as `[ 0x04 CBOR(code)... ]` + + +##### `ACCOUNT_LEAF` + +format: `ACCOUNT_LEAF key:[]byte flags [nonce:uint64] [balance:[]byte]` + +encoded as `[ 0x05 CBOR(ENCODE_KEY(key))... flags /CBOR(nonce).../ /CBOR(balance).../ ]` + +*flags* is a bitset encoded in a single bit (see [`witness_operators_test.go`](../../trie/witness_operators_test.go) to see flags in action). +* bit 0 defines if **code** is present; if set to 1, then `has_code=true`; +* bit 1 defines if **storage** is present; if set to 1, then `has_storage=true`; +* bit 2 defines if **nonce** is not 0; if set to 0, *nonce* field is not encoded; +* bit 3 defines if **balance** is not 0; if set to 0, *balance* field is not encoded; + +##### `NEW_TRIE` + +format: `NEW_TRIE` + +encoded as `[ 0xBB ]` diff --git a/docs/programmers_guide/witness_format.md b/docs/programmers_guide/witness_format.md new file mode 100644 index 00000000000..4b1508f06d9 --- /dev/null +++ b/docs/programmers_guide/witness_format.md @@ -0,0 +1,96 @@ +# Block Witness Format + +Each block witness consists of a header followed by a list of operators. + +There is no length of witness specified anywhere, the code expects to just reach `EOF`. + +Witness: `[HEADER, OP1, OP2, ..., OPn-1, OPn, EOF]` + +## Encoding + +### Keys + +key nibbles are encoded in a following way `[FLAGS NIBBLE1+NIBBLE2 NIBBLE3+NIBBLE4 NIBBLE5... ]` + +*FLAGS* +* bit 0 -- 1 if the number of nibbles were odd +* bit 1 -- 1 if the nibbles end with 0x10 + +## Header + +format: `version:byte` + +encoded as `[ version ]` + +the current version is 1. + +## Operators + +Each operator starts with an opcode (see [`witness_operators.go`](../../trie/witness_operators.go) for exact values). + +Then it might contain some data. + +### `OpEmptyRoot` + +puts empty trie root to on the stack + +format: `OpEmptyRoot` + +encoded as `[ 0x06 ]` + +### `OpHash` + +puts a single hash on the stack + +format: `OpHash hash:[32]byte` + +encoded as `[ 0x03 hash_byte_1 ... hash_byte_32 ]` + +### `OpBranch` + +pops N values from the stack and adds them as the children; pushes the result to the stack; N is the number of 1's in the *mask* field. + +format: `OpBranch mask:uint32` + +*mask* defines which children are present +(e.g. `0000000000001011` means that children 0, 1 and 3 are present and the other ones are not) + +encoded as `[ 0x02 CBOR(mask)...]` + +### `OpCode` + +pushes a code to the stack + +format: `OpCode code:[]byte` + +encoded as `[ 0x04 CBOR(code)... ]` + +### `OpExtension` + +pushes an extension node with a specified key on the stack + +format: `OpExtension key:[]byte` + +encoded as `[ 0x01 CBOR(key)... ]` + +### `OpLeaf` + +pushes a leaf with specified key and value to the stack + +format: `OpLeaf key:[]byte value:[]byte` + +encoded as `[ 0x00 CBOR(key)... CBOR(value)... ]` + +### `OpAccountLeaf` + +pushes a leaf with specified parameters to the stack; if flags show, before that pops 1 or 2 values from the stack; + +format: `OpAccountLeaf key:[]byte flags [nonce:uint64] [balance:[]byte]` + +encoded as `[ 0x05 CBOR(key|[]byte)... flags /CBOR(nonce).../ /CBOR(balance).../ ]` + +*flags* is a bitset encoded in a single bit (see [`witness_operators_test.go`](../../trie/witness_operators_test.go) to see flags in action). +* bit 0 defines if **code** is present; if set to 1 it assumes that either `OpCode` or `OpHash` already put something on the stack; +* bit 1 defines if **storage** is present; if set to 1, the operators preceding `OpAccountLeaf` will reconstruct a storage trie; +* bit 2 defines if **nonce** is not 0; if set to 0, *nonce* field is not encoded; +* bit 3 defines if **balance** is not 0; if set to 0, *balance* field is not encoded; \ No newline at end of file diff --git a/erigon-lib/commitment/commitment.go b/erigon-lib/commitment/commitment.go index 60ca4bcca6f..1e60c1f790f 100644 --- a/erigon-lib/commitment/commitment.go +++ b/erigon-lib/commitment/commitment.go @@ -138,7 +138,7 @@ func InitializeTrieAndUpdates(tv TrieVariant, mode Mode, tmpdir string) (Trie, * default: trie := NewHexPatriciaHashed(length.Addr, nil, tmpdir) - tree := NewUpdates(mode, tmpdir, trie.hashAndNibblizeKey) + tree := NewUpdates(mode, tmpdir, trie.HashAndNibblizeKey) return trie, tree } } diff --git a/erigon-lib/commitment/hex_patricia_hashed.go b/erigon-lib/commitment/hex_patricia_hashed.go index 6e39f1ad034..9c6afeb22ea 100644 --- a/erigon-lib/commitment/hex_patricia_hashed.go +++ b/erigon-lib/commitment/hex_patricia_hashed.go @@ -35,16 +35,19 @@ import ( "github.com/erigontech/erigon-lib/etl" "github.com/erigontech/erigon-lib/log/v3" + "github.com/erigontech/erigon-lib/trie" + "github.com/erigontech/erigon-lib/types/accounts" + witnesstypes "github.com/erigontech/erigon-lib/types/witness" "github.com/erigontech/erigon-lib/common/dbg" - "golang.org/x/crypto/sha3" - - "github.com/erigontech/erigon-lib/common/hexutility" - "github.com/erigontech/erigon-lib/common" + libcommon "github.com/erigontech/erigon-lib/common" + "github.com/erigontech/erigon-lib/common/hexutility" "github.com/erigontech/erigon-lib/common/length" + ecrypto "github.com/erigontech/erigon-lib/crypto" rlp "github.com/erigontech/erigon-lib/rlp2" + "golang.org/x/crypto/sha3" ) // keccakState wraps sha3.state. In addition to the usual hash methods, it also supports @@ -194,27 +197,6 @@ func (cell *cell) reset() { cell.Update.Reset() } -func (cell *cell) String() string { - b := new(strings.Builder) - b.WriteString("{") - b.WriteString(fmt.Sprintf("loaded=%v ", cell.loaded)) - if cell.Deleted() { - b.WriteString("DELETED ") - } - if cell.accountAddrLen > 0 { - b.WriteString(fmt.Sprintf("addr=%x ", cell.accountAddr[:cell.accountAddrLen])) - } - if cell.storageAddrLen > 0 { - b.WriteString(fmt.Sprintf("addr[s]=%x", cell.storageAddr[:cell.storageAddrLen])) - - } - if cell.hashLen > 0 { - b.WriteString(fmt.Sprintf("h=%x", cell.hash[:cell.hashLen])) - } - b.WriteString("}") - return b.String() -} - func (cell *cell) FullString() string { b := new(strings.Builder) b.WriteString("{") @@ -749,6 +731,176 @@ func (hph *HexPatriciaHashed) computeCellHashLen(cell *cell, depth int) int { return length.Hash + 1 } +func (hph *HexPatriciaHashed) computeCellHashWithStorage(cell *cell, depth int, buf []byte) ([]byte, bool, []byte, error) { + var err error + var storageRootHash [length.Hash]byte + var storageRootHashIsSet bool + if cell.storageAddrLen > 0 { + var hashedKeyOffset int + if depth >= 64 { + hashedKeyOffset = depth - 64 + } + singleton := depth <= 64 + koffset := hph.accountKeyLen + if depth == 0 && cell.accountAddrLen == 0 { + // if account key is empty, then we need to hash storage key from the key beginning + koffset = 0 + } + if err = hashKey(hph.keccak, cell.storageAddr[koffset:cell.storageAddrLen], cell.hashedExtension[:], hashedKeyOffset, cell.hashBuf[:]); err != nil { + return nil, storageRootHashIsSet, nil, err + } + cell.hashedExtension[64-hashedKeyOffset] = 16 // Add terminator + + if cell.stateHashLen > 0 { + res := append([]byte{160}, cell.stateHash[:cell.stateHashLen]...) + hph.keccak.Reset() + if hph.trace { + fmt.Printf("REUSED stateHash %x spk %x\n", res, cell.storageAddr[:cell.storageAddrLen]) + } + mxTrieStateSkipRate.Inc() + skippedLoad.Add(1) + if !singleton { + return res, storageRootHashIsSet, nil, err + } else { + storageRootHashIsSet = true + storageRootHash = *(*[length.Hash]byte)(res[1:]) + //copy(storageRootHash[:], res[1:]) + //cell.stateHashLen = 0 + } + } else { + if !cell.loaded.storage() { + update, err := hph.ctx.Storage(cell.storageAddr[:cell.storageAddrLen]) + if err != nil { + return nil, storageRootHashIsSet, nil, err + } + cell.setFromUpdate(update) + fmt.Printf("Storage %x was not loaded\n", cell.storageAddr[:cell.storageAddrLen]) + } + if singleton { + if hph.trace { + fmt.Printf("leafHashWithKeyVal(singleton) for [%x]=>[%x]\n", cell.hashedExtension[:64-hashedKeyOffset+1], cell.Storage[:cell.StorageLen]) + } + aux := make([]byte, 0, 33) + if aux, err = hph.leafHashWithKeyVal(aux, cell.hashedExtension[:64-hashedKeyOffset+1], cell.Storage[:cell.StorageLen], true); err != nil { + return nil, storageRootHashIsSet, nil, err + } + if hph.trace { + fmt.Printf("leafHashWithKeyVal(singleton) storage hash [%x]\n", aux) + } + storageRootHash = *(*[length.Hash]byte)(aux[1:]) + storageRootHashIsSet = true + cell.stateHashLen = 0 + hadToReset.Add(1) + } else { + if hph.trace { + fmt.Printf("leafHashWithKeyVal for [%x]=>[%x] %v\n", cell.hashedExtension[:64-hashedKeyOffset+1], cell.Storage[:cell.StorageLen], cell.String()) + } + leafHash, err := hph.leafHashWithKeyVal(buf, cell.hashedExtension[:64-hashedKeyOffset+1], cell.Storage[:cell.StorageLen], false) + if err != nil { + return nil, storageRootHashIsSet, nil, err + } + + copy(cell.stateHash[:], leafHash[1:]) + cell.stateHashLen = len(leafHash) - 1 + if hph.trace { + fmt.Printf("STATE HASH storage memoized %x spk %x\n", leafHash, cell.storageAddr[:cell.storageAddrLen]) + } + + return leafHash, storageRootHashIsSet, storageRootHash[:], nil + } + } + } + if cell.accountAddrLen > 0 { + if err := hashKey(hph.keccak, cell.accountAddr[:cell.accountAddrLen], cell.hashedExtension[:], depth, cell.hashBuf[:]); err != nil { + return nil, storageRootHashIsSet, nil, err + } + cell.hashedExtension[64-depth] = 16 // Add terminator + if !storageRootHashIsSet { + if cell.extLen > 0 { // Extension + if cell.hashLen == 0 { + return nil, storageRootHashIsSet, nil, errors.New("computeCellHash extension without hash") + } + if hph.trace { + fmt.Printf("extensionHash for [%x]=>[%x]\n", cell.extension[:cell.extLen], cell.hash[:cell.hashLen]) + } + if storageRootHash, err = hph.extensionHash(cell.extension[:cell.extLen], cell.hash[:cell.hashLen]); err != nil { + return nil, storageRootHashIsSet, nil, err + } + if hph.trace { + fmt.Printf("EXTENSION HASH %x DROPS stateHash\n", storageRootHash) + } + cell.stateHashLen = 0 + hadToReset.Add(1) + } else if cell.hashLen > 0 { + storageRootHash = cell.hash + storageRootHashIsSet = true + } else { + storageRootHash = *(*[length.Hash]byte)(EmptyRootHash) + } + } + if !cell.loaded.account() { + if cell.stateHashLen > 0 { + res := append([]byte{160}, cell.stateHash[:cell.stateHashLen]...) + hph.keccak.Reset() + + mxTrieStateSkipRate.Inc() + skippedLoad.Add(1) + if hph.trace { + fmt.Printf("REUSED stateHash %x apk %x\n", res, cell.accountAddr[:cell.accountAddrLen]) + } + return res, storageRootHashIsSet, storageRootHash[:], nil + } + // storage root update or extension update could invalidate older stateHash, so we need to reload state + update, err := hph.ctx.Account(cell.accountAddr[:cell.accountAddrLen]) + if err != nil { + return nil, storageRootHashIsSet, storageRootHash[:], err + } + cell.setFromUpdate(update) + } + + var valBuf [128]byte + valLen := cell.accountForHashing(valBuf[:], storageRootHash) + if hph.trace { + fmt.Printf("accountLeafHashWithKey for [%x]=>[%x]\n", cell.hashedExtension[:65-depth], rlp.RlpEncodedBytes(valBuf[:valLen])) + } + leafHash, err := hph.accountLeafHashWithKey(buf, cell.hashedExtension[:65-depth], rlp.RlpEncodedBytes(valBuf[:valLen])) + if err != nil { + return nil, storageRootHashIsSet, nil, err + } + if hph.trace { + fmt.Printf("STATE HASH account memoized %x\n", leafHash) + } + copy(cell.stateHash[:], leafHash[1:]) + cell.stateHashLen = len(leafHash) - 1 + return leafHash, storageRootHashIsSet, storageRootHash[:], nil + } + + buf = append(buf, 0x80+32) + if cell.extLen > 0 { // Extension + if cell.hashLen > 0 { + if hph.trace { + fmt.Printf("extensionHash for [%x]=>[%x]\n", cell.extension[:cell.extLen], cell.hash[:cell.hashLen]) + } + var hash [length.Hash]byte + if hash, err = hph.extensionHash(cell.extension[:cell.extLen], cell.hash[:cell.hashLen]); err != nil { + return nil, storageRootHashIsSet, storageRootHash[:], err + } + buf = append(buf, hash[:]...) + } else { + return nil, storageRootHashIsSet, storageRootHash[:], errors.New("computeCellHash extension without hash") + } + } else if cell.hashLen > 0 { + buf = append(buf, cell.hash[:cell.hashLen]...) + } else if storageRootHashIsSet { + buf = append(buf, storageRootHash[:]...) + copy(cell.hash[:], storageRootHash[:]) + cell.hashLen = len(storageRootHash) + } else { + buf = append(buf, EmptyRootHash...) + } + return buf, storageRootHashIsSet, storageRootHash[:], nil +} + func (hph *HexPatriciaHashed) computeCellHash(cell *cell, depth int, buf []byte) ([]byte, error) { var err error var storageRootHash [length.Hash]byte @@ -953,6 +1105,228 @@ func (hph *HexPatriciaHashed) needUnfolding(hashedKey []byte) int { return unfolding } +func (c *cell) IsEmpty() bool { + return c.hashLen == 0 && c.hashedExtLen == 0 && c.extLen == 0 && c.accountAddrLen == 0 && c.storageAddrLen == 0 +} + +func (c *cell) String() string { + s := "(" + if c.hashLen > 0 { + s += fmt.Sprintf("hash(len=%d)=%x, ", c.hashLen, c.hash) + } + if c.hashedExtLen > 0 { + s += fmt.Sprintf("hashedExtension(len=%d)=%x, ", c.hashedExtLen, c.hashedExtension[:c.hashedExtLen]) + } + if c.extLen > 0 { + s += fmt.Sprintf("extension(len=%d)=%x, ", c.extLen, c.extension[:c.extLen]) + } + if c.accountAddrLen > 0 { + s += fmt.Sprintf("accountAddr=%x, ", c.accountAddr) + } + if c.storageAddrLen > 0 { + s += fmt.Sprintf("storageAddr=%x, ", c.storageAddr) + } + + s += ")" + return s +} + +func (hph *HexPatriciaHashed) PrintGrid() { + fmt.Printf("GRID:\n") + for row := 0; row < hph.activeRows; row++ { + fmt.Printf("row %d depth %d:\n", row, hph.depths[row]) + for col := 0; col < 16; col++ { + cell := &hph.grid[row][col] + if cell.hashedExtLen > 0 || cell.accountAddrLen > 0 { + var cellHash []byte + cellHash, _, _, err := hph.computeCellHashWithStorage(cell, hph.depths[row], nil) + if err != nil { + panic("failed to compute cell hash") + } + fmt.Printf("\t %x: %v cellHash=%x, \n", col, cell, cellHash) + } else { + fmt.Printf("\t %x: %v , \n", col, cell) + } + } + fmt.Printf("\n") + } + fmt.Printf("\n") +} + +// this function is only related to the witness +func (hph *HexPatriciaHashed) createAccountNode(c *cell, row int, hashedKey []byte, codeReads map[libcommon.Hash]witnesstypes.CodeWithHash) (*trie.AccountNode, error) { + _, storageIsSet, storageRootHash, err := hph.computeCellHashWithStorage(c, hph.depths[row], nil) + if err != nil { + return nil, err + } + accountUpdate, err := hph.ctx.Account(c.accountAddr[:c.accountAddrLen]) + if err != nil { + return nil, err + } + var account accounts.Account + account.Nonce = accountUpdate.Nonce + account.Balance = accountUpdate.Balance + account.Initialised = true + account.Root = accountUpdate.Storage + account.CodeHash = accountUpdate.CodeHash + + addrHash, err := compactKey(hashedKey[:64]) + if err != nil { + return nil, err + } + + // get code + var code []byte + codeWithHash, hasCode := codeReads[[32]byte(addrHash)] + if !hasCode { + code = nil + } else { + code = codeWithHash.Code + // sanity check + if account.CodeHash != codeWithHash.CodeHash { + return nil, fmt.Errorf("account.CodeHash(%x)!=codeReads[%x].CodeHash(%x)", account.CodeHash, addrHash, codeWithHash.CodeHash) + } + } + + var accountNode *trie.AccountNode + if !storageIsSet { + account.Root = trie.EmptyRoot + accountNode = &trie.AccountNode{Account: account, Storage: nil, RootCorrect: true, Code: code, CodeSize: -1} + } else { + accountNode = &trie.AccountNode{Account: account, Storage: trie.NewHashNode(storageRootHash), RootCorrect: true, Code: code, CodeSize: -1} + } + return accountNode, nil +} + +func (hph *HexPatriciaHashed) nCellsInRow(row int) int { //nolint:unused + count := 0 + for col := 0; col < 16; col++ { + c := &hph.grid[row][col] + if !c.IsEmpty() { + count++ + } + } + return count +} + +// Traverse the grid following `hashedKey` and produce the witness `trie.Trie` for that key +func (hph *HexPatriciaHashed) ToTrie(hashedKey []byte, codeReads map[libcommon.Hash]witnesstypes.CodeWithHash) (*trie.Trie, error) { + rootNode := &trie.FullNode{} + var currentNode trie.Node = rootNode + keyPos := 0 // current position in hashedKey (usually same as row, but could be different due to extension nodes) + for row := 0; row < hph.activeRows && keyPos < len(hashedKey); row++ { + currentNibble := hashedKey[keyPos] + // determine the type of the next node to expand (in the next iteration) + var nextNode trie.Node + // need to check node type along the key path + cellToExpand := &hph.grid[row][currentNibble] + // determine the next node + if cellToExpand.hashedExtLen > 0 { // extension cell + keyPos += cellToExpand.hashedExtLen // jump ahead + hashedExtKey := cellToExpand.hashedExtension[:cellToExpand.hashedExtLen] + extKeyLength := len(hashedExtKey) + if keyPos+1 == len(hashedKey) || keyPos+1 == 64 { + extKeyLength++ // +1 for the terminator 0x10 ([16]) byte when on a terminal extension node + } + extensionKey := make([]byte, extKeyLength) + copy(extensionKey, hashedExtKey) + if keyPos+1 == len(hashedKey) || keyPos+1 == 64 { + extensionKey[len(extensionKey)-1] = 16 // append terminator byte + } + nextNode = &trie.ShortNode{Key: extensionKey} // Value will be in the next iteration + if keyPos+1 == len(hashedKey) { + if cellToExpand.storageAddrLen > 0 { + storageUpdate, err := hph.ctx.Storage(cellToExpand.storageAddr[:cellToExpand.storageAddrLen]) + if err != nil { + return nil, err + } + storageValueNode := trie.ValueNode(storageUpdate.Storage[:storageUpdate.StorageLen]) + nextNode = &trie.ShortNode{Key: extensionKey, Val: storageValueNode} + } else if cellToExpand.accountAddrLen > 0 { + accNode, err := hph.createAccountNode(cellToExpand, row, hashedKey, codeReads) + if err != nil { + return nil, err + } + nextNode = &trie.ShortNode{Key: extensionKey, Val: accNode} + extNodeSubTrie := trie.NewInMemoryTrie(nextNode) + subTrieRoot := extNodeSubTrie.Root() + cellHash, _, _, _ := hph.computeCellHashWithStorage(cellToExpand, hph.depths[row], nil) + if !bytes.Equal(subTrieRoot, cellHash[1:]) { + return nil, fmt.Errorf("subTrieRoot(%x) != cellHash(%x)", subTrieRoot, cellHash[1:]) + } + // // DEBUG patch with cell hash which we know to be correct + // nextNode = trie.NewHashNode(cellHash[1:]) + } + } + } else if cellToExpand.storageAddrLen > 0 { // storage cell + storageUpdate, err := hph.ctx.Storage(cellToExpand.storageAddr[:cellToExpand.storageAddrLen]) + if err != nil { + return nil, err + } + storageValueNode := trie.ValueNode(storageUpdate.Storage[:storageUpdate.StorageLen]) + nextNode = &storageValueNode //nolint:ineffassign, wastedassign + break + } else if cellToExpand.accountAddrLen > 0 { // account cell + accNode, err := hph.createAccountNode(cellToExpand, row, hashedKey, codeReads) + if err != nil { + return nil, err + } + nextNode = accNode + keyPos++ // only move one nibble + } else if cellToExpand.hashLen > 0 { // hash cell means we will expand using a full node + nextNode = &trie.FullNode{} + keyPos++ + } else if cellToExpand.IsEmpty() { + nextNode = nil // no more expanding can happen (this could be due ) + } else { // default for now before we handle extLen + nextNode = &trie.FullNode{} + keyPos++ + } + + // process the current node + if fullNode, ok := currentNode.(*trie.FullNode); ok { // handle full node case + for col := 0; col < 16; col++ { + currentCell := &hph.grid[row][col] + if currentCell.IsEmpty() { + fullNode.Children[col] = nil + continue + } + cellHash, _, _, err := hph.computeCellHashWithStorage(currentCell, hph.depths[row], nil) + if err != nil { + return nil, err + } + fullNode.Children[col] = trie.NewHashNode(cellHash[1:]) // because cellHash has 33 bytes and we want 32 + } + fullNode.Children[currentNibble] = nextNode // ready to expand next nibble in the path + } else if accNode, ok := currentNode.(*trie.AccountNode); ok { + if len(hashedKey) <= 64 { // no storage, stop here + nextNode = nil // nolint:ineffassign, wastedassign + break + } + // there is storage so we need to expand further + accNode.Storage = nextNode + } else if extNode, ok := currentNode.(*trie.ShortNode); ok { // handle extension node case + // expect only one item in this row, so take the first one + // technically it should be at the last nibble of the key but we will adjust this later + if extNode.Val != nil { // early termination + break + } + extNode.Val = nextNode + } else { + break // break if currentNode is nil + } + // we need to check if we are dealing with the next node being an account node and we have a storage key, + // in that case start a new tree for the storage + if nextAccNode, ok := nextNode.(*trie.AccountNode); ok && len(hashedKey) > 64 { + nextNode = &trie.FullNode{} + nextAccNode.Storage = nextNode + } + currentNode = nextNode + } + tr := trie.NewInMemoryTrie(rootNode) + return tr, nil +} + // unfoldBranchNode returns true if unfolding has been done func (hph *HexPatriciaHashed) unfoldBranchNode(row, depth int, deleted bool) (bool, error) { key := hexToCompact(hph.currentKey[:hph.currentKeyLen]) @@ -1505,6 +1879,120 @@ func (hph *HexPatriciaHashed) RootHash() ([]byte, error) { return rootHash[1:], nil // first byte is 128+hash_len=160 } +// Generate the block witness. This works by loading each key from the list of updates (they are not really updates since we won't modify the trie, +// but currently need to be defined like that for the fold/unfold algorithm) into the grid and traversing the grid to convert it into `trie.Trie`. +// All the individual tries are combined to create the final witness trie. +// Because the grid is lacking information about the code in smart contract accounts which is also part of the witness, we need to provide that as an input parameter to this function (`codeReads`) +func (hph *HexPatriciaHashed) GenerateWitness(ctx context.Context, updates *Updates, codeReads map[libcommon.Hash]witnesstypes.CodeWithHash, expectedRootHash []byte, logPrefix string) (witnessTrie *trie.Trie, rootHash []byte, err error) { + var ( + m runtime.MemStats + ki uint64 + + updatesCount = updates.Size() + logEvery = time.NewTicker(20 * time.Second) + ) + defer logEvery.Stop() + var tries []*trie.Trie = make([]*trie.Trie, 0, len(updates.keys)) // slice of tries, i.e the witness for each key, these will be all merged into single trie + err = updates.HashSort(ctx, func(hashedKey, plainKey []byte, stateUpdate *Update) error { + select { + case <-logEvery.C: + dbg.ReadMemStats(&m) + log.Info(fmt.Sprintf("[%s][agg] computing trie", logPrefix), + "progress", fmt.Sprintf("%s/%s", common.PrettyCounter(ki), common.PrettyCounter(updatesCount)), + "alloc", common.ByteCount(m.Alloc), "sys", common.ByteCount(m.Sys)) + + default: + } + + var tr *trie.Trie + var computedRootHash []byte + + fmt.Printf("\n%d/%d) plainKey [%x] hashedKey [%x] currentKey [%x]\n", ki+1, updatesCount, plainKey, hashedKey, hph.currentKey[:hph.currentKeyLen]) + + if len(plainKey) == 20 { // account + account, err := hph.ctx.Account(plainKey) + if err != nil { + return fmt.Errorf("account with plainkey=%x not found: %w", plainKey, err) + } else { + addrHash := ecrypto.Keccak256(plainKey) + fmt.Printf("account with plainKey=%x, addrHash=%x FOUND = %v\n", plainKey, addrHash, account) + } + } else { + storage, err := hph.ctx.Storage(plainKey) + if err != nil { + return fmt.Errorf("storage with plainkey=%x not found: %w", plainKey, err) + } + fmt.Printf("storage found = %v\n", storage.Storage) + } + + // Keep folding until the currentKey is the prefix of the key we modify + for hph.needFolding(hashedKey) { + if err := hph.fold(); err != nil { + return fmt.Errorf("fold: %w", err) + } + } + // Now unfold until we step on an empty cell + for unfolding := hph.needUnfolding(hashedKey); unfolding > 0; unfolding = hph.needUnfolding(hashedKey) { + if err := hph.unfold(hashedKey, unfolding); err != nil { + return fmt.Errorf("unfold: %w", err) + } + } + hph.PrintGrid() + + // convert grid to trie.Trie + tr, err = hph.ToTrie(hashedKey, codeReads) // build witness trie for this key, based on the current state of the grid + if err != nil { + return err + } + computedRootHash = tr.Root() + fmt.Printf("computedRootHash = %x\n", computedRootHash) + + if !bytes.Equal(computedRootHash, expectedRootHash) { + err = fmt.Errorf("root hash mismatch computedRootHash(%x)!=expectedRootHash(%x)", computedRootHash, expectedRootHash) + return err + } + + tries = append(tries, tr) + ki++ + return nil + }) + + if err != nil { + return nil, nil, fmt.Errorf("hash sort failed: %w", err) + } + + // Folding everything up to the root + for hph.activeRows > 0 { + if err := hph.fold(); err != nil { + return nil, nil, fmt.Errorf("final fold: %w", err) + } + } + + rootHash, err = hph.RootHash() + if err != nil { + return nil, nil, fmt.Errorf("root hash evaluation failed: %w", err) + } + if hph.trace { + fmt.Printf("root hash %x updates %d\n", rootHash, updatesCount) + } + + // merge all individual tries + witnessTrie, err = trie.MergeTries(tries) + if err != nil { + return nil, nil, err + } + + witnessTrieRootHash := witnessTrie.Root() + + fmt.Printf("mergedTrieRootHash = %x\n", witnessTrieRootHash) + + if !bytes.Equal(witnessTrieRootHash, expectedRootHash) { + return nil, nil, fmt.Errorf("root hash mismatch witnessTrieRootHash(%x)!=expectedRootHash(%x)", witnessTrieRootHash, expectedRootHash) + } + + return witnessTrie, rootHash, nil +} + func (hph *HexPatriciaHashed) Process(ctx context.Context, updates *Updates, logPrefix string) (rootHash []byte, err error) { var ( m runtime.MemStats @@ -2126,7 +2614,7 @@ func commonPrefixLen(b1, b2 []byte) int { // nolint // Hashes provided key and expands resulting hash into nibbles (each byte split into two nibbles by 4 bits) -func (hph *HexPatriciaHashed) hashAndNibblizeKey(key []byte) []byte { +func (hph *HexPatriciaHashed) HashAndNibblizeKey(key []byte) []byte { hashedKey := make([]byte, length.Hash) hph.keccak.Reset() @@ -2151,3 +2639,52 @@ func (hph *HexPatriciaHashed) hashAndNibblizeKey(key []byte) []byte { } return nibblized } + +func nibblize(key []byte) []byte { // nolint:unused + nibblized := make([]byte, len(key)*2) + for i, b := range key { + nibblized[i*2] = (b >> 4) & 0xf + nibblized[i*2+1] = b & 0xf + } + return nibblized +} + +// compactKey takes a slice of nibbles and compacts them into the original byte slice. +// It returns an error if the input contains invalid nibbles (values > 0xF). +func compactKey(nibbles []byte) ([]byte, error) { + // If the number of nibbles is odd, you might decide to handle it differently. + // For this example, we'll return an error. + if len(nibbles)%2 != 0 { + return nil, errors.New("nibbles slice has an odd length") + } + + key := make([]byte, len(nibbles)/2) + for i := 0; i < len(key); i++ { + highNibble := nibbles[i*2] + lowNibble := nibbles[i*2+1] + + // Validate that each nibble is indeed a nibble + if highNibble > 0xF || lowNibble > 0xF { + return nil, fmt.Errorf("invalid nibble at position %d or %d: 0x%X, 0x%X", i*2, i*2+1, highNibble, lowNibble) + } + + key[i] = (highNibble << 4) | (lowNibble & 0x0F) + } + return key, nil +} + +func (hph *HexPatriciaHashed) Grid() [128][16]cell { + return hph.grid +} + +func (hph *HexPatriciaHashed) PrintAccountsInGrid() { + fmt.Printf("SEARCHING FOR ACCOUNTS IN GRID\n") + for row := 0; row < 128; row++ { + for col := 0; col < 16; col++ { + c := hph.grid[row][col] + if c.accountAddr[19] != 0 && c.accountAddr[0] != 0 { + fmt.Printf("FOUND account %x in position (%d,%d)\n", c.accountAddr, row, col) + } + } + } +} diff --git a/erigon-lib/commitment/hex_patricia_hashed_bench_test.go b/erigon-lib/commitment/hex_patricia_hashed_bench_test.go index 3ccba659418..3db0373925c 100644 --- a/erigon-lib/commitment/hex_patricia_hashed_bench_test.go +++ b/erigon-lib/commitment/hex_patricia_hashed_bench_test.go @@ -49,7 +49,7 @@ func Benchmark_HexPatriciaHashed_Process(b *testing.B) { require.NoError(b, err) hph := NewHexPatriciaHashed(length.Addr, ms, ms.TempDir()) - upds := WrapKeyUpdates(b, ModeDirect, hph.hashAndNibblizeKey, nil, nil) + upds := WrapKeyUpdates(b, ModeDirect, hph.HashAndNibblizeKey, nil, nil) defer upds.Close() b.ResetTimer() diff --git a/erigon-lib/commitment/hex_patricia_hashed_fuzz_test.go b/erigon-lib/commitment/hex_patricia_hashed_fuzz_test.go index bbc16f9f18f..76d06d2d4cd 100644 --- a/erigon-lib/commitment/hex_patricia_hashed_fuzz_test.go +++ b/erigon-lib/commitment/hex_patricia_hashed_fuzz_test.go @@ -65,13 +65,13 @@ func Fuzz_ProcessUpdate(f *testing.F) { err = ms2.applyPlainUpdates(plainKeys, updates) require.NoError(t, err) - upds := WrapKeyUpdates(t, ModeDirect, hph.hashAndNibblizeKey, nil, nil) + upds := WrapKeyUpdates(t, ModeDirect, hph.HashAndNibblizeKey, nil, nil) rootHashDirect, err := hph.Process(ctx, upds, "") require.NoError(t, err) require.Len(t, rootHashDirect, length.Hash, "invalid root hash length") upds.Close() - anotherUpds := WrapKeyUpdates(t, ModeUpdate, hphAnother.hashAndNibblizeKey, nil, nil) + anotherUpds := WrapKeyUpdates(t, ModeUpdate, hphAnother.HashAndNibblizeKey, nil, nil) rootHashUpdate, err := hphAnother.Process(ctx, anotherUpds, "") require.NoError(t, err) require.Len(t, rootHashUpdate, length.Hash, "invalid root hash length") @@ -149,7 +149,7 @@ func Fuzz_ProcessUpdates_ArbitraryUpdateCount2(f *testing.F) { err := ms.applyPlainUpdates(plainKeys[i:i+1], updates[i:i+1]) require.NoError(t, err) - updsDirect := WrapKeyUpdates(t, ModeDirect, hph.hashAndNibblizeKey, plainKeys[i:i+1], updates[i:i+1]) + updsDirect := WrapKeyUpdates(t, ModeDirect, hph.HashAndNibblizeKey, plainKeys[i:i+1], updates[i:i+1]) rootHashDirect, err := hph.Process(ctx, updsDirect, "") updsDirect.Close() require.NoError(t, err) @@ -158,7 +158,7 @@ func Fuzz_ProcessUpdates_ArbitraryUpdateCount2(f *testing.F) { err = ms2.applyPlainUpdates(plainKeys[i:i+1], updates[i:i+1]) require.NoError(t, err) - upds := WrapKeyUpdates(t, ModeUpdate, hphAnother.hashAndNibblizeKey, plainKeys[i:i+1], updates[i:i+1]) + upds := WrapKeyUpdates(t, ModeUpdate, hphAnother.HashAndNibblizeKey, plainKeys[i:i+1], updates[i:i+1]) rootHashAnother, err := hphAnother.Process(ctx, upds, "") upds.Close() require.NoError(t, err) @@ -213,7 +213,7 @@ func Fuzz_HexPatriciaHashed_ReviewKeys(f *testing.F) { t.Fatal(err) } - upds := WrapKeyUpdates(t, ModeDirect, hph.hashAndNibblizeKey, plainKeys, updates) + upds := WrapKeyUpdates(t, ModeDirect, hph.HashAndNibblizeKey, plainKeys, updates) defer upds.Close() rootHash, err := hph.Process(ctx, upds, "") diff --git a/erigon-lib/commitment/hex_patricia_hashed_test.go b/erigon-lib/commitment/hex_patricia_hashed_test.go index a8a129f818c..e2cc95bed09 100644 --- a/erigon-lib/commitment/hex_patricia_hashed_test.go +++ b/erigon-lib/commitment/hex_patricia_hashed_test.go @@ -53,7 +53,7 @@ func Test_HexPatriciaHashed_ResetThenSingularUpdates(t *testing.T) { Storage("05", "04", "9898"). Build() - upds := WrapKeyUpdates(t, ModeDirect, hph.hashAndNibblizeKey, plainKeys, updates) + upds := WrapKeyUpdates(t, ModeDirect, hph.HashAndNibblizeKey, plainKeys, updates) defer upds.Close() fmt.Printf("1. Generated %d updates\n", len(updates)) @@ -121,7 +121,7 @@ func Test_HexPatriciaHashed_EmptyUpdate(t *testing.T) { err := ms.applyPlainUpdates(plainKeys, updates) require.NoError(t, err) - upds := WrapKeyUpdates(t, ModeDirect, hph.hashAndNibblizeKey, plainKeys, updates) + upds := WrapKeyUpdates(t, ModeDirect, hph.HashAndNibblizeKey, plainKeys, updates) defer upds.Close() hashBeforeEmptyUpdate, err := hph.Process(ctx, upds, "") @@ -174,7 +174,7 @@ func Test_HexPatriciaHashed_UniqueRepresentation2(t *testing.T) { err := msOne.applyPlainUpdates(plainKeys[i:i+1], updates[i:i+1]) require.NoError(t, err) - updsOne := WrapKeyUpdates(t, ModeDirect, trieOne.hashAndNibblizeKey, plainKeys[i:i+1], updates[i:i+1]) + updsOne := WrapKeyUpdates(t, ModeDirect, trieOne.HashAndNibblizeKey, plainKeys[i:i+1], updates[i:i+1]) sequentialRoot, err := trieOne.Process(ctx, updsOne, "") require.NoError(t, err) @@ -189,7 +189,7 @@ func Test_HexPatriciaHashed_UniqueRepresentation2(t *testing.T) { err := msTwo.applyPlainUpdates(plainKeys, updates) require.NoError(t, err) - updsTwo := WrapKeyUpdates(t, ModeDirect, trieTwo.hashAndNibblizeKey, plainKeys, updates) + updsTwo := WrapKeyUpdates(t, ModeDirect, trieTwo.HashAndNibblizeKey, plainKeys, updates) fmt.Printf("\n2. Trie batch update (%d updates)\n", len(updates)) rh, err := trieTwo.Process(ctx, updsTwo, "") @@ -215,7 +215,7 @@ func Test_HexPatriciaHashed_UniqueRepresentation2(t *testing.T) { err := msOne.applyPlainUpdates(plainKeys[i:i+1], updates[i:i+1]) require.NoError(t, err) - updsOne := WrapKeyUpdates(t, ModeDirect, trieOne.hashAndNibblizeKey, plainKeys[i:i+1], updates[i:i+1]) + updsOne := WrapKeyUpdates(t, ModeDirect, trieOne.HashAndNibblizeKey, plainKeys[i:i+1], updates[i:i+1]) sequentialRoot, err := trieOne.Process(ctx, updsOne, "") require.NoError(t, err) @@ -231,7 +231,7 @@ func Test_HexPatriciaHashed_UniqueRepresentation2(t *testing.T) { err := msTwo.applyPlainUpdates(plainKeys, updates) require.NoError(t, err) - updsTwo := WrapKeyUpdates(t, ModeDirect, trieTwo.hashAndNibblizeKey, plainKeys, updates) + updsTwo := WrapKeyUpdates(t, ModeDirect, trieTwo.HashAndNibblizeKey, plainKeys, updates) rh, err := trieTwo.Process(ctx, updsTwo, "") require.NoError(t, err) @@ -249,7 +249,7 @@ func sortUpdatesByHashIncrease(t *testing.T, hph *HexPatriciaHashed, plainKeys [ ku := make([]*KeyUpdate, len(plainKeys)) for i, pk := range plainKeys { - ku[i] = &KeyUpdate{plainKey: string(pk), hashedKey: hph.hashAndNibblizeKey(pk), update: &updates[i]} + ku[i] = &KeyUpdate{plainKey: string(pk), hashedKey: hph.HashAndNibblizeKey(pk), update: &updates[i]} } sort.Slice(updates, func(i, j int) bool { @@ -316,7 +316,7 @@ func Test_HexPatriciaHashed_BrokenUniqueRepr(t *testing.T) { err := stateSeq.applyPlainUpdates(plainKeys[i:i+1], updates[i:i+1]) require.NoError(t, err) - updsOne := WrapKeyUpdates(t, ModeDirect, trieSequential.hashAndNibblizeKey, plainKeys[i:i+1], updates[i:i+1]) + updsOne := WrapKeyUpdates(t, ModeDirect, trieSequential.HashAndNibblizeKey, plainKeys[i:i+1], updates[i:i+1]) sequentialRoot, err := trieSequential.Process(ctx, updsOne, "") require.NoError(t, err) @@ -332,7 +332,7 @@ func Test_HexPatriciaHashed_BrokenUniqueRepr(t *testing.T) { err := stateBatch.applyPlainUpdates(plainKeys, updates) require.NoError(t, err) - updsTwo := WrapKeyUpdates(t, ModeDirect, trieBatch.hashAndNibblizeKey, plainKeys, updates) + updsTwo := WrapKeyUpdates(t, ModeDirect, trieBatch.HashAndNibblizeKey, plainKeys, updates) rh, err := trieBatch.Process(ctx, updsTwo, "") require.NoError(t, err) @@ -399,7 +399,7 @@ func Test_HexPatriciaHashed_UniqueRepresentation(t *testing.T) { err := stateSeq.applyPlainUpdates(plainKeys[i:i+1], updates[i:i+1]) require.NoError(t, err) - updsOne := WrapKeyUpdates(t, ModeDirect, trieSequential.hashAndNibblizeKey, plainKeys[i:i+1], updates[i:i+1]) + updsOne := WrapKeyUpdates(t, ModeDirect, trieSequential.HashAndNibblizeKey, plainKeys[i:i+1], updates[i:i+1]) sequentialRoot, err := trieSequential.Process(ctx, updsOne, "") require.NoError(t, err) @@ -415,7 +415,7 @@ func Test_HexPatriciaHashed_UniqueRepresentation(t *testing.T) { err := stateBatch.applyPlainUpdates(plainKeys, updates) require.NoError(t, err) - updsTwo := WrapKeyUpdates(t, ModeDirect, trieBatch.hashAndNibblizeKey, plainKeys, updates) + updsTwo := WrapKeyUpdates(t, ModeDirect, trieBatch.HashAndNibblizeKey, plainKeys, updates) rh, err := trieBatch.Process(ctx, updsTwo, "") require.NoError(t, err) @@ -485,7 +485,7 @@ func Test_HexPatriciaHashed_Sepolia(t *testing.T) { err := state.applyPlainUpdates(plainKeys, updates) require.NoError(t, err) - upds := WrapKeyUpdates(t, ModeDirect, hph.hashAndNibblizeKey, plainKeys, updates) + upds := WrapKeyUpdates(t, ModeDirect, hph.HashAndNibblizeKey, plainKeys, updates) rootHash, err := hph.Process(ctx, upds, "") require.NoError(t, err) require.EqualValues(t, testData.expectedRoot, fmt.Sprintf("%x", rootHash)) @@ -598,7 +598,7 @@ func Test_HexPatriciaHashed_StateEncodeDecodeSetup(t *testing.T) { err := ms.applyPlainUpdates(plainKeys, updates) require.NoError(t, err) - upds := WrapKeyUpdates(t, ModeDirect, before.hashAndNibblizeKey, plainKeys, updates) + upds := WrapKeyUpdates(t, ModeDirect, before.HashAndNibblizeKey, plainKeys, updates) defer upds.Close() // process updates @@ -659,7 +659,7 @@ func Test_HexPatriciaHashed_StateRestoreAndContinue(t *testing.T) { err = msTwo.applyPlainUpdates(plainKeys, updates) require.NoError(t, err) - updOne := WrapKeyUpdates(t, ModeDirect, trieOne.hashAndNibblizeKey, plainKeys, updates) + updOne := WrapKeyUpdates(t, ModeDirect, trieOne.HashAndNibblizeKey, plainKeys, updates) defer updOne.Close() withoutRestore, err := trieOne.Process(ctx, updOne, "") @@ -717,7 +717,7 @@ func Test_HexPatriciaHashed_StateRestoreAndContinue(t *testing.T) { t.Logf("batch without restore (%d) root %x\n", len(updates), withoutRestore) - updTwo := WrapKeyUpdates(t, ModeDirect, trieTwo.hashAndNibblizeKey, plainKeys, updates) + updTwo := WrapKeyUpdates(t, ModeDirect, trieTwo.HashAndNibblizeKey, plainKeys, updates) defer updTwo.Close() afterRestore, err := trieTwo.Process(ctx, updTwo, "") @@ -758,7 +758,7 @@ func Test_HexPatriciaHashed_RestoreAndContinue(t *testing.T) { err := ms.applyPlainUpdates(plainKeys, updates) require.NoError(t, err) - updTwo := WrapKeyUpdates(t, ModeDirect, trieOne.hashAndNibblizeKey, plainKeys, updates) + updTwo := WrapKeyUpdates(t, ModeDirect, trieOne.HashAndNibblizeKey, plainKeys, updates) defer updTwo.Close() beforeRestore, err := trieTwo.Process(ctx, updTwo, "") @@ -844,7 +844,7 @@ func Test_HexPatriciaHashed_ProcessUpdates_UniqueRepresentation_AfterStateRestor err := stateSeq.applyPlainUpdates(plainKeys[i:i+1], updates[i:i+1]) require.NoError(t, err) - updsOne := WrapKeyUpdates(t, ModeDirect, trieSequential.hashAndNibblizeKey, plainKeys[i:i+1], updates[i:i+1]) + updsOne := WrapKeyUpdates(t, ModeDirect, trieSequential.HashAndNibblizeKey, plainKeys[i:i+1], updates[i:i+1]) sequentialRoot, err := trieSequential.Process(ctx, updsOne, "") require.NoError(t, err) @@ -871,7 +871,7 @@ func Test_HexPatriciaHashed_ProcessUpdates_UniqueRepresentation_AfterStateRestor err := stateBatch.applyPlainUpdates(plainKeys, updates) require.NoError(t, err) - updsTwo := WrapKeyUpdates(t, ModeDirect, trieBatch.hashAndNibblizeKey, plainKeys, updates) + updsTwo := WrapKeyUpdates(t, ModeDirect, trieBatch.HashAndNibblizeKey, plainKeys, updates) rh, err := trieBatch.Process(ctx, updsTwo, "") require.NoError(t, err) @@ -944,7 +944,7 @@ func Test_HexPatriciaHashed_ProcessUpdates_UniqueRepresentationInTheMiddle(t *te err := stateSeq.applyPlainUpdates(plainKeys[i:i+1], updates[i:i+1]) require.NoError(t, err) - updsOne := WrapKeyUpdates(t, ModeDirect, sequential.hashAndNibblizeKey, plainKeys[i:i+1], updates[i:i+1]) + updsOne := WrapKeyUpdates(t, ModeDirect, sequential.HashAndNibblizeKey, plainKeys[i:i+1], updates[i:i+1]) sequentialRoot, err := sequential.Process(ctx, updsOne, "") require.NoError(t, err) @@ -972,7 +972,7 @@ func Test_HexPatriciaHashed_ProcessUpdates_UniqueRepresentationInTheMiddle(t *te err := stateBatch.applyPlainUpdates(plainKeys, updates) require.NoError(t, err) - updsTwo := WrapKeyUpdates(t, ModeDirect, batch.hashAndNibblizeKey, plainKeys[:somewhere+1], updates[:somewhere+1]) + updsTwo := WrapKeyUpdates(t, ModeDirect, batch.HashAndNibblizeKey, plainKeys[:somewhere+1], updates[:somewhere+1]) rh, err := batch.Process(ctx, updsTwo, "") require.NoError(t, err) @@ -1276,7 +1276,7 @@ func Test_HexPatriciaHashed_ProcessWithDozensOfStorageKeys(t *testing.T) { //prefixesCnt := make(map[string]int) //for i := 0; i < 5000000; i++ { // rnd.Read(noise) - // //hashed := trieOne.hashAndNibblizeKey(noise) + // //hashed := trieOne.HashAndNibblizeKey(noise) // trieOne.keccak.Reset() // trieOne.keccak.Write(noise) // hashed := make([]byte, 32) @@ -1310,7 +1310,7 @@ func Test_HexPatriciaHashed_ProcessWithDozensOfStorageKeys(t *testing.T) { err := msOne.applyPlainUpdates(plainKeys[i:i+1], updates[i:i+1]) require.NoError(t, err) - updsOne := WrapKeyUpdates(t, ModeDirect, trieOne.hashAndNibblizeKey, plainKeys[i:i+1], updates[i:i+1]) + updsOne := WrapKeyUpdates(t, ModeDirect, trieOne.HashAndNibblizeKey, plainKeys[i:i+1], updates[i:i+1]) sequentialRoot, err := trieOne.Process(ctx, updsOne, "") require.NoError(t, err) @@ -1325,7 +1325,7 @@ func Test_HexPatriciaHashed_ProcessWithDozensOfStorageKeys(t *testing.T) { err := msTwo.applyPlainUpdates(plainKeys, updates) require.NoError(t, err) - updsTwo := WrapKeyUpdates(t, ModeDirect, trieTwo.hashAndNibblizeKey, plainKeys, updates) + updsTwo := WrapKeyUpdates(t, ModeDirect, trieTwo.HashAndNibblizeKey, plainKeys, updates) fmt.Printf("\n2. Trie batch update (%d updates)\n", len(updates)) rh, err := trieTwo.Process(ctx, updsTwo, "") diff --git a/erigon-lib/go.mod b/erigon-lib/go.mod index 41427eac8fe..3d047f42c5c 100644 --- a/erigon-lib/go.mod +++ b/erigon-lib/go.mod @@ -47,6 +47,7 @@ require ( github.com/spaolacci/murmur3 v1.1.0 github.com/stretchr/testify v1.9.0 github.com/tidwall/btree v1.6.0 + github.com/ugorji/go/codec v1.2.12 go.uber.org/mock v0.5.0 golang.org/x/crypto v0.29.0 golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c diff --git a/erigon-lib/go.sum b/erigon-lib/go.sum index 79ffc1d5467..f1558ed545f 100644 --- a/erigon-lib/go.sum +++ b/erigon-lib/go.sum @@ -476,6 +476,8 @@ github.com/tklauser/go-sysconf v0.3.14 h1:g5vzr9iPFFz24v2KZXs/pvpvh8/V9Fw6vQK5ZZ github.com/tklauser/go-sysconf v0.3.14/go.mod h1:1ym4lWMLUOhuBOPGtRcJm7tEGX4SCYNEEEtghGG/8uY= github.com/tklauser/numcpus v0.8.0 h1:Mx4Wwe/FjZLeQsK/6kt2EOepwwSl7SmJrK5bV/dXYgY= github.com/tklauser/numcpus v0.8.0/go.mod h1:ZJZlAY+dmR4eut8epnzf0u/VwodKmryxR8txiloSqBE= +github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE= +github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= github.com/willf/bitset v1.1.9/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= github.com/willf/bitset v1.1.10/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= diff --git a/erigon-lib/kv/dbutils/composite_keys.go b/erigon-lib/kv/dbutils/composite_keys.go index a98152fb512..611aa8c530d 100644 --- a/erigon-lib/kv/dbutils/composite_keys.go +++ b/erigon-lib/kv/dbutils/composite_keys.go @@ -75,3 +75,116 @@ func GenerateCompositeTrieKey(addressHash libcommon.Hash, seckey libcommon.Hash) compositeKey = append(compositeKey, seckey[:]...) return compositeKey } + +// Address + storageLocationHash +func GenerateStoragePlainKey(address libcommon.Address, storageKey libcommon.Hash) []byte { + storagePlainKey := make([]byte, 0, length.Addr+length.Hash) + storagePlainKey = append(storagePlainKey, address.Bytes()...) + storagePlainKey = append(storagePlainKey, storageKey.Bytes()...) + return storagePlainKey +} + +// AddrHash + incarnation + KeyHash +// For contract storage +func GenerateCompositeStorageKey(addressHash libcommon.Hash, incarnation uint64, seckey libcommon.Hash) []byte { + compositeKey := make([]byte, length.Hash+length.Incarnation+length.Hash) + copy(compositeKey, addressHash[:]) + binary.BigEndian.PutUint64(compositeKey[length.Hash:], incarnation) + copy(compositeKey[length.Hash+length.Incarnation:], seckey[:]) + return compositeKey +} + +func ParseCompositeStorageKey(compositeKey []byte) (libcommon.Hash, uint64, libcommon.Hash) { + prefixLen := length.Hash + length.Incarnation + addrHash, inc := ParseStoragePrefix(compositeKey[:prefixLen]) + var key libcommon.Hash + copy(key[:], compositeKey[prefixLen:prefixLen+length.Hash]) + return addrHash, inc, key +} + +// AddrHash + incarnation + KeyHash +// For contract storage (for plain state) +func PlainGenerateCompositeStorageKey(address []byte, incarnation uint64, key []byte) []byte { + compositeKey := make([]byte, length.Addr+length.Incarnation+length.Hash) + copy(compositeKey, address) + binary.BigEndian.PutUint64(compositeKey[length.Addr:], incarnation) + copy(compositeKey[length.Addr+length.Incarnation:], key) + return compositeKey +} + +func PlainParseCompositeStorageKey(compositeKey []byte) (libcommon.Address, uint64, libcommon.Hash) { + prefixLen := length.Addr + length.Incarnation + addr, inc := PlainParseStoragePrefix(compositeKey[:prefixLen]) + var key libcommon.Hash + copy(key[:], compositeKey[prefixLen:prefixLen+length.Hash]) + return addr, inc, key +} + +// AddrHash + incarnation + StorageHashPrefix +func GenerateCompositeStoragePrefix(addressHash []byte, incarnation uint64, storageHashPrefix []byte) []byte { + key := make([]byte, length.Hash+length.Incarnation+len(storageHashPrefix)) + copy(key, addressHash) + binary.BigEndian.PutUint64(key[length.Hash:], incarnation) + copy(key[length.Hash+length.Incarnation:], storageHashPrefix) + return key +} + +// address hash + incarnation prefix +func GenerateStoragePrefix(addressHash []byte, incarnation uint64) []byte { + prefix := make([]byte, length.Hash+NumberLength) + copy(prefix, addressHash) + binary.BigEndian.PutUint64(prefix[length.Hash:], incarnation) + return prefix +} + +// address hash + incarnation prefix (for plain state) +func PlainGenerateStoragePrefix(address []byte, incarnation uint64) []byte { + prefix := make([]byte, length.Addr+NumberLength) + copy(prefix, address) + binary.BigEndian.PutUint64(prefix[length.Addr:], incarnation) + return prefix +} + +func PlainParseStoragePrefix(prefix []byte) (libcommon.Address, uint64) { + var addr libcommon.Address + copy(addr[:], prefix[:length.Addr]) + inc := binary.BigEndian.Uint64(prefix[length.Addr : length.Addr+length.Incarnation]) + return addr, inc +} + +func ParseStoragePrefix(prefix []byte) (libcommon.Hash, uint64) { + var addrHash libcommon.Hash + copy(addrHash[:], prefix[:length.Hash]) + inc := binary.BigEndian.Uint64(prefix[length.Hash : length.Hash+length.Incarnation]) + return addrHash, inc +} + +// Key + blockNum +func CompositeKeySuffix(key []byte, timestamp uint64) (composite, encodedTS []byte) { + encodedTS = encodeTimestamp(timestamp) + composite = make([]byte, len(key)+len(encodedTS)) + copy(composite, key) + copy(composite[len(key):], encodedTS) + return composite, encodedTS +} + +// encodeTimestamp has the property: if a < b, then Encoding(a) < Encoding(b) lexicographically +func encodeTimestamp(timestamp uint64) []byte { + var suffix []byte + var limit uint64 = 32 + + for bytecount := 1; bytecount <= 8; bytecount++ { + if timestamp < limit { + suffix = make([]byte, bytecount) + b := timestamp + for i := bytecount - 1; i > 0; i-- { + suffix[i] = byte(b & 0xff) + b >>= 8 + } + suffix[0] = byte(b) | (byte(bytecount) << 5) // 3 most significant bits of the first byte are bytecount + break + } + limit <<= 8 + } + return suffix +} diff --git a/erigon-lib/kv/tables.go b/erigon-lib/kv/tables.go index 00a8ab968d0..0d12d2563de 100644 --- a/erigon-lib/kv/tables.go +++ b/erigon-lib/kv/tables.go @@ -60,6 +60,8 @@ const ( ContractCode = "HashedCodeHash" ) +const Witnesses = "witnesses" // block_num_u64 + "_chunk_" + chunk_num_u64 -> witness ( see: docs/programmers_guide/witness_format.md ) + // Mapping [block number] => [Verkle Root] const VerkleRoots = "VerkleRoots" @@ -128,6 +130,8 @@ const ( ConfigTable = "Config" // config prefix for the db + PreimagePrefix = "SecureKey" // preimagePrefix + hash -> preima + // Progress of sync stages: stageName -> stageData SyncStageProgress = "SyncStage" @@ -449,7 +453,6 @@ var ChaindataTables = []string{ ActiveValidatorIndicies, EffectiveBalancesDump, BalancesDump, - AccountChangeSetDeprecated, StorageChangeSetDeprecated, HashedAccountsDeprecated, diff --git a/erigon-lib/state/domain.go b/erigon-lib/state/domain.go index 4e70ed9f71f..328c25d1f0e 100644 --- a/erigon-lib/state/domain.go +++ b/erigon-lib/state/domain.go @@ -1703,7 +1703,8 @@ func (dt *DomainRoTx) statelessBtree(i int) *BtIndex { func (dt *DomainRoTx) valsCursor(tx kv.Tx) (c kv.Cursor, err error) { if dt.valsC != nil { - return dt.valsC, nil + dt.valsC.Close() + dt.valsC = nil } if dt.d.largeValues { diff --git a/erigon-lib/state/domain_shared.go b/erigon-lib/state/domain_shared.go index 6e0793a3966..abd5ee0177a 100644 --- a/erigon-lib/state/domain_shared.go +++ b/erigon-lib/state/domain_shared.go @@ -1294,6 +1294,10 @@ func (sdc *SharedDomainsCommitmentContext) KeysCount() uint64 { return sdc.updates.Size() } +func (sdc *SharedDomainsCommitmentContext) Trie() commitment.Trie { + return sdc.patriciaTrie +} + // TouchPlainKey marks plainKey as updated and applies different fn for different key types // (different behaviour for Code, Account and Storage key modifications). func (sdc *SharedDomainsCommitmentContext) TouchKey(d kv.Domain, key string, val []byte) { diff --git a/erigon-lib/trie/debug.go b/erigon-lib/trie/debug.go index ecc340338c6..85ffa48917c 100644 --- a/erigon-lib/trie/debug.go +++ b/erigon-lib/trie/debug.go @@ -37,11 +37,28 @@ func (*HexStdOutWriter) Write(p []byte) (n int, err error) { return len(p), nil } +func (t *Trie) Print(w io.Writer) { + witness, err := t.ExtractWitness(false, nil) + if err != nil { + panic(err) + } + _, err = witness.WriteInto(w) + if err != nil { + panic(err) + } +} + +func (t *Trie) PrintTrie() { + fmt.Printf("trie:0x") + t.Print(&HexStdOutWriter{}) + fmt.Println("") +} + func (t *Trie) PrintDiff(t2 *Trie, w io.Writer) { - printDiff(t.root, t2.root, w, "", "0x") + printDiff(t.RootNode, t2.RootNode, w, "", "0x") } -func (n *fullNode) fstring(ind string) string { +func (n *FullNode) fstring(ind string) string { resp := fmt.Sprintf("full\n%s ", ind) for i, node := range &n.Children { if node == nil { @@ -52,7 +69,7 @@ func (n *fullNode) fstring(ind string) string { } return resp + "\n" + ind + "]" } -func (n *fullNode) print(w io.Writer) { +func (n *FullNode) print(w io.Writer) { fmt.Fprintf(w, "f(") for i, node := range &n.Children { if node != nil { @@ -63,14 +80,14 @@ func (n *fullNode) print(w io.Writer) { fmt.Fprintf(w, ")") } -func (n *duoNode) fstring(ind string) string { +func (n *DuoNode) fstring(ind string) string { resp := fmt.Sprintf("duo[\n%s ", ind) i1, i2 := n.childrenIdx() resp += fmt.Sprintf("%s: %v", indices[i1], n.child1.fstring(ind+" ")) resp += fmt.Sprintf("%s: %v", indices[i2], n.child2.fstring(ind+" ")) return resp + fmt.Sprintf("\n%s] ", ind) } -func (n *duoNode) print(w io.Writer) { +func (n *DuoNode) print(w io.Writer) { fmt.Fprintf(w, "d(") i1, i2 := n.childrenIdx() fmt.Fprintf(w, "%d:", i1) @@ -80,55 +97,55 @@ func (n *duoNode) print(w io.Writer) { fmt.Fprintf(w, ")") } -func (n *shortNode) fstring(ind string) string { +func (n *ShortNode) fstring(ind string) string { return fmt.Sprintf("{%x: %v} ", n.Key, n.Val.fstring(ind+" ")) } -func (n *shortNode) print(w io.Writer) { +func (n *ShortNode) print(w io.Writer) { fmt.Fprintf(w, "s(%x:", n.Key) n.Val.print(w) fmt.Fprintf(w, ")") } -func (n hashNode) fstring(ind string) string { +func (n HashNode) fstring(ind string) string { return fmt.Sprintf("<%x> ", n.hash) } -func (n hashNode) print(w io.Writer) { +func (n HashNode) print(w io.Writer) { fmt.Fprintf(w, "h(%x)", n.hash) } -func (n valueNode) fstring(ind string) string { +func (n ValueNode) fstring(ind string) string { return fmt.Sprintf("%x ", []byte(n)) } -func (n valueNode) print(w io.Writer) { +func (n ValueNode) print(w io.Writer) { fmt.Fprintf(w, "v(%x)", []byte(n)) } -func (n codeNode) fstring(ind string) string { +func (n CodeNode) fstring(ind string) string { return fmt.Sprintf("code: %x ", []byte(n)) } -func (n codeNode) print(w io.Writer) { +func (n CodeNode) print(w io.Writer) { fmt.Fprintf(w, "code(%x)", []byte(n)) } -func (an accountNode) fstring(ind string) string { +func (an AccountNode) fstring(ind string) string { encodedAccount := make([]byte, an.EncodingLengthForHashing()) an.EncodeForHashing(encodedAccount) - if an.storage == nil { + if an.Storage == nil { return hex.EncodeToString(encodedAccount) } - return hex.EncodeToString(encodedAccount) + " " + an.storage.fstring(ind+" ") + return hex.EncodeToString(encodedAccount) + " " + an.Storage.fstring(ind+" ") } -func (an accountNode) print(w io.Writer) { +func (an AccountNode) print(w io.Writer) { encodedAccount := make([]byte, an.EncodingLengthForHashing()) an.EncodeForHashing(encodedAccount) fmt.Fprintf(w, "v(%x)", encodedAccount) } -func printDiffSide(n node, w io.Writer, ind string, key string) { +func printDiffSide(n Node, w io.Writer, ind string, key string) { switch n := n.(type) { - case *fullNode: + case *FullNode: fmt.Fprintf(w, "full(\n") for i, child := range &n.Children { if child != nil { @@ -138,7 +155,7 @@ func printDiffSide(n node, w io.Writer, ind string, key string) { } } fmt.Fprintf(w, "%s)\n", ind) - case *duoNode: + case *DuoNode: fmt.Fprintf(w, "duo(\n") i1, i2 := n.childrenIdx() fmt.Fprintf(w, "%s%s:", ind, indices[i1]) @@ -148,7 +165,7 @@ func printDiffSide(n node, w io.Writer, ind string, key string) { printDiffSide(n.child2, w, " "+ind, key+indices[i2]) fmt.Fprintf(w, "\n") fmt.Fprintf(w, "%s)\n", ind) - case *shortNode: + case *ShortNode: fmt.Fprintf(w, "short %x(", n.reference()) keyHex := n.Key hexV := make([]byte, len(keyHex)) @@ -159,19 +176,19 @@ func printDiffSide(n node, w io.Writer, ind string, key string) { printDiffSide(n.Val, w, " "+ind, key+string(hexV)) fmt.Fprintf(w, "\n") fmt.Fprintf(w, "%s)\n", ind) - case hashNode: + case HashNode: fmt.Fprintf(w, "hash(%x)", n.hash) - case valueNode: + case ValueNode: fmt.Fprintf(w, "value(%s %x)", key, []byte(n)) - case *accountNode: + case *AccountNode: fmt.Fprintf(w, "account(%s %x)", key, n) } } -func printDiff(n1, n2 node, w io.Writer, ind string, key string) { - if nv1, ok := n1.(valueNode); ok { +func printDiff(n1, n2 Node, w io.Writer, ind string, key string) { + if nv1, ok := n1.(ValueNode); ok { fmt.Fprintf(w, "value(") - if n, ok := n2.(valueNode); ok { + if n, ok := n2.(ValueNode); ok { fmt.Fprintf(w, "%s %x/%x", key, []byte(nv1), []byte(n)) } else { fmt.Fprintf(w, "/%T", n2) @@ -187,9 +204,9 @@ func printDiff(n1, n2 node, w io.Writer, ind string, key string) { return } switch n1 := n1.(type) { - case *fullNode: + case *FullNode: fmt.Fprintf(w, "full(\n") - if n, ok := n2.(*fullNode); ok { + if n, ok := n2.(*FullNode); ok { for i, child := range &n1.Children { child2 := n.Children[i] if child == nil { @@ -211,9 +228,9 @@ func printDiff(n1, n2 node, w io.Writer, ind string, key string) { printDiffSide(n2, w, ind, key) } fmt.Fprintf(w, "%s)\n", ind) - case *duoNode: + case *DuoNode: fmt.Fprintf(w, "duo(\n") - if n, ok := n2.(*duoNode); ok { + if n, ok := n2.(*DuoNode); ok { i1, i2 := n1.childrenIdx() j1, j2 := n.childrenIdx() if i1 == j1 { @@ -235,9 +252,9 @@ func printDiff(n1, n2 node, w io.Writer, ind string, key string) { printDiffSide(n1, w, ind, key) } fmt.Fprintf(w, "%s)\n", ind) - case *shortNode: + case *ShortNode: fmt.Fprintf(w, "short(") - if n, ok := n2.(*shortNode); ok { + if n, ok := n2.(*ShortNode); ok { if bytes.Equal(n1.Key, n.Key) { keyHex := n1.Key hexV := make([]byte, len(keyHex)) @@ -260,9 +277,9 @@ func printDiff(n1, n2 node, w io.Writer, ind string, key string) { printDiffSide(n2, w, ind, key) } fmt.Fprintf(w, "%s)\n", ind) - case hashNode: + case HashNode: fmt.Fprintf(w, "hash(") - if n, ok := n2.(hashNode); ok { + if n, ok := n2.(HashNode); ok { fmt.Fprintf(w, "%x/%x", n1.hash, n.hash) } else { fmt.Fprintf(w, "hash(%x)/%T(%x)\n", n1.hash, n2, n2.reference()) @@ -273,25 +290,25 @@ func printDiff(n1, n2 node, w io.Writer, ind string, key string) { } func (t *Trie) HashOfHexKey(hexKey []byte) (libcommon.Hash, error) { - nd := t.root + nd := t.RootNode pos := 0 var account bool for pos < len(hexKey) || account { switch n := nd.(type) { case nil: return libcommon.Hash{}, fmt.Errorf("premature nil: pos %d, hexKey %x", pos, hexKey) - case *shortNode: + case *ShortNode: matchlen := prefixLen(hexKey[pos:], n.Key) if matchlen == len(n.Key) || n.Key[matchlen] == 16 { nd = n.Val pos += matchlen - if _, ok := n.Val.(*accountNode); ok { + if _, ok := n.Val.(*AccountNode); ok { account = true } } else { return libcommon.Hash{}, fmt.Errorf("too long shortNode key: pos %d, hexKey %x: %s", pos, hexKey, n.fstring("")) } - case *duoNode: + case *DuoNode: i1, i2 := n.childrenIdx() switch hexKey[pos] { case i1: @@ -303,26 +320,26 @@ func (t *Trie) HashOfHexKey(hexKey []byte) (libcommon.Hash, error) { default: return libcommon.Hash{}, fmt.Errorf("nil entry in the duoNode: pos %d, hexKey %x", pos, hexKey) } - case *fullNode: + case *FullNode: child := n.Children[hexKey[pos]] if child == nil { return libcommon.Hash{}, fmt.Errorf("nil entry in the fullNode: pos %d, hexKey %x", pos, hexKey) } nd = child pos++ - case valueNode: + case ValueNode: return libcommon.Hash{}, fmt.Errorf("premature valueNode: pos %d, hexKey %x", pos, hexKey) - case *accountNode: - nd = n.storage + case *AccountNode: + nd = n.Storage account = false - case hashNode: + case HashNode: return libcommon.Hash{}, fmt.Errorf("premature hashNode: pos %d, hexKey %x", pos, hexKey) default: panic(fmt.Sprintf("Unknown node: %T", n)) } } var hash libcommon.Hash - if hn, ok := nd.(hashNode); ok { + if hn, ok := nd.(HashNode); ok { copy(hash[:], hn.hash) } else { h := t.newHasherFunc() diff --git a/erigon-lib/trie/hack.go b/erigon-lib/trie/hack.go index 17ab3ebc308..6eb67eb4470 100644 --- a/erigon-lib/trie/hack.go +++ b/erigon-lib/trie/hack.go @@ -24,7 +24,7 @@ import ( ) func FullNode1() { - f := &fullNode{} + f := &FullNode{} b, err := rlp.EncodeToBytes(f) if err != nil { panic(err) @@ -33,8 +33,8 @@ func FullNode1() { } func FullNode2() { - f := &fullNode{} - f.Children[0] = valueNode(nil) + f := &FullNode{} + f.Children[0] = ValueNode(nil) b, err := rlp.EncodeToBytes(f) if err != nil { panic(err) @@ -43,10 +43,10 @@ func FullNode2() { } func FullNode3() { - f := &fullNode{} - f.Children[0] = valueNode(nil) + f := &FullNode{} + f.Children[0] = ValueNode(nil) h := common.Hash{} - f.Children[1] = hashNode{hash: h[:]} + f.Children[1] = HashNode{hash: h[:]} b, err := rlp.EncodeToBytes(f) if err != nil { panic(err) @@ -55,10 +55,10 @@ func FullNode3() { } func FullNode4() { - f := &fullNode{} + f := &FullNode{} h := common.Hash{} for i := 0; i < 17; i++ { - f.Children[i] = hashNode{hash: h[:]} + f.Children[i] = HashNode{hash: h[:]} } b, err := rlp.EncodeToBytes(f) if err != nil { @@ -68,7 +68,7 @@ func FullNode4() { } func ShortNode1() { - s := NewShortNode([]byte("1"), valueNode("2")) + s := NewShortNode([]byte("1"), ValueNode("2")) b, err := rlp.EncodeToBytes(s) if err != nil { panic(err) @@ -77,7 +77,7 @@ func ShortNode1() { } func ShortNode2() { - s := NewShortNode([]byte("1"), valueNode("123456789012345678901234567890123456789012345678901234567890")) + s := NewShortNode([]byte("1"), ValueNode("123456789012345678901234567890123456789012345678901234567890")) b, err := rlp.EncodeToBytes(s) if err != nil { panic(err) @@ -85,7 +85,7 @@ func ShortNode2() { fmt.Printf("ShortNode2 %x\n", b) } -func hashRoot(n node, title string) { +func hashRoot(n Node, title string) { h := newHasher(false) h1 := newHasher(true) defer returnHasherToPool(h) @@ -93,51 +93,51 @@ func hashRoot(n node, title string) { var hash common.Hash hLen, _ := h.hash(n, true, hash[:]) if hLen < 32 { - panic("expected hashNode") + panic("expected HashNode") } fmt.Printf("%s noencode: %x\n", title, hash[:]) hLen, _ = h1.hash(n, true, hash[:]) if hLen < 32 { - panic("expected hashNode") + panic("expected HashNode") } fmt.Printf("%s encode: %x\n", title, hash[:]) } func Hash1() { - f := &fullNode{} + f := &FullNode{} hashRoot(f, "Hash1") } func Hash2() { - f := &fullNode{} - f.Children[0] = &fullNode{} + f := &FullNode{} + f.Children[0] = &FullNode{} hashRoot(f, "Hash2") } func Hash3() { - s := NewShortNode([]byte("12"), valueNode("1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012")) + s := NewShortNode([]byte("12"), ValueNode("1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012")) hashRoot(s, "Hash3") } func Hash4() { - s := NewShortNode([]byte("12345678901234567890123456789012"), valueNode("12345678901234567890")) + s := NewShortNode([]byte("12345678901234567890123456789012"), ValueNode("12345678901234567890")) hashRoot(s, "Hash4") } func Hash5() { - s := NewShortNode([]byte("1234567890123456789012345678901"), valueNode("1")) + s := NewShortNode([]byte("1234567890123456789012345678901"), ValueNode("1")) hashRoot(s, "Hash5") } func Hash6() { - s := NewShortNode(common.FromHex("080010"), valueNode(common.FromHex("f90129a0bc7bbe9ce39e604900ca736606290650c4c630501a97745a3f21fae5261623df830362c0b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0"))) + s := NewShortNode(common.FromHex("080010"), ValueNode(common.FromHex("f90129a0bc7bbe9ce39e604900ca736606290650c4c630501a97745a3f21fae5261623df830362c0b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0"))) hashRoot(s, "Hash6") } func Hash7() { - d := &duoNode{} - d.child1 = NewShortNode(common.FromHex("0110"), valueNode(common.FromHex("f871820ba5850ba43b7400830186a0942eb08efb9e10d9f56e46938f28c13ecb33f67b158a085c1bad4187cfe90000801ba0a7e45cf38e44d2c39a4b94bae2e14fccde41e3280c57b611d9cb6494fde12fc7a00858adac2ba2381c591978b8404c22981f7141f0aef9c3cab8f93a55efc40acc"))) - d.child2 = NewShortNode(common.FromHex("0010"), valueNode(common.FromHex("fa02368e820276850ba43b7400830f4240947fd85d1fc04087b3d9d1e610410989191c09b97380ba023624847b07e7000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000011af74000000000000000000000000000000000000000000000000000000000000006c0000000000000000000000000000000000000000000000000000000000000073000000000000000000000000000000000000000000000000000000000000006e000000000000000000000000000000000000000000000000000000000000006f00000000000000000000000000000000000000000000000000000000000000740000000000000000000000000000000000000000000000000000000000000061000000000000000000000000000000000000000000000000000000000000007200000000000000000000000000000000000000000000000000000000000000790000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000006e000000000000000000000000000000000000000000000000000000000000006f0000000000000000000000000000000000000000000000000000000000000074000000000000000000000000000000000000000000000000000000000000006100000000000000000000000000000000000000000000000000000000000000720000000000000000000000000000000000000000000000000000000000000069000000000000000000000000000000000000000000000000000000000000007a000000000000000000000000000000000000000000000000000000000000006100000000000000000000000000000000000000000000000000000000000000740000000000000000000000000000000000000000000000000000000000000069000000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000006e000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000660000000000000000000000000000000000000000000000000000000000000069000000000000000000000000000000000000000000000000000000000000006c0000000000000000000000000000000000000000000000000000000000000065000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000350000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000005a0000000000000000000000000000000000000000000000000000000000000044000000000000000000000000000000000000000000000000000000000000009c00000000000000000000000000000000000000000000000000000000000000eb00000000000000000000000000000000000000000000000000000000000000a100000000000000000000000000000000000000000000000000000000000000c1000000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000005d0000000000000000000000000000000000000000000000000000000000000085000000000000000000000000000000000000000000000000000000000000005400000000000000000000000000000000000000000000000000000000000000ce000000000000000000000000000000000000000000000000000000000000009c000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000cc00000000000000000000000000000000000000000000000000000000000000c3000000000000000000000000000000000000000000000000000000000000004900000000000000000000000000000000000000000000000000000000000000f300000000000000000000000000000000000000000000000000000000000000fe000000000000000000000000000000000000000000000000000000000000005f0000000000000000000000000000000000000000000000000000000000000067000000000000000000000000000000000000000000000000000000000000008300000000000000000000000000000000000000000000000000000000000000af000000000000000000000000000000000000000000000000000000000000004900000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000045000000000000000000000000000000000000000000000000000000000000006e00000000000000000000000000000000000000000000000000000000000000bd00000000000000000000000000000000000000000000000000000000000000a2000000000000000000000000000000000000000000000000000000000000007400000000000000000000000000000000000000000000000000000000000000d100000000000000000000000000000000000000000000000000000000000000e400000000000000000000000000000000000000000000000000000000000000af00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000019000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000d900000000000000000000000000000000000000000000000000000000000000d900000000000000000000000000000000000000000000000000000000000000d1000000000000000000000000000000000000000000000000000000000000008800000000000000000000000000000000000000000000000000000000000000d100000000000000000000000000000000000000000000000000000000000000f800000000000000000000000000000000000000000000000000000000000000d700000000000000000000000000000000000000000000000000000000000000740000000000000000000000000000000000000000000000000000000000000049000000000000000000000000000000000000000000000000000000000000008b0000000000000000000000000000000000000000000000000000000000000062000000000000000000000000000000000000000000000000000000000000005f00000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000000b20000000000000000000000000000000000000000000000000000000000000096000000000000000000000000000000000000000000000000000000000000004d000000000000000000000000000000000000000000000000000000000000006a00000000000000000000000000000000000000000000000000000000000000dd00000000000000000000000000000000000000000000000000000000000000ba00000000000000000000000000000000000000000000000000000000000000f400000000000000000000000000000000000000000000000000000000000000ae0000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000003900000000000000000000000000000000000000000000000000000000000000bf000000000000000000000000000000000000000000000000000000000000009d000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000006500000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000000000000000000000000000000000ab0000000000000000000000000000000000000000000000000000000000000099000000000000000000000000000000000000000000000000000000000000004a00000000000000000000000000000000000000000000000000000000000000b400000000000000000000000000000000000000000000000000000000000000ce00000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000009100000000000000000000000000000000000000000000000000000000000000ee00000000000000000000000000000000000000000000000000000000000000830000000000000000000000000000000000000000000000000000000000000029000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ca00000000000000000000000000000000000000000000000000000000000000760000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000004b00000000000000000000000000000000000000000000000000000000000000bc00000000000000000000000000000000000000000000000000000000000000a600000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000049000000000000000000000000000000000000000000000000000000000000008e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000e50000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000b600000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000082000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000b2000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000820000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000009a00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000019000000000000000000000000000000000000000000000000000000000000008b0000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000000d00000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000002a00000000000000000000000000000000000000000000000000000000000000860000000000000000000000000000000000000000000000000000000000000048000000000000000000000000000000000000000000000000000000000000008600000000000000000000000000000000000000000000000000000000000000f7000000000000000000000000000000000000000000000000000000000000000d00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000b00000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000470000000000000000000000000000000000000000000000000000000000000031000000000000000000000000000000000000000000000000000000000000000b0000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000000900000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000005500000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000001300000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000055000000000000000000000000000000000000000000000000000000000000005300000000000000000000000000000000000000000000000000000000000000310000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000550000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000013000000000000000000000000000000000000000000000000000000000000000d00000000000000000000000000000000000000000000000000000000000000470000000000000000000000000000000000000000000000000000000000000065000000000000000000000000000000000000000000000000000000000000006f0000000000000000000000000000000000000000000000000000000000000054000000000000000000000000000000000000000000000000000000000000007200000000000000000000000000000000000000000000000000000000000000750000000000000000000000000000000000000000000000000000000000000073000000000000000000000000000000000000000000000000000000000000007400000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000049000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000063000000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000003100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000005500000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000001300000000000000000000000000000000000000000000000000000000000000170000000000000000000000000000000000000000000000000000000000000052000000000000000000000000000000000000000000000000000000000000006100000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000069000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000000530000000000000000000000000000000000000000000000000000000000000053000000000000000000000000000000000000000000000000000000000000004c00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000053000000000000000000000000000000000000000000000000000000000000004800000000000000000000000000000000000000000000000000000000000000410000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000003500000000000000000000000000000000000000000000000000000000000000360000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004300000000000000000000000000000000000000000000000000000000000000410000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002d0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004700000000000000000000000000000000000000000000000000000000000000330000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000017000000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000003100000000000000000000000000000000000000000000000000000000000000350000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000003200000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000003100000000000000000000000000000000000000000000000000000000000000390000000000000000000000000000000000000000000000000000000000000035000000000000000000000000000000000000000000000000000000000000003700000000000000000000000000000000000000000000000000000000000000310000000000000000000000000000000000000000000000000000000000000038000000000000000000000000000000000000000000000000000000000000005a0000000000000000000000000000000000000000000000000000000000000017000000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000003100000000000000000000000000000000000000000000000000000000000000360000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000003200000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000036000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000360000000000000000000000000000000000000000000000000000000000000034000000000000000000000000000000000000000000000000000000000000003500000000000000000000000000000000000000000000000000000000000000310000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000005a00000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000081000000000000000000000000000000000000000000000000000000000000009300000000000000000000000000000000000000000000000000000000000000310000000000000000000000000000000000000000000000000000000000000013000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000110000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000550000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000b0000000000000000000000000000000000000000000000000000000000000013000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000047000000000000000000000000000000000000000000000000000000000000005400000000000000000000000000000000000000000000000000000000000000390000000000000000000000000000000000000000000000000000000000000038000000000000000000000000000000000000000000000000000000000000003200000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000036000000000000000000000000000000000000000000000000000000000000003200000000000000000000000000000000000000000000000000000000000000360000000000000000000000000000000000000000000000000000000000000039000000000000000000000000000000000000000000000000000000000000003100000000000000000000000000000000000000000000000000000000000000310000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000002f0000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000550000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000001300000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000053000000000000000000000000000000000000000000000000000000000000006500000000000000000000000000000000000000000000000000000000000000650000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000007700000000000000000000000000000000000000000000000000000000000000770000000000000000000000000000000000000000000000000000000000000077000000000000000000000000000000000000000000000000000000000000002e0000000000000000000000000000000000000000000000000000000000000072000000000000000000000000000000000000000000000000000000000000006100000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000069000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000000730000000000000000000000000000000000000000000000000000000000000073000000000000000000000000000000000000000000000000000000000000006c000000000000000000000000000000000000000000000000000000000000002e0000000000000000000000000000000000000000000000000000000000000063000000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000006d000000000000000000000000000000000000000000000000000000000000002f000000000000000000000000000000000000000000000000000000000000007200000000000000000000000000000000000000000000000000000000000000650000000000000000000000000000000000000000000000000000000000000073000000000000000000000000000000000000000000000000000000000000006f00000000000000000000000000000000000000000000000000000000000000750000000000000000000000000000000000000000000000000000000000000072000000000000000000000000000000000000000000000000000000000000006300000000000000000000000000000000000000000000000000000000000000650000000000000000000000000000000000000000000000000000000000000073000000000000000000000000000000000000000000000000000000000000002f0000000000000000000000000000000000000000000000000000000000000063000000000000000000000000000000000000000000000000000000000000007000000000000000000000000000000000000000000000000000000000000000730000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000000000630000000000000000000000000000000000000000000000000000000000000029000000000000000000000000000000000000000000000000000000000000003100000000000000000000000000000000000000000000000000000000000000350000000000000000000000000000000000000000000000000000000000000031000000000000000000000000000000000000000000000000000000000000002f0000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000002d0000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000550000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000001300000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000000000044000000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000006d00000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000069000000000000000000000000000000000000000000000000000000000000006e00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000043000000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000006e00000000000000000000000000000000000000000000000000000000000000740000000000000000000000000000000000000000000000000000000000000072000000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000006c000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000560000000000000000000000000000000000000000000000000000000000000061000000000000000000000000000000000000000000000000000000000000006c0000000000000000000000000000000000000000000000000000000000000069000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000074000000000000000000000000000000000000000000000000000000000000006500000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002d00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000052000000000000000000000000000000000000000000000000000000000000006100000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000069000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000000530000000000000000000000000000000000000000000000000000000000000053000000000000000000000000000000000000000000000000000000000000004c0000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000005200000000000000000000000000000000000000000000000000000000000000290000000000000000000000000000000000000000000000000000000000000031000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000055000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000013000000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000007700000000000000000000000000000000000000000000000000000000000000770000000000000000000000000000000000000000000000000000000000000077000000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000007200000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000063000000000000000000000000000000000000000000000000000000000000006c0000000000000000000000000000000000000000000000000000000000000069000000000000000000000000000000000000000000000000000000000000007a0000000000000000000000000000000000000000000000000000000000000065000000000000000000000000000000000000000000000000000000000000002e0000000000000000000000000000000000000000000000000000000000000069000000000000000000000000000000000000000000000000000000000000007400000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000082000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000000d00000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000002a00000000000000000000000000000000000000000000000000000000000000860000000000000000000000000000000000000000000000000000000000000048000000000000000000000000000000000000000000000000000000000000008600000000000000000000000000000000000000000000000000000000000000f7000000000000000000000000000000000000000000000000000000000000000d00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000820000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000820000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000008200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b70000000000000000000000000000000000000000000000000000000000000075000000000000000000000000000000000000000000000000000000000000006e000000000000000000000000000000000000000000000000000000000000004e000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000660000000000000000000000000000000000000000000000000000000000000097000000000000000000000000000000000000000000000000000000000000009b000000000000000000000000000000000000000000000000000000000000008f000000000000000000000000000000000000000000000000000000000000000b00000000000000000000000000000000000000000000000000000000000000d500000000000000000000000000000000000000000000000000000000000000d60000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000f40000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000ac00000000000000000000000000000000000000000000000000000000000000a8000000000000000000000000000000000000000000000000000000000000003800000000000000000000000000000000000000000000000000000000000000c7000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a900000000000000000000000000000000000000000000000000000000000000f1000000000000000000000000000000000000000000000000000000000000008200000000000000000000000000000000000000000000000000000000000000e100000000000000000000000000000000000000000000000000000000000000a700000000000000000000000000000000000000000000000000000000000000f4000000000000000000000000000000000000000000000000000000000000004c000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004e00000000000000000000000000000000000000000000000000000000000000c100000000000000000000000000000000000000000000000000000000000000f5000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000006600000000000000000000000000000000000000000000000000000000000000f500000000000000000000000000000000000000000000000000000000000000b900000000000000000000000000000000000000000000000000000000000000cf000000000000000000000000000000000000000000000000000000000000009e00000000000000000000000000000000000000000000000000000000000000f500000000000000000000000000000000000000000000000000000000000000ce000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000bd000000000000000000000000000000000000000000000000000000000000008600000000000000000000000000000000000000000000000000000000000000b10000000000000000000000000000000000000000000000000000000000000039000000000000000000000000000000000000000000000000000000000000003c0000000000000000000000000000000000000000000000000000000000000053000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000000a60000000000000000000000000000000000000000000000000000000000000059000000000000000000000000000000000000000000000000000000000000003a000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000dd000000000000000000000000000000000000000000000000000000000000008d000000000000000000000000000000000000000000000000000000000000009d000000000000000000000000000000000000000000000000000000000000002500000000000000000000000000000000000000000000000000000000000000fa000000000000000000000000000000000000000000000000000000000000003a000000000000000000000000000000000000000000000000000000000000008700000000000000000000000000000000000000000000000000000000000000cb00000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000ad000000000000000000000000000000000000000000000000000000000000007e0000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000009400000000000000000000000000000000000000000000000000000000000000620000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000007c00000000000000000000000000000000000000000000000000000000000000ae00000000000000000000000000000000000000000000000000000000000000f2000000000000000000000000000000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000000000b3000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000cb000000000000000000000000000000000000000000000000000000000000009600000000000000000000000000000000000000000000000000000000000000d700000000000000000000000000000000000000000000000000000000000000fb000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000ae000000000000000000000000000000000000000000000000000000000000006b0000000000000000000000000000000000000000000000000000000000000075000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000004800000000000000000000000000000000000000000000000000000000000000f400000000000000000000000000000000000000000000000000000000000000a7000000000000000000000000000000000000000000000000000000000000004a00000000000000000000000000000000000000000000000000000000000000fc00000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000072000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000de0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001c00000000000000000000000000000000000000000000000000000000000000d50000000000000000000000000000000000000000000000000000000000000061000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000000000e300000000000000000000000000000000000000000000000000000000000000de000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000007e00000000000000000000000000000000000000000000000000000000000000a200000000000000000000000000000000000000000000000000000000000000dc00000000000000000000000000000000000000000000000000000000000000e100000000000000000000000000000000000000000000000000000000000000ab00000000000000000000000000000000000000000000000000000000000000be00000000000000000000000000000000000000000000000000000000000000f30000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000099000000000000000000000000000000000000000000000000000000000000007c000000000000000000000000000000000000000000000000000000000000007e000000000000000000000000000000000000000000000000000000000000009f000000000000000000000000000000000000000000000000000000000000007000000000000000000000000000000000000000000000000000000000000000e1000000000000000000000000000000000000000000000000000000000000002b00000000000000000000000000000000000000000000000000000000000000c200000000000000000000000000000000000000000000000000000000000000c800000000000000000000000000000000000000000000000000000000000000f2000000000000000000000000000000000000000000000000000000000000004100000000000000000000000000000000000000000000000000000000000000900000000000000000000000000000000000000000000000000000000000000093000000000000000000000000000000000000000000000000000000000000009c000000000000000000000000000000000000000000000000000000000000000b00000000000000000000000000000000000000000000000000000000000000970000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000f500000000000000000000000000000000000000000000000000000000000000e400000000000000000000000000000000000000000000000000000000000000fe00000000000000000000000000000000000000000000000000000000000000f100000000000000000000000000000000000000000000000000000000000000de000000000000000000000000000000000000000000000000000000000000000b00000000000000000000000000000000000000000000000000000000000000ba000000000000000000000000000000000000000000000000000000000000004d000000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000003100000000000000000000000000000000000000000000000000000000000000770000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000000000000000000000000000000000c700000000000000000000000000000000000000000000000000000000000000ad000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000ca000000000000000000000000000000000000000000000000000000000000007000000000000000000000000000000000000000000000000000000000000000a30000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000008b00000000000000000000000000000000000000000000000000000000000000a900000000000000000000000000000000000000000000000000000000000000d400000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000000e8000000000000000000000000000000000000000000000000000000000000004c000000000000000000000000000000000000000000000000000000000000004c0000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000006700000000000000000000000000000000000000000000000000000000000000d600000000000000000000000000000000000000000000000000000000000000900000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000007000000000000000000000000000000000000000000000000000000000000000df00000000000000000000000000000000000000000000000000000000000000da00000000000000000000000000000000000000000000000000000000000000f4000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000001500000000000000000000000000000000000000000000000000000000000000ef000000000000000000000000000000000000000000000000000000000000002700000000000000000000000000000000000000000000000000000000000000b9000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000e500000000000000000000000000000000000000000000000000000000000000f3000000000000000000000000000000000000000000000000000000000000004d000000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000049000000000000000000000000000000000000000000000000000000000000004f0000000000000000000000000000000000000000000000000000000000000043000000000000000000000000000000000000000000000000000000000000006d000000000000000000000000000000000000000000000000000000000000003900000000000000000000000000000000000000000000000000000000000000cd000000000000000000000000000000000000000000000000000000000000002300000000000000000000000000000000000000000000000000000000000000aa000000000000000000000000000000000000000000000000000000000000005d00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000c100000000000000000000000000000000000000000000000000000000000000cf000000000000000000000000000000000000000000000000000000000000008e0000000000000000000000000000000000000000000000000000000000000076000000000000000000000000000000000000000000000000000000000000000900000000000000000000000000000000000000000000000000000000000000f9000000000000000000000000000000000000000000000000000000000000009b0000000000000000000000000000000000000000000000000000000000000033000000000000000000000000000000000000000000000000000000000000007600000000000000000000000000000000000000000000000000000000000000bb0000000000000000000000000000000000000000000000000000000000000025000000000000000000000000000000000000000000000000000000000000002e00000000000000000000000000000000000000000000000000000000000000bc00000000000000000000000000000000000000000000000000000000000000b3000000000000000000000000000000000000000000000000000000000000009400000000000000000000000000000000000000000000000000000000000000dd00000000000000000000000000000000000000000000000000000000000000a5000000000000000000000000000000000000000000000000000000000000005400000000000000000000000000000000000000000000000000000000000000970000000000000000000000000000000000000000000000000000000000000085000000000000000000000000000000000000000000000000000000000000000f00000000000000000000000000000000000000000000000000000000000000f50000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002d0000000000000000000000000000000000000000000000000000000000000092000000000000000000000000000000000000000000000000000000000000003f00000000000000000000000000000000000000000000000000000000000000ea00000000000000000000000000000000000000000000000000000000000000770000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000007d00000000000000000000000000000000000000000000000000000000000000dc00000000000000000000000000000000000000000000000000000000000000f50000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000008c00000000000000000000000000000000000000000000000000000000000000cb000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000a8000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000003e000000000000000000000000000000000000000000000000000000000000007e000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000036000000000000000000000000000000000000000000000000000000000000005a00000000000000000000000000000000000000000000000000000000000000e4000000000000000000000000000000000000000000000000000000000000008600000000000000000000000000000000000000000000000000000000000000760000000000000000000000000000000000000000000000000000000000000092000000000000000000000000000000000000000000000000000000000000007c00000000000000000000000000000000000000000000000000000000000000cb000000000000000000000000000000000000000000000000000000000000001b00000000000000000000000000000000000000000000000000000000000000c90000000000000000000000000000000000000000000000000000000000000094000000000000000000000000000000000000000000000000000000000000003600000000000000000000000000000000000000000000000000000000000000660000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000006f00000000000000000000000000000000000000000000000000000000000000c8000000000000000000000000000000000000000000000000000000000000007e00000000000000000000000000000000000000000000000000000000000000f200000000000000000000000000000000000000000000000000000000000000e90000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000a300000000000000000000000000000000000000000000000000000000000000820000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000005800000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000082000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000540000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000001f000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000055000000000000000000000000000000000000000000000000000000000000001d000000000000000000000000000000000000000000000000000000000000002300000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000c3000000000000000000000000000000000000000000000000000000000000009c00000000000000000000000000000000000000000000000000000000000000f300000000000000000000000000000000000000000000000000000000000000fc00000000000000000000000000000000000000000000000000000000000000d300000000000000000000000000000000000000000000000000000000000000460000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000003400000000000000000000000000000000000000000000000000000000000000bb00000000000000000000000000000000000000000000000000000000000000ce0000000000000000000000000000000000000000000000000000000000000046000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000007c000000000000000000000000000000000000000000000000000000000000005b00000000000000000000000000000000000000000000000000000000000000f300000000000000000000000000000000000000000000000000000000000000e2000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000cb00000000000000000000000000000000000000000000000000000000000000590000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000005700000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002b00000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000007000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000004b000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000490000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000001f00000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002b0000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000008600000000000000000000000000000000000000000000000000000000000000130000000000000000000000000000000000000000000000000000000000000068000000000000000000000000000000000000000000000000000000000000007400000000000000000000000000000000000000000000000000000000000000740000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000003a000000000000000000000000000000000000000000000000000000000000002f000000000000000000000000000000000000000000000000000000000000002f00000000000000000000000000000000000000000000000000000000000000670000000000000000000000000000000000000000000000000000000000000076000000000000000000000000000000000000000000000000000000000000002e00000000000000000000000000000000000000000000000000000000000000730000000000000000000000000000000000000000000000000000000000000079000000000000000000000000000000000000000000000000000000000000006d00000000000000000000000000000000000000000000000000000000000000630000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000000000000000000000000000000000002e0000000000000000000000000000000000000000000000000000000000000063000000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000006d0000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002b00000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000007000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000086000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000000068000000000000000000000000000000000000000000000000000000000000007400000000000000000000000000000000000000000000000000000000000000740000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000003a000000000000000000000000000000000000000000000000000000000000002f000000000000000000000000000000000000000000000000000000000000002f00000000000000000000000000000000000000000000000000000000000000670000000000000000000000000000000000000000000000000000000000000076000000000000000000000000000000000000000000000000000000000000002e00000000000000000000000000000000000000000000000000000000000000730000000000000000000000000000000000000000000000000000000000000079000000000000000000000000000000000000000000000000000000000000006d00000000000000000000000000000000000000000000000000000000000000630000000000000000000000000000000000000000000000000000000000000062000000000000000000000000000000000000000000000000000000000000002e0000000000000000000000000000000000000000000000000000000000000063000000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000006d000000000000000000000000000000000000000000000000000000000000002f00000000000000000000000000000000000000000000000000000000000000670000000000000000000000000000000000000000000000000000000000000076000000000000000000000000000000000000000000000000000000000000002e0000000000000000000000000000000000000000000000000000000000000063000000000000000000000000000000000000000000000000000000000000007200000000000000000000000000000000000000000000000000000000000000740000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000055000000000000000000000000000000000000000000000000000000000000001d000000000000000000000000000000000000000000000000000000000000000f0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000ff0000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000001d000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000055000000000000000000000000000000000000000000000000000000000000001d0000000000000000000000000000000000000000000000000000000000000025000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002b000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002b000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000027000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000055000000000000000000000000000000000000000000000000000000000000001d0000000000000000000000000000000000000000000000000000000000000011000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000082000000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000007700000000000000000000000000000000000000000000000000000000000000770000000000000000000000000000000000000000000000000000000000000077000000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000007200000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000063000000000000000000000000000000000000000000000000000000000000006c0000000000000000000000000000000000000000000000000000000000000069000000000000000000000000000000000000000000000000000000000000007a0000000000000000000000000000000000000000000000000000000000000065000000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000006900000000000000000000000000000000000000000000000000000000000000740000000000000000000000000000000000000000000000000000000000000082000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000007200000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000063000000000000000000000000000000000000000000000000000000000000006c0000000000000000000000000000000000000000000000000000000000000069000000000000000000000000000000000000000000000000000000000000007a0000000000000000000000000000000000000000000000000000000000000065000000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000006900000000000000000000000000000000000000000000000000000000000000740000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000002b000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000055000000000000000000000000000000000000000000000000000000000000001d000000000000000000000000000000000000000000000000000000000000001f00000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001c0000000000000000000000000000000000000000000000000000000000000086000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000000068000000000000000000000000000000000000000000000000000000000000007400000000000000000000000000000000000000000000000000000000000000740000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000003a000000000000000000000000000000000000000000000000000000000000002f000000000000000000000000000000000000000000000000000000000000002f00000000000000000000000000000000000000000000000000000000000000670000000000000000000000000000000000000000000000000000000000000076000000000000000000000000000000000000000000000000000000000000002e00000000000000000000000000000000000000000000000000000000000000730000000000000000000000000000000000000000000000000000000000000079000000000000000000000000000000000000000000000000000000000000006d00000000000000000000000000000000000000000000000000000000000000630000000000000000000000000000000000000000000000000000000000000062000000000000000000000000000000000000000000000000000000000000002e0000000000000000000000000000000000000000000000000000000000000063000000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000006d000000000000000000000000000000000000000000000000000000000000002f00000000000000000000000000000000000000000000000000000000000000670000000000000000000000000000000000000000000000000000000000000076000000000000000000000000000000000000000000000000000000000000002e00000000000000000000000000000000000000000000000000000000000000630000000000000000000000000000000000000000000000000000000000000072000000000000000000000000000000000000000000000000000000000000006c0000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000055000000000000000000000000000000000000000000000000000000000000001d00000000000000000000000000000000000000000000000000000000000000130000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000ff000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000045000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000055000000000000000000000000000000000000000000000000000000000000001d00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000003e0000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000003c0000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000003a0000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000008600000000000000000000000000000000000000000000000000000000000000480000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000008600000000000000000000000000000000000000000000000000000000000000f800000000000000000000000000000000000000000000000000000000000000450000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000360000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000002c0000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000002a00000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002b00000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000007000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000680000000000000000000000000000000000000000000000000000000000000074000000000000000000000000000000000000000000000000000000000000007400000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000073000000000000000000000000000000000000000000000000000000000000003a000000000000000000000000000000000000000000000000000000000000002f000000000000000000000000000000000000000000000000000000000000002f000000000000000000000000000000000000000000000000000000000000007700000000000000000000000000000000000000000000000000000000000000770000000000000000000000000000000000000000000000000000000000000077000000000000000000000000000000000000000000000000000000000000002e0000000000000000000000000000000000000000000000000000000000000072000000000000000000000000000000000000000000000000000000000000006100000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000069000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000000730000000000000000000000000000000000000000000000000000000000000073000000000000000000000000000000000000000000000000000000000000006c000000000000000000000000000000000000000000000000000000000000002e0000000000000000000000000000000000000000000000000000000000000063000000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000006d000000000000000000000000000000000000000000000000000000000000002f000000000000000000000000000000000000000000000000000000000000006c000000000000000000000000000000000000000000000000000000000000006500000000000000000000000000000000000000000000000000000000000000670000000000000000000000000000000000000000000000000000000000000061000000000000000000000000000000000000000000000000000000000000006c0000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000000d00000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000002a00000000000000000000000000000000000000000000000000000000000000860000000000000000000000000000000000000000000000000000000000000048000000000000000000000000000000000000000000000000000000000000008600000000000000000000000000000000000000000000000000000000000000f7000000000000000000000000000000000000000000000000000000000000000d00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000b0000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000082000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005100000000000000000000000000000000000000000000000000000000000000b600000000000000000000000000000000000000000000000000000000000000ab000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000240000000000000000000000000000000000000000000000000000000000000047000000000000000000000000000000000000000000000000000000000000005500000000000000000000000000000000000000000000000000000000000000b40000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000007c000000000000000000000000000000000000000000000000000000000000006a00000000000000000000000000000000000000000000000000000000000000c500000000000000000000000000000000000000000000000000000000000000da00000000000000000000000000000000000000000000000000000000000000f100000000000000000000000000000000000000000000000000000000000000d100000000000000000000000000000000000000000000000000000000000000f6000000000000000000000000000000000000000000000000000000000000001500000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000003d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f3000000000000000000000000000000000000000000000000000000000000004300000000000000000000000000000000000000000000000000000000000000c800000000000000000000000000000000000000000000000000000000000000bb0000000000000000000000000000000000000000000000000000000000000092000000000000000000000000000000000000000000000000000000000000009f00000000000000000000000000000000000000000000000000000000000000e90000000000000000000000000000000000000000000000000000000000000015000000000000000000000000000000000000000000000000000000000000005100000000000000000000000000000000000000000000000000000000000000bd000000000000000000000000000000000000000000000000000000000000009100000000000000000000000000000000000000000000000000000000000000a4000000000000000000000000000000000000000000000000000000000000008600000000000000000000000000000000000000000000000000000000000000b20000000000000000000000000000000000000000000000000000000000000039000000000000000000000000000000000000000000000000000000000000004d000000000000000000000000000000000000000000000000000000000000008a000000000000000000000000000000000000000000000000000000000000004200000000000000000000000000000000000000000000000000000000000000ba000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000370000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000005a00000000000000000000000000000000000000000000000000000000000000f00000000000000000000000000000000000000000000000000000000000000027000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000590000000000000000000000000000000000000000000000000000000000000092000000000000000000000000000000000000000000000000000000000000009d00000000000000000000000000000000000000000000000000000000000000bf000000000000000000000000000000000000000000000000000000000000001900000000000000000000000000000000000000000000000000000000000000a400000000000000000000000000000000000000000000000000000000000000d600000000000000000000000000000000000000000000000000000000000000da0000000000000000000000000000000000000000000000000000000000000048000000000000000000000000000000000000000000000000000000000000008d00000000000000000000000000000000000000000000000000000000000000c900000000000000000000000000000000000000000000000000000000000000f10000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000008600000000000000000000000000000000000000000000000000000000000000bf0000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000ac000000000000000000000000000000000000000000000000000000000000004600000000000000000000000000000000000000000000000000000000000000fe000000000000000000000000000000000000000000000000000000000000003300000000000000000000000000000000000000000000000000000000000000db00000000000000000000000000000000000000000000000000000000000000f00000000000000000000000000000000000000000000000000000000000000043000000000000000000000000000000000000000000000000000000000000008400000000000000000000000000000000000000000000000000000000000000f200000000000000000000000000000000000000000000000000000000000000fd00000000000000000000000000000000000000000000000000000000000000cd00000000000000000000000000000000000000000000000000000000000000bb000000000000000000000000000000000000000000000000000000000000004800000000000000000000000000000000000000000000000000000000000000a900000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000002b000000000000000000000000000000000000000000000000000000000000003e000000000000000000000000000000000000000000000000000000000000004e0000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000004f000000000000000000000000000000000000000000000000000000000000003400000000000000000000000000000000000000000000000000000000000000db0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000950000000000000000000000000000000000000000000000000000000000000085000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000fe00000000000000000000000000000000000000000000000000000000000000df000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000590000000000000000000000000000000000000000000000000000000000000013000000000000000000000000000000000000000000000000000000000000007d00000000000000000000000000000000000000000000000000000000000000430000000000000000000000000000000000000000000000000000000000000035000000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000005f000000000000000000000000000000000000000000000000000000000000002b00000000000000000000000000000000000000000000000000000000000000a4000000000000000000000000000000000000000000000000000000000000008200000000000000000000000000000000000000000000000000000000000000490000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000009300000000000000000000000000000000000000000000000000000000000000a500000000000000000000000000000000000000000000000000000000000000f80000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000ca00000000000000000000000000000000000000000000000000000000000000d200000000000000000000000000000000000000000000000000000000000000c50000000000000000000000000000000000000000000000000000000000000074000000000000000000000000000000000000000000000000000000000000009c00000000000000000000000000000000000000000000000000000000000000b6000000000000000000000000000000000000000000000000000000000000009f00000000000000000000000000000000000000000000000000000000000000dc00000000000000000000000000000000000000000000000000000000000000ea0000000000000000000000000000000000000000000000000000000000000025000000000000000000000000000000000000000000000000000000000000003d00000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000093000000000000000000000000000000000000000000000000000000000000003f00000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000069000000000000000000000000000000000000000000000000000000000000007100000000000000000000000000000000000000000000000000000000000000b600000000000000000000000000000000000000000000000000000000000000e70000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000008b00000000000000000000000000000000000000000000000000000000000000840000000000000000000000000000000000000000000000000000000000000063000000000000000000000000000000000000000000000000000000000000004b000000000000000000000000000000000000000000000000000000000000007500000000000000000000000000000000000000000000000000000000000000ab000000000000000000000000000000000000000000000000000000000000003200000000000000000000000000000000000000000000000000000000000000910000000000000000000000000000000000000000000000000000000000000067000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000d6000000000000000000000000000000000000000000000000000000000000003300000000000000000000000000000000000000000000000000000000000000f700000000000000000000000000000000000000000000000000000000000000ca000000000000000000000000000000000000000000000000000000000000008900000000000000000000000000000000000000000000000000000000000000b3000000000000000000000000000000000000000000000000000000000000004600000000000000000000000000000000000000000000000000000000000000a60000000000000000000000000000000000000000000000000000000000000017000000000000000000000000000000000000000000000000000000000000009e000000000000000000000000000000000000000000000000000000000000001b000000000000000000000000000000000000000000000000000000000000006c000000000000000000000000000000000000000000000000000000000000008b000000000000000000000000000000000000000000000000000000000000000d00000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000023000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000720000000000000000000000000000000000000000000000000000000000000094000000000000000000000000000000000000000000000000000000000000009b00000000000000000000000000000000000000000000000000000000000000ac00000000000000000000000000000000000000000000000000000000000000d60000000000000000000000000000000000000000000000000000000000000071000000000000000000000000000000000000000000000000000000000000005300000000000000000000000000000000000000000000000000000000000000810000000000000000000000000000000000000000000000000000000000000033000000000000000000000000000000000000000000000000000000000000007d000000000000000000000000000000000000000000000000000000000000002f000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000b8000000000000000000000000000000000000000000000000000000000000007800000000000000000000000000000000000000000000000000000000000000e4000000000000000000000000000000000000000000000000000000000000008a000000000000000000000000000000000000000000000000000000000000001500000000000000000000000000000000000000000000000000000000000000c50000000000000000000000000000000000000000000000000000000000000065000000000000000000000000000000000000000000000000000000000000004a00000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000034000000000000000000000000000000000000000000000000000000000000007900000000000000000000000000000000000000000000000000000000000000df000000000000000000000000000000000000000000000000000000000000003e000000000000000000000000000000000000000000000000000000000000008f00000000000000000000000000000000000000000000000000000000000000c400000000000000000000000000000000000000000000000000000000000000c200000000000000000000000000000000000000000000000000000000000000b900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000042000000000000000000000000000000000000000000000000000000000000005600000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000b300000000000000000000000000000000000000000000000000000000000000ef00000000000000000000000000000000000000000000000000000000000000eb0000000000000000000000000000000000000000000000000000000000000048000000000000000000000000000000000000000000000000000000000000009d000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000e5000000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000007000000000000000000000000000000000000000000000000000000000000000ea000000000000000000000000000000000000000000000000000000000000003900000000000000000000000000000000000000000000000000000000000000b500000000000000000000000000000000000000000000000000000000000000fc000000000000000000000000000000000000000000000000000000000000004f00000000000000000000000000000000000000000000000000000000000000310000000000000000000000000000000000000000000000000000000000000099000000000000000000000000000000000000000000000000000000000000001900000000000000000000000000000000000000000000000000000000000000b700000000000000000000000000000000000000000000000000000000000000a100000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000000077000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000006b0000000000000000000000000000000000000000000000000000000000000058000000000000000000000000000000000000000000000000000000000000001500000000000000000000000000000000000000000000000000000000000000fd00000000000000000000000000000000000000000000000000000000000000e2000000000000000000000000000000000000000000000000000000000000004600000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000083000000000000000000000000000000000000000000000000000000000000007300000000000000000000000000000000000000000000000000000000000000af000000000000000000000000000000000000000000000000000000000000007800000000000000000000000000000000000000000000000000000000000000c8000000000000000000000000000000000000000000000000000000000000005700000000000000000000000000000000000000000000000000000000000000a100000000000000000000000000000000000000000000000000000000000000fa000000000000000000000000000000000000000000000000000000000000006d0000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000006700000000000000000000000000000000000000000000000000000000000000e900000000000000000000000000000000000000000000000000000000000000b60000000000000000000000000000000000000000000000000000000000000094000000000000000000000000000000000000000000000000000000000000000d0000000000000000000000000000000000000000000000000000000000000017000000000000000000000000000000000000000000000000000000000000007300000000000000000000000000000000000000000000000000000000000000a500000000000000000000000000000000000000000000000000000000000000db000000000000000000000000000000000000000000000000000000000000006f00000000000000000000000000000000000000000000000000000000000000c700000000000000000000000000000000000000000000000000000000000000a7000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000ff000000000000000000000000000000000000000000000000000000000000009d00000000000000000000000000000000000000000000000000000000000000a500000000000000000000000000000000000000000000000000000000000000bd0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000009f00000000000000000000000000000000000000000000000000000000000000dc00000000000000000000000000000000000000000000000000000000000000190000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000290000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000008200000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000025000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000820000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000d00000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000003a00000000000000000000000000000000000000000000000000000000000000770000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000000d00000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000002a00000000000000000000000000000000000000000000000000000000000000860000000000000000000000000000000000000000000000000000000000000048000000000000000000000000000000000000000000000000000000000000008600000000000000000000000000000000000000000000000000000000000000f7000000000000000000000000000000000000000000000000000000000000000d00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000b00000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000031000000000000000000000000000000000000000000000000000000000000000b0000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000000900000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000005500000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000001300000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000055000000000000000000000000000000000000000000000000000000000000005300000000000000000000000000000000000000000000000000000000000000310000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000550000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000013000000000000000000000000000000000000000000000000000000000000000d00000000000000000000000000000000000000000000000000000000000000470000000000000000000000000000000000000000000000000000000000000065000000000000000000000000000000000000000000000000000000000000006f0000000000000000000000000000000000000000000000000000000000000054000000000000000000000000000000000000000000000000000000000000007200000000000000000000000000000000000000000000000000000000000000750000000000000000000000000000000000000000000000000000000000000073000000000000000000000000000000000000000000000000000000000000007400000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000049000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000063000000000000000000000000000000000000000000000000000000000000002e0000000000000000000000000000000000000000000000000000000000000031000000000000000000000000000000000000000000000000000000000000001b00000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000019000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000055000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000013000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000470000000000000000000000000000000000000000000000000000000000000065000000000000000000000000000000000000000000000000000000000000006f0000000000000000000000000000000000000000000000000000000000000054000000000000000000000000000000000000000000000000000000000000007200000000000000000000000000000000000000000000000000000000000000750000000000000000000000000000000000000000000000000000000000000073000000000000000000000000000000000000000000000000000000000000007400000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000047000000000000000000000000000000000000000000000000000000000000006c000000000000000000000000000000000000000000000000000000000000006f00000000000000000000000000000000000000000000000000000000000000620000000000000000000000000000000000000000000000000000000000000061000000000000000000000000000000000000000000000000000000000000006c0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004300000000000000000000000000000000000000000000000000000000000000410000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000017000000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000003100000000000000000000000000000000000000000000000000000000000000340000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000003800000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000039000000000000000000000000000000000000000000000000000000000000003200000000000000000000000000000000000000000000000000000000000000310000000000000000000000000000000000000000000000000000000000000033000000000000000000000000000000000000000000000000000000000000003900000000000000000000000000000000000000000000000000000000000000330000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000005a0000000000000000000000000000000000000000000000000000000000000017000000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000003200000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000003500000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000003200000000000000000000000000000000000000000000000000000000000000310000000000000000000000000000000000000000000000000000000000000033000000000000000000000000000000000000000000000000000000000000003900000000000000000000000000000000000000000000000000000000000000330000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000005a000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000470000000000000000000000000000000000000000000000000000000000000031000000000000000000000000000000000000000000000000000000000000000b0000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000000900000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000005500000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000001300000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000055000000000000000000000000000000000000000000000000000000000000005300000000000000000000000000000000000000000000000000000000000000310000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000550000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000013000000000000000000000000000000000000000000000000000000000000000d00000000000000000000000000000000000000000000000000000000000000470000000000000000000000000000000000000000000000000000000000000065000000000000000000000000000000000000000000000000000000000000006f0000000000000000000000000000000000000000000000000000000000000054000000000000000000000000000000000000000000000000000000000000007200000000000000000000000000000000000000000000000000000000000000750000000000000000000000000000000000000000000000000000000000000073000000000000000000000000000000000000000000000000000000000000007400000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000049000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000063000000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000003100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000005500000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000001300000000000000000000000000000000000000000000000000000000000000170000000000000000000000000000000000000000000000000000000000000052000000000000000000000000000000000000000000000000000000000000006100000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000069000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000000530000000000000000000000000000000000000000000000000000000000000053000000000000000000000000000000000000000000000000000000000000004c00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000053000000000000000000000000000000000000000000000000000000000000004800000000000000000000000000000000000000000000000000000000000000410000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000003500000000000000000000000000000000000000000000000000000000000000360000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004300000000000000000000000000000000000000000000000000000000000000410000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002d00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000047000000000000000000000000000000000000000000000000000000000000003300000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000082000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000000d00000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000002a00000000000000000000000000000000000000000000000000000000000000860000000000000000000000000000000000000000000000000000000000000048000000000000000000000000000000000000000000000000000000000000008600000000000000000000000000000000000000000000000000000000000000f7000000000000000000000000000000000000000000000000000000000000000d00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000820000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000820000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000008200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000af0000000000000000000000000000000000000000000000000000000000000054000000000000000000000000000000000000000000000000000000000000009b00000000000000000000000000000000000000000000000000000000000000d90000000000000000000000000000000000000000000000000000000000000058000000000000000000000000000000000000000000000000000000000000005d000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000005600000000000000000000000000000000000000000000000000000000000000c600000000000000000000000000000000000000000000000000000000000000d500000000000000000000000000000000000000000000000000000000000000e8000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000f4000000000000000000000000000000000000000000000000000000000000007d0000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000ff00000000000000000000000000000000000000000000000000000000000000d0000000000000000000000000000000000000000000000000000000000000008b000000000000000000000000000000000000000000000000000000000000005a00000000000000000000000000000000000000000000000000000000000000e4000000000000000000000000000000000000000000000000000000000000008e00000000000000000000000000000000000000000000000000000000000000a700000000000000000000000000000000000000000000000000000000000000dd0000000000000000000000000000000000000000000000000000000000000054000000000000000000000000000000000000000000000000000000000000002e00000000000000000000000000000000000000000000000000000000000000d4000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000005d0000000000000000000000000000000000000000000000000000000000000098000000000000000000000000000000000000000000000000000000000000009c000000000000000000000000000000000000000000000000000000000000008d0000000000000000000000000000000000000000000000000000000000000090000000000000000000000000000000000000000000000000000000000000000f00000000000000000000000000000000000000000000000000000000000000bc00000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000065000000000000000000000000000000000000000000000000000000000000005f00000000000000000000000000000000000000000000000000000000000000da000000000000000000000000000000000000000000000000000000000000009a00000000000000000000000000000000000000000000000000000000000000d60000000000000000000000000000000000000000000000000000000000000044000000000000000000000000000000000000000000000000000000000000007c00000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000009f00000000000000000000000000000000000000000000000000000000000000b500000000000000000000000000000000000000000000000000000000000000e9000000000000000000000000000000000000000000000000000000000000004a000000000000000000000000000000000000000000000000000000000000008c000000000000000000000000000000000000000000000000000000000000000b00000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000043000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000bb00000000000000000000000000000000000000000000000000000000000000f4000000000000000000000000000000000000000000000000000000000000009600000000000000000000000000000000000000000000000000000000000000e2000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000f600000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000009100000000000000000000000000000000000000000000000000000000000000660000000000000000000000000000000000000000000000000000000000000031000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000c300000000000000000000000000000000000000000000000000000000000000340000000000000000000000000000000000000000000000000000000000000034000000000000000000000000000000000000000000000000000000000000005f000000000000000000000000000000000000000000000000000000000000003f000000000000000000000000000000000000000000000000000000000000003f0000000000000000000000000000000000000000000000000000000000000091000000000000000000000000000000000000000000000000000000000000002f0000000000000000000000000000000000000000000000000000000000000044000000000000000000000000000000000000000000000000000000000000005f00000000000000000000000000000000000000000000000000000000000000dc00000000000000000000000000000000000000000000000000000000000000c7000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000b60000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000009f0000000000000000000000000000000000000000000000000000000000000086000000000000000000000000000000000000000000000000000000000000004b000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000a300000000000000000000000000000000000000000000000000000000000000ff00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000008300000000000000000000000000000000000000000000000000000000000000c300000000000000000000000000000000000000000000000000000000000000d3000000000000000000000000000000000000000000000000000000000000001f0000000000000000000000000000000000000000000000000000000000000069000000000000000000000000000000000000000000000000000000000000005200000000000000000000000000000000000000000000000000000000000000d6000000000000000000000000000000000000000000000000000000000000009d0000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000000000000000000000000000000000000f00000000000000000000000000000000000000000000000000000000000000c9000000000000000000000000000000000000000000000000000000000000008300000000000000000000000000000000000000000000000000000000000000e7000000000000000000000000000000000000000000000000000000000000001b00000000000000000000000000000000000000000000000000000000000000c4000000000000000000000000000000000000000000000000000000000000007000000000000000000000000000000000000000000000000000000000000000ac000000000000000000000000000000000000000000000000000000000000009400000000000000000000000000000000000000000000000000000000000000e700000000000000000000000000000000000000000000000000000000000000c300000000000000000000000000000000000000000000000000000000000000a4000000000000000000000000000000000000000000000000000000000000006a000000000000000000000000000000000000000000000000000000000000002c00000000000000000000000000000000000000000000000000000000000000bd00000000000000000000000000000000000000000000000000000000000000b8000000000000000000000000000000000000000000000000000000000000009e000000000000000000000000000000000000000000000000000000000000006900000000000000000000000000000000000000000000000000000000000000d800000000000000000000000000000000000000000000000000000000000000be000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000008f00000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000063000000000000000000000000000000000000000000000000000000000000005a000000000000000000000000000000000000000000000000000000000000006800000000000000000000000000000000000000000000000000000000000000710000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000de0000000000000000000000000000000000000000000000000000000000000015000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000bf00000000000000000000000000000000000000000000000000000000000000cc00000000000000000000000000000000000000000000000000000000000000d300000000000000000000000000000000000000000000000000000000000000bf000000000000000000000000000000000000000000000000000000000000003e000000000000000000000000000000000000000000000000000000000000004800000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000055000000000000000000000000000000000000000000000000000000000000007a00000000000000000000000000000000000000000000000000000000000000b300000000000000000000000000000000000000000000000000000000000000d70000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000fc000000000000000000000000000000000000000000000000000000000000009b00000000000000000000000000000000000000000000000000000000000000fd000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000a7000000000000000000000000000000000000000000000000000000000000008c000000000000000000000000000000000000000000000000000000000000008c00000000000000000000000000000000000000000000000000000000000000db00000000000000000000000000000000000000000000000000000000000000a7000000000000000000000000000000000000000000000000000000000000008e00000000000000000000000000000000000000000000000000000000000000f1000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000006300000000000000000000000000000000000000000000000000000000000000dc00000000000000000000000000000000000000000000000000000000000000b30000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002f000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000af000000000000000000000000000000000000000000000000000000000000005700000000000000000000000000000000000000000000000000000000000000c3000000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000004800000000000000000000000000000000000000000000000000000000000000a700000000000000000000000000000000000000000000000000000000000000830000000000000000000000000000000000000000000000000000000000000068000000000000000000000000000000000000000000000000000000000000002100000000000000000000000000000000000000000000000000000000000000a7000000000000000000000000000000000000000000000000000000000000002f00000000000000000000000000000000000000000000000000000000000000e700000000000000000000000000000000000000000000000000000000000000a7000000000000000000000000000000000000000000000000000000000000003f00000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000000b5000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000fc00000000000000000000000000000000000000000000000000000000000000f5000000000000000000000000000000000000000000000000000000000000008400000000000000000000000000000000000000000000000000000000000000d1000000000000000000000000000000000000000000000000000000000000005300000000000000000000000000000000000000000000000000000000000000bc000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000072000000000000000000000000000000000000000000000000000000000000004f0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000004200000000000000000000000000000000000000000000000000000000000000b8000000000000000000000000000000000000000000000000000000000000009800000000000000000000000000000000000000000000000000000000000000ad00000000000000000000000000000000000000000000000000000000000000190000000000000000000000000000000000000000000000000000000000000088000000000000000000000000000000000000000000000000000000000000005700000000000000000000000000000000000000000000000000000000000000d7000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000ec000000000000000000000000000000000000000000000000000000000000008700000000000000000000000000000000000000000000000000000000000000bf000000000000000000000000000000000000000000000000000000000000007e0000000000000000000000000000000000000000000000000000000000000087000000000000000000000000000000000000000000000000000000000000004e00000000000000000000000000000000000000000000000000000000000000a3000000000000000000000000000000000000000000000000000000000000002100000000000000000000000000000000000000000000000000000000000000f9000000000000000000000000000000000000000000000000000000000000005300000000000000000000000000000000000000000000000000000000000000fd000000000000000000000000000000000000000000000000000000000000003600000000000000000000000000000000000000000000000000000000000000980000000000000000000000000000000000000000000000000000000000000048000000000000000000000000000000000000000000000000000000000000008d00000000000000000000000000000000000000000000000000000000000000d600000000000000000000000000000000000000000000000000000000000000f800000000000000000000000000000000000000000000000000000000000000bb000000000000000000000000000000000000000000000000000000000000004800000000000000000000000000000000000000000000000000000000000000f2000000000000000000000000000000000000000000000000000000000000002900000000000000000000000000000000000000000000000000000000000000c8000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000000d100000000000000000000000000000000000000000000000000000000000000cc000000000000000000000000000000000000000000000000000000000000005400000000000000000000000000000000000000000000000000000000000000480000000000000000000000000000000000000000000000000000000000000053000000000000000000000000000000000000000000000000000000000000008b00000000000000000000000000000000000000000000000000000000000000af00000000000000000000000000000000000000000000000000000000000000b70000000000000000000000000000000000000000000000000000000000000065000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000bf00000000000000000000000000000000000000000000000000000000000000290000000000000000000000000000000000000000000000000000000000000033000000000000000000000000000000000000000000000000000000000000002900000000000000000000000000000000000000000000000000000000000000d900000000000000000000000000000000000000000000000000000000000000290000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000004800000000000000000000000000000000000000000000000000000000000000f800000000000000000000000000000000000000000000000000000000000000ff000000000000000000000000000000000000000000000000000000000000009100000000000000000000000000000000000000000000000000000000000000bc0000000000000000000000000000000000000000000000000000000000000057000000000000000000000000000000000000000000000000000000000000005800000000000000000000000000000000000000000000000000000000000000e50000000000000000000000000000000000000000000000000000000000000035000000000000000000000000000000000000000000000000000000000000002e00000000000000000000000000000000000000000000000000000000000000bb000000000000000000000000000000000000000000000000000000000000006900000000000000000000000000000000000000000000000000000000000000b600000000000000000000000000000000000000000000000000000000000000590000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000a300000000000000000000000000000000000000000000000000000000000000820000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000001d00000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000082000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000190000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000001f000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000055000000000000000000000000000000000000000000000000000000000000001d000000000000000000000000000000000000000000000000000000000000002300000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000007a00000000000000000000000000000000000000000000000000000000000000980000000000000000000000000000000000000000000000000000000000000068000000000000000000000000000000000000000000000000000000000000008d000000000000000000000000000000000000000000000000000000000000008900000000000000000000000000000000000000000000000000000000000000fb00000000000000000000000000000000000000000000000000000000000000ab00000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000011000000000000000000000000000000000000000000000000000000000000007d00000000000000000000000000000000000000000000000000000000000000aa000000000000000000000000000000000000000000000000000000000000007d000000000000000000000000000000000000000000000000000000000000006500000000000000000000000000000000000000000000000000000000000000b800000000000000000000000000000000000000000000000000000000000000ca00000000000000000000000000000000000000000000000000000000000000cc000000000000000000000000000000000000000000000000000000000000004e0000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000001d000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000055000000000000000000000000000000000000000000000000000000000000001d000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000c3000000000000000000000000000000000000000000000000000000000000009c00000000000000000000000000000000000000000000000000000000000000f300000000000000000000000000000000000000000000000000000000000000fc00000000000000000000000000000000000000000000000000000000000000d300000000000000000000000000000000000000000000000000000000000000460000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000003400000000000000000000000000000000000000000000000000000000000000bb00000000000000000000000000000000000000000000000000000000000000ce0000000000000000000000000000000000000000000000000000000000000046000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000007c000000000000000000000000000000000000000000000000000000000000005b00000000000000000000000000000000000000000000000000000000000000f300000000000000000000000000000000000000000000000000000000000000e2000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000cb000000000000000000000000000000000000000000000000000000000000005900000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000055000000000000000000000000000000000000000000000000000000000000001d00000000000000000000000000000000000000000000000000000000000000130000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000ff00000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000ff0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000055000000000000000000000000000000000000000000000000000000000000001d000000000000000000000000000000000000000000000000000000000000000f0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000ff00000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000035000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000055000000000000000000000000000000000000000000000000000000000000001d000000000000000000000000000000000000000000000000000000000000001f0000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000002e0000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000002c0000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000002a00000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000008600000000000000000000000000000000000000000000000000000000000000240000000000000000000000000000000000000000000000000000000000000068000000000000000000000000000000000000000000000000000000000000007400000000000000000000000000000000000000000000000000000000000000740000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000003a000000000000000000000000000000000000000000000000000000000000002f000000000000000000000000000000000000000000000000000000000000002f0000000000000000000000000000000000000000000000000000000000000067000000000000000000000000000000000000000000000000000000000000002e00000000000000000000000000000000000000000000000000000000000000730000000000000000000000000000000000000000000000000000000000000079000000000000000000000000000000000000000000000000000000000000006d00000000000000000000000000000000000000000000000000000000000000630000000000000000000000000000000000000000000000000000000000000062000000000000000000000000000000000000000000000000000000000000002e0000000000000000000000000000000000000000000000000000000000000063000000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000006d000000000000000000000000000000000000000000000000000000000000002f00000000000000000000000000000000000000000000000000000000000000630000000000000000000000000000000000000000000000000000000000000072000000000000000000000000000000000000000000000000000000000000006c0000000000000000000000000000000000000000000000000000000000000073000000000000000000000000000000000000000000000000000000000000002f000000000000000000000000000000000000000000000000000000000000006700000000000000000000000000000000000000000000000000000000000000740000000000000000000000000000000000000000000000000000000000000067000000000000000000000000000000000000000000000000000000000000006c000000000000000000000000000000000000000000000000000000000000006f00000000000000000000000000000000000000000000000000000000000000620000000000000000000000000000000000000000000000000000000000000061000000000000000000000000000000000000000000000000000000000000006c000000000000000000000000000000000000000000000000000000000000002e00000000000000000000000000000000000000000000000000000000000000630000000000000000000000000000000000000000000000000000000000000072000000000000000000000000000000000000000000000000000000000000006c0000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000002e00000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002b000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002b0000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000008600000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000068000000000000000000000000000000000000000000000000000000000000007400000000000000000000000000000000000000000000000000000000000000740000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000003a000000000000000000000000000000000000000000000000000000000000002f000000000000000000000000000000000000000000000000000000000000002f0000000000000000000000000000000000000000000000000000000000000067000000000000000000000000000000000000000000000000000000000000002e00000000000000000000000000000000000000000000000000000000000000730000000000000000000000000000000000000000000000000000000000000079000000000000000000000000000000000000000000000000000000000000006d00000000000000000000000000000000000000000000000000000000000000630000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000000000000000000000000000000000002e0000000000000000000000000000000000000000000000000000000000000063000000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000006d0000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000004c000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000055000000000000000000000000000000000000000000000000000000000000001d00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000004500000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000043000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000410000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000008600000000000000000000000000000000000000000000000000000000000000480000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000008600000000000000000000000000000000000000000000000000000000000000f80000000000000000000000000000000000000000000000000000000000000045000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000036000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000330000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000003100000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002b0000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000250000000000000000000000000000000000000000000000000000000000000068000000000000000000000000000000000000000000000000000000000000007400000000000000000000000000000000000000000000000000000000000000740000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000003a000000000000000000000000000000000000000000000000000000000000002f000000000000000000000000000000000000000000000000000000000000002f000000000000000000000000000000000000000000000000000000000000007700000000000000000000000000000000000000000000000000000000000000770000000000000000000000000000000000000000000000000000000000000077000000000000000000000000000000000000000000000000000000000000002e00000000000000000000000000000000000000000000000000000000000000670000000000000000000000000000000000000000000000000000000000000065000000000000000000000000000000000000000000000000000000000000006f00000000000000000000000000000000000000000000000000000000000000740000000000000000000000000000000000000000000000000000000000000072000000000000000000000000000000000000000000000000000000000000007500000000000000000000000000000000000000000000000000000000000000730000000000000000000000000000000000000000000000000000000000000074000000000000000000000000000000000000000000000000000000000000002e0000000000000000000000000000000000000000000000000000000000000063000000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000006d000000000000000000000000000000000000000000000000000000000000002f000000000000000000000000000000000000000000000000000000000000007200000000000000000000000000000000000000000000000000000000000000650000000000000000000000000000000000000000000000000000000000000073000000000000000000000000000000000000000000000000000000000000006f00000000000000000000000000000000000000000000000000000000000000750000000000000000000000000000000000000000000000000000000000000072000000000000000000000000000000000000000000000000000000000000006300000000000000000000000000000000000000000000000000000000000000650000000000000000000000000000000000000000000000000000000000000073000000000000000000000000000000000000000000000000000000000000002f0000000000000000000000000000000000000000000000000000000000000063000000000000000000000000000000000000000000000000000000000000007000000000000000000000000000000000000000000000000000000000000000730000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000000d00000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000002a00000000000000000000000000000000000000000000000000000000000000860000000000000000000000000000000000000000000000000000000000000048000000000000000000000000000000000000000000000000000000000000008600000000000000000000000000000000000000000000000000000000000000f7000000000000000000000000000000000000000000000000000000000000000d00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000008200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a30000000000000000000000000000000000000000000000000000000000000058000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000c60000000000000000000000000000000000000000000000000000000000000043000000000000000000000000000000000000000000000000000000000000003200000000000000000000000000000000000000000000000000000000000000ac00000000000000000000000000000000000000000000000000000000000000ac000000000000000000000000000000000000000000000000000000000000002f0000000000000000000000000000000000000000000000000000000000000093000000000000000000000000000000000000000000000000000000000000007800000000000000000000000000000000000000000000000000000000000000b700000000000000000000000000000000000000000000000000000000000000ea00000000000000000000000000000000000000000000000000000000000000ae000000000000000000000000000000000000000000000000000000000000005400000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000047000000000000000000000000000000000000000000000000000000000000002d000000000000000000000000000000000000000000000000000000000000007e0000000000000000000000000000000000000000000000000000000000000078000000000000000000000000000000000000000000000000000000000000008d000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000f600000000000000000000000000000000000000000000000000000000000000f8000000000000000000000000000000000000000000000000000000000000006600000000000000000000000000000000000000000000000000000000000000ac00000000000000000000000000000000000000000000000000000000000000d6000000000000000000000000000000000000000000000000000000000000004f000000000000000000000000000000000000000000000000000000000000007300000000000000000000000000000000000000000000000000000000000000d6000000000000000000000000000000000000000000000000000000000000004400000000000000000000000000000000000000000000000000000000000000ef00000000000000000000000000000000000000000000000000000000000000af000000000000000000000000000000000000000000000000000000000000000b00000000000000000000000000000000000000000000000000000000000000cc000000000000000000000000000000000000000000000000000000000000005b00000000000000000000000000000000000000000000000000000000000000c100000000000000000000000000000000000000000000000000000000000000f4000000000000000000000000000000000000000000000000000000000000004f000000000000000000000000000000000000000000000000000000000000009a000000000000000000000000000000000000000000000000000000000000008f0000000000000000000000000000000000000000000000000000000000000049000000000000000000000000000000000000000000000000000000000000007e000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000af00000000000000000000000000000000000000000000000000000000000000c2000000000000000000000000000000000000000000000000000000000000002700000000000000000000000000000000000000000000000000000000000000c7000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000f100000000000000000000000000000000000000000000000000000000000000fb00000000000000000000000000000000000000000000000000000000000000930000000000000000000000000000000000000000000000000000000000000081000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000a9000000000000000000000000000000000000000000000000000000000000007c00000000000000000000000000000000000000000000000000000000000000ef000000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000007e000000000000000000000000000000000000000000000000000000000000006e000000000000000000000000000000000000000000000000000000000000004500000000000000000000000000000000000000000000000000000000000000940000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000008400000000000000000000000000000000000000000000000000000000000000bd00000000000000000000000000000000000000000000000000000000000000ec000000000000000000000000000000000000000000000000000000000000004900000000000000000000000000000000000000000000000000000000000000f100000000000000000000000000000000000000000000000000000000000000c4000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000f400000000000000000000000000000000000000000000000000000000000000af0000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000005900000000000000000000000000000000000000000000000000000000000000830000000000000000000000000000000000000000000000000000000000000087000000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000003b000000000000000000000000000000000000000000000000000000000000009700000000000000000000000000000000000000000000000000000000000000c3000000000000000000000000000000000000000000000000000000000000005a0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000009b000000000000000000000000000000000000000000000000000000000000007b00000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000035000000000000000000000000000000000000000000000000000000000000007b00000000000000000000000000000000000000000000000000000000000000a3000000000000000000000000000000000000000000000000000000000000009500000000000000000000000000000000000000000000000000000000000000330000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000009300000000000000000000000000000000000000000000000000000000000000710000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000004200000000000000000000000000000000000000000000000000000000000000b300000000000000000000000000000000000000000000000000000000000000a900000000000000000000000000000000000000000000000000000000000000d9000000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000004f0000000000000000000000000000000000000000000000000000000000000081000000000000000000000000000000000000000000000000000000000000009200000000000000000000000000000000000000000000000000000000000000fc000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000b6000000000000000000000000000000000000000000000000000000000000007900000000000000000000000000000000000000000000000000000000000000bc0000000000000000000000000000000000000000000000000000000000000084000000000000000000000000000000000000000000000000000000000000004a000000000000000000000000000000000000000000000000000000000000009d0000000000000000000000000000000000000000000000000000000000000077000000000000000000000000000000000000000000000000000000000000000900000000000000000000000000000000000000000000000000000000000000f100000000000000000000000000000000000000000000000000000000000000c5000000000000000000000000000000000000000000000000000000000000008900000000000000000000000000000000000000000000000000000000000000f200000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000000b4000000000000000000000000000000000000000000000000000000000000009c000000000000000000000000000000000000000000000000000000000000005400000000000000000000000000000000000000000000000000000000000000aa0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000000d00000000000000000000000000000000000000000000000000000000000000ba000000000000000000000000000000000000000000000000000000000000004f00000000000000000000000000000000000000000000000000000000000000ef0000000000000000000000000000000000000000000000000000000000000093000000000000000000000000000000000000000000000000000000000000001900000000000000000000000000000000000000000000000000000000000000ec00000000000000000000000000000000000000000000000000000000000000ef000000000000000000000000000000000000000000000000000000000000007d000000000000000000000000000000000000000000000000000000000000004e000000000000000000000000000000000000000000000000000000000000006100000000000000000000000000000000000000000000000000000000000000a3000000000000000000000000000000000000000000000000000000000000008e0000000000000000000000000000000000000000000000000000000000000076000000000000000000000000000000000000000000000000000000000000009c000000000000000000000000000000000000000000000000000000000000005900000000000000000000000000000000000000000000000000000000000000cf000000000000000000000000000000000000000000000000000000000000008c000000000000000000000000000000000000000000000000000000000000009400000000000000000000000000000000000000000000000000000000000000b10000000000000000000000000000000000000000000000000000000000000084000000000000000000000000000000000000000000000000000000000000009700000000000000000000000000000000000000000000000000000000000000f7000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000b9000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000b800000000000000000000000000000000000000000000000000000000000000b200000000000000000000000000000000000000000000000000000000000000c6000000000000000000000000000000000000000000000000000000000000004f0000000000000000000000000000000000000000000000000000000000000013000000000000000000000000000000000000000000000000000000000000007900000000000000000000000000000000000000000000000000000000000000db00000000000000000000000000000000000000000000000000000000000000bf000000000000000000000000000000000000000000000000000000000000004f0000000000000000000000000000000000000000000000000000000000000051000000000000000000000000000000000000000000000000000000000000001b000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000069000000000000000000000000000000000000000000000000000000000000000d0000000000000000000000000000000000000000000000000000000000000051000000000000000000000000000000000000000000000000000000000000002a00000000000000000000000000000000000000000000000000000000000000c100000000000000000000000000000000000000000000000000000000000000d6000000000000000000000000000000000000000000000000000000000000001500000000000000000000000000000000000000000000000000000000000000ff0000000000000000000000000000000000000000000000000000000000000037000000000000000000000000000000000000000000000000000000000000005100000000000000000000000000000000000000000000000000000000000000340000000000000000000000000000000000000000000000000000000000000065000000000000000000000000000000000000000000000000000000000000005100000000000000000000000000000000000000000000000000000000000000f4000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000be0000000000000000000000000000000000000000000000000000000000000038000000000000000000000000000000000000000000000000000000000000006a00000000000000000000000000000000000000000000000000000000000000ec000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000ab00000000000000000000000000000000000000000000000000000000000000bf000000000000000000000000000000000000000000000000000000000000003d000000000000000000000000000000000000000000000000000000000000007b00000000000000000000000000000000000000000000000000000000000000390000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000007b00000000000000000000000000000000000000000000000000000000000000f400000000000000000000000000000000000000000000000000000000000000f300000000000000000000000000000000000000000000000000000000000000fb000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000a100000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000000c8000000000000000000000000000000000000000000000000000000000000007e000000000000000000000000000000000000000000000000000000000000004e0000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000000000000000000000000000000000008d00000000000000000000000000000000000000000000000000000000000000cd000000000000000000000000000000000000000000000000000000000000008c00000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000055000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000fe000000000000000000000000000000000000000000000000000000000000003a00000000000000000000000000000000000000000000000000000000000000ca000000000000000000000000000000000000000000000000000000000000005d0000000000000000000000000000000000000000000000000000000000000025000000000000000000000000000000000000000000000000000000000000000f00000000000000000000000000000000000000000000000000000000000000f8000000000000000000000000000000000000000000000000000000000000001d00000000000000000000000000000000000000000000000000000000000000a3000000000000000000000000000000000000000000000000000000000000004a00000000000000000000000000000000000000000000000000000000000000740000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000004f000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000000055000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000075000000000000000000000000000000000000000000000000000000000000002500000000000000000000000000000000000000000000000000000000000000a60000000000000000000000000000000000000000000000000000000000000033000000000000000000000000000000000000000000000000000000000000002e00000000000000000000000000000000000000000000000000000000000000ba000000000000000000000000000000000000000000000000000000000000004b00000000000000000000000000000000000000000000000000000000000000a5000000000000000000000000000000000000000000000000000000000000005d0000000000000000000000000000000000000000000000000000000000000053000000000000000000000000000000000000000000000000000000000000009a000000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000e1000000000000000000000000000000000000000000000000000000000000008d000000000000000000000000000000000000000000000000000000000000005f0000000000000000000000000000000000000000000000000000000000000061000000000000000000000000000000000000000000000000000000000000002c00000000000000000000000000000000000000000000000000000000000000af00000000000000000000000000000000000000000000000000000000000000cc00000000000000000000000000000000000000000000000000000000000000ef00000000000000000000000000000000000000000000000000000000000000b0000000000000000000000000000000000000000000000000000000000000009900000000000000000000000000000000000000000000000000000000000000a1000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000ff000000000000000000000000000000000000000000000000000000000000000b00000000000000000000000000000000000000000000000000000000000000f20000000000000000000000000000000000000000000000000000000000000062000000000000000000000000000000000000000000000000000000000000004c0000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000980000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000f60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001700000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000f0000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000081000000000000000000000000000000000000000000000000000000000000006b0000000000000000000000000000000000000000000000000000000000000041000000000000000000000000000000000000000000000000000000000000003c00000000000000000000000000000000000000000000000000000000000000540000000000000000000000000000000000000000000000000000000000000069000000000000000000000000000000000000000000000000000000000000009e00000000000000000000000000000000000000000000000000000000000000f800000000000000000000000000000000000000000000000000000000000000a6000000000000000000000000000000000000000000000000000000000000003400000000000000000000000000000000000000000000000000000000000000fe00000000000000000000000000000000000000000000000000000000000000e300000000000000000000000000000000000000000000000000000000000000b00000000000000000000000000000000000000000000000000000000000000036000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000ba000000000000000000000000000000000000000000000000000000000000003800000000000000000000000000000000000000000000000000000000000000cc000000000000000000000000000000000000000000000000000000000000008e00000000000000000000000000000000000000000000000000000000000000ed0000000000000000000000000000000000000000000000000000000000000025000000000000000000000000000000000000000000000000000000000000006700000000000000000000000000000000000000000000000000000000000000a100000000000000000000000000000000000000000000000000000000000000af00000000000000000000000000000000000000000000000000000000000000a400000000000000000000000000000000000000000000000000000000000000fa000000000000000000000000000000000000000000000000000000000000000d00000000000000000000000000000000000000000000000000000000000000c7000000000000000000000000000000000000000000000000000000000000009b000000000000000000000000000000000000000000000000000000000000009c00000000000000000000000000000000000000000000000000000000000000d60000000000000000000000000000000000000000000000000000000000000036000000000000000000000000000000000000000000000000000000000000002c00000000000000000000000000000000000000000000000000000000000000b1000000000000000000000000000000000000000000000000000000000000009600000000000000000000000000000000000000000000000000000000000000c4000000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000007a0000000000000000000000000000000000000000000000000000000000000086000000000000000000000000000000000000000000000000000000000000009500000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000004f0000000000000000000000000000000000000000000000000000000000000078000000000000000000000000000000000000000000000000000000000000003600000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000008600000000000000000000000000000000000000000000000000000000000000ef00000000000000000000000000000000000000000000000000000000000000fa000000000000000000000000000000000000000000000000000000000000006600000000000000000000000000000000000000000000000000000000000000fb00000000000000000000000000000000000000000000000000000000000000af000000000000000000000000000000000000000000000000000000000000001f00000000000000000000000000000000000000000000000000000000000000a3000000000000000000000000000000000000000000000000000000000000004400000000000000000000000000000000000000000000000000000000000000a50000000000000000000000000000000000000000000000000000000000000052000000000000000000000000000000000000000000000000000000000000002f00000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000093000000000000000000000000000000000000000000000000000000000000009e0000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000009c000000000000000000000000000000000000000000000000000000000000001d0000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000009d00000000000000000000000000000000000000000000000000000000000000fc00000000000000000000000000000000000000000000000000000000000000e900000000000000000000000000000000000000000000000000000000000000ae00000000000000000000000000000000000000000000000000000000000000ae00000000000000000000000000000000000000000000000000000000000000f900000000000000000000000000000000000000000000000000000000000000660000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000003600000000000000000000000000000000000000000000000000000000000000ef000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000b700000000000000000000000000000000000000000000000000000000000000a500000000000000000000000000000000000000000000000000000000000000c1000000000000000000000000000000000000000000000000000000000000006700000000000000000000000000000000000000000000000000000000000000f600000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000900000000000000000000000000000000000000000000000000000000000000e1000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000009500000000000000000000000000000000000000000000000000000000000000e3000000000000000000000000000000000000000000000000000000000000009300000000000000000000000000000000000000000000000000000000000000db00000000000000000000000000000000000000000000000000000000000000f400000000000000000000000000000000000000000000000000000000000000e6000000000000000000000000000000000000000000000000000000000000009b000000000000000000000000000000000000000000000000000000000000006c000000000000000000000000000000000000000000000000000000000000006a000000000000000000000000000000000000000000000000000000000000004b0000000000000000000000000000000000000000000000000000000000000055000000000000000000000000000000000000000000000000000000000000004900000000000000000000000000000000000000000000000000000000000000ea000000000000000000000000000000000000000000000000000000000000001b000000000000000000000000000000000000000000000000000000000000004900000000000000000000000000000000000000000000000000000000000000e300000000000000000000000000000000000000000000000000000000000000ec0000000000000000000000000000000000000000000000000000000000000051000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000b600000000000000000000000000000000000000000000000000000000000000b7000000000000000000000000000000000000000000000000000000000000009600000000000000000000000000000000000000000000000000000000000000630000000000000000000000000000000000000000000000000000000000000025000000000000000000000000000000000000000000000000000000000000008a00000000000000000000000000000000000000000000000000000000000000a900000000000000000000000000000000000000000000000000000000000000e6000000000000000000000000000000000000000000000000000000000000005200000000000000000000000000000000000000000000000000000000000000bf000000000000000000000000000000000000000000000000000000000000003b000000000000000000000000000000000000000000000000000000000000003d000000000000000000000000000000000000000000000000000000000000001300000000000000000000000000000000000000000000000000000000000000e7000000000000000000000000000000000000000000000000000000000000002e00000000000000000000000000000000000000000000000000000000000000b9000000000000000000000000000000000000000000000000000000000000003b000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c5000000000000000000000000000000000000000000000000000000000000008e00000000000000000000000000000000000000000000000000000000000000d200000000000000000000000000000000000000000000000000000000000000e100000000000000000000000000000000000000000000000000000000000000a8000000000000000000000000000000000000000000000000000000000000009100000000000000000000000000000000000000000000000000000000000000e200000000000000000000000000000000000000000000000000000000000000c2000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000ec00000000000000000000000000000000000000000000000000000000000000fe000000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000000000000000000000000000000000004b0000000000000000000000000000000000000000000000000000000000000017000000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000001f000000000000000000000000000000000000000000000000000000000000006e000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000ee000000000000000000000000000000000000000000000000000000000000002500000000000000000000000000000000000000000000000000000000000000a500000000000000000000000000000000000000000000000000000000000000ab0000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000007000000000000000000000000000000000000000000000000000000000000000df00000000000000000000000000000000000000000000000000000000000000d5000000000000000000000000000000000000000000000000000000000000007800000000000000000000000000000000000000000000000000000000000000f0000000000000000000000000000000000000000000000000000000000000001f000000000000000000000000000000000000000000000000000000000000005e000000000000000000000000000000000000000000000000000000000000001f00000000000000000000000000000000000000000000000000000000000000f1000000000000000000000000000000000000000000000000000000000000005b0000000000000000000000000000000000000000000000000000000000000097000000000000000000000000000000000000000000000000000000000000006900000000000000000000000000000000000000000000000000000000000000fe0000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a3000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000870000000000000000000000000000000000000000000000000000000000000094000000000000000000000000000000000000000000000000000000000000007700000000000000000000000000000000000000000000000000000000000000df000000000000000000000000000000000000000000000000000000000000004f00000000000000000000000000000000000000000000000000000000000000b1000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000007a00000000000000000000000000000000000000000000000000000000000000e100000000000000000000000000000000000000000000000000000000000000b900000000000000000000000000000000000000000000000000000000000000ce000000000000000000000000000000000000000000000000000000000000006200000000000000000000000000000000000000000000000000000000000000af0000000000000000000000000000000000000000000000000000000000000027000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000005b0000000000000000000000000000000000000000000000000000000000000036000000000000000000000000000000000000000000000000000000000000003e000000000000000000000000000000000000000000000000000000000000004c00000000000000000000000000000000000000000000000000000000000000b80000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000005c000000000000000000000000000000000000000000000000000000000000009900000000000000000000000000000000000000000000000000000000000000c70000000000000000000000000000000000000000000000000000000000000027000000000000000000000000000000000000000000000000000000000000002b000000000000000000000000000000000000000000000000000000000000007300000000000000000000000000000000000000000000000000000000000000b7000000000000000000000000000000000000000000000000000000000000007a00000000000000000000000000000000000000000000000000000000000000a2000000000000000000000000000000000000000000000000000000000000008600000000000000000000000000000000000000000000000000000000000000bd00000000000000000000000000000000000000000000000000000000000000cc00000000000000000000000000000000000000000000000000000000000000ad000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000de000000000000000000000000000000000000000000000000000000000000008a0000000000000000000000000000000000000000000000000000000000000067000000000000000000000000000000000000000000000000000000000000002500000000000000000000000000000000000000000000000000000000000000b7000000000000000000000000000000000000000000000000000000000000007300000000000000000000000000000000000000000000000000000000000000c500000000000000000000000000000000000000000000000000000000000000ff00000000000000000000000000000000000000000000000000000000000000f5000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000a400000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000000ad00000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000090000000000000000000000000000000000000000000000000000000000000008d000000000000000000000000000000000000000000000000000000000000008c000000000000000000000000000000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000000000ce000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000e9000000000000000000000000000000000000000000000000000000000000007b00000000000000000000000000000000000000000000000000000000000000ed000000000000000000000000000000000000000000000000000000000000007700000000000000000000000000000000000000000000000000000000000000f600000000000000000000000000000000000000000000000000000000000000c50000000000000000000000000000000000000000000000000000000000000092000000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000000000000000000000000000000000000900000000000000000000000000000000000000000000000000000000000000da00000000000000000000000000000000000000000000000000000000000000e400000000000000000000000000000000000000000000000000000000000000aa0000000000000000000000000000000000000000000000000000000000000090000000000000000000000000000000000000000000000000000000000000007e00000000000000000000000000000000000000000000000000000000000000ae000000000000000000000000000000000000000000000000000000000000007c0000000000000000000000000000000000000000000000000000000000000095000000000000000000000000000000000000000000000000000000000000009a000000000000000000000000000000000000000000000000000000000000005600000000000000000000000000000000000000000000000000000000000000c200000000000000000000000000000000000000000000000000000000000000760000000000000000000000000000000000000000000000000000000000000013000000000000000000000000000000000000000000000000000000000000004f000000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000000000000000000000000000000000cd000000000000000000000000000000000000000000000000000000000000002900000000000000000000000000000000000000000000000000000000000000520000000000000000000000000000000000000000000000000000000000000023000000000000000000000000000000000000000000000000000000000000005600000000000000000000000000000000000000000000000000000000000000ab000000000000000000000000000000000000000000000000000000000000003a000000000000000000000000000000000000000000000000000000000000002a00000000000000000000000000000000000000000000000000000000000000d4000000000000000000000000000000000000000000000000000000000000005700000000000000000000000000000000000000000000000000000000000000b400000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000000000043000000000000000000000000000000000000000000000000000000000000001d000000000000000000000000000000000000000000000000000000000000004a000000000000000000000000000000000000000000000000000000000000004b000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000021000000000000000000000000000000000000000000000000000000000000006b00000000000000000000000000000000000000000000000000000000000000410000000000000000000000000000000000000000000000000000000000000017000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000e7000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000001c0000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000000000000000000000000000000000006a0000000000000000000000000000000000000000000000000000000000000039000000000000000000000000000000000000000000000000000000000000004100000000000000000000000000000000000000000000000000000000000000a200000000000000000000000000000000000000000000000000000000000000ca00000000000000000000000000000000000000000000000000000000000000a3000000000000000000000000000000000000000000000000000000000000006c00000000000000000000000000000000000000000000000000000000000000bf00000000000000000000000000000000000000000000000000000000000000130000000000000000000000000000000000000000000000000000000000000015000000000000000000000000000000000000000000000000000000000000007100000000000000000000000000000000000000000000000000000000000000dc00000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000094000000000000000000000000000000000000000000000000000000000000009d00000000000000000000000000000000000000000000000000000000000000ea0000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000006700000000000000000000000000000000000000000000000000000000000000a2000000000000000000000000000000000000000000000000000000000000007a000000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000004b000000000000000000000000000000000000000000000000000000000000004800000000000000000000000000000000000000000000000000000000000000ab000000000000000000000000000000000000000000000000000000000000006300000000000000000000000000000000000000000000000000000000000000230000000000000000000000000000000000000000000000000000000000000068000000000000000000000000000000000000000000000000000000000000009e00000000000000000000000000000000000000000000000000000000000000a4000000000000000000000000000000000000000000000000000000000000006d000000000000000000000000000000000000000000000000000000000000006a000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000cf000000000000000000000000000000000000000000000000000000000000004e000000000000000000000000000000000000000000000000000000000000004a00000000000000000000000000000000000000000000000000000000000000c2000000000000000000000000000000000000000000000000000000000000008a0000000000000000000000000000000000000000000000000000000000000095000000000000000000000000000000000000000000000000000000000000001900000000000000000000000000000000000000000000000000000000000000ac0000000000000000000000000000000000000000000000000000000000000017000000000000000000000000000000000000000000000000000000000000003700000000000000000000000000000000000000000000000000000000000000a500000000000000000000000000000000000000000000000000000000000000d700000000000000000000000000000000000000000000000000000000000000a7000000000000000000000000000000000000000000000000000000000000007600000000000000000000000000000000000000000000000000000000000000c1000000000000000000000000000000000000000000000000000000000000005c000000000000000000000000000000000000000000000000000000000000009b0000000000000000000000000000000000000000000000000000000000000081000000000000000000000000000000000000000000000000000000000000007700000000000000000000000000000000000000000000000000000000000000860000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000054000000000000000000000000000000000000000000000000000000000000009a000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000031000000000000000000000000000000000000000000000000000000000000002100000000000000000000000000000000000000000000000000000000000000ab00000000000000000000000000000000000000000000000000000000000000c100000000000000000000000000000000000000000000000000000000000000550000000000000000000000000000000000000000000000000000000000000027000000000000000000000000000000000000000000000000000000000000008b00000000000000000000000000000000000000000000000000000000000000a90000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000006c00000000000000000000000000000000000000000000000000000000000000f2000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000130000000000000000000000000000000000000000000000000000000000000093000000000000000000000000000000000000000000000000000000000000006600000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000000000046000000000000000000000000000000000000000000000000000000000000004c0000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000f6000000000000000000000000000000000000000000000000000000000000005200000000000000000000000000000000000000000000000000000000000000650000000000000000000000000000000000000000000000000000000000000047000000000000000000000000000000000000000000000000000000000000004b000000000000000000000000000000000000000000000000000000000000005a000000000000000000000000000000000000000000000000000000000000008900000000000000000000000000000000000000000000000000000000000000c100000000000000000000000000000000000000000000000000000000000000ba00000000000000000000000000000000000000000000000000000000000000b9000000000000000000000000000000000000000000000000000000000000005f00000000000000000000000000000000000000000000000000000000000000e10000000000000000000000000000000000000000000000000000000000000052000000000000000000000000000000000000000000000000000000000000006e00000000000000000000000000000000000000000000000000000000000000fc000000000000000000000000000000000000000000000000000000000000009800000000000000000000000000000000000000000000000000000000000000c300000000000000000000000000000000000000000000000000000000000000670000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000007b00000000000000000000000000000000000000000000000000000000000000a4000000000000000000000000000000000000000000000000000000000000009300000000000000000000000000000000000000000000000000000000000000c5000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f2000000000000000000000000000000000000000000000000000000000000000b0000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000009e00000000000000000000000000000000000000000000000000000000000000d2000000000000000000000000000000000000000000000000000000000000002500000000000000000000000000000000000000000000000000000000000000ec000000000000000000000000000000000000000000000000000000000000009600000000000000000000000000000000000000000000000000000000000000c600000000000000000000000000000000000000000000000000000000000000ce00000000000000000000000000000000000000000000000000000000000000c90000000000000000000000000000000000000000000000000000000000000098000000000000000000000000000000000000000000000000000000000000009b000000000000000000000000000000000000000000000000000000000000002d00000000000000000000000000000000000000000000000000000000000000c700000000000000000000000000000000000000000000000000000000000000780000000000000000000000000000000000000000000000000000000000000047000000000000000000000000000000000000000000000000000000000000009a0000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000009e00000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000061000000000000000000000000000000000000000000000000000000000000002d000000000000000000000000000000000000000000000000000000000000001b000000000000000000000000000000000000000000000000000000000000003600000000000000000000000000000000000000000000000000000000000000d900000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000cb000000000000000000000000000000000000000000000000000000000000005600000000000000000000000000000000000000000000000000000000000000b9000000000000000000000000000000000000000000000000000000000000002b000000000000000000000000000000000000000000000000000000000000007100000000000000000000000000000000000000000000000000000000000000e400000000000000000000000000000000000000000000000000000000000000a4000000000000000000000000000000000000000000000000000000000000001d00000000000000000000000000000000000000000000000000000000000000a80000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000002a0000000000000000000000000000000000000000000000000000000000000061000000000000000000000000000000000000000000000000000000000000006700000000000000000000000000000000000000000000000000000000000000fa00000000000000000000000000000000000000000000000000000000000000c900000000000000000000000000000000000000000000000000000000000000f300000000000000000000000000000000000000000000000000000000000000f800000000000000000000000000000000000000000000000000000000000000ef000000000000000000000000000000000000000000000000000000000000008e00000000000000000000000000000000000000000000000000000000000000a4000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000003600000000000000000000000000000000000000000000000000000000000000d800000000000000000000000000000000000000000000000000000000000000ca000000000000000000000000000000000000000000000000000000000000003700000000000000000000000000000000000000000000000000000000000000f800000000000000000000000000000000000000000000000000000000000000620000000000000000000000000000000000000000000000000000000000000007000000000000000000000000000000000000000000000000000000000000002d00000000000000000000000000000000000000000000000000000000000000c4000000000000000000000000000000000000000000000000000000000000002100000000000000000000000000000000000000000000000000000000000000d50000000000000000000000000000000000000000000000000000000000000045000000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000003400000000000000000000000000000000000000000000000000000000000000f3000000000000000000000000000000000000000000000000000000000000008b00000000000000000000000000000000000000000000000000000000000000a10000000000000000000000000000000000000000000000000000000000000019000000000000000000000000000000000000000000000000000000000000002300000000000000000000000000000000000000000000000000000000000000d2000000000000000000000000000000000000000000000000000000000000001d00000000000000000000000000000000000000000000000000000000000000a7000000000000000000000000000000000000000000000000000000000000007600000000000000000000000000000000000000000000000000000000000000d200000000000000000000000000000000000000000000000000000000000000130000000000000000000000000000000000000000000000000000000000000041000000000000000000000000000000000000000000000000000000000000002900000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000f5000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000e70000000000000000000000000000000000000000000000000000000000000084000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000005e000000000000000000000000000000000000000000000000000000000000003a00000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000081000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000c1000000000000000000000000000000000000000000000000000000000000009a0000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000004800000000000000000000000000000000000000000000000000000000000000c60000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000005a00000000000000000000000000000000000000000000000000000000000000f900000000000000000000000000000000000000000000000000000000000000cf000000000000000000000000000000000000000000000000000000000000004800000000000000000000000000000000000000000000000000000000000000b3000000000000000000000000000000000000000000000000000000000000007b00000000000000000000000000000000000000000000000000000000000000970000000000000000000000000000000000000000000000000000000000000078000000000000000000000000000000000000000000000000000000000000001900000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000000db000000000000000000000000000000000000000000000000000000000000006a000000000000000000000000000000000000000000000000000000000000006d000000000000000000000000000000000000000000000000000000000000007800000000000000000000000000000000000000000000000000000000000000cd000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000cc000000000000000000000000000000000000000000000000000000000000005d000000000000000000000000000000000000000000000000000000000000002b000000000000000000000000000000000000000000000000000000000000005f00000000000000000000000000000000000000000000000000000000000000c4000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000011000000000000000000000000000000000000000000000000000000000000009500000000000000000000000000000000000000000000000000000000000000bc000000000000000000000000000000000000000000000000000000000000009c0000000000000000000000000000000000000000000000000000000000000046000000000000000000000000000000000000000000000000000000000000000b00000000000000000000000000000000000000000000000000000000000000d4000000000000000000000000000000000000000000000000000000000000009e000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000fc00000000000000000000000000000000000000000000000000000000000000e600000000000000000000000000000000000000000000000000000000000000ed00000000000000000000000000000000000000000000000000000000000000b6000000000000000000000000000000000000000000000000000000000000009400000000000000000000000000000000000000000000000000000000000000930000000000000000000000000000000000000000000000000000000000000047000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000023000000000000000000000000000000000000000000000000000000000000004400000000000000000000000000000000000000000000000000000000000000e700000000000000000000000000000000000000000000000000000000000000bc00000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000031000000000000000000000000000000000000000000000000000000000000009100000000000000000000000000000000000000000000000000000000000000df0000000000000000000000000000000000000000000000000000000000000097000000000000000000000000000000000000000000000000000000000000007700000000000000000000000000000000000000000000000000000000000000aa000000000000000000000000000000000000000000000000000000000000001900000000000000000000000000000000000000000000000000000000000000ae00000000000000000000000000000000000000000000000000000000000000d0000000000000000000000000000000000000000000000000000000000000005f00000000000000000000000000000000000000000000000000000000000000a1000000000000000000000000000000000000000000000000000000000000002e00000000000000000000000000000000000000000000000000000000000000c800000000000000000000000000000000000000000000000000000000000000cd00000000000000000000000000000000000000000000000000000000000000ce00000000000000000000000000000000000000000000000000000000000000b200000000000000000000000000000000000000000000000000000000000000b100000000000000000000000000000000000000000000000000000000000000cb000000000000000000000000000000000000000000000000000000000000002d00000000000000000000000000000000000000000000000000000000000000920000000000000000000000000000000000000000000000000000000000000043000000000000000000000000000000000000000000000000000000000000003f000000000000000000000000000000000000000000000000000000000000005c0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000003b000000000000000000000000000000000000000000000000000000000000007300000000000000000000000000000000000000000000000000000000000000c100000000000000000000000000000000000000000000000000000000000000d10000000000000000000000000000000000000000000000000000000000000038000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000e50000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000000000000000000000000000000000003e00000000000000000000000000000000000000000000000000000000000000b4000000000000000000000000000000000000000000000000000000000000002d0000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000b6000000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000d90000000000000000000000000000000000000000000000000000000000000096000000000000000000000000000000000000000000000000000000000000004400000000000000000000000000000000000000000000000000000000000000a2000000000000000000000000000000000000000000000000000000000000007c000000000000000000000000000000000000000000000000000000000000006100000000000000000000000000000000000000000000000000000000000000ec0000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000005a00000000000000000000000000000000000000000000000000000000000000d90000000000000000000000000000000000000000000000000000000000000095000000000000000000000000000000000000000000000000000000000000008b00000000000000000000000000000000000000000000000000000000000000f3000000000000000000000000000000000000000000000000000000000000005a0000000000000000000000000000000000000000000000000000000000000046000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000085000000000000000000000000000000000000000000000000000000000000007200000000000000000000000000000000000000000000000000000000000000f1000000000000000000000000000000000000000000000000000000000000001f00000000000000000000000000000000000000000000000000000000000000da00000000000000000000000000000000000000000000000000000000000000230000000000000000000000000000000000000000000000000000000000000045000000000000000000000000000000000000000000000000000000000000003f000000000000000000000000000000000000000000000000000000000000009100000000000000000000000000000000000000000000000000000000000000a6000000000000000000000000000000000000000000000000000000000000005f000000000000000000000000000000000000000000000000000000000000005600000000000000000000000000000000000000000000000000000000000000c8000000000000000000000000000000000000000000000000000000000000007900000000000000000000000000000000000000000000000000000000000000c400000000000000000000000000000000000000000000000000000000000000ab000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000f0000000000000000000000000000000000000000000000000000000000000004f00000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000009e0000000000000000000000000000000000000000000000000000000000000067000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000008f00000000000000000000000000000000000000000000000000000000000000df00000000000000000000000000000000000000000000000000000000000000470000000000000000000000000000000000000000000000000000000000000083000000000000000000000000000000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000006e000000000000000000000000000000000000000000000000000000000000007100000000000000000000000000000000000000000000000000000000000000cd000000000000000000000000000000000000000000000000000000000000002a00000000000000000000000000000000000000000000000000000000000000db00000000000000000000000000000000000000000000000000000000000000cf00000000000000000000000000000000000000000000000000000000000000d600000000000000000000000000000000000000000000000000000000000000f2000000000000000000000000000000000000000000000000000000000000006e00000000000000000000000000000000000000000000000000000000000000d90000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000000900000000000000000000000000000000000000000000000000000000000000f6000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000027000000000000000000000000000000000000000000000000000000000000003300000000000000000000000000000000000000000000000000000000000000ff0000000000000000000000000000000000000000000000000000000000000046000000000000000000000000000000000000000000000000000000000000006a000000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000002f00000000000000000000000000000000000000000000000000000000000000460000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005a00000000000000000000000000000000000000000000000000000000000000af00000000000000000000000000000000000000000000000000000000000000a900000000000000000000000000000000000000000000000000000000000000a200000000000000000000000000000000000000000000000000000000000000e8000000000000000000000000000000000000000000000000000000000000005e000000000000000000000000000000000000000000000000000000000000009100000000000000000000000000000000000000000000000000000000000000ac00000000000000000000000000000000000000000000000000000000000000d3000000000000000000000000000000000000000000000000000000000000009b000000000000000000000000000000000000000000000000000000000000000d00000000000000000000000000000000000000000000000000000000000000a1000000000000000000000000000000000000000000000000000000000000002c0000000000000000000000000000000000000000000000000000000000000092000000000000000000000000000000000000000000000000000000000000003100000000000000000000000000000000000000000000000000000000000000e400000000000000000000000000000000000000000000000000000000000000de0000000000000000000000000000000000000000000000000000000000000019000000000000000000000000000000000000000000000000000000000000009f000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000c200000000000000000000000000000000000000000000000000000000000000b2000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000ac00000000000000000000000000000000000000000000000000000000000000ba000000000000000000000000000000000000000000000000000000000000006900000000000000000000000000000000000000000000000000000000000000ff00000000000000000000000000000000000000000000000000000000000000d400000000000000000000000000000000000000000000000000000000000000d700000000000000000000000000000000000000000000000000000000000000cc0000000000000000000000000000000000000000000000000000000000000076000000000000000000000000000000000000000000000000000000000000004c000000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000000d00000000000000000000000000000000000000000000000000000000000000df00000000000000000000000000000000000000000000000000000000000000d500000000000000000000000000000000000000000000000000000000000000a7000000000000000000000000000000000000000000000000000000000000002e00000000000000000000000000000000000000000000000000000000000000d1000000000000000000000000000000000000000000000000000000000000009e00000000000000000000000000000000000000000000000000000000000000b50000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004d000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000f80000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000001700000000000000000000000000000000000000000000000000000000000000a8000000000000000000000000000000000000000000000000000000000000008d0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000009600000000000000000000000000000000000000000000000000000000000000fd000000000000000000000000000000000000000000000000000000000000002c00000000000000000000000000000000000000000000000000000000000000df00000000000000000000000000000000000000000000000000000000000000cb0000000000000000000000000000000000000000000000000000000000000057000000000000000000000000000000000000000000000000000000000000008400000000000000000000000000000000000000000000000000000000000000650000000000000000000000000000000000000000000000000000000000000086000000000000000000000000000000000000000000000000000000000000004e000000000000000000000000000000000000000000000000000000000000007a00000000000000000000000000000000000000000000000000000000000000d8000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000df00000000000000000000000000000000000000000000000000000000000000ae00000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000038000000000000000000000000000000000000000000000000000000000000009e000000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000007d00000000000000000000000000000000000000000000000000000000000000bc0000000000000000000000000000000000000000000000000000000000000036000000000000000000000000000000000000000000000000000000000000006600000000000000000000000000000000000000000000000000000000000000ec00000000000000000000000000000000000000000000000000000000000000f2000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000f900000000000000000000000000000000000000000000000000000000000000fc0000000000000000000000000000000000000000000000000000000000000019000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000e90000000000000000000000000000000000000000000000000000000000000096000000000000000000000000000000000000000000000000000000000000005a0000000000000000000000000000000000000000000000000000000000000084000000000000000000000000000000000000000000000000000000000000002100000000000000000000000000000000000000000000000000000000000000d500000000000000000000000000000000000000000000000000000000000000290000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000002e00000000000000000000000000000000000000000000000000000000000000d2000000000000000000000000000000000000000000000000000000000000003a00000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000073000000000000000000000000000000000000000000000000000000000000002b00000000000000000000000000000000000000000000000000000000000000eb000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000000b00000000000000000000000000000000000000000000000000000000000000c2000000000000000000000000000000000000000000000000000000000000008c0000000000000000000000000000000000000000000000000000000000000017000000000000000000000000000000000000000000000000000000000000000b00000000000000000000000000000000000000000000000000000000000000da000000000000000000000000000000000000000000000000000000000000003a00000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000f600000000000000000000000000000000000000000000000000000000000000fa00000000000000000000000000000000000000000000000000000000000000bd00000000000000000000000000000000000000000000000000000000000000e900000000000000000000000000000000000000000000000000000000000000a9000000000000000000000000000000000000000000000000000000000000005200000000000000000000000000000000000000000000000000000000000000fd00000000000000000000000000000000000000000000000000000000000000b800000000000000000000000000000000000000000000000000000000000000f800000000000000000000000000000000000000000000000000000000000000de000000000000000000000000000000000000000000000000000000000000009e000000000000000000000000000000000000000000000000000000000000001300000000000000000000000000000000000000000000000000000000000000e5000000000000000000000000000000000000000000000000000000000000007a0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001500000000000000000000000000000000000000000000000000000000000000f1000000000000000000000000000000000000000000000000000000000000005d000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000e8000000000000000000000000000000000000000000000000000000000000003500000000000000000000000000000000000000000000000000000000000000c6000000000000000000000000000000000000000000000000000000000000002a00000000000000000000000000000000000000000000000000000000000000f300000000000000000000000000000000000000000000000000000000000000cf000000000000000000000000000000000000000000000000000000000000005f0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000000000000000000000000000000000003f000000000000000000000000000000000000000000000000000000000000000b00000000000000000000000000000000000000000000000000000000000000fb000000000000000000000000000000000000000000000000000000000000009e00000000000000000000000000000000000000000000000000000000000000f4000000000000000000000000000000000000000000000000000000000000001d00000000000000000000000000000000000000000000000000000000000000f5000000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000002500000000000000000000000000000000000000000000000000000000000000db000000000000000000000000000000000000000000000000000000000000007d0000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000007800000000000000000000000000000000000000000000000000000000000000a80000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000009300000000000000000000000000000000000000000000000000000000000000d900000000000000000000000000000000000000000000000000000000000000dc000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001f0000000000000000000000000000000000000000000000000000000000000072000000000000000000000000000000000000000000000000000000000000009f0000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000006d00000000000000000000000000000000000000000000000000000000000000f500000000000000000000000000000000000000000000000000000000000000f5000000000000000000000000000000000000000000000000000000000000004500000000000000000000000000000000000000000000000000000000000000bb00000000000000000000000000000000000000000000000000000000000000bd00000000000000000000000000000000000000000000000000000000000000b20000000000000000000000000000000000000000000000000000000000000059000000000000000000000000000000000000000000000000000000000000008900000000000000000000000000000000000000000000000000000000000000ac000000000000000000000000000000000000000000000000000000000000006f00000000000000000000000000000000000000000000000000000000000000e500000000000000000000000000000000000000000000000000000000000000c8000000000000000000000000000000000000000000000000000000000000005a00000000000000000000000000000000000000000000000000000000000000d400000000000000000000000000000000000000000000000000000000000000e6000000000000000000000000000000000000000000000000000000000000007800000000000000000000000000000000000000000000000000000000000000be00000000000000000000000000000000000000000000000000000000000000850000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000b4000000000000000000000000000000000000000000000000000000000000008d00000000000000000000000000000000000000000000000000000000000000ad000000000000000000000000000000000000000000000000000000000000008100000000000000000000000000000000000000000000000000000000000000bf00000000000000000000000000000000000000000000000000000000000000e5000000000000000000000000000000000000000000000000000000000000005f00000000000000000000000000000000000000000000000000000000000000720000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000000000000000000000000000000000fd000000000000000000000000000000000000000000000000000000000000006e00000000000000000000000000000000000000000000000000000000000000fc000000000000000000000000000000000000000000000000000000000000007e00000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000b0000000000000000000000000000000000000000000000000000000000000047000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000000000000000000000000000000000ed000000000000000000000000000000000000000000000000000000000000003a0000000000000000000000000000000000000000000000000000000000000013000000000000000000000000000000000000000000000000000000000000008a000000000000000000000000000000000000000000000000000000000000008900000000000000000000000000000000000000000000000000000000000000e6000000000000000000000000000000000000000000000000000000000000006c000000000000000000000000000000000000000000000000000000000000004600000000000000000000000000000000000000000000000000000000000000e4000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000007600000000000000000000000000000000000000000000000000000000000000f9000000000000000000000000000000000000000000000000000000000000001f00000000000000000000000000000000000000000000000000000000000000c300000000000000000000000000000000000000000000000000000000000000ec00000000000000000000000000000000000000000000000000000000000000bb00000000000000000000000000000000000000000000000000000000000000380000000000000000000000000000000000000000000000000000000000000067000000000000000000000000000000000000000000000000000000000000005d000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000002f0000000000000000000000000000000000000000000000000000000000000015000000000000000000000000000000000000000000000000000000000000005b0000000000000000000000000000000000000000000000000000000000000015000000000000000000000000000000000000000000000000000000000000005400000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000006a0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002d0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000a800000000000000000000000000000000000000000000000000000000000000e500000000000000000000000000000000000000000000000000000000000000b400000000000000000000000000000000000000000000000000000000000000bc00000000000000000000000000000000000000000000000000000000000000650000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000001b0000000000000000000000000000000000000000000000000000000000000041000000000000000000000000000000000000000000000000000000000000003f00000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000008e00000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000009600000000000000000000000000000000000000000000000000000000000000a20000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000001f000000000000000000000000000000000000000000000000000000000000004f0000000000000000000000000000000000000000000000000000000000000019000000000000000000000000000000000000000000000000000000000000003b000000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000004100000000000000000000000000000000000000000000000000000000000000d90000000000000000000000000000000000000000000000000000000000000054000000000000000000000000000000000000000000000000000000000000007200000000000000000000000000000000000000000000000000000000000000cc00000000000000000000000000000000000000000000000000000000000000f900000000000000000000000000000000000000000000000000000000000000e1000000000000000000000000000000000000000000000000000000000000004600000000000000000000000000000000000000000000000000000000000000ad000000000000000000000000000000000000000000000000000000000000004d00000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000de00000000000000000000000000000000000000000000000000000000000000e4000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000003800000000000000000000000000000000000000000000000000000000000000950000000000000000000000000000000000000000000000000000000000000073000000000000000000000000000000000000000000000000000000000000005c0000000000000000000000000000000000000000000000000000000000000094000000000000000000000000000000000000000000000000000000000000004e000000000000000000000000000000000000000000000000000000000000001f0000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000003a000000000000000000000000000000000000000000000000000000000000002e00000000000000000000000000000000000000000000000000000000000000fa000000000000000000000000000000000000000000000000000000000000001300000000000000000000000000000000000000000000000000000000000000ff00000000000000000000000000000000000000000000000000000000000000350000000000000000000000000000000000000000000000000000000000000071000000000000000000000000000000000000000000000000000000000000002c00000000000000000000000000000000000000000000000000000000000000d900000000000000000000000000000000000000000000000000000000000000ce00000000000000000000000000000000000000000000000000000000000000bb000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000e20000000000000000000000000000000000000000000000000000000000000076000000000000000000000000000000000000000000000000000000000000001f000000000000000000000000000000000000000000000000000000000000005e000000000000000000000000000000000000000000000000000000000000008f00000000000000000000000000000000000000000000000000000000000000fd000000000000000000000000000000000000000000000000000000000000006600000000000000000000000000000000000000000000000000000000000000e500000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000004500000000000000000000000000000000000000000000000000000000000000c100000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000078000000000000000000000000000000000000000000000000000000000000007d00000000000000000000000000000000000000000000000000000000000000a70000000000000000000000000000000000000000000000000000000000000048000000000000000000000000000000000000000000000000000000000000005c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000000000000000000000000000000000005500000000000000000000000000000000000000000000000000000000000000ed00000000000000000000000000000000000000000000000000000000000000290000000000000000000000000000000000000000000000000000000000000061000000000000000000000000000000000000000000000000000000000000005d00000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000000c500000000000000000000000000000000000000000000000000000000000000c4000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000b7000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000a9000000000000000000000000000000000000000000000000000000000000002100000000000000000000000000000000000000000000000000000000000000d7000000000000000000000000000000000000000000000000000000000000009300000000000000000000000000000000000000000000000000000000000000f800000000000000000000000000000000000000000000000000000000000000f70000000000000000000000000000000000000000000000000000000000000011000000000000000000000000000000000000000000000000000000000000001700000000000000000000000000000000000000000000000000000000000000bb00000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000009b000000000000000000000000000000000000000000000000000000000000006a000000000000000000000000000000000000000000000000000000000000005a0000000000000000000000000000000000000000000000000000000000000074000000000000000000000000000000000000000000000000000000000000001f00000000000000000000000000000000000000000000000000000000000000ea000000000000000000000000000000000000000000000000000000000000009a00000000000000000000000000000000000000000000000000000000000000ae000000000000000000000000000000000000000000000000000000000000004c000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000ad00000000000000000000000000000000000000000000000000000000000000a6000000000000000000000000000000000000000000000000000000000000003e00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000006800000000000000000000000000000000000000000000000000000000000000130000000000000000000000000000000000000000000000000000000000000027000000000000000000000000000000000000000000000000000000000000004e00000000000000000000000000000000000000000000000000000000000000ee000000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000006a000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000003100000000000000000000000000000000000000000000000000000000000000e50000000000000000000000000000000000000000000000000000000000000092000000000000000000000000000000000000000000000000000000000000001700000000000000000000000000000000000000000000000000000000000000fb0000000000000000000000000000000000000000000000000000000000000058000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000d100000000000000000000000000000000000000000000000000000000000000e100000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000059000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000a8000000000000000000000000000000000000000000000000000000000000004b000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000bc00000000000000000000000000000000000000000000000000000000000000da000000000000000000000000000000000000000000000000000000000000002b000000000000000000000000000000000000000000000000000000000000004200000000000000000000000000000000000000000000000000000000000000a600000000000000000000000000000000000000000000000000000000000000cf00000000000000000000000000000000000000000000000000000000000000a6000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000008f00000000000000000000000000000000000000000000000000000000000000ad000000000000000000000000000000000000000000000000000000000000008a0000000000000000000000000000000000000000000000000000000000000081000000000000000000000000000000000000000000000000000000000000002b0000000000000000000000000000000000000000000000000000000000000057000000000000000000000000000000000000000000000000000000000000004800000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000059000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000005500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000f00000000000000000000000000000000000000000000000000000000000000ee00000000000000000000000000000000000000000000000000000000000000a7000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000d800000000000000000000000000000000000000000000000000000000000000df0000000000000000000000000000000000000000000000000000000000000089000000000000000000000000000000000000000000000000000000000000001d000000000000000000000000000000000000000000000000000000000000005900000000000000000000000000000000000000000000000000000000000000ab000000000000000000000000000000000000000000000000000000000000009f00000000000000000000000000000000000000000000000000000000000000c600000000000000000000000000000000000000000000000000000000000000ad000000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000d7000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000008e00000000000000000000000000000000000000000000000000000000000000f40000000000000000000000000000000000000000000000000000000000000072000000000000000000000000000000000000000000000000000000000000001700000000000000000000000000000000000000000000000000000000000000cd000000000000000000000000000000000000000000000000000000000000003200000000000000000000000000000000000000000000000000000000000000c400000000000000000000000000000000000000000000000000000000000000fa00000000000000000000000000000000000000000000000000000000000000d400000000000000000000000000000000000000000000000000000000000000150000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000004a00000000000000000000000000000000000000000000000000000000000000f900000000000000000000000000000000000000000000000000000000000000b800000000000000000000000000000000000000000000000000000000000000eb00000000000000000000000000000000000000000000000000000000000000660000000000000000000000000000000000000000000000000000000000000069000000000000000000000000000000000000000000000000000000000000004e00000000000000000000000000000000000000000000000000000000000000250000000000000000000000000000000000000000000000000000000000000087000000000000000000000000000000000000000000000000000000000000006f00000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000003100000000000000000000000000000000000000000000000000000000000000ca000000000000000000000000000000000000000000000000000000000000009f000000000000000000000000000000000000000000000000000000000000008100000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000e800000000000000000000000000000000000000000000000000000000000000dc000000000000000000000000000000000000000000000000000000000000004a00000000000000000000000000000000000000000000000000000000000000f700000000000000000000000000000000000000000000000000000000000000e800000000000000000000000000000000000000000000000000000000000000a8000000000000000000000000000000000000000000000000000000000000006a000000000000000000000000000000000000000000000000000000000000006e00000000000000000000000000000000000000000000000000000000000000f0000000000000000000000000000000000000000000000000000000000000009a00000000000000000000000000000000000000000000000000000000000000bb000000000000000000000000000000000000000000000000000000000000001f00000000000000000000000000000000000000000000000000000000000000ea000000000000000000000000000000000000000000000000000000000000005e00000000000000000000000000000000000000000000000000000000000000cc00000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000000750000000000000000000000000000000000000000000000000000000000000089000000000000000000000000000000000000000000000000000000000000004700000000000000000000000000000000000000000000000000000000000000ca00000000000000000000000000000000000000000000000000000000000000c1000000000000000000000000000000000000000000000000000000000000007900000000000000000000000000000000000000000000000000000000000000a1000000000000000000000000000000000000000000000000000000000000004600000000000000000000000000000000000000000000000000000000000000c20000000000000000000000000000000000000000000000000000000000000042000000000000000000000000000000000000000000000000000000000000001f000000000000000000000000000000000000000000000000000000000000006b00000000000000000000000000000000000000000000000000000000000000410000000000000000000000000000000000000000000000000000000000000043000000000000000000000000000000000000000000000000000000000000009500000000000000000000000000000000000000000000000000000000000000de0000000000000000000000000000000000000000000000000000000000000023000000000000000000000000000000000000000000000000000000000000006f00000000000000000000000000000000000000000000000000000000000000fc0000000000000000000000000000000000000000000000000000000000000095000000000000000000000000000000000000000000000000000000000000007a00000000000000000000000000000000000000000000000000000000000000df000000000000000000000000000000000000000000000000000000000000003f00000000000000000000000000000000000000000000000000000000000000e6000000000000000000000000000000000000000000000000000000000000006e000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000b1000000000000000000000000000000000000000000000000000000000000009a00000000000000000000000000000000000000000000000000000000000000af000000000000000000000000000000000000000000000000000000000000004300000000000000000000000000000000000000000000000000000000000000dd00000000000000000000000000000000000000000000000000000000000000c2000000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001700000000000000000000000000000000000000000000000000000000000000a2000000000000000000000000000000000000000000000000000000000000004d000000000000000000000000000000000000000000000000000000000000002e0000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000004400000000000000000000000000000000000000000000000000000000000000f800000000000000000000000000000000000000000000000000000000000000bd0000000000000000000000000000000000000000000000000000000000000065000000000000000000000000000000000000000000000000000000000000005200000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000005e000000000000000000000000000000000000000000000000000000000000006300000000000000000000000000000000000000000000000000000000000000d5000000000000000000000000000000000000000000000000000000000000005e00000000000000000000000000000000000000000000000000000000000000e90000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000004b000000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000002a0000000000000000000000000000000000000000000000000000000000000062000000000000000000000000000000000000000000000000000000000000003100000000000000000000000000000000000000000000000000000000000000f3000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000d800000000000000000000000000000000000000000000000000000000000000540000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000006300000000000000000000000000000000000000000000000000000000000000b300000000000000000000000000000000000000000000000000000000000000b5000000000000000000000000000000000000000000000000000000000000007d0000000000000000000000000000000000000000000000000000000000000095000000000000000000000000000000000000000000000000000000000000007700000000000000000000000000000000000000000000000000000000000000da000000000000000000000000000000000000000000000000000000000000008e00000000000000000000000000000000000000000000000000000000000000f300000000000000000000000000000000000000000000000000000000000000cc000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000002500000000000000000000000000000000000000000000000000000000000000e500000000000000000000000000000000000000000000000000000000000000ca000000000000000000000000000000000000000000000000000000000000008e0000000000000000000000000000000000000000000000000000000000000066000000000000000000000000000000000000000000000000000000000000009300000000000000000000000000000000000000000000000000000000000000c2000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000000ec000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000b3000000000000000000000000000000000000000000000000000000000000005a0000000000000000000000000000000000000000000000000000000000000017000000000000000000000000000000000000000000000000000000000000004900000000000000000000000000000000000000000000000000000000000000f700000000000000000000000000000000000000000000000000000000000000f7000000000000000000000000000000000000000000000000000000000000003f00000000000000000000000000000000000000000000000000000000000000d400000000000000000000000000000000000000000000000000000000000000af00000000000000000000000000000000000000000000000000000000000000ee000000000000000000000000000000000000000000000000000000000000007800000000000000000000000000000000000000000000000000000000000000af00000000000000000000000000000000000000000000000000000000000000940000000000000000000000000000000000000000000000000000000000000071000000000000000000000000000000000000000000000000000000000000006d0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000009400000000000000000000000000000000000000000000000000000000000000ec000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000008200000000000000000000000000000000000000000000000000000000000000db000000000000000000000000000000000000000000000000000000000000008d0000000000000000000000000000000000000000000000000000000000000053000000000000000000000000000000000000000000000000000000000000009f00000000000000000000000000000000000000000000000000000000000000a1000000000000000000000000000000000000000000000000000000000000005900000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000090000000000000000000000000000000000000000000000000000000000000004f00000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000003800000000000000000000000000000000000000000000000000000000000000d200000000000000000000000000000000000000000000000000000000000000e2000000000000000000000000000000000000000000000000000000000000008b000000000000000000000000000000000000000000000000000000000000007c000000000000000000000000000000000000000000000000000000000000004100000000000000000000000000000000000000000000000000000000000000ac0000000000000000000000000000000000000000000000000000000000000021000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000be000000000000000000000000000000000000000000000000000000000000009c0000000000000000000000000000000000000000000000000000000000000099000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000a8000000000000000000000000000000000000000000000000000000000000008f000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000c300000000000000000000000000000000000000000000000000000000000000aa00000000000000000000000000000000000000000000000000000000000000b4000000000000000000000000000000000000000000000000000000000000002a00000000000000000000000000000000000000000000000000000000000000b100000000000000000000000000000000000000000000000000000000000000450000000000000000000000000000000000000000000000000000000000000031000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000002b00000000000000000000000000000000000000000000000000000000000000a900000000000000000000000000000000000000000000000000000000000000cd00000000000000000000000000000000000000000000000000000000000000f80000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000000000000000000000000000000000007c00000000000000000000000000000000000000000000000000000000000000ce00000000000000000000000000000000000000000000000000000000000000ff000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000006c000000000000000000000000000000000000000000000000000000000000004300000000000000000000000000000000000000000000000000000000000000bf0000000000000000000000000000000000000000000000000000000000000013000000000000000000000000000000000000000000000000000000000000008a000000000000000000000000000000000000000000000000000000000000004a00000000000000000000000000000000000000000000000000000000000000ef000000000000000000000000000000000000000000000000000000000000005b00000000000000000000000000000000000000000000000000000000000000b900000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000b2000000000000000000000000000000000000000000000000000000000000009e000000000000000000000000000000000000000000000000000000000000003400000000000000000000000000000000000000000000000000000000000000980000000000000000000000000000000000000000000000000000000000000037000000000000000000000000000000000000000000000000000000000000009800000000000000000000000000000000000000000000000000000000000000440000000000000000000000000000000000000000000000000000000000000038000000000000000000000000000000000000000000000000000000000000007e00000000000000000000000000000000000000000000000000000000000000e20000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000005c00000000000000000000000000000000000000000000000000000000000000b0000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000c80000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000008600000000000000000000000000000000000000000000000000000000000000a400000000000000000000000000000000000000000000000000000000000000cf00000000000000000000000000000000000000000000000000000000000000cf0000000000000000000000000000000000000000000000000000000000000058000000000000000000000000000000000000000000000000000000000000005800000000000000000000000000000000000000000000000000000000000000b200000000000000000000000000000000000000000000000000000000000000d8000000000000000000000000000000000000000000000000000000000000003a00000000000000000000000000000000000000000000000000000000000000210000000000000000000000000000000000000000000000000000000000000083000000000000000000000000000000000000000000000000000000000000001b000000000000000000000000000000000000000000000000000000000000006c000000000000000000000000000000000000000000000000000000000000003a0000000000000000000000000000000000000000000000000000000000000082000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000a70000000000000000000000000000000000000000000000000000000000000035000000000000000000000000000000000000000000000000000000000000000f00000000000000000000000000000000000000000000000000000000000000bf000000000000000000000000000000000000000000000000000000000000002c00000000000000000000000000000000000000000000000000000000000000b9000000000000000000000000000000000000000000000000000000000000003b00000000000000000000000000000000000000000000000000000000000000f3000000000000000000000000000000000000000000000000000000000000002d00000000000000000000000000000000000000000000000000000000000000f7000000000000000000000000000000000000000000000000000000000000006c00000000000000000000000000000000000000000000000000000000000000380000000000000000000000000000000000000000000000000000000000000077000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000000000000000000000000000000000a9000000000000000000000000000000000000000000000000000000000000005e000000000000000000000000000000000000000000000000000000000000005900000000000000000000000000000000000000000000000000000000000000fa00000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000086000000000000000000000000000000000000000000000000000000000000008500000000000000000000000000000000000000000000000000000000000000350000000000000000000000000000000000000000000000000000000000000097000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000fb000000000000000000000000000000000000000000000000000000000000008e000000000000000000000000000000000000000000000000000000000000005200000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000bc000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000005900000000000000000000000000000000000000000000000000000000000000850000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000b200000000000000000000000000000000000000000000000000000000000000ee00000000000000000000000000000000000000000000000000000000000000aa0000000000000000000000000000000000000000000000000000000000000058000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000e10000000000000000000000000000000000000000000000000000000000000027000000000000000000000000000000000000000000000000000000000000004c000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000c20000000000000000000000000000000000000000000000000000000000000043000000000000000000000000000000000000000000000000000000000000006d0000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000005d000000000000000000000000000000000000000000000000000000000000000900000000000000000000000000000000000000000000000000000000000000c200000000000000000000000000000000000000000000000000000000000000f900000000000000000000000000000000000000000000000000000000000000a40000000000000000000000000000000000000000000000000000000000000063000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000041000000000000000000000000000000000000000000000000000000000000005c00000000000000000000000000000000000000000000000000000000000000b40000000000000000000000000000000000000000000000000000000000000051000000000000000000000000000000000000000000000000000000000000005a0000000000000000000000000000000000000000000000000000000000000095000000000000000000000000000000000000000000000000000000000000002d000000000000000000000000000000000000000000000000000000000000004d0000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000f600000000000000000000000000000000000000000000000000000000000000d6000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000f5000000000000000000000000000000000000000000000000000000000000009500000000000000000000000000000000000000000000000000000000000000a800000000000000000000000000000000000000000000000000000000000000ec00000000000000000000000000000000000000000000000000000000000000b800000000000000000000000000000000000000000000000000000000000000b00000000000000000000000000000000000000000000000000000000000000037000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000ca00000000000000000000000000000000000000000000000000000000000000aa000000000000000000000000000000000000000000000000000000000000006a00000000000000000000000000000000000000000000000000000000000000f70000000000000000000000000000000000000000000000000000000000000015000000000000000000000000000000000000000000000000000000000000001f000000000000000000000000000000000000000000000000000000000000007c00000000000000000000000000000000000000000000000000000000000000fa000000000000000000000000000000000000000000000000000000000000002700000000000000000000000000000000000000000000000000000000000000d90000000000000000000000000000000000000000000000000000000000000023000000000000000000000000000000000000000000000000000000000000009c000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000d500000000000000000000000000000000000000000000000000000000000000d200000000000000000000000000000000000000000000000000000000000000b800000000000000000000000000000000000000000000000000000000000000be00000000000000000000000000000000000000000000000000000000000000b100000000000000000000000000000000000000000000000000000000000000ce000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000d400000000000000000000000000000000000000000000000000000000000000ab000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000000fa00000000000000000000000000000000000000000000000000000000000000920000000000000000000000000000000000000000000000000000000000000068000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000ff000000000000000000000000000000000000000000000000000000000000007a00000000000000000000000000000000000000000000000000000000000000bc00000000000000000000000000000000000000000000000000000000000000ab000000000000000000000000000000000000000000000000000000000000004400000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000061000000000000000000000000000000000000000000000000000000000000004e00000000000000000000000000000000000000000000000000000000000000db00000000000000000000000000000000000000000000000000000000000000ef00000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000007300000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000087000000000000000000000000000000000000000000000000000000000000008800000000000000000000000000000000000000000000000000000000000000c2000000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000009800000000000000000000000000000000000000000000000000000000000000d200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000051000000000000000000000000000000000000000000000000000000000000005c00000000000000000000000000000000000000000000000000000000000000cc0000000000000000000000000000000000000000000000000000000000000025000000000000000000000000000000000000000000000000000000000000004a00000000000000000000000000000000000000000000000000000000000000fa00000000000000000000000000000000000000000000000000000000000000ea00000000000000000000000000000000000000000000000000000000000000b7000000000000000000000000000000000000000000000000000000000000004f0000000000000000000000000000000000000000000000000000000000000057000000000000000000000000000000000000000000000000000000000000003f00000000000000000000000000000000000000000000000000000000000000bd000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000c70000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000004e00000000000000000000000000000000000000000000000000000000000000f500000000000000000000000000000000000000000000000000000000000000b900000000000000000000000000000000000000000000000000000000000000ce000000000000000000000000000000000000000000000000000000000000003c00000000000000000000000000000000000000000000000000000000000000b0000000000000000000000000000000000000000000000000000000000000003e00000000000000000000000000000000000000000000000000000000000000440000000000000000000000000000000000000000000000000000000000000092000000000000000000000000000000000000000000000000000000000000002900000000000000000000000000000000000000000000000000000000000000d100000000000000000000000000000000000000000000000000000000000000bd0000000000000000000000000000000000000000000000000000000000000062000000000000000000000000000000000000000000000000000000000000008200000000000000000000000000000000000000000000000000000000000000a700000000000000000000000000000000000000000000000000000000000000bc000000000000000000000000000000000000000000000000000000000000008b000000000000000000000000000000000000000000000000000000000000007300000000000000000000000000000000000000000000000000000000000000c600000000000000000000000000000000000000000000000000000000000000f100000000000000000000000000000000000000000000000000000000000000fa0000000000000000000000000000000000000000000000000000000000000074000000000000000000000000000000000000000000000000000000000000005e0000000000000000000000000000000000000000000000000000000000000081000000000000000000000000000000000000000000000000000000000000007800000000000000000000000000000000000000000000000000000000000000d6000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000a300000000000000000000000000000000000000000000000000000000000000490000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000001f000000000000000000000000000000000000000000000000000000000000009a000000000000000000000000000000000000000000000000000000000000004600000000000000000000000000000000000000000000000000000000000000a600000000000000000000000000000000000000000000000000000000000000f3000000000000000000000000000000000000000000000000000000000000002d00000000000000000000000000000000000000000000000000000000000000f500000000000000000000000000000000000000000000000000000000000000d8000000000000000000000000000000000000000000000000000000000000001f000000000000000000000000000000000000000000000000000000000000002d000000000000000000000000000000000000000000000000000000000000004b0000000000000000000000000000000000000000000000000000000000000065000000000000000000000000000000000000000000000000000000000000002b00000000000000000000000000000000000000000000000000000000000000860000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000008c000000000000000000000000000000000000000000000000000000000000008900000000000000000000000000000000000000000000000000000000000000b9000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000760000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000e3000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000da00000000000000000000000000000000000000000000000000000000000000fa00000000000000000000000000000000000000000000000000000000000000df00000000000000000000000000000000000000000000000000000000000000e700000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000092000000000000000000000000000000000000000000000000000000000000005c0000000000000000000000000000000000000000000000000000000000000013000000000000000000000000000000000000000000000000000000000000003d000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000000ff00000000000000000000000000000000000000000000000000000000000000c800000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000075000000000000000000000000000000000000000000000000000000000000009f000000000000000000000000000000000000000000000000000000000000006c00000000000000000000000000000000000000000000000000000000000000ed00000000000000000000000000000000000000000000000000000000000000cc00000000000000000000000000000000000000000000000000000000000000e50000000000000000000000000000000000000000000000000000000000000049000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000008c000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000000bf000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000eb00000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000ea00000000000000000000000000000000000000000000000000000000000000c9000000000000000000000000000000000000000000000000000000000000004200000000000000000000000000000000000000000000000000000000000000a40000000000000000000000000000000000000000000000000000000000000017000000000000000000000000000000000000000000000000000000000000003b000000000000000000000000000000000000000000000000000000000000005700000000000000000000000000000000000000000000000000000000000000b300000000000000000000000000000000000000000000000000000000000000f500000000000000000000000000000000000000000000000000000000000000e400000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000004600000000000000000000000000000000000000000000000000000000000000df000000000000000000000000000000000000000000000000000000000000009a00000000000000000000000000000000000000000000000000000000000000ca00000000000000000000000000000000000000000000000000000000000000b70000000000000000000000000000000000000000000000000000000000000063000000000000000000000000000000000000000000000000000000000000004e000000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000007a0000000000000000000000000000000000000000000000000000000000000045000000000000000000000000000000000000000000000000000000000000007700000000000000000000000000000000000000000000000000000000000000c300000000000000000000000000000000000000000000000000000000000000ea00000000000000000000000000000000000000000000000000000000000000b8000000000000000000000000000000000000000000000000000000000000004d000000000000000000000000000000000000000000000000000000000000009500000000000000000000000000000000000000000000000000000000000000b700000000000000000000000000000000000000000000000000000000000000d90000000000000000000000000000000000000000000000000000000000000055000000000000000000000000000000000000000000000000000000000000005e00000000000000000000000000000000000000000000000000000000000000b400000000000000000000000000000000000000000000000000000000000000b7000000000000000000000000000000000000000000000000000000000000006700000000000000000000000000000000000000000000000000000000000000fc000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000c3000000000000000000000000000000000000000000000000000000000000009200000000000000000000000000000000000000000000000000000000000000760000000000000000000000000000000000000000000000000000000000000031000000000000000000000000000000000000000000000000000000000000006200000000000000000000000000000000000000000000000000000000000000bc000000000000000000000000000000000000000000000000000000000000008e00000000000000000000000000000000000000000000000000000000000000590000000000000000000000000000000000000000000000000000000000000021000000000000000000000000000000000000000000000000000000000000004300000000000000000000000000000000000000000000000000000000000000d500000000000000000000000000000000000000000000000000000000000000cc00000000000000000000000000000000000000000000000000000000000000940000000000000000000000000000000000000000000000000000000000000054000000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000000000000000000000000000000000003800000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000f70000000000000000000000000000000000000000000000000000000000000095000000000000000000000000000000000000000000000000000000000000009600000000000000000000000000000000000000000000000000000000000000b100000000000000000000000000000000000000000000000000000000000000ff000000000000000000000000000000000000000000000000000000000000004200000000000000000000000000000000000000000000000000000000000000a600000000000000000000000000000000000000000000000000000000000000f1000000000000000000000000000000000000000000000000000000000000009800000000000000000000000000000000000000000000000000000000000000b400000000000000000000000000000000000000000000000000000000000000f2000000000000000000000000000000000000000000000000000000000000003f000000000000000000000000000000000000000000000000000000000000004c00000000000000000000000000000000000000000000000000000000000000850000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000043000000000000000000000000000000000000000000000000000000000000005600000000000000000000000000000000000000000000000000000000000000b1000000000000000000000000000000000000000000000000000000000000006800000000000000000000000000000000000000000000000000000000000000bb00000000000000000000000000000000000000000000000000000000000000a9000000000000000000000000000000000000000000000000000000000000007e00000000000000000000000000000000000000000000000000000000000000c70000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000f900000000000000000000000000000000000000000000000000000000000000c200000000000000000000000000000000000000000000000000000000000000c800000000000000000000000000000000000000000000000000000000000000ce000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000c3000000000000000000000000000000000000000000000000000000000000007300000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000000f500000000000000000000000000000000000000000000000000000000000000ab00000000000000000000000000000000000000000000000000000000000000920000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000005700000000000000000000000000000000000000000000000000000000000000f4000000000000000000000000000000000000000000000000000000000000001c00000000000000000000000000000000000000000000000000000000000000b8000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000fd0000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000000000000000000000000000000000001c00000000000000000000000000000000000000000000000000000000000000c9000000000000000000000000000000000000000000000000000000000000002a00000000000000000000000000000000000000000000000000000000000000a3000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000007100000000000000000000000000000000000000000000000000000000000000a500000000000000000000000000000000000000000000000000000000000000c300000000000000000000000000000000000000000000000000000000000000b400000000000000000000000000000000000000000000000000000000000000a200000000000000000000000000000000000000000000000000000000000000d1000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000004a0000000000000000000000000000000000000000000000000000000000000076000000000000000000000000000000000000000000000000000000000000008500000000000000000000000000000000000000000000000000000000000000aa00000000000000000000000000000000000000000000000000000000000000ec00000000000000000000000000000000000000000000000000000000000000b9000000000000000000000000000000000000000000000000000000000000003400000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000079000000000000000000000000000000000000000000000000000000000000005c000000000000000000000000000000000000000000000000000000000000008c000000000000000000000000000000000000000000000000000000000000008300000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000008500000000000000000000000000000000000000000000000000000000000000e9000000000000000000000000000000000000000000000000000000000000009300000000000000000000000000000000000000000000000000000000000000d100000000000000000000000000000000000000000000000000000000000000b0000000000000000000000000000000000000000000000000000000000000004c000000000000000000000000000000000000000000000000000000000000009c000000000000000000000000000000000000000000000000000000000000004f000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000bd00000000000000000000000000000000000000000000000000000000000000560000000000000000000000000000000000000000000000000000000000000041000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000d6000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000b60000000000000000000000000000000000000000000000000000000000000084000000000000000000000000000000000000000000000000000000000000009f000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000c200000000000000000000000000000000000000000000000000000000000000f3000000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000007e00000000000000000000000000000000000000000000000000000000000000ec00000000000000000000000000000000000000000000000000000000000000ec000000000000000000000000000000000000000000000000000000000000003400000000000000000000000000000000000000000000000000000000000000450000000000000000000000000000000000000000000000000000000000000066000000000000000000000000000000000000000000000000000000000000004b000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000fe00000000000000000000000000000000000000000000000000000000000000a7000000000000000000000000000000000000000000000000000000000000006e00000000000000000000000000000000000000000000000000000000000000fb00000000000000000000000000000000000000000000000000000000000000fe00000000000000000000000000000000000000000000000000000000000000ba00000000000000000000000000000000000000000000000000000000000000c100000000000000000000000000000000000000000000000000000000000000b600000000000000000000000000000000000000000000000000000000000000a20000000000000000000000000000000000000000000000000000000000000019000000000000000000000000000000000000000000000000000000000000004b00000000000000000000000000000000000000000000000000000000000000da00000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000000dd00000000000000000000000000000000000000000000000000000000000000940000000000000000000000000000000000000000000000000000000000000091000000000000000000000000000000000000000000000000000000000000008c000000000000000000000000000000000000000000000000000000000000007000000000000000000000000000000000000000000000000000000000000000ee000000000000000000000000000000000000000000000000000000000000008a0000000000000000000000000000000000000000000000000000000000000068000000000000000000000000000000000000000000000000000000000000002e00000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000000c200000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000ad000000000000000000000000000000000000000000000000000000000000004100000000000000000000000000000000000000000000000000000000000000530000000000000000000000000000000000000000000000000000000000000007000000000000000000000000000000000000000000000000000000000000001900000000000000000000000000000000000000000000000000000000000000df000000000000000000000000000000000000000000000000000000000000006600000000000000000000000000000000000000000000000000000000000000c500000000000000000000000000000000000000000000000000000000000000a1000000000000000000000000000000000000000000000000000000000000007e000000000000000000000000000000000000000000000000000000000000002b000000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000007d0000000000000000000000000000000000000000000000000000000000000081000000000000000000000000000000000000000000000000000000000000004400000000000000000000000000000000000000000000000000000000000000850000000000000000000000000000000000000000000000000000000000000029000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000df000000000000000000000000000000000000000000000000000000000000005e00000000000000000000000000000000000000000000000000000000000000fc000000000000000000000000000000000000000000000000000000000000008f00000000000000000000000000000000000000000000000000000000000000930000000000000000000000000000000000000000000000000000000000000076000000000000000000000000000000000000000000000000000000000000007b00000000000000000000000000000000000000000000000000000000000000fb00000000000000000000000000000000000000000000000000000000000000b2000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000d800000000000000000000000000000000000000000000000000000000000000a700000000000000000000000000000000000000000000000000000000000000d400000000000000000000000000000000000000000000000000000000000000a500000000000000000000000000000000000000000000000000000000000000bb0000000000000000000000000000000000000000000000000000000000000073000000000000000000000000000000000000000000000000000000000000003a00000000000000000000000000000000000000000000000000000000000000e800000000000000000000000000000000000000000000000000000000000000fe000000000000000000000000000000000000000000000000000000000000004c000000000000000000000000000000000000000000000000000000000000006a00000000000000000000000000000000000000000000000000000000000000370000000000000000000000000000000000000000000000000000000000000083000000000000000000000000000000000000000000000000000000000000004900000000000000000000000000000000000000000000000000000000000000c20000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000000000000000000000000000000000004a00000000000000000000000000000000000000000000000000000000000000bc00000000000000000000000000000000000000000000000000000000000000e2000000000000000000000000000000000000000000000000000000000000006800000000000000000000000000000000000000000000000000000000000000c9000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c200000000000000000000000000000000000000000000000000000000000000af000000000000000000000000000000000000000000000000000000000000007800000000000000000000000000000000000000000000000000000000000000c6000000000000000000000000000000000000000000000000000000000000007700000000000000000000000000000000000000000000000000000000000000ed000000000000000000000000000000000000000000000000000000000000004700000000000000000000000000000000000000000000000000000000000000cd00000000000000000000000000000000000000000000000000000000000000d6000000000000000000000000000000000000000000000000000000000000003800000000000000000000000000000000000000000000000000000000000000770000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000000000000000000000000000000000004d000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000d7000000000000000000000000000000000000000000000000000000000000003d000000000000000000000000000000000000000000000000000000000000000d0000000000000000000000000000000000000000000000000000000000000090000000000000000000000000000000000000000000000000000000000000009100000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000078000000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000001300000000000000000000000000000000000000000000000000000000000000d9000000000000000000000000000000000000000000000000000000000000009b000000000000000000000000000000000000000000000000000000000000007600000000000000000000000000000000000000000000000000000000000000ed00000000000000000000000000000000000000000000000000000000000000f5000000000000000000000000000000000000000000000000000000000000004e000000000000000000000000000000000000000000000000000000000000008800000000000000000000000000000000000000000000000000000000000000e9000000000000000000000000000000000000000000000000000000000000006a000000000000000000000000000000000000000000000000000000000000006c00000000000000000000000000000000000000000000000000000000000000df00000000000000000000000000000000000000000000000000000000000000d10000000000000000000000000000000000000000000000000000000000000073000000000000000000000000000000000000000000000000000000000000005f00000000000000000000000000000000000000000000000000000000000000df000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000009300000000000000000000000000000000000000000000000000000000000000ab00000000000000000000000000000000000000000000000000000000000000d70000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000009700000000000000000000000000000000000000000000000000000000000000d600000000000000000000000000000000000000000000000000000000000000c80000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000001b000000000000000000000000000000000000000000000000000000000000003100000000000000000000000000000000000000000000000000000000000000b400000000000000000000000000000000000000000000000000000000000000170000000000000000000000000000000000000000000000000000000000000088000000000000000000000000000000000000000000000000000000000000003600000000000000000000000000000000000000000000000000000000000000c200000000000000000000000000000000000000000000000000000000000000a800000000000000000000000000000000000000000000000000000000000000930000000000000000000000000000000000000000000000000000000000000021000000000000000000000000000000000000000000000000000000000000000f00000000000000000000000000000000000000000000000000000000000000cc00000000000000000000000000000000000000000000000000000000000000ed000000000000000000000000000000000000000000000000000000000000004400000000000000000000000000000000000000000000000000000000000000a300000000000000000000000000000000000000000000000000000000000000950000000000000000000000000000000000000000000000000000000000000098000000000000000000000000000000000000000000000000000000000000007d00000000000000000000000000000000000000000000000000000000000000d4000000000000000000000000000000000000000000000000000000000000000900000000000000000000000000000000000000000000000000000000000000f300000000000000000000000000000000000000000000000000000000000000510000000000000000000000000000000000000000000000000000000000000091000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000f9000000000000000000000000000000000000000000000000000000000000007d000000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000001c0000000000000000000000000000000000000000000000000000000000000013000000000000000000000000000000000000000000000000000000000000009b00000000000000000000000000000000000000000000000000000000000000f400000000000000000000000000000000000000000000000000000000000000c200000000000000000000000000000000000000000000000000000000000000ed000000000000000000000000000000000000000000000000000000000000004c000000000000000000000000000000000000000000000000000000000000003400000000000000000000000000000000000000000000000000000000000000c800000000000000000000000000000000000000000000000000000000000000db00000000000000000000000000000000000000000000000000000000000000e300000000000000000000000000000000000000000000000000000000000000180000000000000000000000000000000000000000000000000000000000000036000000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000005800000000000000000000000000000000000000000000000000000000000000aa000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000000000000000000000000000000000b8000000000000000000000000000000000000000000000000000000000000006d000000000000000000000000000000000000000000000000000000000000007a00000000000000000000000000000000000000000000000000000000000000bb00000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000004d00000000000000000000000000000000000000000000000000000000000000bc000000000000000000000000000000000000000000000000000000000000007e00000000000000000000000000000000000000000000000000000000000000d4000000000000000000000000000000000000000000000000000000000000008f000000000000000000000000000000000000000000000000000000000000005d000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000008f0000000000000000000000000000000000000000000000000000000000000085000000000000000000000000000000000000000000000000000000000000003a000000000000000000000000000000000000000000000000000000000000006300000000000000000000000000000000000000000000000000000000000000a900000000000000000000000000000000000000000000000000000000000000de00000000000000000000000000000000000000000000000000000000000000e1000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001d00000000000000000000000000000000000000000000000000000000000000df0000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001b00000000000000000000000000000000000000000000000000000000000000f7000000000000000000000000000000000000000000000000000000000000005c00000000000000000000000000000000000000000000000000000000000000e100000000000000000000000000000000000000000000000000000000000000fd000000000000000000000000000000000000000000000000000000000000007c00000000000000000000000000000000000000000000000000000000000000b9000000000000000000000000000000000000000000000000000000000000004d000000000000000000000000000000000000000000000000000000000000007600000000000000000000000000000000000000000000000000000000000000750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005300000000000000000000000000000000000000000000000000000000000000a9000000000000000000000000000000000000000000000000000000000000001c00000000000000000000000000000000000000000000000000000000000000d9000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000c80000000000000000000000000000000000000000000000000000000000000044000000000000000000000000000000000000000000000000000000000000006d000000000000000000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000000000000000000c6000000000000000000000000000000000000000000000000000000000000005800000000000000000000000000000000000000000000000000000000000000cb00000000000000000000000000000000000000000000000000000000000000a30000000000000000000000000000000000000000000000000000000000000021000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000b800000000000000000000000000000000000000000000000000000000000000ec000000000000000000000000000000000000000000000000000000000000002b00000000000000000000000000000000000000000000000000000000000000aa000000000000000000000000000000000000000000000000000000000000003300000000000000000000000000000000000000000000000000000000000000e1000000000000000000000000000000000000000000000000000000000000009300000000000000000000000000000000000000000000000000000000000000ff000000000000000000000000000000000000000000000000000000000000004e0000000000000000000000000000000000000000000000000000000000000029000000000000000000000000000000000000000000000000000000000000009a00000000000000000000000000000000000000000000000000000000000000c5000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000ab000000000000000000000000000000000000000000000000000000000000005100000000000000000000000000000000000000000000000000000000000000fd00000000000000000000000000000000000000000000000000000000000000860000000000000000000000000000000000000000000000000000000000000097000000000000000000000000000000000000000000000000000000000000006b0000000000000000000000000000000000000000000000000000000000000044000000000000000000000000000000000000000000000000000000000000001700000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000007000000000000000000000000000000000000000000000000000000000000005100000000000000000000000000000000000000000000000000000000000000960000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000006e00000000000000000000000000000000000000000000000000000000000000b8000000000000000000000000000000000000000000000000000000000000008a00000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000089000000000000000000000000000000000000000000000000000000000000002e00000000000000000000000000000000000000000000000000000000000000d10000000000000000000000000000000000000000000000000000000000000098000000000000000000000000000000000000000000000000000000000000002700000000000000000000000000000000000000000000000000000000000000e3000000000000000000000000000000000000000000000000000000000000007d000000000000000000000000000000000000000000000000000000000000006a00000000000000000000000000000000000000000000000000000000000000a1000000000000000000000000000000000000000000000000000000000000008300000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000000290000000000000000000000000000000000000000000000000000000000000052000000000000000000000000000000000000000000000000000000000000004100000000000000000000000000000000000000000000000000000000000000df000000000000000000000000000000000000000000000000000000000000008100000000000000000000000000000000000000000000000000000000000000ac000000000000000000000000000000000000000000000000000000000000005a000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000bd000000000000000000000000000000000000000000000000000000000000009e00000000000000000000000000000000000000000000000000000000000000f0000000000000000000000000000000000000000000000000000000000000004200000000000000000000000000000000000000000000000000000000000000f400000000000000000000000000000000000000000000000000000000000000fd00000000000000000000000000000000000000000000000000000000000000f600000000000000000000000000000000000000000000000000000000000000a7000000000000000000000000000000000000000000000000000000000000004200000000000000000000000000000000000000000000000000000000000000aa00000000000000000000000000000000000000000000000000000000000000d1000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000a200000000000000000000000000000000000000000000000000000000000000d200000000000000000000000000000000000000000000000000000000000000f5000000000000000000000000000000000000000000000000000000000000006e00000000000000000000000000000000000000000000000000000000000000c100000000000000000000000000000000000000000000000000000000000000ac000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000bc0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000001700000000000000000000000000000000000000000000000000000000000000cf000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000053000000000000000000000000000000000000000000000000000000000000005400000000000000000000000000000000000000000000000000000000000000fa000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000950000000000000000000000000000000000000000000000000000000000000090000000000000000000000000000000000000000000000000000000000000007e00000000000000000000000000000000000000000000000000000000000000ed000000000000000000000000000000000000000000000000000000000000002d00000000000000000000000000000000000000000000000000000000000000c2000000000000000000000000000000000000000000000000000000000000009a00000000000000000000000000000000000000000000000000000000000000a3000000000000000000000000000000000000000000000000000000000000009100000000000000000000000000000000000000000000000000000000000000eb000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000002900000000000000000000000000000000000000000000000000000000000000eb00000000000000000000000000000000000000000000000000000000000000d300000000000000000000000000000000000000000000000000000000000000a200000000000000000000000000000000000000000000000000000000000000c900000000000000000000000000000000000000000000000000000000000000d70000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000003a00000000000000000000000000000000000000000000000000000000000000660000000000000000000000000000000000000000000000000000000000000085000000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000002b00000000000000000000000000000000000000000000000000000000000000a6000000000000000000000000000000000000000000000000000000000000008f000000000000000000000000000000000000000000000000000000000000005100000000000000000000000000000000000000000000000000000000000000bb00000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000048000000000000000000000000000000000000000000000000000000000000008c000000000000000000000000000000000000000000000000000000000000004c0000000000000000000000000000000000000000000000000000000000000078000000000000000000000000000000000000000000000000000000000000009200000000000000000000000000000000000000000000000000000000000000f80000000000000000000000000000000000000000000000000000000000000036000000000000000000000000000000000000000000000000000000000000006a00000000000000000000000000000000000000000000000000000000000000aa0000000000000000000000000000000000000000000000000000000000000019000000000000000000000000000000000000000000000000000000000000007e00000000000000000000000000000000000000000000000000000000000000f100000000000000000000000000000000000000000000000000000000000000a1000000000000000000000000000000000000000000000000000000000000006a0000000000000000000000000000000000000000000000000000000000000067000000000000000000000000000000000000000000000000000000000000006c000000000000000000000000000000000000000000000000000000000000006c000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000005800000000000000000000000000000000000000000000000000000000000000b400000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000000db00000000000000000000000000000000000000000000000000000000000000350000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000006a00000000000000000000000000000000000000000000000000000000000000ce00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000037000000000000000000000000000000000000000000000000000000000000006c000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000ee000000000000000000000000000000000000000000000000000000000000007e00000000000000000000000000000000000000000000000000000000000000c2000000000000000000000000000000000000000000000000000000000000006b00000000000000000000000000000000000000000000000000000000000000580000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004d00000000000000000000000000000000000000000000000000000000000000b4000000000000000000000000000000000000000000000000000000000000001d000000000000000000000000000000000000000000000000000000000000004900000000000000000000000000000000000000000000000000000000000000c1000000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000006300000000000000000000000000000000000000000000000000000000000000e500000000000000000000000000000000000000000000000000000000000000db00000000000000000000000000000000000000000000000000000000000000c500000000000000000000000000000000000000000000000000000000000000af00000000000000000000000000000000000000000000000000000000000000f400000000000000000000000000000000000000000000000000000000000000460000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000006e00000000000000000000000000000000000000000000000000000000000000710000000000000000000000000000000000000000000000000000000000000082000000000000000000000000000000000000000000000000000000000000007e0000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000006d000000000000000000000000000000000000000000000000000000000000004a00000000000000000000000000000000000000000000000000000000000000d800000000000000000000000000000000000000000000000000000000000000cb000000000000000000000000000000000000000000000000000000000000003d000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000009200000000000000000000000000000000000000000000000000000000000000c300000000000000000000000000000000000000000000000000000000000000e400000000000000000000000000000000000000000000000000000000000000f00000000000000000000000000000000000000000000000000000000000000019000000000000000000000000000000000000000000000000000000000000009600000000000000000000000000000000000000000000000000000000000000ad000000000000000000000000000000000000000000000000000000000000002f000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000006c000000000000000000000000000000000000000000000000000000000000005e000000000000000000000000000000000000000000000000000000000000006a0000000000000000000000000000000000000000000000000000000000000072000000000000000000000000000000000000000000000000000000000000000d00000000000000000000000000000000000000000000000000000000000000d400000000000000000000000000000000000000000000000000000000000000c300000000000000000000000000000000000000000000000000000000000000f60000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000008a00000000000000000000000000000000000000000000000000000000000000f5000000000000000000000000000000000000000000000000000000000000007a000000000000000000000000000000000000000000000000000000000000003f0000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000005d00000000000000000000000000000000000000000000000000000000000000c900000000000000000000000000000000000000000000000000000000000000ae0000000000000000000000000000000000000000000000000000000000000068000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000d60000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000008b000000000000000000000000000000000000000000000000000000000000003a00000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000d700000000000000000000000000000000000000000000000000000000000000b9000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000004500000000000000000000000000000000000000000000000000000000000000cb00000000000000000000000000000000000000000000000000000000000000ce0000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000003a00000000000000000000000000000000000000000000000000000000000000e700000000000000000000000000000000000000000000000000000000000000ab0000000000000000000000000000000000000000000000000000000000000075000000000000000000000000000000000000000000000000000000000000009f00000000000000000000000000000000000000000000000000000000000000d6000000000000000000000000000000000000000000000000000000000000004900000000000000000000000000000000000000000000000000000000000000ad000000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000009b000000000000000000000000000000000000000000000000000000000000001ba05d4d29b6f1b101809f9b43edea6e227828ed7df55663b482cff3d9d7a14ec20aa023db82ed86dd399e73aee94f0f0f8854d352c413e64c4b7f8d8a9bf5cb198d4b"))) + d := &DuoNode{} + d.child1 = NewShortNode(common.FromHex("0110"), ValueNode(common.FromHex("f871820ba5850ba43b7400830186a0942eb08efb9e10d9f56e46938f28c13ecb33f67b158a085c1bad4187cfe90000801ba0a7e45cf38e44d2c39a4b94bae2e14fccde41e3280c57b611d9cb6494fde12fc7a00858adac2ba2381c591978b8404c22981f7141f0aef9c3cab8f93a55efc40acc"))) + d.child2 = NewShortNode(common.FromHex("0010"), ValueNode(common.FromHex("fa02368e820276850ba43b7400830f4240947fd85d1fc04087b3d9d1e610410989191c09b97380ba023624847b07e7000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000011af74000000000000000000000000000000000000000000000000000000000000006c0000000000000000000000000000000000000000000000000000000000000073000000000000000000000000000000000000000000000000000000000000006e000000000000000000000000000000000000000000000000000000000000006f00000000000000000000000000000000000000000000000000000000000000740000000000000000000000000000000000000000000000000000000000000061000000000000000000000000000000000000000000000000000000000000007200000000000000000000000000000000000000000000000000000000000000790000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000006e000000000000000000000000000000000000000000000000000000000000006f0000000000000000000000000000000000000000000000000000000000000074000000000000000000000000000000000000000000000000000000000000006100000000000000000000000000000000000000000000000000000000000000720000000000000000000000000000000000000000000000000000000000000069000000000000000000000000000000000000000000000000000000000000007a000000000000000000000000000000000000000000000000000000000000006100000000000000000000000000000000000000000000000000000000000000740000000000000000000000000000000000000000000000000000000000000069000000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000006e000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000660000000000000000000000000000000000000000000000000000000000000069000000000000000000000000000000000000000000000000000000000000006c0000000000000000000000000000000000000000000000000000000000000065000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000350000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000005a0000000000000000000000000000000000000000000000000000000000000044000000000000000000000000000000000000000000000000000000000000009c00000000000000000000000000000000000000000000000000000000000000eb00000000000000000000000000000000000000000000000000000000000000a100000000000000000000000000000000000000000000000000000000000000c1000000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000005d0000000000000000000000000000000000000000000000000000000000000085000000000000000000000000000000000000000000000000000000000000005400000000000000000000000000000000000000000000000000000000000000ce000000000000000000000000000000000000000000000000000000000000009c000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000cc00000000000000000000000000000000000000000000000000000000000000c3000000000000000000000000000000000000000000000000000000000000004900000000000000000000000000000000000000000000000000000000000000f300000000000000000000000000000000000000000000000000000000000000fe000000000000000000000000000000000000000000000000000000000000005f0000000000000000000000000000000000000000000000000000000000000067000000000000000000000000000000000000000000000000000000000000008300000000000000000000000000000000000000000000000000000000000000af000000000000000000000000000000000000000000000000000000000000004900000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000045000000000000000000000000000000000000000000000000000000000000006e00000000000000000000000000000000000000000000000000000000000000bd00000000000000000000000000000000000000000000000000000000000000a2000000000000000000000000000000000000000000000000000000000000007400000000000000000000000000000000000000000000000000000000000000d100000000000000000000000000000000000000000000000000000000000000e400000000000000000000000000000000000000000000000000000000000000af00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000019000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000d900000000000000000000000000000000000000000000000000000000000000d900000000000000000000000000000000000000000000000000000000000000d1000000000000000000000000000000000000000000000000000000000000008800000000000000000000000000000000000000000000000000000000000000d100000000000000000000000000000000000000000000000000000000000000f800000000000000000000000000000000000000000000000000000000000000d700000000000000000000000000000000000000000000000000000000000000740000000000000000000000000000000000000000000000000000000000000049000000000000000000000000000000000000000000000000000000000000008b0000000000000000000000000000000000000000000000000000000000000062000000000000000000000000000000000000000000000000000000000000005f00000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000000b20000000000000000000000000000000000000000000000000000000000000096000000000000000000000000000000000000000000000000000000000000004d000000000000000000000000000000000000000000000000000000000000006a00000000000000000000000000000000000000000000000000000000000000dd00000000000000000000000000000000000000000000000000000000000000ba00000000000000000000000000000000000000000000000000000000000000f400000000000000000000000000000000000000000000000000000000000000ae0000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000003900000000000000000000000000000000000000000000000000000000000000bf000000000000000000000000000000000000000000000000000000000000009d000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000006500000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000000000000000000000000000000000ab0000000000000000000000000000000000000000000000000000000000000099000000000000000000000000000000000000000000000000000000000000004a00000000000000000000000000000000000000000000000000000000000000b400000000000000000000000000000000000000000000000000000000000000ce00000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000009100000000000000000000000000000000000000000000000000000000000000ee00000000000000000000000000000000000000000000000000000000000000830000000000000000000000000000000000000000000000000000000000000029000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ca00000000000000000000000000000000000000000000000000000000000000760000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000004b00000000000000000000000000000000000000000000000000000000000000bc00000000000000000000000000000000000000000000000000000000000000a600000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000049000000000000000000000000000000000000000000000000000000000000008e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000e50000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000b600000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000082000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000b2000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000820000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000009a00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000019000000000000000000000000000000000000000000000000000000000000008b0000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000000d00000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000002a00000000000000000000000000000000000000000000000000000000000000860000000000000000000000000000000000000000000000000000000000000048000000000000000000000000000000000000000000000000000000000000008600000000000000000000000000000000000000000000000000000000000000f7000000000000000000000000000000000000000000000000000000000000000d00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000b00000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000470000000000000000000000000000000000000000000000000000000000000031000000000000000000000000000000000000000000000000000000000000000b0000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000000900000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000005500000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000001300000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000055000000000000000000000000000000000000000000000000000000000000005300000000000000000000000000000000000000000000000000000000000000310000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000550000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000013000000000000000000000000000000000000000000000000000000000000000d00000000000000000000000000000000000000000000000000000000000000470000000000000000000000000000000000000000000000000000000000000065000000000000000000000000000000000000000000000000000000000000006f0000000000000000000000000000000000000000000000000000000000000054000000000000000000000000000000000000000000000000000000000000007200000000000000000000000000000000000000000000000000000000000000750000000000000000000000000000000000000000000000000000000000000073000000000000000000000000000000000000000000000000000000000000007400000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000049000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000063000000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000003100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000005500000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000001300000000000000000000000000000000000000000000000000000000000000170000000000000000000000000000000000000000000000000000000000000052000000000000000000000000000000000000000000000000000000000000006100000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000069000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000000530000000000000000000000000000000000000000000000000000000000000053000000000000000000000000000000000000000000000000000000000000004c00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000053000000000000000000000000000000000000000000000000000000000000004800000000000000000000000000000000000000000000000000000000000000410000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000003500000000000000000000000000000000000000000000000000000000000000360000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004300000000000000000000000000000000000000000000000000000000000000410000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002d0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004700000000000000000000000000000000000000000000000000000000000000330000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000017000000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000003100000000000000000000000000000000000000000000000000000000000000350000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000003200000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000003100000000000000000000000000000000000000000000000000000000000000390000000000000000000000000000000000000000000000000000000000000035000000000000000000000000000000000000000000000000000000000000003700000000000000000000000000000000000000000000000000000000000000310000000000000000000000000000000000000000000000000000000000000038000000000000000000000000000000000000000000000000000000000000005a0000000000000000000000000000000000000000000000000000000000000017000000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000003100000000000000000000000000000000000000000000000000000000000000360000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000003200000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000036000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000360000000000000000000000000000000000000000000000000000000000000034000000000000000000000000000000000000000000000000000000000000003500000000000000000000000000000000000000000000000000000000000000310000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000005a00000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000081000000000000000000000000000000000000000000000000000000000000009300000000000000000000000000000000000000000000000000000000000000310000000000000000000000000000000000000000000000000000000000000013000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000110000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000550000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000b0000000000000000000000000000000000000000000000000000000000000013000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000047000000000000000000000000000000000000000000000000000000000000005400000000000000000000000000000000000000000000000000000000000000390000000000000000000000000000000000000000000000000000000000000038000000000000000000000000000000000000000000000000000000000000003200000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000036000000000000000000000000000000000000000000000000000000000000003200000000000000000000000000000000000000000000000000000000000000360000000000000000000000000000000000000000000000000000000000000039000000000000000000000000000000000000000000000000000000000000003100000000000000000000000000000000000000000000000000000000000000310000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000002f0000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000550000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000001300000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000053000000000000000000000000000000000000000000000000000000000000006500000000000000000000000000000000000000000000000000000000000000650000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000007700000000000000000000000000000000000000000000000000000000000000770000000000000000000000000000000000000000000000000000000000000077000000000000000000000000000000000000000000000000000000000000002e0000000000000000000000000000000000000000000000000000000000000072000000000000000000000000000000000000000000000000000000000000006100000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000069000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000000730000000000000000000000000000000000000000000000000000000000000073000000000000000000000000000000000000000000000000000000000000006c000000000000000000000000000000000000000000000000000000000000002e0000000000000000000000000000000000000000000000000000000000000063000000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000006d000000000000000000000000000000000000000000000000000000000000002f000000000000000000000000000000000000000000000000000000000000007200000000000000000000000000000000000000000000000000000000000000650000000000000000000000000000000000000000000000000000000000000073000000000000000000000000000000000000000000000000000000000000006f00000000000000000000000000000000000000000000000000000000000000750000000000000000000000000000000000000000000000000000000000000072000000000000000000000000000000000000000000000000000000000000006300000000000000000000000000000000000000000000000000000000000000650000000000000000000000000000000000000000000000000000000000000073000000000000000000000000000000000000000000000000000000000000002f0000000000000000000000000000000000000000000000000000000000000063000000000000000000000000000000000000000000000000000000000000007000000000000000000000000000000000000000000000000000000000000000730000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000000000630000000000000000000000000000000000000000000000000000000000000029000000000000000000000000000000000000000000000000000000000000003100000000000000000000000000000000000000000000000000000000000000350000000000000000000000000000000000000000000000000000000000000031000000000000000000000000000000000000000000000000000000000000002f0000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000002d0000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000550000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000001300000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000000000044000000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000006d00000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000069000000000000000000000000000000000000000000000000000000000000006e00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000043000000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000006e00000000000000000000000000000000000000000000000000000000000000740000000000000000000000000000000000000000000000000000000000000072000000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000006c000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000560000000000000000000000000000000000000000000000000000000000000061000000000000000000000000000000000000000000000000000000000000006c0000000000000000000000000000000000000000000000000000000000000069000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000074000000000000000000000000000000000000000000000000000000000000006500000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002d00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000052000000000000000000000000000000000000000000000000000000000000006100000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000069000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000000530000000000000000000000000000000000000000000000000000000000000053000000000000000000000000000000000000000000000000000000000000004c0000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000005200000000000000000000000000000000000000000000000000000000000000290000000000000000000000000000000000000000000000000000000000000031000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000055000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000013000000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000007700000000000000000000000000000000000000000000000000000000000000770000000000000000000000000000000000000000000000000000000000000077000000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000007200000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000063000000000000000000000000000000000000000000000000000000000000006c0000000000000000000000000000000000000000000000000000000000000069000000000000000000000000000000000000000000000000000000000000007a0000000000000000000000000000000000000000000000000000000000000065000000000000000000000000000000000000000000000000000000000000002e0000000000000000000000000000000000000000000000000000000000000069000000000000000000000000000000000000000000000000000000000000007400000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000082000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000000d00000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000002a00000000000000000000000000000000000000000000000000000000000000860000000000000000000000000000000000000000000000000000000000000048000000000000000000000000000000000000000000000000000000000000008600000000000000000000000000000000000000000000000000000000000000f7000000000000000000000000000000000000000000000000000000000000000d00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000820000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000820000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000008200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b70000000000000000000000000000000000000000000000000000000000000075000000000000000000000000000000000000000000000000000000000000006e000000000000000000000000000000000000000000000000000000000000004e000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000660000000000000000000000000000000000000000000000000000000000000097000000000000000000000000000000000000000000000000000000000000009b000000000000000000000000000000000000000000000000000000000000008f000000000000000000000000000000000000000000000000000000000000000b00000000000000000000000000000000000000000000000000000000000000d500000000000000000000000000000000000000000000000000000000000000d60000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000f40000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000ac00000000000000000000000000000000000000000000000000000000000000a8000000000000000000000000000000000000000000000000000000000000003800000000000000000000000000000000000000000000000000000000000000c7000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a900000000000000000000000000000000000000000000000000000000000000f1000000000000000000000000000000000000000000000000000000000000008200000000000000000000000000000000000000000000000000000000000000e100000000000000000000000000000000000000000000000000000000000000a700000000000000000000000000000000000000000000000000000000000000f4000000000000000000000000000000000000000000000000000000000000004c000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004e00000000000000000000000000000000000000000000000000000000000000c100000000000000000000000000000000000000000000000000000000000000f5000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000006600000000000000000000000000000000000000000000000000000000000000f500000000000000000000000000000000000000000000000000000000000000b900000000000000000000000000000000000000000000000000000000000000cf000000000000000000000000000000000000000000000000000000000000009e00000000000000000000000000000000000000000000000000000000000000f500000000000000000000000000000000000000000000000000000000000000ce000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000bd000000000000000000000000000000000000000000000000000000000000008600000000000000000000000000000000000000000000000000000000000000b10000000000000000000000000000000000000000000000000000000000000039000000000000000000000000000000000000000000000000000000000000003c0000000000000000000000000000000000000000000000000000000000000053000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000000a60000000000000000000000000000000000000000000000000000000000000059000000000000000000000000000000000000000000000000000000000000003a000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000dd000000000000000000000000000000000000000000000000000000000000008d000000000000000000000000000000000000000000000000000000000000009d000000000000000000000000000000000000000000000000000000000000002500000000000000000000000000000000000000000000000000000000000000fa000000000000000000000000000000000000000000000000000000000000003a000000000000000000000000000000000000000000000000000000000000008700000000000000000000000000000000000000000000000000000000000000cb00000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000ad000000000000000000000000000000000000000000000000000000000000007e0000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000009400000000000000000000000000000000000000000000000000000000000000620000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000007c00000000000000000000000000000000000000000000000000000000000000ae00000000000000000000000000000000000000000000000000000000000000f2000000000000000000000000000000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000000000b3000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000cb000000000000000000000000000000000000000000000000000000000000009600000000000000000000000000000000000000000000000000000000000000d700000000000000000000000000000000000000000000000000000000000000fb000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000ae000000000000000000000000000000000000000000000000000000000000006b0000000000000000000000000000000000000000000000000000000000000075000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000004800000000000000000000000000000000000000000000000000000000000000f400000000000000000000000000000000000000000000000000000000000000a7000000000000000000000000000000000000000000000000000000000000004a00000000000000000000000000000000000000000000000000000000000000fc00000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000072000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000de0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001c00000000000000000000000000000000000000000000000000000000000000d50000000000000000000000000000000000000000000000000000000000000061000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000000000e300000000000000000000000000000000000000000000000000000000000000de000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000007e00000000000000000000000000000000000000000000000000000000000000a200000000000000000000000000000000000000000000000000000000000000dc00000000000000000000000000000000000000000000000000000000000000e100000000000000000000000000000000000000000000000000000000000000ab00000000000000000000000000000000000000000000000000000000000000be00000000000000000000000000000000000000000000000000000000000000f30000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000099000000000000000000000000000000000000000000000000000000000000007c000000000000000000000000000000000000000000000000000000000000007e000000000000000000000000000000000000000000000000000000000000009f000000000000000000000000000000000000000000000000000000000000007000000000000000000000000000000000000000000000000000000000000000e1000000000000000000000000000000000000000000000000000000000000002b00000000000000000000000000000000000000000000000000000000000000c200000000000000000000000000000000000000000000000000000000000000c800000000000000000000000000000000000000000000000000000000000000f2000000000000000000000000000000000000000000000000000000000000004100000000000000000000000000000000000000000000000000000000000000900000000000000000000000000000000000000000000000000000000000000093000000000000000000000000000000000000000000000000000000000000009c000000000000000000000000000000000000000000000000000000000000000b00000000000000000000000000000000000000000000000000000000000000970000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000f500000000000000000000000000000000000000000000000000000000000000e400000000000000000000000000000000000000000000000000000000000000fe00000000000000000000000000000000000000000000000000000000000000f100000000000000000000000000000000000000000000000000000000000000de000000000000000000000000000000000000000000000000000000000000000b00000000000000000000000000000000000000000000000000000000000000ba000000000000000000000000000000000000000000000000000000000000004d000000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000003100000000000000000000000000000000000000000000000000000000000000770000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000000000000000000000000000000000c700000000000000000000000000000000000000000000000000000000000000ad000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000ca000000000000000000000000000000000000000000000000000000000000007000000000000000000000000000000000000000000000000000000000000000a30000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000008b00000000000000000000000000000000000000000000000000000000000000a900000000000000000000000000000000000000000000000000000000000000d400000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000000e8000000000000000000000000000000000000000000000000000000000000004c000000000000000000000000000000000000000000000000000000000000004c0000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000006700000000000000000000000000000000000000000000000000000000000000d600000000000000000000000000000000000000000000000000000000000000900000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000007000000000000000000000000000000000000000000000000000000000000000df00000000000000000000000000000000000000000000000000000000000000da00000000000000000000000000000000000000000000000000000000000000f4000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000001500000000000000000000000000000000000000000000000000000000000000ef000000000000000000000000000000000000000000000000000000000000002700000000000000000000000000000000000000000000000000000000000000b9000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000e500000000000000000000000000000000000000000000000000000000000000f3000000000000000000000000000000000000000000000000000000000000004d000000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000049000000000000000000000000000000000000000000000000000000000000004f0000000000000000000000000000000000000000000000000000000000000043000000000000000000000000000000000000000000000000000000000000006d000000000000000000000000000000000000000000000000000000000000003900000000000000000000000000000000000000000000000000000000000000cd000000000000000000000000000000000000000000000000000000000000002300000000000000000000000000000000000000000000000000000000000000aa000000000000000000000000000000000000000000000000000000000000005d00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000c100000000000000000000000000000000000000000000000000000000000000cf000000000000000000000000000000000000000000000000000000000000008e0000000000000000000000000000000000000000000000000000000000000076000000000000000000000000000000000000000000000000000000000000000900000000000000000000000000000000000000000000000000000000000000f9000000000000000000000000000000000000000000000000000000000000009b0000000000000000000000000000000000000000000000000000000000000033000000000000000000000000000000000000000000000000000000000000007600000000000000000000000000000000000000000000000000000000000000bb0000000000000000000000000000000000000000000000000000000000000025000000000000000000000000000000000000000000000000000000000000002e00000000000000000000000000000000000000000000000000000000000000bc00000000000000000000000000000000000000000000000000000000000000b3000000000000000000000000000000000000000000000000000000000000009400000000000000000000000000000000000000000000000000000000000000dd00000000000000000000000000000000000000000000000000000000000000a5000000000000000000000000000000000000000000000000000000000000005400000000000000000000000000000000000000000000000000000000000000970000000000000000000000000000000000000000000000000000000000000085000000000000000000000000000000000000000000000000000000000000000f00000000000000000000000000000000000000000000000000000000000000f50000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002d0000000000000000000000000000000000000000000000000000000000000092000000000000000000000000000000000000000000000000000000000000003f00000000000000000000000000000000000000000000000000000000000000ea00000000000000000000000000000000000000000000000000000000000000770000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000007d00000000000000000000000000000000000000000000000000000000000000dc00000000000000000000000000000000000000000000000000000000000000f50000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000008c00000000000000000000000000000000000000000000000000000000000000cb000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000a8000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000003e000000000000000000000000000000000000000000000000000000000000007e000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000036000000000000000000000000000000000000000000000000000000000000005a00000000000000000000000000000000000000000000000000000000000000e4000000000000000000000000000000000000000000000000000000000000008600000000000000000000000000000000000000000000000000000000000000760000000000000000000000000000000000000000000000000000000000000092000000000000000000000000000000000000000000000000000000000000007c00000000000000000000000000000000000000000000000000000000000000cb000000000000000000000000000000000000000000000000000000000000001b00000000000000000000000000000000000000000000000000000000000000c90000000000000000000000000000000000000000000000000000000000000094000000000000000000000000000000000000000000000000000000000000003600000000000000000000000000000000000000000000000000000000000000660000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000006f00000000000000000000000000000000000000000000000000000000000000c8000000000000000000000000000000000000000000000000000000000000007e00000000000000000000000000000000000000000000000000000000000000f200000000000000000000000000000000000000000000000000000000000000e90000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000a300000000000000000000000000000000000000000000000000000000000000820000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000005800000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000082000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000540000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000001f000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000055000000000000000000000000000000000000000000000000000000000000001d000000000000000000000000000000000000000000000000000000000000002300000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000c3000000000000000000000000000000000000000000000000000000000000009c00000000000000000000000000000000000000000000000000000000000000f300000000000000000000000000000000000000000000000000000000000000fc00000000000000000000000000000000000000000000000000000000000000d300000000000000000000000000000000000000000000000000000000000000460000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000003400000000000000000000000000000000000000000000000000000000000000bb00000000000000000000000000000000000000000000000000000000000000ce0000000000000000000000000000000000000000000000000000000000000046000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000007c000000000000000000000000000000000000000000000000000000000000005b00000000000000000000000000000000000000000000000000000000000000f300000000000000000000000000000000000000000000000000000000000000e2000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000cb00000000000000000000000000000000000000000000000000000000000000590000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000005700000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002b00000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000007000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000004b000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000490000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000001f00000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002b0000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000008600000000000000000000000000000000000000000000000000000000000000130000000000000000000000000000000000000000000000000000000000000068000000000000000000000000000000000000000000000000000000000000007400000000000000000000000000000000000000000000000000000000000000740000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000003a000000000000000000000000000000000000000000000000000000000000002f000000000000000000000000000000000000000000000000000000000000002f00000000000000000000000000000000000000000000000000000000000000670000000000000000000000000000000000000000000000000000000000000076000000000000000000000000000000000000000000000000000000000000002e00000000000000000000000000000000000000000000000000000000000000730000000000000000000000000000000000000000000000000000000000000079000000000000000000000000000000000000000000000000000000000000006d00000000000000000000000000000000000000000000000000000000000000630000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000000000000000000000000000000000002e0000000000000000000000000000000000000000000000000000000000000063000000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000006d0000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002b00000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000007000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000086000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000000068000000000000000000000000000000000000000000000000000000000000007400000000000000000000000000000000000000000000000000000000000000740000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000003a000000000000000000000000000000000000000000000000000000000000002f000000000000000000000000000000000000000000000000000000000000002f00000000000000000000000000000000000000000000000000000000000000670000000000000000000000000000000000000000000000000000000000000076000000000000000000000000000000000000000000000000000000000000002e00000000000000000000000000000000000000000000000000000000000000730000000000000000000000000000000000000000000000000000000000000079000000000000000000000000000000000000000000000000000000000000006d00000000000000000000000000000000000000000000000000000000000000630000000000000000000000000000000000000000000000000000000000000062000000000000000000000000000000000000000000000000000000000000002e0000000000000000000000000000000000000000000000000000000000000063000000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000006d000000000000000000000000000000000000000000000000000000000000002f00000000000000000000000000000000000000000000000000000000000000670000000000000000000000000000000000000000000000000000000000000076000000000000000000000000000000000000000000000000000000000000002e0000000000000000000000000000000000000000000000000000000000000063000000000000000000000000000000000000000000000000000000000000007200000000000000000000000000000000000000000000000000000000000000740000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000055000000000000000000000000000000000000000000000000000000000000001d000000000000000000000000000000000000000000000000000000000000000f0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000ff0000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000001d000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000055000000000000000000000000000000000000000000000000000000000000001d0000000000000000000000000000000000000000000000000000000000000025000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002b000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002b000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000027000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000055000000000000000000000000000000000000000000000000000000000000001d0000000000000000000000000000000000000000000000000000000000000011000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000082000000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000007700000000000000000000000000000000000000000000000000000000000000770000000000000000000000000000000000000000000000000000000000000077000000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000007200000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000063000000000000000000000000000000000000000000000000000000000000006c0000000000000000000000000000000000000000000000000000000000000069000000000000000000000000000000000000000000000000000000000000007a0000000000000000000000000000000000000000000000000000000000000065000000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000006900000000000000000000000000000000000000000000000000000000000000740000000000000000000000000000000000000000000000000000000000000082000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000007200000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000063000000000000000000000000000000000000000000000000000000000000006c0000000000000000000000000000000000000000000000000000000000000069000000000000000000000000000000000000000000000000000000000000007a0000000000000000000000000000000000000000000000000000000000000065000000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000006900000000000000000000000000000000000000000000000000000000000000740000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000002b000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000055000000000000000000000000000000000000000000000000000000000000001d000000000000000000000000000000000000000000000000000000000000001f00000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001c0000000000000000000000000000000000000000000000000000000000000086000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000000068000000000000000000000000000000000000000000000000000000000000007400000000000000000000000000000000000000000000000000000000000000740000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000003a000000000000000000000000000000000000000000000000000000000000002f000000000000000000000000000000000000000000000000000000000000002f00000000000000000000000000000000000000000000000000000000000000670000000000000000000000000000000000000000000000000000000000000076000000000000000000000000000000000000000000000000000000000000002e00000000000000000000000000000000000000000000000000000000000000730000000000000000000000000000000000000000000000000000000000000079000000000000000000000000000000000000000000000000000000000000006d00000000000000000000000000000000000000000000000000000000000000630000000000000000000000000000000000000000000000000000000000000062000000000000000000000000000000000000000000000000000000000000002e0000000000000000000000000000000000000000000000000000000000000063000000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000006d000000000000000000000000000000000000000000000000000000000000002f00000000000000000000000000000000000000000000000000000000000000670000000000000000000000000000000000000000000000000000000000000076000000000000000000000000000000000000000000000000000000000000002e00000000000000000000000000000000000000000000000000000000000000630000000000000000000000000000000000000000000000000000000000000072000000000000000000000000000000000000000000000000000000000000006c0000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000055000000000000000000000000000000000000000000000000000000000000001d00000000000000000000000000000000000000000000000000000000000000130000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000ff000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000045000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000055000000000000000000000000000000000000000000000000000000000000001d00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000003e0000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000003c0000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000003a0000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000008600000000000000000000000000000000000000000000000000000000000000480000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000008600000000000000000000000000000000000000000000000000000000000000f800000000000000000000000000000000000000000000000000000000000000450000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000360000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000002c0000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000002a00000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002b00000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000007000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000680000000000000000000000000000000000000000000000000000000000000074000000000000000000000000000000000000000000000000000000000000007400000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000073000000000000000000000000000000000000000000000000000000000000003a000000000000000000000000000000000000000000000000000000000000002f000000000000000000000000000000000000000000000000000000000000002f000000000000000000000000000000000000000000000000000000000000007700000000000000000000000000000000000000000000000000000000000000770000000000000000000000000000000000000000000000000000000000000077000000000000000000000000000000000000000000000000000000000000002e0000000000000000000000000000000000000000000000000000000000000072000000000000000000000000000000000000000000000000000000000000006100000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000069000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000000730000000000000000000000000000000000000000000000000000000000000073000000000000000000000000000000000000000000000000000000000000006c000000000000000000000000000000000000000000000000000000000000002e0000000000000000000000000000000000000000000000000000000000000063000000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000006d000000000000000000000000000000000000000000000000000000000000002f000000000000000000000000000000000000000000000000000000000000006c000000000000000000000000000000000000000000000000000000000000006500000000000000000000000000000000000000000000000000000000000000670000000000000000000000000000000000000000000000000000000000000061000000000000000000000000000000000000000000000000000000000000006c0000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000000d00000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000002a00000000000000000000000000000000000000000000000000000000000000860000000000000000000000000000000000000000000000000000000000000048000000000000000000000000000000000000000000000000000000000000008600000000000000000000000000000000000000000000000000000000000000f7000000000000000000000000000000000000000000000000000000000000000d00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000b0000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000082000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005100000000000000000000000000000000000000000000000000000000000000b600000000000000000000000000000000000000000000000000000000000000ab000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000240000000000000000000000000000000000000000000000000000000000000047000000000000000000000000000000000000000000000000000000000000005500000000000000000000000000000000000000000000000000000000000000b40000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000007c000000000000000000000000000000000000000000000000000000000000006a00000000000000000000000000000000000000000000000000000000000000c500000000000000000000000000000000000000000000000000000000000000da00000000000000000000000000000000000000000000000000000000000000f100000000000000000000000000000000000000000000000000000000000000d100000000000000000000000000000000000000000000000000000000000000f6000000000000000000000000000000000000000000000000000000000000001500000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000003d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f3000000000000000000000000000000000000000000000000000000000000004300000000000000000000000000000000000000000000000000000000000000c800000000000000000000000000000000000000000000000000000000000000bb0000000000000000000000000000000000000000000000000000000000000092000000000000000000000000000000000000000000000000000000000000009f00000000000000000000000000000000000000000000000000000000000000e90000000000000000000000000000000000000000000000000000000000000015000000000000000000000000000000000000000000000000000000000000005100000000000000000000000000000000000000000000000000000000000000bd000000000000000000000000000000000000000000000000000000000000009100000000000000000000000000000000000000000000000000000000000000a4000000000000000000000000000000000000000000000000000000000000008600000000000000000000000000000000000000000000000000000000000000b20000000000000000000000000000000000000000000000000000000000000039000000000000000000000000000000000000000000000000000000000000004d000000000000000000000000000000000000000000000000000000000000008a000000000000000000000000000000000000000000000000000000000000004200000000000000000000000000000000000000000000000000000000000000ba000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000370000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000005a00000000000000000000000000000000000000000000000000000000000000f00000000000000000000000000000000000000000000000000000000000000027000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000590000000000000000000000000000000000000000000000000000000000000092000000000000000000000000000000000000000000000000000000000000009d00000000000000000000000000000000000000000000000000000000000000bf000000000000000000000000000000000000000000000000000000000000001900000000000000000000000000000000000000000000000000000000000000a400000000000000000000000000000000000000000000000000000000000000d600000000000000000000000000000000000000000000000000000000000000da0000000000000000000000000000000000000000000000000000000000000048000000000000000000000000000000000000000000000000000000000000008d00000000000000000000000000000000000000000000000000000000000000c900000000000000000000000000000000000000000000000000000000000000f10000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000008600000000000000000000000000000000000000000000000000000000000000bf0000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000ac000000000000000000000000000000000000000000000000000000000000004600000000000000000000000000000000000000000000000000000000000000fe000000000000000000000000000000000000000000000000000000000000003300000000000000000000000000000000000000000000000000000000000000db00000000000000000000000000000000000000000000000000000000000000f00000000000000000000000000000000000000000000000000000000000000043000000000000000000000000000000000000000000000000000000000000008400000000000000000000000000000000000000000000000000000000000000f200000000000000000000000000000000000000000000000000000000000000fd00000000000000000000000000000000000000000000000000000000000000cd00000000000000000000000000000000000000000000000000000000000000bb000000000000000000000000000000000000000000000000000000000000004800000000000000000000000000000000000000000000000000000000000000a900000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000002b000000000000000000000000000000000000000000000000000000000000003e000000000000000000000000000000000000000000000000000000000000004e0000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000004f000000000000000000000000000000000000000000000000000000000000003400000000000000000000000000000000000000000000000000000000000000db0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000950000000000000000000000000000000000000000000000000000000000000085000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000fe00000000000000000000000000000000000000000000000000000000000000df000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000590000000000000000000000000000000000000000000000000000000000000013000000000000000000000000000000000000000000000000000000000000007d00000000000000000000000000000000000000000000000000000000000000430000000000000000000000000000000000000000000000000000000000000035000000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000005f000000000000000000000000000000000000000000000000000000000000002b00000000000000000000000000000000000000000000000000000000000000a4000000000000000000000000000000000000000000000000000000000000008200000000000000000000000000000000000000000000000000000000000000490000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000009300000000000000000000000000000000000000000000000000000000000000a500000000000000000000000000000000000000000000000000000000000000f80000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000ca00000000000000000000000000000000000000000000000000000000000000d200000000000000000000000000000000000000000000000000000000000000c50000000000000000000000000000000000000000000000000000000000000074000000000000000000000000000000000000000000000000000000000000009c00000000000000000000000000000000000000000000000000000000000000b6000000000000000000000000000000000000000000000000000000000000009f00000000000000000000000000000000000000000000000000000000000000dc00000000000000000000000000000000000000000000000000000000000000ea0000000000000000000000000000000000000000000000000000000000000025000000000000000000000000000000000000000000000000000000000000003d00000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000093000000000000000000000000000000000000000000000000000000000000003f00000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000069000000000000000000000000000000000000000000000000000000000000007100000000000000000000000000000000000000000000000000000000000000b600000000000000000000000000000000000000000000000000000000000000e70000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000008b00000000000000000000000000000000000000000000000000000000000000840000000000000000000000000000000000000000000000000000000000000063000000000000000000000000000000000000000000000000000000000000004b000000000000000000000000000000000000000000000000000000000000007500000000000000000000000000000000000000000000000000000000000000ab000000000000000000000000000000000000000000000000000000000000003200000000000000000000000000000000000000000000000000000000000000910000000000000000000000000000000000000000000000000000000000000067000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000d6000000000000000000000000000000000000000000000000000000000000003300000000000000000000000000000000000000000000000000000000000000f700000000000000000000000000000000000000000000000000000000000000ca000000000000000000000000000000000000000000000000000000000000008900000000000000000000000000000000000000000000000000000000000000b3000000000000000000000000000000000000000000000000000000000000004600000000000000000000000000000000000000000000000000000000000000a60000000000000000000000000000000000000000000000000000000000000017000000000000000000000000000000000000000000000000000000000000009e000000000000000000000000000000000000000000000000000000000000001b000000000000000000000000000000000000000000000000000000000000006c000000000000000000000000000000000000000000000000000000000000008b000000000000000000000000000000000000000000000000000000000000000d00000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000023000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000720000000000000000000000000000000000000000000000000000000000000094000000000000000000000000000000000000000000000000000000000000009b00000000000000000000000000000000000000000000000000000000000000ac00000000000000000000000000000000000000000000000000000000000000d60000000000000000000000000000000000000000000000000000000000000071000000000000000000000000000000000000000000000000000000000000005300000000000000000000000000000000000000000000000000000000000000810000000000000000000000000000000000000000000000000000000000000033000000000000000000000000000000000000000000000000000000000000007d000000000000000000000000000000000000000000000000000000000000002f000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000b8000000000000000000000000000000000000000000000000000000000000007800000000000000000000000000000000000000000000000000000000000000e4000000000000000000000000000000000000000000000000000000000000008a000000000000000000000000000000000000000000000000000000000000001500000000000000000000000000000000000000000000000000000000000000c50000000000000000000000000000000000000000000000000000000000000065000000000000000000000000000000000000000000000000000000000000004a00000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000034000000000000000000000000000000000000000000000000000000000000007900000000000000000000000000000000000000000000000000000000000000df000000000000000000000000000000000000000000000000000000000000003e000000000000000000000000000000000000000000000000000000000000008f00000000000000000000000000000000000000000000000000000000000000c400000000000000000000000000000000000000000000000000000000000000c200000000000000000000000000000000000000000000000000000000000000b900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000042000000000000000000000000000000000000000000000000000000000000005600000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000b300000000000000000000000000000000000000000000000000000000000000ef00000000000000000000000000000000000000000000000000000000000000eb0000000000000000000000000000000000000000000000000000000000000048000000000000000000000000000000000000000000000000000000000000009d000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000e5000000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000007000000000000000000000000000000000000000000000000000000000000000ea000000000000000000000000000000000000000000000000000000000000003900000000000000000000000000000000000000000000000000000000000000b500000000000000000000000000000000000000000000000000000000000000fc000000000000000000000000000000000000000000000000000000000000004f00000000000000000000000000000000000000000000000000000000000000310000000000000000000000000000000000000000000000000000000000000099000000000000000000000000000000000000000000000000000000000000001900000000000000000000000000000000000000000000000000000000000000b700000000000000000000000000000000000000000000000000000000000000a100000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000000077000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000006b0000000000000000000000000000000000000000000000000000000000000058000000000000000000000000000000000000000000000000000000000000001500000000000000000000000000000000000000000000000000000000000000fd00000000000000000000000000000000000000000000000000000000000000e2000000000000000000000000000000000000000000000000000000000000004600000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000083000000000000000000000000000000000000000000000000000000000000007300000000000000000000000000000000000000000000000000000000000000af000000000000000000000000000000000000000000000000000000000000007800000000000000000000000000000000000000000000000000000000000000c8000000000000000000000000000000000000000000000000000000000000005700000000000000000000000000000000000000000000000000000000000000a100000000000000000000000000000000000000000000000000000000000000fa000000000000000000000000000000000000000000000000000000000000006d0000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000006700000000000000000000000000000000000000000000000000000000000000e900000000000000000000000000000000000000000000000000000000000000b60000000000000000000000000000000000000000000000000000000000000094000000000000000000000000000000000000000000000000000000000000000d0000000000000000000000000000000000000000000000000000000000000017000000000000000000000000000000000000000000000000000000000000007300000000000000000000000000000000000000000000000000000000000000a500000000000000000000000000000000000000000000000000000000000000db000000000000000000000000000000000000000000000000000000000000006f00000000000000000000000000000000000000000000000000000000000000c700000000000000000000000000000000000000000000000000000000000000a7000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000ff000000000000000000000000000000000000000000000000000000000000009d00000000000000000000000000000000000000000000000000000000000000a500000000000000000000000000000000000000000000000000000000000000bd0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000009f00000000000000000000000000000000000000000000000000000000000000dc00000000000000000000000000000000000000000000000000000000000000190000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000290000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000008200000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000025000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000820000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000d00000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000003a00000000000000000000000000000000000000000000000000000000000000770000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000000d00000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000002a00000000000000000000000000000000000000000000000000000000000000860000000000000000000000000000000000000000000000000000000000000048000000000000000000000000000000000000000000000000000000000000008600000000000000000000000000000000000000000000000000000000000000f7000000000000000000000000000000000000000000000000000000000000000d00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000b00000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000031000000000000000000000000000000000000000000000000000000000000000b0000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000000900000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000005500000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000001300000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000055000000000000000000000000000000000000000000000000000000000000005300000000000000000000000000000000000000000000000000000000000000310000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000550000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000013000000000000000000000000000000000000000000000000000000000000000d00000000000000000000000000000000000000000000000000000000000000470000000000000000000000000000000000000000000000000000000000000065000000000000000000000000000000000000000000000000000000000000006f0000000000000000000000000000000000000000000000000000000000000054000000000000000000000000000000000000000000000000000000000000007200000000000000000000000000000000000000000000000000000000000000750000000000000000000000000000000000000000000000000000000000000073000000000000000000000000000000000000000000000000000000000000007400000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000049000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000063000000000000000000000000000000000000000000000000000000000000002e0000000000000000000000000000000000000000000000000000000000000031000000000000000000000000000000000000000000000000000000000000001b00000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000019000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000055000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000013000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000470000000000000000000000000000000000000000000000000000000000000065000000000000000000000000000000000000000000000000000000000000006f0000000000000000000000000000000000000000000000000000000000000054000000000000000000000000000000000000000000000000000000000000007200000000000000000000000000000000000000000000000000000000000000750000000000000000000000000000000000000000000000000000000000000073000000000000000000000000000000000000000000000000000000000000007400000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000047000000000000000000000000000000000000000000000000000000000000006c000000000000000000000000000000000000000000000000000000000000006f00000000000000000000000000000000000000000000000000000000000000620000000000000000000000000000000000000000000000000000000000000061000000000000000000000000000000000000000000000000000000000000006c0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004300000000000000000000000000000000000000000000000000000000000000410000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000017000000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000003100000000000000000000000000000000000000000000000000000000000000340000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000003800000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000039000000000000000000000000000000000000000000000000000000000000003200000000000000000000000000000000000000000000000000000000000000310000000000000000000000000000000000000000000000000000000000000033000000000000000000000000000000000000000000000000000000000000003900000000000000000000000000000000000000000000000000000000000000330000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000005a0000000000000000000000000000000000000000000000000000000000000017000000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000003200000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000003500000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000003200000000000000000000000000000000000000000000000000000000000000310000000000000000000000000000000000000000000000000000000000000033000000000000000000000000000000000000000000000000000000000000003900000000000000000000000000000000000000000000000000000000000000330000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000005a000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000470000000000000000000000000000000000000000000000000000000000000031000000000000000000000000000000000000000000000000000000000000000b0000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000000900000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000005500000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000001300000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000055000000000000000000000000000000000000000000000000000000000000005300000000000000000000000000000000000000000000000000000000000000310000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000550000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000013000000000000000000000000000000000000000000000000000000000000000d00000000000000000000000000000000000000000000000000000000000000470000000000000000000000000000000000000000000000000000000000000065000000000000000000000000000000000000000000000000000000000000006f0000000000000000000000000000000000000000000000000000000000000054000000000000000000000000000000000000000000000000000000000000007200000000000000000000000000000000000000000000000000000000000000750000000000000000000000000000000000000000000000000000000000000073000000000000000000000000000000000000000000000000000000000000007400000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000049000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000063000000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000003100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000005500000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000001300000000000000000000000000000000000000000000000000000000000000170000000000000000000000000000000000000000000000000000000000000052000000000000000000000000000000000000000000000000000000000000006100000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000069000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000000530000000000000000000000000000000000000000000000000000000000000053000000000000000000000000000000000000000000000000000000000000004c00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000053000000000000000000000000000000000000000000000000000000000000004800000000000000000000000000000000000000000000000000000000000000410000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000003500000000000000000000000000000000000000000000000000000000000000360000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004300000000000000000000000000000000000000000000000000000000000000410000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002d00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000047000000000000000000000000000000000000000000000000000000000000003300000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000082000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000000d00000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000002a00000000000000000000000000000000000000000000000000000000000000860000000000000000000000000000000000000000000000000000000000000048000000000000000000000000000000000000000000000000000000000000008600000000000000000000000000000000000000000000000000000000000000f7000000000000000000000000000000000000000000000000000000000000000d00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000820000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000820000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000008200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000af0000000000000000000000000000000000000000000000000000000000000054000000000000000000000000000000000000000000000000000000000000009b00000000000000000000000000000000000000000000000000000000000000d90000000000000000000000000000000000000000000000000000000000000058000000000000000000000000000000000000000000000000000000000000005d000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000005600000000000000000000000000000000000000000000000000000000000000c600000000000000000000000000000000000000000000000000000000000000d500000000000000000000000000000000000000000000000000000000000000e8000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000f4000000000000000000000000000000000000000000000000000000000000007d0000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000ff00000000000000000000000000000000000000000000000000000000000000d0000000000000000000000000000000000000000000000000000000000000008b000000000000000000000000000000000000000000000000000000000000005a00000000000000000000000000000000000000000000000000000000000000e4000000000000000000000000000000000000000000000000000000000000008e00000000000000000000000000000000000000000000000000000000000000a700000000000000000000000000000000000000000000000000000000000000dd0000000000000000000000000000000000000000000000000000000000000054000000000000000000000000000000000000000000000000000000000000002e00000000000000000000000000000000000000000000000000000000000000d4000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000005d0000000000000000000000000000000000000000000000000000000000000098000000000000000000000000000000000000000000000000000000000000009c000000000000000000000000000000000000000000000000000000000000008d0000000000000000000000000000000000000000000000000000000000000090000000000000000000000000000000000000000000000000000000000000000f00000000000000000000000000000000000000000000000000000000000000bc00000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000065000000000000000000000000000000000000000000000000000000000000005f00000000000000000000000000000000000000000000000000000000000000da000000000000000000000000000000000000000000000000000000000000009a00000000000000000000000000000000000000000000000000000000000000d60000000000000000000000000000000000000000000000000000000000000044000000000000000000000000000000000000000000000000000000000000007c00000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000009f00000000000000000000000000000000000000000000000000000000000000b500000000000000000000000000000000000000000000000000000000000000e9000000000000000000000000000000000000000000000000000000000000004a000000000000000000000000000000000000000000000000000000000000008c000000000000000000000000000000000000000000000000000000000000000b00000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000043000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000bb00000000000000000000000000000000000000000000000000000000000000f4000000000000000000000000000000000000000000000000000000000000009600000000000000000000000000000000000000000000000000000000000000e2000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000f600000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000009100000000000000000000000000000000000000000000000000000000000000660000000000000000000000000000000000000000000000000000000000000031000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000c300000000000000000000000000000000000000000000000000000000000000340000000000000000000000000000000000000000000000000000000000000034000000000000000000000000000000000000000000000000000000000000005f000000000000000000000000000000000000000000000000000000000000003f000000000000000000000000000000000000000000000000000000000000003f0000000000000000000000000000000000000000000000000000000000000091000000000000000000000000000000000000000000000000000000000000002f0000000000000000000000000000000000000000000000000000000000000044000000000000000000000000000000000000000000000000000000000000005f00000000000000000000000000000000000000000000000000000000000000dc00000000000000000000000000000000000000000000000000000000000000c7000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000b60000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000009f0000000000000000000000000000000000000000000000000000000000000086000000000000000000000000000000000000000000000000000000000000004b000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000a300000000000000000000000000000000000000000000000000000000000000ff00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000008300000000000000000000000000000000000000000000000000000000000000c300000000000000000000000000000000000000000000000000000000000000d3000000000000000000000000000000000000000000000000000000000000001f0000000000000000000000000000000000000000000000000000000000000069000000000000000000000000000000000000000000000000000000000000005200000000000000000000000000000000000000000000000000000000000000d6000000000000000000000000000000000000000000000000000000000000009d0000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000000000000000000000000000000000000f00000000000000000000000000000000000000000000000000000000000000c9000000000000000000000000000000000000000000000000000000000000008300000000000000000000000000000000000000000000000000000000000000e7000000000000000000000000000000000000000000000000000000000000001b00000000000000000000000000000000000000000000000000000000000000c4000000000000000000000000000000000000000000000000000000000000007000000000000000000000000000000000000000000000000000000000000000ac000000000000000000000000000000000000000000000000000000000000009400000000000000000000000000000000000000000000000000000000000000e700000000000000000000000000000000000000000000000000000000000000c300000000000000000000000000000000000000000000000000000000000000a4000000000000000000000000000000000000000000000000000000000000006a000000000000000000000000000000000000000000000000000000000000002c00000000000000000000000000000000000000000000000000000000000000bd00000000000000000000000000000000000000000000000000000000000000b8000000000000000000000000000000000000000000000000000000000000009e000000000000000000000000000000000000000000000000000000000000006900000000000000000000000000000000000000000000000000000000000000d800000000000000000000000000000000000000000000000000000000000000be000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000008f00000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000063000000000000000000000000000000000000000000000000000000000000005a000000000000000000000000000000000000000000000000000000000000006800000000000000000000000000000000000000000000000000000000000000710000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000de0000000000000000000000000000000000000000000000000000000000000015000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000bf00000000000000000000000000000000000000000000000000000000000000cc00000000000000000000000000000000000000000000000000000000000000d300000000000000000000000000000000000000000000000000000000000000bf000000000000000000000000000000000000000000000000000000000000003e000000000000000000000000000000000000000000000000000000000000004800000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000055000000000000000000000000000000000000000000000000000000000000007a00000000000000000000000000000000000000000000000000000000000000b300000000000000000000000000000000000000000000000000000000000000d70000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000fc000000000000000000000000000000000000000000000000000000000000009b00000000000000000000000000000000000000000000000000000000000000fd000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000a7000000000000000000000000000000000000000000000000000000000000008c000000000000000000000000000000000000000000000000000000000000008c00000000000000000000000000000000000000000000000000000000000000db00000000000000000000000000000000000000000000000000000000000000a7000000000000000000000000000000000000000000000000000000000000008e00000000000000000000000000000000000000000000000000000000000000f1000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000006300000000000000000000000000000000000000000000000000000000000000dc00000000000000000000000000000000000000000000000000000000000000b30000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002f000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000af000000000000000000000000000000000000000000000000000000000000005700000000000000000000000000000000000000000000000000000000000000c3000000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000004800000000000000000000000000000000000000000000000000000000000000a700000000000000000000000000000000000000000000000000000000000000830000000000000000000000000000000000000000000000000000000000000068000000000000000000000000000000000000000000000000000000000000002100000000000000000000000000000000000000000000000000000000000000a7000000000000000000000000000000000000000000000000000000000000002f00000000000000000000000000000000000000000000000000000000000000e700000000000000000000000000000000000000000000000000000000000000a7000000000000000000000000000000000000000000000000000000000000003f00000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000000b5000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000fc00000000000000000000000000000000000000000000000000000000000000f5000000000000000000000000000000000000000000000000000000000000008400000000000000000000000000000000000000000000000000000000000000d1000000000000000000000000000000000000000000000000000000000000005300000000000000000000000000000000000000000000000000000000000000bc000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000072000000000000000000000000000000000000000000000000000000000000004f0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000004200000000000000000000000000000000000000000000000000000000000000b8000000000000000000000000000000000000000000000000000000000000009800000000000000000000000000000000000000000000000000000000000000ad00000000000000000000000000000000000000000000000000000000000000190000000000000000000000000000000000000000000000000000000000000088000000000000000000000000000000000000000000000000000000000000005700000000000000000000000000000000000000000000000000000000000000d7000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000ec000000000000000000000000000000000000000000000000000000000000008700000000000000000000000000000000000000000000000000000000000000bf000000000000000000000000000000000000000000000000000000000000007e0000000000000000000000000000000000000000000000000000000000000087000000000000000000000000000000000000000000000000000000000000004e00000000000000000000000000000000000000000000000000000000000000a3000000000000000000000000000000000000000000000000000000000000002100000000000000000000000000000000000000000000000000000000000000f9000000000000000000000000000000000000000000000000000000000000005300000000000000000000000000000000000000000000000000000000000000fd000000000000000000000000000000000000000000000000000000000000003600000000000000000000000000000000000000000000000000000000000000980000000000000000000000000000000000000000000000000000000000000048000000000000000000000000000000000000000000000000000000000000008d00000000000000000000000000000000000000000000000000000000000000d600000000000000000000000000000000000000000000000000000000000000f800000000000000000000000000000000000000000000000000000000000000bb000000000000000000000000000000000000000000000000000000000000004800000000000000000000000000000000000000000000000000000000000000f2000000000000000000000000000000000000000000000000000000000000002900000000000000000000000000000000000000000000000000000000000000c8000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000000d100000000000000000000000000000000000000000000000000000000000000cc000000000000000000000000000000000000000000000000000000000000005400000000000000000000000000000000000000000000000000000000000000480000000000000000000000000000000000000000000000000000000000000053000000000000000000000000000000000000000000000000000000000000008b00000000000000000000000000000000000000000000000000000000000000af00000000000000000000000000000000000000000000000000000000000000b70000000000000000000000000000000000000000000000000000000000000065000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000bf00000000000000000000000000000000000000000000000000000000000000290000000000000000000000000000000000000000000000000000000000000033000000000000000000000000000000000000000000000000000000000000002900000000000000000000000000000000000000000000000000000000000000d900000000000000000000000000000000000000000000000000000000000000290000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000004800000000000000000000000000000000000000000000000000000000000000f800000000000000000000000000000000000000000000000000000000000000ff000000000000000000000000000000000000000000000000000000000000009100000000000000000000000000000000000000000000000000000000000000bc0000000000000000000000000000000000000000000000000000000000000057000000000000000000000000000000000000000000000000000000000000005800000000000000000000000000000000000000000000000000000000000000e50000000000000000000000000000000000000000000000000000000000000035000000000000000000000000000000000000000000000000000000000000002e00000000000000000000000000000000000000000000000000000000000000bb000000000000000000000000000000000000000000000000000000000000006900000000000000000000000000000000000000000000000000000000000000b600000000000000000000000000000000000000000000000000000000000000590000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000a300000000000000000000000000000000000000000000000000000000000000820000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000001d00000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000082000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000190000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000001f000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000055000000000000000000000000000000000000000000000000000000000000001d000000000000000000000000000000000000000000000000000000000000002300000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000007a00000000000000000000000000000000000000000000000000000000000000980000000000000000000000000000000000000000000000000000000000000068000000000000000000000000000000000000000000000000000000000000008d000000000000000000000000000000000000000000000000000000000000008900000000000000000000000000000000000000000000000000000000000000fb00000000000000000000000000000000000000000000000000000000000000ab00000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000011000000000000000000000000000000000000000000000000000000000000007d00000000000000000000000000000000000000000000000000000000000000aa000000000000000000000000000000000000000000000000000000000000007d000000000000000000000000000000000000000000000000000000000000006500000000000000000000000000000000000000000000000000000000000000b800000000000000000000000000000000000000000000000000000000000000ca00000000000000000000000000000000000000000000000000000000000000cc000000000000000000000000000000000000000000000000000000000000004e0000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000001d000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000055000000000000000000000000000000000000000000000000000000000000001d000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000c3000000000000000000000000000000000000000000000000000000000000009c00000000000000000000000000000000000000000000000000000000000000f300000000000000000000000000000000000000000000000000000000000000fc00000000000000000000000000000000000000000000000000000000000000d300000000000000000000000000000000000000000000000000000000000000460000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000003400000000000000000000000000000000000000000000000000000000000000bb00000000000000000000000000000000000000000000000000000000000000ce0000000000000000000000000000000000000000000000000000000000000046000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000007c000000000000000000000000000000000000000000000000000000000000005b00000000000000000000000000000000000000000000000000000000000000f300000000000000000000000000000000000000000000000000000000000000e2000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000cb000000000000000000000000000000000000000000000000000000000000005900000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000055000000000000000000000000000000000000000000000000000000000000001d00000000000000000000000000000000000000000000000000000000000000130000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000ff00000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000ff0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000055000000000000000000000000000000000000000000000000000000000000001d000000000000000000000000000000000000000000000000000000000000000f0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000ff00000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000035000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000055000000000000000000000000000000000000000000000000000000000000001d000000000000000000000000000000000000000000000000000000000000001f0000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000002e0000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000002c0000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000002a00000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000008600000000000000000000000000000000000000000000000000000000000000240000000000000000000000000000000000000000000000000000000000000068000000000000000000000000000000000000000000000000000000000000007400000000000000000000000000000000000000000000000000000000000000740000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000003a000000000000000000000000000000000000000000000000000000000000002f000000000000000000000000000000000000000000000000000000000000002f0000000000000000000000000000000000000000000000000000000000000067000000000000000000000000000000000000000000000000000000000000002e00000000000000000000000000000000000000000000000000000000000000730000000000000000000000000000000000000000000000000000000000000079000000000000000000000000000000000000000000000000000000000000006d00000000000000000000000000000000000000000000000000000000000000630000000000000000000000000000000000000000000000000000000000000062000000000000000000000000000000000000000000000000000000000000002e0000000000000000000000000000000000000000000000000000000000000063000000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000006d000000000000000000000000000000000000000000000000000000000000002f00000000000000000000000000000000000000000000000000000000000000630000000000000000000000000000000000000000000000000000000000000072000000000000000000000000000000000000000000000000000000000000006c0000000000000000000000000000000000000000000000000000000000000073000000000000000000000000000000000000000000000000000000000000002f000000000000000000000000000000000000000000000000000000000000006700000000000000000000000000000000000000000000000000000000000000740000000000000000000000000000000000000000000000000000000000000067000000000000000000000000000000000000000000000000000000000000006c000000000000000000000000000000000000000000000000000000000000006f00000000000000000000000000000000000000000000000000000000000000620000000000000000000000000000000000000000000000000000000000000061000000000000000000000000000000000000000000000000000000000000006c000000000000000000000000000000000000000000000000000000000000002e00000000000000000000000000000000000000000000000000000000000000630000000000000000000000000000000000000000000000000000000000000072000000000000000000000000000000000000000000000000000000000000006c0000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000002e00000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002b000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002b0000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000008600000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000068000000000000000000000000000000000000000000000000000000000000007400000000000000000000000000000000000000000000000000000000000000740000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000003a000000000000000000000000000000000000000000000000000000000000002f000000000000000000000000000000000000000000000000000000000000002f0000000000000000000000000000000000000000000000000000000000000067000000000000000000000000000000000000000000000000000000000000002e00000000000000000000000000000000000000000000000000000000000000730000000000000000000000000000000000000000000000000000000000000079000000000000000000000000000000000000000000000000000000000000006d00000000000000000000000000000000000000000000000000000000000000630000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000000000000000000000000000000000002e0000000000000000000000000000000000000000000000000000000000000063000000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000006d0000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000004c000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000055000000000000000000000000000000000000000000000000000000000000001d00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000004500000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000043000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000410000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000008600000000000000000000000000000000000000000000000000000000000000480000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000008600000000000000000000000000000000000000000000000000000000000000f80000000000000000000000000000000000000000000000000000000000000045000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000036000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000330000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000003100000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002b0000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000250000000000000000000000000000000000000000000000000000000000000068000000000000000000000000000000000000000000000000000000000000007400000000000000000000000000000000000000000000000000000000000000740000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000003a000000000000000000000000000000000000000000000000000000000000002f000000000000000000000000000000000000000000000000000000000000002f000000000000000000000000000000000000000000000000000000000000007700000000000000000000000000000000000000000000000000000000000000770000000000000000000000000000000000000000000000000000000000000077000000000000000000000000000000000000000000000000000000000000002e00000000000000000000000000000000000000000000000000000000000000670000000000000000000000000000000000000000000000000000000000000065000000000000000000000000000000000000000000000000000000000000006f00000000000000000000000000000000000000000000000000000000000000740000000000000000000000000000000000000000000000000000000000000072000000000000000000000000000000000000000000000000000000000000007500000000000000000000000000000000000000000000000000000000000000730000000000000000000000000000000000000000000000000000000000000074000000000000000000000000000000000000000000000000000000000000002e0000000000000000000000000000000000000000000000000000000000000063000000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000006d000000000000000000000000000000000000000000000000000000000000002f000000000000000000000000000000000000000000000000000000000000007200000000000000000000000000000000000000000000000000000000000000650000000000000000000000000000000000000000000000000000000000000073000000000000000000000000000000000000000000000000000000000000006f00000000000000000000000000000000000000000000000000000000000000750000000000000000000000000000000000000000000000000000000000000072000000000000000000000000000000000000000000000000000000000000006300000000000000000000000000000000000000000000000000000000000000650000000000000000000000000000000000000000000000000000000000000073000000000000000000000000000000000000000000000000000000000000002f0000000000000000000000000000000000000000000000000000000000000063000000000000000000000000000000000000000000000000000000000000007000000000000000000000000000000000000000000000000000000000000000730000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000000d00000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000002a00000000000000000000000000000000000000000000000000000000000000860000000000000000000000000000000000000000000000000000000000000048000000000000000000000000000000000000000000000000000000000000008600000000000000000000000000000000000000000000000000000000000000f7000000000000000000000000000000000000000000000000000000000000000d00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000008200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a30000000000000000000000000000000000000000000000000000000000000058000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000c60000000000000000000000000000000000000000000000000000000000000043000000000000000000000000000000000000000000000000000000000000003200000000000000000000000000000000000000000000000000000000000000ac00000000000000000000000000000000000000000000000000000000000000ac000000000000000000000000000000000000000000000000000000000000002f0000000000000000000000000000000000000000000000000000000000000093000000000000000000000000000000000000000000000000000000000000007800000000000000000000000000000000000000000000000000000000000000b700000000000000000000000000000000000000000000000000000000000000ea00000000000000000000000000000000000000000000000000000000000000ae000000000000000000000000000000000000000000000000000000000000005400000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000047000000000000000000000000000000000000000000000000000000000000002d000000000000000000000000000000000000000000000000000000000000007e0000000000000000000000000000000000000000000000000000000000000078000000000000000000000000000000000000000000000000000000000000008d000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000f600000000000000000000000000000000000000000000000000000000000000f8000000000000000000000000000000000000000000000000000000000000006600000000000000000000000000000000000000000000000000000000000000ac00000000000000000000000000000000000000000000000000000000000000d6000000000000000000000000000000000000000000000000000000000000004f000000000000000000000000000000000000000000000000000000000000007300000000000000000000000000000000000000000000000000000000000000d6000000000000000000000000000000000000000000000000000000000000004400000000000000000000000000000000000000000000000000000000000000ef00000000000000000000000000000000000000000000000000000000000000af000000000000000000000000000000000000000000000000000000000000000b00000000000000000000000000000000000000000000000000000000000000cc000000000000000000000000000000000000000000000000000000000000005b00000000000000000000000000000000000000000000000000000000000000c100000000000000000000000000000000000000000000000000000000000000f4000000000000000000000000000000000000000000000000000000000000004f000000000000000000000000000000000000000000000000000000000000009a000000000000000000000000000000000000000000000000000000000000008f0000000000000000000000000000000000000000000000000000000000000049000000000000000000000000000000000000000000000000000000000000007e000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000af00000000000000000000000000000000000000000000000000000000000000c2000000000000000000000000000000000000000000000000000000000000002700000000000000000000000000000000000000000000000000000000000000c7000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000f100000000000000000000000000000000000000000000000000000000000000fb00000000000000000000000000000000000000000000000000000000000000930000000000000000000000000000000000000000000000000000000000000081000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000a9000000000000000000000000000000000000000000000000000000000000007c00000000000000000000000000000000000000000000000000000000000000ef000000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000007e000000000000000000000000000000000000000000000000000000000000006e000000000000000000000000000000000000000000000000000000000000004500000000000000000000000000000000000000000000000000000000000000940000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000008400000000000000000000000000000000000000000000000000000000000000bd00000000000000000000000000000000000000000000000000000000000000ec000000000000000000000000000000000000000000000000000000000000004900000000000000000000000000000000000000000000000000000000000000f100000000000000000000000000000000000000000000000000000000000000c4000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000f400000000000000000000000000000000000000000000000000000000000000af0000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000005900000000000000000000000000000000000000000000000000000000000000830000000000000000000000000000000000000000000000000000000000000087000000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000003b000000000000000000000000000000000000000000000000000000000000009700000000000000000000000000000000000000000000000000000000000000c3000000000000000000000000000000000000000000000000000000000000005a0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000009b000000000000000000000000000000000000000000000000000000000000007b00000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000035000000000000000000000000000000000000000000000000000000000000007b00000000000000000000000000000000000000000000000000000000000000a3000000000000000000000000000000000000000000000000000000000000009500000000000000000000000000000000000000000000000000000000000000330000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000009300000000000000000000000000000000000000000000000000000000000000710000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000004200000000000000000000000000000000000000000000000000000000000000b300000000000000000000000000000000000000000000000000000000000000a900000000000000000000000000000000000000000000000000000000000000d9000000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000004f0000000000000000000000000000000000000000000000000000000000000081000000000000000000000000000000000000000000000000000000000000009200000000000000000000000000000000000000000000000000000000000000fc000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000b6000000000000000000000000000000000000000000000000000000000000007900000000000000000000000000000000000000000000000000000000000000bc0000000000000000000000000000000000000000000000000000000000000084000000000000000000000000000000000000000000000000000000000000004a000000000000000000000000000000000000000000000000000000000000009d0000000000000000000000000000000000000000000000000000000000000077000000000000000000000000000000000000000000000000000000000000000900000000000000000000000000000000000000000000000000000000000000f100000000000000000000000000000000000000000000000000000000000000c5000000000000000000000000000000000000000000000000000000000000008900000000000000000000000000000000000000000000000000000000000000f200000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000000b4000000000000000000000000000000000000000000000000000000000000009c000000000000000000000000000000000000000000000000000000000000005400000000000000000000000000000000000000000000000000000000000000aa0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000000d00000000000000000000000000000000000000000000000000000000000000ba000000000000000000000000000000000000000000000000000000000000004f00000000000000000000000000000000000000000000000000000000000000ef0000000000000000000000000000000000000000000000000000000000000093000000000000000000000000000000000000000000000000000000000000001900000000000000000000000000000000000000000000000000000000000000ec00000000000000000000000000000000000000000000000000000000000000ef000000000000000000000000000000000000000000000000000000000000007d000000000000000000000000000000000000000000000000000000000000004e000000000000000000000000000000000000000000000000000000000000006100000000000000000000000000000000000000000000000000000000000000a3000000000000000000000000000000000000000000000000000000000000008e0000000000000000000000000000000000000000000000000000000000000076000000000000000000000000000000000000000000000000000000000000009c000000000000000000000000000000000000000000000000000000000000005900000000000000000000000000000000000000000000000000000000000000cf000000000000000000000000000000000000000000000000000000000000008c000000000000000000000000000000000000000000000000000000000000009400000000000000000000000000000000000000000000000000000000000000b10000000000000000000000000000000000000000000000000000000000000084000000000000000000000000000000000000000000000000000000000000009700000000000000000000000000000000000000000000000000000000000000f7000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000b9000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000b800000000000000000000000000000000000000000000000000000000000000b200000000000000000000000000000000000000000000000000000000000000c6000000000000000000000000000000000000000000000000000000000000004f0000000000000000000000000000000000000000000000000000000000000013000000000000000000000000000000000000000000000000000000000000007900000000000000000000000000000000000000000000000000000000000000db00000000000000000000000000000000000000000000000000000000000000bf000000000000000000000000000000000000000000000000000000000000004f0000000000000000000000000000000000000000000000000000000000000051000000000000000000000000000000000000000000000000000000000000001b000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000069000000000000000000000000000000000000000000000000000000000000000d0000000000000000000000000000000000000000000000000000000000000051000000000000000000000000000000000000000000000000000000000000002a00000000000000000000000000000000000000000000000000000000000000c100000000000000000000000000000000000000000000000000000000000000d6000000000000000000000000000000000000000000000000000000000000001500000000000000000000000000000000000000000000000000000000000000ff0000000000000000000000000000000000000000000000000000000000000037000000000000000000000000000000000000000000000000000000000000005100000000000000000000000000000000000000000000000000000000000000340000000000000000000000000000000000000000000000000000000000000065000000000000000000000000000000000000000000000000000000000000005100000000000000000000000000000000000000000000000000000000000000f4000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000be0000000000000000000000000000000000000000000000000000000000000038000000000000000000000000000000000000000000000000000000000000006a00000000000000000000000000000000000000000000000000000000000000ec000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000ab00000000000000000000000000000000000000000000000000000000000000bf000000000000000000000000000000000000000000000000000000000000003d000000000000000000000000000000000000000000000000000000000000007b00000000000000000000000000000000000000000000000000000000000000390000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000007b00000000000000000000000000000000000000000000000000000000000000f400000000000000000000000000000000000000000000000000000000000000f300000000000000000000000000000000000000000000000000000000000000fb000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000a100000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000000c8000000000000000000000000000000000000000000000000000000000000007e000000000000000000000000000000000000000000000000000000000000004e0000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000000000000000000000000000000000008d00000000000000000000000000000000000000000000000000000000000000cd000000000000000000000000000000000000000000000000000000000000008c00000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000055000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000fe000000000000000000000000000000000000000000000000000000000000003a00000000000000000000000000000000000000000000000000000000000000ca000000000000000000000000000000000000000000000000000000000000005d0000000000000000000000000000000000000000000000000000000000000025000000000000000000000000000000000000000000000000000000000000000f00000000000000000000000000000000000000000000000000000000000000f8000000000000000000000000000000000000000000000000000000000000001d00000000000000000000000000000000000000000000000000000000000000a3000000000000000000000000000000000000000000000000000000000000004a00000000000000000000000000000000000000000000000000000000000000740000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000004f000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000000055000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000075000000000000000000000000000000000000000000000000000000000000002500000000000000000000000000000000000000000000000000000000000000a60000000000000000000000000000000000000000000000000000000000000033000000000000000000000000000000000000000000000000000000000000002e00000000000000000000000000000000000000000000000000000000000000ba000000000000000000000000000000000000000000000000000000000000004b00000000000000000000000000000000000000000000000000000000000000a5000000000000000000000000000000000000000000000000000000000000005d0000000000000000000000000000000000000000000000000000000000000053000000000000000000000000000000000000000000000000000000000000009a000000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000e1000000000000000000000000000000000000000000000000000000000000008d000000000000000000000000000000000000000000000000000000000000005f0000000000000000000000000000000000000000000000000000000000000061000000000000000000000000000000000000000000000000000000000000002c00000000000000000000000000000000000000000000000000000000000000af00000000000000000000000000000000000000000000000000000000000000cc00000000000000000000000000000000000000000000000000000000000000ef00000000000000000000000000000000000000000000000000000000000000b0000000000000000000000000000000000000000000000000000000000000009900000000000000000000000000000000000000000000000000000000000000a1000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000ff000000000000000000000000000000000000000000000000000000000000000b00000000000000000000000000000000000000000000000000000000000000f20000000000000000000000000000000000000000000000000000000000000062000000000000000000000000000000000000000000000000000000000000004c0000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000980000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000f60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001700000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000f0000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000081000000000000000000000000000000000000000000000000000000000000006b0000000000000000000000000000000000000000000000000000000000000041000000000000000000000000000000000000000000000000000000000000003c00000000000000000000000000000000000000000000000000000000000000540000000000000000000000000000000000000000000000000000000000000069000000000000000000000000000000000000000000000000000000000000009e00000000000000000000000000000000000000000000000000000000000000f800000000000000000000000000000000000000000000000000000000000000a6000000000000000000000000000000000000000000000000000000000000003400000000000000000000000000000000000000000000000000000000000000fe00000000000000000000000000000000000000000000000000000000000000e300000000000000000000000000000000000000000000000000000000000000b00000000000000000000000000000000000000000000000000000000000000036000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000ba000000000000000000000000000000000000000000000000000000000000003800000000000000000000000000000000000000000000000000000000000000cc000000000000000000000000000000000000000000000000000000000000008e00000000000000000000000000000000000000000000000000000000000000ed0000000000000000000000000000000000000000000000000000000000000025000000000000000000000000000000000000000000000000000000000000006700000000000000000000000000000000000000000000000000000000000000a100000000000000000000000000000000000000000000000000000000000000af00000000000000000000000000000000000000000000000000000000000000a400000000000000000000000000000000000000000000000000000000000000fa000000000000000000000000000000000000000000000000000000000000000d00000000000000000000000000000000000000000000000000000000000000c7000000000000000000000000000000000000000000000000000000000000009b000000000000000000000000000000000000000000000000000000000000009c00000000000000000000000000000000000000000000000000000000000000d60000000000000000000000000000000000000000000000000000000000000036000000000000000000000000000000000000000000000000000000000000002c00000000000000000000000000000000000000000000000000000000000000b1000000000000000000000000000000000000000000000000000000000000009600000000000000000000000000000000000000000000000000000000000000c4000000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000007a0000000000000000000000000000000000000000000000000000000000000086000000000000000000000000000000000000000000000000000000000000009500000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000004f0000000000000000000000000000000000000000000000000000000000000078000000000000000000000000000000000000000000000000000000000000003600000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000008600000000000000000000000000000000000000000000000000000000000000ef00000000000000000000000000000000000000000000000000000000000000fa000000000000000000000000000000000000000000000000000000000000006600000000000000000000000000000000000000000000000000000000000000fb00000000000000000000000000000000000000000000000000000000000000af000000000000000000000000000000000000000000000000000000000000001f00000000000000000000000000000000000000000000000000000000000000a3000000000000000000000000000000000000000000000000000000000000004400000000000000000000000000000000000000000000000000000000000000a50000000000000000000000000000000000000000000000000000000000000052000000000000000000000000000000000000000000000000000000000000002f00000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000093000000000000000000000000000000000000000000000000000000000000009e0000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000009c000000000000000000000000000000000000000000000000000000000000001d0000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000009d00000000000000000000000000000000000000000000000000000000000000fc00000000000000000000000000000000000000000000000000000000000000e900000000000000000000000000000000000000000000000000000000000000ae00000000000000000000000000000000000000000000000000000000000000ae00000000000000000000000000000000000000000000000000000000000000f900000000000000000000000000000000000000000000000000000000000000660000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000003600000000000000000000000000000000000000000000000000000000000000ef000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000b700000000000000000000000000000000000000000000000000000000000000a500000000000000000000000000000000000000000000000000000000000000c1000000000000000000000000000000000000000000000000000000000000006700000000000000000000000000000000000000000000000000000000000000f600000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000900000000000000000000000000000000000000000000000000000000000000e1000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000009500000000000000000000000000000000000000000000000000000000000000e3000000000000000000000000000000000000000000000000000000000000009300000000000000000000000000000000000000000000000000000000000000db00000000000000000000000000000000000000000000000000000000000000f400000000000000000000000000000000000000000000000000000000000000e6000000000000000000000000000000000000000000000000000000000000009b000000000000000000000000000000000000000000000000000000000000006c000000000000000000000000000000000000000000000000000000000000006a000000000000000000000000000000000000000000000000000000000000004b0000000000000000000000000000000000000000000000000000000000000055000000000000000000000000000000000000000000000000000000000000004900000000000000000000000000000000000000000000000000000000000000ea000000000000000000000000000000000000000000000000000000000000001b000000000000000000000000000000000000000000000000000000000000004900000000000000000000000000000000000000000000000000000000000000e300000000000000000000000000000000000000000000000000000000000000ec0000000000000000000000000000000000000000000000000000000000000051000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000b600000000000000000000000000000000000000000000000000000000000000b7000000000000000000000000000000000000000000000000000000000000009600000000000000000000000000000000000000000000000000000000000000630000000000000000000000000000000000000000000000000000000000000025000000000000000000000000000000000000000000000000000000000000008a00000000000000000000000000000000000000000000000000000000000000a900000000000000000000000000000000000000000000000000000000000000e6000000000000000000000000000000000000000000000000000000000000005200000000000000000000000000000000000000000000000000000000000000bf000000000000000000000000000000000000000000000000000000000000003b000000000000000000000000000000000000000000000000000000000000003d000000000000000000000000000000000000000000000000000000000000001300000000000000000000000000000000000000000000000000000000000000e7000000000000000000000000000000000000000000000000000000000000002e00000000000000000000000000000000000000000000000000000000000000b9000000000000000000000000000000000000000000000000000000000000003b000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c5000000000000000000000000000000000000000000000000000000000000008e00000000000000000000000000000000000000000000000000000000000000d200000000000000000000000000000000000000000000000000000000000000e100000000000000000000000000000000000000000000000000000000000000a8000000000000000000000000000000000000000000000000000000000000009100000000000000000000000000000000000000000000000000000000000000e200000000000000000000000000000000000000000000000000000000000000c2000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000ec00000000000000000000000000000000000000000000000000000000000000fe000000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000000000000000000000000000000000004b0000000000000000000000000000000000000000000000000000000000000017000000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000001f000000000000000000000000000000000000000000000000000000000000006e000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000ee000000000000000000000000000000000000000000000000000000000000002500000000000000000000000000000000000000000000000000000000000000a500000000000000000000000000000000000000000000000000000000000000ab0000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000007000000000000000000000000000000000000000000000000000000000000000df00000000000000000000000000000000000000000000000000000000000000d5000000000000000000000000000000000000000000000000000000000000007800000000000000000000000000000000000000000000000000000000000000f0000000000000000000000000000000000000000000000000000000000000001f000000000000000000000000000000000000000000000000000000000000005e000000000000000000000000000000000000000000000000000000000000001f00000000000000000000000000000000000000000000000000000000000000f1000000000000000000000000000000000000000000000000000000000000005b0000000000000000000000000000000000000000000000000000000000000097000000000000000000000000000000000000000000000000000000000000006900000000000000000000000000000000000000000000000000000000000000fe0000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a3000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000870000000000000000000000000000000000000000000000000000000000000094000000000000000000000000000000000000000000000000000000000000007700000000000000000000000000000000000000000000000000000000000000df000000000000000000000000000000000000000000000000000000000000004f00000000000000000000000000000000000000000000000000000000000000b1000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000007a00000000000000000000000000000000000000000000000000000000000000e100000000000000000000000000000000000000000000000000000000000000b900000000000000000000000000000000000000000000000000000000000000ce000000000000000000000000000000000000000000000000000000000000006200000000000000000000000000000000000000000000000000000000000000af0000000000000000000000000000000000000000000000000000000000000027000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000005b0000000000000000000000000000000000000000000000000000000000000036000000000000000000000000000000000000000000000000000000000000003e000000000000000000000000000000000000000000000000000000000000004c00000000000000000000000000000000000000000000000000000000000000b80000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000005c000000000000000000000000000000000000000000000000000000000000009900000000000000000000000000000000000000000000000000000000000000c70000000000000000000000000000000000000000000000000000000000000027000000000000000000000000000000000000000000000000000000000000002b000000000000000000000000000000000000000000000000000000000000007300000000000000000000000000000000000000000000000000000000000000b7000000000000000000000000000000000000000000000000000000000000007a00000000000000000000000000000000000000000000000000000000000000a2000000000000000000000000000000000000000000000000000000000000008600000000000000000000000000000000000000000000000000000000000000bd00000000000000000000000000000000000000000000000000000000000000cc00000000000000000000000000000000000000000000000000000000000000ad000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000de000000000000000000000000000000000000000000000000000000000000008a0000000000000000000000000000000000000000000000000000000000000067000000000000000000000000000000000000000000000000000000000000002500000000000000000000000000000000000000000000000000000000000000b7000000000000000000000000000000000000000000000000000000000000007300000000000000000000000000000000000000000000000000000000000000c500000000000000000000000000000000000000000000000000000000000000ff00000000000000000000000000000000000000000000000000000000000000f5000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000a400000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000000ad00000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000090000000000000000000000000000000000000000000000000000000000000008d000000000000000000000000000000000000000000000000000000000000008c000000000000000000000000000000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000000000ce000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000e9000000000000000000000000000000000000000000000000000000000000007b00000000000000000000000000000000000000000000000000000000000000ed000000000000000000000000000000000000000000000000000000000000007700000000000000000000000000000000000000000000000000000000000000f600000000000000000000000000000000000000000000000000000000000000c50000000000000000000000000000000000000000000000000000000000000092000000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000000000000000000000000000000000000900000000000000000000000000000000000000000000000000000000000000da00000000000000000000000000000000000000000000000000000000000000e400000000000000000000000000000000000000000000000000000000000000aa0000000000000000000000000000000000000000000000000000000000000090000000000000000000000000000000000000000000000000000000000000007e00000000000000000000000000000000000000000000000000000000000000ae000000000000000000000000000000000000000000000000000000000000007c0000000000000000000000000000000000000000000000000000000000000095000000000000000000000000000000000000000000000000000000000000009a000000000000000000000000000000000000000000000000000000000000005600000000000000000000000000000000000000000000000000000000000000c200000000000000000000000000000000000000000000000000000000000000760000000000000000000000000000000000000000000000000000000000000013000000000000000000000000000000000000000000000000000000000000004f000000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000000000000000000000000000000000cd000000000000000000000000000000000000000000000000000000000000002900000000000000000000000000000000000000000000000000000000000000520000000000000000000000000000000000000000000000000000000000000023000000000000000000000000000000000000000000000000000000000000005600000000000000000000000000000000000000000000000000000000000000ab000000000000000000000000000000000000000000000000000000000000003a000000000000000000000000000000000000000000000000000000000000002a00000000000000000000000000000000000000000000000000000000000000d4000000000000000000000000000000000000000000000000000000000000005700000000000000000000000000000000000000000000000000000000000000b400000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000000000043000000000000000000000000000000000000000000000000000000000000001d000000000000000000000000000000000000000000000000000000000000004a000000000000000000000000000000000000000000000000000000000000004b000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000021000000000000000000000000000000000000000000000000000000000000006b00000000000000000000000000000000000000000000000000000000000000410000000000000000000000000000000000000000000000000000000000000017000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000e7000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000001c0000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000000000000000000000000000000000006a0000000000000000000000000000000000000000000000000000000000000039000000000000000000000000000000000000000000000000000000000000004100000000000000000000000000000000000000000000000000000000000000a200000000000000000000000000000000000000000000000000000000000000ca00000000000000000000000000000000000000000000000000000000000000a3000000000000000000000000000000000000000000000000000000000000006c00000000000000000000000000000000000000000000000000000000000000bf00000000000000000000000000000000000000000000000000000000000000130000000000000000000000000000000000000000000000000000000000000015000000000000000000000000000000000000000000000000000000000000007100000000000000000000000000000000000000000000000000000000000000dc00000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000094000000000000000000000000000000000000000000000000000000000000009d00000000000000000000000000000000000000000000000000000000000000ea0000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000006700000000000000000000000000000000000000000000000000000000000000a2000000000000000000000000000000000000000000000000000000000000007a000000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000004b000000000000000000000000000000000000000000000000000000000000004800000000000000000000000000000000000000000000000000000000000000ab000000000000000000000000000000000000000000000000000000000000006300000000000000000000000000000000000000000000000000000000000000230000000000000000000000000000000000000000000000000000000000000068000000000000000000000000000000000000000000000000000000000000009e00000000000000000000000000000000000000000000000000000000000000a4000000000000000000000000000000000000000000000000000000000000006d000000000000000000000000000000000000000000000000000000000000006a000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000cf000000000000000000000000000000000000000000000000000000000000004e000000000000000000000000000000000000000000000000000000000000004a00000000000000000000000000000000000000000000000000000000000000c2000000000000000000000000000000000000000000000000000000000000008a0000000000000000000000000000000000000000000000000000000000000095000000000000000000000000000000000000000000000000000000000000001900000000000000000000000000000000000000000000000000000000000000ac0000000000000000000000000000000000000000000000000000000000000017000000000000000000000000000000000000000000000000000000000000003700000000000000000000000000000000000000000000000000000000000000a500000000000000000000000000000000000000000000000000000000000000d700000000000000000000000000000000000000000000000000000000000000a7000000000000000000000000000000000000000000000000000000000000007600000000000000000000000000000000000000000000000000000000000000c1000000000000000000000000000000000000000000000000000000000000005c000000000000000000000000000000000000000000000000000000000000009b0000000000000000000000000000000000000000000000000000000000000081000000000000000000000000000000000000000000000000000000000000007700000000000000000000000000000000000000000000000000000000000000860000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000054000000000000000000000000000000000000000000000000000000000000009a000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000031000000000000000000000000000000000000000000000000000000000000002100000000000000000000000000000000000000000000000000000000000000ab00000000000000000000000000000000000000000000000000000000000000c100000000000000000000000000000000000000000000000000000000000000550000000000000000000000000000000000000000000000000000000000000027000000000000000000000000000000000000000000000000000000000000008b00000000000000000000000000000000000000000000000000000000000000a90000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000006c00000000000000000000000000000000000000000000000000000000000000f2000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000130000000000000000000000000000000000000000000000000000000000000093000000000000000000000000000000000000000000000000000000000000006600000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000000000046000000000000000000000000000000000000000000000000000000000000004c0000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000f6000000000000000000000000000000000000000000000000000000000000005200000000000000000000000000000000000000000000000000000000000000650000000000000000000000000000000000000000000000000000000000000047000000000000000000000000000000000000000000000000000000000000004b000000000000000000000000000000000000000000000000000000000000005a000000000000000000000000000000000000000000000000000000000000008900000000000000000000000000000000000000000000000000000000000000c100000000000000000000000000000000000000000000000000000000000000ba00000000000000000000000000000000000000000000000000000000000000b9000000000000000000000000000000000000000000000000000000000000005f00000000000000000000000000000000000000000000000000000000000000e10000000000000000000000000000000000000000000000000000000000000052000000000000000000000000000000000000000000000000000000000000006e00000000000000000000000000000000000000000000000000000000000000fc000000000000000000000000000000000000000000000000000000000000009800000000000000000000000000000000000000000000000000000000000000c300000000000000000000000000000000000000000000000000000000000000670000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000007b00000000000000000000000000000000000000000000000000000000000000a4000000000000000000000000000000000000000000000000000000000000009300000000000000000000000000000000000000000000000000000000000000c5000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f2000000000000000000000000000000000000000000000000000000000000000b0000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000009e00000000000000000000000000000000000000000000000000000000000000d2000000000000000000000000000000000000000000000000000000000000002500000000000000000000000000000000000000000000000000000000000000ec000000000000000000000000000000000000000000000000000000000000009600000000000000000000000000000000000000000000000000000000000000c600000000000000000000000000000000000000000000000000000000000000ce00000000000000000000000000000000000000000000000000000000000000c90000000000000000000000000000000000000000000000000000000000000098000000000000000000000000000000000000000000000000000000000000009b000000000000000000000000000000000000000000000000000000000000002d00000000000000000000000000000000000000000000000000000000000000c700000000000000000000000000000000000000000000000000000000000000780000000000000000000000000000000000000000000000000000000000000047000000000000000000000000000000000000000000000000000000000000009a0000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000009e00000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000061000000000000000000000000000000000000000000000000000000000000002d000000000000000000000000000000000000000000000000000000000000001b000000000000000000000000000000000000000000000000000000000000003600000000000000000000000000000000000000000000000000000000000000d900000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000cb000000000000000000000000000000000000000000000000000000000000005600000000000000000000000000000000000000000000000000000000000000b9000000000000000000000000000000000000000000000000000000000000002b000000000000000000000000000000000000000000000000000000000000007100000000000000000000000000000000000000000000000000000000000000e400000000000000000000000000000000000000000000000000000000000000a4000000000000000000000000000000000000000000000000000000000000001d00000000000000000000000000000000000000000000000000000000000000a80000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000002a0000000000000000000000000000000000000000000000000000000000000061000000000000000000000000000000000000000000000000000000000000006700000000000000000000000000000000000000000000000000000000000000fa00000000000000000000000000000000000000000000000000000000000000c900000000000000000000000000000000000000000000000000000000000000f300000000000000000000000000000000000000000000000000000000000000f800000000000000000000000000000000000000000000000000000000000000ef000000000000000000000000000000000000000000000000000000000000008e00000000000000000000000000000000000000000000000000000000000000a4000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000003600000000000000000000000000000000000000000000000000000000000000d800000000000000000000000000000000000000000000000000000000000000ca000000000000000000000000000000000000000000000000000000000000003700000000000000000000000000000000000000000000000000000000000000f800000000000000000000000000000000000000000000000000000000000000620000000000000000000000000000000000000000000000000000000000000007000000000000000000000000000000000000000000000000000000000000002d00000000000000000000000000000000000000000000000000000000000000c4000000000000000000000000000000000000000000000000000000000000002100000000000000000000000000000000000000000000000000000000000000d50000000000000000000000000000000000000000000000000000000000000045000000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000003400000000000000000000000000000000000000000000000000000000000000f3000000000000000000000000000000000000000000000000000000000000008b00000000000000000000000000000000000000000000000000000000000000a10000000000000000000000000000000000000000000000000000000000000019000000000000000000000000000000000000000000000000000000000000002300000000000000000000000000000000000000000000000000000000000000d2000000000000000000000000000000000000000000000000000000000000001d00000000000000000000000000000000000000000000000000000000000000a7000000000000000000000000000000000000000000000000000000000000007600000000000000000000000000000000000000000000000000000000000000d200000000000000000000000000000000000000000000000000000000000000130000000000000000000000000000000000000000000000000000000000000041000000000000000000000000000000000000000000000000000000000000002900000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000f5000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000e70000000000000000000000000000000000000000000000000000000000000084000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000005e000000000000000000000000000000000000000000000000000000000000003a00000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000081000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000c1000000000000000000000000000000000000000000000000000000000000009a0000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000004800000000000000000000000000000000000000000000000000000000000000c60000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000005a00000000000000000000000000000000000000000000000000000000000000f900000000000000000000000000000000000000000000000000000000000000cf000000000000000000000000000000000000000000000000000000000000004800000000000000000000000000000000000000000000000000000000000000b3000000000000000000000000000000000000000000000000000000000000007b00000000000000000000000000000000000000000000000000000000000000970000000000000000000000000000000000000000000000000000000000000078000000000000000000000000000000000000000000000000000000000000001900000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000000db000000000000000000000000000000000000000000000000000000000000006a000000000000000000000000000000000000000000000000000000000000006d000000000000000000000000000000000000000000000000000000000000007800000000000000000000000000000000000000000000000000000000000000cd000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000cc000000000000000000000000000000000000000000000000000000000000005d000000000000000000000000000000000000000000000000000000000000002b000000000000000000000000000000000000000000000000000000000000005f00000000000000000000000000000000000000000000000000000000000000c4000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000011000000000000000000000000000000000000000000000000000000000000009500000000000000000000000000000000000000000000000000000000000000bc000000000000000000000000000000000000000000000000000000000000009c0000000000000000000000000000000000000000000000000000000000000046000000000000000000000000000000000000000000000000000000000000000b00000000000000000000000000000000000000000000000000000000000000d4000000000000000000000000000000000000000000000000000000000000009e000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000fc00000000000000000000000000000000000000000000000000000000000000e600000000000000000000000000000000000000000000000000000000000000ed00000000000000000000000000000000000000000000000000000000000000b6000000000000000000000000000000000000000000000000000000000000009400000000000000000000000000000000000000000000000000000000000000930000000000000000000000000000000000000000000000000000000000000047000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000023000000000000000000000000000000000000000000000000000000000000004400000000000000000000000000000000000000000000000000000000000000e700000000000000000000000000000000000000000000000000000000000000bc00000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000031000000000000000000000000000000000000000000000000000000000000009100000000000000000000000000000000000000000000000000000000000000df0000000000000000000000000000000000000000000000000000000000000097000000000000000000000000000000000000000000000000000000000000007700000000000000000000000000000000000000000000000000000000000000aa000000000000000000000000000000000000000000000000000000000000001900000000000000000000000000000000000000000000000000000000000000ae00000000000000000000000000000000000000000000000000000000000000d0000000000000000000000000000000000000000000000000000000000000005f00000000000000000000000000000000000000000000000000000000000000a1000000000000000000000000000000000000000000000000000000000000002e00000000000000000000000000000000000000000000000000000000000000c800000000000000000000000000000000000000000000000000000000000000cd00000000000000000000000000000000000000000000000000000000000000ce00000000000000000000000000000000000000000000000000000000000000b200000000000000000000000000000000000000000000000000000000000000b100000000000000000000000000000000000000000000000000000000000000cb000000000000000000000000000000000000000000000000000000000000002d00000000000000000000000000000000000000000000000000000000000000920000000000000000000000000000000000000000000000000000000000000043000000000000000000000000000000000000000000000000000000000000003f000000000000000000000000000000000000000000000000000000000000005c0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000003b000000000000000000000000000000000000000000000000000000000000007300000000000000000000000000000000000000000000000000000000000000c100000000000000000000000000000000000000000000000000000000000000d10000000000000000000000000000000000000000000000000000000000000038000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000e50000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000000000000000000000000000000000003e00000000000000000000000000000000000000000000000000000000000000b4000000000000000000000000000000000000000000000000000000000000002d0000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000b6000000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000d90000000000000000000000000000000000000000000000000000000000000096000000000000000000000000000000000000000000000000000000000000004400000000000000000000000000000000000000000000000000000000000000a2000000000000000000000000000000000000000000000000000000000000007c000000000000000000000000000000000000000000000000000000000000006100000000000000000000000000000000000000000000000000000000000000ec0000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000005a00000000000000000000000000000000000000000000000000000000000000d90000000000000000000000000000000000000000000000000000000000000095000000000000000000000000000000000000000000000000000000000000008b00000000000000000000000000000000000000000000000000000000000000f3000000000000000000000000000000000000000000000000000000000000005a0000000000000000000000000000000000000000000000000000000000000046000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000085000000000000000000000000000000000000000000000000000000000000007200000000000000000000000000000000000000000000000000000000000000f1000000000000000000000000000000000000000000000000000000000000001f00000000000000000000000000000000000000000000000000000000000000da00000000000000000000000000000000000000000000000000000000000000230000000000000000000000000000000000000000000000000000000000000045000000000000000000000000000000000000000000000000000000000000003f000000000000000000000000000000000000000000000000000000000000009100000000000000000000000000000000000000000000000000000000000000a6000000000000000000000000000000000000000000000000000000000000005f000000000000000000000000000000000000000000000000000000000000005600000000000000000000000000000000000000000000000000000000000000c8000000000000000000000000000000000000000000000000000000000000007900000000000000000000000000000000000000000000000000000000000000c400000000000000000000000000000000000000000000000000000000000000ab000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000f0000000000000000000000000000000000000000000000000000000000000004f00000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000009e0000000000000000000000000000000000000000000000000000000000000067000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000008f00000000000000000000000000000000000000000000000000000000000000df00000000000000000000000000000000000000000000000000000000000000470000000000000000000000000000000000000000000000000000000000000083000000000000000000000000000000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000006e000000000000000000000000000000000000000000000000000000000000007100000000000000000000000000000000000000000000000000000000000000cd000000000000000000000000000000000000000000000000000000000000002a00000000000000000000000000000000000000000000000000000000000000db00000000000000000000000000000000000000000000000000000000000000cf00000000000000000000000000000000000000000000000000000000000000d600000000000000000000000000000000000000000000000000000000000000f2000000000000000000000000000000000000000000000000000000000000006e00000000000000000000000000000000000000000000000000000000000000d90000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000000900000000000000000000000000000000000000000000000000000000000000f6000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000027000000000000000000000000000000000000000000000000000000000000003300000000000000000000000000000000000000000000000000000000000000ff0000000000000000000000000000000000000000000000000000000000000046000000000000000000000000000000000000000000000000000000000000006a000000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000002f00000000000000000000000000000000000000000000000000000000000000460000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005a00000000000000000000000000000000000000000000000000000000000000af00000000000000000000000000000000000000000000000000000000000000a900000000000000000000000000000000000000000000000000000000000000a200000000000000000000000000000000000000000000000000000000000000e8000000000000000000000000000000000000000000000000000000000000005e000000000000000000000000000000000000000000000000000000000000009100000000000000000000000000000000000000000000000000000000000000ac00000000000000000000000000000000000000000000000000000000000000d3000000000000000000000000000000000000000000000000000000000000009b000000000000000000000000000000000000000000000000000000000000000d00000000000000000000000000000000000000000000000000000000000000a1000000000000000000000000000000000000000000000000000000000000002c0000000000000000000000000000000000000000000000000000000000000092000000000000000000000000000000000000000000000000000000000000003100000000000000000000000000000000000000000000000000000000000000e400000000000000000000000000000000000000000000000000000000000000de0000000000000000000000000000000000000000000000000000000000000019000000000000000000000000000000000000000000000000000000000000009f000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000c200000000000000000000000000000000000000000000000000000000000000b2000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000ac00000000000000000000000000000000000000000000000000000000000000ba000000000000000000000000000000000000000000000000000000000000006900000000000000000000000000000000000000000000000000000000000000ff00000000000000000000000000000000000000000000000000000000000000d400000000000000000000000000000000000000000000000000000000000000d700000000000000000000000000000000000000000000000000000000000000cc0000000000000000000000000000000000000000000000000000000000000076000000000000000000000000000000000000000000000000000000000000004c000000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000000d00000000000000000000000000000000000000000000000000000000000000df00000000000000000000000000000000000000000000000000000000000000d500000000000000000000000000000000000000000000000000000000000000a7000000000000000000000000000000000000000000000000000000000000002e00000000000000000000000000000000000000000000000000000000000000d1000000000000000000000000000000000000000000000000000000000000009e00000000000000000000000000000000000000000000000000000000000000b50000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004d000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000f80000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000001700000000000000000000000000000000000000000000000000000000000000a8000000000000000000000000000000000000000000000000000000000000008d0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000009600000000000000000000000000000000000000000000000000000000000000fd000000000000000000000000000000000000000000000000000000000000002c00000000000000000000000000000000000000000000000000000000000000df00000000000000000000000000000000000000000000000000000000000000cb0000000000000000000000000000000000000000000000000000000000000057000000000000000000000000000000000000000000000000000000000000008400000000000000000000000000000000000000000000000000000000000000650000000000000000000000000000000000000000000000000000000000000086000000000000000000000000000000000000000000000000000000000000004e000000000000000000000000000000000000000000000000000000000000007a00000000000000000000000000000000000000000000000000000000000000d8000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000df00000000000000000000000000000000000000000000000000000000000000ae00000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000038000000000000000000000000000000000000000000000000000000000000009e000000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000007d00000000000000000000000000000000000000000000000000000000000000bc0000000000000000000000000000000000000000000000000000000000000036000000000000000000000000000000000000000000000000000000000000006600000000000000000000000000000000000000000000000000000000000000ec00000000000000000000000000000000000000000000000000000000000000f2000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000f900000000000000000000000000000000000000000000000000000000000000fc0000000000000000000000000000000000000000000000000000000000000019000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000e90000000000000000000000000000000000000000000000000000000000000096000000000000000000000000000000000000000000000000000000000000005a0000000000000000000000000000000000000000000000000000000000000084000000000000000000000000000000000000000000000000000000000000002100000000000000000000000000000000000000000000000000000000000000d500000000000000000000000000000000000000000000000000000000000000290000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000002e00000000000000000000000000000000000000000000000000000000000000d2000000000000000000000000000000000000000000000000000000000000003a00000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000073000000000000000000000000000000000000000000000000000000000000002b00000000000000000000000000000000000000000000000000000000000000eb000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000000b00000000000000000000000000000000000000000000000000000000000000c2000000000000000000000000000000000000000000000000000000000000008c0000000000000000000000000000000000000000000000000000000000000017000000000000000000000000000000000000000000000000000000000000000b00000000000000000000000000000000000000000000000000000000000000da000000000000000000000000000000000000000000000000000000000000003a00000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000f600000000000000000000000000000000000000000000000000000000000000fa00000000000000000000000000000000000000000000000000000000000000bd00000000000000000000000000000000000000000000000000000000000000e900000000000000000000000000000000000000000000000000000000000000a9000000000000000000000000000000000000000000000000000000000000005200000000000000000000000000000000000000000000000000000000000000fd00000000000000000000000000000000000000000000000000000000000000b800000000000000000000000000000000000000000000000000000000000000f800000000000000000000000000000000000000000000000000000000000000de000000000000000000000000000000000000000000000000000000000000009e000000000000000000000000000000000000000000000000000000000000001300000000000000000000000000000000000000000000000000000000000000e5000000000000000000000000000000000000000000000000000000000000007a0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001500000000000000000000000000000000000000000000000000000000000000f1000000000000000000000000000000000000000000000000000000000000005d000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000e8000000000000000000000000000000000000000000000000000000000000003500000000000000000000000000000000000000000000000000000000000000c6000000000000000000000000000000000000000000000000000000000000002a00000000000000000000000000000000000000000000000000000000000000f300000000000000000000000000000000000000000000000000000000000000cf000000000000000000000000000000000000000000000000000000000000005f0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000000000000000000000000000000000003f000000000000000000000000000000000000000000000000000000000000000b00000000000000000000000000000000000000000000000000000000000000fb000000000000000000000000000000000000000000000000000000000000009e00000000000000000000000000000000000000000000000000000000000000f4000000000000000000000000000000000000000000000000000000000000001d00000000000000000000000000000000000000000000000000000000000000f5000000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000002500000000000000000000000000000000000000000000000000000000000000db000000000000000000000000000000000000000000000000000000000000007d0000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000007800000000000000000000000000000000000000000000000000000000000000a80000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000009300000000000000000000000000000000000000000000000000000000000000d900000000000000000000000000000000000000000000000000000000000000dc000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001f0000000000000000000000000000000000000000000000000000000000000072000000000000000000000000000000000000000000000000000000000000009f0000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000006d00000000000000000000000000000000000000000000000000000000000000f500000000000000000000000000000000000000000000000000000000000000f5000000000000000000000000000000000000000000000000000000000000004500000000000000000000000000000000000000000000000000000000000000bb00000000000000000000000000000000000000000000000000000000000000bd00000000000000000000000000000000000000000000000000000000000000b20000000000000000000000000000000000000000000000000000000000000059000000000000000000000000000000000000000000000000000000000000008900000000000000000000000000000000000000000000000000000000000000ac000000000000000000000000000000000000000000000000000000000000006f00000000000000000000000000000000000000000000000000000000000000e500000000000000000000000000000000000000000000000000000000000000c8000000000000000000000000000000000000000000000000000000000000005a00000000000000000000000000000000000000000000000000000000000000d400000000000000000000000000000000000000000000000000000000000000e6000000000000000000000000000000000000000000000000000000000000007800000000000000000000000000000000000000000000000000000000000000be00000000000000000000000000000000000000000000000000000000000000850000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000b4000000000000000000000000000000000000000000000000000000000000008d00000000000000000000000000000000000000000000000000000000000000ad000000000000000000000000000000000000000000000000000000000000008100000000000000000000000000000000000000000000000000000000000000bf00000000000000000000000000000000000000000000000000000000000000e5000000000000000000000000000000000000000000000000000000000000005f00000000000000000000000000000000000000000000000000000000000000720000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000000000000000000000000000000000fd000000000000000000000000000000000000000000000000000000000000006e00000000000000000000000000000000000000000000000000000000000000fc000000000000000000000000000000000000000000000000000000000000007e00000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000b0000000000000000000000000000000000000000000000000000000000000047000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000000000000000000000000000000000ed000000000000000000000000000000000000000000000000000000000000003a0000000000000000000000000000000000000000000000000000000000000013000000000000000000000000000000000000000000000000000000000000008a000000000000000000000000000000000000000000000000000000000000008900000000000000000000000000000000000000000000000000000000000000e6000000000000000000000000000000000000000000000000000000000000006c000000000000000000000000000000000000000000000000000000000000004600000000000000000000000000000000000000000000000000000000000000e4000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000007600000000000000000000000000000000000000000000000000000000000000f9000000000000000000000000000000000000000000000000000000000000001f00000000000000000000000000000000000000000000000000000000000000c300000000000000000000000000000000000000000000000000000000000000ec00000000000000000000000000000000000000000000000000000000000000bb00000000000000000000000000000000000000000000000000000000000000380000000000000000000000000000000000000000000000000000000000000067000000000000000000000000000000000000000000000000000000000000005d000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000002f0000000000000000000000000000000000000000000000000000000000000015000000000000000000000000000000000000000000000000000000000000005b0000000000000000000000000000000000000000000000000000000000000015000000000000000000000000000000000000000000000000000000000000005400000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000006a0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002d0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000a800000000000000000000000000000000000000000000000000000000000000e500000000000000000000000000000000000000000000000000000000000000b400000000000000000000000000000000000000000000000000000000000000bc00000000000000000000000000000000000000000000000000000000000000650000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000001b0000000000000000000000000000000000000000000000000000000000000041000000000000000000000000000000000000000000000000000000000000003f00000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000008e00000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000009600000000000000000000000000000000000000000000000000000000000000a20000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000001f000000000000000000000000000000000000000000000000000000000000004f0000000000000000000000000000000000000000000000000000000000000019000000000000000000000000000000000000000000000000000000000000003b000000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000004100000000000000000000000000000000000000000000000000000000000000d90000000000000000000000000000000000000000000000000000000000000054000000000000000000000000000000000000000000000000000000000000007200000000000000000000000000000000000000000000000000000000000000cc00000000000000000000000000000000000000000000000000000000000000f900000000000000000000000000000000000000000000000000000000000000e1000000000000000000000000000000000000000000000000000000000000004600000000000000000000000000000000000000000000000000000000000000ad000000000000000000000000000000000000000000000000000000000000004d00000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000de00000000000000000000000000000000000000000000000000000000000000e4000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000003800000000000000000000000000000000000000000000000000000000000000950000000000000000000000000000000000000000000000000000000000000073000000000000000000000000000000000000000000000000000000000000005c0000000000000000000000000000000000000000000000000000000000000094000000000000000000000000000000000000000000000000000000000000004e000000000000000000000000000000000000000000000000000000000000001f0000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000003a000000000000000000000000000000000000000000000000000000000000002e00000000000000000000000000000000000000000000000000000000000000fa000000000000000000000000000000000000000000000000000000000000001300000000000000000000000000000000000000000000000000000000000000ff00000000000000000000000000000000000000000000000000000000000000350000000000000000000000000000000000000000000000000000000000000071000000000000000000000000000000000000000000000000000000000000002c00000000000000000000000000000000000000000000000000000000000000d900000000000000000000000000000000000000000000000000000000000000ce00000000000000000000000000000000000000000000000000000000000000bb000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000e20000000000000000000000000000000000000000000000000000000000000076000000000000000000000000000000000000000000000000000000000000001f000000000000000000000000000000000000000000000000000000000000005e000000000000000000000000000000000000000000000000000000000000008f00000000000000000000000000000000000000000000000000000000000000fd000000000000000000000000000000000000000000000000000000000000006600000000000000000000000000000000000000000000000000000000000000e500000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000004500000000000000000000000000000000000000000000000000000000000000c100000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000078000000000000000000000000000000000000000000000000000000000000007d00000000000000000000000000000000000000000000000000000000000000a70000000000000000000000000000000000000000000000000000000000000048000000000000000000000000000000000000000000000000000000000000005c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000000000000000000000000000000000005500000000000000000000000000000000000000000000000000000000000000ed00000000000000000000000000000000000000000000000000000000000000290000000000000000000000000000000000000000000000000000000000000061000000000000000000000000000000000000000000000000000000000000005d00000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000000c500000000000000000000000000000000000000000000000000000000000000c4000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000b7000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000a9000000000000000000000000000000000000000000000000000000000000002100000000000000000000000000000000000000000000000000000000000000d7000000000000000000000000000000000000000000000000000000000000009300000000000000000000000000000000000000000000000000000000000000f800000000000000000000000000000000000000000000000000000000000000f70000000000000000000000000000000000000000000000000000000000000011000000000000000000000000000000000000000000000000000000000000001700000000000000000000000000000000000000000000000000000000000000bb00000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000009b000000000000000000000000000000000000000000000000000000000000006a000000000000000000000000000000000000000000000000000000000000005a0000000000000000000000000000000000000000000000000000000000000074000000000000000000000000000000000000000000000000000000000000001f00000000000000000000000000000000000000000000000000000000000000ea000000000000000000000000000000000000000000000000000000000000009a00000000000000000000000000000000000000000000000000000000000000ae000000000000000000000000000000000000000000000000000000000000004c000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000ad00000000000000000000000000000000000000000000000000000000000000a6000000000000000000000000000000000000000000000000000000000000003e00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000006800000000000000000000000000000000000000000000000000000000000000130000000000000000000000000000000000000000000000000000000000000027000000000000000000000000000000000000000000000000000000000000004e00000000000000000000000000000000000000000000000000000000000000ee000000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000006a000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000003100000000000000000000000000000000000000000000000000000000000000e50000000000000000000000000000000000000000000000000000000000000092000000000000000000000000000000000000000000000000000000000000001700000000000000000000000000000000000000000000000000000000000000fb0000000000000000000000000000000000000000000000000000000000000058000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000d100000000000000000000000000000000000000000000000000000000000000e100000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000059000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000a8000000000000000000000000000000000000000000000000000000000000004b000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000bc00000000000000000000000000000000000000000000000000000000000000da000000000000000000000000000000000000000000000000000000000000002b000000000000000000000000000000000000000000000000000000000000004200000000000000000000000000000000000000000000000000000000000000a600000000000000000000000000000000000000000000000000000000000000cf00000000000000000000000000000000000000000000000000000000000000a6000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000008f00000000000000000000000000000000000000000000000000000000000000ad000000000000000000000000000000000000000000000000000000000000008a0000000000000000000000000000000000000000000000000000000000000081000000000000000000000000000000000000000000000000000000000000002b0000000000000000000000000000000000000000000000000000000000000057000000000000000000000000000000000000000000000000000000000000004800000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000059000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000005500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000f00000000000000000000000000000000000000000000000000000000000000ee00000000000000000000000000000000000000000000000000000000000000a7000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000d800000000000000000000000000000000000000000000000000000000000000df0000000000000000000000000000000000000000000000000000000000000089000000000000000000000000000000000000000000000000000000000000001d000000000000000000000000000000000000000000000000000000000000005900000000000000000000000000000000000000000000000000000000000000ab000000000000000000000000000000000000000000000000000000000000009f00000000000000000000000000000000000000000000000000000000000000c600000000000000000000000000000000000000000000000000000000000000ad000000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000d7000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000008e00000000000000000000000000000000000000000000000000000000000000f40000000000000000000000000000000000000000000000000000000000000072000000000000000000000000000000000000000000000000000000000000001700000000000000000000000000000000000000000000000000000000000000cd000000000000000000000000000000000000000000000000000000000000003200000000000000000000000000000000000000000000000000000000000000c400000000000000000000000000000000000000000000000000000000000000fa00000000000000000000000000000000000000000000000000000000000000d400000000000000000000000000000000000000000000000000000000000000150000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000004a00000000000000000000000000000000000000000000000000000000000000f900000000000000000000000000000000000000000000000000000000000000b800000000000000000000000000000000000000000000000000000000000000eb00000000000000000000000000000000000000000000000000000000000000660000000000000000000000000000000000000000000000000000000000000069000000000000000000000000000000000000000000000000000000000000004e00000000000000000000000000000000000000000000000000000000000000250000000000000000000000000000000000000000000000000000000000000087000000000000000000000000000000000000000000000000000000000000006f00000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000003100000000000000000000000000000000000000000000000000000000000000ca000000000000000000000000000000000000000000000000000000000000009f000000000000000000000000000000000000000000000000000000000000008100000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000e800000000000000000000000000000000000000000000000000000000000000dc000000000000000000000000000000000000000000000000000000000000004a00000000000000000000000000000000000000000000000000000000000000f700000000000000000000000000000000000000000000000000000000000000e800000000000000000000000000000000000000000000000000000000000000a8000000000000000000000000000000000000000000000000000000000000006a000000000000000000000000000000000000000000000000000000000000006e00000000000000000000000000000000000000000000000000000000000000f0000000000000000000000000000000000000000000000000000000000000009a00000000000000000000000000000000000000000000000000000000000000bb000000000000000000000000000000000000000000000000000000000000001f00000000000000000000000000000000000000000000000000000000000000ea000000000000000000000000000000000000000000000000000000000000005e00000000000000000000000000000000000000000000000000000000000000cc00000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000000750000000000000000000000000000000000000000000000000000000000000089000000000000000000000000000000000000000000000000000000000000004700000000000000000000000000000000000000000000000000000000000000ca00000000000000000000000000000000000000000000000000000000000000c1000000000000000000000000000000000000000000000000000000000000007900000000000000000000000000000000000000000000000000000000000000a1000000000000000000000000000000000000000000000000000000000000004600000000000000000000000000000000000000000000000000000000000000c20000000000000000000000000000000000000000000000000000000000000042000000000000000000000000000000000000000000000000000000000000001f000000000000000000000000000000000000000000000000000000000000006b00000000000000000000000000000000000000000000000000000000000000410000000000000000000000000000000000000000000000000000000000000043000000000000000000000000000000000000000000000000000000000000009500000000000000000000000000000000000000000000000000000000000000de0000000000000000000000000000000000000000000000000000000000000023000000000000000000000000000000000000000000000000000000000000006f00000000000000000000000000000000000000000000000000000000000000fc0000000000000000000000000000000000000000000000000000000000000095000000000000000000000000000000000000000000000000000000000000007a00000000000000000000000000000000000000000000000000000000000000df000000000000000000000000000000000000000000000000000000000000003f00000000000000000000000000000000000000000000000000000000000000e6000000000000000000000000000000000000000000000000000000000000006e000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000b1000000000000000000000000000000000000000000000000000000000000009a00000000000000000000000000000000000000000000000000000000000000af000000000000000000000000000000000000000000000000000000000000004300000000000000000000000000000000000000000000000000000000000000dd00000000000000000000000000000000000000000000000000000000000000c2000000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001700000000000000000000000000000000000000000000000000000000000000a2000000000000000000000000000000000000000000000000000000000000004d000000000000000000000000000000000000000000000000000000000000002e0000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000004400000000000000000000000000000000000000000000000000000000000000f800000000000000000000000000000000000000000000000000000000000000bd0000000000000000000000000000000000000000000000000000000000000065000000000000000000000000000000000000000000000000000000000000005200000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000005e000000000000000000000000000000000000000000000000000000000000006300000000000000000000000000000000000000000000000000000000000000d5000000000000000000000000000000000000000000000000000000000000005e00000000000000000000000000000000000000000000000000000000000000e90000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000004b000000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000002a0000000000000000000000000000000000000000000000000000000000000062000000000000000000000000000000000000000000000000000000000000003100000000000000000000000000000000000000000000000000000000000000f3000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000d800000000000000000000000000000000000000000000000000000000000000540000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000006300000000000000000000000000000000000000000000000000000000000000b300000000000000000000000000000000000000000000000000000000000000b5000000000000000000000000000000000000000000000000000000000000007d0000000000000000000000000000000000000000000000000000000000000095000000000000000000000000000000000000000000000000000000000000007700000000000000000000000000000000000000000000000000000000000000da000000000000000000000000000000000000000000000000000000000000008e00000000000000000000000000000000000000000000000000000000000000f300000000000000000000000000000000000000000000000000000000000000cc000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000002500000000000000000000000000000000000000000000000000000000000000e500000000000000000000000000000000000000000000000000000000000000ca000000000000000000000000000000000000000000000000000000000000008e0000000000000000000000000000000000000000000000000000000000000066000000000000000000000000000000000000000000000000000000000000009300000000000000000000000000000000000000000000000000000000000000c2000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000000ec000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000b3000000000000000000000000000000000000000000000000000000000000005a0000000000000000000000000000000000000000000000000000000000000017000000000000000000000000000000000000000000000000000000000000004900000000000000000000000000000000000000000000000000000000000000f700000000000000000000000000000000000000000000000000000000000000f7000000000000000000000000000000000000000000000000000000000000003f00000000000000000000000000000000000000000000000000000000000000d400000000000000000000000000000000000000000000000000000000000000af00000000000000000000000000000000000000000000000000000000000000ee000000000000000000000000000000000000000000000000000000000000007800000000000000000000000000000000000000000000000000000000000000af00000000000000000000000000000000000000000000000000000000000000940000000000000000000000000000000000000000000000000000000000000071000000000000000000000000000000000000000000000000000000000000006d0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000009400000000000000000000000000000000000000000000000000000000000000ec000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000008200000000000000000000000000000000000000000000000000000000000000db000000000000000000000000000000000000000000000000000000000000008d0000000000000000000000000000000000000000000000000000000000000053000000000000000000000000000000000000000000000000000000000000009f00000000000000000000000000000000000000000000000000000000000000a1000000000000000000000000000000000000000000000000000000000000005900000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000090000000000000000000000000000000000000000000000000000000000000004f00000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000003800000000000000000000000000000000000000000000000000000000000000d200000000000000000000000000000000000000000000000000000000000000e2000000000000000000000000000000000000000000000000000000000000008b000000000000000000000000000000000000000000000000000000000000007c000000000000000000000000000000000000000000000000000000000000004100000000000000000000000000000000000000000000000000000000000000ac0000000000000000000000000000000000000000000000000000000000000021000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000be000000000000000000000000000000000000000000000000000000000000009c0000000000000000000000000000000000000000000000000000000000000099000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000a8000000000000000000000000000000000000000000000000000000000000008f000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000c300000000000000000000000000000000000000000000000000000000000000aa00000000000000000000000000000000000000000000000000000000000000b4000000000000000000000000000000000000000000000000000000000000002a00000000000000000000000000000000000000000000000000000000000000b100000000000000000000000000000000000000000000000000000000000000450000000000000000000000000000000000000000000000000000000000000031000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000002b00000000000000000000000000000000000000000000000000000000000000a900000000000000000000000000000000000000000000000000000000000000cd00000000000000000000000000000000000000000000000000000000000000f80000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000000000000000000000000000000000007c00000000000000000000000000000000000000000000000000000000000000ce00000000000000000000000000000000000000000000000000000000000000ff000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000006c000000000000000000000000000000000000000000000000000000000000004300000000000000000000000000000000000000000000000000000000000000bf0000000000000000000000000000000000000000000000000000000000000013000000000000000000000000000000000000000000000000000000000000008a000000000000000000000000000000000000000000000000000000000000004a00000000000000000000000000000000000000000000000000000000000000ef000000000000000000000000000000000000000000000000000000000000005b00000000000000000000000000000000000000000000000000000000000000b900000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000b2000000000000000000000000000000000000000000000000000000000000009e000000000000000000000000000000000000000000000000000000000000003400000000000000000000000000000000000000000000000000000000000000980000000000000000000000000000000000000000000000000000000000000037000000000000000000000000000000000000000000000000000000000000009800000000000000000000000000000000000000000000000000000000000000440000000000000000000000000000000000000000000000000000000000000038000000000000000000000000000000000000000000000000000000000000007e00000000000000000000000000000000000000000000000000000000000000e20000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000005c00000000000000000000000000000000000000000000000000000000000000b0000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000c80000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000008600000000000000000000000000000000000000000000000000000000000000a400000000000000000000000000000000000000000000000000000000000000cf00000000000000000000000000000000000000000000000000000000000000cf0000000000000000000000000000000000000000000000000000000000000058000000000000000000000000000000000000000000000000000000000000005800000000000000000000000000000000000000000000000000000000000000b200000000000000000000000000000000000000000000000000000000000000d8000000000000000000000000000000000000000000000000000000000000003a00000000000000000000000000000000000000000000000000000000000000210000000000000000000000000000000000000000000000000000000000000083000000000000000000000000000000000000000000000000000000000000001b000000000000000000000000000000000000000000000000000000000000006c000000000000000000000000000000000000000000000000000000000000003a0000000000000000000000000000000000000000000000000000000000000082000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000a70000000000000000000000000000000000000000000000000000000000000035000000000000000000000000000000000000000000000000000000000000000f00000000000000000000000000000000000000000000000000000000000000bf000000000000000000000000000000000000000000000000000000000000002c00000000000000000000000000000000000000000000000000000000000000b9000000000000000000000000000000000000000000000000000000000000003b00000000000000000000000000000000000000000000000000000000000000f3000000000000000000000000000000000000000000000000000000000000002d00000000000000000000000000000000000000000000000000000000000000f7000000000000000000000000000000000000000000000000000000000000006c00000000000000000000000000000000000000000000000000000000000000380000000000000000000000000000000000000000000000000000000000000077000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000000000000000000000000000000000a9000000000000000000000000000000000000000000000000000000000000005e000000000000000000000000000000000000000000000000000000000000005900000000000000000000000000000000000000000000000000000000000000fa00000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000086000000000000000000000000000000000000000000000000000000000000008500000000000000000000000000000000000000000000000000000000000000350000000000000000000000000000000000000000000000000000000000000097000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000fb000000000000000000000000000000000000000000000000000000000000008e000000000000000000000000000000000000000000000000000000000000005200000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000bc000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000005900000000000000000000000000000000000000000000000000000000000000850000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000b200000000000000000000000000000000000000000000000000000000000000ee00000000000000000000000000000000000000000000000000000000000000aa0000000000000000000000000000000000000000000000000000000000000058000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000e10000000000000000000000000000000000000000000000000000000000000027000000000000000000000000000000000000000000000000000000000000004c000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000c20000000000000000000000000000000000000000000000000000000000000043000000000000000000000000000000000000000000000000000000000000006d0000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000005d000000000000000000000000000000000000000000000000000000000000000900000000000000000000000000000000000000000000000000000000000000c200000000000000000000000000000000000000000000000000000000000000f900000000000000000000000000000000000000000000000000000000000000a40000000000000000000000000000000000000000000000000000000000000063000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000041000000000000000000000000000000000000000000000000000000000000005c00000000000000000000000000000000000000000000000000000000000000b40000000000000000000000000000000000000000000000000000000000000051000000000000000000000000000000000000000000000000000000000000005a0000000000000000000000000000000000000000000000000000000000000095000000000000000000000000000000000000000000000000000000000000002d000000000000000000000000000000000000000000000000000000000000004d0000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000f600000000000000000000000000000000000000000000000000000000000000d6000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000f5000000000000000000000000000000000000000000000000000000000000009500000000000000000000000000000000000000000000000000000000000000a800000000000000000000000000000000000000000000000000000000000000ec00000000000000000000000000000000000000000000000000000000000000b800000000000000000000000000000000000000000000000000000000000000b00000000000000000000000000000000000000000000000000000000000000037000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000ca00000000000000000000000000000000000000000000000000000000000000aa000000000000000000000000000000000000000000000000000000000000006a00000000000000000000000000000000000000000000000000000000000000f70000000000000000000000000000000000000000000000000000000000000015000000000000000000000000000000000000000000000000000000000000001f000000000000000000000000000000000000000000000000000000000000007c00000000000000000000000000000000000000000000000000000000000000fa000000000000000000000000000000000000000000000000000000000000002700000000000000000000000000000000000000000000000000000000000000d90000000000000000000000000000000000000000000000000000000000000023000000000000000000000000000000000000000000000000000000000000009c000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000d500000000000000000000000000000000000000000000000000000000000000d200000000000000000000000000000000000000000000000000000000000000b800000000000000000000000000000000000000000000000000000000000000be00000000000000000000000000000000000000000000000000000000000000b100000000000000000000000000000000000000000000000000000000000000ce000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000d400000000000000000000000000000000000000000000000000000000000000ab000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000000fa00000000000000000000000000000000000000000000000000000000000000920000000000000000000000000000000000000000000000000000000000000068000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000ff000000000000000000000000000000000000000000000000000000000000007a00000000000000000000000000000000000000000000000000000000000000bc00000000000000000000000000000000000000000000000000000000000000ab000000000000000000000000000000000000000000000000000000000000004400000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000061000000000000000000000000000000000000000000000000000000000000004e00000000000000000000000000000000000000000000000000000000000000db00000000000000000000000000000000000000000000000000000000000000ef00000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000007300000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000087000000000000000000000000000000000000000000000000000000000000008800000000000000000000000000000000000000000000000000000000000000c2000000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000009800000000000000000000000000000000000000000000000000000000000000d200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000051000000000000000000000000000000000000000000000000000000000000005c00000000000000000000000000000000000000000000000000000000000000cc0000000000000000000000000000000000000000000000000000000000000025000000000000000000000000000000000000000000000000000000000000004a00000000000000000000000000000000000000000000000000000000000000fa00000000000000000000000000000000000000000000000000000000000000ea00000000000000000000000000000000000000000000000000000000000000b7000000000000000000000000000000000000000000000000000000000000004f0000000000000000000000000000000000000000000000000000000000000057000000000000000000000000000000000000000000000000000000000000003f00000000000000000000000000000000000000000000000000000000000000bd000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000c70000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000004e00000000000000000000000000000000000000000000000000000000000000f500000000000000000000000000000000000000000000000000000000000000b900000000000000000000000000000000000000000000000000000000000000ce000000000000000000000000000000000000000000000000000000000000003c00000000000000000000000000000000000000000000000000000000000000b0000000000000000000000000000000000000000000000000000000000000003e00000000000000000000000000000000000000000000000000000000000000440000000000000000000000000000000000000000000000000000000000000092000000000000000000000000000000000000000000000000000000000000002900000000000000000000000000000000000000000000000000000000000000d100000000000000000000000000000000000000000000000000000000000000bd0000000000000000000000000000000000000000000000000000000000000062000000000000000000000000000000000000000000000000000000000000008200000000000000000000000000000000000000000000000000000000000000a700000000000000000000000000000000000000000000000000000000000000bc000000000000000000000000000000000000000000000000000000000000008b000000000000000000000000000000000000000000000000000000000000007300000000000000000000000000000000000000000000000000000000000000c600000000000000000000000000000000000000000000000000000000000000f100000000000000000000000000000000000000000000000000000000000000fa0000000000000000000000000000000000000000000000000000000000000074000000000000000000000000000000000000000000000000000000000000005e0000000000000000000000000000000000000000000000000000000000000081000000000000000000000000000000000000000000000000000000000000007800000000000000000000000000000000000000000000000000000000000000d6000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000a300000000000000000000000000000000000000000000000000000000000000490000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000001f000000000000000000000000000000000000000000000000000000000000009a000000000000000000000000000000000000000000000000000000000000004600000000000000000000000000000000000000000000000000000000000000a600000000000000000000000000000000000000000000000000000000000000f3000000000000000000000000000000000000000000000000000000000000002d00000000000000000000000000000000000000000000000000000000000000f500000000000000000000000000000000000000000000000000000000000000d8000000000000000000000000000000000000000000000000000000000000001f000000000000000000000000000000000000000000000000000000000000002d000000000000000000000000000000000000000000000000000000000000004b0000000000000000000000000000000000000000000000000000000000000065000000000000000000000000000000000000000000000000000000000000002b00000000000000000000000000000000000000000000000000000000000000860000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000008c000000000000000000000000000000000000000000000000000000000000008900000000000000000000000000000000000000000000000000000000000000b9000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000760000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000e3000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000da00000000000000000000000000000000000000000000000000000000000000fa00000000000000000000000000000000000000000000000000000000000000df00000000000000000000000000000000000000000000000000000000000000e700000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000092000000000000000000000000000000000000000000000000000000000000005c0000000000000000000000000000000000000000000000000000000000000013000000000000000000000000000000000000000000000000000000000000003d000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000000ff00000000000000000000000000000000000000000000000000000000000000c800000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000075000000000000000000000000000000000000000000000000000000000000009f000000000000000000000000000000000000000000000000000000000000006c00000000000000000000000000000000000000000000000000000000000000ed00000000000000000000000000000000000000000000000000000000000000cc00000000000000000000000000000000000000000000000000000000000000e50000000000000000000000000000000000000000000000000000000000000049000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000008c000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000000bf000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000eb00000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000ea00000000000000000000000000000000000000000000000000000000000000c9000000000000000000000000000000000000000000000000000000000000004200000000000000000000000000000000000000000000000000000000000000a40000000000000000000000000000000000000000000000000000000000000017000000000000000000000000000000000000000000000000000000000000003b000000000000000000000000000000000000000000000000000000000000005700000000000000000000000000000000000000000000000000000000000000b300000000000000000000000000000000000000000000000000000000000000f500000000000000000000000000000000000000000000000000000000000000e400000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000004600000000000000000000000000000000000000000000000000000000000000df000000000000000000000000000000000000000000000000000000000000009a00000000000000000000000000000000000000000000000000000000000000ca00000000000000000000000000000000000000000000000000000000000000b70000000000000000000000000000000000000000000000000000000000000063000000000000000000000000000000000000000000000000000000000000004e000000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000007a0000000000000000000000000000000000000000000000000000000000000045000000000000000000000000000000000000000000000000000000000000007700000000000000000000000000000000000000000000000000000000000000c300000000000000000000000000000000000000000000000000000000000000ea00000000000000000000000000000000000000000000000000000000000000b8000000000000000000000000000000000000000000000000000000000000004d000000000000000000000000000000000000000000000000000000000000009500000000000000000000000000000000000000000000000000000000000000b700000000000000000000000000000000000000000000000000000000000000d90000000000000000000000000000000000000000000000000000000000000055000000000000000000000000000000000000000000000000000000000000005e00000000000000000000000000000000000000000000000000000000000000b400000000000000000000000000000000000000000000000000000000000000b7000000000000000000000000000000000000000000000000000000000000006700000000000000000000000000000000000000000000000000000000000000fc000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000c3000000000000000000000000000000000000000000000000000000000000009200000000000000000000000000000000000000000000000000000000000000760000000000000000000000000000000000000000000000000000000000000031000000000000000000000000000000000000000000000000000000000000006200000000000000000000000000000000000000000000000000000000000000bc000000000000000000000000000000000000000000000000000000000000008e00000000000000000000000000000000000000000000000000000000000000590000000000000000000000000000000000000000000000000000000000000021000000000000000000000000000000000000000000000000000000000000004300000000000000000000000000000000000000000000000000000000000000d500000000000000000000000000000000000000000000000000000000000000cc00000000000000000000000000000000000000000000000000000000000000940000000000000000000000000000000000000000000000000000000000000054000000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000000000000000000000000000000000003800000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000f70000000000000000000000000000000000000000000000000000000000000095000000000000000000000000000000000000000000000000000000000000009600000000000000000000000000000000000000000000000000000000000000b100000000000000000000000000000000000000000000000000000000000000ff000000000000000000000000000000000000000000000000000000000000004200000000000000000000000000000000000000000000000000000000000000a600000000000000000000000000000000000000000000000000000000000000f1000000000000000000000000000000000000000000000000000000000000009800000000000000000000000000000000000000000000000000000000000000b400000000000000000000000000000000000000000000000000000000000000f2000000000000000000000000000000000000000000000000000000000000003f000000000000000000000000000000000000000000000000000000000000004c00000000000000000000000000000000000000000000000000000000000000850000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000043000000000000000000000000000000000000000000000000000000000000005600000000000000000000000000000000000000000000000000000000000000b1000000000000000000000000000000000000000000000000000000000000006800000000000000000000000000000000000000000000000000000000000000bb00000000000000000000000000000000000000000000000000000000000000a9000000000000000000000000000000000000000000000000000000000000007e00000000000000000000000000000000000000000000000000000000000000c70000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000f900000000000000000000000000000000000000000000000000000000000000c200000000000000000000000000000000000000000000000000000000000000c800000000000000000000000000000000000000000000000000000000000000ce000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000c3000000000000000000000000000000000000000000000000000000000000007300000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000000f500000000000000000000000000000000000000000000000000000000000000ab00000000000000000000000000000000000000000000000000000000000000920000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000005700000000000000000000000000000000000000000000000000000000000000f4000000000000000000000000000000000000000000000000000000000000001c00000000000000000000000000000000000000000000000000000000000000b8000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000fd0000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000000000000000000000000000000000001c00000000000000000000000000000000000000000000000000000000000000c9000000000000000000000000000000000000000000000000000000000000002a00000000000000000000000000000000000000000000000000000000000000a3000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000007100000000000000000000000000000000000000000000000000000000000000a500000000000000000000000000000000000000000000000000000000000000c300000000000000000000000000000000000000000000000000000000000000b400000000000000000000000000000000000000000000000000000000000000a200000000000000000000000000000000000000000000000000000000000000d1000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000004a0000000000000000000000000000000000000000000000000000000000000076000000000000000000000000000000000000000000000000000000000000008500000000000000000000000000000000000000000000000000000000000000aa00000000000000000000000000000000000000000000000000000000000000ec00000000000000000000000000000000000000000000000000000000000000b9000000000000000000000000000000000000000000000000000000000000003400000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000079000000000000000000000000000000000000000000000000000000000000005c000000000000000000000000000000000000000000000000000000000000008c000000000000000000000000000000000000000000000000000000000000008300000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000008500000000000000000000000000000000000000000000000000000000000000e9000000000000000000000000000000000000000000000000000000000000009300000000000000000000000000000000000000000000000000000000000000d100000000000000000000000000000000000000000000000000000000000000b0000000000000000000000000000000000000000000000000000000000000004c000000000000000000000000000000000000000000000000000000000000009c000000000000000000000000000000000000000000000000000000000000004f000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000bd00000000000000000000000000000000000000000000000000000000000000560000000000000000000000000000000000000000000000000000000000000041000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000d6000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000b60000000000000000000000000000000000000000000000000000000000000084000000000000000000000000000000000000000000000000000000000000009f000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000c200000000000000000000000000000000000000000000000000000000000000f3000000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000007e00000000000000000000000000000000000000000000000000000000000000ec00000000000000000000000000000000000000000000000000000000000000ec000000000000000000000000000000000000000000000000000000000000003400000000000000000000000000000000000000000000000000000000000000450000000000000000000000000000000000000000000000000000000000000066000000000000000000000000000000000000000000000000000000000000004b000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000fe00000000000000000000000000000000000000000000000000000000000000a7000000000000000000000000000000000000000000000000000000000000006e00000000000000000000000000000000000000000000000000000000000000fb00000000000000000000000000000000000000000000000000000000000000fe00000000000000000000000000000000000000000000000000000000000000ba00000000000000000000000000000000000000000000000000000000000000c100000000000000000000000000000000000000000000000000000000000000b600000000000000000000000000000000000000000000000000000000000000a20000000000000000000000000000000000000000000000000000000000000019000000000000000000000000000000000000000000000000000000000000004b00000000000000000000000000000000000000000000000000000000000000da00000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000000dd00000000000000000000000000000000000000000000000000000000000000940000000000000000000000000000000000000000000000000000000000000091000000000000000000000000000000000000000000000000000000000000008c000000000000000000000000000000000000000000000000000000000000007000000000000000000000000000000000000000000000000000000000000000ee000000000000000000000000000000000000000000000000000000000000008a0000000000000000000000000000000000000000000000000000000000000068000000000000000000000000000000000000000000000000000000000000002e00000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000000c200000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000ad000000000000000000000000000000000000000000000000000000000000004100000000000000000000000000000000000000000000000000000000000000530000000000000000000000000000000000000000000000000000000000000007000000000000000000000000000000000000000000000000000000000000001900000000000000000000000000000000000000000000000000000000000000df000000000000000000000000000000000000000000000000000000000000006600000000000000000000000000000000000000000000000000000000000000c500000000000000000000000000000000000000000000000000000000000000a1000000000000000000000000000000000000000000000000000000000000007e000000000000000000000000000000000000000000000000000000000000002b000000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000007d0000000000000000000000000000000000000000000000000000000000000081000000000000000000000000000000000000000000000000000000000000004400000000000000000000000000000000000000000000000000000000000000850000000000000000000000000000000000000000000000000000000000000029000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000df000000000000000000000000000000000000000000000000000000000000005e00000000000000000000000000000000000000000000000000000000000000fc000000000000000000000000000000000000000000000000000000000000008f00000000000000000000000000000000000000000000000000000000000000930000000000000000000000000000000000000000000000000000000000000076000000000000000000000000000000000000000000000000000000000000007b00000000000000000000000000000000000000000000000000000000000000fb00000000000000000000000000000000000000000000000000000000000000b2000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000d800000000000000000000000000000000000000000000000000000000000000a700000000000000000000000000000000000000000000000000000000000000d400000000000000000000000000000000000000000000000000000000000000a500000000000000000000000000000000000000000000000000000000000000bb0000000000000000000000000000000000000000000000000000000000000073000000000000000000000000000000000000000000000000000000000000003a00000000000000000000000000000000000000000000000000000000000000e800000000000000000000000000000000000000000000000000000000000000fe000000000000000000000000000000000000000000000000000000000000004c000000000000000000000000000000000000000000000000000000000000006a00000000000000000000000000000000000000000000000000000000000000370000000000000000000000000000000000000000000000000000000000000083000000000000000000000000000000000000000000000000000000000000004900000000000000000000000000000000000000000000000000000000000000c20000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000000000000000000000000000000000004a00000000000000000000000000000000000000000000000000000000000000bc00000000000000000000000000000000000000000000000000000000000000e2000000000000000000000000000000000000000000000000000000000000006800000000000000000000000000000000000000000000000000000000000000c9000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c200000000000000000000000000000000000000000000000000000000000000af000000000000000000000000000000000000000000000000000000000000007800000000000000000000000000000000000000000000000000000000000000c6000000000000000000000000000000000000000000000000000000000000007700000000000000000000000000000000000000000000000000000000000000ed000000000000000000000000000000000000000000000000000000000000004700000000000000000000000000000000000000000000000000000000000000cd00000000000000000000000000000000000000000000000000000000000000d6000000000000000000000000000000000000000000000000000000000000003800000000000000000000000000000000000000000000000000000000000000770000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000000000000000000000000000000000004d000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000d7000000000000000000000000000000000000000000000000000000000000003d000000000000000000000000000000000000000000000000000000000000000d0000000000000000000000000000000000000000000000000000000000000090000000000000000000000000000000000000000000000000000000000000009100000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000078000000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000001300000000000000000000000000000000000000000000000000000000000000d9000000000000000000000000000000000000000000000000000000000000009b000000000000000000000000000000000000000000000000000000000000007600000000000000000000000000000000000000000000000000000000000000ed00000000000000000000000000000000000000000000000000000000000000f5000000000000000000000000000000000000000000000000000000000000004e000000000000000000000000000000000000000000000000000000000000008800000000000000000000000000000000000000000000000000000000000000e9000000000000000000000000000000000000000000000000000000000000006a000000000000000000000000000000000000000000000000000000000000006c00000000000000000000000000000000000000000000000000000000000000df00000000000000000000000000000000000000000000000000000000000000d10000000000000000000000000000000000000000000000000000000000000073000000000000000000000000000000000000000000000000000000000000005f00000000000000000000000000000000000000000000000000000000000000df000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000009300000000000000000000000000000000000000000000000000000000000000ab00000000000000000000000000000000000000000000000000000000000000d70000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000009700000000000000000000000000000000000000000000000000000000000000d600000000000000000000000000000000000000000000000000000000000000c80000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000001b000000000000000000000000000000000000000000000000000000000000003100000000000000000000000000000000000000000000000000000000000000b400000000000000000000000000000000000000000000000000000000000000170000000000000000000000000000000000000000000000000000000000000088000000000000000000000000000000000000000000000000000000000000003600000000000000000000000000000000000000000000000000000000000000c200000000000000000000000000000000000000000000000000000000000000a800000000000000000000000000000000000000000000000000000000000000930000000000000000000000000000000000000000000000000000000000000021000000000000000000000000000000000000000000000000000000000000000f00000000000000000000000000000000000000000000000000000000000000cc00000000000000000000000000000000000000000000000000000000000000ed000000000000000000000000000000000000000000000000000000000000004400000000000000000000000000000000000000000000000000000000000000a300000000000000000000000000000000000000000000000000000000000000950000000000000000000000000000000000000000000000000000000000000098000000000000000000000000000000000000000000000000000000000000007d00000000000000000000000000000000000000000000000000000000000000d4000000000000000000000000000000000000000000000000000000000000000900000000000000000000000000000000000000000000000000000000000000f300000000000000000000000000000000000000000000000000000000000000510000000000000000000000000000000000000000000000000000000000000091000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000f9000000000000000000000000000000000000000000000000000000000000007d000000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000001c0000000000000000000000000000000000000000000000000000000000000013000000000000000000000000000000000000000000000000000000000000009b00000000000000000000000000000000000000000000000000000000000000f400000000000000000000000000000000000000000000000000000000000000c200000000000000000000000000000000000000000000000000000000000000ed000000000000000000000000000000000000000000000000000000000000004c000000000000000000000000000000000000000000000000000000000000003400000000000000000000000000000000000000000000000000000000000000c800000000000000000000000000000000000000000000000000000000000000db00000000000000000000000000000000000000000000000000000000000000e300000000000000000000000000000000000000000000000000000000000000180000000000000000000000000000000000000000000000000000000000000036000000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000005800000000000000000000000000000000000000000000000000000000000000aa000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000000000000000000000000000000000b8000000000000000000000000000000000000000000000000000000000000006d000000000000000000000000000000000000000000000000000000000000007a00000000000000000000000000000000000000000000000000000000000000bb00000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000004d00000000000000000000000000000000000000000000000000000000000000bc000000000000000000000000000000000000000000000000000000000000007e00000000000000000000000000000000000000000000000000000000000000d4000000000000000000000000000000000000000000000000000000000000008f000000000000000000000000000000000000000000000000000000000000005d000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000008f0000000000000000000000000000000000000000000000000000000000000085000000000000000000000000000000000000000000000000000000000000003a000000000000000000000000000000000000000000000000000000000000006300000000000000000000000000000000000000000000000000000000000000a900000000000000000000000000000000000000000000000000000000000000de00000000000000000000000000000000000000000000000000000000000000e1000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001d00000000000000000000000000000000000000000000000000000000000000df0000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001b00000000000000000000000000000000000000000000000000000000000000f7000000000000000000000000000000000000000000000000000000000000005c00000000000000000000000000000000000000000000000000000000000000e100000000000000000000000000000000000000000000000000000000000000fd000000000000000000000000000000000000000000000000000000000000007c00000000000000000000000000000000000000000000000000000000000000b9000000000000000000000000000000000000000000000000000000000000004d000000000000000000000000000000000000000000000000000000000000007600000000000000000000000000000000000000000000000000000000000000750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005300000000000000000000000000000000000000000000000000000000000000a9000000000000000000000000000000000000000000000000000000000000001c00000000000000000000000000000000000000000000000000000000000000d9000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000c80000000000000000000000000000000000000000000000000000000000000044000000000000000000000000000000000000000000000000000000000000006d000000000000000000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000000000000000000c6000000000000000000000000000000000000000000000000000000000000005800000000000000000000000000000000000000000000000000000000000000cb00000000000000000000000000000000000000000000000000000000000000a30000000000000000000000000000000000000000000000000000000000000021000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000b800000000000000000000000000000000000000000000000000000000000000ec000000000000000000000000000000000000000000000000000000000000002b00000000000000000000000000000000000000000000000000000000000000aa000000000000000000000000000000000000000000000000000000000000003300000000000000000000000000000000000000000000000000000000000000e1000000000000000000000000000000000000000000000000000000000000009300000000000000000000000000000000000000000000000000000000000000ff000000000000000000000000000000000000000000000000000000000000004e0000000000000000000000000000000000000000000000000000000000000029000000000000000000000000000000000000000000000000000000000000009a00000000000000000000000000000000000000000000000000000000000000c5000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000ab000000000000000000000000000000000000000000000000000000000000005100000000000000000000000000000000000000000000000000000000000000fd00000000000000000000000000000000000000000000000000000000000000860000000000000000000000000000000000000000000000000000000000000097000000000000000000000000000000000000000000000000000000000000006b0000000000000000000000000000000000000000000000000000000000000044000000000000000000000000000000000000000000000000000000000000001700000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000007000000000000000000000000000000000000000000000000000000000000005100000000000000000000000000000000000000000000000000000000000000960000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000006e00000000000000000000000000000000000000000000000000000000000000b8000000000000000000000000000000000000000000000000000000000000008a00000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000089000000000000000000000000000000000000000000000000000000000000002e00000000000000000000000000000000000000000000000000000000000000d10000000000000000000000000000000000000000000000000000000000000098000000000000000000000000000000000000000000000000000000000000002700000000000000000000000000000000000000000000000000000000000000e3000000000000000000000000000000000000000000000000000000000000007d000000000000000000000000000000000000000000000000000000000000006a00000000000000000000000000000000000000000000000000000000000000a1000000000000000000000000000000000000000000000000000000000000008300000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000000290000000000000000000000000000000000000000000000000000000000000052000000000000000000000000000000000000000000000000000000000000004100000000000000000000000000000000000000000000000000000000000000df000000000000000000000000000000000000000000000000000000000000008100000000000000000000000000000000000000000000000000000000000000ac000000000000000000000000000000000000000000000000000000000000005a000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000bd000000000000000000000000000000000000000000000000000000000000009e00000000000000000000000000000000000000000000000000000000000000f0000000000000000000000000000000000000000000000000000000000000004200000000000000000000000000000000000000000000000000000000000000f400000000000000000000000000000000000000000000000000000000000000fd00000000000000000000000000000000000000000000000000000000000000f600000000000000000000000000000000000000000000000000000000000000a7000000000000000000000000000000000000000000000000000000000000004200000000000000000000000000000000000000000000000000000000000000aa00000000000000000000000000000000000000000000000000000000000000d1000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000a200000000000000000000000000000000000000000000000000000000000000d200000000000000000000000000000000000000000000000000000000000000f5000000000000000000000000000000000000000000000000000000000000006e00000000000000000000000000000000000000000000000000000000000000c100000000000000000000000000000000000000000000000000000000000000ac000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000bc0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000001700000000000000000000000000000000000000000000000000000000000000cf000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000053000000000000000000000000000000000000000000000000000000000000005400000000000000000000000000000000000000000000000000000000000000fa000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000950000000000000000000000000000000000000000000000000000000000000090000000000000000000000000000000000000000000000000000000000000007e00000000000000000000000000000000000000000000000000000000000000ed000000000000000000000000000000000000000000000000000000000000002d00000000000000000000000000000000000000000000000000000000000000c2000000000000000000000000000000000000000000000000000000000000009a00000000000000000000000000000000000000000000000000000000000000a3000000000000000000000000000000000000000000000000000000000000009100000000000000000000000000000000000000000000000000000000000000eb000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000002900000000000000000000000000000000000000000000000000000000000000eb00000000000000000000000000000000000000000000000000000000000000d300000000000000000000000000000000000000000000000000000000000000a200000000000000000000000000000000000000000000000000000000000000c900000000000000000000000000000000000000000000000000000000000000d70000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000003a00000000000000000000000000000000000000000000000000000000000000660000000000000000000000000000000000000000000000000000000000000085000000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000002b00000000000000000000000000000000000000000000000000000000000000a6000000000000000000000000000000000000000000000000000000000000008f000000000000000000000000000000000000000000000000000000000000005100000000000000000000000000000000000000000000000000000000000000bb00000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000048000000000000000000000000000000000000000000000000000000000000008c000000000000000000000000000000000000000000000000000000000000004c0000000000000000000000000000000000000000000000000000000000000078000000000000000000000000000000000000000000000000000000000000009200000000000000000000000000000000000000000000000000000000000000f80000000000000000000000000000000000000000000000000000000000000036000000000000000000000000000000000000000000000000000000000000006a00000000000000000000000000000000000000000000000000000000000000aa0000000000000000000000000000000000000000000000000000000000000019000000000000000000000000000000000000000000000000000000000000007e00000000000000000000000000000000000000000000000000000000000000f100000000000000000000000000000000000000000000000000000000000000a1000000000000000000000000000000000000000000000000000000000000006a0000000000000000000000000000000000000000000000000000000000000067000000000000000000000000000000000000000000000000000000000000006c000000000000000000000000000000000000000000000000000000000000006c000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000005800000000000000000000000000000000000000000000000000000000000000b400000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000000db00000000000000000000000000000000000000000000000000000000000000350000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000006a00000000000000000000000000000000000000000000000000000000000000ce00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000037000000000000000000000000000000000000000000000000000000000000006c000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000ee000000000000000000000000000000000000000000000000000000000000007e00000000000000000000000000000000000000000000000000000000000000c2000000000000000000000000000000000000000000000000000000000000006b00000000000000000000000000000000000000000000000000000000000000580000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004d00000000000000000000000000000000000000000000000000000000000000b4000000000000000000000000000000000000000000000000000000000000001d000000000000000000000000000000000000000000000000000000000000004900000000000000000000000000000000000000000000000000000000000000c1000000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000006300000000000000000000000000000000000000000000000000000000000000e500000000000000000000000000000000000000000000000000000000000000db00000000000000000000000000000000000000000000000000000000000000c500000000000000000000000000000000000000000000000000000000000000af00000000000000000000000000000000000000000000000000000000000000f400000000000000000000000000000000000000000000000000000000000000460000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000006e00000000000000000000000000000000000000000000000000000000000000710000000000000000000000000000000000000000000000000000000000000082000000000000000000000000000000000000000000000000000000000000007e0000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000006d000000000000000000000000000000000000000000000000000000000000004a00000000000000000000000000000000000000000000000000000000000000d800000000000000000000000000000000000000000000000000000000000000cb000000000000000000000000000000000000000000000000000000000000003d000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000009200000000000000000000000000000000000000000000000000000000000000c300000000000000000000000000000000000000000000000000000000000000e400000000000000000000000000000000000000000000000000000000000000f00000000000000000000000000000000000000000000000000000000000000019000000000000000000000000000000000000000000000000000000000000009600000000000000000000000000000000000000000000000000000000000000ad000000000000000000000000000000000000000000000000000000000000002f000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000006c000000000000000000000000000000000000000000000000000000000000005e000000000000000000000000000000000000000000000000000000000000006a0000000000000000000000000000000000000000000000000000000000000072000000000000000000000000000000000000000000000000000000000000000d00000000000000000000000000000000000000000000000000000000000000d400000000000000000000000000000000000000000000000000000000000000c300000000000000000000000000000000000000000000000000000000000000f60000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000008a00000000000000000000000000000000000000000000000000000000000000f5000000000000000000000000000000000000000000000000000000000000007a000000000000000000000000000000000000000000000000000000000000003f0000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000005d00000000000000000000000000000000000000000000000000000000000000c900000000000000000000000000000000000000000000000000000000000000ae0000000000000000000000000000000000000000000000000000000000000068000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000d60000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000008b000000000000000000000000000000000000000000000000000000000000003a00000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000d700000000000000000000000000000000000000000000000000000000000000b9000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000004500000000000000000000000000000000000000000000000000000000000000cb00000000000000000000000000000000000000000000000000000000000000ce0000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000003a00000000000000000000000000000000000000000000000000000000000000e700000000000000000000000000000000000000000000000000000000000000ab0000000000000000000000000000000000000000000000000000000000000075000000000000000000000000000000000000000000000000000000000000009f00000000000000000000000000000000000000000000000000000000000000d6000000000000000000000000000000000000000000000000000000000000004900000000000000000000000000000000000000000000000000000000000000ad000000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000009b000000000000000000000000000000000000000000000000000000000000001ba05d4d29b6f1b101809f9b43edea6e227828ed7df55663b482cff3d9d7a14ec20aa023db82ed86dd399e73aee94f0f0f8854d352c413e64c4b7f8d8a9bf5cb198d4b"))) d.mask |= uint32(1) << 0 d.mask |= uint32(1) << 8 hashRoot(d, "Hash7") diff --git a/erigon-lib/trie/hashbuilder.go b/erigon-lib/trie/hashbuilder.go index a38d922aade..e982b133345 100644 --- a/erigon-lib/trie/hashbuilder.go +++ b/erigon-lib/trie/hashbuilder.go @@ -46,7 +46,7 @@ type HashBuilder struct { byteArrayWriter *ByteArrayWriter hashStack []byte // Stack of sub-slices, each 33 bytes each, containing RLP encodings of node hashes (or of nodes themselves, if shorter than 32 bytes) - nodeStack []node // Stack of nodes + nodeStack []Node // Stack of nodes acc accounts.Account // Working account instance (to avoid extra allocations) sha keccakState // Keccak primitive that can absorb data (Write), and get squeezed to the hash out (Read) hashBuf [hashStackStride]byte // RLP representation of hash (or un-hashes value) @@ -104,7 +104,7 @@ func (hb *HashBuilder) leaf(length int, keyHex []byte, val rlphacks.RlpSerializa hb.proofElement.storageValue = new(uint256.Int).SetBytes(val.RawBytes()) } key := keyHex[len(keyHex)-length:] - s := &shortNode{Key: libcommon.CopyBytes(key), Val: valueNode(libcommon.CopyBytes(val.RawBytes()))} + s := &ShortNode{Key: libcommon.CopyBytes(key), Val: ValueNode(libcommon.CopyBytes(val.RawBytes()))} hb.nodeStack = append(hb.nodeStack, s) if err := hb.leafHashWithKeyVal(key, val); err != nil { return err @@ -245,19 +245,19 @@ func (hb *HashBuilder) accountLeaf(length int, keyHex []byte, balance *uint256.I hb.acc.Incarnation = incarnation popped := 0 - var root node + var root Node if fieldSet&uint32(4) != 0 { copy(hb.acc.Root[:], hb.hashStack[len(hb.hashStack)-popped*hashStackStride-length2.Hash:len(hb.hashStack)-popped*hashStackStride]) if hb.acc.Root != EmptyRoot { // Root is on top of the stack root = hb.nodeStack[len(hb.nodeStack)-popped-1] if root == nil { - root = hashNode{hash: libcommon.CopyBytes(hb.acc.Root[:])} + root = &HashNode{hash: libcommon.CopyBytes(hb.acc.Root[:])} } } popped++ } - var accountCode codeNode + var accountCode CodeNode if fieldSet&uint32(8) != 0 { copy(hb.acc.CodeHash[:], hb.hashStack[len(hb.hashStack)-popped*hashStackStride-length2.Hash:len(hb.hashStack)-popped*hashStackStride]) var ok bool @@ -265,7 +265,7 @@ func (hb *HashBuilder) accountLeaf(length int, keyHex []byte, balance *uint256.I stackTop := hb.nodeStack[len(hb.nodeStack)-popped-1] if stackTop != nil { // if we don't have any stack top it might be okay because we didn't resolve the code yet (stateful resolver) // but if we have something on top of the stack that isn't `nil`, it has to be a codeNode - accountCode, ok = stackTop.(codeNode) + accountCode, ok = stackTop.(CodeNode) if !ok { return fmt.Errorf("unexpected node type on the node stack, wanted codeNode, got %T:%s", stackTop, stackTop) } @@ -289,8 +289,8 @@ func (hb *HashBuilder) accountLeaf(length int, keyHex []byte, balance *uint256.I accountCodeSize = len(accountCode) } - a := &accountNode{accCopy, root, true, accountCode, accountCodeSize} - s := &shortNode{Key: libcommon.CopyBytes(key), Val: a} + a := &AccountNode{accCopy, root, true, accountCode, accountCodeSize} + s := &ShortNode{Key: libcommon.CopyBytes(key), Val: a} // this invocation will take care of the popping given number of items from both hash stack and node stack, // pushing resulting hash to the hash stack, and nil to the node stack if err = hb.accountLeafHashWithKey(key, popped); err != nil { @@ -391,13 +391,13 @@ func (hb *HashBuilder) extension(key []byte) error { fmt.Printf("EXTENSION %x\n", key) } nd := hb.nodeStack[len(hb.nodeStack)-1] - var s *shortNode + var s *ShortNode switch n := nd.(type) { case nil: branchHash := libcommon.CopyBytes(hb.hashStack[len(hb.hashStack)-length2.Hash:]) - s = &shortNode{Key: libcommon.CopyBytes(key), Val: hashNode{hash: branchHash}} - case *fullNode: - s = &shortNode{Key: libcommon.CopyBytes(key), Val: n} + s = &ShortNode{Key: libcommon.CopyBytes(key), Val: &HashNode{hash: branchHash}} + case *FullNode: + s = &ShortNode{Key: libcommon.CopyBytes(key), Val: n} default: return fmt.Errorf("wrong Val type for an extension: %T", nd) } @@ -488,7 +488,7 @@ func (hb *HashBuilder) extensionHash(key []byte) error { if hb.trace { fmt.Printf("extensionHash [%x]=>[%x]\nHash [%x]\n", key, capture, hb.hashStack[len(hb.hashStack)-hashStackStride:len(hb.hashStack)]) } - if _, ok := hb.nodeStack[len(hb.nodeStack)-1].(*fullNode); ok { + if _, ok := hb.nodeStack[len(hb.nodeStack)-1].(*FullNode); ok { return errors.New("extensionHash cannot be emitted when a node is on top of the stack") } return nil @@ -501,7 +501,7 @@ func (hb *HashBuilder) branch(set uint16) error { if hb.trace { fmt.Printf("Stack depth: %d\n", len(hb.nodeStack)) } - f := &fullNode{} + f := &FullNode{} digits := bits.OnesCount16(set) if len(hb.nodeStack) < digits { return fmt.Errorf("len(hb.nodeStask) %d < digits %d", len(hb.nodeStack), digits) @@ -512,7 +512,7 @@ func (hb *HashBuilder) branch(set uint16) error { for digit := uint(0); digit < 16; digit++ { if ((1 << digit) & set) != 0 { if nodes[i] == nil { - f.Children[digit] = hashNode{hash: libcommon.CopyBytes(hashes[hashStackStride*i+1 : hashStackStride*(i+1)])} + f.Children[digit] = &HashNode{hash: libcommon.CopyBytes(hashes[hashStackStride*i+1 : hashStackStride*(i+1)])} } else { f.Children[digit] = nodes[i] } @@ -643,7 +643,7 @@ func (hb *HashBuilder) code(code []byte) error { fmt.Printf("CODE\n") } codeCopy := libcommon.CopyBytes(code) - n := codeNode(codeCopy) + n := CodeNode(codeCopy) hb.nodeStack = append(hb.nodeStack, n) hb.sha.Reset() if _, err := hb.sha.Write(codeCopy); err != nil { @@ -658,6 +658,17 @@ func (hb *HashBuilder) code(code []byte) error { return nil } +func (hb *HashBuilder) emptyRoot() { + if hb.trace { + fmt.Printf("EMPTYROOT\n") + } + hb.nodeStack = append(hb.nodeStack, nil) + var hash [hashStackStride]byte // RLP representation of hash (or un-hashes value) + hash[0] = 0x80 + length2.Hash + copy(hash[1:], EmptyRoot[:]) + hb.hashStack = append(hb.hashStack, hash[:]...) +} + func (hb *HashBuilder) RootHash() (libcommon.Hash, error) { if !hb.hasRoot() { return libcommon.Hash{}, errors.New("no root in the tree") @@ -721,7 +732,7 @@ func (hb *HashBuilder) topHashes(prefix []byte, hasHash, hasState uint16) []byte return hb.topHashesCopy } -func (hb *HashBuilder) root() node { +func (hb *HashBuilder) root() Node { if hb.trace && len(hb.nodeStack) > 0 { fmt.Printf("len(hb.nodeStack)=%d\n", len(hb.nodeStack)) } diff --git a/erigon-lib/trie/hasher.go b/erigon-lib/trie/hasher.go index e191ca32044..5a11bc38318 100644 --- a/erigon-lib/trie/hasher.go +++ b/erigon-lib/trie/hasher.go @@ -21,15 +21,15 @@ package trie import ( "errors" + "fmt" "hash" "sync" - "golang.org/x/crypto/sha3" - libcommon "github.com/erigontech/erigon-lib/common" "github.com/erigontech/erigon-lib/common/length" - "github.com/erigontech/erigon-lib/crypto" + "golang.org/x/crypto/sha3" + "github.com/erigontech/erigon-lib/crypto" "github.com/erigontech/erigon-lib/rlp" "github.com/erigontech/erigon-lib/rlphacks" ) @@ -40,7 +40,7 @@ type hasher struct { buffers [1024 * 1024]byte prefixBuf [8]byte bw *ByteArrayWriter - callback func(libcommon.Hash, node) + callback func(libcommon.Hash, Node) } const rlpPrefixLength = 4 @@ -76,7 +76,7 @@ func returnHasherToPool(h *hasher) { // and stores the RLP if len(RLP) < 32 and not force, // otherwise it stores hash(RLP). // It also updates node's ref with that value. -func (h *hasher) hash(n node, force bool, storeTo []byte) (int, error) { +func (h *hasher) hash(n Node, force bool, storeTo []byte) (int, error) { return h.hashInternal(n, force, storeTo, 0) } @@ -84,8 +84,8 @@ func (h *hasher) hash(n node, force bool, storeTo []byte) (int, error) { // and stores the RLP if len(RLP) < 32 and not force, // otherwise it stores hash(RLP). // It also updates node's ref with that value. -func (h *hasher) hashInternal(n node, force bool, storeTo []byte, bufOffset int) (int, error) { - if hn, ok := n.(hashNode); ok { +func (h *hasher) hashInternal(n Node, force bool, storeTo []byte, bufOffset int) (int, error) { + if hn, ok := n.(HashNode); ok { copy(storeTo, hn.hash) return length.Hash, nil } @@ -105,15 +105,15 @@ func (h *hasher) hashInternal(n node, force bool, storeTo []byte, bufOffset int) } switch n := n.(type) { - case *shortNode: + case *ShortNode: copy(n.ref.data[:], storeTo) n.ref.len = byte(refLen) - case *accountNode: - n.rootCorrect = true - case *duoNode: + case *AccountNode: + n.RootCorrect = true + case *DuoNode: copy(n.ref.data[:], storeTo) n.ref.len = byte(refLen) - case *fullNode: + case *FullNode: copy(n.ref.data[:], storeTo) n.ref.len = byte(refLen) } @@ -155,12 +155,12 @@ func writeRlpPrefix(buffer []byte, pos int) []byte { // if the RLP-encoded size of the child is >= 32, // returning node's RLP with the child hashes cached in. // DESCRIBED: docs/programmers_guide/guide.md#hexary-radix-patricia-tree -func (h *hasher) hashChildren(original node, bufOffset int) ([]byte, error) { +func (h *hasher) hashChildren(original Node, bufOffset int) ([]byte, error) { buffer := h.buffers[bufOffset:] pos := rlpPrefixLength switch n := original.(type) { - case *shortNode: + case *ShortNode: // Starting at position 3, to leave space for len prefix // Encode key compactKey := hexToCompact(n.Key) @@ -172,19 +172,19 @@ func (h *hasher) hashChildren(original node, bufOffset int) ([]byte, error) { pos += written // Encode value - if vn, ok := n.Val.(valueNode); ok { + if vn, ok := n.Val.(ValueNode); ok { written, err := h.valueNodeToBuffer(vn, buffer, pos) if err != nil { return nil, err } pos += written - } else if ac, ok := n.Val.(*accountNode); ok { + } else if ac, ok := n.Val.(*AccountNode); ok { // Hashing the storage trie if necessary - if ac.storage == nil { + if ac.Storage == nil { ac.Root = EmptyRoot } else { - _, err := h.hashInternal(ac.storage, true, ac.Root[:], bufOffset+pos) + _, err := h.hashInternal(ac.Storage, true, ac.Root[:], bufOffset+pos) if err != nil { return nil, err } @@ -204,10 +204,10 @@ func (h *hasher) hashChildren(original node, bufOffset int) ([]byte, error) { } return writeRlpPrefix(buffer, pos), nil - case *duoNode: + case *DuoNode: i1, i2 := n.childrenIdx() for i := 0; i < 17; i++ { - var child node + var child Node if i == int(i1) { child = n.child1 @@ -227,7 +227,7 @@ func (h *hasher) hashChildren(original node, bufOffset int) ([]byte, error) { } return writeRlpPrefix(buffer, pos), nil - case *fullNode: + case *FullNode: // Hash the full node's children, caching the newly hashed subtrees for _, child := range n.Children[:16] { written, err := h.hashChild(child, buffer, pos, bufOffset) @@ -237,14 +237,14 @@ func (h *hasher) hashChildren(original node, bufOffset int) ([]byte, error) { pos += written } switch n := n.Children[16].(type) { - case *accountNode: + case *AccountNode: written, err := h.accountNodeToBuffer(n, buffer, pos) if err != nil { return nil, err } pos += written - case valueNode: + case ValueNode: written, err := h.valueNodeToBuffer(n, buffer, pos) if err != nil { return nil, err @@ -260,7 +260,7 @@ func (h *hasher) hashChildren(original node, bufOffset int) ([]byte, error) { return writeRlpPrefix(buffer, pos), nil - case valueNode: + case ValueNode: written, err := h.valueNodeToBuffer(n, buffer, pos) if err != nil { return nil, err @@ -269,19 +269,19 @@ func (h *hasher) hashChildren(original node, bufOffset int) ([]byte, error) { return buffer[rlpPrefixLength:pos], nil - case *accountNode: + case *AccountNode: // we don't do double RLP here, so `accountNodeToBuffer` is not applicable n.EncodeForHashing(buffer[pos:]) return buffer[rlpPrefixLength:pos], nil - case hashNode: + case HashNode: return nil, errors.New("hasher#hashChildren: met unexpected hash node") } return nil, nil } -func (h *hasher) valueNodeToBuffer(vn valueNode, buffer []byte, pos int) (int, error) { +func (h *hasher) valueNodeToBuffer(vn ValueNode, buffer []byte, pos int) (int, error) { h.bw.Setup(buffer, pos) var val rlphacks.RlpSerializable @@ -292,13 +292,14 @@ func (h *hasher) valueNodeToBuffer(vn valueNode, buffer []byte, pos int) (int, e val = rlphacks.RlpSerializableBytes(vn) } + fmt.Printf("valueNodeToBuffer()>>>>>>> val=%x\n", val) if err := val.ToDoubleRLP(h.bw, h.prefixBuf[:]); err != nil { return 0, err } return val.DoubleRLPLen(), nil } -func (h *hasher) accountNodeToBuffer(ac *accountNode, buffer []byte, pos int) (int, error) { +func (h *hasher) accountNodeToBuffer(ac *AccountNode, buffer []byte, pos int) (int, error) { acRlp := make([]byte, ac.EncodingLengthForHashing()) ac.EncodeForHashing(acRlp) enc := rlphacks.RlpEncodedBytes(acRlp) @@ -336,7 +337,7 @@ func (h *hasher) nodeRef(nodeRlp []byte, force bool, storeTo []byte) (int, error return 32, nil } -func (h *hasher) hashChild(child node, buffer []byte, pos int, bufOffset int) (int, error) { +func (h *hasher) hashChild(child Node, buffer []byte, pos int, bufOffset int) (int, error) { if child == nil { return writeEmptyByteArray(buffer, pos), nil } diff --git a/erigon-lib/trie/hasher_test.go b/erigon-lib/trie/hasher_test.go index ca1b4d87490..542cd16440c 100644 --- a/erigon-lib/trie/hasher_test.go +++ b/erigon-lib/trie/hasher_test.go @@ -28,7 +28,7 @@ func TestValue(t *testing.T) { h := newHasher(false) var hn libcommon.Hash - h.hash(valueNode("BLAH"), false, hn[:]) + h.hash(ValueNode("BLAH"), false, hn[:]) expected := "0x0" actual := fmt.Sprintf("0x%x", hn[:]) if actual != expected { diff --git a/erigon-lib/trie/node.go b/erigon-lib/trie/node.go index 5fbdfb187df..9900eb0043b 100644 --- a/erigon-lib/trie/node.go +++ b/erigon-lib/trie/node.go @@ -34,7 +34,7 @@ const codeSizeUncached = -1 var indices = []string{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f", "[17]"} -type node interface { +type Node interface { print(io.Writer) fstring(string) string @@ -44,45 +44,49 @@ type node interface { type ( // DESCRIBED: docs/programmers_guide/guide.md#hexary-radix-patricia-tree - fullNode struct { + FullNode struct { ref nodeRef - Children [17]node // Actual trie node data to encode/decode (needs custom encoder) + Children [17]Node // Actual trie node data to encode/decode (needs custom encoder) } // DESCRIBED: docs/programmers_guide/guide.md#hexary-radix-patricia-tree - duoNode struct { + DuoNode struct { ref nodeRef mask uint32 // Bitmask. The set bits indicate the child is not nil - child1 node - child2 node + child1 Node + child2 Node } // DESCRIBED: docs/programmers_guide/guide.md#hexary-radix-patricia-tree - shortNode struct { + ShortNode struct { ref nodeRef Key []byte // HEX encoding - Val node + Val Node } - hashNode struct { + HashNode struct { hash []byte } - valueNode []byte + ValueNode []byte - accountNode struct { + AccountNode struct { accounts.Account - storage node - rootCorrect bool - code codeNode - codeSize int + Storage Node + RootCorrect bool + Code CodeNode + CodeSize int } - codeNode []byte + CodeNode []byte ) // nilValueNode is used when collapsing internal trie nodes for hashing, since // unset hasState need to serialize correctly. -var nilValueNode = valueNode(nil) +var nilValueNode = ValueNode(nil) -func NewShortNode(key []byte, value node) *shortNode { - s := &shortNode{ +func NewHashNode(hash []byte) *HashNode { + return &HashNode{hash: hash} +} + +func NewShortNode(key []byte, value Node) *ShortNode { + s := &ShortNode{ Key: key, Val: value, } @@ -92,15 +96,15 @@ func NewShortNode(key []byte, value node) *shortNode { func EncodeAsValue(data []byte) ([]byte, error) { tmp := new(bytes.Buffer) - if err := rlp.Encode(tmp, valueNode(data)); err != nil { + if err := rlp.Encode(tmp, ValueNode(data)); err != nil { return nil, err } return tmp.Bytes(), nil } // EncodeRLP encodes a full node into the consensus RLP format. -func (n *fullNode) EncodeRLP(w io.Writer) error { - var nodes [17]node +func (n *FullNode) EncodeRLP(w io.Writer) error { + var nodes [17]Node for i, child := range &n.Children { if child != nil { @@ -112,20 +116,20 @@ func (n *fullNode) EncodeRLP(w io.Writer) error { return rlp.Encode(w, nodes) } -func (n *duoNode) EncodeRLP(w io.Writer) error { - var children [17]node +func (n *DuoNode) EncodeRLP(w io.Writer) error { + var children [17]Node i1, i2 := n.childrenIdx() children[i1] = n.child1 children[i2] = n.child2 for i := 0; i < 17; i++ { if i != int(i1) && i != int(i2) { - children[i] = valueNode(nil) + children[i] = ValueNode(nil) } } return rlp.Encode(w, children) } -func (n *duoNode) childrenIdx() (i1 byte, i2 byte) { +func (n *DuoNode) childrenIdx() (i1 byte, i2 byte) { child := 1 var m uint32 = 1 for i := 0; i < 17; i++ { @@ -143,16 +147,16 @@ func (n *duoNode) childrenIdx() (i1 byte, i2 byte) { return i1, i2 } -func resetRefs(nd node) { +func resetRefs(nd Node) { switch n := nd.(type) { - case *shortNode: + case *ShortNode: n.ref.len = 0 resetRefs(n.Val) - case *duoNode: + case *DuoNode: n.ref.len = 0 resetRefs(n.child1) resetRefs(n.child2) - case *fullNode: + case *FullNode: n.ref.len = 0 for _, child := range n.Children { if child != nil { @@ -169,22 +173,22 @@ type nodeRef struct { len byte // length of the data (0 indicates invalid data) } -func (n hashNode) reference() []byte { return n.hash } -func (n valueNode) reference() []byte { return nil } -func (n codeNode) reference() []byte { return nil } -func (n *fullNode) reference() []byte { return n.ref.data[0:n.ref.len] } -func (n *duoNode) reference() []byte { return n.ref.data[0:n.ref.len] } -func (n *shortNode) reference() []byte { return n.ref.data[0:n.ref.len] } -func (an *accountNode) reference() []byte { return nil } +func (n HashNode) reference() []byte { return n.hash } +func (n ValueNode) reference() []byte { return nil } +func (n CodeNode) reference() []byte { return nil } +func (n *FullNode) reference() []byte { return n.ref.data[0:n.ref.len] } +func (n *DuoNode) reference() []byte { return n.ref.data[0:n.ref.len] } +func (n *ShortNode) reference() []byte { return n.ref.data[0:n.ref.len] } +func (an *AccountNode) reference() []byte { return nil } // Pretty printing. -func (n fullNode) String() string { return n.fstring("") } -func (n duoNode) String() string { return n.fstring("") } -func (n shortNode) String() string { return n.fstring("") } -func (n hashNode) String() string { return n.fstring("") } -func (n valueNode) String() string { return n.fstring("") } -func (n codeNode) String() string { return n.fstring("") } -func (an accountNode) String() string { return an.fstring("") } +func (n FullNode) String() string { return n.fstring("") } +func (n DuoNode) String() string { return n.fstring("") } +func (n ShortNode) String() string { return n.fstring("") } +func (n HashNode) String() string { return n.fstring("") } +func (n ValueNode) String() string { return n.fstring("") } +func (n CodeNode) String() string { return n.fstring("") } +func (an AccountNode) String() string { return an.fstring("") } func CodeKeyFromAddrHash(addrHash []byte) []byte { return append(addrHash, 0xC0, 0xDE) @@ -209,52 +213,52 @@ func AddrHashFromCodeKey(codeKey []byte) []byte { return codeKey[:len(codeKey)-2] } -func calcSubtreeSize(node node) int { +func calcSubtreeSize(node Node) int { switch n := node.(type) { case nil: return 0 - case valueNode: + case ValueNode: return 0 - case *shortNode: + case *ShortNode: return calcSubtreeSize(n.Val) - case *duoNode: + case *DuoNode: return 1 + calcSubtreeSize(n.child1) + calcSubtreeSize(n.child2) - case *fullNode: + case *FullNode: size := 1 for _, child := range n.Children { size += calcSubtreeSize(child) } return size - case *accountNode: - return len(n.code) + calcSubtreeSize(n.storage) - case hashNode: + case *AccountNode: + return len(n.Code) + calcSubtreeSize(n.Storage) + case HashNode: return 0 } return 0 } -func calcSubtreeNodes(node node) int { +func calcSubtreeNodes(node Node) int { switch n := node.(type) { case nil: return 0 - case valueNode: + case ValueNode: return 0 - case *shortNode: + case *ShortNode: return calcSubtreeNodes(n.Val) - case *duoNode: + case *DuoNode: return 1 + calcSubtreeNodes(n.child1) + calcSubtreeNodes(n.child2) - case *fullNode: + case *FullNode: size := 1 for _, child := range n.Children { size += calcSubtreeNodes(child) } return size - case *accountNode: - if n.code != nil { - return 1 + calcSubtreeNodes(n.storage) + case *AccountNode: + if n.Code != nil { + return 1 + calcSubtreeNodes(n.Storage) } - return calcSubtreeNodes(n.storage) - case hashNode: + return calcSubtreeNodes(n.Storage) + case HashNode: return 0 } return 0 diff --git a/erigon-lib/trie/proof.go b/erigon-lib/trie/proof.go index 9fcd8770aea..6e54235cc18 100644 --- a/erigon-lib/trie/proof.go +++ b/erigon-lib/trie/proof.go @@ -43,10 +43,10 @@ func (t *Trie) Prove(key []byte, fromLevel int, storage bool) ([][]byte, error) // Collect all nodes on the path to key. key = keybytesToHex(key) key = key[:len(key)-1] // Remove terminator - tn := t.root + tn := t.RootNode for len(key) > 0 && tn != nil { switch n := tn.(type) { - case *shortNode: + case *ShortNode: if fromLevel == 0 { if rlp, err := hasher.hashChildren(n, 0); err == nil { proof = append(proof, libcommon.CopyBytes(rlp)) @@ -68,7 +68,7 @@ func (t *Trie) Prove(key []byte, fromLevel int, storage bool) ([][]byte, error) if fromLevel > 0 { fromLevel -= len(nKey) } - case *duoNode: + case *DuoNode: if fromLevel == 0 { if rlp, err := hasher.hashChildren(n, 0); err == nil { proof = append(proof, libcommon.CopyBytes(rlp)) @@ -90,7 +90,7 @@ func (t *Trie) Prove(key []byte, fromLevel int, storage bool) ([][]byte, error) if fromLevel > 0 { fromLevel-- } - case *fullNode: + case *FullNode: if fromLevel == 0 { if rlp, err := hasher.hashChildren(n, 0); err == nil { proof = append(proof, libcommon.CopyBytes(rlp)) @@ -103,15 +103,15 @@ func (t *Trie) Prove(key []byte, fromLevel int, storage bool) ([][]byte, error) if fromLevel > 0 { fromLevel-- } - case *accountNode: + case *AccountNode: if storage { - tn = n.storage + tn = n.Storage } else { tn = nil } - case valueNode: + case ValueNode: tn = nil - case hashNode: + case HashNode: return nil, fmt.Errorf("encountered hashNode unexpectedly, key %x, fromLevel %d", key, fromLevel) default: panic(fmt.Sprintf("%T: invalid node: %v", tn, tn)) @@ -120,7 +120,7 @@ func (t *Trie) Prove(key []byte, fromLevel int, storage bool) ([][]byte, error) return proof, nil } -func decodeRef(buf []byte) (node, []byte, error) { +func decodeRef(buf []byte) (Node, []byte, error) { kind, val, rest, err := rlp.Split(buf) if err != nil { return nil, nil, err @@ -138,14 +138,14 @@ func decodeRef(buf []byte) (node, []byte, error) { case kind == rlp.String && len(val) == 0: return nil, rest, nil case kind == rlp.String && len(val) == 32: - return hashNode{hash: val}, rest, nil + return HashNode{hash: val}, rest, nil default: return nil, nil, fmt.Errorf("invalid RLP string size %d (want 0 through 32)", len(val)) } } -func decodeFull(elems []byte) (*fullNode, error) { - n := &fullNode{} +func decodeFull(elems []byte) (*FullNode, error) { + n := &FullNode{} for i := 0; i < 16; i++ { var err error n.Children[i], elems, err = decodeRef(elems) @@ -159,12 +159,12 @@ func decodeFull(elems []byte) (*fullNode, error) { return nil, err } if len(val) > 0 { - n.Children[16] = valueNode(val) + n.Children[16] = ValueNode(val) } return n, nil } -func decodeShort(elems []byte) (*shortNode, error) { +func decodeShort(elems []byte) (*ShortNode, error) { kbuf, rest, err := rlp.SplitString(elems) if err != nil { return nil, err @@ -175,9 +175,9 @@ func decodeShort(elems []byte) (*shortNode, error) { if err != nil { return nil, err } - return &shortNode{ + return &ShortNode{ Key: kb.ToHex(), - Val: valueNode(val), + Val: ValueNode(val), }, nil } @@ -185,13 +185,13 @@ func decodeShort(elems []byte) (*shortNode, error) { if err != nil { return nil, err } - return &shortNode{ + return &ShortNode{ Key: kb.ToHex(), Val: val, }, nil } -func decodeNode(encoded []byte) (node, error) { +func decodeNode(encoded []byte) (Node, error) { if len(encoded) == 0 { return nil, errors.New("nodes must not be zero length") } @@ -215,8 +215,8 @@ type rawProofElement struct { } // proofMap creates a map from hash to proof node -func proofMap(proof []hexutility.Bytes) (map[libcommon.Hash]node, map[libcommon.Hash]rawProofElement, error) { - res := map[libcommon.Hash]node{} +func proofMap(proof []hexutility.Bytes) (map[libcommon.Hash]Node, map[libcommon.Hash]rawProofElement, error) { + res := map[libcommon.Hash]Node{} raw := map[libcommon.Hash]rawProofElement{} for i, proofB := range proof { hash := crypto.Keccak256Hash(proofB) @@ -233,13 +233,13 @@ func proofMap(proof []hexutility.Bytes) (map[libcommon.Hash]node, map[libcommon. return res, raw, nil } -func verifyProof(root libcommon.Hash, key []byte, proofs map[libcommon.Hash]node, used map[libcommon.Hash]rawProofElement) ([]byte, error) { +func verifyProof(root libcommon.Hash, key []byte, proofs map[libcommon.Hash]Node, used map[libcommon.Hash]rawProofElement) ([]byte, error) { nextIndex := 0 key = keybytesToHex(key) - var node node = hashNode{hash: root[:]} + var node Node = HashNode{hash: root[:]} for { switch nt := node.(type) { - case *fullNode: + case *FullNode: if len(key) == 0 { return nil, errors.New("full nodes should not have values") } @@ -247,7 +247,7 @@ func verifyProof(root libcommon.Hash, key []byte, proofs map[libcommon.Hash]node if node == nil { return nil, nil } - case *shortNode: + case *ShortNode: shortHex := nt.Key if len(shortHex) > len(key) { return nil, fmt.Errorf("len(shortHex)=%d must be leq len(key)=%d", len(shortHex), len(key)) @@ -256,7 +256,7 @@ func verifyProof(root libcommon.Hash, key []byte, proofs map[libcommon.Hash]node return nil, nil } node, key = nt.Val, key[len(shortHex):] - case hashNode: + case HashNode: var ok bool h := libcommon.BytesToHash(nt.hash) node, ok = proofs[h] @@ -272,7 +272,7 @@ func verifyProof(root libcommon.Hash, key []byte, proofs map[libcommon.Hash]node } nextIndex++ delete(used, h) - case valueNode: + case ValueNode: if len(key) != 0 { return nil, fmt.Errorf("value node should have zero length remaining in key %x", key) } diff --git a/erigon-lib/trie/retain_list.go b/erigon-lib/trie/retain_list.go index fb9215c3c4f..e40c3664e65 100644 --- a/erigon-lib/trie/retain_list.go +++ b/erigon-lib/trie/retain_list.go @@ -50,11 +50,58 @@ type RetainDeciderWithMarker interface { RetainWithMarker(prefix []byte) (retain bool, nextMarkedKey []byte) } -// ProofRetainer is a wrapper around the RetainList passed to the trie builder. +// ProofRetainer is an interface that is used to retain proof elements during trie computation +type ProofRetainer interface { + // ProofElement requests a new proof element for a given prefix. Returns nil if + // the prefix is not needed for the proof. + ProofElement(prefix []byte) *proofElement +} + +type MultiAccountProofRetainer struct { + AccHexKeys [][]byte + Rl *RetainList +} + +func NewMultiAccountProofRetainer(rl *RetainList) *MultiAccountProofRetainer { + return &MultiAccountProofRetainer{ + AccHexKeys: make([][]byte, 0), + Rl: rl, + } +} + +func (pr *MultiAccountProofRetainer) ProofElement(prefix []byte) *proofElement { + if !pr.Rl.Retain(prefix) && ((len(prefix) > 1) && !pr.Rl.Retain(prefix[:len(prefix)-2])) { + return nil + } + + found := false + + for _, accHexKey := range pr.AccHexKeys { + if bytes.HasPrefix(accHexKey, prefix) { + found = true + break + } + + if bytes.HasPrefix(prefix, accHexKey) { + found = true + break + } + } + + if !found { + return nil + } + + return &proofElement{ + hexKey: prefix, + } +} + +// DefaultProofRetainer is a wrapper around the RetainList passed to the trie builder. // It is responsible for aggregating proof values from the trie computation and // will return a valid accounts.AccProofresult after the trie root hash // calculation has completed. -type ProofRetainer struct { +type DefaultProofRetainer struct { rl *RetainList addr libcommon.Address acc *accounts.Account @@ -69,7 +116,7 @@ type ProofRetainer struct { // storage keys are added to the given RetainList. The ProofRetainer should be // set onto the FlatDBTrieLoader via SetProofRetainer before performing its Load // operation in order to appropriately collect the proof elements. -func NewProofRetainer(addr libcommon.Address, a *accounts.Account, storageKeys []libcommon.Hash, rl *RetainList) (*ProofRetainer, error) { +func NewProofRetainer(addr libcommon.Address, a *accounts.Account, storageKeys []libcommon.Hash, rl *RetainList) (*DefaultProofRetainer, error) { addrHash, err := libcommon.HashData(addr[:]) if err != nil { return nil, err @@ -90,7 +137,7 @@ func NewProofRetainer(addr libcommon.Address, a *accounts.Account, storageKeys [ storageHexKeys[i] = rl.AddKey(compactEncoded[:]) } - return &ProofRetainer{ + return &DefaultProofRetainer{ rl: rl, addr: addr, acc: a, @@ -104,7 +151,7 @@ func NewProofRetainer(addr libcommon.Address, a *accounts.Account, storageKeys [ // element is retained by the ProofRetainer, and will be utilized to compute the // proof after the trie computation has completed. The prefix is the standard // nibble encoded prefix used in the rest of the trie computations. -func (pr *ProofRetainer) ProofElement(prefix []byte) *proofElement { +func (pr *DefaultProofRetainer) ProofElement(prefix []byte) *proofElement { if !pr.rl.Retain(prefix) { return nil } @@ -134,7 +181,7 @@ func (pr *ProofRetainer) ProofElement(prefix []byte) *proofElement { // Balance, Nonce, and CodeHash from the account data supplied in the // constructor, the StorageHash, storageKey values, and proof elements are // supplied by the Load operation of the trie construction. -func (pr *ProofRetainer) ProofResult() (*accounts.AccProofResult, error) { +func (pr *DefaultProofRetainer) ProofResult() (*accounts.AccProofResult, error) { result := &accounts.AccProofResult{ Address: pr.addr, Balance: (*hexutil.Big)(pr.acc.Balance.ToBig()), @@ -280,6 +327,10 @@ func (rl *RetainList) AddHex(hex []byte) { rl.hexes = append(rl.hexes, hex) } +func (rl *RetainList) AddMarker(marker bool) { + rl.markers = append(rl.markers, marker) +} + // AddCodeTouch adds a new code touch into the resolve set func (rl *RetainList) AddCodeTouch(codeHash libcommon.Hash) { rl.codeTouches[codeHash] = struct{}{} @@ -310,6 +361,10 @@ func (rl *RetainList) ensureInited() { // come in monotonically ascending order, we optimise for this, though // the function would still work if the order is different func (rl *RetainList) Retain(prefix []byte) bool { + // if bytes.HasPrefix(prefix, libcommon.FromHex("0x0d05")) { + // fmt.Println("here!!!!!") + // } + rl.ensureInited() if len(prefix) < rl.minLength { return true diff --git a/erigon-lib/trie/retain_list_builder.go b/erigon-lib/trie/retain_list_builder.go new file mode 100644 index 00000000000..adc84d2e2f5 --- /dev/null +++ b/erigon-lib/trie/retain_list_builder.go @@ -0,0 +1,101 @@ +package trie + +import ( + "github.com/erigontech/erigon-lib/common" +) + +// RetainListBuilder is the structure that accumulates the list of keys that were read or changes (touched) during +// the execution of a block. It also tracks the contract codes that were created and used during the execution +// of a block +type RetainListBuilder struct { + touches [][]byte // Read/change set of account keys (account hashes) + storageTouches [][]byte // Read/change set of storage keys (account hashes concatenated with storage key hashes) + proofCodes map[common.Hash][]byte // Contract codes that have been accessed (codeHash) + createdCodes map[common.Hash]struct{} // Contract codes that were created (deployed) (codeHash) +} + +// NewRetainListBuilder creates new ProofGenerator and initialised its maps +func NewRetainListBuilder() *RetainListBuilder { + return &RetainListBuilder{ + proofCodes: make(map[common.Hash][]byte), + createdCodes: make(map[common.Hash]struct{}), + } +} + +// AddTouch adds a key (in KEY encoding) into the read/change set of account keys +func (rlb *RetainListBuilder) AddTouch(touch []byte) { + rlb.touches = append(rlb.touches, common.CopyBytes(touch)) +} + +// AddStorageTouch adds a key (in KEY encoding) into the read/change set of storage keys +func (rlb *RetainListBuilder) AddStorageTouch(touch []byte) { + rlb.storageTouches = append(rlb.storageTouches, common.CopyBytes(touch)) +} + +// ExtractTouches returns accumulated read/change sets and clears them for the next block's execution +func (rlb *RetainListBuilder) ExtractTouches() ([][]byte, [][]byte) { + touches := rlb.touches + storageTouches := rlb.storageTouches + rlb.touches = nil + rlb.storageTouches = nil + return touches, storageTouches +} + +// extractCodeTouches returns the set of all contract codes that were required during the block's execution +// but were not created during that same block. It also clears the set for the next block's execution +func (rlb *RetainListBuilder) extractCodeTouches() map[common.Hash][]byte { + proofCodes := rlb.proofCodes + rlb.proofCodes = make(map[common.Hash][]byte) + rlb.createdCodes = make(map[common.Hash]struct{}) + return proofCodes +} + +// ReadCode registers that given contract code has been accessed during current block's execution +func (rlb *RetainListBuilder) ReadCode(codeHash common.Hash, code []byte) { + if _, ok := rlb.proofCodes[codeHash]; !ok { + rlb.proofCodes[codeHash] = code + } +} + +// CreateCode registers that given contract code has been created (deployed) during current block's execution +func (rlb *RetainListBuilder) CreateCode(codeHash common.Hash) { + if _, ok := rlb.proofCodes[codeHash]; !ok { + rlb.createdCodes[codeHash] = struct{}{} + } +} + +func (rlb *RetainListBuilder) Build(isBinary bool) *RetainList { + var rl *RetainList = NewRetainList(0) + + touches, storageTouches := rlb.ExtractTouches() + codeTouches := rlb.extractCodeTouches() + + for _, touch := range touches { + rl.AddKey(touch) + } + for _, touch := range storageTouches { + rl.AddKey(touch) + } + for codeHash := range codeTouches { + rl.AddCodeTouch(codeHash) + } + + return rl +} + +func (rlb *RetainListBuilder) Copy() *RetainListBuilder { + rlbCopy := NewRetainListBuilder() + for _, touch := range rlb.touches { + rlbCopy.AddTouch(touch) + } + for _, touch := range rlb.storageTouches { + rlbCopy.AddStorageTouch(touch) + } + for codeHash, code := range rlb.proofCodes { + rlbCopy.ReadCode(codeHash, code) + } + for codeHash := range rlb.createdCodes { + rlbCopy.CreateCode(codeHash) + } + return rlbCopy +} diff --git a/erigon-lib/trie/retain_list_test.go b/erigon-lib/trie/retain_list_test.go index 8ea96798208..7b0ffd58b29 100644 --- a/erigon-lib/trie/retain_list_test.go +++ b/erigon-lib/trie/retain_list_test.go @@ -39,7 +39,7 @@ func FakePreimage(hash libcommon.Hash) libcommon.Hash { // manually construct a ProofRetainer based on a set of keys. This is // especially useful for tests which want to manually manipulate the hash // databases without worrying about generating and tracking pre-images. -func NewManualProofRetainer(t *testing.T, acc *accounts.Account, rl *RetainList, keys [][]byte) *ProofRetainer { +func NewManualProofRetainer(t *testing.T, acc *accounts.Account, rl *RetainList, keys [][]byte) *DefaultProofRetainer { t.Helper() var accHexKey []byte var storageKeys []libcommon.Hash @@ -60,7 +60,7 @@ func NewManualProofRetainer(t *testing.T, acc *accounts.Account, rl *RetainList, require.Fail(t, "unexpected key length %d", len(key)) } } - return &ProofRetainer{ + return &DefaultProofRetainer{ rl: rl, acc: acc, accHexKey: accHexKey, diff --git a/erigon-lib/trie/stream.go b/erigon-lib/trie/stream.go index ce5bd1593ff..1875fa98174 100644 --- a/erigon-lib/trie/stream.go +++ b/erigon-lib/trie/stream.go @@ -98,7 +98,7 @@ type StreamIterator interface { type Iterator struct { rl *RetainList hex []byte - nodeStack []node + nodeStack []Node iStack []int goDeepStack []bool lenStack []int @@ -112,7 +112,7 @@ func NewIterator(t *Trie, rl *RetainList, trace bool) *Iterator { return &Iterator{ rl: rl, hex: []byte{}, - nodeStack: []node{t.root}, + nodeStack: []Node{t.RootNode}, iStack: []int{0}, goDeepStack: []bool{true}, lenStack: []int{0}, @@ -129,7 +129,7 @@ func (it *Iterator) Reset(t *Trie, rl *RetainList, trace bool) { if len(it.nodeStack) > 0 { it.nodeStack = it.nodeStack[:0] } - it.nodeStack = append(it.nodeStack, t.root) + it.nodeStack = append(it.nodeStack, t.RootNode) if len(it.iStack) > 0 { it.iStack = it.iStack[:0] } @@ -161,13 +161,13 @@ func (it *Iterator) Next() (itemType StreamItem, hex1 []byte, aValue *accounts.A switch n := nd.(type) { case nil: return NoItem, nil, nil, nil, nil - case valueNode: + case ValueNode: if it.trace { fmt.Printf("valueNode %x\n", hex) } it.top-- return StorageStreamItem, hex, nil, nil, n - case *shortNode: + case *ShortNode: if it.trace { fmt.Printf("shortNode %x\n", hex) } @@ -177,20 +177,20 @@ func (it *Iterator) Next() (itemType StreamItem, hex1 []byte, aValue *accounts.A } hex = append(hex, nKey...) switch v := n.Val.(type) { - case hashNode: + case HashNode: it.top-- if accounts { return AHashStreamItem, hex, nil, v.hash, nil } return SHashStreamItem, hex, nil, v.hash, nil - case valueNode: + case ValueNode: it.top-- return StorageStreamItem, hex, nil, nil, v - case *accountNode: + case *AccountNode: if it.trace { fmt.Printf("accountNode %x\n", hex) } - if v.storage != nil { + if v.Storage != nil { binary.BigEndian.PutUint64(bytes8[:], v.Incarnation) // Add decompressed incarnation to the hex for i, b := range bytes8[:] { @@ -198,7 +198,7 @@ func (it *Iterator) Next() (itemType StreamItem, hex1 []byte, aValue *accounts.A bytes16[i*2+1] = b % 16 } it.hex = append(hex, bytes16[:]...) - it.nodeStack[l] = v.storage + it.nodeStack[l] = v.Storage it.iStack[l] = 0 it.goDeepStack[l] = true it.lenStack[l] = len(it.hex) @@ -214,7 +214,7 @@ func (it *Iterator) Next() (itemType StreamItem, hex1 []byte, aValue *accounts.A it.goDeepStack[l] = it.rl.Retain(hex) it.lenStack[l] = len(hex) it.accountStack[l] = accounts - case *duoNode: + case *DuoNode: if it.trace { fmt.Printf("duoNode %x\n", hex) } @@ -232,12 +232,12 @@ func (it *Iterator) Next() (itemType StreamItem, hex1 []byte, aValue *accounts.A hex = append(hex, i1) var childGoDeep bool switch v := n.child1.(type) { - case hashNode: + case HashNode: if accounts { return AHashStreamItem, hex, nil, v.hash, nil } return SHashStreamItem, hex, nil, v.hash, nil - case *duoNode: + case *DuoNode: childGoDeep = it.rl.Retain(hex) if !childGoDeep { if accounts { @@ -245,7 +245,7 @@ func (it *Iterator) Next() (itemType StreamItem, hex1 []byte, aValue *accounts.A } return SHashStreamItem, hex, nil, v.reference(), nil } - case *fullNode: + case *FullNode: childGoDeep = it.rl.Retain(hex) if !childGoDeep { if accounts { @@ -274,13 +274,13 @@ func (it *Iterator) Next() (itemType StreamItem, hex1 []byte, aValue *accounts.A hex = append(hex, i2) var childGoDeep bool switch v := n.child2.(type) { - case hashNode: + case HashNode: it.top-- if accounts { return AHashStreamItem, hex, nil, v.hash, nil } return SHashStreamItem, hex, nil, v.hash, nil - case *duoNode: + case *DuoNode: childGoDeep = it.rl.Retain(hex) if !childGoDeep { it.top-- @@ -289,7 +289,7 @@ func (it *Iterator) Next() (itemType StreamItem, hex1 []byte, aValue *accounts.A } return SHashStreamItem, hex, nil, v.reference(), nil } - case *fullNode: + case *FullNode: childGoDeep = it.rl.Retain(hex) if !childGoDeep { it.top-- @@ -306,7 +306,7 @@ func (it *Iterator) Next() (itemType StreamItem, hex1 []byte, aValue *accounts.A it.lenStack[l] = len(hex) it.accountStack[l] = accounts } - case *fullNode: + case *FullNode: if it.trace { fmt.Printf("fullNode %x\n", hex) } @@ -338,12 +338,12 @@ func (it *Iterator) Next() (itemType StreamItem, hex1 []byte, aValue *accounts.A hex = append(hex, byte(i1)) var childGoDeep bool switch v := n.Children[i1].(type) { - case hashNode: + case HashNode: if accounts { return AHashStreamItem, hex, nil, v.hash, nil } return SHashStreamItem, hex, nil, v.hash, nil - case *duoNode: + case *DuoNode: childGoDeep = it.rl.Retain(hex) if !childGoDeep { if accounts { @@ -351,7 +351,7 @@ func (it *Iterator) Next() (itemType StreamItem, hex1 []byte, aValue *accounts.A } return SHashStreamItem, hex, nil, v.reference(), nil } - case *fullNode: + case *FullNode: childGoDeep = it.rl.Retain(hex) if !childGoDeep { if accounts { @@ -380,13 +380,13 @@ func (it *Iterator) Next() (itemType StreamItem, hex1 []byte, aValue *accounts.A hex = append(hex, byte(i1)) var childGoDeep bool switch v := n.Children[i1].(type) { - case hashNode: + case HashNode: it.top-- if accounts { return AHashStreamItem, hex, nil, v.hash, nil } return SHashStreamItem, hex, nil, v.hash, nil - case *duoNode: + case *DuoNode: childGoDeep = it.rl.Retain(hex) if !childGoDeep { it.top-- @@ -395,7 +395,7 @@ func (it *Iterator) Next() (itemType StreamItem, hex1 []byte, aValue *accounts.A } return SHashStreamItem, hex, nil, v.reference(), nil } - case *fullNode: + case *FullNode: childGoDeep = it.rl.Retain(hex) if !childGoDeep { it.top-- @@ -412,11 +412,11 @@ func (it *Iterator) Next() (itemType StreamItem, hex1 []byte, aValue *accounts.A it.lenStack[l] = len(hex) it.accountStack[l] = accounts } - case *accountNode: + case *AccountNode: if it.trace { fmt.Printf("accountNode %x\n", hex) } - if n.storage != nil { + if n.Storage != nil { binary.BigEndian.PutUint64(bytes8[:], n.Incarnation) // Add decompressed incarnation to the hex for i, b := range bytes8[:] { @@ -424,7 +424,7 @@ func (it *Iterator) Next() (itemType StreamItem, hex1 []byte, aValue *accounts.A bytes16[i*2+1] = b % 16 } it.hex = append(hex, bytes16[:]...) - it.nodeStack[l] = n.storage + it.nodeStack[l] = n.Storage it.iStack[l] = 0 it.goDeepStack[l] = true it.lenStack[l] = len(it.hex) @@ -433,7 +433,7 @@ func (it *Iterator) Next() (itemType StreamItem, hex1 []byte, aValue *accounts.A it.top-- } return AccountStreamItem, hex, &n.Account, nil, nil - case hashNode: + case HashNode: if it.trace { fmt.Printf("hashNode %x\n", hex) } @@ -772,7 +772,7 @@ func StreamHash(it *StreamMergeIterator, storagePrefixLen int, hb *HashBuilder, } if trace { tt := New(common.Hash{}) - tt.root = hb.root() + tt.RootNode = hb.root() filename := "root.txt" f, err1 := os.Create(filename) if err1 == nil { diff --git a/erigon-lib/trie/structural_test.go b/erigon-lib/trie/structural_test.go index cda3ecaccb6..f947681a2b7 100644 --- a/erigon-lib/trie/structural_test.go +++ b/erigon-lib/trie/structural_test.go @@ -164,7 +164,7 @@ func TestV2Resolution(t *testing.T) { t.Errorf("Could not execute step of structGen algorithm: %v", err) } tr1 := New(common.Hash{}) - tr1.root = hb.root() + tr1.RootNode = hb.root() builtHash := hb.rootHash() if trieHash != builtHash { t.Errorf("Expected hash %x, got %x", trieHash, builtHash) @@ -247,7 +247,7 @@ func TestEmbeddedStorage(t *testing.T) { builtHash := hb.rootHash() if trieHash != builtHash { fmt.Printf("Trie built: %s\n", hb.root().fstring("")) - fmt.Printf("Trie expected: %s\n", tr.root.fstring("")) + fmt.Printf("Trie expected: %s\n", tr.RootNode.fstring("")) t.Errorf("Expected hash %x, got %x", trieHash, builtHash) } fmt.Printf("groups: %d\n", len(groups)) diff --git a/erigon-lib/trie/sub_trie_loader.go b/erigon-lib/trie/sub_trie_loader.go index 576c345e797..59964e2a205 100644 --- a/erigon-lib/trie/sub_trie_loader.go +++ b/erigon-lib/trie/sub_trie_loader.go @@ -28,7 +28,7 @@ var emptyHash [32]byte // sub-tree root hash would be queried type SubTries struct { Hashes []libcommon.Hash // Root hashes of the sub-tries - roots []node // Sub-tries + roots []Node // Sub-tries } type LoadFunc func(*SubTrieLoader, *RetainList, [][]byte, []int) (SubTries, error) diff --git a/erigon-lib/trie/trie.go b/erigon-lib/trie/trie.go index 5fb5c9e7dd9..abbf1d44b4f 100644 --- a/erigon-lib/trie/trie.go +++ b/erigon-lib/trie/trie.go @@ -23,11 +23,13 @@ package trie import ( "bytes" "encoding/binary" + "errors" "fmt" + "reflect" libcommon "github.com/erigontech/erigon-lib/common" - "github.com/erigontech/erigon-lib/crypto" + "github.com/erigontech/erigon-lib/crypto" "github.com/erigontech/erigon-lib/types/accounts" ) @@ -48,10 +50,11 @@ var ( // Deprecated // use package turbo/trie type Trie struct { - root node + RootNode Node valueNodesRLPEncoded bool newHasherFunc func() *hasher + strictHash bool // if true, the trie will panic on a hash access } // New creates a trie with an existing root node from db. @@ -67,11 +70,211 @@ func New(root libcommon.Hash) *Trie { newHasherFunc: func() *hasher { return newHasher( /*valueNodesRlpEncoded = */ false) }, } if (root != libcommon.Hash{}) && root != EmptyRoot { - trie.root = hashNode{hash: root[:]} + trie.RootNode = &HashNode{hash: root[:]} + } + return trie +} + +func NewInMemoryTrie(root Node) *Trie { + trie := &Trie{ + newHasherFunc: func() *hasher { return newHasher( /*valueNodesRlpEncoded = */ false) }, + RootNode: root, + } + return trie +} + +func NewInMemoryTrieRLPEncoded(root Node) *Trie { + trie := &Trie{ + newHasherFunc: func() *hasher { return newHasher( /*valueNodesRlpEncoded = */ true) }, + RootNode: root, + valueNodesRLPEncoded: true, } return trie } +// this will merge node2 into node1, returns a boolean mergeNecessary, if it was necessary to replace a child. +// If not, then the two full nodes are the same so no replacement was necessary +// This function also performs certain sanity checks which can result in an error if they fail +func merge2FullNodes(node1, node2 *FullNode) (bool, error) { + furtherMergingNeeded := false + for i := 0; i < len(node1.Children); i++ { + // either both children are hashnodes, or only one of them is, or none of them is. + // if both of the two children (of trie1 and trie2) at a certain index are not hashnodes + // they must be the same type (e.g. both a FullNode, or both a ShortNode, or both nil) . If this is true for all children then no merge takes place at this level. + child1 := node1.Children[i] + child2 := node2.Children[i] + if hashNode1, ok1 := child1.(*HashNode); ok1 { // child1 is a hashnode + if hashNode2, ok2 := child2.(*HashNode); ok2 { //child2 is a hashnode + // both are hashnodes + if !bytes.Equal(hashNode1.hash, hashNode2.hash) { // sanity check + return false, fmt.Errorf("children hashnodes have different hashes: hash1(%x)!=hash2(%x)", hashNode1.hash, hashNode2.hash) + } + } else if child2 == nil { + return false, fmt.Errorf("child of tr2 should not be nil, because child of tr1 is a hashnode") + } else { // child2 is not a hashnode, in this case replace the hashnode in tree 1 by child2 which has the expanded node type + node1.Children[i] = child2 + } + } else if child1 == nil { + if child2 != nil { + // sanity check + return false, fmt.Errorf("child of first node is nil , but corresponding child of second node is non-nil") + } + } else { // child1 is not nil and not a hashnode + if _, ok2 := child2.(*HashNode); !ok2 { // if child2 is not hashnode, now they are expected to have the same type , if child2 is a hashnode then no changes are necessary to node1 + if reflect.TypeOf(child1) != reflect.TypeOf(child2) { // sanity check + return false, fmt.Errorf("children have different types: %T != %T", child1, child2) + } else { // further merging will be needed at the next level + furtherMergingNeeded = true + } + } + } + } + return furtherMergingNeeded, nil +} + +func merge2ShortNodes(node1, node2 *ShortNode) (bool, error) { + furtherMergingNeeded := false + if !bytes.Equal(node1.Key, node2.Key) { // sanity check + return false, fmt.Errorf("mismatch in the short node keys node1.Key(%x)!=node2.Key(%x)", node1.Key, node2.Key) + } + if hashNode1, ok1 := node1.Val.(*HashNode); ok1 { // node1.Val is a HashNode + if hashNode2, ok2 := node2.Val.(*HashNode); ok2 { // node2.Val is a HashNode + // both are hashnodes + if !bytes.Equal(hashNode1.hash, hashNode2.hash) { // sanity check + return false, fmt.Errorf("hashnodes have different hashes: hash1(%x) != hash2(%x)", hashNode1.hash, hashNode2.hash) + } + } else if node2.Val == nil { + return false, fmt.Errorf("node2.Val should not be nil, because node1.Val is a hashnode") + } else { // in this case node2.Val is not a HashNode, while node1.Val is a hash node, so replace node1.Val by node2.Val, and the merging is complete + node1.Val = node2.Val + } + } else { // node1.Val is not a hashnode + // if node2.Val is not a hashnode, node2.Val is expected to have the same type as node1.Val, otherwise if it is a hashnode no action is necessary (just ignore the hashnode) + if _, ok2 := node2.Val.(*HashNode); !ok2 { + if reflect.TypeOf(node1.Val) != reflect.TypeOf(node2.Val) { // sanity check + return false, fmt.Errorf("node1.Val and node2.Val have different types: %T != %T ", node1.Val, node2.Val) + } else { + furtherMergingNeeded = true + } + } + } + return furtherMergingNeeded, nil +} + +func merge2AccountNodes(node1, node2 *AccountNode) (furtherMergingNeeded bool) { + storage1 := node1.Storage + storage2 := node2.Storage + if storage1 == nil || storage2 == nil { // in this case do nothing, we can use the storage tree of node 1 + return false + } + _, isHashNode1 := storage1.(*HashNode) // check if storage1 is a hashnode + _, isHashNode2 := storage2.(*HashNode) // check if storage2 is a hashnode + if isHashNode1 && !isHashNode2 { // node2 has the expanded storage trie, so use that instead of the hashnode + node1.Storage = storage2 + return false + } + + if !isHashNode1 && !isHashNode2 { // the 2 storage tries need to be merged + return true + } + return false +} + +func merge2Tries(tr1 *Trie, tr2 *Trie) (*Trie, error) { + // starting from the roots merge each level + rootNode1 := tr1.RootNode + rootNode2 := tr2.RootNode + mergeComplete := false + + for !mergeComplete { + switch node1 := (rootNode1).(type) { + case nil: + // sanity checks might be good later on + return nil, nil + case *ShortNode: + node2, ok := rootNode2.(*ShortNode) + if !ok { + return nil, fmt.Errorf("expected *trie.ShortNode in trie 2, but got %T", rootNode2) + } + furtherMergingNeeded, err := merge2ShortNodes(node1, node2) + if err != nil { + return nil, err + } + if furtherMergingNeeded { + rootNode1 = node1.Val + rootNode2 = node2.Val + } else { + mergeComplete = true + } + case *FullNode: + node2, ok := rootNode2.(*FullNode) + if !ok { + return nil, fmt.Errorf("expected *trie.FullNode in trie 2, but got %T", rootNode2) + } + furthedMergingNeeded, err := merge2FullNodes(node1, node2) + if err != nil { + return nil, err + } + if furthedMergingNeeded { // find the next nodes to merge + nextRootsFound := false + for i := 0; i < len(node1.Children); i++ { // it is guaranteed that we will find a non-nil, non-hashnode + childNode1 := node1.Children[i] + childNode2 := node2.Children[i] + if _, isHashNode := childNode2.(*HashNode); childNode2 != nil && !isHashNode { + // update rootNode1, and rootNode2 to merge at the next level at the next iteration + rootNode1 = childNode1 + rootNode2 = childNode2 + nextRootsFound = true + break + } + } + if !nextRootsFound { + return nil, errors.New("could not find next node pair to merge") + } + } else { + mergeComplete = true + } + case *HashNode: + return tr2, nil + case ValueNode: + return tr1, nil + case *AccountNode: + node2, ok := rootNode2.(*AccountNode) + if !ok { + return nil, fmt.Errorf("expected *trie.AccountNode in trie 2, but got %T", rootNode2) + } + furthedMergingNeeded := merge2AccountNodes(node1, node2) + if !furthedMergingNeeded { + return tr1, nil + } else { + // need to merge storage trees + rootNode1 = node1.Storage + rootNode2 = node2.Storage + } + + } + } + return tr1, nil +} +func MergeTries(tries []*Trie) (*Trie, error) { + if len(tries) == 0 { + return nil, nil + } + + if len(tries) == 1 { + return tries[0], nil + } + + resultingTrie := tries[0] + for i := 1; i < len(tries); i++ { + resultingTrie, err := merge2Tries(resultingTrie, tries[i]) + if err != nil { + return resultingTrie, err + } + } + return resultingTrie, nil +} + // NewTestRLPTrie treats all the data provided to `Update` function as rlp-encoded. // it is usually used for testing purposes. func NewTestRLPTrie(root libcommon.Hash) *Trie { @@ -80,38 +283,42 @@ func NewTestRLPTrie(root libcommon.Hash) *Trie { newHasherFunc: func() *hasher { return newHasher( /*valueNodesRlpEncoded = */ true) }, } if (root != libcommon.Hash{}) && root != EmptyRoot { - trie.root = hashNode{hash: root[:]} + trie.RootNode = &HashNode{hash: root[:]} } return trie } +func (t *Trie) SetStrictHash(strict bool) { + t.strictHash = strict +} + // Get returns the value for key stored in the trie. func (t *Trie) Get(key []byte) (value []byte, gotValue bool) { - if t.root == nil { + if t.RootNode == nil { return nil, true } hex := keybytesToHex(key) - return t.get(t.root, hex, 0) + return t.get(t.RootNode, hex, 0) } func (t *Trie) FindPath(key []byte) (value []byte, parents [][]byte, gotValue bool) { - if t.root == nil { + if t.RootNode == nil { return nil, nil, true } hex := keybytesToHex(key) - return t.getPath(t.root, nil, hex, 0) + return t.getPath(t.RootNode, nil, hex, 0) } func (t *Trie) GetAccount(key []byte) (value *accounts.Account, gotValue bool) { - if t.root == nil { + if t.RootNode == nil { return nil, true } hex := keybytesToHex(key) - accNode, gotValue := t.getAccount(t.root, hex, 0) + accNode, gotValue := t.getAccount(t.RootNode, hex, 0) if accNode != nil { var value accounts.Account value.Copy(&accNode.Account) @@ -121,57 +328,57 @@ func (t *Trie) GetAccount(key []byte) (value *accounts.Account, gotValue bool) { } func (t *Trie) GetAccountCode(key []byte) (value []byte, gotValue bool) { - if t.root == nil { + if t.RootNode == nil { return nil, false } hex := keybytesToHex(key) - accNode, gotValue := t.getAccount(t.root, hex, 0) + accNode, gotValue := t.getAccount(t.RootNode, hex, 0) if accNode != nil { if bytes.Equal(accNode.Account.CodeHash[:], EmptyCodeHash[:]) { return nil, gotValue } - if accNode.code == nil { + if accNode.Code == nil { return nil, false } - return accNode.code, gotValue + return accNode.Code, gotValue } return nil, gotValue } func (t *Trie) GetAccountCodeSize(key []byte) (value int, gotValue bool) { - if t.root == nil { + if t.RootNode == nil { return 0, false } hex := keybytesToHex(key) - accNode, gotValue := t.getAccount(t.root, hex, 0) + accNode, gotValue := t.getAccount(t.RootNode, hex, 0) if accNode != nil { if bytes.Equal(accNode.Account.CodeHash[:], EmptyCodeHash[:]) { return 0, gotValue } - if accNode.codeSize == codeSizeUncached { + if accNode.CodeSize == codeSizeUncached { return 0, false } - return accNode.codeSize, gotValue + return accNode.CodeSize, gotValue } return 0, gotValue } -func (t *Trie) getAccount(origNode node, key []byte, pos int) (value *accountNode, gotValue bool) { +func (t *Trie) getAccount(origNode Node, key []byte, pos int) (value *AccountNode, gotValue bool) { switch n := (origNode).(type) { case nil: return nil, true - case *shortNode: + case *ShortNode: matchlen := prefixLen(key[pos:], n.Key) if matchlen == len(n.Key) { - if v, ok := n.Val.(*accountNode); ok { + if v, ok := n.Val.(*AccountNode); ok { return v, true } else { return t.getAccount(n.Val, key, pos+matchlen) @@ -179,7 +386,7 @@ func (t *Trie) getAccount(origNode node, key []byte, pos int) (value *accountNod } else { return nil, true } - case *duoNode: + case *DuoNode: i1, i2 := n.childrenIdx() switch key[pos] { case i1: @@ -189,28 +396,28 @@ func (t *Trie) getAccount(origNode node, key []byte, pos int) (value *accountNod default: return nil, true } - case *fullNode: + case *FullNode: child := n.Children[key[pos]] return t.getAccount(child, key, pos+1) - case hashNode: + case *HashNode: return nil, false - case *accountNode: + case *AccountNode: return n, true default: panic(fmt.Sprintf("%T: invalid node: %v", origNode, origNode)) } } -func (t *Trie) get(origNode node, key []byte, pos int) (value []byte, gotValue bool) { +func (t *Trie) get(origNode Node, key []byte, pos int) (value []byte, gotValue bool) { switch n := (origNode).(type) { case nil: return nil, true - case valueNode: + case ValueNode: return n, true - case *accountNode: - return t.get(n.storage, key, pos) - case *shortNode: + case *AccountNode: + return t.get(n.Storage, key, pos) + case *ShortNode: matchlen := prefixLen(key[pos:], n.Key) if matchlen == len(n.Key) || n.Key[matchlen] == 16 { value, gotValue = t.get(n.Val, key, pos+matchlen) @@ -218,7 +425,7 @@ func (t *Trie) get(origNode node, key []byte, pos int) (value []byte, gotValue b value, gotValue = nil, true } return - case *duoNode: + case *DuoNode: i1, i2 := n.childrenIdx() switch key[pos] { case i1: @@ -229,13 +436,13 @@ func (t *Trie) get(origNode node, key []byte, pos int) (value []byte, gotValue b value, gotValue = nil, true } return - case *fullNode: + case *FullNode: child := n.Children[key[pos]] if child == nil { return nil, true } return t.get(child, key, pos+1) - case hashNode: + case *HashNode: return n.hash, false default: @@ -243,15 +450,15 @@ func (t *Trie) get(origNode node, key []byte, pos int) (value []byte, gotValue b } } -func (t *Trie) getPath(origNode node, parents [][]byte, key []byte, pos int) ([]byte, [][]byte, bool) { +func (t *Trie) getPath(origNode Node, parents [][]byte, key []byte, pos int) ([]byte, [][]byte, bool) { switch n := (origNode).(type) { case nil: return nil, parents, true - case valueNode: + case ValueNode: return n, parents, true - case *accountNode: - return t.getPath(n.storage, append(parents, n.reference()), key, pos) - case *shortNode: + case *AccountNode: + return t.getPath(n.Storage, append(parents, n.reference()), key, pos) + case *ShortNode: matchlen := prefixLen(key[pos:], n.Key) if matchlen == len(n.Key) || n.Key[matchlen] == 16 { return t.getPath(n.Val, append(parents, n.reference()), key, pos+matchlen) @@ -259,7 +466,7 @@ func (t *Trie) getPath(origNode node, parents [][]byte, key []byte, pos int) ([] return nil, parents, true } - case *duoNode: + case *DuoNode: i1, i2 := n.childrenIdx() switch key[pos] { case i1: @@ -269,13 +476,13 @@ func (t *Trie) getPath(origNode node, parents [][]byte, key []byte, pos int) ([] default: return nil, parents, true } - case *fullNode: + case *FullNode: child := n.Children[key[pos]] if child == nil { return nil, parents, true } return t.getPath(child, append(parents, n.reference()), key, pos+1) - case hashNode: + case *HashNode: return n.hash, parents, false default: @@ -293,12 +500,12 @@ func (t *Trie) getPath(origNode node, parents [][]byte, key []byte, pos int) ([] func (t *Trie) Update(key, value []byte) { hex := keybytesToHex(key) - newnode := valueNode(value) + newnode := ValueNode(value) - if t.root == nil { - t.root = NewShortNode(hex, newnode) + if t.RootNode == nil { + t.RootNode = NewShortNode(hex, newnode) } else { - _, t.root = t.insert(t.root, hex, valueNode(value)) + _, t.RootNode = t.insert(t.RootNode, hex, ValueNode(value)) } } @@ -309,29 +516,29 @@ func (t *Trie) UpdateAccount(key []byte, acc *accounts.Account) { hex := keybytesToHex(key) - var newnode *accountNode + var newnode *AccountNode if value.Root == EmptyRoot || value.Root == (libcommon.Hash{}) { - newnode = &accountNode{*value, nil, true, nil, codeSizeUncached} + newnode = &AccountNode{*value, nil, true, nil, codeSizeUncached} } else { - newnode = &accountNode{*value, hashNode{hash: value.Root[:]}, true, nil, codeSizeUncached} + newnode = &AccountNode{*value, HashNode{hash: value.Root[:]}, true, nil, codeSizeUncached} } - if t.root == nil { - t.root = NewShortNode(hex, newnode) + if t.RootNode == nil { + t.RootNode = NewShortNode(hex, newnode) } else { - _, t.root = t.insert(t.root, hex, newnode) + _, t.RootNode = t.insert(t.RootNode, hex, newnode) } } // UpdateAccountCode attaches the code node to an account at specified key -func (t *Trie) UpdateAccountCode(key []byte, code codeNode) error { - if t.root == nil { +func (t *Trie) UpdateAccountCode(key []byte, code CodeNode) error { + if t.RootNode == nil { return nil } hex := keybytesToHex(key) - accNode, gotValue := t.getAccount(t.root, hex, 0) + accNode, gotValue := t.getAccount(t.RootNode, hex, 0) if accNode == nil || !gotValue { return fmt.Errorf("account not found with key: %x", key) } @@ -341,31 +548,31 @@ func (t *Trie) UpdateAccountCode(key []byte, code codeNode) error { return fmt.Errorf("inserted code mismatch account hash (acc.CodeHash=%x codeHash=%x)", accNode.CodeHash[:], actualCodeHash) } - accNode.code = code - accNode.codeSize = len(code) + accNode.Code = code + accNode.CodeSize = len(code) // t.insert will call the observer methods itself - _, t.root = t.insert(t.root, hex, accNode) + _, t.RootNode = t.insert(t.RootNode, hex, accNode) return nil } // UpdateAccountCodeSize attaches the code size to the account func (t *Trie) UpdateAccountCodeSize(key []byte, codeSize int) error { - if t.root == nil { + if t.RootNode == nil { return nil } hex := keybytesToHex(key) - accNode, gotValue := t.getAccount(t.root, hex, 0) + accNode, gotValue := t.getAccount(t.RootNode, hex, 0) if accNode == nil || !gotValue { return fmt.Errorf("account not found with key: %x", key) } - accNode.codeSize = codeSize + accNode.CodeSize = codeSize // t.insert will call the observer methods itself - _, t.root = t.insert(t.root, hex, accNode) + _, t.RootNode = t.insert(t.RootNode, hex, accNode) return nil } @@ -410,15 +617,15 @@ func (t *Trie) NeedLoadCode(addrHash libcommon.Hash, codeHash libcommon.Hash, by // It also create list of `hooks`, the paths in the trie (in nibbles) where the loaded // sub-tries need to be inserted. func (t *Trie) FindSubTriesToLoad(rl RetainDecider) (prefixes [][]byte, fixedbits []int, hooks [][]byte) { - return findSubTriesToLoad(t.root, nil, nil, rl, nil, 0, nil, nil, nil) + return findSubTriesToLoad(t.RootNode, nil, nil, rl, nil, 0, nil, nil, nil) } var bytes8 [8]byte var bytes16 [16]byte -func findSubTriesToLoad(nd node, nibblePath []byte, hook []byte, rl RetainDecider, dbPrefix []byte, bits int, prefixes [][]byte, fixedbits []int, hooks [][]byte) (newPrefixes [][]byte, newFixedBits []int, newHooks [][]byte) { +func findSubTriesToLoad(nd Node, nibblePath []byte, hook []byte, rl RetainDecider, dbPrefix []byte, bits int, prefixes [][]byte, fixedbits []int, hooks [][]byte) (newPrefixes [][]byte, newFixedBits []int, newHooks [][]byte) { switch n := nd.(type) { - case *shortNode: + case *ShortNode: nKey := n.Key if nKey[len(nKey)-1] == 16 { nKey = nKey[:len(nKey)-1] @@ -438,7 +645,7 @@ func findSubTriesToLoad(nd node, nibblePath []byte, hook []byte, rl RetainDecide bits += 4 } return findSubTriesToLoad(n.Val, nibblePath, hook, rl, dbPrefix, bits, prefixes, fixedbits, hooks) - case *duoNode: + case *DuoNode: i1, i2 := n.childrenIdx() newPrefixes = prefixes newFixedBits = fixedbits @@ -470,7 +677,7 @@ func findSubTriesToLoad(nd node, nibblePath []byte, hook []byte, rl RetainDecide newPrefixes, newFixedBits, newHooks = findSubTriesToLoad(n.child2, newNibblePath, newHook, rl, newDbPrefix, bits+4, newPrefixes, newFixedBits, newHooks) } return newPrefixes, newFixedBits, newHooks - case *fullNode: + case *FullNode: newPrefixes = prefixes newFixedBits = fixedbits newHooks = hooks @@ -494,8 +701,8 @@ func findSubTriesToLoad(nd node, nibblePath []byte, hook []byte, rl RetainDecide } } return newPrefixes, newFixedBits, newHooks - case *accountNode: - if n.storage == nil { + case *AccountNode: + if n.Storage == nil { return prefixes, fixedbits, hooks } binary.BigEndian.PutUint64(bytes8[:], n.Incarnation) @@ -510,10 +717,10 @@ func findSubTriesToLoad(nd node, nibblePath []byte, hook []byte, rl RetainDecide newFixedBits = fixedbits newHooks = hooks if rl.Retain(nibblePath) { - newPrefixes, newFixedBits, newHooks = findSubTriesToLoad(n.storage, nibblePath, hook, rl, dbPrefix, bits+64, prefixes, fixedbits, hooks) + newPrefixes, newFixedBits, newHooks = findSubTriesToLoad(n.Storage, nibblePath, hook, rl, dbPrefix, bits+64, prefixes, fixedbits, hooks) } return newPrefixes, newFixedBits, newHooks - case hashNode: + case *HashNode: newPrefixes = append(prefixes, libcommon.Copy(dbPrefix)) newFixedBits = append(fixedbits, bits) newHooks = append(hooks, libcommon.Copy(hook)) @@ -524,14 +731,14 @@ func findSubTriesToLoad(nd node, nibblePath []byte, hook []byte, rl RetainDecide // can pass incarnation=0 if start from root, method internally will // put incarnation from accountNode when pass it by traverse -func (t *Trie) insert(origNode node, key []byte, value node) (updated bool, newNode node) { +func (t *Trie) insert(origNode Node, key []byte, value Node) (updated bool, newNode Node) { return t.insertRecursive(origNode, key, 0, value) } -func (t *Trie) insertRecursive(origNode node, key []byte, pos int, value node) (updated bool, newNode node) { +func (t *Trie) insertRecursive(origNode Node, key []byte, pos int, value Node) (updated bool, newNode Node) { if len(key) == pos { - origN, origNok := origNode.(valueNode) - vn, vnok := value.(valueNode) + origN, origNok := origNode.(ValueNode) + vn, vnok := value.(ValueNode) if origNok && vnok { updated = !bytes.Equal(origN, vn) if updated { @@ -541,19 +748,19 @@ func (t *Trie) insertRecursive(origNode node, key []byte, pos int, value node) ( } return } - origAccN, origNok := origNode.(*accountNode) - vAccN, vnok := value.(*accountNode) + origAccN, origNok := origNode.(*AccountNode) + vAccN, vnok := value.(*AccountNode) if origNok && vnok { updated = !origAccN.Equals(&vAccN.Account) if updated { if !bytes.Equal(origAccN.CodeHash[:], vAccN.CodeHash[:]) { - origAccN.code = nil - } else if vAccN.code != nil { - origAccN.code = vAccN.code + origAccN.Code = nil + } else if vAccN.Code != nil { + origAccN.Code = vAccN.Code } origAccN.Account.Copy(&vAccN.Account) - origAccN.codeSize = vAccN.codeSize - origAccN.rootCorrect = false + origAccN.CodeSize = vAccN.CodeSize + origAccN.RootCorrect = false } newNode = origAccN return @@ -565,18 +772,18 @@ func (t *Trie) insertRecursive(origNode node, key []byte, pos int, value node) ( } } - var nn node + var nn Node switch n := origNode.(type) { case nil: return true, NewShortNode(libcommon.Copy(key[pos:]), value) - case *accountNode: - updated, nn = t.insertRecursive(n.storage, key, pos, value) + case *AccountNode: + updated, nn = t.insertRecursive(n.Storage, key, pos, value) if updated { - n.storage = nn - n.rootCorrect = false + n.Storage = nn + n.RootCorrect = false } return updated, n - case *shortNode: + case *ShortNode: matchlen := prefixLen(key[pos:], n.Key) // If the whole key matches, keep this short node as is // and only update the value. @@ -589,19 +796,19 @@ func (t *Trie) insertRecursive(origNode node, key []byte, pos int, value node) ( newNode = n } else { // Otherwise branch out at the index where they differ. - var c1 node + var c1 Node if len(n.Key) == matchlen+1 { c1 = n.Val } else { c1 = NewShortNode(libcommon.Copy(n.Key[matchlen+1:]), n.Val) } - var c2 node + var c2 Node if len(key) == pos+matchlen+1 { c2 = value } else { c2 = NewShortNode(libcommon.Copy(key[pos+matchlen+1:]), value) } - branch := &duoNode{} + branch := &DuoNode{} if n.Key[matchlen] < key[pos+matchlen] { branch.child1 = c1 branch.child2 = c2 @@ -625,7 +832,7 @@ func (t *Trie) insertRecursive(origNode node, key []byte, pos int, value node) ( } return - case *duoNode: + case *DuoNode: i1, i2 := n.childrenIdx() switch key[pos] { case i1: @@ -643,13 +850,13 @@ func (t *Trie) insertRecursive(origNode node, key []byte, pos int, value node) ( } newNode = n default: - var child node + var child Node if len(key) == pos+1 { child = value } else { child = NewShortNode(libcommon.Copy(key[pos+1:]), value) } - newnode := &fullNode{} + newnode := &FullNode{} newnode.Children[i1] = n.child1 newnode.Children[i2] = n.child2 newnode.Children[key[pos]] = child @@ -659,7 +866,7 @@ func (t *Trie) insertRecursive(origNode node, key []byte, pos int, value node) ( } return - case *fullNode: + case *FullNode: child := n.Children[key[pos]] if child == nil { if len(key) == pos+1 { @@ -684,9 +891,9 @@ func (t *Trie) insertRecursive(origNode node, key []byte, pos int, value node) ( } // non-recursive version of get and returns: node and parent node -func (t *Trie) getNode(hex []byte, doTouch bool) (node, node, bool, uint64) { - var nd = t.root - var parent node +func (t *Trie) getNode(hex []byte, doTouch bool) (Node, Node, bool, uint64) { + var nd = t.RootNode + var parent Node pos := 0 var account bool var incarnation uint64 @@ -694,19 +901,19 @@ func (t *Trie) getNode(hex []byte, doTouch bool) (node, node, bool, uint64) { switch n := nd.(type) { case nil: return nil, nil, false, incarnation - case *shortNode: + case *ShortNode: matchlen := prefixLen(hex[pos:], n.Key) if matchlen == len(n.Key) || n.Key[matchlen] == 16 { parent = n nd = n.Val pos += matchlen - if _, ok := nd.(*accountNode); ok { + if _, ok := nd.(*AccountNode); ok { account = true } } else { return nil, nil, false, incarnation } - case *duoNode: + case *DuoNode: i1, i2 := n.childrenIdx() switch hex[pos] { case i1: @@ -720,7 +927,7 @@ func (t *Trie) getNode(hex []byte, doTouch bool) (node, node, bool, uint64) { default: return nil, nil, false, incarnation } - case *fullNode: + case *FullNode: child := n.Children[hex[pos]] if child == nil { return nil, nil, false, incarnation @@ -728,14 +935,14 @@ func (t *Trie) getNode(hex []byte, doTouch bool) (node, node, bool, uint64) { parent = n nd = child pos++ - case *accountNode: + case *AccountNode: parent = n - nd = n.storage + nd = n.Storage incarnation = n.Incarnation account = false - case valueNode: + case ValueNode: return nd, parent, true, incarnation - case hashNode: + case HashNode: return nd, parent, true, incarnation default: panic(fmt.Sprintf("Unknown node: %T", n)) @@ -758,15 +965,15 @@ func (t *Trie) HookSubTries(subTries SubTries, hooks [][]byte) error { return nil } -func (t *Trie) hook(hex []byte, n node, hash []byte) error { +func (t *Trie) hook(hex []byte, n Node, hash []byte) error { nd, parent, ok, incarnation := t.getNode(hex, true) if !ok { return nil } - if _, ok := nd.(valueNode); ok { + if _, ok := nd.(ValueNode); ok { return nil } - if hn, ok := nd.(hashNode); ok { + if hn, ok := nd.(HashNode); ok { if !bytes.Equal(hn.hash, hash) { return fmt.Errorf("wrong hash when hooking, expected %s, sub-tree hash %x", hn, hash) } @@ -777,10 +984,10 @@ func (t *Trie) hook(hex []byte, n node, hash []byte) error { t.touchAll(n, hex, false, incarnation) switch p := parent.(type) { case nil: - t.root = n - case *shortNode: + t.RootNode = n + case *ShortNode: p.Val = n - case *duoNode: + case *DuoNode: i1, i2 := p.childrenIdx() switch hex[len(hex)-1] { case i1: @@ -788,19 +995,19 @@ func (t *Trie) hook(hex []byte, n node, hash []byte) error { case i2: p.child2 = n } - case *fullNode: + case *FullNode: idx := hex[len(hex)-1] p.Children[idx] = n - case *accountNode: - p.storage = n + case *AccountNode: + p.Storage = n } return nil } -func (t *Trie) touchAll(n node, hex []byte, del bool, incarnation uint64) { +func (t *Trie) touchAll(n Node, hex []byte, del bool, incarnation uint64) { switch n := n.(type) { - case *shortNode: - if _, ok := n.Val.(valueNode); !ok { + case *ShortNode: + if _, ok := n.Val.(ValueNode); !ok { // Don't need to compute prefix for a leaf h := n.Key // Remove terminator @@ -810,7 +1017,7 @@ func (t *Trie) touchAll(n node, hex []byte, del bool, incarnation uint64) { hexVal := concat(hex, h...) t.touchAll(n.Val, hexVal, del, incarnation) } - case *duoNode: + case *DuoNode: i1, i2 := n.childrenIdx() hex1 := make([]byte, len(hex)+1) copy(hex1, hex) @@ -820,15 +1027,15 @@ func (t *Trie) touchAll(n node, hex []byte, del bool, incarnation uint64) { hex2[len(hex)] = i2 t.touchAll(n.child1, hex1, del, incarnation) t.touchAll(n.child2, hex2, del, incarnation) - case *fullNode: + case *FullNode: for i, child := range n.Children { if child != nil { t.touchAll(child, concat(hex, byte(i)), del, incarnation) } } - case *accountNode: - if n.storage != nil { - t.touchAll(n.storage, hex, del, n.Incarnation) + case *AccountNode: + if n.Storage != nil { + t.touchAll(n.Storage, hex, del, n.Incarnation) } } } @@ -837,10 +1044,10 @@ func (t *Trie) touchAll(n node, hex []byte, del bool, incarnation uint64) { // DESCRIBED: docs/programmers_guide/guide.md#root func (t *Trie) Delete(key []byte) { hex := keybytesToHex(key) - _, t.root = t.delete(t.root, hex, false) + _, t.RootNode = t.delete(t.RootNode, hex, false) } -func (t *Trie) convertToShortNode(child node, pos uint) node { +func (t *Trie) convertToShortNode(child Node, pos uint) Node { if pos != 16 { // If the remaining entry is a short node, it replaces // n and its key gets the missing nibble tacked to the @@ -848,7 +1055,7 @@ func (t *Trie) convertToShortNode(child node, pos uint) node { // shortNode{..., shortNode{...}}. Since the entry // might not be loaded yet, resolve it just for this // check. - if short, ok := child.(*shortNode); ok { + if short, ok := child.(*ShortNode); ok { k := make([]byte, len(short.Key)+1) k[0] = byte(pos) copy(k[1:], short.Key) @@ -860,7 +1067,7 @@ func (t *Trie) convertToShortNode(child node, pos uint) node { return NewShortNode([]byte{byte(pos)}, child) } -func (t *Trie) delete(origNode node, key []byte, preserveAccountNode bool) (updated bool, newNode node) { +func (t *Trie) delete(origNode Node, key []byte, preserveAccountNode bool) (updated bool, newNode Node) { return t.deleteRecursive(origNode, key, 0, preserveAccountNode, 0) } @@ -870,10 +1077,10 @@ func (t *Trie) delete(origNode node, key []byte, preserveAccountNode bool) (upda // // can pass incarnation=0 if start from root, method internally will // put incarnation from accountNode when pass it by traverse -func (t *Trie) deleteRecursive(origNode node, key []byte, keyStart int, preserveAccountNode bool, incarnation uint64) (updated bool, newNode node) { - var nn node +func (t *Trie) deleteRecursive(origNode Node, key []byte, keyStart int, preserveAccountNode bool, incarnation uint64) (updated bool, newNode Node) { + var nn Node switch n := origNode.(type) { - case *shortNode: + case *ShortNode: matchlen := prefixLen(key[keyStart:], n.Key) if matchlen == min(len(n.Key), len(key[keyStart:])) || n.Key[matchlen] == 16 || key[keyStart+matchlen] == 16 { fullMatch := matchlen == len(key)-keyStart @@ -902,7 +1109,7 @@ func (t *Trie) deleteRecursive(origNode node, key []byte, keyStart int, preserve if nn == nil { newNode = nil } else { - if shortChild, ok := nn.(*shortNode); ok { + if shortChild, ok := nn.(*ShortNode); ok { // Deleting from the subtrie reduced it to another // short node. Merge the nodes to avoid creating a // shortNode{..., shortNode{...}}. Use concat (which @@ -924,7 +1131,7 @@ func (t *Trie) deleteRecursive(origNode node, key []byte, keyStart int, preserve } return - case *duoNode: + case *DuoNode: i1, i2 := n.childrenIdx() switch key[keyStart] { case i1: @@ -959,7 +1166,7 @@ func (t *Trie) deleteRecursive(origNode node, key []byte, keyStart int, preserve } return - case *fullNode: + case *FullNode: child := n.Children[key[keyStart]] updated, nn = t.deleteRecursive(child, key, keyStart+1, preserveAccountNode, incarnation) if !updated { @@ -994,7 +1201,7 @@ func (t *Trie) deleteRecursive(origNode node, key []byte, keyStart int, preserve if count == 1 { newNode = t.convertToShortNode(n.Children[pos1], uint(pos1)) } else if count == 2 { - duo := &duoNode{} + duo := &DuoNode{} if pos1 == int(key[keyStart]) { duo.child1 = nn } else { @@ -1015,36 +1222,36 @@ func (t *Trie) deleteRecursive(origNode node, key []byte, keyStart int, preserve } return - case valueNode: + case ValueNode: updated = true newNode = nil return - case *accountNode: + case *AccountNode: if keyStart >= len(key) || key[keyStart] == 16 { // Key terminates here h := key[:keyStart] if h[len(h)-1] == 16 { h = h[:len(h)-1] } - if n.storage != nil { + if n.Storage != nil { // Mark all the storage nodes as deleted - t.touchAll(n.storage, h, true, n.Incarnation) + t.touchAll(n.Storage, h, true, n.Incarnation) } if preserveAccountNode { - n.storage = nil - n.code = nil + n.Storage = nil + n.Code = nil n.Root = EmptyRoot - n.rootCorrect = true + n.RootCorrect = true return true, n } return true, nil } - updated, nn = t.deleteRecursive(n.storage, key, keyStart, preserveAccountNode, n.Incarnation) + updated, nn = t.deleteRecursive(n.Storage, key, keyStart, preserveAccountNode, n.Incarnation) if updated { - n.storage = nn - n.rootCorrect = false + n.Storage = nn + n.RootCorrect = false } newNode = n return @@ -1065,7 +1272,7 @@ func (t *Trie) deleteRecursive(origNode node, key []byte, keyStart int, preserve func (t *Trie) DeleteSubtree(keyPrefix []byte) { hexPrefix := keybytesToHex(keyPrefix) - _, t.root = t.delete(t.root, hexPrefix, true) + _, t.RootNode = t.delete(t.RootNode, hexPrefix, true) } @@ -1084,7 +1291,7 @@ func (t *Trie) Root() []byte { return t.Hash().Bytes() } // database and can be used even if the trie doesn't have one. // DESCRIBED: docs/programmers_guide/guide.md#root func (t *Trie) Hash() libcommon.Hash { - if t == nil || t.root == nil { + if t == nil || t.RootNode == nil { return EmptyRoot } @@ -1092,13 +1299,13 @@ func (t *Trie) Hash() libcommon.Hash { defer returnHasherToPool(h) var result libcommon.Hash - _, _ = h.hash(t.root, true, result[:]) + _, _ = h.hash(t.RootNode, true, result[:]) return result } func (t *Trie) Reset() { - resetRefs(t.root) + resetRefs(t.RootNode) } func (t *Trie) getHasher() *hasher { @@ -1112,20 +1319,20 @@ func (t *Trie) getHasher() *hasher { // First returned value is `true` if the node with the specified prefix is found. func (t *Trie) DeepHash(keyPrefix []byte) (bool, libcommon.Hash) { hexPrefix := keybytesToHex(keyPrefix) - accNode, gotValue := t.getAccount(t.root, hexPrefix, 0) + accNode, gotValue := t.getAccount(t.RootNode, hexPrefix, 0) if !gotValue { return false, libcommon.Hash{} } - if accNode.rootCorrect { + if accNode.RootCorrect { return true, accNode.Root } - if accNode.storage == nil { + if accNode.Storage == nil { accNode.Root = EmptyRoot - accNode.rootCorrect = true + accNode.RootCorrect = true } else { h := t.getHasher() defer returnHasherToPool(h) - h.hash(accNode.storage, true, accNode.Root[:]) + h.hash(accNode.Storage, true, accNode.Root[:]) } return true, accNode.Root } @@ -1140,14 +1347,14 @@ func (t *Trie) EvictNode(hex []byte) { if !ok { return } - if accNode, ok := parent.(*accountNode); isCode && ok { + if accNode, ok := parent.(*AccountNode); isCode && ok { // add special treatment to code nodes - accNode.code = nil + accNode.Code = nil return } switch nd.(type) { - case valueNode, hashNode: + case ValueNode, *HashNode: return default: // can work with other nodes type @@ -1159,16 +1366,16 @@ func (t *Trie) EvictNode(hex []byte) { return } copy(hn[:], nd.reference()) - hnode := hashNode{hash: hn[:]} + hnode := &HashNode{hash: hn[:]} t.notifyUnloadRecursive(hex, incarnation, nd) switch p := parent.(type) { case nil: - t.root = hnode - case *shortNode: + t.RootNode = hnode + case *ShortNode: p.Val = hnode - case *duoNode: + case *DuoNode: i1, i2 := p.childrenIdx() switch hex[len(hex)-1] { case i1: @@ -1176,41 +1383,41 @@ func (t *Trie) EvictNode(hex []byte) { case i2: p.child2 = hnode } - case *fullNode: + case *FullNode: idx := hex[len(hex)-1] p.Children[idx] = hnode - case *accountNode: - p.storage = hnode + case *AccountNode: + p.Storage = hnode } } -func (t *Trie) notifyUnloadRecursive(hex []byte, incarnation uint64, nd node) { +func (t *Trie) notifyUnloadRecursive(hex []byte, incarnation uint64, nd Node) { switch n := nd.(type) { - case *shortNode: + case *ShortNode: hex = append(hex, n.Key...) if hex[len(hex)-1] == 16 { hex = hex[:len(hex)-1] } t.notifyUnloadRecursive(hex, incarnation, n.Val) - case *accountNode: - if n.storage == nil { + case *AccountNode: + if n.Storage == nil { return } - if _, ok := n.storage.(hashNode); ok { + if _, ok := n.Storage.(*HashNode); ok { return } - t.notifyUnloadRecursive(hex, n.Incarnation, n.storage) - case *fullNode: + t.notifyUnloadRecursive(hex, n.Incarnation, n.Storage) + case *FullNode: for i := range n.Children { if n.Children[i] == nil { continue } - if _, ok := n.Children[i].(hashNode); ok { + if _, ok := n.Children[i].(*HashNode); ok { continue } t.notifyUnloadRecursive(append(hex, uint8(i)), incarnation, n.Children[i]) } - case *duoNode: + case *DuoNode: i1, i2 := n.childrenIdx() if n.child1 != nil { t.notifyUnloadRecursive(append(hex, i1), incarnation, n.child1) @@ -1224,9 +1431,9 @@ func (t *Trie) notifyUnloadRecursive(hex []byte, incarnation uint64, nd node) { } func (t *Trie) TrieSize() int { - return calcSubtreeSize(t.root) + return calcSubtreeSize(t.RootNode) } func (t *Trie) NumberOfAccounts() int { - return calcSubtreeNodes(t.root) + return calcSubtreeNodes(t.RootNode) } diff --git a/erigon-lib/trie/trie_from_witness.go b/erigon-lib/trie/trie_from_witness.go new file mode 100644 index 00000000000..0584cfd210b --- /dev/null +++ b/erigon-lib/trie/trie_from_witness.go @@ -0,0 +1,95 @@ +package trie + +import ( + "fmt" + + "github.com/holiman/uint256" + + "github.com/erigontech/erigon-lib/rlphacks" +) + +func BuildTrieFromWitness(witness *Witness, trace bool) (*Trie, error) { + hb := NewHashBuilder(false) + for _, operator := range witness.Operators { + switch op := operator.(type) { + case *OperatorLeafValue: + if trace { + fmt.Printf("LEAF ") + } + keyHex := op.Key + val := op.Value + if err := hb.leaf(len(op.Key), keyHex, rlphacks.RlpSerializableBytes(val)); err != nil { + return nil, err + } + case *OperatorExtension: + if trace { + fmt.Printf("EXTENSION ") + } + if err := hb.extension(op.Key); err != nil { + return nil, err + } + case *OperatorBranch: + if trace { + fmt.Printf("BRANCH ") + } + if err := hb.branch(uint16(op.Mask)); err != nil { + return nil, err + } + case *OperatorHash: + if trace { + fmt.Printf("HASH ") + } + if err := hb.hash(op.Hash[:]); err != nil { + return nil, err + } + case *OperatorCode: + if trace { + fmt.Printf("CODE ") + } + + if err := hb.code(op.Code); err != nil { + return nil, err + } + + case *OperatorLeafAccount: + if trace { + fmt.Printf("ACCOUNTLEAF(code=%v storage=%v) ", op.HasCode, op.HasStorage) + } + balance := uint256.NewInt(0) + balance.SetBytes(op.Balance.Bytes()) + nonce := op.Nonce + + // FIXME: probably not needed, fix hb.accountLeaf + fieldSet := uint32(3) + if op.HasCode && op.HasStorage { + fieldSet = 15 + } + + // Incarnation is always needed for a hashbuilder. + // but it is just our implementation detail needed for contract self-descruction support with our + // db structure. Stateless clients don't access the DB so we can just pass 0 here. + incarnation := uint64(0) + + if err := hb.accountLeaf(len(op.Key), op.Key, balance, nonce, incarnation, fieldSet, int(op.CodeSize)); err != nil { + return nil, err + } + case *OperatorEmptyRoot: + if trace { + fmt.Printf("EMPTYROOT ") + } + hb.emptyRoot() + default: + return nil, fmt.Errorf("unknown operand type: %T", operator) + } + } + if trace { + fmt.Printf("\n") + } + if !hb.hasRoot() { + return New(EmptyRoot), nil + } + r := hb.root() + tr := New(hb.rootHash()) + tr.RootNode = r + return tr, nil +} diff --git a/erigon-lib/trie/trie_root.go b/erigon-lib/trie/trie_root.go index b1694b2bbcc..59cb975c8b4 100644 --- a/erigon-lib/trie/trie_root.go +++ b/erigon-lib/trie/trie_root.go @@ -140,7 +140,7 @@ type RootHashAggregator struct { accData GenStructStepAccountData // Used to construct an Account proof while calculating the tree root. - proofRetainer *ProofRetainer + proofRetainer ProofRetainer cutoff bool } @@ -176,7 +176,7 @@ func NewFlatDBTrieLoader(logPrefix string, rd RetainDeciderWithMarker, hc HashCo } func (l *FlatDBTrieLoader) SetProofRetainer(pr *ProofRetainer) { - l.receiver.proofRetainer = pr + l.receiver.proofRetainer = *pr } // CalcTrieRoot algo: diff --git a/erigon-lib/trie/trie_test.go b/erigon-lib/trie/trie_test.go index 48ecfdebb76..ba7f649b7ba 100644 --- a/erigon-lib/trie/trie_test.go +++ b/erigon-lib/trie/trie_test.go @@ -22,6 +22,7 @@ package trie import ( "bytes" "encoding/binary" + "encoding/hex" "fmt" "math/big" "math/rand" @@ -398,7 +399,7 @@ func TestCodeNodeGetHashedAccount(t *testing.T) { hex := keybytesToHex(crypto.Keccak256(address[:])) - _, trie.root = trie.insert(trie.root, hex, hashNode{hash: fakeAccountHash[:]}) + _, trie.RootNode = trie.insert(trie.RootNode, hex, &HashNode{hash: fakeAccountHash[:]}) value, gotValue := trie.GetAccountCode(crypto.Keccak256(address[:])) assert.False(t, gotValue, "should indicate that account exists but hashed") @@ -635,3 +636,98 @@ func TestNextSubtreeHex(t *testing.T) { assert.Equal(tc.expect, res, "%s, %s", tc.prev, tc.next) } } + +func TestShortNode(t *testing.T) { + extensionKeyStr := "0b00000d020809020b080f0d0a090a0a0705070f050d0002090f0d0d0e07080e0402070e010c08030d0e0409060e040b0e0406060b0c080b0503010005" + extensionKeyNibbles := make([]byte, len(extensionKeyStr)/2+1) + for i := 0; i < len(extensionKeyStr)/2; i++ { + c, err := hex.DecodeString(extensionKeyStr[2*i : 2*i+2]) + if err != nil { + t.Errorf("parsing error") + } + extensionKeyNibbles[i] = c[0] + } + extensionKeyNibbles[len(extensionKeyNibbles)-1] = 16 + + accRlpHex := "f84b08873f54314ab16fd0a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470" + accRlp, err := hex.DecodeString(accRlpHex) + if err != nil { + t.Fatalf("failed to decode rlp from hex") + } + + valNode := ValueNode(accRlp) + + shortNode := &ShortNode{Key: extensionKeyNibbles, Val: valNode} + trie := NewInMemoryTrieRLPEncoded(shortNode) + trie.valueNodesRLPEncoded = true + rootHash := trie.Root() + + expectedHashStr := "fa7297cfa8b2d445e356e9f752e23b018ae8717fdf117cbe4fcef1b16217d3c2" + expectedHashBytes, err := hex.DecodeString(expectedHashStr) + if err != nil { + t.Fatalf("unable to decode expected hash %v", err) + } + if !bytes.Equal(rootHash, expectedHashBytes) { + t.Fatalf("rootHash(%x) != expectedHash(%x)", rootHash, expectedHashBytes) + } +} + +//func TestIHCursorCanUseNextParent(t *testing.T) { +// db, assert := ethdb.NewMemDatabase(), require.New(t) +// defer db.Close() +// hash := fmt.Sprintf("%064d", 0) +// +// ih := AccTrie(nil, nil, nil, nil) +// +// ih.k[1], ih.v[1], ih.hasTree[1] = common.FromHex("00"), common.FromHex(hash+hash), 0b0000000000000110 +// ih.k[2], ih.v[2], ih.hasTree[2] = common.FromHex("0001"), common.FromHex(hash), 0b1000000000000000 +// ih.lvl = 2 +// ih.hashID[2] = 1 +// ih.hashID[1] = 0 +// assert.True(ih._nextSiblingOfParentInMem()) +// assert.Equal(ih.k[ih.lvl], common.FromHex("00")) +// +// ih.k[1], ih.v[1], ih.hasTree[1] = common.FromHex("00"), common.FromHex(hash+hash), 0b0000000000000110 +// ih.k[3], ih.v[3], ih.hasTree[3] = common.FromHex("000101"), common.FromHex(hash), 0b1000000000000000 +// ih.lvl = 3 +// ih.hashID[3] = 1 +// ih.hashID[1] = 0 +// assert.True(ih._nextSiblingOfParentInMem()) +// assert.Equal(ih.k[ih.lvl], common.FromHex("00")) +// +//} +// +//func _TestEmptyRoot(t *testing.T) { +// sc := shards.NewStateCache(32, 64*1024) +// +// sc.SetAccountHashesRead(common.FromHex("00"), 0b111, 0b111, 0b111, []libcommon.Hash{{}, {}, {}}) +// sc.SetAccountHashesRead(common.FromHex("01"), 0b111, 0b111, 0b111, []libcommon.Hash{{}, {}, {}}) +// sc.SetAccountHashesRead(common.FromHex("02"), 0b111, 0b111, 0b111, []libcommon.Hash{{}, {}, {}}) +// +// rl := NewRetainList(0) +// rl.AddHex(common.FromHex("01")) +// rl.AddHex(common.FromHex("0101")) +// canUse := func(prefix []byte) bool { return !rl.Retain(prefix) } +// i := 0 +// if err := sc.AccountTree([]byte{}, func(ihK []byte, h libcommon.Hash, hasTree, skipState bool) (toChild bool, err error) { +// i++ +// switch i { +// case 1: +// assert.Equal(t, common.FromHex("0001"), ihK) +// case 2: +// assert.Equal(t, common.FromHex("0100"), ihK) +// case 3: +// assert.Equal(t, common.FromHex("0102"), ihK) +// case 4: +// assert.Equal(t, common.FromHex("0202"), ihK) +// } +// if ok := canUse(ihK); ok { +// return false, nil +// } +// return hasTree, nil +// }, func(cur []byte) { +// panic(fmt.Errorf("key %x not found in cache", cur)) +// }); err != nil { +// t.Fatal(err) +// } +//} diff --git a/erigon-lib/trie/trie_witness.go b/erigon-lib/trie/trie_witness.go new file mode 100644 index 00000000000..59731d55ffa --- /dev/null +++ b/erigon-lib/trie/trie_witness.go @@ -0,0 +1,55 @@ +package trie + +import "errors" + +func (t *Trie) ExtractWitness(trace bool, rl RetainDecider) (*Witness, error) { + var rd RetainDecider + if rl != nil { + rd = rl + } + return extractWitnessFromRootNode(t.RootNode, trace, rd) +} + +func (t *Trie) ExtractWitnessForPrefix(prefix []byte, trace bool, rl RetainDecider) (*Witness, error) { + foundNode, _, found, _ := t.getNode(prefix, false) + if !found { + return nil, errors.New("no data found for given prefix") + } + return extractWitnessFromRootNode(foundNode, trace, rl) +} + +// ExtractWitnesses extracts witnesses for subtries starting from the specified root +// if retainDec param is nil it will make a witness for the full subtrie, +// if retainDec param is set to a RetainList instance, it will make a witness for only the accounts/storages that were actually touched; other paths will be hashed. +func ExtractWitnesses(subTries SubTries, trace bool, retainDec RetainDecider) ([]*Witness, error) { + var witnesses []*Witness + for _, root := range subTries.roots { + builder := NewWitnessBuilder(root, trace) + var limiter *MerklePathLimiter = nil + if retainDec != nil { + hr := newHasher(false) + defer returnHasherToPool(hr) + limiter = &MerklePathLimiter{retainDec, hr.hash} + } + if witness, err := builder.Build(limiter); err == nil { + witnesses = append(witnesses, witness) + } else { + return witnesses, err + } + } + return witnesses, nil +} + +// extractWitnessFromRootNode extracts witness for subtrie starting from the specified root +// if retainDec param is nil it will make a witness for the full subtrie, +// if retainDec param is set to a RetainList instance, it will make a witness for only the accounts/storages that were actually touched; other paths will be hashed. +func extractWitnessFromRootNode(root Node, trace bool, retainDec RetainDecider) (*Witness, error) { + builder := NewWitnessBuilder(root, trace) + var limiter *MerklePathLimiter = nil + if retainDec != nil { + hr := newHasher(false) + defer returnHasherToPool(hr) + limiter = &MerklePathLimiter{retainDec, hr.hash} + } + return builder.Build(limiter) +} diff --git a/erigon-lib/trie/witness.go b/erigon-lib/trie/witness.go new file mode 100644 index 00000000000..22005d9677d --- /dev/null +++ b/erigon-lib/trie/witness.go @@ -0,0 +1,238 @@ +package trie + +import ( + "bytes" + "errors" + "fmt" + "io" +) + +// WitnessStorage is an interface representing a single +type WitnessStorage interface { + GetWitnessesForBlock(uint64, uint32) ([]byte, error) +} + +// WitnessVersion represents the current version of the block witness +// in case of incompatible changes it should be updated and the code to migrate the +// old witness format should be present +const WitnessVersion = uint8(0) + +// WitnessHeader contains version information and maybe some future format bits +// the version is always the 1st bit. +type WitnessHeader struct { + Version uint8 +} + +func (h *WitnessHeader) WriteTo(out *OperatorMarshaller) error { + _, err := out.WithColumn(ColumnStructure).Write([]byte{h.Version}) + return err +} + +func (h *WitnessHeader) LoadFrom(input io.Reader) error { + version := make([]byte, 1) + if _, err := input.Read(version); err != nil { + return err + } + + h.Version = version[0] + return nil +} + +func defaultWitnessHeader() WitnessHeader { + return WitnessHeader{WitnessVersion} +} + +type Witness struct { + Header WitnessHeader + Operators []WitnessOperator +} + +func NewWitness(operands []WitnessOperator) *Witness { + return &Witness{ + Header: defaultWitnessHeader(), + Operators: operands, + } +} + +func (w *Witness) WriteInto(out io.Writer) (*BlockWitnessStats, error) { + statsCollector := NewOperatorMarshaller(out) + + if err := w.Header.WriteTo(statsCollector); err != nil { + return nil, err + } + + for _, op := range w.Operators { + if err := op.WriteTo(statsCollector); err != nil { + return nil, err + } + } + return statsCollector.GetStats(), nil +} + +func NewWitnessFromReader(input io.Reader, trace bool) (*Witness, error) { + var header WitnessHeader + if err := header.LoadFrom(input); err != nil { + return nil, err + } + + if header.Version != WitnessVersion { + return nil, fmt.Errorf("unexpected witness version: expected %d, got %d", WitnessVersion, header.Version) + } + + operatorLoader := NewOperatorUnmarshaller(input) + + opcode := make([]byte, 1) + var err error + operands := make([]WitnessOperator, 0) + for _, err = input.Read(opcode); ; _, err = input.Read(opcode) { + if errors.Is(err, io.EOF) { + break + } + if err != nil { + return nil, err + } + var op WitnessOperator + switch OperatorKindCode(opcode[0]) { + case OpHash: + op = &OperatorHash{} + case OpLeaf: + op = &OperatorLeafValue{} + case OpAccountLeaf: + op = &OperatorLeafAccount{} + case OpCode: + op = &OperatorCode{} + case OpBranch: + op = &OperatorBranch{} + case OpEmptyRoot: + op = &OperatorEmptyRoot{} + case OpExtension: + op = &OperatorExtension{} + case OpNewTrie: + /* end of the current trie, end the function */ + default: + return nil, fmt.Errorf("unexpected opcode while reading witness: %x", opcode[0]) + } + + if op == nil { + break + } + + err = op.LoadFrom(operatorLoader) + if err != nil { + return nil, err + } + + if trace { + fmt.Printf("read op %T -> %+v\n", op, op) + } + + operands = append(operands, op) + } + if trace { + fmt.Println("end of read ***** ") + } + if err != nil && !errors.Is(err, io.EOF) { + return nil, err + } + + return &Witness{Header: header, Operators: operands}, nil +} + +func (w *Witness) WriteDiff(w2 *Witness, output io.Writer) { + if w.Header.Version != w2.Header.Version { + fmt.Fprintf(output, "w1 header %d; w2 header %d\n", w.Header.Version, w2.Header.Version) + } + + if len(w.Operators) != len(w2.Operators) { + fmt.Fprintf(output, "w1 operands: %d; w2 operands: %d\n", len(w.Operators), len(w2.Operators)) + } + + length := len(w.Operators) + if len(w2.Operators) > length { + length = len(w2.Operators) + } + + for i := 0; i < length; i++ { + var op WitnessOperator + if i < len(w.Operators) { + op = w.Operators[i] + } + if i >= len(w2.Operators) { + fmt.Fprintf(output, "unexpected o1[%d] = %T %v; o2[%d] = nil\n", i, op, op, i) + continue + } + switch o1 := op.(type) { + case *OperatorBranch: + o2, ok := w2.Operators[i].(*OperatorBranch) + if !ok { + fmt.Fprintf(output, "o1[%d] = %T %+v; o2[%d] = %T %+v\n", i, o1, o1, i, o2, o2) + } + if o1.Mask != o2.Mask { + fmt.Fprintf(output, "o1[%d].Mask = %v; o2[%d].Mask = %v", i, o1.Mask, i, o2.Mask) + } + case *OperatorHash: + o2, ok := w2.Operators[i].(*OperatorHash) + if !ok { + fmt.Fprintf(output, "o1[%d] = %T %+v; o2[%d] = %T %+v\n", i, o1, o1, i, o2, o2) + } + if !bytes.Equal(o1.Hash.Bytes(), o2.Hash.Bytes()) { + fmt.Fprintf(output, "o1[%d].Hash = %s; o2[%d].Hash = %s\n", i, o1.Hash.Hex(), i, o2.Hash.Hex()) + } + case *OperatorCode: + o2, ok := w2.Operators[i].(*OperatorCode) + if !ok { + fmt.Fprintf(output, "o1[%d] = %T %+v; o2[%d] = %T %+v\n", i, o1, o1, i, o2, o2) + } + if !bytes.Equal(o1.Code, o2.Code) { + fmt.Fprintf(output, "o1[%d].Code = %x; o2[%d].Code = %x\n", i, o1.Code, i, o2.Code) + } + case *OperatorEmptyRoot: + o2, ok := w2.Operators[i].(*OperatorEmptyRoot) + if !ok { + fmt.Fprintf(output, "o1[%d] = %T %+v; o2[%d] = %T %+v\n", i, o1, o1, i, o2, o2) + } + case *OperatorExtension: + o2, ok := w2.Operators[i].(*OperatorExtension) + if !ok { + fmt.Fprintf(output, "o1[%d] = %T %+v; o2[%d] = %T %+v\n", i, o1, o1, i, o2, o2) + } + if !bytes.Equal(o1.Key, o2.Key) { + fmt.Fprintf(output, "extension o1[%d].Key = %x; o2[%d].Key = %x\n", i, o1.Key, i, o2.Key) + } + case *OperatorLeafAccount: + o2, ok := w2.Operators[i].(*OperatorLeafAccount) + if !ok { + fmt.Fprintf(output, "o1[%d] = %T %+v; o2[%d] = %T %+v\n", i, o1, o1, i, o2, o2) + } + if !bytes.Equal(o1.Key, o2.Key) { + fmt.Fprintf(output, "leafAcc o1[%d].Key = %x; o2[%d].Key = %x\n", i, o1.Key, i, o2.Key) + } + if o1.Nonce != o2.Nonce { + fmt.Fprintf(output, "leafAcc o1[%d].Nonce = %v; o2[%d].Nonce = %v\n", i, o1.Nonce, i, o2.Nonce) + } + if o1.Balance.String() != o2.Balance.String() { + fmt.Fprintf(output, "leafAcc o1[%d].Balance = %v; o2[%d].Balance = %v\n", i, o1.Balance.String(), i, o2.Balance.String()) + } + if o1.HasCode != o2.HasCode { + fmt.Fprintf(output, "leafAcc o1[%d].HasCode = %v; o2[%d].HasCode = %v\n", i, o1.HasCode, i, o2.HasCode) + } + if o1.HasStorage != o2.HasStorage { + fmt.Fprintf(output, "leafAcc o1[%d].HasStorage = %v; o2[%d].HasStorage = %v\n", i, o1.HasStorage, i, o2.HasStorage) + } + case *OperatorLeafValue: + o2, ok := w2.Operators[i].(*OperatorLeafValue) + if !ok { + fmt.Fprintf(output, "o1[%d] = %T %+v; o2[%d] = %T %+v\n", i, o1, o1, i, o2, o2) + } + if !bytes.Equal(o1.Key, o2.Key) { + fmt.Fprintf(output, "leafVal o1[%d].Key = %x; o2[%d].Key = %x\n", i, o1.Key, i, o2.Key) + } + if !bytes.Equal(o1.Value, o2.Value) { + fmt.Fprintf(output, "leafVal o1[%d].Value = %x; o2[%d].Value = %x\n", i, o1.Value, i, o2.Value) + } + default: + o2 := w2.Operators[i] + fmt.Fprintf(output, "unexpected o1[%d] = %T %+v; o2[%d] = %T %+v\n", i, o1, o1, i, o2, o2) + } + } +} diff --git a/erigon-lib/trie/witness_builder.go b/erigon-lib/trie/witness_builder.go new file mode 100644 index 00000000000..e14b6425c24 --- /dev/null +++ b/erigon-lib/trie/witness_builder.go @@ -0,0 +1,287 @@ +package trie + +import ( + "fmt" + "math/big" + + libcommon "github.com/erigontech/erigon-lib/common" +) + +type HashNodeFunc func(Node, bool, []byte) (int, error) + +type MerklePathLimiter struct { + RetainDecider RetainDecider + HashFunc HashNodeFunc +} + +type WitnessBuilder struct { + root Node + trace bool + operands []WitnessOperator +} + +func NewWitnessBuilder(root Node, trace bool) *WitnessBuilder { + return &WitnessBuilder{ + root: root, + trace: trace, + operands: make([]WitnessOperator, 0), + } +} + +func (b *WitnessBuilder) Build(limiter *MerklePathLimiter) (*Witness, error) { + err := b.makeBlockWitness(b.root, []byte{}, limiter, true) + witness := NewWitness(b.operands) + b.operands = nil + return witness, err +} + +func (b *WitnessBuilder) addLeafOp(key []byte, value []byte) error { + if b.trace { + fmt.Printf("LEAF_VALUE: k %x v:%x\n", key, value) + } + + var op OperatorLeafValue + + op.Key = make([]byte, len(key)) + copy(op.Key, key) + if value != nil { + op.Value = make([]byte, len(value)) + copy(op.Value, value) + } + + b.operands = append(b.operands, &op) + return nil +} + +func (b *WitnessBuilder) addAccountLeafOp(key []byte, accountNode *AccountNode, codeSize int) error { + if b.trace { + fmt.Printf("LEAF_ACCOUNT: k %x acc:%v\n", key, accountNode) + } + + var op OperatorLeafAccount + op.Key = make([]byte, len(key)) + copy(op.Key, key) + + op.Nonce = accountNode.Nonce + op.Balance = big.NewInt(0) + op.Balance.SetBytes(accountNode.Balance.Bytes()) + + if !accountNode.IsEmptyRoot() || !accountNode.IsEmptyCodeHash() { + op.HasCode = true + op.HasStorage = true + } + + op.CodeSize = uint64(codeSize) + + b.operands = append(b.operands, &op) + + return nil +} + +func (b *WitnessBuilder) addExtensionOp(key []byte) error { + if b.trace { + fmt.Printf("EXTENSION: k %x\n", key) + } + + var op OperatorExtension + op.Key = make([]byte, len(key)) + copy(op.Key, key) + + b.operands = append(b.operands, &op) + return nil +} + +func (b *WitnessBuilder) makeHashNode(n Node, force bool, hashNodeFunc HashNodeFunc) (HashNode, error) { + switch n := n.(type) { + case HashNode: + return n, nil + default: + var hash libcommon.Hash + if _, err := hashNodeFunc(n, force, hash[:]); err != nil { + return HashNode{}, err + } + return HashNode{hash: hash[:]}, nil + } +} + +func (b *WitnessBuilder) addHashOp(n *HashNode) error { + if b.trace { + fmt.Printf("HASH: type: %T v %s\n", n, n) + } + + var op OperatorHash + op.Hash = libcommon.BytesToHash(n.hash) + + b.operands = append(b.operands, &op) + return nil +} + +func (b *WitnessBuilder) addBranchOp(mask uint32) error { + if b.trace { + fmt.Printf("BRANCH: mask=%b\n", mask) + } + + var op OperatorBranch + op.Mask = mask + + b.operands = append(b.operands, &op) + return nil +} + +func (b *WitnessBuilder) addCodeOp(code []byte) error { + if b.trace { + fmt.Printf("CODE: len=%d\n", len(code)) + } + + var op OperatorCode + op.Code = make([]byte, len(code)) + copy(op.Code, code) + + b.operands = append(b.operands, &op) + return nil +} + +func (b *WitnessBuilder) addEmptyRoot() error { + if b.trace { + fmt.Printf("EMPTY ROOT\n") + } + + b.operands = append(b.operands, &OperatorEmptyRoot{}) + return nil +} + +func (b *WitnessBuilder) processAccountCode(n *AccountNode, retainDec RetainDecider) (int, error) { + if n.IsEmptyRoot() && n.IsEmptyCodeHash() { + return 0, nil + } + + if n.Code == nil || (retainDec != nil && !retainDec.IsCodeTouched(n.CodeHash)) { + codeSize := n.CodeSize + if n.Code != nil { + codeSize = len(n.Code) + } + return codeSize, b.addHashOp(&HashNode{hash: n.CodeHash[:]}) + } + + return len(n.Code), b.addCodeOp(n.Code) +} + +func (b *WitnessBuilder) processAccountStorage(n *AccountNode, hex []byte, limiter *MerklePathLimiter) error { + if n.IsEmptyRoot() && n.IsEmptyCodeHash() { + return nil + } + + if n.Storage == nil { + return b.addEmptyRoot() + } + + // Here we substitute rs parameter for storageRs, because it needs to become the default + return b.makeBlockWitness(n.Storage, hex, limiter, true) +} + +func (b *WitnessBuilder) makeBlockWitness( + nd Node, hex []byte, limiter *MerklePathLimiter, force bool) error { + + processAccountNode := func(key []byte, storageKey []byte, n *AccountNode) error { + var retainDec RetainDecider + if limiter != nil { + retainDec = limiter.RetainDecider + } + var codeSize int + var err error + if codeSize, err = b.processAccountCode(n, retainDec); err != nil { + return err + } + if err := b.processAccountStorage(n, storageKey, limiter); err != nil { + return err + } + return b.addAccountLeafOp(key, n, codeSize) + } + + switch n := nd.(type) { + case nil: + return nil + case ValueNode: + return b.addLeafOp(hex, n) + case *AccountNode: + return processAccountNode(hex, hex, n) + case *ShortNode: + h := n.Key + // Remove terminator + if h[len(h)-1] == 16 { + h = h[:len(h)-1] + } + hexVal := concat(hex, h...) + switch v := n.Val.(type) { + case ValueNode: + return b.addLeafOp(n.Key, v[:]) + case *AccountNode: + return processAccountNode(n.Key, hexVal, v) + default: + if err := b.makeBlockWitness(n.Val, hexVal, limiter, false); err != nil { + return err + } + + return b.addExtensionOp(n.Key) + } + case *DuoNode: + hashOnly := limiter != nil && !limiter.RetainDecider.Retain(hex) // Save this because rl can move on to other keys during the recursive invocation + if b.trace { + fmt.Printf("b.retainDec.Retain(%x) -> %v\n", hex, !hashOnly) + } + if hashOnly { + hn, err := b.makeHashNode(n, force, limiter.HashFunc) + if err != nil { + return err + } + return b.addHashOp(&hn) + } + + i1, i2 := n.childrenIdx() + + if err := b.makeBlockWitness(n.child1, expandKeyHex(hex, i1), limiter, false); err != nil { + return err + } + if err := b.makeBlockWitness(n.child2, expandKeyHex(hex, i2), limiter, false); err != nil { + return err + } + return b.addBranchOp(n.mask) + + case *FullNode: + hashOnly := limiter != nil && !limiter.RetainDecider.Retain(hex) // Save this because rs can move on to other keys during the recursive invocation + if hashOnly { + hn, err := b.makeHashNode(n, force, limiter.HashFunc) + if err != nil { + return err + } + return b.addHashOp(&hn) + } + + var mask uint32 + for i, child := range n.Children { + if child != nil { + if err := b.makeBlockWitness(child, expandKeyHex(hex, byte(i)), limiter, false); err != nil { + return err + } + mask |= uint32(1) << uint(i) + } + } + return b.addBranchOp(mask) + + case *HashNode: + hashOnly := limiter == nil || !limiter.RetainDecider.Retain(hex) + if hashOnly { + return b.addHashOp(n) + } + return fmt.Errorf("unexpected hashNode: %s, at hex: %x, (%d), hashOnly: %t", n, hex, len(hex), hashOnly) + default: + return fmt.Errorf("unexpected node type: %T", nd) + } +} + +func expandKeyHex(hex []byte, nibble byte) []byte { + result := make([]byte, len(hex)+1) + copy(result, hex) + result[len(hex)] = nibble + return result +} diff --git a/erigon-lib/trie/witness_builder_test.go b/erigon-lib/trie/witness_builder_test.go new file mode 100644 index 00000000000..5a83c44a044 --- /dev/null +++ b/erigon-lib/trie/witness_builder_test.go @@ -0,0 +1,80 @@ +package trie + +import ( + "bytes" + "testing" + + libcommon "github.com/erigontech/erigon-lib/common" + + "github.com/erigontech/erigon-lib/types/accounts" +) + +func TestBlockWitness(t *testing.T) { + tr := New(libcommon.Hash{}) + tr.Update([]byte("ABCD0001"), []byte("val1")) + tr.Update([]byte("ABCE0002"), []byte("val2")) + + rl := NewRetainList(2) + rl.AddKey([]byte("ABCD0001")) + + bwb := NewWitnessBuilder(tr.RootNode, false) + + hr := newHasher(false) + defer returnHasherToPool(hr) + + var w *Witness + var err error + if w, err = bwb.Build(&MerklePathLimiter{rl, hr.hash}); err != nil { + t.Errorf("Could not make block witness: %v", err) + } + + tr1, err := BuildTrieFromWitness(w, false) + if err != nil { + t.Errorf("Could not restore trie from the block witness: %v", err) + } + if tr.Hash() != tr1.Hash() { + t.Errorf("Reconstructed block witness has different root hash than source trie") + } + + expected := []byte("val1") + got, _ := tr1.Get([]byte("ABCD0001")) + if !bytes.Equal(got, expected) { + t.Errorf("unexpected value: %x (expected %x)", got, expected) + } +} + +func TestBlockWitnessAccount(t *testing.T) { + tr := New(libcommon.Hash{}) + + account := accounts.NewAccount() + account.Balance.SetUint64(1 * 1000 * 1000) + + tr.UpdateAccount([]byte("ABCD0001"), &account) + + rl := NewRetainList(2) + rl.AddKey([]byte("ABCD0001")) + + bwb := NewWitnessBuilder(tr.RootNode, false) + + hr := newHasher(false) + defer returnHasherToPool(hr) + + var w *Witness + var err error + if w, err = bwb.Build(&MerklePathLimiter{rl, hr.hash}); err != nil { + t.Errorf("Could not make block witness: %v", err) + } + + trBin1, err := BuildTrieFromWitness(w, false) + if err != nil { + t.Errorf("Could not restore trie from the block witness: %v", err) + } + if tr.Hash() != trBin1.Hash() { + t.Errorf("Reconstructed block witness has different root hash than source trie") + } + + got, _ := trBin1.GetAccount([]byte("ABCD0001")) + if !account.Equals(got) { + t.Errorf("received account is not equal to the initial one") + } +} diff --git a/erigon-lib/trie/witness_marshalling.go b/erigon-lib/trie/witness_marshalling.go new file mode 100644 index 00000000000..b1642e5b358 --- /dev/null +++ b/erigon-lib/trie/witness_marshalling.go @@ -0,0 +1,224 @@ +package trie + +import ( + "fmt" + "io" + + libcommon "github.com/erigontech/erigon-lib/common" + "github.com/ugorji/go/codec" +) + +var cbor codec.CborHandle + +// OperatorMarshaller provides all needed primitives to read witness operators from a serialized form. +type OperatorUnmarshaller struct { + reader io.Reader + decoder *codec.Decoder +} + +func NewOperatorUnmarshaller(r io.Reader) *OperatorUnmarshaller { + return &OperatorUnmarshaller{r, codec.NewDecoder(r, &cbor)} +} + +func (l *OperatorUnmarshaller) ReadByteArray() ([]byte, error) { + var buffer []byte + err := l.decoder.Decode(&buffer) + if err != nil { + return []byte{}, err + } + + return buffer, nil +} + +func (l *OperatorUnmarshaller) ReadHash() (libcommon.Hash, error) { + var hash libcommon.Hash + bytesRead, err := l.reader.Read(hash[:]) + if err != nil { + return hash, err + } + if bytesRead != len(hash) { + return hash, fmt.Errorf("error while reading hash from input. expected to read %d bytes, read only %d", len(hash), bytesRead) + } + return hash, nil +} + +func (l *OperatorUnmarshaller) ReadUint32() (uint32, error) { + var value uint32 + if err := l.decoder.Decode(&value); err != nil { + return 0, err + } + return value, nil +} + +func (l *OperatorUnmarshaller) ReadByte() (byte, error) { + values := make([]byte, 1) + bytesRead, err := l.reader.Read(values) + if err != nil { + return 0, err + } + if bytesRead < 1 { + return 0, fmt.Errorf("could not read a byte from a reader") + } + return values[0], nil +} + +func (l *OperatorUnmarshaller) ReadKey() ([]byte, error) { + b, err := l.ReadByteArray() + if err != nil { + return nil, err + } + return keyBytesToNibbles(b), nil +} + +func (l *OperatorUnmarshaller) ReadUInt64() (uint64, error) { + var value uint64 + err := l.decoder.Decode(&value) + if err != nil { + return 0, err + } + return value, nil + +} + +// OperatorMarshaller is responsible for encoding operators to a stream +// and collecting stats +// IMPORTANT: not thread-safe! use from a single thread only +type OperatorMarshaller struct { + currentColumn StatsColumn + encoder *codec.Encoder + w io.Writer + stats map[StatsColumn]uint64 + total uint64 +} + +func NewOperatorMarshaller(w io.Writer) *OperatorMarshaller { + marshaller := &OperatorMarshaller{w: w, stats: make(map[StatsColumn]uint64)} + // so we can collect stats + marshaller.encoder = codec.NewEncoder(marshaller, &cbor) + return marshaller +} + +func (w *OperatorMarshaller) WriteOpCode(opcode OperatorKindCode) error { + w.WithColumn(ColumnStructure) + _, err := w.Write([]byte{byte(opcode)}) + return err +} + +func (w *OperatorMarshaller) WriteKey(keyNibbles []byte) error { + w.WithColumn(ColumnLeafKeys) + return w.encoder.Encode(keyNibblesToBytes(keyNibbles)) +} + +func (w *OperatorMarshaller) WriteByteValue(value byte) error { + w.WithColumn(ColumnLeafValues) + _, err := w.Write([]byte{value}) + return err +} + +func (w *OperatorMarshaller) WriteUint64Value(value uint64) error { + w.WithColumn(ColumnLeafValues) + return w.encoder.Encode(value) +} + +func (w *OperatorMarshaller) WriteByteArrayValue(value []byte) error { + w.WithColumn(ColumnLeafValues) + return w.encoder.Encode(value) +} + +func (w *OperatorMarshaller) WriteCode(value []byte) error { + w.WithColumn(ColumnCodes) + return w.encoder.Encode(value) +} + +func (w *OperatorMarshaller) WriteHash(hash libcommon.Hash) error { + w.WithColumn(ColumnHashes) + _, err := w.Write(hash[:]) + return err +} + +func (w *OperatorMarshaller) Write(p []byte) (int, error) { + val := w.stats[w.currentColumn] + + written, err := w.w.Write(p) + + val += uint64(written) + w.total += uint64(written) + + w.stats[w.currentColumn] = val + + return written, err +} + +func (w *OperatorMarshaller) WithColumn(column StatsColumn) *OperatorMarshaller { + w.currentColumn = column + return w +} + +func (w *OperatorMarshaller) GetStats() *BlockWitnessStats { + return &BlockWitnessStats{ + witnessSize: w.total, + stats: w.stats, + } +} + +func keyNibblesToBytes(nibbles []byte) []byte { + if len(nibbles) < 1 { + return []byte{} + } + if len(nibbles) < 2 { + return nibbles + } + hasTerminator := false + if nibbles[len(nibbles)-1] == 0x10 { + nibbles = nibbles[:len(nibbles)-1] + hasTerminator = true + } + + targetLen := len(nibbles)/2 + len(nibbles)%2 + 1 + + result := make([]byte, targetLen) + nibbleIndex := 0 + result[0] = byte(len(nibbles) % 2) // parity bit + for i := 1; i < len(result); i++ { + result[i] = nibbles[nibbleIndex] * 16 + nibbleIndex++ + if nibbleIndex < len(nibbles) { + result[i] += nibbles[nibbleIndex] + nibbleIndex++ + } + } + if hasTerminator { + result[0] |= 1 << 1 + } + + return result +} + +func keyBytesToNibbles(b []byte) []byte { + if len(b) < 1 { + return []byte{} + } + if len(b) < 2 { + return b + } + + hasTerminator := b[0]&(1<<1) != 0 + + targetLen := (len(b)-1)*2 - int(b[0]&1) + + nibbles := make([]byte, targetLen) + + nibbleIndex := 0 + for i := 1; i < len(b); i++ { + nibbles[nibbleIndex] = b[i] / 16 + nibbleIndex++ + if nibbleIndex < len(nibbles) { + nibbles[nibbleIndex] = b[i] % 16 + nibbleIndex++ + } + } + if hasTerminator { + return append(nibbles, 0x10) + } + return nibbles +} diff --git a/erigon-lib/trie/witness_operators.go b/erigon-lib/trie/witness_operators.go new file mode 100644 index 00000000000..a96fcf98196 --- /dev/null +++ b/erigon-lib/trie/witness_operators.go @@ -0,0 +1,283 @@ +package trie + +import ( + "math/big" + + libcommon "github.com/erigontech/erigon-lib/common" + "github.com/ugorji/go/codec" +) + +const ( + flagCode = 1 << iota + flagStorage + flagNonce + flagBalance +) + +// OperatorKindCode is "enum" type for defining the opcodes of the stack machine that reconstructs the structure of tries from Structure tape +type OperatorKindCode uint8 + +const ( + // OpLeaf creates leaf node and pushes it onto the node stack, its hash onto the hash stack + OpLeaf OperatorKindCode = iota + // OpExtension pops a node from the node stack, constructs extension node from it and its operand's key, and pushes this extension node onto + // the node stack, its hash onto the hash stack + OpExtension + // OpBranch has operand, which is a bitset representing digits in the branch node. Pops the children nodes from the node stack (the number of + // children is equal to the number of bits in the bitset), constructs branch node and pushes it onto the node stack, its hash onto the hash stack + OpBranch + // OpHash and pushes the hash them onto the stack. + OpHash + // OpCode constructs code node and pushes it onto the node stack, its hash onto the hash stack. + OpCode + // OpAccountLeaf constructs an account node (without any storage and code) and pushes it onto the node stack, its hash onto the hash stack. + OpAccountLeaf + // OpEmptyRoot places nil onto the node stack, and empty root hash onto the hash stack. + OpEmptyRoot + + // OpNewTrie stops the processing, because another trie is encoded into the witness. + OpNewTrie = OperatorKindCode(0xBB) +) + +// WitnessOperator is a single operand in the block witness. It knows how to serialize/deserialize itself. +type WitnessOperator interface { + WriteTo(*OperatorMarshaller) error + + // LoadFrom always assumes that the opcode value was already read + LoadFrom(*OperatorUnmarshaller) error +} + +type OperatorHash struct { + Hash libcommon.Hash +} + +func (o *OperatorHash) WriteTo(output *OperatorMarshaller) error { + if err := output.WriteOpCode(OpHash); err != nil { + return err + } + return output.WriteHash(o.Hash) +} + +func (o *OperatorHash) LoadFrom(loader *OperatorUnmarshaller) error { + hash, err := loader.ReadHash() + if err != nil { + return err + } + + o.Hash = hash + return nil +} + +type OperatorLeafValue struct { + Key []byte + Value []byte +} + +func (o *OperatorLeafValue) WriteTo(output *OperatorMarshaller) error { + if err := output.WriteOpCode(OpLeaf); err != nil { + return err + } + + if err := output.WriteKey(o.Key); err != nil { + return err + } + + return output.WriteByteArrayValue(o.Value) +} + +func (o *OperatorLeafValue) LoadFrom(loader *OperatorUnmarshaller) error { + key, err := loader.ReadKey() + if err != nil { + return err + } + + o.Key = key + + value, err := loader.ReadByteArray() + if err != nil { + return err + } + + o.Value = value + return nil +} + +type OperatorLeafAccount struct { + Key []byte + Nonce uint64 + Balance *big.Int + HasCode bool + HasStorage bool + CodeSize uint64 +} + +func (o *OperatorLeafAccount) WriteTo(output *OperatorMarshaller) error { + if err := output.WriteOpCode(OpAccountLeaf); err != nil { + return err + } + + if err := output.WriteKey(o.Key); err != nil { + return err + } + + flags := byte(0) + if o.HasCode { + flags |= flagCode + } + if o.HasStorage { + flags |= flagStorage + } + if o.Nonce > 0 { + flags |= flagNonce + } + + if o.Balance.Sign() != 0 { + flags |= flagBalance + } + + if err := output.WriteByteValue(flags); err != nil { + return err + } + + if o.Nonce > 0 { + if err := output.WriteUint64Value(o.Nonce); err != nil { + return err + } + } + + if o.Balance.Sign() != 0 { + if err := output.WriteByteArrayValue(o.Balance.Bytes()); err != nil { + return err + } + } + + if o.HasCode { + if err := output.WriteUint64Value(o.CodeSize); err != nil { + return err + } + } + + return nil +} + +func (o *OperatorLeafAccount) LoadFrom(loader *OperatorUnmarshaller) error { + key, err := loader.ReadKey() + if err != nil { + return err + } + o.Key = key + + flags, err := loader.ReadByte() + if err != nil { + return err + } + + o.HasCode = flags&flagCode != 0 + o.HasStorage = flags&flagStorage != 0 + + if flags&flagNonce != 0 { + o.Nonce, err = loader.ReadUInt64() + if err != nil { + return err + } + } + + balance := big.NewInt(0) + + if flags&flagBalance != 0 { + var balanceBytes []byte + balanceBytes, err = loader.ReadByteArray() + if err != nil { + return err + } + balance.SetBytes(balanceBytes) + } + + o.Balance = balance + + if o.HasCode { + if codeSize, err := loader.ReadUInt64(); err == nil { + o.CodeSize = codeSize + } else { + return err + } + } + + return nil +} + +type OperatorCode struct { + Code []byte +} + +func (o *OperatorCode) WriteTo(output *OperatorMarshaller) error { + if err := output.WriteOpCode(OpCode); err != nil { + return err + } + + return output.WriteCode(o.Code) +} + +func (o *OperatorCode) LoadFrom(loader *OperatorUnmarshaller) error { + code, err := loader.ReadByteArray() + if err != nil { + return err + } + o.Code = code + return nil +} + +type OperatorBranch struct { + Mask uint32 +} + +func (o *OperatorBranch) WriteTo(output *OperatorMarshaller) error { + if err := output.WriteOpCode(OpBranch); err != nil { + return err + } + + encoder := codec.NewEncoder(output.WithColumn(ColumnStructure), &cbor) + return encoder.Encode(o.Mask) +} + +func (o *OperatorBranch) LoadFrom(loader *OperatorUnmarshaller) error { + mask, err := loader.ReadUint32() + if err != nil { + return err + } + + o.Mask = mask + return nil +} + +type OperatorEmptyRoot struct{} + +func (o *OperatorEmptyRoot) WriteTo(output *OperatorMarshaller) error { + return output.WriteOpCode(OpEmptyRoot) +} + +func (o *OperatorEmptyRoot) LoadFrom(loader *OperatorUnmarshaller) error { + // no-op + return nil +} + +type OperatorExtension struct { + Key []byte +} + +func (o *OperatorExtension) WriteTo(output *OperatorMarshaller) error { + if err := output.WriteOpCode(OpExtension); err != nil { + return err + } + return output.WriteKey(o.Key) +} + +func (o *OperatorExtension) LoadFrom(loader *OperatorUnmarshaller) error { + key, err := loader.ReadKey() + if err != nil { + return err + } + o.Key = key + + return nil +} diff --git a/erigon-lib/trie/witness_operators_test.go b/erigon-lib/trie/witness_operators_test.go new file mode 100644 index 00000000000..aec67539e93 --- /dev/null +++ b/erigon-lib/trie/witness_operators_test.go @@ -0,0 +1,263 @@ +package trie + +import ( + "bytes" + "math/big" + "testing" + + "github.com/ugorji/go/codec" +) + +func TestOperatoLoaderByteArray(t *testing.T) { + + var cbor codec.CborHandle + + var buffer bytes.Buffer + + encoder := codec.NewEncoder(&buffer, &cbor) + + bytes1 := []byte("test1") + bytes2 := []byte("abcd2") + + if err := encoder.Encode(bytes1); err != nil { + t.Error(err) + } + + if err := encoder.Encode(bytes2); err != nil { + t.Error(err) + } + + loader1 := NewOperatorUnmarshaller(&buffer) + + decoded1, err := loader1.ReadByteArray() + if err != nil { + t.Error(err) + } + if !bytes.Equal(decoded1, bytes1) { + t.Errorf("failed to decode bytes, expected %v got %v", bytes1, decoded1) + } + + decoded2, err := loader1.ReadByteArray() + if err != nil { + t.Error(err) + } + if !bytes.Equal(decoded2, bytes2) { + t.Errorf("failed to decode bytes, expected %v got %v", bytes1, decoded1) + } +} + +func TestAccountBigBalance(t *testing.T) { + key := []byte("l") + balance := big.NewInt(0) + var ok bool + balance, ok = balance.SetString("92233720368547758080", 10) + if !ok { + t.Error("fail to set balance to a large number") + } + acc := &OperatorLeafAccount{ + key, + 0, + balance, + false, + false, + 0, + } + + var buff bytes.Buffer + + collector := NewOperatorMarshaller(&buff) + + err := acc.WriteTo(collector) + if err != nil { + t.Error(err) + } + + // discard the opcode + _, err = buff.ReadByte() + if err != nil { + t.Error(err) + } + + acc2 := &OperatorLeafAccount{} + loader := NewOperatorUnmarshaller(&buff) + if err := acc2.LoadFrom(loader); err != nil { + t.Error(err) + } + + if acc2.Balance.Cmp(acc.Balance) != 0 { + t.Errorf("wrong deserialization of balance (expected: %s got %s)", acc.Balance.String(), acc2.Balance.String()) + } + +} + +func TestAccountCompactWriteTo(t *testing.T) { + key := []byte("l") + acc := &OperatorLeafAccount{ + key, + 0, + big.NewInt(0), + false, + false, + 0, + } + + var buff bytes.Buffer + + collector := NewOperatorMarshaller(&buff) + + err := acc.WriteTo(collector) + if err != nil { + t.Error(err) + } + + b := buff.Bytes() + + expectedLen := 1 /* opcode */ + 1 /* CBOR prefix for key */ + len(key) + 1 /* flags */ + + if len(b) != expectedLen { + t.Errorf("unexpected serialization len for default fields, expected %d (no fields seralized), got %d (raw: %v)", expectedLen, len(b), b) + } +} + +func TestAccountFullWriteTo(t *testing.T) { + key := []byte("l") + acc := &OperatorLeafAccount{ + key, + 20, + big.NewInt(10), + true, + true, + 0, + } + + var buff bytes.Buffer + + collector := NewOperatorMarshaller(&buff) + + err := acc.WriteTo(collector) + if err != nil { + t.Error(err) + } + + b := buff.Bytes() + + compactLen := 1 /* opcode */ + 1 /* CBOR prefix for key */ + len(key) + 1 /* flags */ + + if len(b) <= compactLen { + t.Errorf("unexpected serialization expected to be bigger than %d (fields seralized), got %d (raw: %v)", compactLen, len(b), b) + } + + flags := b[3] + + expectedFlags := byte(0) + expectedFlags |= flagStorage + expectedFlags |= flagCode + expectedFlags |= flagNonce + expectedFlags |= flagBalance + + if flags != expectedFlags { + t.Errorf("unexpected flags value (expected %b, got %b)", expectedFlags, flags) + } +} + +func TestAccountPartialNoNonceWriteTo(t *testing.T) { + key := []byte("l") + acc := &OperatorLeafAccount{ + key, + 0, + big.NewInt(10), + true, + true, + 0, + } + + var buff bytes.Buffer + + collector := NewOperatorMarshaller(&buff) + + err := acc.WriteTo(collector) + if err != nil { + t.Error(err) + } + + b := buff.Bytes() + + compactLen := 1 /* opcode */ + 1 /* CBOR prefix for key */ + len(key) + 1 /* flags */ + + if len(b) <= compactLen { + t.Errorf("unexpected serialization expected to be bigger than %d (fields seralized), got %d (raw: %v)", compactLen, len(b), b) + } + + flags := b[3] + + expectedFlags := byte(0) + expectedFlags |= flagStorage + expectedFlags |= flagCode + expectedFlags |= flagBalance + + if flags != expectedFlags { + t.Errorf("unexpected flags value (expected %b, got %b)", expectedFlags, flags) + } +} + +func TestAccountPartialNoBalanceWriteTo(t *testing.T) { + key := []byte("l") + acc := &OperatorLeafAccount{ + key, + 22, + big.NewInt(0), + true, + true, + 0, + } + + var buff bytes.Buffer + + collector := NewOperatorMarshaller(&buff) + + err := acc.WriteTo(collector) + if err != nil { + t.Error(err) + } + + b := buff.Bytes() + + compactLen := 1 /* opcode */ + 1 /* CBOR prefix for key */ + len(key) + 1 /* flags */ + + if len(b) <= compactLen { + t.Errorf("unexpected serialization expected to be bigger than %d (fields seralized), got %d (raw: %v)", compactLen, len(b), b) + } + + flags := b[3] + + expectedFlags := byte(0) + expectedFlags |= flagStorage + expectedFlags |= flagCode + expectedFlags |= flagNonce + + if flags != expectedFlags { + t.Errorf("unexpected flags value (expected %b, got %b)", expectedFlags, flags) + } +} + +func TestKeySerialization(t *testing.T) { + for _, key := range [][]byte{ + {1, 16}, + {1, 2, 3, 4, 5}, + {1, 2, 3, 4, 5, 6}, + {}, + {3, 9, 1}, + {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 15, 15, 15, 15, 15}, + {1}, + {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 15, 15, 15, 15, 16}, + } { + b := keyNibblesToBytes(key) + + key2 := keyBytesToNibbles(b) + + if !bytes.Equal(key, key2) { + t.Errorf("wrong deserialization, expected %x got %x", key, key2) + } + + } +} diff --git a/erigon-lib/trie/witness_stats.go b/erigon-lib/trie/witness_stats.go new file mode 100644 index 00000000000..da0e5180316 --- /dev/null +++ b/erigon-lib/trie/witness_stats.go @@ -0,0 +1,41 @@ +package trie + +type StatsColumn string + +const ( + ColumnStructure = StatsColumn("structure") + ColumnHashes = StatsColumn("hashes") + ColumnCodes = StatsColumn("codes") + ColumnLeafKeys = StatsColumn("leaf_keys") + ColumnLeafValues = StatsColumn("leaf_values") + ColumnTotal = StatsColumn("total_witness_size") +) + +type BlockWitnessStats struct { + witnessSize uint64 + stats map[StatsColumn]uint64 +} + +func (s *BlockWitnessStats) BlockWitnessSize() uint64 { + return s.witnessSize +} + +func (s *BlockWitnessStats) CodesSize() uint64 { + return s.stats[ColumnCodes] +} + +func (s *BlockWitnessStats) LeafKeysSize() uint64 { + return s.stats[ColumnLeafKeys] +} + +func (s *BlockWitnessStats) LeafValuesSize() uint64 { + return s.stats[ColumnLeafValues] +} + +func (s *BlockWitnessStats) StructureSize() uint64 { + return s.stats[ColumnStructure] +} + +func (s *BlockWitnessStats) HashesSize() uint64 { + return s.stats[ColumnHashes] +} diff --git a/erigon-lib/trie/witness_test.go b/erigon-lib/trie/witness_test.go new file mode 100644 index 00000000000..8cfbf497605 --- /dev/null +++ b/erigon-lib/trie/witness_test.go @@ -0,0 +1,96 @@ +package trie + +import ( + "bytes" + "fmt" + "math/big" + "testing" + + libcommon "github.com/erigontech/erigon-lib/common" +) + +func generateOperands() []WitnessOperator { + return []WitnessOperator{ + &OperatorBranch{Mask: 0xFF}, + &OperatorEmptyRoot{}, + &OperatorCode{[]byte("code-operand-1")}, + &OperatorExtension{[]byte{5, 5, 4, 6, 6, 6}}, + &OperatorLeafValue{[]byte{5, 5, 4, 3, 2, 1}, []byte("leaf-value-value-1")}, + &OperatorHash{libcommon.HexToHash("0xabcabcabcabc")}, + &OperatorLeafAccount{ + []byte{2, 2, 4, 5, 6}, + 999, + big.NewInt(552), + true, + false, + 10, + }, + &OperatorLeafAccount{ + []byte{2, 2, 4, 5, 7}, + 757, + big.NewInt(334), + true, + true, + 11, + }, + &OperatorLeafAccount{ + []byte{2, 2, 4, 5, 8}, + 333, + big.NewInt(11112), + false, + false, + 12, + }, + &OperatorLeafAccount{ + []byte{2, 2, 4, 5, 9}, + 0, + big.NewInt(0), + false, + false, + 13, + }, + } +} + +func witnessesEqual(w1, w2 *Witness) bool { + if w1 == nil { + return w2 == nil + } + + if w2 == nil { + return w1 == nil + } + + var buff bytes.Buffer + + w1.WriteDiff(w2, &buff) + + diff := buff.String() + + fmt.Printf("%s", diff) + + return len(diff) == 0 +} + +func TestWitnessSerialization(t *testing.T) { + expectedHeader := defaultWitnessHeader() + + expectedOperands := generateOperands() + + expectedWitness := Witness{expectedHeader, expectedOperands} + + var buffer bytes.Buffer + + if _, err := expectedWitness.WriteInto(&buffer); err != nil { + t.Error(err) + } + + decodedWitness, err := NewWitnessFromReader(&buffer, false /* trace */) + if err != nil { + t.Error(err) + } + + if !witnessesEqual(&expectedWitness, decodedWitness) { + t.Errorf("witnesses not equal: expected %+v; got %+v", expectedWitness, decodedWitness) + } +} diff --git a/erigon-lib/types/accounts/account.go b/erigon-lib/types/accounts/account.go index 4bf92881a27..ce8c9a311aa 100644 --- a/erigon-lib/types/accounts/account.go +++ b/erigon-lib/types/accounts/account.go @@ -197,6 +197,13 @@ func (a *Account) EncodeRLP(w io.Writer) error { return err } +// returns the RLP encoding of the account directly as a []byte +func (a *Account) RLP() []byte { + accRlp := make([]byte, a.EncodingLengthForHashing()) + a.EncodeForHashing(accRlp) + return accRlp +} + func (a *Account) EncodeForHashing(buffer []byte) { balanceBytes := 0 if !a.Balance.LtUint64(128) { diff --git a/erigon-lib/types/witness/types.go b/erigon-lib/types/witness/types.go new file mode 100644 index 00000000000..3e4e6aa189b --- /dev/null +++ b/erigon-lib/types/witness/types.go @@ -0,0 +1,16 @@ +package witness + +import ( + libcommon "github.com/erigontech/erigon-lib/common" + "github.com/erigontech/erigon-lib/types/accounts" +) + +type AccountWithAddress struct { + Address libcommon.Address + Account *accounts.Account +} + +type CodeWithHash struct { + Code []byte + CodeHash libcommon.Hash +} diff --git a/eth/stagedsync/stage_witness.go b/eth/stagedsync/stage_witness.go new file mode 100644 index 00000000000..d1143980eed --- /dev/null +++ b/eth/stagedsync/stage_witness.go @@ -0,0 +1,146 @@ +package stagedsync + +import ( + "bytes" + "context" + + "github.com/c2h5oh/datasize" + "github.com/erigontech/erigon-lib/chain" + libcommon "github.com/erigontech/erigon-lib/common" + "github.com/erigontech/erigon-lib/common/datadir" + "github.com/erigontech/erigon-lib/kv" + "github.com/erigontech/erigon-lib/kv/membatchwithdb" + "github.com/erigontech/erigon-lib/kv/rawdbv3" + "github.com/erigontech/erigon-lib/log/v3" + "github.com/erigontech/erigon-lib/trie" + "github.com/erigontech/erigon-lib/wrap" + "github.com/erigontech/erigon/consensus" + "github.com/erigontech/erigon/core" + "github.com/erigontech/erigon/core/state" + "github.com/erigontech/erigon/core/types" + "github.com/erigontech/erigon/core/vm" + "github.com/erigontech/erigon/eth/ethconfig" + "github.com/erigontech/erigon/eth/stagedsync/stages" + "github.com/erigontech/erigon/ethdb/prune" + "github.com/erigontech/erigon/turbo/rpchelper" + "github.com/erigontech/erigon/turbo/services" +) + +type WitnessCfg struct { + db kv.RwDB + enableWitnessGeneration bool + maxWitnessLimit uint64 + chainConfig *chain.Config + engine consensus.Engine + blockReader services.FullBlockReader + dirs datadir.Dirs +} + +type WitnessStore struct { + Tds *state.TrieDbState + TrieStateWriter *state.TrieStateWriter + Statedb *state.IntraBlockState + ChainReader *ChainReaderImpl + GetHashFn func(n uint64) libcommon.Hash +} + +func StageWitnessCfg(enableWitnessGeneration bool, maxWitnessLimit uint64, chainConfig *chain.Config, engine consensus.Engine, blockReader services.FullBlockReader, dirs datadir.Dirs) WitnessCfg { + return WitnessCfg{ + enableWitnessGeneration: enableWitnessGeneration, + maxWitnessLimit: maxWitnessLimit, + chainConfig: chainConfig, + engine: engine, + blockReader: blockReader, + dirs: dirs, + } +} + +// PrepareForWitness abstracts the process of initialising bunch of necessary things required for witness +// generation and puts them in a WitnessStore. +func PrepareForWitness(tx kv.Tx, block *types.Block, prevRoot libcommon.Hash, cfg *WitnessCfg, ctx context.Context, logger log.Logger) (*WitnessStore, error) { + blockNr := block.NumberU64() + txNumsReader := rawdbv3.TxNums + reader, err := rpchelper.CreateHistoryStateReader(tx, txNumsReader, blockNr, 0, cfg.chainConfig.ChainName) + // stateReader, err := rpchelper.CreateHistoryStateReader(roTx, txNumsReader, blockNr, 0, "") + if err != nil { + return nil, err + } + + tds := state.NewTrieDbState(prevRoot, blockNr-1, reader) + tds.SetResolveReads(true) + + tds.StartNewBuffer() + trieStateWriter := tds.TrieStateWriter() + + statedb := state.New(tds) + + chainReader := NewChainReaderImpl(cfg.chainConfig, tx, cfg.blockReader, logger) + + getHeader := func(hash libcommon.Hash, number uint64) *types.Header { + h, e := cfg.blockReader.Header(ctx, tx, hash, number) + if e != nil { + log.Error("getHeader error", "number", number, "hash", hash, "err", e) + } + return h + } + getHashFn := core.GetHashFn(block.Header(), getHeader) + + return &WitnessStore{ + Tds: tds, + TrieStateWriter: trieStateWriter, + Statedb: statedb, + ChainReader: chainReader, + GetHashFn: getHashFn, + }, nil +} + +// RewindStagesForWitness rewinds the Execution stage to previous block. +func RewindStagesForWitness(batch *membatchwithdb.MemoryMutation, blockNr, latestBlockNr uint64, cfg *WitnessCfg, regenerateHash bool, ctx context.Context, logger log.Logger) error { + // Rewind the Execution stage to previous block + unwindState := &UnwindState{ID: stages.Execution, UnwindPoint: blockNr - 1, CurrentBlockNumber: latestBlockNr} + stageState := &StageState{ID: stages.Execution, BlockNumber: blockNr} + + txc := wrap.TxContainer{Tx: batch} + batchSizeStr := "512M" + var batchSize datasize.ByteSize + err := batchSize.UnmarshalText([]byte(batchSizeStr)) + if err != nil { + return err + } + + pruneMode := prune.Mode{ + Initialised: false, + } + vmConfig := &vm.Config{} + dirs := cfg.dirs + blockReader := cfg.blockReader + syncCfg := ethconfig.Defaults.Sync + execCfg := StageExecuteBlocksCfg(batch.MemDB(), pruneMode, batchSize, cfg.chainConfig, cfg.engine, vmConfig, nil, + /*stateStream=*/ false, + /*badBlockHalt=*/ true, dirs, blockReader, nil, nil, syncCfg, nil) + + if err := UnwindExecutionStage(unwindState, stageState, txc, ctx, execCfg, logger); err != nil { + return err + } + + return nil +} + +func ExecuteBlockStatelessly(block *types.Block, prevHeader *types.Header, chainReader consensus.ChainReader, tds *state.TrieDbState, cfg *WitnessCfg, buf *bytes.Buffer, getHashFn func(n uint64) libcommon.Hash, logger log.Logger) (libcommon.Hash, error) { + blockNr := block.NumberU64() + nw, err := trie.NewWitnessFromReader(bytes.NewReader(buf.Bytes()), false) + if err != nil { + return libcommon.Hash{}, err + } + + statelessIbs, err := state.NewStateless(prevHeader.Root, nw, blockNr-1, true /* trace */, false /* is binary */) + if err != nil { + return libcommon.Hash{}, err + } + execResult, err := core.ExecuteBlockEphemerally(cfg.chainConfig, &vm.Config{}, getHashFn, cfg.engine, block, statelessIbs, statelessIbs, chainReader, nil, logger) + if err != nil { + return libcommon.Hash{}, err + } + _ = execResult + return statelessIbs.Finalize(), nil +} diff --git a/eth/stagedsync/witness_util.go b/eth/stagedsync/witness_util.go new file mode 100644 index 00000000000..cebda023e47 --- /dev/null +++ b/eth/stagedsync/witness_util.go @@ -0,0 +1,247 @@ +package stagedsync + +import ( + "bytes" + "context" + "encoding/binary" + "encoding/csv" + "fmt" + "strconv" + + "github.com/erigontech/erigon-lib/common" + "github.com/erigontech/erigon-lib/kv" + "github.com/erigontech/erigon-lib/trie" +) + +type WitnessDBWriter struct { + storage kv.RwDB + statsWriter *csv.Writer +} + +func NewWitnessDBWriter(storage kv.RwDB, statsWriter *csv.Writer) (*WitnessDBWriter, error) { + err := statsWriter.Write([]string{ + "blockNum", "maxTrieSize", "witnessesSize", + }) + if err != nil { + return nil, err + } + return &WitnessDBWriter{storage, statsWriter}, nil +} + +const chunkSize = 100000 // 100KB + +func WriteChunks(tx kv.RwTx, tableName string, key []byte, valueBytes []byte) error { + // Split the valueBytes into chunks and write each chunk + for i := 0; i < len(valueBytes); i += chunkSize { + end := i + chunkSize + if end > len(valueBytes) { + end = len(valueBytes) + } + chunk := valueBytes[i:end] + chunkKey := append(key, []byte("_chunk_"+strconv.Itoa(i/chunkSize))...) + + // Write each chunk to the KV store + if err := tx.Put(tableName, chunkKey, chunk); err != nil { + return err + } + } + + return nil +} + +func ReadChunks(tx kv.Tx, tableName string, key []byte) ([]byte, error) { + // Initialize a buffer to store the concatenated chunks + var result []byte + + // Retrieve and concatenate each chunk + for i := 0; ; i++ { + chunkKey := append(key, []byte("_chunk_"+strconv.Itoa(i))...) + chunk, err := tx.GetOne(tableName, chunkKey) + if err != nil { + return nil, err + } + + // Check if this is the last chunk + if len(chunk) == 0 { + break + } + + // Append the chunk to the result + result = append(result, chunk...) + } + + return result, nil +} + +// HasWitness returns whether a witness exists for the given key or not +func HasWitness(tx kv.Tx, tableName string, key []byte) (bool, error) { + firstChunkKey := append(key, []byte("_chunk_0")...) + chunk, err := tx.GetOne(tableName, firstChunkKey) + if err != nil { + return false, err + } + + if len(chunk) == 0 { + return false, nil + } + + return true, nil +} + +// DeleteChunks deletes all the chunks present with prefix `key` +// TODO: Try to see if this can be optimised by using tx.ForEach +// and iterate over each element with prefix `key` +func DeleteChunks(tx kv.RwTx, tableName string, key []byte) error { + for i := 0; ; i++ { + chunkKey := append(key, []byte("_chunk_"+strconv.Itoa(i))...) + chunk, err := tx.GetOne(tableName, chunkKey) + if err != nil { + return err + } + + err = tx.Delete(tableName, chunkKey) + if err != nil { + return err + } + + // Check if this is the last chunk + if len(chunk) == 0 { + break + } + } + + return nil +} + +// FindOldestWitness returns the block number of the oldest stored block +func FindOldestWitness(tx kv.Tx, tableName string) (uint64, error) { + cursor, err := tx.Cursor(tableName) + if err != nil { + return 0, err + } + + k, _, err := cursor.First() + if err != nil { + return 0, err + } + + return BytesToUint64(k), nil +} + +func (db *WitnessDBWriter) MustUpsertOneWitness(blockNumber uint64, witness *trie.Witness) { + k := make([]byte, 8) + + binary.LittleEndian.PutUint64(k, blockNumber) + + var buf bytes.Buffer + _, err := witness.WriteInto(&buf) + if err != nil { + panic(fmt.Sprintf("error extracting witness for block %d: %v\n", blockNumber, err)) + } + + wb := buf.Bytes() + + tx, err := db.storage.BeginRw(context.Background()) + if err != nil { + panic(fmt.Errorf("error opening tx: %w", err)) + } + + defer tx.Rollback() + + fmt.Printf("Size of witness: %d\n", len(wb)) + + err = WriteChunks(tx, kv.Witnesses, k, common.CopyBytes(wb)) + + tx.Commit() + + if err != nil { + panic(fmt.Errorf("error while upserting witness: %w", err)) + } +} + +func (db *WitnessDBWriter) MustUpsert(blockNumber uint64, maxTrieSize uint32, resolveWitnesses []*trie.Witness) { + key := deriveDbKey(blockNumber, maxTrieSize) + + var buf bytes.Buffer + + for i, witness := range resolveWitnesses { + if _, err := witness.WriteInto(&buf); err != nil { + panic(fmt.Errorf("error while writing witness to a buffer: %w", err)) + } + if i < len(resolveWitnesses)-1 { + buf.WriteByte(byte(trie.OpNewTrie)) + } + } + + bytes := buf.Bytes() + + tx, err := db.storage.BeginRw(context.Background()) + if err != nil { + panic(fmt.Errorf("error opening tx: %w", err)) + } + + defer tx.Rollback() + + err = tx.Put(kv.Witnesses, common.CopyBytes(key), common.CopyBytes(bytes)) + + tx.Commit() + + if err != nil { + panic(fmt.Errorf("error while upserting witness: %w", err)) + } + + err = db.statsWriter.Write([]string{ + strconv.Itoa(int(blockNumber)), + strconv.Itoa(int(maxTrieSize)), + strconv.Itoa(len(bytes)), + }) + + if err != nil { + panic(fmt.Errorf("error while writing stats: %w", err)) + } + + db.statsWriter.Flush() +} + +type WitnessDBReader struct { + db kv.RwDB +} + +func NewWitnessDBReader(db kv.RwDB) *WitnessDBReader { + return &WitnessDBReader{db} +} + +func (db *WitnessDBReader) GetWitnessesForBlock(blockNumber uint64, maxTrieSize uint32) ([]byte, error) { + key := deriveDbKey(blockNumber, maxTrieSize) + + tx, err := db.db.BeginRo(context.Background()) + if err != nil { + panic(fmt.Errorf("error opening tx: %w", err)) + } + + defer tx.Rollback() + + return tx.GetOne(kv.Witnesses, key) +} + +func deriveDbKey(blockNumber uint64, maxTrieSize uint32) []byte { + buffer := make([]byte, 8+4) + + binary.LittleEndian.PutUint64(buffer, blockNumber) + binary.LittleEndian.PutUint32(buffer[8:], maxTrieSize) + + return buffer +} + +func BytesToUint64(b []byte) uint64 { + if len(b) < 8 { + return 0 + } + return binary.BigEndian.Uint64(b) +} + +func Uint64ToBytes(i uint64) []byte { + buf := make([]byte, 8) + binary.BigEndian.PutUint64(buf, i) + return buf +} diff --git a/turbo/jsonrpc/eth_call.go b/turbo/jsonrpc/eth_call.go index 2f9cd154068..748265bd566 100644 --- a/turbo/jsonrpc/eth_call.go +++ b/turbo/jsonrpc/eth_call.go @@ -17,14 +17,22 @@ package jsonrpc import ( + "bytes" "context" "errors" "fmt" "math/big" + "github.com/erigontech/erigon-lib/kv/dbutils" + "github.com/erigontech/erigon-lib/trie" + + "github.com/erigontech/erigon-lib/commitment" + libstate "github.com/erigontech/erigon-lib/state" "github.com/holiman/uint256" "google.golang.org/grpc" + "github.com/erigontech/erigon-lib/kv/membatchwithdb" + libcommon "github.com/erigontech/erigon-lib/common" "github.com/erigontech/erigon-lib/common/hexutil" "github.com/erigontech/erigon-lib/common/hexutility" @@ -35,11 +43,13 @@ import ( "github.com/erigontech/erigon-lib/kv/rawdbv3" "github.com/erigontech/erigon-lib/log/v3" "github.com/erigontech/erigon-lib/types/accounts" + "github.com/erigontech/erigon/consensus" "github.com/erigontech/erigon/core" "github.com/erigontech/erigon/core/state" "github.com/erigontech/erigon/core/types" "github.com/erigontech/erigon/core/vm" "github.com/erigontech/erigon/core/vm/evmtypes" + "github.com/erigontech/erigon/eth/stagedsync" "github.com/erigontech/erigon/eth/tracers/logger" "github.com/erigontech/erigon/params" "github.com/erigontech/erigon/rpc" @@ -420,6 +430,217 @@ func (api *APIImpl) GetProof(ctx context.Context, address libcommon.Address, sto */ } +func (api *APIImpl) GetWitness(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (hexutility.Bytes, error) { + return api.getWitness(ctx, api.db, blockNrOrHash, 0, true, api.MaxGetProofRewindBlockCount, api.logger) +} + +func (api *APIImpl) GetTxWitness(ctx context.Context, blockNr rpc.BlockNumberOrHash, txIndex hexutil.Uint) (hexutility.Bytes, error) { + return api.getWitness(ctx, api.db, blockNr, txIndex, false, api.MaxGetProofRewindBlockCount, api.logger) +} + +func verifyExecResult(execResult *core.EphemeralExecResult, block *types.Block) error { + actualTxRoot := execResult.TxRoot.Bytes() + expectedTxRoot := block.TxHash().Bytes() + if !bytes.Equal(actualTxRoot, expectedTxRoot) { + return fmt.Errorf("mismatch in block TxRoot actual(%x) != expected(%x)", actualTxRoot, expectedTxRoot) + } + + actualGasUsed := uint64(execResult.GasUsed) + expectedGasUsed := block.GasUsed() + if actualGasUsed != expectedGasUsed { + return fmt.Errorf("mismatch in block gas used actual(%x) != expected(%x)", actualGasUsed, expectedGasUsed) + } + + actualReceiptsHash := execResult.ReceiptRoot.Bytes() + expectedReceiptsHash := block.ReceiptHash().Bytes() + if !bytes.Equal(actualReceiptsHash, expectedReceiptsHash) { + return fmt.Errorf("mismatch in receipts hash actual(%x) != expected(%x)", actualReceiptsHash, expectedReceiptsHash) + } + + // check the state root + resultingStateRoot := execResult.StateRoot.Bytes() + expectedBlockStateRoot := block.Root().Bytes() + if !bytes.Equal(resultingStateRoot, expectedBlockStateRoot) { + return fmt.Errorf("resulting state root after execution doesn't match state root in block actual(%x)!=expected(%x)", resultingStateRoot, expectedBlockStateRoot) + } + return nil +} + +func (api *BaseAPI) getWitness(ctx context.Context, db kv.RoDB, blockNrOrHash rpc.BlockNumberOrHash, txIndex hexutil.Uint, fullBlock bool, maxGetProofRewindBlockCount int, logger log.Logger) (hexutility.Bytes, error) { + roTx, err := db.BeginRo(ctx) + if err != nil { + return nil, err + } + defer roTx.Rollback() + + blockNr, hash, _, err := rpchelper.GetCanonicalBlockNumber(ctx, blockNrOrHash, roTx, api._blockReader, api.filters) // DoCall cannot be executed on non-canonical blocks + if err != nil { + return nil, err + } + + // Witness for genesis block is empty + if blockNr == 0 { + w := trie.NewWitness(make([]trie.WitnessOperator, 0)) + + var buf bytes.Buffer + _, err = w.WriteInto(&buf) + if err != nil { + return nil, err + } + + return buf.Bytes(), nil + } + + block, err := api.blockWithSenders(ctx, roTx, hash, blockNr) + if err != nil { + return nil, err + } + if block == nil { + return nil, nil + } + + if !fullBlock && int(txIndex) >= len(block.Transactions()) { + return nil, fmt.Errorf("transaction index out of bounds: %d", txIndex) + } + + latestBlock, err := rpchelper.GetLatestBlockNumber(roTx) + if err != nil { + return nil, err + } + + if latestBlock < blockNr { + // shouldn't happen, but check anyway + return nil, fmt.Errorf("block number is in the future latest=%d requested=%d", latestBlock, blockNr) + } + + // Compute the witness if it's for a tx or it's not present in db + prevHeader, err := api._blockReader.HeaderByNumber(ctx, roTx, blockNr-1) + if err != nil { + return nil, err + } + + regenerateHash := false + if latestBlock-blockNr > uint64(maxGetProofRewindBlockCount) { + regenerateHash = true + } + + engine, ok := api.engine().(consensus.Engine) + if !ok { + return nil, errors.New("engine is not consensus.Engine") + } + + roTx2, err := db.BeginRo(ctx) + if err != nil { + return nil, err + } + defer roTx2.Rollback() + txBatch2 := membatchwithdb.NewMemoryBatch(roTx2, "", logger) + defer txBatch2.Rollback() + + // Prepare witness config + chainConfig, err := api.chainConfig(ctx, roTx2) + if err != nil { + return nil, fmt.Errorf("error loading chain config: %v", err) + } + + // Unwind to blockNr + cfg := stagedsync.StageWitnessCfg(true, 0, chainConfig, engine, api._blockReader, api.dirs) + err = stagedsync.RewindStagesForWitness(txBatch2, blockNr, latestBlock, &cfg, regenerateHash, ctx, logger) + if err != nil { + return nil, err + } + + store, err := stagedsync.PrepareForWitness(txBatch2, block, prevHeader.Root, &cfg, ctx, logger) + if err != nil { + return nil, err + } + + domains, err := libstate.NewSharedDomains(txBatch2, log.New()) + if err != nil { + return nil, err + } + sdCtx := libstate.NewSharedDomainsCommitmentContext(domains, commitment.ModeUpdate, commitment.VariantHexPatriciaTrie) + patricieTrie := sdCtx.Trie() + hph, ok := patricieTrie.(*commitment.HexPatriciaHashed) + if !ok { + return nil, errors.New("casting to HexPatriciaTrieHashed failed") + } + + // execute block #blockNr ephemerally. This will use TrieStateWriter to record touches of accounts and storage keys. + _, err = core.ExecuteBlockEphemerally(chainConfig, &vm.Config{}, store.GetHashFn, engine, block, store.Tds, store.TrieStateWriter, store.ChainReader, nil, logger) + if err != nil { + return nil, err + } + + // gather touched keys from ephemeral block execution + touchedPlainKeys, touchedHashedKeys := store.Tds.GetTouchedPlainKeys() + codeReads := store.Tds.BuildCodeTouches() + + // define these keys as "updates", but we are not really updating anything, we just want to load them into the grid, + // so this is just to satisfy the current hex patricia trie api. + updates := commitment.NewUpdates(commitment.ModeDirect, sdCtx.TempDir(), hph.HashAndNibblizeKey) + for _, key := range touchedPlainKeys { + updates.TouchPlainKey(string(key), nil, updates.TouchAccount) + } + + hph.SetTrace(false) // disable tracing to avoid mixing with trace from witness computation + // generate the block witness, this works by loading the merkle paths to the touched keys (they are loaded from the state at block #blockNr-1) + witnessTrie, witnessRootHash, err := hph.GenerateWitness(ctx, updates, codeReads, prevHeader.Root[:], "computeWitness") + if err != nil { + return nil, err + } + + // + if !bytes.Equal(witnessRootHash, prevHeader.Root[:]) { + return nil, fmt.Errorf("witness root hash mismatch actual(%x)!=expected(%x)", witnessRootHash, prevHeader.Root[:]) + } + + // retain list is need for the serialization of the trie.Trie into a witness + retainListBuilder := trie.NewRetainListBuilder() + for _, key := range touchedHashedKeys { + if len(key) == 32 { + retainListBuilder.AddTouch(key) + } else { + addr, _, hash := dbutils.ParseCompositeStorageKey(key) + storageTouch := dbutils.GenerateCompositeTrieKey(addr, hash) + retainListBuilder.AddStorageTouch(storageTouch) + } + } + + for _, codeWithHash := range codeReads { + retainListBuilder.ReadCode(codeWithHash.CodeHash, codeWithHash.Code) + } + + retainList := retainListBuilder.Build(false) + + // serialize witness trie + witness, err := witnessTrie.ExtractWitness(true, retainList) + if err != nil { + return nil, err + } + + var witnessBuffer bytes.Buffer + _, err = witness.WriteInto(&witnessBuffer) + if err != nil { + return nil, err + } + + // this is a verification step: we execute block #blockNr statelessly using the witness, and we expect to get the same state root as in the header + // otherwise something went wrong + store.Tds.SetTrie(witnessTrie) + newStateRoot, err := stagedsync.ExecuteBlockStatelessly(block, prevHeader, store.ChainReader, store.Tds, &cfg, &witnessBuffer, store.GetHashFn, logger) + if err != nil { + return nil, err + } + if !bytes.Equal(newStateRoot.Bytes(), block.Root().Bytes()) { + fmt.Printf("state root mismatch after stateless execution actual(%x) != expected(%x)\n", newStateRoot.Bytes(), block.Root().Bytes()) + } + witnessBufBytes := witnessBuffer.Bytes() + witnessBufBytesCopy := make([]byte, len(witnessBufBytes)) + copy(witnessBufBytesCopy, witnessBufBytes) + return witnessBufBytesCopy, nil +} + func (api *APIImpl) tryBlockFromLru(hash libcommon.Hash) *types.Block { var block *types.Block if api.blocksLRU != nil { diff --git a/turbo/jsonrpc/trace_filtering.go b/turbo/jsonrpc/trace_filtering.go index d4fc600370e..70a8ca5985d 100644 --- a/turbo/jsonrpc/trace_filtering.go +++ b/turbo/jsonrpc/trace_filtering.go @@ -780,7 +780,7 @@ func (api *TraceAPIImpl) callManyTransactions( engine := api.engine() consensusHeaderReader := consensuschain.NewReader(cfg, dbtx, nil, nil) logger := log.New("trace_filtering") - err = core.InitializeBlockExecution(engine.(consensus.Engine), consensusHeaderReader, block.HeaderNoCopy(), cfg, ibs, logger, nil) + err = core.InitializeBlockExecution(engine.(consensus.Engine), consensusHeaderReader, block.HeaderNoCopy(), cfg, ibs, nil, logger, nil) if err != nil { return nil, nil, err } From c214305858b8fc86c7665da5588c1006adad67c9 Mon Sep 17 00:00:00 2001 From: Andrew Ashikhmin <34320705+yperbasis@users.noreply.github.com> Date: Mon, 9 Dec 2024 19:08:37 +0100 Subject: [PATCH 10/24] params: v3.0.0-alpha6 (#13054) --- params/version.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/params/version.go b/params/version.go index b2b6c14433d..e3da300d50f 100644 --- a/params/version.go +++ b/params/version.go @@ -37,7 +37,7 @@ const ( VersionMajor = 3 // Major version component of the current release VersionMinor = 0 // Minor version component of the current release VersionMicro = 0 // Patch version component of the current release - VersionModifier = "alpha5" // Modifier component of the current release + VersionModifier = "alpha6" // Modifier component of the current release VersionKeyCreated = "ErigonVersionCreated" VersionKeyFinished = "ErigonVersionFinished" ) From 2e40cb0312b3fffb421ec0456606d34e2ee3217b Mon Sep 17 00:00:00 2001 From: Andrew Ashikhmin <34320705+yperbasis@users.noreply.github.com> Date: Tue, 10 Dec 2024 03:44:20 +0100 Subject: [PATCH 11/24] go.mod: holiman/uint256 v1.3.1 => v1.3.2 (#13053) See https://github.com/holiman/uint256/releases/tag/v1.3.2 --- erigon-lib/go.mod | 2 +- erigon-lib/go.sum | 4 ++-- go.mod | 2 +- go.sum | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/erigon-lib/go.mod b/erigon-lib/go.mod index 3d047f42c5c..a1183f858fe 100644 --- a/erigon-lib/go.mod +++ b/erigon-lib/go.mod @@ -36,7 +36,7 @@ require ( github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 github.com/hashicorp/go-retryablehttp v0.7.7 github.com/holiman/bloomfilter/v2 v2.0.3 - github.com/holiman/uint256 v1.3.1 + github.com/holiman/uint256 v1.3.2 github.com/nyaosorg/go-windows-shortcut v0.0.0-20220529122037-8b0c89bca4c4 github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 github.com/pelletier/go-toml/v2 v2.2.3 diff --git a/erigon-lib/go.sum b/erigon-lib/go.sum index f1558ed545f..6d99de06a16 100644 --- a/erigon-lib/go.sum +++ b/erigon-lib/go.sum @@ -261,8 +261,8 @@ github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFO github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= -github.com/holiman/uint256 v1.3.1 h1:JfTzmih28bittyHM8z360dCjIA9dbPIBlcTI6lmctQs= -github.com/holiman/uint256 v1.3.1/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E= +github.com/holiman/uint256 v1.3.2 h1:a9EgMPSC1AAaj1SZL5zIQD3WbwTuHrMGOerLjGmM/TA= +github.com/holiman/uint256 v1.3.2/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huandu/xstrings v1.0.0/go.mod h1:4qWG/gcEcfX4z/mBDHJ++3ReCw9ibxbsNJbcucJdbSo= github.com/huandu/xstrings v1.2.0/go.mod h1:DvyZB1rfVYsBIigL8HwpZgxHwXozlTgGqn63UyNX5k4= diff --git a/go.mod b/go.mod index 40c3e76e5d8..656d9257fe1 100644 --- a/go.mod +++ b/go.mod @@ -53,7 +53,7 @@ require ( github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 github.com/hashicorp/golang-lru/arc/v2 v2.0.7 github.com/hashicorp/golang-lru/v2 v2.0.7 - github.com/holiman/uint256 v1.3.1 + github.com/holiman/uint256 v1.3.2 github.com/huandu/xstrings v1.5.0 github.com/huin/goupnp v1.3.0 github.com/jackpal/go-nat-pmp v1.0.2 diff --git a/go.sum b/go.sum index fbc4315e5a6..95b49b8fdb2 100644 --- a/go.sum +++ b/go.sum @@ -472,8 +472,8 @@ github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyf github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= github.com/holiman/uint256 v1.2.0/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25ApIH5Jw= -github.com/holiman/uint256 v1.3.1 h1:JfTzmih28bittyHM8z360dCjIA9dbPIBlcTI6lmctQs= -github.com/holiman/uint256 v1.3.1/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E= +github.com/holiman/uint256 v1.3.2 h1:a9EgMPSC1AAaj1SZL5zIQD3WbwTuHrMGOerLjGmM/TA= +github.com/holiman/uint256 v1.3.2/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huandu/xstrings v1.0.0/go.mod h1:4qWG/gcEcfX4z/mBDHJ++3ReCw9ibxbsNJbcucJdbSo= github.com/huandu/xstrings v1.2.0/go.mod h1:DvyZB1rfVYsBIigL8HwpZgxHwXozlTgGqn63UyNX5k4= From dce89b3b8e2dc39834102245d48aec1647880cf5 Mon Sep 17 00:00:00 2001 From: Giulio rebuffo Date: Tue, 10 Dec 2024 04:19:29 +0100 Subject: [PATCH 12/24] Caplin: Bump limits from 10MiB to 15Mib (#13058) --- cl/clparams/config.go | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/cl/clparams/config.go b/cl/clparams/config.go index 67d0cb99f91..ac093f7f89b 100644 --- a/cl/clparams/config.go +++ b/cl/clparams/config.go @@ -105,11 +105,12 @@ const ( ) const ( - MaxDialTimeout = 15 * time.Second - VersionLength int = 4 - MaxChunkSize uint64 = 1 << 20 // 1 MiB - ReqTimeout time.Duration = 10 * time.Second - RespTimeout time.Duration = 15 * time.Second + MaxDialTimeout = 15 * time.Second + VersionLength int = 4 + // 15 MiB + MaxChunkSize uint64 = 15728640 + ReqTimeout time.Duration = 10 * time.Second + RespTimeout time.Duration = 15 * time.Second ) const ( @@ -210,8 +211,8 @@ type NetworkConfig struct { var NetworkConfigs map[NetworkType]NetworkConfig = map[NetworkType]NetworkConfig{ MainnetNetwork: { - GossipMaxSize: 1 << 20, // 1 MiB - GossipMaxSizeBellatrix: 10485760, + GossipMaxSize: 15728640, + GossipMaxSizeBellatrix: 15728640, MaxChunkSize: MaxChunkSize, AttestationSubnetCount: 64, AttestationPropagationSlotRange: 32, @@ -229,9 +230,9 @@ var NetworkConfigs map[NetworkType]NetworkConfig = map[NetworkType]NetworkConfig }, SepoliaNetwork: { - GossipMaxSize: 1 << 20, // 1 MiB - GossipMaxSizeBellatrix: 10485760, - MaxChunkSize: 1 << 20, // 1 MiB + GossipMaxSize: 15728640, + GossipMaxSizeBellatrix: 15728640, + MaxChunkSize: 15728640, AttestationSubnetCount: 64, AttestationPropagationSlotRange: 32, MaxRequestBlocks: 1 << 10, // 1024 @@ -248,9 +249,9 @@ var NetworkConfigs map[NetworkType]NetworkConfig = map[NetworkType]NetworkConfig }, GnosisNetwork: { - GossipMaxSize: 1 << 20, // 1 MiB - GossipMaxSizeBellatrix: 10485760, - MaxChunkSize: 1 << 20, // 1 MiB + GossipMaxSize: 15728640, // 15 MiB + GossipMaxSizeBellatrix: 15728640, + MaxChunkSize: 15728640, // 15 MiB AttestationSubnetCount: 64, AttestationPropagationSlotRange: 32, MaxRequestBlocks: 1 << 10, // 1024 @@ -267,9 +268,9 @@ var NetworkConfigs map[NetworkType]NetworkConfig = map[NetworkType]NetworkConfig }, ChiadoNetwork: { - GossipMaxSize: 1 << 20, // 1 MiB - GossipMaxSizeBellatrix: 10485760, - MaxChunkSize: 1 << 20, // 1 MiB + GossipMaxSize: 15728640, // 15 MiB + GossipMaxSizeBellatrix: 15728640, + MaxChunkSize: 15728640, // 15 MiB AttestationSubnetCount: 64, AttestationPropagationSlotRange: 32, MaxRequestBlocks: 1 << 10, // 1024 @@ -286,9 +287,9 @@ var NetworkConfigs map[NetworkType]NetworkConfig = map[NetworkType]NetworkConfig }, HoleskyNetwork: { - GossipMaxSize: 1 << 20, // 1 MiB - GossipMaxSizeBellatrix: 10485760, - MaxChunkSize: 1 << 20, // 1 MiB + GossipMaxSize: 15728640, // 15 MiB + GossipMaxSizeBellatrix: 15728640, + MaxChunkSize: 15728640, // 15 MiB AttestationSubnetCount: 64, AttestationPropagationSlotRange: 32, MaxRequestBlocks: 1 << 10, // 1024 From c4bd853ea57fd760dd57fa4d54c0599d73f8ed12 Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Tue, 10 Dec 2024 00:31:37 -0300 Subject: [PATCH 13/24] Generalize iterator exhausted error (#13060) As part of https://github.com/erigontech/erigon/pull/12907 I'll have other iterator-like sequence implementations. It makes sense to generalize the ErrEliasFanoIterExhausted and move it to a common package and reuse it, rather than making a bunch of IteratorExhausted-like for each implementation. --- erigon-lib/kv/stream/stream_interface.go | 6 ++++++ erigon-lib/recsplit/eliasfano32/elias_fano.go | 6 ++---- erigon-lib/recsplit/eliasfano32/elias_fano_test.go | 4 ++-- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/erigon-lib/kv/stream/stream_interface.go b/erigon-lib/kv/stream/stream_interface.go index 6974c58e468..819154853a0 100644 --- a/erigon-lib/kv/stream/stream_interface.go +++ b/erigon-lib/kv/stream/stream_interface.go @@ -16,6 +16,8 @@ package stream +import "errors" + // Streams - it's iterator-like composable high-level abstraction - which designed for inter-process communication and between processes: // - cancelable // - return errors @@ -38,6 +40,10 @@ package stream // check in loops on stream. Duo has very limited API - user has no way to // terminate it - but user can specify more strict conditions when creating stream (then server knows better when to stop) +// Indicates the iterator has no more elements. Meant to be returned by implementations of Next() +// when there are no more elements. +var ErrIteratorExhausted = errors.New("iterator exhausted") + // Uno - return 1 item. Example: // // for s.HasNext() { diff --git a/erigon-lib/recsplit/eliasfano32/elias_fano.go b/erigon-lib/recsplit/eliasfano32/elias_fano.go index 37580963e5c..fb00f12b300 100644 --- a/erigon-lib/recsplit/eliasfano32/elias_fano.go +++ b/erigon-lib/recsplit/eliasfano32/elias_fano.go @@ -18,7 +18,6 @@ package eliasfano32 import ( "encoding/binary" - "errors" "fmt" "io" "math" @@ -27,6 +26,7 @@ import ( "unsafe" "github.com/erigontech/erigon-lib/common/bitutil" + "github.com/erigontech/erigon-lib/kv/stream" ) // EliasFano algo overview https://www.antoniomallia.it/sorted-integers-compression-with-elias-fano-encoding.html @@ -44,8 +44,6 @@ const ( superQSize uint64 = 1 + qPerSuperQ/2 // 1 + 64/2 = 33 ) -var ErrEliasFanoIterExhausted = errors.New("elias fano iterator exhausted") - // EliasFano can be used to encode one monotone sequence type EliasFano struct { data []uint64 @@ -486,7 +484,7 @@ func (efi *EliasFanoIter) decrement() { func (efi *EliasFanoIter) Next() (uint64, error) { if !efi.HasNext() { - return 0, ErrEliasFanoIterExhausted + return 0, stream.ErrIteratorExhausted } idx64, shift := efi.lowerIdx/64, efi.lowerIdx%64 lower := efi.lowerBits[idx64] >> shift diff --git a/erigon-lib/recsplit/eliasfano32/elias_fano_test.go b/erigon-lib/recsplit/eliasfano32/elias_fano_test.go index 89ec594603e..89976581072 100644 --- a/erigon-lib/recsplit/eliasfano32/elias_fano_test.go +++ b/erigon-lib/recsplit/eliasfano32/elias_fano_test.go @@ -355,7 +355,7 @@ func TestIterator(t *testing.T) { require.NoError(t, err) } _, err := it.Next() - require.ErrorIs(t, err, ErrEliasFanoIterExhausted) + require.ErrorIs(t, err, stream.ErrIteratorExhausted) it = ef.ReverseIterator() for range offsets { @@ -363,7 +363,7 @@ func TestIterator(t *testing.T) { require.NoError(t, err) } _, err = it.Next() - require.ErrorIs(t, err, ErrEliasFanoIterExhausted) + require.ErrorIs(t, err, stream.ErrIteratorExhausted) }) t.Run("article-example1", func(t *testing.T) { From 6da5497e26730b1ee21c48b428f23b2952e384bf Mon Sep 17 00:00:00 2001 From: Noisy <125606576+donatik27@users.noreply.github.com> Date: Tue, 10 Dec 2024 08:57:54 +0100 Subject: [PATCH 14/24] Spelling and Formatting Improvements in Documentation (#13002) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit availible → available seperate → separate reather → rather intefere → interfere From 9009f3596ae4aadf7eb1c5263ab82872ae21d419 Mon Sep 17 00:00:00 2001 From: Michelangelo Riccobene Date: Tue, 10 Dec 2024 08:58:12 +0100 Subject: [PATCH 15/24] qa-tests: activate constrained-tip-tracking test on polygon (#13011) --- .../workflows/qa-constrained-tip-tracking.yml | 25 +++++++++++++------ 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/.github/workflows/qa-constrained-tip-tracking.yml b/.github/workflows/qa-constrained-tip-tracking.yml index b0b6d4505a7..434e2c39f45 100644 --- a/.github/workflows/qa-constrained-tip-tracking.yml +++ b/.github/workflows/qa-constrained-tip-tracking.yml @@ -7,15 +7,26 @@ on: jobs: constrained-tip-tracking-test: - runs-on: [self-hosted, Erigon3] timeout-minutes: 600 + strategy: + fail-fast: false + matrix: + include: + - chain: mainnet + backend: Erigon3 + cgroup_name: constrained_res_32G + - chain: bor-mainnet + backend: Polygon + cgroup_name: constrained_res_64G + runs-on: [ self-hosted, "${{ matrix.backend }}" ] env: ERIGON_REFERENCE_DATA_DIR: /opt/erigon-versions/reference-version/datadir ERIGON_TESTBED_DATA_DIR: /opt/erigon-testbed/datadir ERIGON_QA_PATH: /home/qarunner/erigon-qa TRACKING_TIME_SECONDS: 14400 # 4 hours TOTAL_TIME_SECONDS: 28800 # 8 hours - CHAIN: mainnet + CHAIN: ${{ matrix.chain }} + CGROUP_NAME: ${{ matrix.cgroup_name }} steps: - name: Check out repository @@ -44,15 +55,15 @@ jobs: set +e # Disable exit on error # Run Erigon under memory constraints, wait sync and check ability to maintain sync - cgexec -g memory:constrained_res_32G python3 $ERIGON_QA_PATH/test_system/qa-tests/tip-tracking/run_and_check_tip_tracking.py \ + cgexec -g memory:$CGROUP_NAME python3 $ERIGON_QA_PATH/test_system/qa-tests/tip-tracking/run_and_check_tip_tracking.py \ ${{ github.workspace }}/build/bin $ERIGON_TESTBED_DATA_DIR $TRACKING_TIME_SECONDS $TOTAL_TIME_SECONDS Erigon3 $CHAIN standard_node statistics # Capture monitoring script exit status test_exit_status=$? # Save the subsection reached status - echo "::set-output name=test_executed::true" - + echo "test_executed=true" >> $GITHUB_OUTPUT + # Clean up Erigon process if it's still running if kill -0 $ERIGON_PID 2> /dev/null; then echo "Terminating Erigon" @@ -94,14 +105,14 @@ jobs: if: steps.test_step.outputs.test_executed == 'true' uses: actions/upload-artifact@v4 with: - name: test-results + name: test-results-${{ env.CHAIN }} path: ${{ github.workspace }}/result-${{ env.CHAIN }}.json - name: Upload Erigon full log if: steps.test_step.outputs.test_executed == 'true' uses: actions/upload-artifact@v4 with: - name: erigon-log + name: erigon-log-${{ env.CHAIN }} path: | ${{ env.ERIGON_TESTBED_DATA_DIR }}/logs/erigon.log ${{ env.ERIGON_TESTBED_DATA_DIR }}/proc_stat.log From 27d136b56bd05fb93e9a3e733dd488db272830e7 Mon Sep 17 00:00:00 2001 From: Giulio rebuffo Date: Tue, 10 Dec 2024 13:40:40 +0100 Subject: [PATCH 16/24] Caplin: remove beacon api limiters and open state snapshots after processing (#13062) --- cl/antiquary/antiquary.go | 2 ++ cl/beacon/handler/validators.go | 24 ------------------------ 2 files changed, 2 insertions(+), 24 deletions(-) diff --git a/cl/antiquary/antiquary.go b/cl/antiquary/antiquary.go index da1a6f97c83..bab10cb5e86 100644 --- a/cl/antiquary/antiquary.go +++ b/cl/antiquary/antiquary.go @@ -217,6 +217,8 @@ func (a *Antiquary) Loop() error { } } + a.stateSn.OpenFolder() + frozenSlots := a.sn.BlocksAvailable() if frozenSlots != 0 { if err := beacon_indicies.PruneBlocks(a.ctx, tx, frozenSlots); err != nil { diff --git a/cl/beacon/handler/validators.go b/cl/beacon/handler/validators.go index c30134e356d..276e0f7d9f1 100644 --- a/cl/beacon/handler/validators.go +++ b/cl/beacon/handler/validators.go @@ -174,16 +174,10 @@ func (s validatorStatus) String() string { } } -const maxValidatorsLookupFilter = 128 - func parseStatuses(s []string) ([]validatorStatus, error) { seenAlready := make(map[validatorStatus]struct{}) statuses := make([]validatorStatus, 0, len(s)) - if len(s) > maxValidatorsLookupFilter { - return nil, beaconhttp.NewEndpointError(http.StatusBadRequest, errors.New("too many statuses requested")) - } - for _, status := range s { s, err := validatorStatusFromString(status) if err != nil { @@ -248,10 +242,6 @@ func (a *ApiHandler) GetEthV1BeaconStatesValidators(w http.ResponseWriter, r *ht return } - if len(validatorIds) > maxValidatorsLookupFilter { - http.Error(w, errors.New("too many validators requested").Error(), http.StatusBadRequest) - return - } a.writeValidatorsResponse(w, r, tx, blockId, blockRoot, validatorIds, queryFilters) } @@ -288,11 +278,6 @@ func (a *ApiHandler) PostEthV1BeaconStatesValidators(w http.ResponseWriter, r *h return } - if len(req.Ids) > maxValidatorsLookupFilter { - http.Error(w, errors.New("too many validators requested").Error(), http.StatusBadRequest) - return - } - a.writeValidatorsResponse(w, r, tx, blockId, blockRoot, req.Ids, req.Statuses) } @@ -536,11 +521,6 @@ func (a *ApiHandler) PostEthV1BeaconValidatorsBalances(w http.ResponseWriter, r return } - if len(validatorIds) > maxValidatorsLookupFilter { - http.Error(w, errors.New("too many validators requested").Error(), http.StatusBadRequest) - return - } - a.getValidatorBalances(r.Context(), w, blockId, validatorIds) } @@ -558,10 +538,6 @@ func (a *ApiHandler) GetEthV1BeaconValidatorsBalances(w http.ResponseWriter, r * return } - if len(validatorIds) > maxValidatorsLookupFilter { - http.Error(w, errors.New("too many validators requested").Error(), http.StatusBadRequest) - return - } a.getValidatorBalances(r.Context(), w, blockId, validatorIds) } From aba14b39bf0ed12367d5862b1cb2f8648b83a4fc Mon Sep 17 00:00:00 2001 From: Giulio rebuffo Date: Tue, 10 Dec 2024 14:21:09 +0100 Subject: [PATCH 17/24] Increase default gas limit from 30MN to 36MN (#13057) This will pump the price to 6000$ so it is very important. --- cl/clparams/config.go | 11 +++++------ eth/ethconfig/config.go | 2 +- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/cl/clparams/config.go b/cl/clparams/config.go index ac093f7f89b..25aeaeba310 100644 --- a/cl/clparams/config.go +++ b/cl/clparams/config.go @@ -532,11 +532,10 @@ type BeaconChainConfig struct { MinSyncCommitteeParticipants uint64 `yaml:"MIN_SYNC_COMMITTEE_PARTICIPANTS" spec:"true" json:"MIN_SYNC_COMMITTEE_PARTICIPANTS,string"` // MinSyncCommitteeParticipants defines the minimum amount of sync committee participants for which the light client acknowledges the signature. // Bellatrix - TerminalBlockHash libcommon.Hash `yaml:"TERMINAL_BLOCK_HASH" spec:"true" json:"TERMINAL_BLOCK_HASH"` // TerminalBlockHash of beacon chain. - TerminalBlockHashActivationEpoch uint64 `yaml:"TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH" spec:"true" json:"TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH,string"` // TerminalBlockHashActivationEpoch of beacon chain. - TerminalTotalDifficulty string `yaml:"TERMINAL_TOTAL_DIFFICULTY" spec:"true" json:"TERMINAL_TOTAL_DIFFICULTY"` // TerminalTotalDifficulty is part of the experimental Bellatrix spec. This value is type is currently TBD. - DefaultFeeRecipient libcommon.Address `json:"-"` // DefaultFeeRecipient where the transaction fee goes to. - DefaultBuilderGasLimit uint64 `json:"-"` // DefaultBuilderGasLimit is the default used to set the gaslimit for the Builder APIs, typically at around 30M wei. + TerminalBlockHash libcommon.Hash `yaml:"TERMINAL_BLOCK_HASH" spec:"true" json:"TERMINAL_BLOCK_HASH"` // TerminalBlockHash of beacon chain. + TerminalBlockHashActivationEpoch uint64 `yaml:"TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH" spec:"true" json:"TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH,string"` // TerminalBlockHashActivationEpoch of beacon chain. + TerminalTotalDifficulty string `yaml:"TERMINAL_TOTAL_DIFFICULTY" spec:"true" json:"TERMINAL_TOTAL_DIFFICULTY"` // TerminalTotalDifficulty is part of the experimental Bellatrix spec. This value is type is currently TBD. + DefaultBuilderGasLimit uint64 `json:"-"` // DefaultBuilderGasLimit is the default used to set the gaslimit for the Builder APIs, typically at around 30M wei. // Mev-boost circuit breaker MaxBuilderConsecutiveMissedSlots uint64 `json:"-"` // MaxBuilderConsecutiveMissedSlots defines the number of consecutive skip slot to fallback from using relay/builder to local execution engine for block construction. @@ -805,7 +804,7 @@ var MainnetBeaconConfig BeaconChainConfig = BeaconChainConfig{ TerminalBlockHashActivationEpoch: 18446744073709551615, TerminalBlockHash: [32]byte{}, TerminalTotalDifficulty: "58750000000000000000000", // Estimated: Sept 15, 2022 - DefaultBuilderGasLimit: uint64(30000000), + DefaultBuilderGasLimit: uint64(36000000), // Mevboost circuit breaker MaxBuilderConsecutiveMissedSlots: 3, diff --git a/eth/ethconfig/config.go b/eth/ethconfig/config.go index 3396a787d1e..a36daa2c1ec 100644 --- a/eth/ethconfig/config.go +++ b/eth/ethconfig/config.go @@ -90,7 +90,7 @@ var Defaults = Config{ NetworkID: 1, Prune: prune.DefaultMode, Miner: params.MiningConfig{ - GasLimit: 30_000_000, + GasLimit: 36_000_000, GasPrice: big.NewInt(params.GWei), Recommit: 3 * time.Second, }, From f453a3e0cf41542016d443a7f45007b09c8263d0 Mon Sep 17 00:00:00 2001 From: Andrew Ashikhmin <34320705+yperbasis@users.noreply.github.com> Date: Tue, 10 Dec 2024 15:33:41 +0100 Subject: [PATCH 18/24] deps: update go-libp2p (#13068) This is to fix https://github.com/erigontech/erigon/security/dependabot/37 --- go.mod | 59 +++++++++++------------ go.sum | 147 +++++++++++++++++++++++++-------------------------------- 2 files changed, 95 insertions(+), 111 deletions(-) diff --git a/go.mod b/go.mod index 656d9257fe1..2b8348ef6dd 100644 --- a/go.mod +++ b/go.mod @@ -60,12 +60,12 @@ require ( github.com/jedib0t/go-pretty/v6 v6.5.9 github.com/json-iterator/go v1.1.12 github.com/julienschmidt/httprouter v1.3.0 - github.com/klauspost/compress v1.17.9 - github.com/libp2p/go-libp2p v0.34.0 + github.com/klauspost/compress v1.17.11 + github.com/libp2p/go-libp2p v0.37.2 github.com/libp2p/go-libp2p-mplex v0.9.0 github.com/libp2p/go-libp2p-pubsub v0.11.0 github.com/maticnetwork/crand v1.0.2 - github.com/multiformats/go-multiaddr v0.12.4 + github.com/multiformats/go-multiaddr v0.13.0 github.com/nxadm/tail v1.4.11 github.com/pelletier/go-toml v1.9.5 github.com/pelletier/go-toml/v2 v2.2.3 @@ -115,6 +115,7 @@ require ( github.com/elastic/go-freelru v0.13.0 // indirect github.com/erigontech/speedtest v0.0.2 // indirect github.com/go-ole/go-ole v1.2.6 // indirect + github.com/go-task/slim-sprig/v3 v3.0.0 // indirect github.com/go-viper/mapstructure/v2 v2.2.1 // indirect github.com/google/uuid v1.6.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect @@ -123,6 +124,7 @@ require ( github.com/nyaosorg/go-windows-shortcut v0.0.0-20220529122037-8b0c89bca4c4 // indirect github.com/tklauser/go-sysconf v0.3.14 // indirect github.com/tklauser/numcpus v0.8.0 // indirect + github.com/wlynxg/anet v0.0.5 // indirect github.com/yusufpapurcu/wmi v1.2.4 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117 // indirect @@ -167,7 +169,7 @@ require ( github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/dustin/go-humanize v1.0.1 // indirect - github.com/elastic/gosigar v0.14.2 // indirect + github.com/elastic/gosigar v0.14.3 // indirect github.com/erigontech/erigon-snapshot v1.3.1-0.20241023024258-f64407a77e8e // indirect github.com/flynn/noise v1.1.0 // indirect github.com/francoispqt/gojay v1.2.13 // indirect @@ -175,15 +177,14 @@ require ( github.com/garslo/gogen v0.0.0-20170307003452-d6ebae628c7c // indirect github.com/go-llsqlite/adapter v0.0.0-20230927005056-7f5ce7f0c916 // indirect github.com/go-llsqlite/crawshaw v0.5.2-0.20240425034140-f30eb7704568 // indirect - github.com/go-logr/logr v1.3.0 // indirect + github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect github.com/go-stack/stack v1.8.1 - github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/google/gopacket v1.1.19 // indirect - github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd // indirect + github.com/google/pprof v0.0.0-20241017200806-017d972448fc // indirect github.com/holiman/bloomfilter/v2 v2.0.3 // indirect github.com/ianlancetaylor/cgosymbolizer v0.0.0-20240503222823-736c933a666d // indirect github.com/imdario/mergo v0.3.11 // indirect @@ -191,12 +192,12 @@ require ( github.com/ipfs/go-cid v0.4.1 // indirect github.com/ipfs/go-log/v2 v2.5.1 // indirect github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect - github.com/klauspost/cpuid/v2 v2.2.7 // indirect + github.com/klauspost/cpuid/v2 v2.2.8 // indirect github.com/koron/go-ssdp v0.0.4 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect github.com/libp2p/go-buffer-pool v0.1.0 // indirect - github.com/libp2p/go-flow-metrics v0.1.0 // indirect + github.com/libp2p/go-flow-metrics v0.2.0 // indirect github.com/libp2p/go-libp2p-asn-util v0.4.1 // indirect github.com/libp2p/go-mplex v0.7.0 // indirect github.com/libp2p/go-msgio v0.3.0 // indirect @@ -209,7 +210,7 @@ require ( github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect - github.com/miekg/dns v1.1.58 // indirect + github.com/miekg/dns v1.1.62 // indirect github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b // indirect github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc // indirect github.com/minio/sha256-simd v1.0.1 // indirect @@ -222,40 +223,40 @@ require ( github.com/mschoch/smat v0.2.0 // indirect github.com/multiformats/go-base32 v0.1.0 // indirect github.com/multiformats/go-base36 v0.2.0 // indirect - github.com/multiformats/go-multiaddr-dns v0.3.1 // indirect + github.com/multiformats/go-multiaddr-dns v0.4.1 // indirect github.com/multiformats/go-multiaddr-fmt v0.1.0 // indirect github.com/multiformats/go-multibase v0.2.0 // indirect github.com/multiformats/go-multicodec v0.9.0 // indirect github.com/multiformats/go-multihash v0.2.3 // indirect - github.com/multiformats/go-multistream v0.5.0 // indirect + github.com/multiformats/go-multistream v0.6.0 // indirect github.com/multiformats/go-varint v0.0.7 // indirect github.com/ncruces/go-strftime v0.1.9 // indirect - github.com/onsi/ginkgo/v2 v2.15.0 // indirect + github.com/onsi/ginkgo/v2 v2.20.2 // indirect github.com/opencontainers/runtime-spec v1.2.0 // indirect github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect - github.com/pion/datachannel v1.5.6 // indirect - github.com/pion/dtls/v2 v2.2.11 // indirect - github.com/pion/ice/v2 v2.3.24 // indirect - github.com/pion/interceptor v0.1.29 // indirect + github.com/pion/datachannel v1.5.9 // indirect + github.com/pion/dtls/v2 v2.2.12 // indirect + github.com/pion/ice/v2 v2.3.36 // indirect + github.com/pion/interceptor v0.1.37 // indirect github.com/pion/logging v0.2.2 // indirect github.com/pion/mdns v0.0.12 // indirect github.com/pion/rtcp v1.2.14 // indirect - github.com/pion/rtp v1.8.6 // indirect - github.com/pion/sctp v1.8.16 // indirect + github.com/pion/rtp v1.8.9 // indirect + github.com/pion/sctp v1.8.33 // indirect github.com/pion/sdp/v3 v3.0.9 // indirect - github.com/pion/srtp/v2 v2.0.18 // indirect - github.com/pion/transport/v2 v2.2.5 // indirect + github.com/pion/srtp/v2 v2.0.20 // indirect + github.com/pion/transport/v2 v2.2.10 // indirect github.com/pion/turn/v2 v2.1.6 // indirect - github.com/pion/webrtc/v3 v3.2.40 // indirect + github.com/pion/webrtc/v3 v3.3.4 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/prometheus/client_golang v1.20.5 github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.55.0 // indirect + github.com/prometheus/common v0.60.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect - github.com/quic-go/qpack v0.4.0 // indirect - github.com/quic-go/quic-go v0.44.0 // indirect - github.com/quic-go/webtransport-go v0.8.0 // indirect + github.com/quic-go/qpack v0.5.1 // indirect + github.com/quic-go/quic-go v0.48.2 // indirect + github.com/quic-go/webtransport-go v0.8.1-0.20241018022711-4ac2c9250e66 // indirect github.com/raulk/go-watchdog v1.3.0 // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/rivo/uniseg v0.4.7 // indirect @@ -275,14 +276,14 @@ require ( go.etcd.io/bbolt v1.3.6 // indirect go.opentelemetry.io/otel v1.8.0 // indirect go.opentelemetry.io/otel/trace v1.8.0 // indirect - go.uber.org/dig v1.17.1 // indirect - go.uber.org/fx v1.21.1 // indirect + go.uber.org/dig v1.18.0 // indirect + go.uber.org/fx v1.23.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/mod v0.21.0 // indirect golang.org/x/text v0.20.0 // indirect golang.org/x/tools v0.26.0 // indirect gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect - lukechampine.com/blake3 v1.2.1 // indirect + lukechampine.com/blake3 v1.3.0 // indirect modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 // indirect modernc.org/libc v1.55.3 // indirect modernc.org/mathutil v1.6.0 // indirect diff --git a/go.sum b/go.sum index 95b49b8fdb2..ad8fccd3067 100644 --- a/go.sum +++ b/go.sum @@ -255,8 +255,8 @@ github.com/edsrzf/mmap-go v1.1.0/go.mod h1:19H/e8pUPLicwkyNgOykDXkJ9F0MHE+Z52B8E github.com/elastic/go-freelru v0.13.0 h1:TKKY6yCfNNNky7Pj9xZAOEpBcdNgZJfihEftOb55omg= github.com/elastic/go-freelru v0.13.0/go.mod h1:bSdWT4M0lW79K8QbX6XY2heQYSCqD7THoYf82pT/H3I= github.com/elastic/gosigar v0.12.0/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs= -github.com/elastic/gosigar v0.14.2 h1:Dg80n8cr90OZ7x+bAax/QjoW/XqTI11RmA79ZwIm9/4= -github.com/elastic/gosigar v0.14.2/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs= +github.com/elastic/gosigar v0.14.3 h1:xwkKwPia+hSfg9GqrCUKYdId102m9qTJIIr7egmK/uo= +github.com/elastic/gosigar v0.14.3/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs= github.com/emicklei/dot v1.6.2 h1:08GN+DD79cy/tzN6uLCT84+2Wk9u+wvqP+Hkx/dIR8A= github.com/emicklei/dot v1.6.2/go.mod h1:DeV7GvQtIw4h2u73RKBkkFdvVAz0D9fzeJrgPW6gy/s= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -327,8 +327,8 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9 github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= -github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= @@ -338,8 +338,8 @@ github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5Nq github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= -github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= -github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= +github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= +github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= github.com/go-test/deep v1.1.1 h1:0r/53hagsehfO4bzD2Pgr/+RgHqhmf+k1Bpse2cTu1U= github.com/go-test/deep v1.1.1/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss= @@ -431,8 +431,8 @@ github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd h1:gbpYu9NMq8jhDVbvlGkMFWCjLFlqqEZjEmObmhUy6Vo= -github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw= +github.com/google/pprof v0.0.0-20241017200806-017d972448fc h1:NGyrhhFhwvRAZg02jnYVg3GBQy0qGBKmFQJwaPmpmxs= +github.com/google/pprof v0.0.0-20241017200806-017d972448fc/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -518,10 +518,10 @@ github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8 github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= -github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= -github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM= -github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= +github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc= +github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= +github.com/klauspost/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM= +github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/koron/go-ssdp v0.0.4 h1:1IDwrghSKYM7yLf7XCzbByg2sJ/JcNOZRXS2jczTwz0= github.com/koron/go-ssdp v0.0.4/go.mod h1:oDXq+E5IL5q0U8uSBcoAXzTzInwy5lEgC91HoKtbmZk= @@ -544,10 +544,10 @@ github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7 github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= -github.com/libp2p/go-flow-metrics v0.1.0 h1:0iPhMI8PskQwzh57jB9WxIuIOQ0r+15PChFGkx3Q3WM= -github.com/libp2p/go-flow-metrics v0.1.0/go.mod h1:4Xi8MX8wj5aWNDAZttg6UPmc0ZrnFNsMtpsYUClFtro= -github.com/libp2p/go-libp2p v0.34.0 h1:J+SL3DMz+zPz06OHSRt42GKA5n5hmwgY1l7ckLUz3+c= -github.com/libp2p/go-libp2p v0.34.0/go.mod h1:snyJQix4ET6Tj+LeI0VPjjxTtdWpeOhYt5lEY0KirkQ= +github.com/libp2p/go-flow-metrics v0.2.0 h1:EIZzjmeOE6c8Dav0sNv35vhZxATIXWZg6j/C08XmmDw= +github.com/libp2p/go-flow-metrics v0.2.0/go.mod h1:st3qqfu8+pMfh+9Mzqb2GTiwrAGjIPszEjZmtksN8Jc= +github.com/libp2p/go-libp2p v0.37.2 h1:Irh+n9aDPTLt9wJYwtlHu6AhMUipbC1cGoJtOiBqI9c= +github.com/libp2p/go-libp2p v0.37.2/go.mod h1:M8CRRywYkqC6xKHdZ45hmqVckBj5z4mRLIMLWReypz8= github.com/libp2p/go-libp2p-asn-util v0.4.1 h1:xqL7++IKD9TBFMgnLPZR6/6iYhawHKHl950SO9L6n94= github.com/libp2p/go-libp2p-asn-util v0.4.1/go.mod h1:d/NI6XZ9qxw67b4e+NgpQexCIiFYJjErASrYW4PFDN8= github.com/libp2p/go-libp2p-mplex v0.9.0 h1:R58pDRAmuBXkYugbSSXR9wrTX3+1pFM1xP2bLuodIq8= @@ -586,9 +586,8 @@ github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZ github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4= -github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= -github.com/miekg/dns v1.1.58 h1:ca2Hdkz+cDg/7eNF6V56jjzuZ4aCAE+DbVkILdQWG/4= -github.com/miekg/dns v1.1.58/go.mod h1:Ypv+3b/KadlvW9vJfXOTf300O4UqaHFzFCuHz+rPkBY= +github.com/miekg/dns v1.1.62 h1:cN8OuEF1/x5Rq6Np+h1epln8OiyPWV+lROx9LxcGgIQ= +github.com/miekg/dns v1.1.62/go.mod h1:mvDlcItzm+br7MToIKqkglaGhlFMHJ9DTNNWONWXbNQ= github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c h1:bzE/A84HN25pxAuk9Eej1Kz9OUelF97nAc82bDquQI8= github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c/go.mod h1:0SQS9kMwD2VsyFEB++InYyBJroV/FRmBgcydeSUcJms= github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b h1:z78hV3sbSMAUoyUMM0I83AUIT6Hu17AWfgjzIbtrYFc= @@ -624,11 +623,10 @@ github.com/multiformats/go-base32 v0.1.0/go.mod h1:Kj3tFY6zNr+ABYMqeUNeGvkIC/UYg github.com/multiformats/go-base36 v0.2.0 h1:lFsAbNOGeKtuKozrtBsAkSVhv1p9D0/qedU9rQyccr0= github.com/multiformats/go-base36 v0.2.0/go.mod h1:qvnKE++v+2MWCfePClUEjE78Z7P2a1UV0xHgWc0hkp4= github.com/multiformats/go-multiaddr v0.1.1/go.mod h1:aMKBKNEYmzmDmxfX88/vz+J5IU55txyt0p4aiWVohjo= -github.com/multiformats/go-multiaddr v0.2.0/go.mod h1:0nO36NvPpyV4QzvTLi/lafl2y95ncPj0vFwVF6k6wJ4= -github.com/multiformats/go-multiaddr v0.12.4 h1:rrKqpY9h+n80EwhhC/kkcunCZZ7URIF8yN1WEUt2Hvc= -github.com/multiformats/go-multiaddr v0.12.4/go.mod h1:sBXrNzucqkFJhvKOiwwLyqamGa/P5EIXNPLovyhQCII= -github.com/multiformats/go-multiaddr-dns v0.3.1 h1:QgQgR+LQVt3NPTjbrLLpsaT2ufAA2y0Mkk+QRVJbW3A= -github.com/multiformats/go-multiaddr-dns v0.3.1/go.mod h1:G/245BRQ6FJGmryJCrOuTdB37AMA5AMOVuO6NY3JwTk= +github.com/multiformats/go-multiaddr v0.13.0 h1:BCBzs61E3AGHcYYTv8dqRH43ZfyrqM8RXVPT8t13tLQ= +github.com/multiformats/go-multiaddr v0.13.0/go.mod h1:sBXrNzucqkFJhvKOiwwLyqamGa/P5EIXNPLovyhQCII= +github.com/multiformats/go-multiaddr-dns v0.4.1 h1:whi/uCLbDS3mSEUMb1MsoT4uzUeZB0N32yzufqS0i5M= +github.com/multiformats/go-multiaddr-dns v0.4.1/go.mod h1:7hfthtB4E4pQwirrz+J0CcDUfbWzTqEzVyYKKIKpgkc= github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E= github.com/multiformats/go-multiaddr-fmt v0.1.0/go.mod h1:hGtDIW4PU4BqJ50gW2quDuPVjyWNZxToGUh/HwTZYJo= github.com/multiformats/go-multibase v0.2.0 h1:isdYCVLvksgWlMW9OZRYJEa9pZETFivncJHmHnnd87g= @@ -638,9 +636,8 @@ github.com/multiformats/go-multicodec v0.9.0/go.mod h1:L3QTQvMIaVBkXOXXtVmYE+LI1 github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= github.com/multiformats/go-multihash v0.2.3 h1:7Lyc8XfX/IY2jWb/gI7JP+o7JEq9hOa7BFvVU9RSh+U= github.com/multiformats/go-multihash v0.2.3/go.mod h1:dXgKXCXjBzdscBLk9JkjINiEsCKRVch90MdaGiKsvSM= -github.com/multiformats/go-multistream v0.5.0 h1:5htLSLl7lvJk3xx3qT/8Zm9J4K8vEOf/QGkvOGQAyiE= -github.com/multiformats/go-multistream v0.5.0/go.mod h1:n6tMZiwiP2wUsR8DgfDWw1dydlEqV3l6N3/GBsX6ILA= -github.com/multiformats/go-varint v0.0.1/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= +github.com/multiformats/go-multistream v0.6.0 h1:ZaHKbsL404720283o4c/IHQXiS6gb8qAN5EIJ4PN5EA= +github.com/multiformats/go-multistream v0.6.0/go.mod h1:MOyoG5otO24cHIg8kf9QW2/NozURlkP/rvi2FQJyCPg= github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/nEGOHFS8= github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= @@ -658,11 +655,11 @@ github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= -github.com/onsi/ginkgo/v2 v2.15.0 h1:79HwNRBAZHOEwrczrgSOPy+eFTTlIGELKy5as+ClttY= -github.com/onsi/ginkgo/v2 v2.15.0/go.mod h1:HlxMHtYF57y6Dpf+mc5529KKmSq9h2FpCF+/ZkwUxKM= +github.com/onsi/ginkgo/v2 v2.20.2 h1:7NVCeyIWROIAheY21RLS+3j2bb52W0W82tkberYytp4= +github.com/onsi/ginkgo/v2 v2.20.2/go.mod h1:K9gyxPIlb+aIvnZ8bd9Ak+YP18w3APlR+5coaZoE2ag= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8= -github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= +github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k= +github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY= github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-spec v1.2.0 h1:z97+pHb3uELt/yiAWD691HNHQIF07bE7dzrbT927iTk= github.com/opencontainers/runtime-spec v1.2.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= @@ -677,15 +674,15 @@ github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNH github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= -github.com/pion/datachannel v1.5.6 h1:1IxKJntfSlYkpUj8LlYRSWpYiTTC02nUrOE8T3DqGeg= -github.com/pion/datachannel v1.5.6/go.mod h1:1eKT6Q85pRnr2mHiWHxJwO50SfZRtWHTsNIVb/NfGW4= +github.com/pion/datachannel v1.5.9 h1:LpIWAOYPyDrXtU+BW7X0Yt/vGtYxtXQ8ql7dFfYUVZA= +github.com/pion/datachannel v1.5.9/go.mod h1:kDUuk4CU4Uxp82NH4LQZbISULkX/HtzKa4P7ldf9izE= github.com/pion/dtls/v2 v2.2.7/go.mod h1:8WiMkebSHFD0T+dIU+UeBaoV7kDhOW5oDCzZ7WZ/F9s= -github.com/pion/dtls/v2 v2.2.11 h1:9U/dpCYl1ySttROPWJgqWKEylUdT0fXp/xst6JwY5Ks= -github.com/pion/dtls/v2 v2.2.11/go.mod h1:d9SYc9fch0CqK90mRk1dC7AkzzpwJj6u2GU3u+9pqFE= -github.com/pion/ice/v2 v2.3.24 h1:RYgzhH/u5lH0XO+ABatVKCtRd+4U1GEaCXSMjNr13tI= -github.com/pion/ice/v2 v2.3.24/go.mod h1:KXJJcZK7E8WzrBEYnV4UtqEZsGeWfHxsNqhVcVvgjxw= -github.com/pion/interceptor v0.1.29 h1:39fsnlP1U8gw2JzOFWdfCU82vHvhW9o0rZnZF56wF+M= -github.com/pion/interceptor v0.1.29/go.mod h1:ri+LGNjRUc5xUNtDEPzfdkmSqISixVTBF/z/Zms/6T4= +github.com/pion/dtls/v2 v2.2.12 h1:KP7H5/c1EiVAAKUmXyCzPiQe5+bCJrpOeKg/L05dunk= +github.com/pion/dtls/v2 v2.2.12/go.mod h1:d9SYc9fch0CqK90mRk1dC7AkzzpwJj6u2GU3u+9pqFE= +github.com/pion/ice/v2 v2.3.36 h1:SopeXiVbbcooUg2EIR8sq4b13RQ8gzrkkldOVg+bBsc= +github.com/pion/ice/v2 v2.3.36/go.mod h1:mBF7lnigdqgtB+YHkaY/Y6s6tsyRyo4u4rPGRuOjUBQ= +github.com/pion/interceptor v0.1.37 h1:aRA8Zpab/wE7/c0O3fh1PqY0AJI3fCSEM5lRWJVorwI= +github.com/pion/interceptor v0.1.37/go.mod h1:JzxbJ4umVTlZAf+/utHzNesY8tmRkM2lVmkS82TTj8Y= github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY= github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms= github.com/pion/mdns v0.0.12 h1:CiMYlY+O0azojWDmxdNr7ADGrnZ+V6Ilfner+6mSVK8= @@ -696,32 +693,30 @@ github.com/pion/rtcp v1.2.12/go.mod h1:sn6qjxvnwyAkkPzPULIbVqSKI5Dv54Rv7VG0kNxh9 github.com/pion/rtcp v1.2.14 h1:KCkGV3vJ+4DAJmvP0vaQShsb0xkRfWkO540Gy102KyE= github.com/pion/rtcp v1.2.14/go.mod h1:sn6qjxvnwyAkkPzPULIbVqSKI5Dv54Rv7VG0kNxh9L4= github.com/pion/rtp v1.8.3/go.mod h1:pBGHaFt/yW7bf1jjWAoUjpSNoDnw98KTMg+jWWvziqU= -github.com/pion/rtp v1.8.6 h1:MTmn/b0aWWsAzux2AmP8WGllusBVw4NPYPVFFd7jUPw= -github.com/pion/rtp v1.8.6/go.mod h1:pBGHaFt/yW7bf1jjWAoUjpSNoDnw98KTMg+jWWvziqU= -github.com/pion/sctp v1.8.13/go.mod h1:YKSgO/bO/6aOMP9LCie1DuD7m+GamiK2yIiPM6vH+GA= -github.com/pion/sctp v1.8.16 h1:PKrMs+o9EMLRvFfXq59WFsC+V8mN1wnKzqrv+3D/gYY= -github.com/pion/sctp v1.8.16/go.mod h1:P6PbDVA++OJMrVNg2AL3XtYHV4uD6dvfyOovCgMs0PE= +github.com/pion/rtp v1.8.9 h1:E2HX740TZKaqdcPmf4pw6ZZuG8u5RlMMt+l3dxeu6Wk= +github.com/pion/rtp v1.8.9/go.mod h1:pBGHaFt/yW7bf1jjWAoUjpSNoDnw98KTMg+jWWvziqU= +github.com/pion/sctp v1.8.33 h1:dSE4wX6uTJBcNm8+YlMg7lw1wqyKHggsP5uKbdj+NZw= +github.com/pion/sctp v1.8.33/go.mod h1:beTnqSzewI53KWoG3nqB282oDMGrhNxBdb+JZnkCwRM= github.com/pion/sdp/v3 v3.0.9 h1:pX++dCHoHUwq43kuwf3PyJfHlwIj4hXA7Vrifiq0IJY= github.com/pion/sdp/v3 v3.0.9/go.mod h1:B5xmvENq5IXJimIO4zfp6LAe1fD9N+kFv+V/1lOdz8M= -github.com/pion/srtp/v2 v2.0.18 h1:vKpAXfawO9RtTRKZJbG4y0v1b11NZxQnxRl85kGuUlo= -github.com/pion/srtp/v2 v2.0.18/go.mod h1:0KJQjA99A6/a0DOVTu1PhDSw0CXF2jTkqOoMg3ODqdA= +github.com/pion/srtp/v2 v2.0.20 h1:HNNny4s+OUmG280ETrCdgFndp4ufx3/uy85EawYEhTk= +github.com/pion/srtp/v2 v2.0.20/go.mod h1:0KJQjA99A6/a0DOVTu1PhDSw0CXF2jTkqOoMg3ODqdA= github.com/pion/stun v0.6.1 h1:8lp6YejULeHBF8NmV8e2787BogQhduZugh5PdhDyyN4= github.com/pion/stun v0.6.1/go.mod h1:/hO7APkX4hZKu/D0f2lHzNyvdkTGtIy3NDmLR7kSz/8= github.com/pion/transport v0.13.1 h1:/UH5yLeQtwm2VZIPjxwnNFxjS4DFhyLfS4GlfuKUzfA= github.com/pion/transport/v2 v2.2.1/go.mod h1:cXXWavvCnFF6McHTft3DWS9iic2Mftcz1Aq29pGcU5g= -github.com/pion/transport/v2 v2.2.2/go.mod h1:OJg3ojoBJopjEeECq2yJdXH9YVrUJ1uQ++NjXLOUorc= github.com/pion/transport/v2 v2.2.3/go.mod h1:q2U/tf9FEfnSBGSW6w5Qp5PFWRLRj3NjLhCCgpRK4p0= github.com/pion/transport/v2 v2.2.4/go.mod h1:q2U/tf9FEfnSBGSW6w5Qp5PFWRLRj3NjLhCCgpRK4p0= -github.com/pion/transport/v2 v2.2.5 h1:iyi25i/21gQck4hfRhomF6SktmUQjRsRW4WJdhfc3Kc= -github.com/pion/transport/v2 v2.2.5/go.mod h1:q2U/tf9FEfnSBGSW6w5Qp5PFWRLRj3NjLhCCgpRK4p0= +github.com/pion/transport/v2 v2.2.10 h1:ucLBLE8nuxiHfvkFKnkDQRYWYfp8ejf4YBOPfaQpw6Q= +github.com/pion/transport/v2 v2.2.10/go.mod h1:sq1kSLWs+cHW9E+2fJP95QudkzbK7wscs8yYgQToO5E= github.com/pion/transport/v3 v3.0.1/go.mod h1:UY7kiITrlMv7/IKgd5eTUcaahZx5oUN3l9SzK5f5xE0= -github.com/pion/transport/v3 v3.0.2 h1:r+40RJR25S9w3jbA6/5uEPTzcdn7ncyU44RWCbHkLg4= -github.com/pion/transport/v3 v3.0.2/go.mod h1:nIToODoOlb5If2jF9y2Igfx3PFYWfuXi37m0IlWa/D0= +github.com/pion/transport/v3 v3.0.7 h1:iRbMH05BzSNwhILHoBoAPxoB9xQgOaJk+591KC9P1o0= +github.com/pion/transport/v3 v3.0.7/go.mod h1:YleKiTZ4vqNxVwh77Z0zytYi7rXHl7j6uPLGhhz9rwo= github.com/pion/turn/v2 v2.1.3/go.mod h1:huEpByKKHix2/b9kmTAM3YoX6MKP+/D//0ClgUYR2fY= github.com/pion/turn/v2 v2.1.6 h1:Xr2niVsiPTB0FPtt+yAWKFUkU1eotQbGgpTIld4x1Gc= github.com/pion/turn/v2 v2.1.6/go.mod h1:huEpByKKHix2/b9kmTAM3YoX6MKP+/D//0ClgUYR2fY= -github.com/pion/webrtc/v3 v3.2.40 h1:Wtfi6AZMQg+624cvCXUuSmrKWepSB7zfgYDOYqsSOVU= -github.com/pion/webrtc/v3 v3.2.40/go.mod h1:M1RAe3TNTD1tzyvqHrbVODfwdPGSXOUo/OgpoGGJqFY= +github.com/pion/webrtc/v3 v3.3.4 h1:v2heQVnXTSqNRXcaFQVOhIOYkLMxOu1iJG8uy1djvkk= +github.com/pion/webrtc/v3 v3.3.4/go.mod h1:liNa+E1iwyzyXqNUwvoMRNQ10x8h8FOeJKL8RkIbamE= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -750,8 +745,8 @@ github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7q github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= -github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc= -github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8= +github.com/prometheus/common v0.60.0 h1:+V9PAREWNvJMAuJ1x1BaWl9dewMW4YrHZQbx0sJNllA= +github.com/prometheus/common v0.60.0/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= @@ -768,12 +763,12 @@ github.com/prysmaticlabs/gohashtree v0.0.3-alpha.0.20230502123415-aafd8b3ca202 h github.com/prysmaticlabs/gohashtree v0.0.3-alpha.0.20230502123415-aafd8b3ca202/go.mod h1:4pWaT30XoEx1j8KNJf3TV+E3mQkaufn7mf+jRNb/Fuk= github.com/quasilyte/go-ruleguard/dsl v0.3.22 h1:wd8zkOhSNr+I+8Qeciml08ivDt1pSXe60+5DqOpCjPE= github.com/quasilyte/go-ruleguard/dsl v0.3.22/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= -github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo= -github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A= -github.com/quic-go/quic-go v0.44.0 h1:So5wOr7jyO4vzL2sd8/pD9Kesciv91zSk8BoFngItQ0= -github.com/quic-go/quic-go v0.44.0/go.mod h1:z4cx/9Ny9UtGITIPzmPTXh1ULfOyWh4qGQlpnPcWmek= -github.com/quic-go/webtransport-go v0.8.0 h1:HxSrwun11U+LlmwpgM1kEqIqH90IT4N8auv/cD7QFJg= -github.com/quic-go/webtransport-go v0.8.0/go.mod h1:N99tjprW432Ut5ONql/aUhSLT0YVSlwHohQsuac9WaM= +github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI= +github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg= +github.com/quic-go/quic-go v0.48.2 h1:wsKXZPeGWpMpCGSWqOcqpW2wZYic/8T3aqiOID0/KWE= +github.com/quic-go/quic-go v0.48.2/go.mod h1:yBgs3rWBOADpga7F+jJsb6Ybg1LSYiQvwWlLX+/6HMs= +github.com/quic-go/webtransport-go v0.8.1-0.20241018022711-4ac2c9250e66 h1:4WFk6u3sOT6pLa1kQ50ZVdm8BQFgJNA117cepZxtLIg= +github.com/quic-go/webtransport-go v0.8.1-0.20241018022711-4ac2c9250e66/go.mod h1:Vp72IJajgeOL6ddqrAhmp7IM9zbTcgkQxD/YdxrVwMw= github.com/raulk/go-watchdog v1.3.0 h1:oUmdlHxdkXRJlwfG0O9omj8ukerm8MEQavSiDTEtBsk= github.com/raulk/go-watchdog v1.3.0/go.mod h1:fIvOnLbF0b0ZwkB9YU4mOW9Did//4vPZtDqv66NfsMU= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= @@ -869,7 +864,6 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= @@ -904,6 +898,9 @@ github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49u github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM= github.com/willf/bitset v1.1.9/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= github.com/willf/bitset v1.1.10/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= +github.com/wlynxg/anet v0.0.3/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA= +github.com/wlynxg/anet v0.0.5 h1:J3VJGi1gvo0JwZ/P1/Yc/8p63SoW98B5dHkYDmpgvvU= +github.com/wlynxg/anet v0.0.5/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA= github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4= github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM= github.com/xsleonard/go-merkle v1.1.0 h1:fHe1fuhJjGH22ZzVTAH0jqHLhTGhOq3wQjJN+8P0jQg= @@ -932,10 +929,10 @@ go.opentelemetry.io/otel v1.8.0/go.mod h1:2pkj+iMj0o03Y+cW6/m8Y4WkRdYN3AvCXCnzRM go.opentelemetry.io/otel/trace v1.8.0 h1:cSy0DF9eGI5WIfNwZ1q2iUyGj00tGzP24dE1lOlHrfY= go.opentelemetry.io/otel/trace v1.8.0/go.mod h1:0Bt3PXY8w+3pheS3hQUt+wow8b1ojPaTBoTCh2zIFI4= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/dig v1.17.1 h1:Tga8Lz8PcYNsWsyHMZ1Vm0OQOUaJNDyvPImgbAu9YSc= -go.uber.org/dig v1.17.1/go.mod h1:Us0rSJiThwCv2GteUN0Q7OKvU7n5J4dxZ9JKUXozFdE= -go.uber.org/fx v1.21.1 h1:RqBh3cYdzZS0uqwVeEjOX2p73dddLpym315myy/Bpb0= -go.uber.org/fx v1.21.1/go.mod h1:HT2M7d7RHo+ebKGh9NRcrsrHHfpZ60nW3QRubMRfv48= +go.uber.org/dig v1.18.0 h1:imUL1UiY0Mg4bqbFfsRQO5G4CGRBec/ZujWTvSVp3pw= +go.uber.org/dig v1.18.0/go.mod h1:Us0rSJiThwCv2GteUN0Q7OKvU7n5J4dxZ9JKUXozFdE= +go.uber.org/fx v1.23.0 h1:lIr/gYWQGfTwGcSXWXu4vP5Ws6iqnNEIY+F/aFzCKTg= +go.uber.org/fx v1.23.0/go.mod h1:o/D9n+2mLP6v1EG+qsdT1O8wKopYAsqZasju97SDFCU= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= @@ -967,11 +964,8 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE= -golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= -golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= -golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ= golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1062,11 +1056,8 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.13.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= -golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= -golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo= golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -1144,7 +1135,6 @@ golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1164,11 +1154,8 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -1177,11 +1164,8 @@ golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= -golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o= golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= -golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= -golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1193,7 +1177,6 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= @@ -1412,8 +1395,8 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -lukechampine.com/blake3 v1.2.1 h1:YuqqRuaqsGV71BV/nm9xlI0MKUv4QC54jQnBChWbGnI= -lukechampine.com/blake3 v1.2.1/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k= +lukechampine.com/blake3 v1.3.0 h1:sJ3XhFINmHSrYCgl958hscfIa3bw8x4DqMP3u1YvoYE= +lukechampine.com/blake3 v1.3.0/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k= modernc.org/cc/v4 v4.21.4 h1:3Be/Rdo1fpr8GrQ7IVw9OHtplU4gWbb+wNgeoBMmGLQ= modernc.org/cc/v4 v4.21.4/go.mod h1:HM7VJTZbUCR3rV8EYBi9wxnJ0ZBRiGE5OeGXNA0IsLQ= modernc.org/ccgo/v4 v4.19.2 h1:lwQZgvboKD0jBwdaeVCTouxhxAyN6iawF3STraAal8Y= From 43813d81bbec93fdba789c14407b0247d8095dce Mon Sep 17 00:00:00 2001 From: Giulio rebuffo Date: Tue, 10 Dec 2024 21:54:58 +0100 Subject: [PATCH 19/24] Added engine API warnings when --externalcl is on if no CL is connected (#13059) --- .../engine_logs_spammer/engine_log_spammer.go | 52 +++++++++++++++++++ turbo/engineapi/engine_server.go | 22 ++++++++ 2 files changed, 74 insertions(+) create mode 100644 turbo/engineapi/engine_logs_spammer/engine_log_spammer.go diff --git a/turbo/engineapi/engine_logs_spammer/engine_log_spammer.go b/turbo/engineapi/engine_logs_spammer/engine_log_spammer.go new file mode 100644 index 00000000000..431aa850d3e --- /dev/null +++ b/turbo/engineapi/engine_logs_spammer/engine_log_spammer.go @@ -0,0 +1,52 @@ +package engine_logs_spammer + +import ( + "context" + "sync/atomic" + "time" + + "github.com/erigontech/erigon-lib/chain" + "github.com/erigontech/erigon-lib/log/v3" +) + +type EngineLogsSpammer struct { + lastRequestTime atomic.Value + logger log.Logger + chainConfig *chain.Config +} + +func NewEngineLogsSpammer(logger log.Logger, chainConfig *chain.Config) *EngineLogsSpammer { + lastRequestTimeAtomic := atomic.Value{} + lastRequestTimeAtomic.Store(time.Now()) + return &EngineLogsSpammer{ + logger: logger, + chainConfig: chainConfig, + lastRequestTime: lastRequestTimeAtomic, + } +} + +func (e *EngineLogsSpammer) Start(ctx context.Context) { + e.lastRequestTime.Store(time.Now()) + logSpamInterval := 20 * time.Second + if !e.chainConfig.TerminalTotalDifficultyPassed { + return + } + go func() { + intervalSpam := time.NewTicker(logSpamInterval) + defer intervalSpam.Stop() + for { + select { + case <-ctx.Done(): + return + case <-intervalSpam.C: + if time.Since(e.lastRequestTime.Load().(time.Time)) > logSpamInterval { + e.logger.Warn("flag --externalcl was provided, but no CL seems to be connected.") + } + } + } + }() +} + +func (e *EngineLogsSpammer) RecordRequest() { + e.lastRequestTime.Store(time.Now()) +} diff --git a/turbo/engineapi/engine_server.go b/turbo/engineapi/engine_server.go index 431392ec895..57010f4e350 100644 --- a/turbo/engineapi/engine_server.go +++ b/turbo/engineapi/engine_server.go @@ -47,6 +47,7 @@ import ( "github.com/erigontech/erigon/rpc" "github.com/erigontech/erigon/turbo/engineapi/engine_block_downloader" "github.com/erigontech/erigon/turbo/engineapi/engine_helpers" + "github.com/erigontech/erigon/turbo/engineapi/engine_logs_spammer" "github.com/erigontech/erigon/turbo/engineapi/engine_types" "github.com/erigontech/erigon/turbo/execution/eth1/eth1_chain_reader.go" "github.com/erigontech/erigon/turbo/jsonrpc" @@ -71,6 +72,8 @@ type EngineServer struct { chainRW eth1_chain_reader.ChainReaderWriterEth1 lock sync.Mutex logger log.Logger + + engineLogSpamer *engine_logs_spammer.EngineLogsSpammer } const fcuTimeout = 1000 // according to mathematics: 1000 millisecods = 1 second @@ -88,6 +91,7 @@ func NewEngineServer(logger log.Logger, config *chain.Config, executionService e proposing: proposing, hd: hd, caplin: caplin, + engineLogSpamer: engine_logs_spammer.NewEngineLogsSpammer(logger, config), } } @@ -103,6 +107,9 @@ func (e *EngineServer) Start( txPool txpool.TxpoolClient, mining txpool.MiningClient, ) { + if !e.caplin { + e.engineLogSpamer.Start(ctx) + } base := jsonrpc.NewBaseApi(filters, stateCache, blockReader, httpConfig.WithDatadir, httpConfig.EvmCallTimeout, engineReader, httpConfig.Dirs, nil) ethImpl := jsonrpc.NewEthAPI(base, db, eth, txPool, mining, httpConfig.Gascap, httpConfig.Feecap, httpConfig.ReturnDataLimit, httpConfig.AllowUnprotectedTxs, httpConfig.MaxGetProofRewindBlockCount, httpConfig.WebsocketSubscribeLogsChannelSize, e.logger) @@ -161,6 +168,7 @@ func (s *EngineServer) newPayload(ctx context.Context, req *engine_types.Executi s.logger.Crit(caplinEnabledLog) return nil, errCaplinEnabled } + s.engineLogSpamer.RecordRequest() if len(req.LogsBloom) != types.BloomByteLength { return nil, &rpc.InvalidParamsError{Message: fmt.Sprintf("invalid logsBloom length: %d", len(req.LogsBloom))} @@ -459,6 +467,8 @@ func (s *EngineServer) getPayload(ctx context.Context, payloadId uint64, version s.logger.Crit("[NewPayload] caplin is enabled") return nil, errCaplinEnabled } + s.engineLogSpamer.RecordRequest() + if !s.proposing { return nil, errors.New("execution layer not running as a proposer. enable proposer by taking out the --proposer.disable flag on startup") } @@ -527,6 +537,8 @@ func (s *EngineServer) forkchoiceUpdated(ctx context.Context, forkchoiceState *e s.logger.Crit("[NewPayload] caplin is enabled") return nil, errCaplinEnabled } + s.engineLogSpamer.RecordRequest() + status, err := s.getQuickPayloadStatusIfPossible(ctx, forkchoiceState.HeadHash, 0, libcommon.Hash{}, forkchoiceState, false) if err != nil { return nil, err @@ -630,6 +642,8 @@ func (s *EngineServer) getPayloadBodiesByHash(ctx context.Context, request []lib if len(request) > 1024 { return nil, &engine_helpers.TooLargeRequestErr } + s.engineLogSpamer.RecordRequest() + bodies, err := s.chainRW.GetBodiesByHashes(ctx, request) if err != nil { return nil, err @@ -682,6 +696,8 @@ func (e *EngineServer) GetPayloadV1(ctx context.Context, payloadId hexutility.By e.logger.Crit(caplinEnabledLog) return nil, errCaplinEnabled } + e.engineLogSpamer.RecordRequest() + decodedPayloadId := binary.BigEndian.Uint64(payloadId) e.logger.Info("Received GetPayloadV1", "payloadId", decodedPayloadId) @@ -794,6 +810,8 @@ var ourCapabilities = []string{ } func (e *EngineServer) ExchangeCapabilities(fromCl []string) []string { + e.engineLogSpamer.RecordRequest() + missingOurs := compareCapabilities(fromCl, ourCapabilities) missingCl := compareCapabilities(ourCapabilities, fromCl) @@ -828,6 +846,8 @@ func (e *EngineServer) HandleNewPayload( block *types.Block, versionedHashes []libcommon.Hash, ) (*engine_types.PayloadStatus, error) { + e.engineLogSpamer.RecordRequest() + header := block.Header() headerNumber := header.Number.Uint64() headerHash := block.Hash() @@ -937,6 +957,8 @@ func (e *EngineServer) HandlesForkChoice( forkChoice *engine_types.ForkChoiceState, requestId int, ) (*engine_types.PayloadStatus, error) { + e.engineLogSpamer.RecordRequest() + headerHash := forkChoice.HeadHash e.logger.Debug(fmt.Sprintf("[%s] Handling fork choice", logPrefix), "headerHash", headerHash) From 98545dc661c6443040aa0a6d0af09bbaf469499f Mon Sep 17 00:00:00 2001 From: Shota Date: Wed, 11 Dec 2024 01:20:52 +0400 Subject: [PATCH 20/24] add slot data from electra (#13042) Adding slot data to support to Antiquary Co-authored-by: shota.silagadze --- cl/antiquary/state_antiquary_test.go | 5 ++ .../test_data/electra/blocks_0.ssz_snappy | Bin 0 -> 65932 bytes .../test_data/electra/blocks_1.ssz_snappy | Bin 0 -> 25700 bytes .../tests/test_data/electra/meta.yaml | 3 + .../tests/test_data/electra/post.ssz_snappy | Bin 0 -> 214406 bytes .../tests/test_data/electra/pre.ssz_snappy | Bin 0 -> 202065 bytes cl/antiquary/tests/tests.go | 36 ++++++++++++ cl/beacon/handler/rewards.go | 2 +- .../historical_states_reader.go | 8 +-- cl/persistence/state/slot_data.go | 54 +++++++++++++++--- cl/persistence/state/slot_data_test.go | 27 ++++++--- cl/persistence/state/state_accessors.go | 5 +- cl/phase1/core/state/raw/getters.go | 28 +++++++++ 13 files changed, 147 insertions(+), 21 deletions(-) create mode 100644 cl/antiquary/tests/test_data/electra/blocks_0.ssz_snappy create mode 100644 cl/antiquary/tests/test_data/electra/blocks_1.ssz_snappy create mode 100644 cl/antiquary/tests/test_data/electra/meta.yaml create mode 100644 cl/antiquary/tests/test_data/electra/post.ssz_snappy create mode 100644 cl/antiquary/tests/test_data/electra/pre.ssz_snappy diff --git a/cl/antiquary/state_antiquary_test.go b/cl/antiquary/state_antiquary_test.go index 4dc4538c952..c30ff84a75f 100644 --- a/cl/antiquary/state_antiquary_test.go +++ b/cl/antiquary/state_antiquary_test.go @@ -48,6 +48,11 @@ func runTest(t *testing.T, blocks []*cltypes.SignedBeaconBlock, preState, postSt require.NoError(t, a.IncrementBeaconState(ctx, blocks[len(blocks)-1].Block.Slot+33)) } +func TestStateAntiquaryElectra(t *testing.T) { + blocks, preState, postState := tests.GetElectraRandom() + runTest(t, blocks, preState, postState) +} + func TestStateAntiquaryCapella(t *testing.T) { blocks, preState, postState := tests.GetCapellaRandom() runTest(t, blocks, preState, postState) diff --git a/cl/antiquary/tests/test_data/electra/blocks_0.ssz_snappy b/cl/antiquary/tests/test_data/electra/blocks_0.ssz_snappy new file mode 100644 index 0000000000000000000000000000000000000000..2e2f35ecc0260314b0fa4dd298a08fb18080ce22 GIT binary patch literal 65932 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

eBH2 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 TJ5=PtKuBJ^{O`NX|GEAbZj&p~ literal 0 HcmV?d00001 diff --git a/cl/antiquary/tests/test_data/electra/blocks_1.ssz_snappy b/cl/antiquary/tests/test_data/electra/blocks_1.ssz_snappy new file mode 100644 index 0000000000000000000000000000000000000000..f50dac5c2cab527b473ae082404927ee5db78b14 GIT binary patch literal 25700 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[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%0DDt>q#5KmV2Mf(K>dQ( zzw%Eo3Sx%hoXeZx4>v~5+usT`@zIBX!Cy`|02&bTzpx2})cy)?`#HXKX6*|)W6`LW zl8nj{VjpX$^n~uh0D8n!*>wQEXvF766(j&a$|4L9K%|$yyIKg8n_~AE>F(P1zPQNp zjYZN!)h4_Y0;GPS;`B4aAt@ADFh7uQ`mu17G3NgdT8JGV6GchKqz$BO(hGE>;LnYtC+tfa{O; z!f0!VXg`CN{QMbQBQOu=N!g=B(%^mj>thCT!(MkxSE!4-BpgRCc3_3-+v7pm3YIjA z^qgEj00{ab7gB$n)9y5GCFh0~+OAiwp#eJ{GHrA9vs4Aq&I$Sejx5;riZoJ0OsrH%Jh z(pHPgR((+enNcsS#KAAGYMw@EY5)=;$n7Vga>C!KG%y5eWX6OMWq0~?+D#!idyI<@ z8hyktu{73alxC*HFHllvZ~GTwrTE24`Q{qs8X;Oz&}~q}97{0UUS?%Kxzscg?H5C1 z|D%?^O`hTDZB9rgL=%~G*2sMh&PufpQ;C8oI-tGz%5O+eFP`VV7#yud3N2X&QhJ7fIV15fZMJBhr@jI z5+a~J#%X+aFd}9!GIS5Ek@NYFTKpZx zd$+F6UFf7o5oLhc_kVHND@1yo3ZvhRyua^NvJyt$<3>Q0CbChWMdD)yo%~1bo(@>> zP$Yq0?LfvLGj6kUoJ@LM%$TV^*a}Mo9POERh$STuc5~RRgcIg!ISwwRLFqGDGCpbwb1x+>*WQtzpu%zlJ?*i?xiyLXQ1b9*E)+wh+ kK@0UW9ugfGwy*{vVPYh8jRor=YzwHsL52VK5&hr(A8Z_`AOHXW literal 0 HcmV?d00001 diff --git a/cl/antiquary/tests/test_data/electra/meta.yaml b/cl/antiquary/tests/test_data/electra/meta.yaml new file mode 100644 index 00000000000..2521cc1d0e1 --- /dev/null +++ b/cl/antiquary/tests/test_data/electra/meta.yaml @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:73018ecc96aa42f2d6baef211fb8d504750ad1ab638d94705d3d1b051b4ad71e +size 34 diff --git a/cl/antiquary/tests/test_data/electra/post.ssz_snappy b/cl/antiquary/tests/test_data/electra/post.ssz_snappy new file mode 100644 index 0000000000000000000000000000000000000000..d8877dc5b182f851ceedac72177155a5079ab14d GIT binary patch literal 214406 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 V8s!t6Mv*4TdM_C6<%I$;`ak(eQ}+M> literal 0 HcmV?d00001 diff --git a/cl/antiquary/tests/tests.go b/cl/antiquary/tests/tests.go index 425ffc0de9b..272c001ff49 100644 --- a/cl/antiquary/tests/tests.go +++ b/cl/antiquary/tests/tests.go @@ -33,6 +33,18 @@ import ( "github.com/stretchr/testify/require" ) +//go:embed test_data/electra/blocks_0.ssz_snappy +var electra_blocks_0_ssz_snappy []byte + +//go:embed test_data/electra/blocks_1.ssz_snappy +var electra_blocks_1_ssz_snappy []byte + +//go:embed test_data/electra/pre.ssz_snappy +var electra_pre_state_ssz_snappy []byte + +//go:embed test_data/electra/post.ssz_snappy +var electra_post_state_ssz_snappy []byte + //go:embed test_data/capella/blocks_0.ssz_snappy var capella_blocks_0_ssz_snappy []byte @@ -126,6 +138,30 @@ func LoadChain(blocks []*cltypes.SignedBeaconBlock, s *state.CachingBeaconState, return m } +func GetElectraRandom() ([]*cltypes.SignedBeaconBlock, *state.CachingBeaconState, *state.CachingBeaconState) { + block1 := cltypes.NewSignedBeaconBlock(&clparams.MainnetBeaconConfig, clparams.ElectraVersion) + block2 := cltypes.NewSignedBeaconBlock(&clparams.MainnetBeaconConfig, clparams.ElectraVersion) + + // Lets do te + if err := utils.DecodeSSZSnappy(block1, electra_blocks_0_ssz_snappy, int(clparams.ElectraVersion)); err != nil { + panic(err) + } + if err := utils.DecodeSSZSnappy(block2, electra_blocks_1_ssz_snappy, int(clparams.ElectraVersion)); err != nil { + panic(err) + } + + preState := state.New(&clparams.MainnetBeaconConfig) + if err := utils.DecodeSSZSnappy(preState, electra_pre_state_ssz_snappy, int(clparams.ElectraVersion)); err != nil { + panic(err) + + } + postState := state.New(&clparams.MainnetBeaconConfig) + if err := utils.DecodeSSZSnappy(postState, electra_post_state_ssz_snappy, int(clparams.ElectraVersion)); err != nil { + panic(err) + } + return []*cltypes.SignedBeaconBlock{block1, block2}, preState, postState +} + func GetCapellaRandom() ([]*cltypes.SignedBeaconBlock, *state.CachingBeaconState, *state.CachingBeaconState) { block1 := cltypes.NewSignedBeaconBlock(&clparams.MainnetBeaconConfig, clparams.CapellaVersion) block2 := cltypes.NewSignedBeaconBlock(&clparams.MainnetBeaconConfig, clparams.CapellaVersion) diff --git a/cl/beacon/handler/rewards.go b/cl/beacon/handler/rewards.go index dbfe400027c..72488120499 100644 --- a/cl/beacon/handler/rewards.go +++ b/cl/beacon/handler/rewards.go @@ -86,7 +86,7 @@ func (a *ApiHandler) GetEthV1BeaconRewardsBlocks(w http.ResponseWriter, r *http. defer snRoTx.Close() stateGetter := state_accessors.GetValFnTxAndSnapshot(tx, snRoTx) - slotData, err := state_accessors.ReadSlotData(stateGetter, slot) + slotData, err := state_accessors.ReadSlotData(stateGetter, slot, a.beaconChainCfg) if err != nil { return nil, err } diff --git a/cl/persistence/state/historical_states_reader/historical_states_reader.go b/cl/persistence/state/historical_states_reader/historical_states_reader.go index d2e7d3ba268..a2536572f2b 100644 --- a/cl/persistence/state/historical_states_reader/historical_states_reader.go +++ b/cl/persistence/state/historical_states_reader/historical_states_reader.go @@ -114,7 +114,7 @@ func (r *HistoricalStatesReader) ReadHistoricalState(ctx context.Context, tx kv. blockHeader := block.SignedBeaconBlockHeader().Header blockHeader.Root = common.Hash{} // Read the epoch and per-slot data. - slotData, err := state_accessors.ReadSlotData(kvGetter, slot) + slotData, err := state_accessors.ReadSlotData(kvGetter, slot, r.cfg) if err != nil { return nil, err } @@ -673,7 +673,7 @@ func (r *HistoricalStatesReader) ReconstructUint64ListDump(kvGetter state_access func (r *HistoricalStatesReader) ReadValidatorsForHistoricalState(tx kv.Tx, kvGetter state_accessors.GetValFn, slot uint64) (*solid.ValidatorSet, error) { // Read the minimal beacon state which have the small fields. - sd, err := state_accessors.ReadSlotData(kvGetter, slot) + sd, err := state_accessors.ReadSlotData(kvGetter, slot, r.cfg) if err != nil { return nil, err } @@ -777,7 +777,7 @@ func (r *HistoricalStatesReader) ReadParticipations(tx kv.Tx, kvGetter state_acc } // Read the minimal beacon state which have the small fields. - sd, err := state_accessors.ReadSlotData(kvGetter, slot) + sd, err := state_accessors.ReadSlotData(kvGetter, slot, r.cfg) if err != nil { return nil, nil, err } @@ -900,7 +900,7 @@ func (r *HistoricalStatesReader) tryCachingEpochsInParallell(tx kv.Tx, kvGetter } func (r *HistoricalStatesReader) ReadValidatorsBalances(tx kv.Tx, kvGetter state_accessors.GetValFn, slot uint64) (solid.Uint64ListSSZ, error) { - sd, err := state_accessors.ReadSlotData(kvGetter, slot) + sd, err := state_accessors.ReadSlotData(kvGetter, slot, r.cfg) if err != nil { return nil, err } diff --git a/cl/persistence/state/slot_data.go b/cl/persistence/state/slot_data.go index eca6c12c073..8f23427cde5 100644 --- a/cl/persistence/state/slot_data.go +++ b/cl/persistence/state/slot_data.go @@ -23,6 +23,7 @@ import ( "github.com/erigontech/erigon/cl/clparams" "github.com/erigontech/erigon/cl/cltypes" + "github.com/erigontech/erigon/cl/cltypes/solid" "github.com/erigontech/erigon/cl/phase1/core/state" ssz2 "github.com/erigontech/erigon/cl/ssz" ) @@ -40,6 +41,16 @@ type SlotData struct { // Capella NextWithdrawalIndex uint64 NextWithdrawalValidatorIndex uint64 + // Electra + DepositRequestsStartIndex uint64 + DepositBalanceToConsume uint64 + ExitBalanceToConsume uint64 + EarliestExitEpoch uint64 + ConsolidationBalanceToConsume uint64 + EarliestConsolidationEpoch uint64 + PendingDeposits *solid.ListSSZ[*solid.PendingDeposit] + PendingPartialWithdrawals *solid.ListSSZ[*solid.PendingPartialWithdrawal] + PendingConsolidations *solid.ListSSZ[*solid.PendingConsolidation] // BlockRewards for proposer AttestationsRewards uint64 @@ -56,12 +67,21 @@ func SlotDataFromBeaconState(s *state.CachingBeaconState) *SlotData { ValidatorLength: uint64(s.ValidatorLength()), Eth1DataLength: uint64(s.Eth1DataVotes().Len()), - Version: s.Version(), - Eth1Data: s.Eth1Data(), - Eth1DepositIndex: s.Eth1DepositIndex(), - NextWithdrawalIndex: s.NextWithdrawalIndex(), - NextWithdrawalValidatorIndex: s.NextWithdrawalValidatorIndex(), - Fork: s.Fork(), + Version: s.Version(), + Eth1Data: s.Eth1Data(), + Eth1DepositIndex: s.Eth1DepositIndex(), + NextWithdrawalIndex: s.NextWithdrawalIndex(), + NextWithdrawalValidatorIndex: s.NextWithdrawalValidatorIndex(), + DepositRequestsStartIndex: s.DepositRequestsStartIndex(), + DepositBalanceToConsume: s.DepositBalanceToConsume(), + ExitBalanceToConsume: s.ExitBalanceToConsume(), + EarliestExitEpoch: s.EarliestExitEpoch(), + ConsolidationBalanceToConsume: s.ConsolidationBalanceToConsume(), + EarliestConsolidationEpoch: s.EarliestConsolidationEpoch(), + PendingDeposits: s.PendingDeposits(), + PendingPartialWithdrawals: s.PendingPartialWithdrawals(), + PendingConsolidations: s.PendingConsolidations(), + Fork: s.Fork(), } } @@ -87,7 +107,7 @@ func (m *SlotData) WriteTo(w io.Writer) error { } // Deserialize deserializes the state from a byte slice with zstd compression. -func (m *SlotData) ReadFrom(r io.Reader) error { +func (m *SlotData) ReadFrom(r io.Reader, cfg *clparams.BeaconChainConfig) error { m.Eth1Data = &cltypes.Eth1Data{} m.Fork = &cltypes.Fork{} var err error @@ -98,6 +118,12 @@ func (m *SlotData) ReadFrom(r io.Reader) error { } m.Version = clparams.StateVersion(versionByte[0]) + if m.Version >= clparams.ElectraVersion { + m.PendingDeposits = solid.NewPendingDepositList(cfg) + m.PendingPartialWithdrawals = solid.NewPendingWithdrawalList(cfg) + m.PendingConsolidations = solid.NewPendingConsolidationList(cfg) + } + lenB := make([]byte, 8) if _, err = r.Read(lenB); err != nil { return err @@ -122,5 +148,19 @@ func (m *SlotData) getSchema() []interface{} { if m.Version >= clparams.CapellaVersion { schema = append(schema, &m.NextWithdrawalIndex, &m.NextWithdrawalValidatorIndex) } + + if m.Version >= clparams.ElectraVersion { + schema = append(schema, + &m.DepositRequestsStartIndex, + &m.DepositBalanceToConsume, + &m.ExitBalanceToConsume, + &m.EarliestExitEpoch, + &m.ConsolidationBalanceToConsume, + &m.EarliestConsolidationEpoch, + m.PendingDeposits, + m.PendingPartialWithdrawals, + m.PendingConsolidations, + ) + } return schema } diff --git a/cl/persistence/state/slot_data_test.go b/cl/persistence/state/slot_data_test.go index 886b4417cba..9b4d91688e6 100644 --- a/cl/persistence/state/slot_data_test.go +++ b/cl/persistence/state/slot_data_test.go @@ -21,25 +21,38 @@ import ( "testing" "github.com/erigontech/erigon/cl/clparams" + "github.com/erigontech/erigon/cl/clparams/initial_state" "github.com/erigontech/erigon/cl/cltypes" + "github.com/erigontech/erigon/cl/cltypes/solid" "github.com/stretchr/testify/require" ) func TestSlotData(t *testing.T) { + s, err := initial_state.GetGenesisState(clparams.MainnetNetwork) + require.NoError(t, err) m := &SlotData{ - Version: clparams.CapellaVersion, - Eth1Data: &cltypes.Eth1Data{}, - Eth1DepositIndex: 0, - NextWithdrawalIndex: 0, - NextWithdrawalValidatorIndex: 0, - Fork: &cltypes.Fork{Epoch: 12}, + Version: clparams.ElectraVersion, + Eth1Data: &cltypes.Eth1Data{}, + Eth1DepositIndex: 1, + NextWithdrawalIndex: 2, + NextWithdrawalValidatorIndex: 3, + DepositRequestsStartIndex: 4, + DepositBalanceToConsume: 5, + ExitBalanceToConsume: 6, + EarliestExitEpoch: 7, + ConsolidationBalanceToConsume: 8, + EarliestConsolidationEpoch: 9, + PendingDeposits: solid.NewPendingDepositList(s.BeaconConfig()), + PendingPartialWithdrawals: solid.NewPendingWithdrawalList(s.BeaconConfig()), + PendingConsolidations: solid.NewPendingConsolidationList(s.BeaconConfig()), + Fork: &cltypes.Fork{Epoch: 12}, } var b bytes.Buffer if err := m.WriteTo(&b); err != nil { t.Fatal(err) } m2 := &SlotData{} - if err := m2.ReadFrom(&b); err != nil { + if err := m2.ReadFrom(&b, s.BeaconConfig()); err != nil { t.Fatal(err) } diff --git a/cl/persistence/state/state_accessors.go b/cl/persistence/state/state_accessors.go index a34fd1645e2..143cf1189b4 100644 --- a/cl/persistence/state/state_accessors.go +++ b/cl/persistence/state/state_accessors.go @@ -21,6 +21,7 @@ import ( "encoding/binary" "github.com/erigontech/erigon-lib/kv" + "github.com/erigontech/erigon/cl/clparams" "github.com/erigontech/erigon/cl/cltypes/solid" "github.com/erigontech/erigon/cl/persistence/base_encoding" "github.com/erigontech/erigon/turbo/snapshotsync" @@ -56,7 +57,7 @@ func SetStateProcessingProgress(tx kv.RwTx, progress uint64) error { return tx.Put(kv.StatesProcessingProgress, kv.StatesProcessingKey, base_encoding.Encode64ToBytes4(progress)) } -func ReadSlotData(getFn GetValFn, slot uint64) (*SlotData, error) { +func ReadSlotData(getFn GetValFn, slot uint64, cfg *clparams.BeaconChainConfig) (*SlotData, error) { sd := &SlotData{} v, err := getFn(kv.SlotData, base_encoding.Encode64ToBytes4(slot)) if err != nil { @@ -67,7 +68,7 @@ func ReadSlotData(getFn GetValFn, slot uint64) (*SlotData, error) { } buf := bytes.NewBuffer(v) - return sd, sd.ReadFrom(buf) + return sd, sd.ReadFrom(buf, cfg) } func ReadEpochData(getFn GetValFn, slot uint64) (*EpochData, error) { diff --git a/cl/phase1/core/state/raw/getters.go b/cl/phase1/core/state/raw/getters.go index 688bb216c91..5ad68c09a9f 100644 --- a/cl/phase1/core/state/raw/getters.go +++ b/cl/phase1/core/state/raw/getters.go @@ -323,6 +323,34 @@ func (b *BeaconState) NextWithdrawalValidatorIndex() uint64 { return b.nextWithdrawalValidatorIndex } +func (b *BeaconState) DepositRequestsStartIndex() uint64 { + return b.depositRequestsStartIndex +} + +func (b *BeaconState) DepositBalanceToConsume() uint64 { + return b.depositBalanceToConsume +} + +func (b *BeaconState) ConsolidationBalanceToConsume() uint64 { + return b.consolidationBalanceToConsume +} + +func (b *BeaconState) EarliestConsolidationEpoch() uint64 { + return b.earliestConsolidationEpoch +} + +func (b *BeaconState) PendingDeposits() *solid.ListSSZ[*solid.PendingDeposit] { + return b.pendingDeposits +} + +func (b *BeaconState) PendingPartialWithdrawals() *solid.ListSSZ[*solid.PendingPartialWithdrawal] { + return b.pendingPartialWithdrawals +} + +func (b *BeaconState) PendingConsolidations() *solid.ListSSZ[*solid.PendingConsolidation] { + return b.pendingConsolidations +} + // more compluicated ones // GetBlockRootAtSlot returns the block root at a given slot From f22317efc3a001cb9f8528ba99fbdc6436152575 Mon Sep 17 00:00:00 2001 From: Giulio rebuffo Date: Wed, 11 Dec 2024 07:14:58 +0100 Subject: [PATCH 21/24] Caplin: Added more logs to `--caplin.archive` (#13074) Co-authored-by: Kewei --- cl/antiquary/antiquary.go | 8 +++++++- cl/antiquary/state_antiquary.go | 23 ++++++++++++++++------- cl/phase1/stages/forkchoice.go | 3 +++ 3 files changed, 26 insertions(+), 8 deletions(-) diff --git a/cl/antiquary/antiquary.go b/cl/antiquary/antiquary.go index bab10cb5e86..22a42c16aab 100644 --- a/cl/antiquary/antiquary.go +++ b/cl/antiquary/antiquary.go @@ -217,7 +217,13 @@ func (a *Antiquary) Loop() error { } } - a.stateSn.OpenFolder() + if a.stateSn != nil { + if err := a.stateSn.OpenFolder(); err != nil { + return err + } + } + log.Info("[Caplin] Stat", "blocks-static", a.sn.BlocksAvailable(), "states-static", a.stateSn.BlocksAvailable(), "blobs-static", a.sn.FrozenBlobs(), + "state-history-enabled", a.states, "block-history-enabled", a.blocks, "blob-history-enabled", a.blobs, "snapgen", a.snapgen) frozenSlots := a.sn.BlocksAvailable() if frozenSlots != 0 { diff --git a/cl/antiquary/state_antiquary.go b/cl/antiquary/state_antiquary.go index c30ad6892d5..4e6cb2e9412 100644 --- a/cl/antiquary/state_antiquary.go +++ b/cl/antiquary/state_antiquary.go @@ -57,11 +57,11 @@ func (s *Antiquary) loopStates(ctx context.Context) { // Execute this each second reqRetryTimer := time.NewTicker(100 * time.Millisecond) defer reqRetryTimer.Stop() + if !initial_state.IsGenesisStateSupported(clparams.NetworkType(s.cfg.DepositNetworkID)) { s.logger.Warn("Genesis state is not supported for this network, no historical states data will be available") return } - _, beforeFinalized, err := s.readHistoricalProcessingProgress(ctx) if err != nil { s.logger.Error("Failed to read historical processing progress", "err", err) @@ -81,14 +81,16 @@ func (s *Antiquary) loopStates(ctx context.Context) { s.logger.Error("Failed to read historical processing progress", "err", err) continue } + if s.sn == nil || s.syncedData.Syncing() { + continue + } + // We wait for updated finality. if finalized == beforeFinalized { continue } beforeFinalized = finalized - if s.sn == nil || s.syncedData.Syncing() { - continue - } + if err := s.IncrementBeaconState(ctx, finalized); err != nil { if s.currentState != nil { s.logger.Warn("Could not to increment beacon state, trying again later", "err", err, "slot", s.currentState.Slot()) @@ -140,9 +142,16 @@ func FillStaticValidatorsTableIfNeeded(ctx context.Context, logger log.Logger, s blocksAvaiable := stateSn.BlocksAvailable() stateSnRoTx := stateSn.View() defer stateSnRoTx.Close() - + log.Info("[Caplin-Archive] filling validators table", "from", 0, "to", stateSn.BlocksAvailable()) + logTicker := time.NewTicker(10 * time.Second) + defer logTicker.Stop() start := time.Now() for slot := uint64(0); slot <= stateSn.BlocksAvailable(); slot++ { + select { + case <-logTicker.C: + log.Info("[Caplin-Archive] Filled validators table", "progress", fmt.Sprintf("%d/%d", slot, stateSn.BlocksAvailable())) + default: + } seg, ok := stateSnRoTx.VisibleSegment(slot, kv.StateEvents) if !ok { return false, fmt.Errorf("segment not found for slot %d", slot) @@ -437,7 +446,7 @@ func (s *Antiquary) IncrementBeaconState(ctx context.Context, to uint64) error { // We now do some post-processing on the state. select { case <-progressTimer.C: - log.Log(logLvl, "State processing progress", "slot", slot, "blk/sec", fmt.Sprintf("%.2f", float64(slot-prevSlot)/60)) + log.Log(logLvl, "[Caplin-Archive] Historical States reconstruction", "slot", slot, "blk/sec", fmt.Sprintf("%.2f", float64(slot-prevSlot)/60)) prevSlot = slot default: } @@ -491,7 +500,7 @@ func (s *Antiquary) IncrementBeaconState(ctx context.Context, to uint64) error { return err } - log.Info("Historical states antiquated", "slot", s.currentState.Slot(), "root", libcommon.Hash(stateRoot), "latency", endTime) + log.Info("[Caplin-Archive] Historical states antiquated", "slot", s.currentState.Slot(), "root", libcommon.Hash(stateRoot), "latency", endTime) if s.stateSn != nil { if err := s.stateSn.OpenFolder(); err != nil { return err diff --git a/cl/phase1/stages/forkchoice.go b/cl/phase1/stages/forkchoice.go index 03d3e6c3cc2..3c1de440594 100644 --- a/cl/phase1/stages/forkchoice.go +++ b/cl/phase1/stages/forkchoice.go @@ -307,6 +307,9 @@ func postForkchoiceOperations(ctx context.Context, tx kv.RwTx, logger log.Logger if _, err = cfg.attestationDataProducer.ProduceAndCacheAttestationData(tx, headState, headRoot, headState.Slot(), 0); err != nil { logger.Warn("failed to produce and cache attestation data", "err", err) } + if err := beacon_indicies.WriteHighestFinalized(tx, cfg.forkChoice.FinalizedSlot()); err != nil { + return err + } start := time.Now() cfg.forkChoice.SetSynced(true) // Now we are synced // Update the head state with the new head state From f3e688f91057b21a5926c0144289a5491e7110cc Mon Sep 17 00:00:00 2001 From: Somnath Date: Wed, 11 Dec 2024 17:07:56 +0400 Subject: [PATCH 22/24] Implement GetClientVersionV1 (#13071) A rather simple implementation for `engine_getClientVersionV1` --- params/version.go | 2 ++ turbo/engineapi/engine_server.go | 23 +++++++++++++++++++++++ turbo/engineapi/engine_types/jsonrpc.go | 12 ++++++++++++ turbo/engineapi/interface.go | 1 + 4 files changed, 38 insertions(+) diff --git a/params/version.go b/params/version.go index e3da300d50f..5cba261ef11 100644 --- a/params/version.go +++ b/params/version.go @@ -40,6 +40,8 @@ const ( VersionModifier = "alpha6" // Modifier component of the current release VersionKeyCreated = "ErigonVersionCreated" VersionKeyFinished = "ErigonVersionFinished" + ClientName = "erigon" + ClientCode = "EG" ) // Version holds the textual version string. diff --git a/turbo/engineapi/engine_server.go b/turbo/engineapi/engine_server.go index 57010f4e350..19ca98fed7a 100644 --- a/turbo/engineapi/engine_server.go +++ b/turbo/engineapi/engine_server.go @@ -44,6 +44,7 @@ import ( "github.com/erigontech/erigon/consensus/merge" "github.com/erigontech/erigon/core/types" "github.com/erigontech/erigon/eth/ethutils" + "github.com/erigontech/erigon/params" "github.com/erigontech/erigon/rpc" "github.com/erigontech/erigon/turbo/engineapi/engine_block_downloader" "github.com/erigontech/erigon/turbo/engineapi/engine_helpers" @@ -793,6 +794,27 @@ func (e *EngineServer) GetPayloadBodiesByRangeV1(ctx context.Context, start, cou return e.getPayloadBodiesByRange(ctx, uint64(start), uint64(count)) } +// Returns the node's code and commit details in a slice +// See https://github.com/ethereum/execution-apis/blob/main/src/engine/identification.md#engine_getclientversionv1 +func (e *EngineServer) GetClientVersionV1(ctx context.Context, callerVersion *engine_types.ClientVersionV1) ([]engine_types.ClientVersionV1, error) { + if callerVersion != nil { + e.logger.Info("[GetClientVersionV1] Received request from" + callerVersion.String()) + } + commitBytes := [4]byte{} + c := []byte(params.GitCommit) + if len(c) >= 4 { + copy(commitBytes[:], c[0:4]) + } + result := make([]engine_types.ClientVersionV1, 1) + result[0] = engine_types.ClientVersionV1{ + Code: params.ClientCode, + Name: params.ClientName, + Version: params.Version, + Commit: commitBytes, + } + return result, nil +} + var ourCapabilities = []string{ "engine_forkchoiceUpdatedV1", "engine_forkchoiceUpdatedV2", @@ -807,6 +829,7 @@ var ourCapabilities = []string{ "engine_getPayloadV4", "engine_getPayloadBodiesByHashV1", "engine_getPayloadBodiesByRangeV1", + "engine_getClientVersionV1", } func (e *EngineServer) ExchangeCapabilities(fromCl []string) []string { diff --git a/turbo/engineapi/engine_types/jsonrpc.go b/turbo/engineapi/engine_types/jsonrpc.go index 93e375cbbcc..021a4a96125 100644 --- a/turbo/engineapi/engine_types/jsonrpc.go +++ b/turbo/engineapi/engine_types/jsonrpc.go @@ -20,6 +20,7 @@ import ( "encoding/binary" "encoding/json" "errors" + "fmt" "github.com/erigontech/erigon-lib/common/hexutil" @@ -107,6 +108,17 @@ type GetPayloadResponse struct { ShouldOverrideBuilder bool `json:"shouldOverrideBuilder"` } +type ClientVersionV1 struct { + Code string `json:"code" gencodec:"required"` + Name string `json:"name" gencodec:"required"` + Version string `json:"version" gencodec:"required"` + Commit [4]byte `json:"commit" gencodec:"required"` +} + +func (c ClientVersionV1) String() string { + return fmt.Sprintf("ClientCode: %s, %s-%s-%s", c.Code, c.Name, c.Version, c.Commit) +} + type StringifiedError struct{ err error } func NewStringifiedError(err error) *StringifiedError { diff --git a/turbo/engineapi/interface.go b/turbo/engineapi/interface.go index d7f627cb4ce..6fb5e51b4e4 100644 --- a/turbo/engineapi/interface.go +++ b/turbo/engineapi/interface.go @@ -40,4 +40,5 @@ type EngineAPI interface { GetPayloadV4(ctx context.Context, payloadID hexutility.Bytes) (*engine_types.GetPayloadResponse, error) GetPayloadBodiesByHashV1(ctx context.Context, hashes []common.Hash) ([]*engine_types.ExecutionPayloadBody, error) GetPayloadBodiesByRangeV1(ctx context.Context, start, count hexutil.Uint64) ([]*engine_types.ExecutionPayloadBody, error) + GetClientVersionV1(ctx context.Context, callerVersion *engine_types.ClientVersionV1) ([]engine_types.ClientVersionV1, error) } From 8489566886b1a076d48e31499eb01a97310baad9 Mon Sep 17 00:00:00 2001 From: Ilya Mikheev <54912776+JkLondon@users.noreply.github.com> Date: Wed, 11 Dec 2024 15:06:44 +0100 Subject: [PATCH 23/24] TxLookup index per-txn-granularity (#12424) closes #12366 closes #12343 (For test purposes) closes #12892 Requires https://github.com/erigontech/interfaces/pull/240 Also, I suppose it would require resync of chaindata --------- Co-authored-by: JkLondon Co-authored-by: alex.sharov --- .github/workflows/scripts/run_rpc_tests.sh | 2 + ChangeLog.md | 1 + accounts/abi/bind/backends/simulated.go | 4 +- accounts/abi/bind/backends/simulated_test.go | 2 +- cmd/rpcdaemon/rpcservices/eth_backend.go | 2 +- core/rawdb/accessors_indexes.go | 26 +- core/rawdb/accessors_indexes_test.go | 64 +++-- core/state/txtask.go | 6 + erigon-lib/go.mod | 2 +- erigon-lib/go.sum | 4 +- .../gointerfaces/remoteproto/ethbackend.pb.go | 250 +++++++++--------- .../gointerfaces/remoteproto/kv_grpc.pb.go | 13 +- erigon-lib/state/history.go | 2 +- eth/stagedsync/stage_txlookup.go | 22 +- ethdb/privateapi/ethbackend.go | 6 +- migrations/migrations.go | 1 + migrations/reset_stage_txn_lookup.go | 47 ++++ turbo/jsonrpc/eth_api.go | 2 +- turbo/jsonrpc/eth_block.go | 2 +- turbo/jsonrpc/eth_receipts.go | 17 +- turbo/jsonrpc/eth_txs.go | 4 +- turbo/jsonrpc/otterscan_api.go | 2 +- turbo/jsonrpc/otterscan_search_v3.go | 4 +- turbo/jsonrpc/overlay_api.go | 2 +- turbo/jsonrpc/receipts/receipts_generator.go | 53 ++-- turbo/jsonrpc/trace_adhoc.go | 2 +- turbo/jsonrpc/trace_filtering.go | 2 +- turbo/jsonrpc/tracing.go | 2 +- turbo/services/interfaces.go | 2 +- .../snapshotsync/freezeblocks/block_reader.go | 37 ++- turbo/stages/blockchain_test.go | 16 +- 31 files changed, 349 insertions(+), 252 deletions(-) create mode 100644 migrations/reset_stage_txn_lookup.go diff --git a/.github/workflows/scripts/run_rpc_tests.sh b/.github/workflows/scripts/run_rpc_tests.sh index 64dfe5d1975..74e68533e7b 100755 --- a/.github/workflows/scripts/run_rpc_tests.sh +++ b/.github/workflows/scripts/run_rpc_tests.sh @@ -19,6 +19,8 @@ disabled_tests=( eth_coinbase/test_01.json eth_createAccessList/test_16.json eth_getTransactionByHash/test_02.json + # Small prune issue that leads to wrong ReceiptDomain data at 16999999 (probably at every million) block: https://github.com/erigontech/erigon/issues/13050 + ots_searchTransactionsBefore/test_04.tar eth_getWork/test_01.json eth_mining/test_01.json eth_protocolVersion/test_1.json diff --git a/ChangeLog.md b/ChangeLog.md index ad5981794db..47b3a86805c 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -36,6 +36,7 @@ ChangeLog ### New features: - Reduced `.idx` and `.efi` files size by 25% (require re-sync) +- Support: `debug_getRawReceipts` - debian packages - `--externalcl` support - bor-mainnet can work on 32G machine diff --git a/accounts/abi/bind/backends/simulated.go b/accounts/abi/bind/backends/simulated.go index 3645d0cc824..cb785a93af3 100644 --- a/accounts/abi/bind/backends/simulated.go +++ b/accounts/abi/bind/backends/simulated.go @@ -265,7 +265,7 @@ func (b *SimulatedBackend) TransactionReceipt(ctx context.Context, txHash libcom defer tx.Rollback() // Retrieve the context of the receipt based on the transaction hash - blockNumber, err := rawdb.ReadTxLookupEntry(tx, txHash) + blockNumber, _, err := rawdb.ReadTxLookupEntry(tx, txHash) if err != nil { return nil, err } @@ -308,7 +308,7 @@ func (b *SimulatedBackend) TransactionByHash(ctx context.Context, txHash libcomm if txn != nil { return txn, true, nil } - blockNumber, ok, err := b.BlockReader().TxnLookup(ctx, tx, txHash) + blockNumber, _, ok, err := b.BlockReader().TxnLookup(ctx, tx, txHash) if err != nil { return nil, false, err } diff --git a/accounts/abi/bind/backends/simulated_test.go b/accounts/abi/bind/backends/simulated_test.go index 2882c933316..632e25bd9fb 100644 --- a/accounts/abi/bind/backends/simulated_test.go +++ b/accounts/abi/bind/backends/simulated_test.go @@ -89,7 +89,7 @@ func TestSimulatedBackend(t *testing.T) { sim.Commit() _, isPending, err = sim.TransactionByHash(context.Background(), txHash) if err != nil { - t.Fatalf("error getting transaction with hash: %v", txHash.String()) + t.Fatalf("error getting transaction with hash: %v %v", txHash.String(), err.Error()) } if isPending { t.Fatal("transaction should not have pending status") diff --git a/cmd/rpcdaemon/rpcservices/eth_backend.go b/cmd/rpcdaemon/rpcservices/eth_backend.go index 68e06fabe83..8598411befd 100644 --- a/cmd/rpcdaemon/rpcservices/eth_backend.go +++ b/cmd/rpcdaemon/rpcservices/eth_backend.go @@ -282,7 +282,7 @@ func (back *RemoteBackend) SubscribeLogs(ctx context.Context, onNewLogs func(rep return nil } -func (back *RemoteBackend) TxnLookup(ctx context.Context, tx kv.Getter, txnHash common.Hash) (uint64, bool, error) { +func (back *RemoteBackend) TxnLookup(ctx context.Context, tx kv.Getter, txnHash common.Hash) (uint64, uint64, bool, error) { return back.blockReader.TxnLookup(ctx, tx, txnHash) } func (back *RemoteBackend) HasSenders(ctx context.Context, tx kv.Getter, hash common.Hash, blockNum uint64) (bool, error) { diff --git a/core/rawdb/accessors_indexes.go b/core/rawdb/accessors_indexes.go index cc672a33fe8..c1b5175cb46 100644 --- a/core/rawdb/accessors_indexes.go +++ b/core/rawdb/accessors_indexes.go @@ -20,8 +20,7 @@ package rawdb import ( - "math/big" - + "encoding/binary" libcommon "github.com/erigontech/erigon-lib/common" "github.com/erigontech/erigon-lib/kv" "github.com/erigontech/erigon-lib/log/v3" @@ -39,23 +38,28 @@ type TxLookupEntry struct { // ReadTxLookupEntry retrieves the positional metadata associated with a transaction // hash to allow retrieving the transaction or receipt by hash. -func ReadTxLookupEntry(db kv.Getter, txnHash libcommon.Hash) (*uint64, error) { +func ReadTxLookupEntry(db kv.Getter, txnHash libcommon.Hash) (blockNumber *uint64, txNum *uint64, err error) { data, err := db.GetOne(kv.TxLookup, txnHash.Bytes()) if err != nil { - return nil, err + return nil, nil, err } - if len(data) == 0 { - return nil, nil + if len(data) != 16 { + return nil, nil, nil } - number := new(big.Int).SetBytes(data).Uint64() - return &number, nil + numberBlockNum := binary.BigEndian.Uint64(data[:8]) + numberTxNum := binary.BigEndian.Uint64(data[8:]) + 1 + + return &numberBlockNum, &numberTxNum, nil } // WriteTxLookupEntries stores a positional metadata for every transaction from // a block, enabling hash based transaction and receipt lookups. -func WriteTxLookupEntries(db kv.Putter, block *types.Block) { - for _, txn := range block.Transactions() { - data := block.Number().Bytes() +func WriteTxLookupEntries(db kv.Putter, block *types.Block, txNum uint64) { + data := make([]byte, 16) + for i, txn := range block.Transactions() { + binary.BigEndian.PutUint64(data[:8], block.NumberU64()) + binary.BigEndian.PutUint64(data[8:], txNum+uint64(i)+1) + if err := db.Put(kv.TxLookup, txn.Hash().Bytes(), data); err != nil { log.Crit("Failed to store transaction lookup entry", "err", err) } diff --git a/core/rawdb/accessors_indexes_test.go b/core/rawdb/accessors_indexes_test.go index 8dd02b14a13..a0ba8bb95f4 100644 --- a/core/rawdb/accessors_indexes_test.go +++ b/core/rawdb/accessors_indexes_test.go @@ -29,6 +29,7 @@ import ( libcommon "github.com/erigontech/erigon-lib/common" "github.com/erigontech/erigon-lib/kv" + "github.com/erigontech/erigon-lib/kv/rawdbv3" "github.com/erigontech/erigon-lib/log/v3" "github.com/erigontech/erigon/core/rawdb" "github.com/erigontech/erigon/core/types" @@ -41,12 +42,12 @@ func TestLookupStorage(t *testing.T) { t.Parallel() tests := []struct { name string - writeTxLookupEntries func(kv.Putter, *types.Block) + writeTxLookupEntries func(kv.Putter, *types.Block, uint64) }{ { "DatabaseV6", - func(db kv.Putter, block *types.Block) { - rawdb.WriteTxLookupEntries(db, block) + func(db kv.Putter, block *types.Block, txNum uint64) { + rawdb.WriteTxLookupEntries(db, block, txNum) }, }, // Erigon: older databases are removed, no backward compatibility @@ -71,7 +72,7 @@ func TestLookupStorage(t *testing.T) { // Check that no transactions entries are in a pristine database for i, txn := range txs { - if txn2, _, _, _, _ := readTransactionByHash(tx, txn.Hash(), br); txn2 != nil { + if txn2, _, _, _, _, _ := readTransactionByHash(tx, txn.Hash(), br); txn2 != nil { t.Fatalf("txn #%d [%x]: non existent transaction returned: %v", i, txn.Hash(), txn2) } } @@ -85,18 +86,26 @@ func TestLookupStorage(t *testing.T) { if err := rawdb.WriteSenders(tx, block.Hash(), block.NumberU64(), block.Body().SendersFromTxs()); err != nil { t.Fatal(err) } - tc.writeTxLookupEntries(tx, block) + txNumMin, err := rawdbv3.TxNums.Min(tx, block.NumberU64()) + if err != nil { + t.Fatal(err) + } + + tc.writeTxLookupEntries(tx, block, txNumMin) for i, txn := range txs { - if txn2, hash, number, index, _ := readTransactionByHash(tx, txn.Hash(), br); txn2 == nil { + if txn2, hash, blockNumber, txNum, index, _ := readTransactionByHash(tx, txn.Hash(), br); txn2 == nil { t.Fatalf("txn #%d [%x]: transaction not found", i, txn.Hash()) } else { - if hash != block.Hash() || number != block.NumberU64() || index != uint64(i) { - t.Fatalf("txn #%d [%x]: positional metadata mismatch: have %x/%d/%d, want %x/%v/%v", i, txn.Hash(), hash, number, index, block.Hash(), block.NumberU64(), i) + if hash != block.Hash() || blockNumber != block.NumberU64() || index != uint64(i) { + t.Fatalf("txn #%d [%x]: positional metadata mismatch: have %x/%d/%d, want %x/%v/%v", i, txn.Hash(), hash, blockNumber, index, block.Hash(), block.NumberU64(), i) } if txn.Hash() != txn2.Hash() { t.Fatalf("txn #%d [%x]: transaction mismatch: have %v, want %v", i, txn.Hash(), txn, txn2) } + if txNum != txNumMin+uint64(i)+2 { + t.Fatalf("txn #%d [%x]: txnum mismatch: have %d, want %d", i, txn.Hash(), txNum, txNumMin+uint64(i)+1) + } } } // Delete the transactions and check purge @@ -104,7 +113,7 @@ func TestLookupStorage(t *testing.T) { if err := rawdb.DeleteTxLookupEntry(tx, txn.Hash()); err != nil { t.Fatal(err) } - if txn2, _, _, _, _ := readTransactionByHash(tx, txn.Hash(), br); txn2 != nil { + if txn2, _, _, _, _, _ := readTransactionByHash(tx, txn.Hash(), br); txn2 != nil { t.Fatalf("txn #%d [%x]: deleted transaction returned: %v", i, txn.Hash(), txn2) } } @@ -114,36 +123,41 @@ func TestLookupStorage(t *testing.T) { // ReadTransactionByHash retrieves a specific transaction from the database, along with // its added positional metadata. -func readTransactionByHash(db kv.Tx, hash libcommon.Hash, br services.FullBlockReader) (types.Transaction, libcommon.Hash, uint64, uint64, error) { - blockNumber, err := rawdb.ReadTxLookupEntry(db, hash) +func readTransactionByHash(db kv.Tx, hash libcommon.Hash, br services.FullBlockReader) (txn types.Transaction, blockHash libcommon.Hash, blockNumber uint64, txNum uint64, txIndex uint64, err error) { + blockNumberPtr, txNumPtr, err := rawdb.ReadTxLookupEntry(db, hash) if err != nil { - return nil, libcommon.Hash{}, 0, 0, err + return nil, libcommon.Hash{}, 0, 0, 0, err + } + if blockNumberPtr == nil { + return nil, libcommon.Hash{}, 0, 0, 0, nil } - if blockNumber == nil { - return nil, libcommon.Hash{}, 0, 0, nil + blockNumber = *blockNumberPtr + if txNumPtr == nil { + return nil, libcommon.Hash{}, 0, 0, 0, nil } - blockHash, ok, err := br.CanonicalHash(context.Background(), db, *blockNumber) + txNum = *txNumPtr + blockHash, ok, err := br.CanonicalHash(context.Background(), db, blockNumber) if err != nil { - return nil, libcommon.Hash{}, 0, 0, err + return nil, libcommon.Hash{}, 0, 0, 0, err } if !ok || blockHash == (libcommon.Hash{}) { - return nil, libcommon.Hash{}, 0, 0, nil + return nil, libcommon.Hash{}, 0, 0, 0, nil } - body, _ := br.BodyWithTransactions(context.Background(), db, blockHash, *blockNumber) + body, _ := br.BodyWithTransactions(context.Background(), db, blockHash, blockNumber) if body == nil { log.Error("Transaction referenced missing", "number", blockNumber, "hash", blockHash) - return nil, libcommon.Hash{}, 0, 0, nil + return nil, libcommon.Hash{}, 0, 0, 0, nil } - senders, err1 := rawdb.ReadSenders(db, blockHash, *blockNumber) + senders, err1 := rawdb.ReadSenders(db, blockHash, blockNumber) if err1 != nil { - return nil, libcommon.Hash{}, 0, 0, err1 + return nil, libcommon.Hash{}, 0, 0, 0, err1 } body.SendersToTxs(senders) - for txIndex, txn := range body.Transactions { - if txn.Hash() == hash { - return txn, blockHash, *blockNumber, uint64(txIndex), nil + for txInd, txnValue := range body.Transactions { + if txnValue.Hash() == hash { + return txnValue, blockHash, blockNumber, txNum, uint64(txInd), nil } } log.Error("Transaction not found", "number", blockNumber, "hash", blockHash, "txhash", hash) - return nil, libcommon.Hash{}, 0, 0, nil + return nil, libcommon.Hash{}, 0, 0, 0, nil } diff --git a/core/state/txtask.go b/core/state/txtask.go index 6ea205cbeff..15551bd6a38 100644 --- a/core/state/txtask.go +++ b/core/state/txtask.go @@ -19,6 +19,8 @@ package state import ( "container/heap" "context" + "fmt" + "github.com/erigontech/erigon-lib/common/dbg" "sync" "time" @@ -106,6 +108,10 @@ func (t *TxTask) CreateReceipt(tx kv.Tx) { } cumulativeGasUsed += t.UsedGas + if t.UsedGas == 0 { + msg := fmt.Sprintf("no gas used stack: %s tx %+v", dbg.Stack(), t.Tx) + panic(msg) + } r := t.createReceipt(cumulativeGasUsed) r.FirstLogIndexWithinBlock = firstLogIndex diff --git a/erigon-lib/go.mod b/erigon-lib/go.mod index a1183f858fe..2d96fdd3bf9 100644 --- a/erigon-lib/go.mod +++ b/erigon-lib/go.mod @@ -9,7 +9,7 @@ replace ( require ( github.com/erigontech/erigon-snapshot v1.3.1-0.20241023024258-f64407a77e8e - github.com/erigontech/interfaces v0.0.0-20241116035842-5d396f10468e + github.com/erigontech/interfaces v0.0.0-20241120074553-214b5fd396ed github.com/erigontech/mdbx-go v0.38.4 github.com/erigontech/secp256k1 v1.1.0 github.com/rs/dnscache v0.0.0-20211102005908-e0241e321417 diff --git a/erigon-lib/go.sum b/erigon-lib/go.sum index 6d99de06a16..3559d3e1e95 100644 --- a/erigon-lib/go.sum +++ b/erigon-lib/go.sum @@ -152,8 +152,8 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/erigontech/erigon-snapshot v1.3.1-0.20241023024258-f64407a77e8e h1:ZpIO6HeopuZPYDLldL6zR0qyRezj80kQrDOGEF779ts= github.com/erigontech/erigon-snapshot v1.3.1-0.20241023024258-f64407a77e8e/go.mod h1:ooHlCl+eEYzebiPu+FP6Q6SpPUeMADn8Jxabv3IKb9M= -github.com/erigontech/interfaces v0.0.0-20241116035842-5d396f10468e h1:KD/yuduvNJDKkdmEaaiDYb9RQstnkJn5ZcSZHjH/C/w= -github.com/erigontech/interfaces v0.0.0-20241116035842-5d396f10468e/go.mod h1:N7OUkhkcagp9+7yb4ycHsG2VWCOmuJ1ONBecJshxtLE= +github.com/erigontech/interfaces v0.0.0-20241120074553-214b5fd396ed h1:un44S8Tuol4LBIC6R94t93GShM53BYjz7GsNPziDLQ8= +github.com/erigontech/interfaces v0.0.0-20241120074553-214b5fd396ed/go.mod h1:N7OUkhkcagp9+7yb4ycHsG2VWCOmuJ1ONBecJshxtLE= github.com/erigontech/mdbx-go v0.38.4 h1:S9T7mTe9KPcFe4dOoOtVdI6gPzht9y7wMnYfUBgrQLo= github.com/erigontech/mdbx-go v0.38.4/go.mod h1:IcOLQDPw3VM/asP6T5JVPPN4FHHgJtY16XfYjzWKVNI= github.com/erigontech/secp256k1 v1.1.0 h1:mO3YJMUSoASE15Ya//SoHiisptUhdXExuMUN1M0X9qY= diff --git a/erigon-lib/gointerfaces/remoteproto/ethbackend.pb.go b/erigon-lib/gointerfaces/remoteproto/ethbackend.pb.go index 62a4302d0b0..fbef7e8dd8f 100644 --- a/erigon-lib/gointerfaces/remoteproto/ethbackend.pb.go +++ b/erigon-lib/gointerfaces/remoteproto/ethbackend.pb.go @@ -1310,6 +1310,7 @@ type TxnLookupReply struct { unknownFields protoimpl.UnknownFields BlockNumber uint64 `protobuf:"varint,1,opt,name=block_number,json=blockNumber,proto3" json:"block_number,omitempty"` + TxNumber uint64 `protobuf:"varint,2,opt,name=tx_number,json=txNumber,proto3" json:"tx_number,omitempty"` } func (x *TxnLookupReply) Reset() { @@ -1351,6 +1352,13 @@ func (x *TxnLookupReply) GetBlockNumber() uint64 { return 0 } +func (x *TxnLookupReply) GetTxNumber() uint64 { + if x != nil { + return x.TxNumber + } + return 0 +} + type NodesInfoRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1916,131 +1924,133 @@ var file_remote_ethbackend_proto_rawDesc = []byte{ 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x26, 0x0a, 0x08, 0x74, 0x78, 0x6e, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x48, 0x32, 0x35, 0x36, 0x52, 0x07, 0x74, 0x78, - 0x6e, 0x48, 0x61, 0x73, 0x68, 0x22, 0x33, 0x0a, 0x0e, 0x54, 0x78, 0x6e, 0x4c, 0x6f, 0x6f, 0x6b, + 0x6e, 0x48, 0x61, 0x73, 0x68, 0x22, 0x50, 0x0a, 0x0e, 0x54, 0x78, 0x6e, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x21, 0x0a, 0x0c, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x62, - 0x6c, 0x6f, 0x63, 0x6b, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x22, 0x28, 0x0a, 0x10, 0x4e, 0x6f, - 0x64, 0x65, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, - 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x6c, - 0x69, 0x6d, 0x69, 0x74, 0x22, 0x22, 0x0a, 0x0e, 0x41, 0x64, 0x64, 0x50, 0x65, 0x65, 0x72, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x22, 0x45, 0x0a, 0x0e, 0x4e, 0x6f, 0x64, 0x65, - 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x33, 0x0a, 0x0a, 0x6e, 0x6f, - 0x64, 0x65, 0x73, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, - 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, - 0x65, 0x70, 0x6c, 0x79, 0x52, 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x22, - 0x33, 0x0a, 0x0a, 0x50, 0x65, 0x65, 0x72, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x25, 0x0a, - 0x05, 0x70, 0x65, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, - 0x79, 0x70, 0x65, 0x73, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x05, 0x70, - 0x65, 0x65, 0x72, 0x73, 0x22, 0x28, 0x0a, 0x0c, 0x41, 0x64, 0x64, 0x50, 0x65, 0x65, 0x72, 0x52, - 0x65, 0x70, 0x6c, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x22, 0x30, - 0x0a, 0x11, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, - 0x70, 0x6c, 0x79, 0x12, 0x1b, 0x0a, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x72, 0x6c, 0x70, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x6c, 0x70, - 0x22, 0x4c, 0x0a, 0x25, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x47, 0x65, 0x74, 0x50, 0x61, 0x79, - 0x6c, 0x6f, 0x61, 0x64, 0x42, 0x6f, 0x64, 0x69, 0x65, 0x73, 0x42, 0x79, 0x48, 0x61, 0x73, 0x68, - 0x56, 0x31, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x23, 0x0a, 0x06, 0x68, 0x61, 0x73, - 0x68, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x74, 0x79, 0x70, 0x65, - 0x73, 0x2e, 0x48, 0x32, 0x35, 0x36, 0x52, 0x06, 0x68, 0x61, 0x73, 0x68, 0x65, 0x73, 0x22, 0x54, - 0x0a, 0x26, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x47, 0x65, 0x74, 0x50, 0x61, 0x79, 0x6c, 0x6f, - 0x61, 0x64, 0x42, 0x6f, 0x64, 0x69, 0x65, 0x73, 0x42, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x56, - 0x31, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, - 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x14, - 0x0a, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x63, - 0x6f, 0x75, 0x6e, 0x74, 0x2a, 0x4a, 0x0a, 0x05, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x0a, 0x0a, - 0x06, 0x48, 0x45, 0x41, 0x44, 0x45, 0x52, 0x10, 0x00, 0x12, 0x10, 0x0a, 0x0c, 0x50, 0x45, 0x4e, - 0x44, 0x49, 0x4e, 0x47, 0x5f, 0x4c, 0x4f, 0x47, 0x53, 0x10, 0x01, 0x12, 0x11, 0x0a, 0x0d, 0x50, - 0x45, 0x4e, 0x44, 0x49, 0x4e, 0x47, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x10, 0x02, 0x12, 0x10, - 0x0a, 0x0c, 0x4e, 0x45, 0x57, 0x5f, 0x53, 0x4e, 0x41, 0x50, 0x53, 0x48, 0x4f, 0x54, 0x10, 0x03, - 0x32, 0xd3, 0x0a, 0x0a, 0x0a, 0x45, 0x54, 0x48, 0x42, 0x41, 0x43, 0x4b, 0x45, 0x4e, 0x44, 0x12, - 0x3d, 0x0a, 0x09, 0x45, 0x74, 0x68, 0x65, 0x72, 0x62, 0x61, 0x73, 0x65, 0x12, 0x18, 0x2e, 0x72, - 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x45, 0x74, 0x68, 0x65, 0x72, 0x62, 0x61, 0x73, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, - 0x45, 0x74, 0x68, 0x65, 0x72, 0x62, 0x61, 0x73, 0x65, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x40, - 0x0a, 0x0a, 0x4e, 0x65, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x19, 0x2e, 0x72, - 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x4e, 0x65, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, - 0x2e, 0x4e, 0x65, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x70, 0x6c, 0x79, - 0x12, 0x46, 0x0a, 0x0c, 0x4e, 0x65, 0x74, 0x50, 0x65, 0x65, 0x72, 0x43, 0x6f, 0x75, 0x6e, 0x74, - 0x12, 0x1b, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x4e, 0x65, 0x74, 0x50, 0x65, 0x65, - 0x72, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, + 0x6c, 0x6f, 0x63, 0x6b, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x78, + 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x74, + 0x78, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x22, 0x28, 0x0a, 0x10, 0x4e, 0x6f, 0x64, 0x65, 0x73, + 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x6c, + 0x69, 0x6d, 0x69, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, + 0x74, 0x22, 0x22, 0x0a, 0x0e, 0x41, 0x64, 0x64, 0x50, 0x65, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x03, 0x75, 0x72, 0x6c, 0x22, 0x45, 0x0a, 0x0e, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x49, 0x6e, + 0x66, 0x6f, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x33, 0x0a, 0x0a, 0x6e, 0x6f, 0x64, 0x65, 0x73, + 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x74, 0x79, + 0x70, 0x65, 0x73, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x70, 0x6c, + 0x79, 0x52, 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x33, 0x0a, 0x0a, + 0x50, 0x65, 0x65, 0x72, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x25, 0x0a, 0x05, 0x70, 0x65, + 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, 0x79, 0x70, 0x65, + 0x73, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x05, 0x70, 0x65, 0x65, 0x72, + 0x73, 0x22, 0x28, 0x0a, 0x0c, 0x41, 0x64, 0x64, 0x50, 0x65, 0x65, 0x72, 0x52, 0x65, 0x70, 0x6c, + 0x79, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x22, 0x30, 0x0a, 0x11, 0x50, + 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x70, 0x6c, 0x79, + 0x12, 0x1b, 0x0a, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x72, 0x6c, 0x70, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x08, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x6c, 0x70, 0x22, 0x4c, 0x0a, + 0x25, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x47, 0x65, 0x74, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, + 0x64, 0x42, 0x6f, 0x64, 0x69, 0x65, 0x73, 0x42, 0x79, 0x48, 0x61, 0x73, 0x68, 0x56, 0x31, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x23, 0x0a, 0x06, 0x68, 0x61, 0x73, 0x68, 0x65, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x48, + 0x32, 0x35, 0x36, 0x52, 0x06, 0x68, 0x61, 0x73, 0x68, 0x65, 0x73, 0x22, 0x54, 0x0a, 0x26, 0x45, + 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x47, 0x65, 0x74, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x42, + 0x6f, 0x64, 0x69, 0x65, 0x73, 0x42, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x56, 0x31, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x63, + 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e, + 0x74, 0x2a, 0x4a, 0x0a, 0x05, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x0a, 0x0a, 0x06, 0x48, 0x45, + 0x41, 0x44, 0x45, 0x52, 0x10, 0x00, 0x12, 0x10, 0x0a, 0x0c, 0x50, 0x45, 0x4e, 0x44, 0x49, 0x4e, + 0x47, 0x5f, 0x4c, 0x4f, 0x47, 0x53, 0x10, 0x01, 0x12, 0x11, 0x0a, 0x0d, 0x50, 0x45, 0x4e, 0x44, + 0x49, 0x4e, 0x47, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x10, 0x02, 0x12, 0x10, 0x0a, 0x0c, 0x4e, + 0x45, 0x57, 0x5f, 0x53, 0x4e, 0x41, 0x50, 0x53, 0x48, 0x4f, 0x54, 0x10, 0x03, 0x32, 0xd3, 0x0a, + 0x0a, 0x0a, 0x45, 0x54, 0x48, 0x42, 0x41, 0x43, 0x4b, 0x45, 0x4e, 0x44, 0x12, 0x3d, 0x0a, 0x09, + 0x45, 0x74, 0x68, 0x65, 0x72, 0x62, 0x61, 0x73, 0x65, 0x12, 0x18, 0x2e, 0x72, 0x65, 0x6d, 0x6f, + 0x74, 0x65, 0x2e, 0x45, 0x74, 0x68, 0x65, 0x72, 0x62, 0x61, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x45, 0x74, 0x68, + 0x65, 0x72, 0x62, 0x61, 0x73, 0x65, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x40, 0x0a, 0x0a, 0x4e, + 0x65, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x19, 0x2e, 0x72, 0x65, 0x6d, 0x6f, + 0x74, 0x65, 0x2e, 0x4e, 0x65, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x4e, 0x65, + 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x46, 0x0a, + 0x0c, 0x4e, 0x65, 0x74, 0x50, 0x65, 0x65, 0x72, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1b, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x4e, 0x65, 0x74, 0x50, 0x65, 0x65, 0x72, 0x43, 0x6f, - 0x75, 0x6e, 0x74, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x36, 0x0a, 0x07, 0x56, 0x65, 0x72, 0x73, - 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x13, 0x2e, 0x74, 0x79, - 0x70, 0x65, 0x73, 0x2e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x70, 0x6c, 0x79, - 0x12, 0x37, 0x0a, 0x07, 0x53, 0x79, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x12, 0x16, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, - 0x70, 0x74, 0x79, 0x1a, 0x14, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x53, 0x79, 0x6e, - 0x63, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x4f, 0x0a, 0x0f, 0x50, 0x72, 0x6f, - 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x2e, 0x72, - 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x56, 0x65, - 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x72, - 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x56, 0x65, - 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x49, 0x0a, 0x0d, 0x43, 0x6c, - 0x69, 0x65, 0x6e, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1c, 0x2e, 0x72, 0x65, - 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, - 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x72, 0x65, 0x6d, 0x6f, - 0x74, 0x65, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, - 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x3f, 0x0a, 0x09, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, - 0x62, 0x65, 0x12, 0x18, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x53, 0x75, 0x62, 0x73, - 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x72, - 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, - 0x65, 0x70, 0x6c, 0x79, 0x30, 0x01, 0x12, 0x4a, 0x0a, 0x0d, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, - 0x69, 0x62, 0x65, 0x4c, 0x6f, 0x67, 0x73, 0x12, 0x19, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, - 0x2e, 0x4c, 0x6f, 0x67, 0x73, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x53, 0x75, 0x62, 0x73, - 0x63, 0x72, 0x69, 0x62, 0x65, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x28, 0x01, - 0x30, 0x01, 0x12, 0x31, 0x0a, 0x05, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x14, 0x2e, 0x72, 0x65, - 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x12, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, - 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x67, 0x0a, 0x17, 0x43, 0x61, 0x6e, 0x6f, 0x6e, 0x69, 0x63, - 0x61, 0x6c, 0x42, 0x6f, 0x64, 0x79, 0x46, 0x6f, 0x72, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, - 0x12, 0x26, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x43, 0x61, 0x6e, 0x6f, 0x6e, 0x69, - 0x63, 0x61, 0x6c, 0x42, 0x6f, 0x64, 0x79, 0x46, 0x6f, 0x72, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, - 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, - 0x65, 0x2e, 0x43, 0x61, 0x6e, 0x6f, 0x6e, 0x69, 0x63, 0x61, 0x6c, 0x42, 0x6f, 0x64, 0x79, 0x46, - 0x6f, 0x72, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x49, - 0x0a, 0x0d, 0x43, 0x61, 0x6e, 0x6f, 0x6e, 0x69, 0x63, 0x61, 0x6c, 0x48, 0x61, 0x73, 0x68, 0x12, - 0x1c, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x43, 0x61, 0x6e, 0x6f, 0x6e, 0x69, 0x63, - 0x61, 0x6c, 0x48, 0x61, 0x73, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, + 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x72, 0x65, 0x6d, + 0x6f, 0x74, 0x65, 0x2e, 0x4e, 0x65, 0x74, 0x50, 0x65, 0x65, 0x72, 0x43, 0x6f, 0x75, 0x6e, 0x74, + 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x36, 0x0a, 0x07, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x13, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, + 0x2e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x37, 0x0a, + 0x07, 0x53, 0x79, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, + 0x1a, 0x14, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x69, 0x6e, + 0x67, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x4f, 0x0a, 0x0f, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, + 0x6f, 0x6c, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x2e, 0x72, 0x65, 0x6d, 0x6f, + 0x74, 0x65, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x56, 0x65, 0x72, 0x73, 0x69, + 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x72, 0x65, 0x6d, 0x6f, + 0x74, 0x65, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x56, 0x65, 0x72, 0x73, 0x69, + 0x6f, 0x6e, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x49, 0x0a, 0x0d, 0x43, 0x6c, 0x69, 0x65, 0x6e, + 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1c, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, + 0x65, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, + 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x70, + 0x6c, 0x79, 0x12, 0x3f, 0x0a, 0x09, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x12, + 0x18, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, + 0x62, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x72, 0x65, 0x6d, 0x6f, + 0x74, 0x65, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x65, 0x70, 0x6c, + 0x79, 0x30, 0x01, 0x12, 0x4a, 0x0a, 0x0d, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, + 0x4c, 0x6f, 0x67, 0x73, 0x12, 0x19, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x4c, 0x6f, + 0x67, 0x73, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x1a, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, + 0x62, 0x65, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x28, 0x01, 0x30, 0x01, 0x12, + 0x31, 0x0a, 0x05, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x14, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, + 0x65, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, + 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x70, + 0x6c, 0x79, 0x12, 0x67, 0x0a, 0x17, 0x43, 0x61, 0x6e, 0x6f, 0x6e, 0x69, 0x63, 0x61, 0x6c, 0x42, + 0x6f, 0x64, 0x79, 0x46, 0x6f, 0x72, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x12, 0x26, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x43, 0x61, 0x6e, 0x6f, 0x6e, 0x69, 0x63, 0x61, 0x6c, - 0x48, 0x61, 0x73, 0x68, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x46, 0x0a, 0x0c, 0x48, 0x65, 0x61, - 0x64, 0x65, 0x72, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x1b, 0x2e, 0x72, 0x65, 0x6d, 0x6f, - 0x74, 0x65, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, - 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x65, 0x70, 0x6c, - 0x79, 0x12, 0x3d, 0x0a, 0x09, 0x54, 0x78, 0x6e, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x12, 0x18, - 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x54, 0x78, 0x6e, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, - 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, - 0x65, 0x2e, 0x54, 0x78, 0x6e, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x52, 0x65, 0x70, 0x6c, 0x79, - 0x12, 0x3c, 0x0a, 0x08, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x18, 0x2e, 0x72, - 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, - 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x33, - 0x0a, 0x05, 0x50, 0x65, 0x65, 0x72, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, - 0x12, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x73, 0x52, 0x65, - 0x70, 0x6c, 0x79, 0x12, 0x37, 0x0a, 0x07, 0x41, 0x64, 0x64, 0x50, 0x65, 0x65, 0x72, 0x12, 0x16, - 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x41, 0x64, 0x64, 0x50, 0x65, 0x65, 0x72, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, - 0x41, 0x64, 0x64, 0x50, 0x65, 0x65, 0x72, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x41, 0x0a, 0x0c, - 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x16, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, - 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x19, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x50, 0x65, - 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, - 0x46, 0x0a, 0x0c, 0x42, 0x6f, 0x72, 0x54, 0x78, 0x6e, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x12, - 0x1b, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x42, 0x6f, 0x72, 0x54, 0x78, 0x6e, 0x4c, - 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x72, + 0x42, 0x6f, 0x64, 0x79, 0x46, 0x6f, 0x72, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x43, + 0x61, 0x6e, 0x6f, 0x6e, 0x69, 0x63, 0x61, 0x6c, 0x42, 0x6f, 0x64, 0x79, 0x46, 0x6f, 0x72, 0x53, + 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x49, 0x0a, 0x0d, 0x43, + 0x61, 0x6e, 0x6f, 0x6e, 0x69, 0x63, 0x61, 0x6c, 0x48, 0x61, 0x73, 0x68, 0x12, 0x1c, 0x2e, 0x72, + 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x43, 0x61, 0x6e, 0x6f, 0x6e, 0x69, 0x63, 0x61, 0x6c, 0x48, + 0x61, 0x73, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x72, 0x65, 0x6d, + 0x6f, 0x74, 0x65, 0x2e, 0x43, 0x61, 0x6e, 0x6f, 0x6e, 0x69, 0x63, 0x61, 0x6c, 0x48, 0x61, 0x73, + 0x68, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x46, 0x0a, 0x0c, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x1b, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, + 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x48, 0x65, 0x61, + 0x64, 0x65, 0x72, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x3d, + 0x0a, 0x09, 0x54, 0x78, 0x6e, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x12, 0x18, 0x2e, 0x72, 0x65, + 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x54, 0x78, 0x6e, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x54, + 0x78, 0x6e, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x3c, 0x0a, + 0x08, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x18, 0x2e, 0x72, 0x65, 0x6d, 0x6f, + 0x74, 0x65, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x4e, 0x6f, 0x64, + 0x65, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x33, 0x0a, 0x05, 0x50, + 0x65, 0x65, 0x72, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x12, 0x2e, 0x72, + 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x79, + 0x12, 0x37, 0x0a, 0x07, 0x41, 0x64, 0x64, 0x50, 0x65, 0x65, 0x72, 0x12, 0x16, 0x2e, 0x72, 0x65, + 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x41, 0x64, 0x64, 0x50, 0x65, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x41, 0x64, 0x64, + 0x50, 0x65, 0x65, 0x72, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x41, 0x0a, 0x0c, 0x50, 0x65, 0x6e, + 0x64, 0x69, 0x6e, 0x67, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, + 0x79, 0x1a, 0x19, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x50, 0x65, 0x6e, 0x64, 0x69, + 0x6e, 0x67, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x46, 0x0a, 0x0c, + 0x42, 0x6f, 0x72, 0x54, 0x78, 0x6e, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x12, 0x1b, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x42, 0x6f, 0x72, 0x54, 0x78, 0x6e, 0x4c, 0x6f, 0x6f, 0x6b, - 0x75, 0x70, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x3d, 0x0a, 0x09, 0x42, 0x6f, 0x72, 0x45, 0x76, - 0x65, 0x6e, 0x74, 0x73, 0x12, 0x18, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x42, 0x6f, - 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, - 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x42, 0x6f, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, - 0x73, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x42, 0x16, 0x5a, 0x14, 0x2e, 0x2f, 0x72, 0x65, 0x6d, 0x6f, - 0x74, 0x65, 0x3b, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x72, 0x65, 0x6d, 0x6f, + 0x74, 0x65, 0x2e, 0x42, 0x6f, 0x72, 0x54, 0x78, 0x6e, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x52, + 0x65, 0x70, 0x6c, 0x79, 0x12, 0x3d, 0x0a, 0x09, 0x42, 0x6f, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, + 0x73, 0x12, 0x18, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x42, 0x6f, 0x72, 0x45, 0x76, + 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x72, 0x65, + 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x42, 0x6f, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, + 0x70, 0x6c, 0x79, 0x42, 0x16, 0x5a, 0x14, 0x2e, 0x2f, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x3b, + 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x33, } var ( diff --git a/erigon-lib/gointerfaces/remoteproto/kv_grpc.pb.go b/erigon-lib/gointerfaces/remoteproto/kv_grpc.pb.go index f64ddddf7e7..8179df4b950 100644 --- a/erigon-lib/gointerfaces/remoteproto/kv_grpc.pb.go +++ b/erigon-lib/gointerfaces/remoteproto/kv_grpc.pb.go @@ -7,13 +7,12 @@ package remoteproto import ( - "context" - - "github.com/erigontech/erigon-lib/gointerfaces/typesproto" - "google.golang.org/grpc" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" - "google.golang.org/protobuf/types/known/emptypb" + context "context" + typesproto "github.com/erigontech/erigon-lib/gointerfaces/typesproto" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + emptypb "google.golang.org/protobuf/types/known/emptypb" ) // This is a compile-time assertion to ensure that this generated file diff --git a/erigon-lib/state/history.go b/erigon-lib/state/history.go index 78ddeb764c2..13728088c3f 100644 --- a/erigon-lib/state/history.go +++ b/erigon-lib/state/history.go @@ -1079,7 +1079,7 @@ func (ht *HistoryRoTx) Prune(ctx context.Context, rwTx kv.RwTx, txFrom, txTo, li } if ht.h.historyLargeValues { - seek = append(append(seek[:0], k...), txnm...) + seek = append(bytes.Clone(k), txnm...) if err := valsC.Delete(seek); err != nil { return err } diff --git a/eth/stagedsync/stage_txlookup.go b/eth/stagedsync/stage_txlookup.go index 42884727d78..8083945b318 100644 --- a/eth/stagedsync/stage_txlookup.go +++ b/eth/stagedsync/stage_txlookup.go @@ -24,6 +24,7 @@ import ( "time" "github.com/erigontech/erigon-lib/kv/rawdbv3" + "github.com/erigontech/erigon-lib/log/v3" "github.com/erigontech/erigon/eth/stagedsync/stages" @@ -136,7 +137,7 @@ func SpawnTxLookup(s *StageState, tx kv.RwTx, toBlock uint64, cfg TxLookupCfg, c // txnLookupTransform - [startKey, endKey) func txnLookupTransform(logPrefix string, tx kv.RwTx, blockFrom, blockTo uint64, ctx context.Context, cfg TxLookupCfg, logger log.Logger) (err error) { - bigNum := new(big.Int) + data := make([]byte, 16) return etl.Transform(logPrefix, tx, kv.HeaderCanonical, kv.TxLookup, cfg.tmpdir, func(k, v []byte, next etl.ExtractNextFunc) error { blocknum, blockHash := binary.BigEndian.Uint64(k), libcommon.CastToHash(v) body, err := cfg.blockReader.BodyWithTransactions(ctx, tx, blockHash, blocknum) @@ -148,9 +149,21 @@ func txnLookupTransform(logPrefix string, tx kv.RwTx, blockFrom, blockTo uint64, return nil } - blockNumBytes := bigNum.SetUint64(blocknum).Bytes() - for _, txn := range body.Transactions { - if err := next(k, txn.Hash().Bytes(), blockNumBytes); err != nil { + firstTxNumInBlock, err := rawdbv3.TxNums.Min(tx, blocknum) + if err != nil { + return err + } + + if firstTxNumInBlock == 0 { + log.Warn(fmt.Sprintf("[%s] transform: empty txnum %d, hash %x", logPrefix, firstTxNumInBlock, v)) + return nil + } + + binary.BigEndian.PutUint64(data[:8], blocknum) + + for i, txn := range body.Transactions { + binary.BigEndian.PutUint64(data[8:], firstTxNumInBlock+uint64(i)+1) + if err := next(k, txn.Hash().Bytes(), data); err != nil { return err } } @@ -294,6 +307,7 @@ func PruneTxLookup(s *PruneState, tx kv.RwTx, cfg TxLookupCfg, ctx context.Conte if err != nil { return fmt.Errorf("prune TxLookUp: %w", err) } + if cfg.borConfig != nil && pruneBor { if err = deleteBorTxLookupRange(tx, logPrefix, pruneBlockNum, pruneBlockNum+1, ctx, cfg, logger); err != nil { return fmt.Errorf("prune BorTxLookUp: %w", err) diff --git a/ethdb/privateapi/ethbackend.go b/ethdb/privateapi/ethbackend.go index 4fab7e5beaa..9e67064ba1f 100644 --- a/ethdb/privateapi/ethbackend.go +++ b/ethdb/privateapi/ethbackend.go @@ -275,15 +275,15 @@ func (s *EthBackendServer) TxnLookup(ctx context.Context, req *remote.TxnLookupR } defer tx.Rollback() - blockNum, ok, err := s.blockReader.TxnLookup(ctx, tx, gointerfaces.ConvertH256ToHash(req.TxnHash)) + blockNum, txNum, ok, err := s.blockReader.TxnLookup(ctx, tx, gointerfaces.ConvertH256ToHash(req.TxnHash)) if err != nil { return nil, err } if !ok { // Not a perfect solution, assumes there are no transactions in block 0 - return &remote.TxnLookupReply{BlockNumber: 0}, nil + return &remote.TxnLookupReply{BlockNumber: 0, TxNumber: txNum}, nil } - return &remote.TxnLookupReply{BlockNumber: blockNum}, nil + return &remote.TxnLookupReply{BlockNumber: blockNum, TxNumber: txNum}, nil } func (s *EthBackendServer) Block(ctx context.Context, req *remote.BlockRequest) (*remote.BlockReply, error) { diff --git a/migrations/migrations.go b/migrations/migrations.go index 211d77f860e..5fc2d4ed99b 100644 --- a/migrations/migrations.go +++ b/migrations/migrations.go @@ -55,6 +55,7 @@ var migrations = map[kv.Label][]Migration{ ProhibitNewDownloadsLock, ProhibitNewDownloadsLock2, ClearBorTables, + ResetStageTxnLookup, }, kv.TxPoolDB: {}, kv.SentryDB: {}, diff --git a/migrations/reset_stage_txn_lookup.go b/migrations/reset_stage_txn_lookup.go new file mode 100644 index 00000000000..d4c9e7cb8b2 --- /dev/null +++ b/migrations/reset_stage_txn_lookup.go @@ -0,0 +1,47 @@ +// Copyright 2024 The Erigon Authors +// This file is part of Erigon. +// +// Erigon is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Erigon is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with Erigon. If not, see . + +package migrations + +import ( + "context" + "github.com/erigontech/erigon-lib/common/datadir" + "github.com/erigontech/erigon-lib/kv" + "github.com/erigontech/erigon-lib/log/v3" + reset2 "github.com/erigontech/erigon/core/rawdb/rawdbreset" +) + +// for new txn index. +var ResetStageTxnLookup = Migration{ + Name: "reset_stage_txn_lookup", + Up: func(db kv.RwDB, dirs datadir.Dirs, progress []byte, BeforeCommit Callback, logger log.Logger) (err error) { + tx, err := db.BeginRw(context.Background()) + if err != nil { + return err + } + defer tx.Rollback() + + if err := BeforeCommit(tx, nil, true); err != nil { + return err + } + + if err := reset2.ResetTxLookup(tx); err != nil { + return err + } + + return tx.Commit() + }, +} diff --git a/turbo/jsonrpc/eth_api.go b/turbo/jsonrpc/eth_api.go index cab6a993190..70b3876eaa6 100644 --- a/turbo/jsonrpc/eth_api.go +++ b/turbo/jsonrpc/eth_api.go @@ -192,7 +192,7 @@ func (api *BaseAPI) genesis(ctx context.Context, tx kv.Tx) (*types.Block, error) return genesis, err } -func (api *BaseAPI) txnLookup(ctx context.Context, tx kv.Tx, txnHash common.Hash) (uint64, bool, error) { +func (api *BaseAPI) txnLookup(ctx context.Context, tx kv.Tx, txnHash common.Hash) (blockNum uint64, txNum uint64, ok bool, err error) { return api._txnReader.TxnLookup(ctx, tx, txnHash) } diff --git a/turbo/jsonrpc/eth_block.go b/turbo/jsonrpc/eth_block.go index 279978b68b1..880615dfd73 100644 --- a/turbo/jsonrpc/eth_block.go +++ b/turbo/jsonrpc/eth_block.go @@ -67,7 +67,7 @@ func (api *APIImpl) CallBundle(ctx context.Context, txHashes []common.Hash, stat var txs types.Transactions for _, txHash := range txHashes { - blockNum, ok, err := api.txnLookup(ctx, tx, txHash) + blockNum, _, ok, err := api.txnLookup(ctx, tx, txHash) if err != nil { return nil, err } diff --git a/turbo/jsonrpc/eth_receipts.go b/turbo/jsonrpc/eth_receipts.go index 92066aaf4a4..10edc6a73a5 100644 --- a/turbo/jsonrpc/eth_receipts.go +++ b/turbo/jsonrpc/eth_receipts.go @@ -51,8 +51,8 @@ func (api *BaseAPI) getReceipts(ctx context.Context, tx kv.Tx, block *types.Bloc return api.receiptsGenerator.GetReceipts(ctx, chainConfig, tx, block) } -func (api *BaseAPI) getReceipt(ctx context.Context, cc *chain.Config, tx kv.Tx, block *types.Block, index int, optimize bool) (*types.Receipt, error) { - return api.receiptsGenerator.GetReceipt(ctx, cc, tx, block, index, optimize) +func (api *BaseAPI) getReceipt(ctx context.Context, cc *chain.Config, tx kv.TemporalTx, block *types.Block, index int, txNum uint64) (*types.Receipt, error) { + return api.receiptsGenerator.GetReceipt(ctx, cc, tx, block, index, txNum) } func (api *BaseAPI) getCachedReceipts(ctx context.Context, hash common.Hash) (types.Receipts, bool) { @@ -407,18 +407,22 @@ func (api *APIImpl) GetTransactionReceipt(ctx context.Context, txnHash common.Ha } defer tx.Rollback() - var blockNum uint64 + var blockNum, txNum uint64 var ok bool - blockNum, ok, err = api.txnLookup(ctx, tx, txnHash) + chainConfig, err := api.chainConfig(ctx, tx) if err != nil { return nil, err } - chainConfig, err := api.chainConfig(ctx, tx) + blockNum, txNum, ok, err = api.txnLookup(ctx, tx, txnHash) if err != nil { return nil, err } + if !ok && chainConfig.Bor == nil { + return nil, nil + } + // Private API returns 0 if transaction is not found. if blockNum == 0 && chainConfig.Bor != nil { if api.useBridgeReader { @@ -476,13 +480,12 @@ func (api *APIImpl) GetTransactionReceipt(ctx context.Context, txnHash common.Ha return ethutils.MarshalReceipt(borReceipt, bortypes.NewBorTransaction(), chainConfig, block.HeaderNoCopy(), txnHash, false), nil } - receipt, err := api.getReceipt(ctx, chainConfig, tx, block, int(txnIndex), false) + receipt, err := api.getReceipt(ctx, chainConfig, tx.(kv.TemporalTx), block, int(txnIndex), txNum) if err != nil { return nil, fmt.Errorf("getReceipt error: %w", err) } return ethutils.MarshalReceipt(receipt, block.Transactions()[txnIndex], chainConfig, block.HeaderNoCopy(), txnHash, true), nil - } // GetBlockReceipts - receipts for individual block diff --git a/turbo/jsonrpc/eth_txs.go b/turbo/jsonrpc/eth_txs.go index f81ba55d972..b53134c4fcb 100644 --- a/turbo/jsonrpc/eth_txs.go +++ b/turbo/jsonrpc/eth_txs.go @@ -49,7 +49,7 @@ func (api *APIImpl) GetTransactionByHash(ctx context.Context, txnHash common.Has } // https://infura.io/docs/ethereum/json-rpc/eth-getTransactionByHash - blockNum, ok, err := api.txnLookup(ctx, tx, txnHash) + blockNum, _, ok, err := api.txnLookup(ctx, tx, txnHash) if err != nil { return nil, err } @@ -139,7 +139,7 @@ func (api *APIImpl) GetRawTransactionByHash(ctx context.Context, hash common.Has defer tx.Rollback() // https://infura.io/docs/ethereum/json-rpc/eth-getTransactionByHash - blockNum, ok, err := api.txnLookup(ctx, tx, hash) + blockNum, _, ok, err := api.txnLookup(ctx, tx, hash) if err != nil { return nil, err } diff --git a/turbo/jsonrpc/otterscan_api.go b/turbo/jsonrpc/otterscan_api.go index b6f9eb9fd31..272f6327581 100644 --- a/turbo/jsonrpc/otterscan_api.go +++ b/turbo/jsonrpc/otterscan_api.go @@ -90,7 +90,7 @@ func (api *OtterscanAPIImpl) GetApiLevel() uint8 { // TODO: dedup from eth_txs.go#GetTransactionByHash func (api *OtterscanAPIImpl) getTransactionByHash(ctx context.Context, tx kv.Tx, hash common.Hash) (types.Transaction, *types.Block, common.Hash, uint64, uint64, error) { // https://infura.io/docs/ethereum/json-rpc/eth-getTransactionByHash - blockNum, ok, err := api.txnLookup(ctx, tx, hash) + blockNum, _, ok, err := api.txnLookup(ctx, tx, hash) if err != nil { return nil, nil, common.Hash{}, 0, 0, err } diff --git a/turbo/jsonrpc/otterscan_search_v3.go b/turbo/jsonrpc/otterscan_search_v3.go index 1bdc05874cd..dbc34b5a18a 100644 --- a/turbo/jsonrpc/otterscan_search_v3.go +++ b/turbo/jsonrpc/otterscan_search_v3.go @@ -53,7 +53,7 @@ func (api *OtterscanAPIImpl) buildSearchResults(ctx context.Context, tx kv.Tempo reachedPageSize := false hasMore := false for txNumsIter.HasNext() { - _, blockNum, txIndex, isFinalTxn, blockNumChanged, err := txNumsIter.Next() + txNum, blockNum, txIndex, isFinalTxn, blockNumChanged, err := txNumsIter.Next() if err != nil { return nil, nil, false, err } @@ -96,7 +96,7 @@ func (api *OtterscanAPIImpl) buildSearchResults(ctx context.Context, tx kv.Tempo rpcTx := NewRPCTransaction(txn, block.Hash(), blockNum, uint64(txIndex), block.BaseFee()) txs = append(txs, rpcTx) - receipt, err := api.receiptsGenerator.GetReceipt(ctx, chainConfig, tx, block, txIndex, false) + receipt, err := api.receiptsGenerator.GetReceipt(ctx, chainConfig, tx, block, txIndex, txNum+1) if err != nil { return nil, nil, false, err } diff --git a/turbo/jsonrpc/overlay_api.go b/turbo/jsonrpc/overlay_api.go index dead2ff8405..d3f3585ecd4 100644 --- a/turbo/jsonrpc/overlay_api.go +++ b/turbo/jsonrpc/overlay_api.go @@ -115,7 +115,7 @@ func (api *OverlayAPIImpl) CallConstructor(ctx context.Context, address common.A return nil, err } - blockNum, ok, err := api.txnLookup(ctx, tx, creationData.Tx) + blockNum, _, ok, err := api.txnLookup(ctx, tx, creationData.Tx) if err != nil { return nil, err } diff --git a/turbo/jsonrpc/receipts/receipts_generator.go b/turbo/jsonrpc/receipts/receipts_generator.go index 05d6f92fa7b..5b2138e4339 100644 --- a/turbo/jsonrpc/receipts/receipts_generator.go +++ b/turbo/jsonrpc/receipts/receipts_generator.go @@ -12,6 +12,7 @@ import ( "github.com/erigontech/erigon-lib/log/v3" "github.com/erigontech/erigon/consensus" "github.com/erigontech/erigon/core" + "github.com/erigontech/erigon/core/rawdb/rawtemporaldb" "github.com/erigontech/erigon/core/state" "github.com/erigontech/erigon/core/types" "github.com/erigontech/erigon/core/vm" @@ -106,38 +107,34 @@ func (g *Generator) addToCache(header *types.Header, receipts types.Receipts) { g.receiptsCache.Add(header.Hash(), receipts.Copy()) // .Copy() helps pprof to attribute memory to cache - instead of evm (where it was allocated). } -func (g *Generator) GetReceipt(ctx context.Context, cfg *chain.Config, tx kv.Tx, block *types.Block, index int, optimize bool) (*types.Receipt, error) { +func (g *Generator) GetReceipt(ctx context.Context, cfg *chain.Config, tx kv.TemporalTx, block *types.Block, index int, txNum uint64) (*types.Receipt, error) { if receipts, ok := g.receiptsCache.Get(block.Hash()); ok && len(receipts) > index { return receipts[index], nil } - var receipt *types.Receipt - if optimize { - genEnv, err := g.PrepareEnv(ctx, block, cfg, tx, index) - if err != nil { - return nil, err - } - receipt, _, err = core.ApplyTransaction(cfg, core.GetHashFn(genEnv.header, genEnv.getHeader), g.engine, nil, genEnv.gp, genEnv.ibs, genEnv.noopWriter, genEnv.header, block.Transactions()[index], genEnv.usedGas, genEnv.usedBlobGas, vm.Config{}) - if err != nil { - return nil, fmt.Errorf("ReceiptGen.GetReceipt: bn=%d, txnIdx=%d, %w", block.NumberU64(), index, err) - } - receipt.BlockHash = block.Hash() - } else { - genEnv, err := g.PrepareEnv(ctx, block, cfg, tx, 0) - if err != nil { - return nil, err - } - for i, txn := range block.Transactions() { - genEnv.ibs.SetTxContext(i) - receipt, _, err = core.ApplyTransaction(cfg, core.GetHashFn(genEnv.header, genEnv.getHeader), g.engine, nil, genEnv.gp, genEnv.ibs, genEnv.noopWriter, genEnv.header, txn, genEnv.usedGas, genEnv.usedBlobGas, vm.Config{}) - if err != nil { - return nil, fmt.Errorf("ReceiptGen.GetReceipt: bn=%d, txnIdx=%d, %w", block.NumberU64(), i, err) - } - receipt.BlockHash = block.Hash() - if i == index { - break - } - } + genEnv, err := g.PrepareEnv(ctx, block, cfg, tx, index) + if err != nil { + return nil, err + } + + cumGasUsed, _, firstLogIndex, err := rawtemporaldb.ReceiptAsOf(tx, txNum) + if err != nil { + return nil, err + } + + receipt, _, err = core.ApplyTransaction(cfg, core.GetHashFn(genEnv.header, genEnv.getHeader), g.engine, nil, genEnv.gp, genEnv.ibs, genEnv.noopWriter, genEnv.header, block.Transactions()[index], genEnv.usedGas, genEnv.usedBlobGas, vm.Config{}) + if err != nil { + return nil, fmt.Errorf("ReceiptGen.GetReceipt: bn=%d, txnIdx=%d, %w", block.NumberU64(), index, err) + } + + receipt.BlockHash = block.Hash() + + receipt.CumulativeGasUsed = cumGasUsed + receipt.TransactionIndex = uint(index) + + for i := range receipt.Logs { + receipt.Logs[i].TxIndex = uint(index) + receipt.Logs[i].Index = uint(firstLogIndex + uint32(i)) } return receipt, nil diff --git a/turbo/jsonrpc/trace_adhoc.go b/turbo/jsonrpc/trace_adhoc.go index 0a24f0beca4..1434461bd35 100644 --- a/turbo/jsonrpc/trace_adhoc.go +++ b/turbo/jsonrpc/trace_adhoc.go @@ -817,7 +817,7 @@ func (api *TraceAPIImpl) ReplayTransaction(ctx context.Context, txHash libcommon } var isBorStateSyncTxn bool - blockNum, ok, err := api.txnLookup(ctx, tx, txHash) + blockNum, _, ok, err := api.txnLookup(ctx, tx, txHash) if err != nil { return nil, err } diff --git a/turbo/jsonrpc/trace_filtering.go b/turbo/jsonrpc/trace_filtering.go index 70a8ca5985d..3b04ed3f46d 100644 --- a/turbo/jsonrpc/trace_filtering.go +++ b/turbo/jsonrpc/trace_filtering.go @@ -67,7 +67,7 @@ func (api *TraceAPIImpl) Transaction(ctx context.Context, txHash common.Hash, ga } var isBorStateSyncTxn bool - blockNumber, ok, err := api.txnLookup(ctx, tx, txHash) + blockNumber, _, ok, err := api.txnLookup(ctx, tx, txHash) if err != nil { return nil, err } diff --git a/turbo/jsonrpc/tracing.go b/turbo/jsonrpc/tracing.go index 032c42eaa62..d92c7027bdd 100644 --- a/turbo/jsonrpc/tracing.go +++ b/turbo/jsonrpc/tracing.go @@ -252,7 +252,7 @@ func (api *PrivateDebugAPIImpl) TraceTransaction(ctx context.Context, hash commo } // Retrieve the transaction and assemble its EVM context var isBorStateSyncTxn bool - blockNum, ok, err := api.txnLookup(ctx, tx, hash) + blockNum, _, ok, err := api.txnLookup(ctx, tx, hash) if err != nil { stream.WriteNil() return err diff --git a/turbo/services/interfaces.go b/turbo/services/interfaces.go index dd26a7cfd64..ceee3c57569 100644 --- a/turbo/services/interfaces.go +++ b/turbo/services/interfaces.go @@ -96,7 +96,7 @@ type BodyReader interface { } type TxnReader interface { - TxnLookup(ctx context.Context, tx kv.Getter, txnHash common.Hash) (uint64, bool, error) + TxnLookup(ctx context.Context, tx kv.Getter, txnHash common.Hash) (blockNum uint64, txNum uint64, ok bool, err error) TxnByIdxInBlock(ctx context.Context, tx kv.Getter, blockNum uint64, i int) (txn types.Transaction, err error) RawTransactions(ctx context.Context, tx kv.Getter, fromBlock, toBlock uint64) (txs [][]byte, err error) FirstTxnNumNotInSnapshots() uint64 diff --git a/turbo/snapshotsync/freezeblocks/block_reader.go b/turbo/snapshotsync/freezeblocks/block_reader.go index ef87b25f6fb..0ab0faac892 100644 --- a/turbo/snapshotsync/freezeblocks/block_reader.go +++ b/turbo/snapshotsync/freezeblocks/block_reader.go @@ -164,15 +164,15 @@ func NewRemoteBlockReader(client remote.ETHBACKENDClient) *RemoteBlockReader { return &RemoteBlockReader{client} } -func (r *RemoteBlockReader) TxnLookup(ctx context.Context, tx kv.Getter, txnHash common.Hash) (uint64, bool, error) { +func (r *RemoteBlockReader) TxnLookup(ctx context.Context, tx kv.Getter, txnHash common.Hash) (uint64, uint64, bool, error) { reply, err := r.client.TxnLookup(ctx, &remote.TxnLookupRequest{TxnHash: gointerfaces.ConvertHashToH256(txnHash)}) if err != nil { - return 0, false, err + return 0, 0, false, err } if reply == nil { - return 0, false, nil + return 0, 0, false, nil } - return reply.BlockNumber, true, nil + return reply.BlockNumber, reply.TxNumber, true, nil } func (r *RemoteBlockReader) TxnByIdxInBlock(ctx context.Context, tx kv.Getter, blockNum uint64, i int) (txn types.Transaction, err error) { @@ -1082,7 +1082,7 @@ func (r *BlockReader) txnByID(txnID uint64, sn *snapshotsync.VisibleSegment, buf return } -func (r *BlockReader) txnByHash(txnHash common.Hash, segments []*snapshotsync.VisibleSegment, buf []byte) (types.Transaction, uint64, bool, error) { +func (r *BlockReader) txnByHash(txnHash common.Hash, segments []*snapshotsync.VisibleSegment, buf []byte) (types.Transaction, uint64, uint64, bool, error) { for i := len(segments) - 1; i >= 0; i-- { sn := segments[i] @@ -1094,11 +1094,11 @@ func (r *BlockReader) txnByHash(txnHash common.Hash, segments []*snapshotsync.Vi } reader := recsplit.NewIndexReader(idxTxnHash) - txnId, ok := reader.Lookup(txnHash[:]) + txNumInFile, ok := reader.Lookup(txnHash[:]) if !ok { continue } - offset := idxTxnHash.OrdinalLookup(txnId) + offset := idxTxnHash.OrdinalLookup(txNumInFile) gg := sn.Src().MakeGetter() gg.Reset(offset) // first byte txnHash check - reducing false-positives 256 times. Allows don't store and don't calculate full hash of entity - when checking many snapshots. @@ -1111,7 +1111,7 @@ func (r *BlockReader) txnByHash(txnHash common.Hash, segments []*snapshotsync.Vi txn, err := types.DecodeTransaction(txnRlp) if err != nil { - return nil, 0, false, err + return nil, 0, 0, false, err } txn.SetSender(sender) // see: https://tip.golang.org/ref/spec#Conversions_from_slice_to_array_pointer @@ -1124,11 +1124,11 @@ func (r *BlockReader) txnByHash(txnHash common.Hash, segments []*snapshotsync.Vi // final txnHash check - completely avoid false-positives if txn.Hash() == txnHash { - return txn, blockNum, true, nil + return txn, blockNum, idxTxnHash.BaseDataID() + txNumInFile + 1, true, nil } } - return nil, 0, false, nil + return nil, 0, 0, false, nil } // TxnByIdxInBlock - doesn't include system-transactions in the begin/end of block @@ -1178,24 +1178,23 @@ func (r *BlockReader) TxnByIdxInBlock(ctx context.Context, tx kv.Getter, blockNu } // TxnLookup - find blockNumber and txnID by txnHash -func (r *BlockReader) TxnLookup(_ context.Context, tx kv.Getter, txnHash common.Hash) (uint64, bool, error) { - n, err := rawdb.ReadTxLookupEntry(tx, txnHash) +func (r *BlockReader) TxnLookup(_ context.Context, tx kv.Getter, txnHash common.Hash) (blockNum uint64, txNum uint64, ok bool, err error) { + blockNumPointer, txNumPointer, err := rawdb.ReadTxLookupEntry(tx, txnHash) if err != nil { - return 0, false, err + return 0, 0, false, err } - if n != nil { - return *n, true, nil + if blockNumPointer != nil && txNumPointer != nil { + return *blockNumPointer, *txNumPointer, true, nil } txns := r.sn.ViewType(coresnaptype.Transactions) defer txns.Close() - _, blockNum, ok, err := r.txnByHash(txnHash, txns.Segments, nil) + _, blockNum, txNum, ok, err = r.txnByHash(txnHash, txns.Segments, nil) if err != nil { - return 0, false, err + return 0, 0, false, err } - - return blockNum, ok, nil + return blockNum, txNum, ok, nil } func (r *BlockReader) FirstTxnNumNotInSnapshots() uint64 { diff --git a/turbo/stages/blockchain_test.go b/turbo/stages/blockchain_test.go index a37243413bc..ec5f0e34f66 100644 --- a/turbo/stages/blockchain_test.go +++ b/turbo/stages/blockchain_test.go @@ -544,7 +544,7 @@ func TestChainTxReorgs(t *testing.T) { // removed tx txs := types.Transactions{pastDrop, freshDrop} for i, txn := range txs { - if bn, _ := rawdb.ReadTxLookupEntry(tx, txn.Hash()); bn != nil { + if bn, _, _ := rawdb.ReadTxLookupEntry(tx, txn.Hash()); bn != nil { t.Errorf("drop %d: tx %v found while shouldn't have been", i, txn) } if rcpt, _, _, _, _ := readReceipt(tx, txn.Hash(), m); rcpt != nil { @@ -555,18 +555,18 @@ func TestChainTxReorgs(t *testing.T) { // added tx txs = types.Transactions{pastAdd, freshAdd, futureAdd} for i, txn := range txs { - _, found, err := m.BlockReader.TxnLookup(m.Ctx, tx, txn.Hash()) + _, _, found, err := m.BlockReader.TxnLookup(m.Ctx, tx, txn.Hash()) require.NoError(t, err) require.True(t, found) - if rcpt, _, _, _, _ := readReceipt(tx, txn.Hash(), m); rcpt == nil { - t.Errorf("add %d: expected receipt to be found", i) + if rcpt, _, _, _, err := readReceipt(tx, txn.Hash(), m); rcpt == nil { + t.Errorf("add %d: expected receipt to be found, err %v", i, err) } } // shared tx txs = types.Transactions{postponed, swapped} for i, txn := range txs { - if bn, _ := rawdb.ReadTxLookupEntry(tx, txn.Hash()); bn == nil { + if bn, _, _ := rawdb.ReadTxLookupEntry(tx, txn.Hash()); bn == nil { t.Errorf("drop %d: tx %v found while shouldn't have been", i, txn) } @@ -578,7 +578,7 @@ func TestChainTxReorgs(t *testing.T) { func readReceipt(db kv.Tx, txHash libcommon.Hash, m *mock.MockSentry) (*types.Receipt, libcommon.Hash, uint64, uint64, error) { // Retrieve the context of the receipt based on the transaction hash - blockNumber, err := rawdb.ReadTxLookupEntry(db, txHash) + blockNumber, _, err := rawdb.ReadTxLookupEntry(db, txHash) if err != nil { return nil, libcommon.Hash{}, 0, 0, err } @@ -883,7 +883,7 @@ func doModesTest(t *testing.T, pm prune.Mode) error { b, err := m.BlockReader.BlockByNumber(m.Ctx, tx, 1) require.NoError(err) for _, txn := range b.Transactions() { - found, err := rawdb.ReadTxLookupEntry(tx, txn.Hash()) + found, _, err := rawdb.ReadTxLookupEntry(tx, txn.Hash()) require.NoError(err) require.Nil(found) } @@ -891,7 +891,7 @@ func doModesTest(t *testing.T, pm prune.Mode) error { b, err := m.BlockReader.BlockByNumber(m.Ctx, tx, 1) require.NoError(err) for _, txn := range b.Transactions() { - foundBlockNum, found, err := m.BlockReader.TxnLookup(context.Background(), tx, txn.Hash()) + foundBlockNum, _, found, err := m.BlockReader.TxnLookup(context.Background(), tx, txn.Hash()) require.NoError(err) require.True(found) require.Equal(uint64(1), foundBlockNum) From db603607b75be8522a0f95013f41445912e66733 Mon Sep 17 00:00:00 2001 From: Somnath Date: Wed, 11 Dec 2024 18:24:29 +0400 Subject: [PATCH 24/24] jsonrpc: Refactor top level api methods to separate file (#13072) The separate file - `engine_api_methods.go` created to separate out the top level methods, which also have links to their documents. The main `engine_server.go` still holds most important bits of logic. --- turbo/engineapi/engine_api_methods.go | 168 ++++++++++++++++++++++++++ turbo/engineapi/engine_server.go | 157 ------------------------ 2 files changed, 168 insertions(+), 157 deletions(-) create mode 100644 turbo/engineapi/engine_api_methods.go diff --git a/turbo/engineapi/engine_api_methods.go b/turbo/engineapi/engine_api_methods.go new file mode 100644 index 00000000000..43e9b98bce2 --- /dev/null +++ b/turbo/engineapi/engine_api_methods.go @@ -0,0 +1,168 @@ +package engineapi + +import ( + "context" + "encoding/binary" + + libcommon "github.com/erigontech/erigon-lib/common" + "github.com/erigontech/erigon-lib/common/hexutil" + "github.com/erigontech/erigon-lib/common/hexutility" + "github.com/erigontech/erigon/params" + + "github.com/erigontech/erigon/cl/clparams" + "github.com/erigontech/erigon/turbo/engineapi/engine_types" +) + +var ourCapabilities = []string{ + "engine_forkchoiceUpdatedV1", + "engine_forkchoiceUpdatedV2", + "engine_forkchoiceUpdatedV3", + "engine_newPayloadV1", + "engine_newPayloadV2", + "engine_newPayloadV3", + "engine_newPayloadV4", + "engine_getPayloadV1", + "engine_getPayloadV2", + "engine_getPayloadV3", + "engine_getPayloadV4", + "engine_getPayloadBodiesByHashV1", + "engine_getPayloadBodiesByRangeV1", + "engine_getClientVersionV1", +} + +// Returns the most recent version of the payload(for the payloadID) at the time of receiving the call +// See https://github.com/ethereum/execution-apis/blob/main/src/engine/paris.md#engine_getpayloadv1 +func (e *EngineServer) GetPayloadV1(ctx context.Context, payloadId hexutility.Bytes) (*engine_types.ExecutionPayload, error) { + if e.caplin { + e.logger.Crit(caplinEnabledLog) + return nil, errCaplinEnabled + } + e.engineLogSpamer.RecordRequest() + + decodedPayloadId := binary.BigEndian.Uint64(payloadId) + e.logger.Info("Received GetPayloadV1", "payloadId", decodedPayloadId) + + response, err := e.getPayload(ctx, decodedPayloadId, clparams.BellatrixVersion) + if err != nil { + return nil, err + } + + return response.ExecutionPayload, nil +} + +// Same as [GetPayloadV1] with addition of blockValue +// See https://github.com/ethereum/execution-apis/blob/main/src/engine/shanghai.md#engine_getpayloadv2 +func (e *EngineServer) GetPayloadV2(ctx context.Context, payloadID hexutility.Bytes) (*engine_types.GetPayloadResponse, error) { + decodedPayloadId := binary.BigEndian.Uint64(payloadID) + e.logger.Info("Received GetPayloadV2", "payloadId", decodedPayloadId) + return e.getPayload(ctx, decodedPayloadId, clparams.CapellaVersion) +} + +// Same as [GetPayloadV2], with addition of blobsBundle containing valid blobs, commitments, proofs +// See https://github.com/ethereum/execution-apis/blob/main/src/engine/cancun.md#engine_getpayloadv3 +func (e *EngineServer) GetPayloadV3(ctx context.Context, payloadID hexutility.Bytes) (*engine_types.GetPayloadResponse, error) { + decodedPayloadId := binary.BigEndian.Uint64(payloadID) + e.logger.Info("Received GetPayloadV3", "payloadId", decodedPayloadId) + return e.getPayload(ctx, decodedPayloadId, clparams.DenebVersion) +} + +// Same as [GetPayloadV3], but returning ExecutionPayloadV4 (= ExecutionPayloadV3 + requests) +// See https://github.com/ethereum/execution-apis/blob/main/src/engine/prague.md#engine_getpayloadv4 +func (e *EngineServer) GetPayloadV4(ctx context.Context, payloadID hexutility.Bytes) (*engine_types.GetPayloadResponse, error) { + decodedPayloadId := binary.BigEndian.Uint64(payloadID) + e.logger.Info("Received GetPayloadV4", "payloadId", decodedPayloadId) + return e.getPayload(ctx, decodedPayloadId, clparams.ElectraVersion) +} + +// Updates the forkchoice state after validating the headBlockHash +// Additionally, builds and returns a unique identifier for an initial version of a payload +// (asynchronously updated with transactions), if payloadAttributes is not nil and passes validation +// See https://github.com/ethereum/execution-apis/blob/main/src/engine/paris.md#engine_forkchoiceupdatedv1 +func (e *EngineServer) ForkchoiceUpdatedV1(ctx context.Context, forkChoiceState *engine_types.ForkChoiceState, payloadAttributes *engine_types.PayloadAttributes) (*engine_types.ForkChoiceUpdatedResponse, error) { + return e.forkchoiceUpdated(ctx, forkChoiceState, payloadAttributes, clparams.BellatrixVersion) +} + +// Same as, and a replacement for, [ForkchoiceUpdatedV1], post Shanghai +// See https://github.com/ethereum/execution-apis/blob/main/src/engine/shanghai.md#engine_forkchoiceupdatedv2 +func (e *EngineServer) ForkchoiceUpdatedV2(ctx context.Context, forkChoiceState *engine_types.ForkChoiceState, payloadAttributes *engine_types.PayloadAttributes) (*engine_types.ForkChoiceUpdatedResponse, error) { + return e.forkchoiceUpdated(ctx, forkChoiceState, payloadAttributes, clparams.CapellaVersion) +} + +// Successor of [ForkchoiceUpdatedV2] post Cancun, with stricter check on params +// See https://github.com/ethereum/execution-apis/blob/main/src/engine/cancun.md#engine_forkchoiceupdatedv3 +func (e *EngineServer) ForkchoiceUpdatedV3(ctx context.Context, forkChoiceState *engine_types.ForkChoiceState, payloadAttributes *engine_types.PayloadAttributes) (*engine_types.ForkChoiceUpdatedResponse, error) { + return e.forkchoiceUpdated(ctx, forkChoiceState, payloadAttributes, clparams.DenebVersion) +} + +// NewPayloadV1 processes new payloads (blocks) from the beacon chain without withdrawals. +// See https://github.com/ethereum/execution-apis/blob/main/src/engine/paris.md#engine_newpayloadv1 +func (e *EngineServer) NewPayloadV1(ctx context.Context, payload *engine_types.ExecutionPayload) (*engine_types.PayloadStatus, error) { + return e.newPayload(ctx, payload, nil, nil, nil, clparams.BellatrixVersion) +} + +// NewPayloadV2 processes new payloads (blocks) from the beacon chain with withdrawals. +// See https://github.com/ethereum/execution-apis/blob/main/src/engine/shanghai.md#engine_newpayloadv2 +func (e *EngineServer) NewPayloadV2(ctx context.Context, payload *engine_types.ExecutionPayload) (*engine_types.PayloadStatus, error) { + return e.newPayload(ctx, payload, nil, nil, nil, clparams.CapellaVersion) +} + +// NewPayloadV3 processes new payloads (blocks) from the beacon chain with withdrawals & blob gas. +// See https://github.com/ethereum/execution-apis/blob/main/src/engine/cancun.md#engine_newpayloadv3 +func (e *EngineServer) NewPayloadV3(ctx context.Context, payload *engine_types.ExecutionPayload, + expectedBlobHashes []libcommon.Hash, parentBeaconBlockRoot *libcommon.Hash) (*engine_types.PayloadStatus, error) { + return e.newPayload(ctx, payload, expectedBlobHashes, parentBeaconBlockRoot, nil, clparams.DenebVersion) +} + +// NewPayloadV4 processes new payloads (blocks) from the beacon chain with withdrawals, blob gas and requests. +// See https://github.com/ethereum/execution-apis/blob/main/src/engine/prague.md#engine_newpayloadv4 +func (e *EngineServer) NewPayloadV4(ctx context.Context, payload *engine_types.ExecutionPayload, + expectedBlobHashes []libcommon.Hash, parentBeaconBlockRoot *libcommon.Hash, executionRequests []hexutility.Bytes) (*engine_types.PayloadStatus, error) { + // TODO(racytech): add proper version or refactor this part + // add all version ralated checks here so the newpayload doesn't have to deal with checks + return e.newPayload(ctx, payload, expectedBlobHashes, parentBeaconBlockRoot, executionRequests, clparams.ElectraVersion) +} + +// Returns an array of execution payload bodies referenced by their block hashes +// See https://github.com/ethereum/execution-apis/blob/main/src/engine/shanghai.md#engine_getpayloadbodiesbyhashv1 +func (e *EngineServer) GetPayloadBodiesByHashV1(ctx context.Context, hashes []libcommon.Hash) ([]*engine_types.ExecutionPayloadBody, error) { + return e.getPayloadBodiesByHash(ctx, hashes) +} + +// Returns an ordered (as per canonical chain) array of execution payload bodies, with corresponding execution block numbers from "start", up to "count" +// See https://github.com/ethereum/execution-apis/blob/main/src/engine/shanghai.md#engine_getpayloadbodiesbyrangev1 +func (e *EngineServer) GetPayloadBodiesByRangeV1(ctx context.Context, start, count hexutil.Uint64) ([]*engine_types.ExecutionPayloadBody, error) { + return e.getPayloadBodiesByRange(ctx, uint64(start), uint64(count)) +} + +// Returns the node's code and commit details in a slice +// See https://github.com/ethereum/execution-apis/blob/main/src/engine/identification.md#engine_getclientversionv1 +func (e *EngineServer) GetClientVersionV1(ctx context.Context, callerVersion *engine_types.ClientVersionV1) ([]engine_types.ClientVersionV1, error) { + if callerVersion != nil { + e.logger.Info("[GetClientVersionV1] Received request from" + callerVersion.String()) + } + commitBytes := [4]byte{} + c := []byte(params.GitCommit) + if len(c) >= 4 { + copy(commitBytes[:], c[0:4]) + } + result := make([]engine_types.ClientVersionV1, 1) + result[0] = engine_types.ClientVersionV1{ + Code: params.ClientCode, + Name: params.ClientName, + Version: params.Version, + Commit: commitBytes, + } + return result, nil +} + +func (e *EngineServer) ExchangeCapabilities(fromCl []string) []string { + e.engineLogSpamer.RecordRequest() + missingOurs := compareCapabilities(fromCl, ourCapabilities) + missingCl := compareCapabilities(ourCapabilities, fromCl) + + if len(missingCl) > 0 || len(missingOurs) > 0 { + e.logger.Debug("ExchangeCapabilities mismatches", "cl_unsupported", missingCl, "erigon_unsupported", missingOurs) + } + + return ourCapabilities +} diff --git a/turbo/engineapi/engine_server.go b/turbo/engineapi/engine_server.go index 19ca98fed7a..6576fb7b6ae 100644 --- a/turbo/engineapi/engine_server.go +++ b/turbo/engineapi/engine_server.go @@ -18,7 +18,6 @@ package engineapi import ( "context" - "encoding/binary" "errors" "fmt" "math/big" @@ -44,7 +43,6 @@ import ( "github.com/erigontech/erigon/consensus/merge" "github.com/erigontech/erigon/core/types" "github.com/erigontech/erigon/eth/ethutils" - "github.com/erigontech/erigon/params" "github.com/erigontech/erigon/rpc" "github.com/erigontech/erigon/turbo/engineapi/engine_block_downloader" "github.com/erigontech/erigon/turbo/engineapi/engine_helpers" @@ -690,161 +688,6 @@ func (s *EngineServer) getPayloadBodiesByRange(ctx context.Context, start, count return resp, nil } -// Returns the most recent version of the payload(for the payloadID) at the time of receiving the call -// See https://github.com/ethereum/execution-apis/blob/main/src/engine/paris.md#engine_getpayloadv1 -func (e *EngineServer) GetPayloadV1(ctx context.Context, payloadId hexutility.Bytes) (*engine_types.ExecutionPayload, error) { - if e.caplin { - e.logger.Crit(caplinEnabledLog) - return nil, errCaplinEnabled - } - e.engineLogSpamer.RecordRequest() - - decodedPayloadId := binary.BigEndian.Uint64(payloadId) - e.logger.Info("Received GetPayloadV1", "payloadId", decodedPayloadId) - - response, err := e.getPayload(ctx, decodedPayloadId, clparams.BellatrixVersion) - if err != nil { - return nil, err - } - - return response.ExecutionPayload, nil -} - -// Same as [GetPayloadV1] with addition of blockValue -// See https://github.com/ethereum/execution-apis/blob/main/src/engine/shanghai.md#engine_getpayloadv2 -func (e *EngineServer) GetPayloadV2(ctx context.Context, payloadID hexutility.Bytes) (*engine_types.GetPayloadResponse, error) { - decodedPayloadId := binary.BigEndian.Uint64(payloadID) - e.logger.Info("Received GetPayloadV2", "payloadId", decodedPayloadId) - return e.getPayload(ctx, decodedPayloadId, clparams.CapellaVersion) -} - -// Same as [GetPayloadV2], with addition of blobsBundle containing valid blobs, commitments, proofs -// See https://github.com/ethereum/execution-apis/blob/main/src/engine/cancun.md#engine_getpayloadv3 -func (e *EngineServer) GetPayloadV3(ctx context.Context, payloadID hexutility.Bytes) (*engine_types.GetPayloadResponse, error) { - decodedPayloadId := binary.BigEndian.Uint64(payloadID) - e.logger.Info("Received GetPayloadV3", "payloadId", decodedPayloadId) - return e.getPayload(ctx, decodedPayloadId, clparams.DenebVersion) -} - -// Same as [GetPayloadV3], but returning ExecutionPayloadV4 (= ExecutionPayloadV3 + requests) -// See https://github.com/ethereum/execution-apis/blob/main/src/engine/prague.md#engine_getpayloadv4 -func (e *EngineServer) GetPayloadV4(ctx context.Context, payloadID hexutility.Bytes) (*engine_types.GetPayloadResponse, error) { - decodedPayloadId := binary.BigEndian.Uint64(payloadID) - e.logger.Info("Received GetPayloadV4", "payloadId", decodedPayloadId) - return e.getPayload(ctx, decodedPayloadId, clparams.ElectraVersion) -} - -// Updates the forkchoice state after validating the headBlockHash -// Additionally, builds and returns a unique identifier for an initial version of a payload -// (asynchronously updated with transactions), if payloadAttributes is not nil and passes validation -// See https://github.com/ethereum/execution-apis/blob/main/src/engine/paris.md#engine_forkchoiceupdatedv1 -func (e *EngineServer) ForkchoiceUpdatedV1(ctx context.Context, forkChoiceState *engine_types.ForkChoiceState, payloadAttributes *engine_types.PayloadAttributes) (*engine_types.ForkChoiceUpdatedResponse, error) { - return e.forkchoiceUpdated(ctx, forkChoiceState, payloadAttributes, clparams.BellatrixVersion) -} - -// Same as, and a replacement for, [ForkchoiceUpdatedV1], post Shanghai -// See https://github.com/ethereum/execution-apis/blob/main/src/engine/shanghai.md#engine_forkchoiceupdatedv2 -func (e *EngineServer) ForkchoiceUpdatedV2(ctx context.Context, forkChoiceState *engine_types.ForkChoiceState, payloadAttributes *engine_types.PayloadAttributes) (*engine_types.ForkChoiceUpdatedResponse, error) { - return e.forkchoiceUpdated(ctx, forkChoiceState, payloadAttributes, clparams.CapellaVersion) -} - -// Successor of [ForkchoiceUpdatedV2] post Cancun, with stricter check on params -// See https://github.com/ethereum/execution-apis/blob/main/src/engine/cancun.md#engine_forkchoiceupdatedv3 -func (e *EngineServer) ForkchoiceUpdatedV3(ctx context.Context, forkChoiceState *engine_types.ForkChoiceState, payloadAttributes *engine_types.PayloadAttributes) (*engine_types.ForkChoiceUpdatedResponse, error) { - return e.forkchoiceUpdated(ctx, forkChoiceState, payloadAttributes, clparams.DenebVersion) -} - -// NewPayloadV1 processes new payloads (blocks) from the beacon chain without withdrawals. -// See https://github.com/ethereum/execution-apis/blob/main/src/engine/paris.md#engine_newpayloadv1 -func (e *EngineServer) NewPayloadV1(ctx context.Context, payload *engine_types.ExecutionPayload) (*engine_types.PayloadStatus, error) { - return e.newPayload(ctx, payload, nil, nil, nil, clparams.BellatrixVersion) -} - -// NewPayloadV2 processes new payloads (blocks) from the beacon chain with withdrawals. -// See https://github.com/ethereum/execution-apis/blob/main/src/engine/shanghai.md#engine_newpayloadv2 -func (e *EngineServer) NewPayloadV2(ctx context.Context, payload *engine_types.ExecutionPayload) (*engine_types.PayloadStatus, error) { - return e.newPayload(ctx, payload, nil, nil, nil, clparams.CapellaVersion) -} - -// NewPayloadV3 processes new payloads (blocks) from the beacon chain with withdrawals & blob gas. -// See https://github.com/ethereum/execution-apis/blob/main/src/engine/cancun.md#engine_newpayloadv3 -func (e *EngineServer) NewPayloadV3(ctx context.Context, payload *engine_types.ExecutionPayload, - expectedBlobHashes []libcommon.Hash, parentBeaconBlockRoot *libcommon.Hash) (*engine_types.PayloadStatus, error) { - return e.newPayload(ctx, payload, expectedBlobHashes, parentBeaconBlockRoot, nil, clparams.DenebVersion) -} - -// NewPayloadV4 processes new payloads (blocks) from the beacon chain with withdrawals, blob gas and requests. -// See https://github.com/ethereum/execution-apis/blob/main/src/engine/prague.md#engine_newpayloadv4 -func (e *EngineServer) NewPayloadV4(ctx context.Context, payload *engine_types.ExecutionPayload, - expectedBlobHashes []libcommon.Hash, parentBeaconBlockRoot *libcommon.Hash, executionRequests []hexutility.Bytes) (*engine_types.PayloadStatus, error) { - // TODO(racytech): add proper version or refactor this part - // add all version ralated checks here so the newpayload doesn't have to deal with checks - return e.newPayload(ctx, payload, expectedBlobHashes, parentBeaconBlockRoot, executionRequests, clparams.ElectraVersion) -} - -// Returns an array of execution payload bodies referenced by their block hashes -// See https://github.com/ethereum/execution-apis/blob/main/src/engine/shanghai.md#engine_getpayloadbodiesbyhashv1 -func (e *EngineServer) GetPayloadBodiesByHashV1(ctx context.Context, hashes []libcommon.Hash) ([]*engine_types.ExecutionPayloadBody, error) { - return e.getPayloadBodiesByHash(ctx, hashes) -} - -// Returns an ordered (as per canonical chain) array of execution payload bodies, with corresponding execution block numbers from "start", up to "count" -// See https://github.com/ethereum/execution-apis/blob/main/src/engine/shanghai.md#engine_getpayloadbodiesbyrangev1 -func (e *EngineServer) GetPayloadBodiesByRangeV1(ctx context.Context, start, count hexutil.Uint64) ([]*engine_types.ExecutionPayloadBody, error) { - return e.getPayloadBodiesByRange(ctx, uint64(start), uint64(count)) -} - -// Returns the node's code and commit details in a slice -// See https://github.com/ethereum/execution-apis/blob/main/src/engine/identification.md#engine_getclientversionv1 -func (e *EngineServer) GetClientVersionV1(ctx context.Context, callerVersion *engine_types.ClientVersionV1) ([]engine_types.ClientVersionV1, error) { - if callerVersion != nil { - e.logger.Info("[GetClientVersionV1] Received request from" + callerVersion.String()) - } - commitBytes := [4]byte{} - c := []byte(params.GitCommit) - if len(c) >= 4 { - copy(commitBytes[:], c[0:4]) - } - result := make([]engine_types.ClientVersionV1, 1) - result[0] = engine_types.ClientVersionV1{ - Code: params.ClientCode, - Name: params.ClientName, - Version: params.Version, - Commit: commitBytes, - } - return result, nil -} - -var ourCapabilities = []string{ - "engine_forkchoiceUpdatedV1", - "engine_forkchoiceUpdatedV2", - "engine_forkchoiceUpdatedV3", - "engine_newPayloadV1", - "engine_newPayloadV2", - "engine_newPayloadV3", - "engine_newPayloadV4", - "engine_getPayloadV1", - "engine_getPayloadV2", - "engine_getPayloadV3", - "engine_getPayloadV4", - "engine_getPayloadBodiesByHashV1", - "engine_getPayloadBodiesByRangeV1", - "engine_getClientVersionV1", -} - -func (e *EngineServer) ExchangeCapabilities(fromCl []string) []string { - e.engineLogSpamer.RecordRequest() - - missingOurs := compareCapabilities(fromCl, ourCapabilities) - missingCl := compareCapabilities(ourCapabilities, fromCl) - - if len(missingCl) > 0 || len(missingOurs) > 0 { - e.logger.Debug("ExchangeCapabilities mismatches", "cl_unsupported", missingCl, "erigon_unsupported", missingOurs) - } - - return ourCapabilities -} - func compareCapabilities(from []string, to []string) []string { result := make([]string, 0) for _, f := range from {