diff --git a/.github/workflows/build-latest.yaml b/.github/workflows/build-latest.yaml index c5c0293e..383e5c04 100644 --- a/.github/workflows/build-latest.yaml +++ b/.github/workflows/build-latest.yaml @@ -15,7 +15,7 @@ jobs: with: image_name: ${{ github.repository }} # it will be lowercased internally github_token: ${{ secrets.PERSONAL_TOKEN }} - dockerfile: ./serv/Dockerfile + dockerfile: ./listener/Dockerfile - name: clone repo run: git clone https://${{secrets.PERSONAL_USERNAME}}:${{secrets.PERSONAL_TOKEN}}@github.com/b2network/devops.git - name: modify diff --git a/.gitignore b/.gitignore index 3cf52cc4..916dd166 100644 --- a/.gitignore +++ b/.gitignore @@ -104,4 +104,5 @@ fabric.properties .openzeppelin contracts/artifacts/* -contracts/cache/* \ No newline at end of file +contracts/cache/* +config-dev.yaml \ No newline at end of file diff --git a/README.md b/README.md index 0ea641b5..85651d03 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ function call(uint256 to_chain_id, address contract_address, bytes calldata data bsquared testnet ``` -B2MessageBridge: 0xc7441Ac47596D1356fcc70062dA0462FcA98E14e +B2MessageBridge: 0x5c2646996eEe3ECf865BEfA2De24e5BbE1C552Ba BusinessContract: 0x91171cf194a4B66Bd459Ada038397c7e890FB9D4 ``` @@ -47,7 +47,7 @@ BusinessContract: 0x8Ac2C830532d7203a12C4C32C0BE4d3d15917534 ``` // -messageAddress = "0xc7441Ac47596D1356fcc70062dA0462FcA98E14e"; +messageAddress = "0x5c2646996eEe3ECf865BEfA2De24e5BbE1C552Ba"; businessAddress = "0x8Ac2C830532d7203a12C4C32C0BE4d3d15917534"; to_chain_id = 421614; data = '0x1234'; diff --git a/contracts/.openzeppelin/unknown-1123.json b/contracts/.openzeppelin/unknown-1123.json index adeebc85..46d52794 100644 --- a/contracts/.openzeppelin/unknown-1123.json +++ b/contracts/.openzeppelin/unknown-1123.json @@ -30,6 +30,11 @@ "address": "0xc7441Ac47596D1356fcc70062dA0462FcA98E14e", "txHash": "0xec63c6ceb308bd775eca61cc14c25f2b02ba63c70bb3d08ad37d8287bdde268e", "kind": "uups" + }, + { + "address": "0x5c2646996eEe3ECf865BEfA2De24e5BbE1C552Ba", + "txHash": "0xa4dfa5848c2f6a45f5d1cc047a59383f23007e179b57f9e840529cc96d21e583", + "kind": "uups" } ], "impls": { @@ -595,8 +600,466 @@ } }, "fd6a3fcc07a72ce9a4d4b587b112ac686c02d216f964ce041e551f07ea1c386d": { - "address": "0x5005F20fcC6029c9319e85FBBc0E5FaC7be1a6Bd", - "txHash": "0xcedca8a1884f8b6128c81cb0b74c5c7112dc867ec71fcdfa62d4e10cc2bf1f79", + "address": "0x4dee1bF18D3a215385956E011b739349410dbF0B", + "txHash": "0x1bdb578f3a6d77b8700af651a20910bfbcfa6bd410f5d3869f044a238318d791", + "layout": { + "solcVersion": "0.8.20", + "storage": [ + { + "label": "sequence", + "offset": 0, + "slot": "0", + "type": "t_uint256", + "contract": "B2MessageBridge", + "src": "contracts/message/B2MessageBridge.sol:26" + }, + { + "label": "weight", + "offset": 0, + "slot": "1", + "type": "t_uint256", + "contract": "B2MessageBridge", + "src": "contracts/message/B2MessageBridge.sol:27" + }, + { + "label": "sequences", + "offset": 0, + "slot": "2", + "type": "t_mapping(t_uint256,t_uint256)", + "contract": "B2MessageBridge", + "src": "contracts/message/B2MessageBridge.sol:28" + }, + { + "label": "ids", + "offset": 0, + "slot": "3", + "type": "t_mapping(t_uint256,t_mapping(t_uint256,t_bool))", + "contract": "B2MessageBridge", + "src": "contracts/message/B2MessageBridge.sol:29" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_bytes32,t_struct(RoleData)25_storage)": { + "label": "mapping(bytes32 => struct AccessControlUpgradeable.RoleData)", + "numberOfBytes": "32" + }, + "t_string_storage": { + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(AccessControlStorage)35_storage": { + "label": "struct AccessControlUpgradeable.AccessControlStorage", + "members": [ + { + "label": "_roles", + "type": "t_mapping(t_bytes32,t_struct(RoleData)25_storage)", + "offset": 0, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_struct(EIP712Storage)376_storage": { + "label": "struct EIP712Upgradeable.EIP712Storage", + "members": [ + { + "label": "_hashedName", + "type": "t_bytes32", + "offset": 0, + "slot": "0" + }, + { + "label": "_hashedVersion", + "type": "t_bytes32", + "offset": 0, + "slot": "1" + }, + { + "label": "_name", + "type": "t_string_storage", + "offset": 0, + "slot": "2" + }, + { + "label": "_version", + "type": "t_string_storage", + "offset": 0, + "slot": "3" + } + ], + "numberOfBytes": "128" + }, + "t_struct(InitializableStorage)174_storage": { + "label": "struct Initializable.InitializableStorage", + "members": [ + { + "label": "_initialized", + "type": "t_uint64", + "offset": 0, + "slot": "0" + }, + { + "label": "_initializing", + "type": "t_bool", + "offset": 8, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_struct(RoleData)25_storage": { + "label": "struct AccessControlUpgradeable.RoleData", + "members": [ + { + "label": "hasRole", + "type": "t_mapping(t_address,t_bool)", + "offset": 0, + "slot": "0" + }, + { + "label": "adminRole", + "type": "t_bytes32", + "offset": 0, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_uint64": { + "label": "uint64", + "numberOfBytes": "8" + }, + "t_mapping(t_uint256,t_bool)": { + "label": "mapping(uint256 => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_mapping(t_uint256,t_bool))": { + "label": "mapping(uint256 => mapping(uint256 => bool))", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_uint256)": { + "label": "mapping(uint256 => uint256)", + "numberOfBytes": "32" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + } + }, + "namespaces": { + "erc7201:openzeppelin.storage.AccessControl": [ + { + "contract": "AccessControlUpgradeable", + "label": "_roles", + "type": "t_mapping(t_bytes32,t_struct(RoleData)25_storage)", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:61", + "offset": 0, + "slot": "0" + } + ], + "erc7201:openzeppelin.storage.EIP712": [ + { + "contract": "EIP712Upgradeable", + "label": "_hashedName", + "type": "t_bytes32", + "src": "@openzeppelin/contracts-upgradeable/utils/cryptography/EIP712Upgradeable.sol:39", + "offset": 0, + "slot": "0" + }, + { + "contract": "EIP712Upgradeable", + "label": "_hashedVersion", + "type": "t_bytes32", + "src": "@openzeppelin/contracts-upgradeable/utils/cryptography/EIP712Upgradeable.sol:41", + "offset": 0, + "slot": "1" + }, + { + "contract": "EIP712Upgradeable", + "label": "_name", + "type": "t_string_storage", + "src": "@openzeppelin/contracts-upgradeable/utils/cryptography/EIP712Upgradeable.sol:43", + "offset": 0, + "slot": "2" + }, + { + "contract": "EIP712Upgradeable", + "label": "_version", + "type": "t_string_storage", + "src": "@openzeppelin/contracts-upgradeable/utils/cryptography/EIP712Upgradeable.sol:44", + "offset": 0, + "slot": "3" + } + ], + "erc7201:openzeppelin.storage.Initializable": [ + { + "contract": "Initializable", + "label": "_initialized", + "type": "t_uint64", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:69", + "offset": 0, + "slot": "0" + }, + { + "contract": "Initializable", + "label": "_initializing", + "type": "t_bool", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:73", + "offset": 8, + "slot": "0" + } + ] + } + } + }, + "226e38b1100d05b5fd6a3a136524b9ada5f9cb29e7694ba6267a0d254ea05f7b": { + "address": "0x79bd136DDE1EF960565f3dA29fA7a7BDc13973A3", + "txHash": "0xb273dfbc82da973e0e16b6790361e321353c765bbe1ab5f623d2f212788d4039", + "layout": { + "solcVersion": "0.8.20", + "storage": [ + { + "label": "sequence", + "offset": 0, + "slot": "0", + "type": "t_uint256", + "contract": "B2MessageBridge", + "src": "contracts/message/B2MessageBridge.sol:26" + }, + { + "label": "weight", + "offset": 0, + "slot": "1", + "type": "t_uint256", + "contract": "B2MessageBridge", + "src": "contracts/message/B2MessageBridge.sol:27" + }, + { + "label": "sequences", + "offset": 0, + "slot": "2", + "type": "t_mapping(t_uint256,t_uint256)", + "contract": "B2MessageBridge", + "src": "contracts/message/B2MessageBridge.sol:28" + }, + { + "label": "ids", + "offset": 0, + "slot": "3", + "type": "t_mapping(t_uint256,t_mapping(t_uint256,t_bool))", + "contract": "B2MessageBridge", + "src": "contracts/message/B2MessageBridge.sol:29" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_bytes32,t_struct(RoleData)25_storage)": { + "label": "mapping(bytes32 => struct AccessControlUpgradeable.RoleData)", + "numberOfBytes": "32" + }, + "t_string_storage": { + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(AccessControlStorage)35_storage": { + "label": "struct AccessControlUpgradeable.AccessControlStorage", + "members": [ + { + "label": "_roles", + "type": "t_mapping(t_bytes32,t_struct(RoleData)25_storage)", + "offset": 0, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_struct(EIP712Storage)376_storage": { + "label": "struct EIP712Upgradeable.EIP712Storage", + "members": [ + { + "label": "_hashedName", + "type": "t_bytes32", + "offset": 0, + "slot": "0" + }, + { + "label": "_hashedVersion", + "type": "t_bytes32", + "offset": 0, + "slot": "1" + }, + { + "label": "_name", + "type": "t_string_storage", + "offset": 0, + "slot": "2" + }, + { + "label": "_version", + "type": "t_string_storage", + "offset": 0, + "slot": "3" + } + ], + "numberOfBytes": "128" + }, + "t_struct(InitializableStorage)174_storage": { + "label": "struct Initializable.InitializableStorage", + "members": [ + { + "label": "_initialized", + "type": "t_uint64", + "offset": 0, + "slot": "0" + }, + { + "label": "_initializing", + "type": "t_bool", + "offset": 8, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_struct(RoleData)25_storage": { + "label": "struct AccessControlUpgradeable.RoleData", + "members": [ + { + "label": "hasRole", + "type": "t_mapping(t_address,t_bool)", + "offset": 0, + "slot": "0" + }, + { + "label": "adminRole", + "type": "t_bytes32", + "offset": 0, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_uint64": { + "label": "uint64", + "numberOfBytes": "8" + }, + "t_mapping(t_uint256,t_bool)": { + "label": "mapping(uint256 => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_mapping(t_uint256,t_bool))": { + "label": "mapping(uint256 => mapping(uint256 => bool))", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_uint256)": { + "label": "mapping(uint256 => uint256)", + "numberOfBytes": "32" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + } + }, + "namespaces": { + "erc7201:openzeppelin.storage.AccessControl": [ + { + "contract": "AccessControlUpgradeable", + "label": "_roles", + "type": "t_mapping(t_bytes32,t_struct(RoleData)25_storage)", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:61", + "offset": 0, + "slot": "0" + } + ], + "erc7201:openzeppelin.storage.EIP712": [ + { + "contract": "EIP712Upgradeable", + "label": "_hashedName", + "type": "t_bytes32", + "src": "@openzeppelin/contracts-upgradeable/utils/cryptography/EIP712Upgradeable.sol:39", + "offset": 0, + "slot": "0" + }, + { + "contract": "EIP712Upgradeable", + "label": "_hashedVersion", + "type": "t_bytes32", + "src": "@openzeppelin/contracts-upgradeable/utils/cryptography/EIP712Upgradeable.sol:41", + "offset": 0, + "slot": "1" + }, + { + "contract": "EIP712Upgradeable", + "label": "_name", + "type": "t_string_storage", + "src": "@openzeppelin/contracts-upgradeable/utils/cryptography/EIP712Upgradeable.sol:43", + "offset": 0, + "slot": "2" + }, + { + "contract": "EIP712Upgradeable", + "label": "_version", + "type": "t_string_storage", + "src": "@openzeppelin/contracts-upgradeable/utils/cryptography/EIP712Upgradeable.sol:44", + "offset": 0, + "slot": "3" + } + ], + "erc7201:openzeppelin.storage.Initializable": [ + { + "contract": "Initializable", + "label": "_initialized", + "type": "t_uint64", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:69", + "offset": 0, + "slot": "0" + }, + { + "contract": "Initializable", + "label": "_initializing", + "type": "t_bool", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:73", + "offset": 8, + "slot": "0" + } + ] + } + } + }, + "761be4fd462127a5b98506e034b0a1d4d3274a6054936536bee56fb2465e26cb": { + "address": "0xd6abe748Fd22d8c18f815Ec3C082178C0168c1ba", + "txHash": "0xbbfc6315057a9556d8638545e4efe63d848fc390906808e46a76bb55d470db51", "layout": { "solcVersion": "0.8.20", "storage": [ diff --git a/contracts/artifacts/contracts/message/B2MessageBridge.sol/B2MessageBridge.dbg.json b/contracts/artifacts/contracts/message/B2MessageBridge.sol/B2MessageBridge.dbg.json index 116ee53e..7447626a 100644 --- a/contracts/artifacts/contracts/message/B2MessageBridge.sol/B2MessageBridge.dbg.json +++ b/contracts/artifacts/contracts/message/B2MessageBridge.sol/B2MessageBridge.dbg.json @@ -1,4 +1,4 @@ { "_format": "hh-sol-dbg-1", - "buildInfo": "../../../build-info/b6b5a288b7f14e968aadb592e7a63ae5.json" + "buildInfo": "../../../build-info/70e62623267d7ba9585ce6fb07d39bd0.json" } diff --git a/contracts/artifacts/contracts/message/B2MessageBridge.sol/B2MessageBridge.json b/contracts/artifacts/contracts/message/B2MessageBridge.sol/B2MessageBridge.json index 505ec4e1..ebc07d64 100644 --- a/contracts/artifacts/contracts/message/B2MessageBridge.sol/B2MessageBridge.json +++ b/contracts/artifacts/contracts/message/B2MessageBridge.sol/B2MessageBridge.json @@ -833,8 +833,8 @@ "type": "function" } ], - "bytecode": "0x60a06040523060805234801561001457600080fd5b5060805161242c61003e600039600081816110a9015281816110d20152611274015261242c6000f3fe6080604052600436106101965760003560e01c806384b0196e116100e1578063b908afa81161008a578063c86a64f711610064578063c86a64f714610527578063cc8f426114610554578063d547741f14610588578063fc1711f2146105a857600080fd5b8063b908afa81461049f578063bc5c11aa146104d3578063c49baebe146104f357600080fd5b8063a1aab33f116100bb578063a1aab33f1461041e578063a217fddf14610434578063ad3cb1cc1461044957600080fd5b806384b0196e1461035657806391d148541461037e5780639d449d11146103e357600080fd5b80634f1ef286116101435780636ba3300c1161011d5780636ba3300c146102ed57806375b238fc1461030d5780638129fc1c1461034157600080fd5b80634f1ef286146102af578063529d15cc146102c257806352d1902d146102d857600080fd5b8063248a9ca311610174578063248a9ca3146102205780632f2ff15d1461026f57806336568abe1461028f57600080fd5b806301ffc9a71461019b57806304760f2e146101d05780630d682acb146101fe575b600080fd5b3480156101a757600080fd5b506101bb6101b6366004611b45565b6105c8565b60405190151581526020015b60405180910390f35b3480156101dc57600080fd5b506101f06101eb366004611bec565b610661565b6040519081526020016101c7565b34801561020a57600080fd5b5061021e610219366004611c6e565b6106cc565b005b34801561022c57600080fd5b506101f061023b366004611d42565b60009081527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602052604090206001015490565b34801561027b57600080fd5b5061021e61028a366004611d5b565b610934565b34801561029b57600080fd5b5061021e6102aa366004611d5b565b61097e565b61021e6102bd366004611d9d565b6109cf565b3480156102ce57600080fd5b506101f060005481565b3480156102e457600080fd5b506101f06109ee565b3480156102f957600080fd5b506101f0610308366004611e5f565b610a1d565b34801561031957600080fd5b506101f07f589d473ba17c0f47d494622893831497bad25919b9afb8e33e9521b8963fccde81565b34801561034d57600080fd5b5061021e610aa6565b34801561036257600080fd5b5061036b610cbf565b6040516101c79796959493929190611f09565b34801561038a57600080fd5b506101bb610399366004611d5b565b60009182527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602090815260408084206001600160a01b0393909316845291905290205460ff1690565b3480156103ef57600080fd5b506101bb6103fe366004611fbb565b600360209081526000928352604080842090915290825290205460ff1681565b34801561042a57600080fd5b506101f060015481565b34801561044057600080fd5b506101f0600081565b34801561045557600080fd5b506104926040518060400160405280600581526020017f352e302e3000000000000000000000000000000000000000000000000000000081525081565b6040516101c79190611fdd565b3480156104ab57600080fd5b506101f07fcab03bc4dbcc648cd59d6bbe9f848d1e9092f914016aa290ee92e18700d1e6f981565b3480156104df57600080fd5b506101bb6104ee366004611ff0565b610da1565b3480156104ff57600080fd5b506101f07f5635ac0328a174458ffe72e6c6023489a57ff03280729989530f567288831c9181565b34801561053357600080fd5b506101f0610542366004611d42565b60026020526000908152604090205481565b34801561056057600080fd5b506101f07f17a4f53d2ecdb8066d7886a0e506b8014ce17a9a263db690785538a077e52b0981565b34801561059457600080fd5b5061021e6105a3366004611d5b565b610e2a565b3480156105b457600080fd5b5061021e6105c3366004611d42565b610e6e565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b00000000000000000000000000000000000000000000000000000000148061065b57507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b60006106c07f17a4f53d2ecdb8066d7886a0e506b8014ce17a9a263db690785538a077e52b09898989898989896040516020016106a59897969594939291906120c9565b60405160208183030381529060405280519060200120610ed4565b98975050505050505050565b60008881526003602090815260408083208a845290915290205460ff161561073b5760405162461bcd60e51b815260206004820152601960248201527f6e6f6e2d72657065617461626c652070726f63657373696e670000000000000060448201526064015b60405180910390fd5b6000805b828110156107a05760006107778a8c8b468c8c8c8c8c8b8181106107655761076561211c565b90506020028101906104ee9190612132565b9050801561078d5761078a83600161218f565b92505b5080610798816121a2565b91505061073f565b506001548110156107f35760405162461bcd60e51b815260206004820181905260248201527f766572696679207369676e6174757265732077656967687420696e76616c69646044820152606401610732565b6001600160a01b038616156108e6576040517fe09ee8700000000000000000000000000000000000000000000000000000000081526000906001600160a01b0388169063e09ee87090610852908d908d908d908c908c906004016121bb565b6020604051808303816000875af1158015610871573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061089591906121f5565b9050806108e45760405162461bcd60e51b815260206004820152600b60248201527f43616c6c206661696c65640000000000000000000000000000000000000000006044820152606401610732565b505b7f5849ae3f4bc77f0ebd2d6db4ff282f91f2191d3df4493e63176c2ed22fb81852898989468a8a8a6040516109219796959493929190612217565b60405180910390a1505050505050505050565b60008281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602052604090206001015461096e81610f1c565b6109788383610f29565b50505050565b6001600160a01b03811633146109c0576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6109ca8282610ff8565b505050565b6109d761109e565b6109e082611157565b6109ea8282611181565b5050565b60006109f8611269565b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc90565b600084815260026020526040812080549082610a38836121a2565b9091555050600085815260026020526040908190205490517f599c34a8d0b3638870afcfe3d7d8125602721889a7535cda986ea656e63fc38c91610a889146919033908a908a908a908a90612217565b60405180910390a15050506000918252506002602052604090205490565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff16600081158015610af15750825b905060008267ffffffffffffffff166001148015610b0e5750303b155b905081158015610b1c575080155b15610b53576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b845467ffffffffffffffff191660011785558315610b8757845468ff00000000000000001916680100000000000000001785555b610bfb6040518060400160405280600f81526020017f42324d65737361676542726964676500000000000000000000000000000000008152506040518060400160405280600181526020017f31000000000000000000000000000000000000000000000000000000000000008152506112b2565b610c036112c4565b610c0b6112c4565b610c16600033610f29565b50610c417f589d473ba17c0f47d494622893831497bad25919b9afb8e33e9521b8963fccde33610f29565b50610c6c7fcab03bc4dbcc648cd59d6bbe9f848d1e9092f914016aa290ee92e18700d1e6f933610f29565b508315610cb857845468ff000000000000000019168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050565b600060608082808083817fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1008054909150158015610cfe57506001810154155b610d4a5760405162461bcd60e51b815260206004820152601560248201527f4549503731323a20556e696e697469616c697a656400000000000000000000006044820152606401610732565b610d526112cc565b610d5a6113a1565b604080516000808252602082019092527f0f000000000000000000000000000000000000000000000000000000000000009c939b5091995046985030975095509350915050565b600080610db38b8b8b8b8b8b8b610661565b9050610e1b7f5635ac0328a174458ffe72e6c6023489a57ff03280729989530f567288831c9161039986868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525087939250506113f29050565b9b9a5050505050505050505050565b60008281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020526040902060010154610e6481610f1c565b6109788383610ff8565b7f589d473ba17c0f47d494622893831497bad25919b9afb8e33e9521b8963fccde610e9881610f1c565b60018290556040518281527f1b29ec9f95417d697093ba2f17ce0861fb5bcbb7d5011cdde1020c9263ecc1169060200160405180910390a15050565b600061065b610ee161141c565b836040517f19010000000000000000000000000000000000000000000000000000000000008152600281019290925260228201526042902090565b610f26813361142b565b50565b60008281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602081815260408084206001600160a01b038616855290915282205460ff16610fee576000848152602082815260408083206001600160a01b03871684529091529020805460ff19166001179055610fa43390565b6001600160a01b0316836001600160a01b0316857f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4600191505061065b565b600091505061065b565b60008281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602081815260408084206001600160a01b038616855290915282205460ff1615610fee576000848152602082815260408083206001600160a01b0387168085529252808320805460ff1916905551339287917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a4600191505061065b565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148061113757507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661112b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b6001600160a01b031614155b156111555760405163703e46dd60e11b815260040160405180910390fd5b565b7fcab03bc4dbcc648cd59d6bbe9f848d1e9092f914016aa290ee92e18700d1e6f96109ea81610f1c565b816001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156111db575060408051601f3d908101601f191682019092526111d891810190612263565b60015b61120357604051634c9c8ce360e01b81526001600160a01b0383166004820152602401610732565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc811461125f576040517faa1d49a400000000000000000000000000000000000000000000000000000000815260048101829052602401610732565b6109ca83836114b8565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146111555760405163703e46dd60e11b815260040160405180910390fd5b6112ba61150e565b6109ea8282611575565b61115561150e565b7fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10280546060917fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1009161131d9061227c565b80601f01602080910402602001604051908101604052809291908181526020018280546113499061227c565b80156113965780601f1061136b57610100808354040283529160200191611396565b820191906000526020600020905b81548152906001019060200180831161137957829003601f168201915b505050505091505090565b7fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10380546060917fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1009161131d9061227c565b60008060008061140286866115e8565b9250925092506114128282611635565b5090949350505050565b6000611426611739565b905090565b60008281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602090815260408083206001600160a01b038516845290915290205460ff166109ea576040517fe2517d3f0000000000000000000000000000000000000000000000000000000081526001600160a01b038216600482015260248101839052604401610732565b6114c1826117ad565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a2805115611506576109ca828261183c565b6109ea6118b2565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005468010000000000000000900460ff16611155576040517fd7e6bcf800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61157d61150e565b7fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1007fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1026115c98482612304565b50600381016115d88382612304565b5060008082556001909101555050565b600080600083516041036116225760208401516040850151606086015160001a611614888285856118ea565b95509550955050505061162e565b50508151600091506002905b9250925092565b6000826003811115611649576116496123c4565b03611652575050565b6001826003811115611666576116666123c4565b0361169d576040517ff645eedf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60028260038111156116b1576116b16123c4565b036116eb576040517ffce698f700000000000000000000000000000000000000000000000000000000815260048101829052602401610732565b60038260038111156116ff576116ff6123c4565b036109ea576040517fd78bce0c00000000000000000000000000000000000000000000000000000000815260048101829052602401610732565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6117646119b9565b61176c611a35565b60408051602081019490945283019190915260608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b806001600160a01b03163b6000036117e357604051634c9c8ce360e01b81526001600160a01b0382166004820152602401610732565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6060600080846001600160a01b03168460405161185991906123da565b600060405180830381855af49150503d8060008114611894576040519150601f19603f3d011682016040523d82523d6000602084013e611899565b606091505b50915091506118a9858383611a8b565b95945050505050565b3415611155576040517fb398979f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a084111561192557506000915060039050826119af565b604080516000808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa158015611979573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166119a5575060009250600191508290506119af565b9250600091508190505b9450945094915050565b60007fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d100816119e56112cc565b8051909150156119fd57805160209091012092915050565b81548015611a0c579392505050565b7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470935050505090565b60007fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10081611a616113a1565b805190915015611a7957805160209091012092915050565b60018201548015611a0c579392505050565b606082611aa057611a9b82611b03565b611afc565b8151158015611ab757506001600160a01b0384163b155b15611af9576040517f9996b3150000000000000000000000000000000000000000000000000000000081526001600160a01b0385166004820152602401610732565b50805b9392505050565b805115611b135780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060208284031215611b5757600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114611afc57600080fd5b80356001600160a01b0381168114611b9e57600080fd5b919050565b60008083601f840112611bb557600080fd5b50813567ffffffffffffffff811115611bcd57600080fd5b602083019150836020828501011115611be557600080fd5b9250929050565b600080600080600080600060c0888a031215611c0757600080fd5b8735965060208801359550611c1e60408901611b87565b945060608801359350611c3360808901611b87565b925060a088013567ffffffffffffffff811115611c4f57600080fd5b611c5b8a828b01611ba3565b989b979a50959850939692959293505050565b60008060008060008060008060c0898b031215611c8a57600080fd5b8835975060208901359650611ca160408a01611b87565b9550611caf60608a01611b87565b9450608089013567ffffffffffffffff80821115611ccc57600080fd5b611cd88c838d01611ba3565b909650945060a08b0135915080821115611cf157600080fd5b818b0191508b601f830112611d0557600080fd5b813581811115611d1457600080fd5b8c60208260051b8501011115611d2957600080fd5b6020830194508093505050509295985092959890939650565b600060208284031215611d5457600080fd5b5035919050565b60008060408385031215611d6e57600080fd5b82359150611d7e60208401611b87565b90509250929050565b634e487b7160e01b600052604160045260246000fd5b60008060408385031215611db057600080fd5b611db983611b87565b9150602083013567ffffffffffffffff80821115611dd657600080fd5b818501915085601f830112611dea57600080fd5b813581811115611dfc57611dfc611d87565b604051601f8201601f19908116603f01168101908382118183101715611e2457611e24611d87565b81604052828152886020848701011115611e3d57600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b60008060008060608587031215611e7557600080fd5b84359350611e8560208601611b87565b9250604085013567ffffffffffffffff811115611ea157600080fd5b611ead87828801611ba3565b95989497509550505050565b60005b83811015611ed4578181015183820152602001611ebc565b50506000910152565b60008151808452611ef5816020860160208601611eb9565b601f01601f19169290920160200192915050565b7fff00000000000000000000000000000000000000000000000000000000000000881681526000602060e081840152611f4560e084018a611edd565b8381036040850152611f57818a611edd565b606085018990526001600160a01b038816608086015260a0850187905284810360c0860152855180825283870192509083019060005b81811015611fa957835183529284019291840191600101611f8d565b50909c9b505050505050505050505050565b60008060408385031215611fce57600080fd5b50508035926020909101359150565b602081526000611afc6020830184611edd565b600080600080600080600080600060e08a8c03121561200e57600080fd5b8935985060208a0135975061202560408b01611b87565b965060608a0135955061203a60808b01611b87565b945060a08a013567ffffffffffffffff8082111561205757600080fd5b6120638d838e01611ba3565b909650945060c08c013591508082111561207c57600080fd5b506120898c828d01611ba3565b915080935050809150509295985092959850929598565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b88815287602082015286604082015260006001600160a01b03808816606084015286608084015280861660a08401525060e060c083015261210e60e0830184866120a0565b9a9950505050505050505050565b634e487b7160e01b600052603260045260246000fd5b6000808335601e1984360301811261214957600080fd5b83018035915067ffffffffffffffff82111561216457600080fd5b602001915036819003821315611be557600080fd5b634e487b7160e01b600052601160045260246000fd5b8082018082111561065b5761065b612179565b6000600182016121b4576121b4612179565b5060010190565b8581528460208201526001600160a01b03841660408201526080606082015260006121ea6080830184866120a0565b979650505050505050565b60006020828403121561220757600080fd5b81518015158114611afc57600080fd5b87815286602082015260006001600160a01b03808816604084015286606084015280861660808401525060c060a083015261225660c0830184866120a0565b9998505050505050505050565b60006020828403121561227557600080fd5b5051919050565b600181811c9082168061229057607f821691505b6020821081036122b057634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156109ca57600081815260208120601f850160051c810160208610156122dd5750805b601f850160051c820191505b818110156122fc578281556001016122e9565b505050505050565b815167ffffffffffffffff81111561231e5761231e611d87565b6123328161232c845461227c565b846122b6565b602080601f831160018114612367576000841561234f5750858301515b600019600386901b1c1916600185901b1785556122fc565b600085815260208120601f198616915b8281101561239657888601518255948401946001909101908401612377565b50858210156123b45787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b600052602160045260246000fd5b600082516123ec818460208701611eb9565b919091019291505056fea26469706673582212208228339ac58ba7f0c6cd5a8b7725a0b11e1581706294a7353b09ed34aa03e68164736f6c63430008140033", - "deployedBytecode": "0x6080604052600436106101965760003560e01c806384b0196e116100e1578063b908afa81161008a578063c86a64f711610064578063c86a64f714610527578063cc8f426114610554578063d547741f14610588578063fc1711f2146105a857600080fd5b8063b908afa81461049f578063bc5c11aa146104d3578063c49baebe146104f357600080fd5b8063a1aab33f116100bb578063a1aab33f1461041e578063a217fddf14610434578063ad3cb1cc1461044957600080fd5b806384b0196e1461035657806391d148541461037e5780639d449d11146103e357600080fd5b80634f1ef286116101435780636ba3300c1161011d5780636ba3300c146102ed57806375b238fc1461030d5780638129fc1c1461034157600080fd5b80634f1ef286146102af578063529d15cc146102c257806352d1902d146102d857600080fd5b8063248a9ca311610174578063248a9ca3146102205780632f2ff15d1461026f57806336568abe1461028f57600080fd5b806301ffc9a71461019b57806304760f2e146101d05780630d682acb146101fe575b600080fd5b3480156101a757600080fd5b506101bb6101b6366004611b45565b6105c8565b60405190151581526020015b60405180910390f35b3480156101dc57600080fd5b506101f06101eb366004611bec565b610661565b6040519081526020016101c7565b34801561020a57600080fd5b5061021e610219366004611c6e565b6106cc565b005b34801561022c57600080fd5b506101f061023b366004611d42565b60009081527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602052604090206001015490565b34801561027b57600080fd5b5061021e61028a366004611d5b565b610934565b34801561029b57600080fd5b5061021e6102aa366004611d5b565b61097e565b61021e6102bd366004611d9d565b6109cf565b3480156102ce57600080fd5b506101f060005481565b3480156102e457600080fd5b506101f06109ee565b3480156102f957600080fd5b506101f0610308366004611e5f565b610a1d565b34801561031957600080fd5b506101f07f589d473ba17c0f47d494622893831497bad25919b9afb8e33e9521b8963fccde81565b34801561034d57600080fd5b5061021e610aa6565b34801561036257600080fd5b5061036b610cbf565b6040516101c79796959493929190611f09565b34801561038a57600080fd5b506101bb610399366004611d5b565b60009182527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602090815260408084206001600160a01b0393909316845291905290205460ff1690565b3480156103ef57600080fd5b506101bb6103fe366004611fbb565b600360209081526000928352604080842090915290825290205460ff1681565b34801561042a57600080fd5b506101f060015481565b34801561044057600080fd5b506101f0600081565b34801561045557600080fd5b506104926040518060400160405280600581526020017f352e302e3000000000000000000000000000000000000000000000000000000081525081565b6040516101c79190611fdd565b3480156104ab57600080fd5b506101f07fcab03bc4dbcc648cd59d6bbe9f848d1e9092f914016aa290ee92e18700d1e6f981565b3480156104df57600080fd5b506101bb6104ee366004611ff0565b610da1565b3480156104ff57600080fd5b506101f07f5635ac0328a174458ffe72e6c6023489a57ff03280729989530f567288831c9181565b34801561053357600080fd5b506101f0610542366004611d42565b60026020526000908152604090205481565b34801561056057600080fd5b506101f07f17a4f53d2ecdb8066d7886a0e506b8014ce17a9a263db690785538a077e52b0981565b34801561059457600080fd5b5061021e6105a3366004611d5b565b610e2a565b3480156105b457600080fd5b5061021e6105c3366004611d42565b610e6e565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b00000000000000000000000000000000000000000000000000000000148061065b57507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b60006106c07f17a4f53d2ecdb8066d7886a0e506b8014ce17a9a263db690785538a077e52b09898989898989896040516020016106a59897969594939291906120c9565b60405160208183030381529060405280519060200120610ed4565b98975050505050505050565b60008881526003602090815260408083208a845290915290205460ff161561073b5760405162461bcd60e51b815260206004820152601960248201527f6e6f6e2d72657065617461626c652070726f63657373696e670000000000000060448201526064015b60405180910390fd5b6000805b828110156107a05760006107778a8c8b468c8c8c8c8c8b8181106107655761076561211c565b90506020028101906104ee9190612132565b9050801561078d5761078a83600161218f565b92505b5080610798816121a2565b91505061073f565b506001548110156107f35760405162461bcd60e51b815260206004820181905260248201527f766572696679207369676e6174757265732077656967687420696e76616c69646044820152606401610732565b6001600160a01b038616156108e6576040517fe09ee8700000000000000000000000000000000000000000000000000000000081526000906001600160a01b0388169063e09ee87090610852908d908d908d908c908c906004016121bb565b6020604051808303816000875af1158015610871573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061089591906121f5565b9050806108e45760405162461bcd60e51b815260206004820152600b60248201527f43616c6c206661696c65640000000000000000000000000000000000000000006044820152606401610732565b505b7f5849ae3f4bc77f0ebd2d6db4ff282f91f2191d3df4493e63176c2ed22fb81852898989468a8a8a6040516109219796959493929190612217565b60405180910390a1505050505050505050565b60008281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602052604090206001015461096e81610f1c565b6109788383610f29565b50505050565b6001600160a01b03811633146109c0576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6109ca8282610ff8565b505050565b6109d761109e565b6109e082611157565b6109ea8282611181565b5050565b60006109f8611269565b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc90565b600084815260026020526040812080549082610a38836121a2565b9091555050600085815260026020526040908190205490517f599c34a8d0b3638870afcfe3d7d8125602721889a7535cda986ea656e63fc38c91610a889146919033908a908a908a908a90612217565b60405180910390a15050506000918252506002602052604090205490565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff16600081158015610af15750825b905060008267ffffffffffffffff166001148015610b0e5750303b155b905081158015610b1c575080155b15610b53576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b845467ffffffffffffffff191660011785558315610b8757845468ff00000000000000001916680100000000000000001785555b610bfb6040518060400160405280600f81526020017f42324d65737361676542726964676500000000000000000000000000000000008152506040518060400160405280600181526020017f31000000000000000000000000000000000000000000000000000000000000008152506112b2565b610c036112c4565b610c0b6112c4565b610c16600033610f29565b50610c417f589d473ba17c0f47d494622893831497bad25919b9afb8e33e9521b8963fccde33610f29565b50610c6c7fcab03bc4dbcc648cd59d6bbe9f848d1e9092f914016aa290ee92e18700d1e6f933610f29565b508315610cb857845468ff000000000000000019168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050565b600060608082808083817fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1008054909150158015610cfe57506001810154155b610d4a5760405162461bcd60e51b815260206004820152601560248201527f4549503731323a20556e696e697469616c697a656400000000000000000000006044820152606401610732565b610d526112cc565b610d5a6113a1565b604080516000808252602082019092527f0f000000000000000000000000000000000000000000000000000000000000009c939b5091995046985030975095509350915050565b600080610db38b8b8b8b8b8b8b610661565b9050610e1b7f5635ac0328a174458ffe72e6c6023489a57ff03280729989530f567288831c9161039986868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525087939250506113f29050565b9b9a5050505050505050505050565b60008281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020526040902060010154610e6481610f1c565b6109788383610ff8565b7f589d473ba17c0f47d494622893831497bad25919b9afb8e33e9521b8963fccde610e9881610f1c565b60018290556040518281527f1b29ec9f95417d697093ba2f17ce0861fb5bcbb7d5011cdde1020c9263ecc1169060200160405180910390a15050565b600061065b610ee161141c565b836040517f19010000000000000000000000000000000000000000000000000000000000008152600281019290925260228201526042902090565b610f26813361142b565b50565b60008281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602081815260408084206001600160a01b038616855290915282205460ff16610fee576000848152602082815260408083206001600160a01b03871684529091529020805460ff19166001179055610fa43390565b6001600160a01b0316836001600160a01b0316857f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4600191505061065b565b600091505061065b565b60008281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602081815260408084206001600160a01b038616855290915282205460ff1615610fee576000848152602082815260408083206001600160a01b0387168085529252808320805460ff1916905551339287917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a4600191505061065b565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148061113757507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661112b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b6001600160a01b031614155b156111555760405163703e46dd60e11b815260040160405180910390fd5b565b7fcab03bc4dbcc648cd59d6bbe9f848d1e9092f914016aa290ee92e18700d1e6f96109ea81610f1c565b816001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156111db575060408051601f3d908101601f191682019092526111d891810190612263565b60015b61120357604051634c9c8ce360e01b81526001600160a01b0383166004820152602401610732565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc811461125f576040517faa1d49a400000000000000000000000000000000000000000000000000000000815260048101829052602401610732565b6109ca83836114b8565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146111555760405163703e46dd60e11b815260040160405180910390fd5b6112ba61150e565b6109ea8282611575565b61115561150e565b7fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10280546060917fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1009161131d9061227c565b80601f01602080910402602001604051908101604052809291908181526020018280546113499061227c565b80156113965780601f1061136b57610100808354040283529160200191611396565b820191906000526020600020905b81548152906001019060200180831161137957829003601f168201915b505050505091505090565b7fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10380546060917fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1009161131d9061227c565b60008060008061140286866115e8565b9250925092506114128282611635565b5090949350505050565b6000611426611739565b905090565b60008281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602090815260408083206001600160a01b038516845290915290205460ff166109ea576040517fe2517d3f0000000000000000000000000000000000000000000000000000000081526001600160a01b038216600482015260248101839052604401610732565b6114c1826117ad565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a2805115611506576109ca828261183c565b6109ea6118b2565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005468010000000000000000900460ff16611155576040517fd7e6bcf800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61157d61150e565b7fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1007fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1026115c98482612304565b50600381016115d88382612304565b5060008082556001909101555050565b600080600083516041036116225760208401516040850151606086015160001a611614888285856118ea565b95509550955050505061162e565b50508151600091506002905b9250925092565b6000826003811115611649576116496123c4565b03611652575050565b6001826003811115611666576116666123c4565b0361169d576040517ff645eedf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60028260038111156116b1576116b16123c4565b036116eb576040517ffce698f700000000000000000000000000000000000000000000000000000000815260048101829052602401610732565b60038260038111156116ff576116ff6123c4565b036109ea576040517fd78bce0c00000000000000000000000000000000000000000000000000000000815260048101829052602401610732565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6117646119b9565b61176c611a35565b60408051602081019490945283019190915260608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b806001600160a01b03163b6000036117e357604051634c9c8ce360e01b81526001600160a01b0382166004820152602401610732565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6060600080846001600160a01b03168460405161185991906123da565b600060405180830381855af49150503d8060008114611894576040519150601f19603f3d011682016040523d82523d6000602084013e611899565b606091505b50915091506118a9858383611a8b565b95945050505050565b3415611155576040517fb398979f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a084111561192557506000915060039050826119af565b604080516000808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa158015611979573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166119a5575060009250600191508290506119af565b9250600091508190505b9450945094915050565b60007fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d100816119e56112cc565b8051909150156119fd57805160209091012092915050565b81548015611a0c579392505050565b7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470935050505090565b60007fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10081611a616113a1565b805190915015611a7957805160209091012092915050565b60018201548015611a0c579392505050565b606082611aa057611a9b82611b03565b611afc565b8151158015611ab757506001600160a01b0384163b155b15611af9576040517f9996b3150000000000000000000000000000000000000000000000000000000081526001600160a01b0385166004820152602401610732565b50805b9392505050565b805115611b135780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060208284031215611b5757600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114611afc57600080fd5b80356001600160a01b0381168114611b9e57600080fd5b919050565b60008083601f840112611bb557600080fd5b50813567ffffffffffffffff811115611bcd57600080fd5b602083019150836020828501011115611be557600080fd5b9250929050565b600080600080600080600060c0888a031215611c0757600080fd5b8735965060208801359550611c1e60408901611b87565b945060608801359350611c3360808901611b87565b925060a088013567ffffffffffffffff811115611c4f57600080fd5b611c5b8a828b01611ba3565b989b979a50959850939692959293505050565b60008060008060008060008060c0898b031215611c8a57600080fd5b8835975060208901359650611ca160408a01611b87565b9550611caf60608a01611b87565b9450608089013567ffffffffffffffff80821115611ccc57600080fd5b611cd88c838d01611ba3565b909650945060a08b0135915080821115611cf157600080fd5b818b0191508b601f830112611d0557600080fd5b813581811115611d1457600080fd5b8c60208260051b8501011115611d2957600080fd5b6020830194508093505050509295985092959890939650565b600060208284031215611d5457600080fd5b5035919050565b60008060408385031215611d6e57600080fd5b82359150611d7e60208401611b87565b90509250929050565b634e487b7160e01b600052604160045260246000fd5b60008060408385031215611db057600080fd5b611db983611b87565b9150602083013567ffffffffffffffff80821115611dd657600080fd5b818501915085601f830112611dea57600080fd5b813581811115611dfc57611dfc611d87565b604051601f8201601f19908116603f01168101908382118183101715611e2457611e24611d87565b81604052828152886020848701011115611e3d57600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b60008060008060608587031215611e7557600080fd5b84359350611e8560208601611b87565b9250604085013567ffffffffffffffff811115611ea157600080fd5b611ead87828801611ba3565b95989497509550505050565b60005b83811015611ed4578181015183820152602001611ebc565b50506000910152565b60008151808452611ef5816020860160208601611eb9565b601f01601f19169290920160200192915050565b7fff00000000000000000000000000000000000000000000000000000000000000881681526000602060e081840152611f4560e084018a611edd565b8381036040850152611f57818a611edd565b606085018990526001600160a01b038816608086015260a0850187905284810360c0860152855180825283870192509083019060005b81811015611fa957835183529284019291840191600101611f8d565b50909c9b505050505050505050505050565b60008060408385031215611fce57600080fd5b50508035926020909101359150565b602081526000611afc6020830184611edd565b600080600080600080600080600060e08a8c03121561200e57600080fd5b8935985060208a0135975061202560408b01611b87565b965060608a0135955061203a60808b01611b87565b945060a08a013567ffffffffffffffff8082111561205757600080fd5b6120638d838e01611ba3565b909650945060c08c013591508082111561207c57600080fd5b506120898c828d01611ba3565b915080935050809150509295985092959850929598565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b88815287602082015286604082015260006001600160a01b03808816606084015286608084015280861660a08401525060e060c083015261210e60e0830184866120a0565b9a9950505050505050505050565b634e487b7160e01b600052603260045260246000fd5b6000808335601e1984360301811261214957600080fd5b83018035915067ffffffffffffffff82111561216457600080fd5b602001915036819003821315611be557600080fd5b634e487b7160e01b600052601160045260246000fd5b8082018082111561065b5761065b612179565b6000600182016121b4576121b4612179565b5060010190565b8581528460208201526001600160a01b03841660408201526080606082015260006121ea6080830184866120a0565b979650505050505050565b60006020828403121561220757600080fd5b81518015158114611afc57600080fd5b87815286602082015260006001600160a01b03808816604084015286606084015280861660808401525060c060a083015261225660c0830184866120a0565b9998505050505050505050565b60006020828403121561227557600080fd5b5051919050565b600181811c9082168061229057607f821691505b6020821081036122b057634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156109ca57600081815260208120601f850160051c810160208610156122dd5750805b601f850160051c820191505b818110156122fc578281556001016122e9565b505050505050565b815167ffffffffffffffff81111561231e5761231e611d87565b6123328161232c845461227c565b846122b6565b602080601f831160018114612367576000841561234f5750858301515b600019600386901b1c1916600185901b1785556122fc565b600085815260208120601f198616915b8281101561239657888601518255948401946001909101908401612377565b50858210156123b45787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b600052602160045260246000fd5b600082516123ec818460208701611eb9565b919091019291505056fea26469706673582212208228339ac58ba7f0c6cd5a8b7725a0b11e1581706294a7353b09ed34aa03e68164736f6c63430008140033", + "bytecode": "0x60a06040523060805234801561001457600080fd5b5060805161242761003e600039600081816110e70152818161111001526112b201526124276000f3fe6080604052600436106101965760003560e01c806384b0196e116100e1578063b908afa81161008a578063c86a64f711610064578063c86a64f714610527578063cc8f426114610554578063d547741f14610588578063fc1711f2146105a857600080fd5b8063b908afa81461049f578063bc5c11aa146104d3578063c49baebe146104f357600080fd5b8063a1aab33f116100bb578063a1aab33f1461041e578063a217fddf14610434578063ad3cb1cc1461044957600080fd5b806384b0196e1461035657806391d148541461037e5780639d449d11146103e357600080fd5b80634f1ef286116101435780636ba3300c1161011d5780636ba3300c146102ed57806375b238fc1461030d5780638129fc1c1461034157600080fd5b80634f1ef286146102af578063529d15cc146102c257806352d1902d146102d857600080fd5b8063248a9ca311610174578063248a9ca3146102205780632f2ff15d1461026f57806336568abe1461028f57600080fd5b806301ffc9a71461019b57806304760f2e146101d05780630d682acb146101fe575b600080fd5b3480156101a757600080fd5b506101bb6101b6366004611b83565b6105c8565b60405190151581526020015b60405180910390f35b3480156101dc57600080fd5b506101f06101eb366004611c2a565b610661565b6040519081526020016101c7565b34801561020a57600080fd5b5061021e610219366004611cac565b61070a565b005b34801561022c57600080fd5b506101f061023b366004611d80565b60009081527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602052604090206001015490565b34801561027b57600080fd5b5061021e61028a366004611d99565b610972565b34801561029b57600080fd5b5061021e6102aa366004611d99565b6109bc565b61021e6102bd366004611ddb565b610a0d565b3480156102ce57600080fd5b506101f060005481565b3480156102e457600080fd5b506101f0610a2c565b3480156102f957600080fd5b506101f0610308366004611e9d565b610a5b565b34801561031957600080fd5b506101f07f589d473ba17c0f47d494622893831497bad25919b9afb8e33e9521b8963fccde81565b34801561034d57600080fd5b5061021e610ae4565b34801561036257600080fd5b5061036b610cfd565b6040516101c79796959493929190611f47565b34801561038a57600080fd5b506101bb610399366004611d99565b60009182527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602090815260408084206001600160a01b0393909316845291905290205460ff1690565b3480156103ef57600080fd5b506101bb6103fe366004611ff9565b600360209081526000928352604080842090915290825290205460ff1681565b34801561042a57600080fd5b506101f060015481565b34801561044057600080fd5b506101f0600081565b34801561045557600080fd5b506104926040518060400160405280600581526020017f352e302e3000000000000000000000000000000000000000000000000000000081525081565b6040516101c7919061201b565b3480156104ab57600080fd5b506101f07fcab03bc4dbcc648cd59d6bbe9f848d1e9092f914016aa290ee92e18700d1e6f981565b3480156104df57600080fd5b506101bb6104ee36600461202e565b610ddf565b3480156104ff57600080fd5b506101f07f5635ac0328a174458ffe72e6c6023489a57ff03280729989530f567288831c9181565b34801561053357600080fd5b506101f0610542366004611d80565b60026020526000908152604090205481565b34801561056057600080fd5b506101f07f17a4f53d2ecdb8066d7886a0e506b8014ce17a9a263db690785538a077e52b0981565b34801561059457600080fd5b5061021e6105a3366004611d99565b610e68565b3480156105b457600080fd5b5061021e6105c3366004611d80565b610eac565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b00000000000000000000000000000000000000000000000000000000148061065b57507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b60006106fe7f17a4f53d2ecdb8066d7886a0e506b8014ce17a9a263db690785538a077e52b098989898989898960405161069c9291906120de565b60408051918290038220602083019890985281019590955260608501939093526001600160a01b03918216608085015260a08401521660c082015260e08101919091526101000160405160208183030381529060405280519060200120610f12565b98975050505050505050565b60008881526003602090815260408083208a845290915290205460ff16156107795760405162461bcd60e51b815260206004820152601960248201527f6e6f6e2d72657065617461626c652070726f63657373696e670000000000000060448201526064015b60405180910390fd5b6000805b828110156107de5760006107b58b8b8b468c8c8c8c8c8b8181106107a3576107a36120ee565b90506020028101906104ee9190612104565b905080156107cb576107c8836001612161565b92505b50806107d681612174565b91505061077d565b506001548110156108315760405162461bcd60e51b815260206004820181905260248201527f766572696679207369676e6174757265732077656967687420696e76616c69646044820152606401610770565b6001600160a01b03861615610924576040517fe09ee8700000000000000000000000000000000000000000000000000000000081526000906001600160a01b0388169063e09ee87090610890908d908d908d908c908c906004016121b6565b6020604051808303816000875af11580156108af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108d391906121f0565b9050806109225760405162461bcd60e51b815260206004820152600b60248201527f43616c6c206661696c65640000000000000000000000000000000000000000006044820152606401610770565b505b7f5849ae3f4bc77f0ebd2d6db4ff282f91f2191d3df4493e63176c2ed22fb81852898989468a8a8a60405161095f9796959493929190612212565b60405180910390a1505050505050505050565b60008281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b62680060205260409020600101546109ac81610f5a565b6109b68383610f67565b50505050565b6001600160a01b03811633146109fe576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a088282611036565b505050565b610a156110dc565b610a1e82611195565b610a2882826111bf565b5050565b6000610a366112a7565b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc90565b600084815260026020526040812080549082610a7683612174565b9091555050600085815260026020526040908190205490517f599c34a8d0b3638870afcfe3d7d8125602721889a7535cda986ea656e63fc38c91610ac69146919033908a908a908a908a90612212565b60405180910390a15050506000918252506002602052604090205490565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff16600081158015610b2f5750825b905060008267ffffffffffffffff166001148015610b4c5750303b155b905081158015610b5a575080155b15610b91576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b845467ffffffffffffffff191660011785558315610bc557845468ff00000000000000001916680100000000000000001785555b610c396040518060400160405280600f81526020017f42324d65737361676542726964676500000000000000000000000000000000008152506040518060400160405280600181526020017f31000000000000000000000000000000000000000000000000000000000000008152506112f0565b610c41611302565b610c49611302565b610c54600033610f67565b50610c7f7f589d473ba17c0f47d494622893831497bad25919b9afb8e33e9521b8963fccde33610f67565b50610caa7fcab03bc4dbcc648cd59d6bbe9f848d1e9092f914016aa290ee92e18700d1e6f933610f67565b508315610cf657845468ff000000000000000019168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050565b600060608082808083817fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1008054909150158015610d3c57506001810154155b610d885760405162461bcd60e51b815260206004820152601560248201527f4549503731323a20556e696e697469616c697a656400000000000000000000006044820152606401610770565b610d9061130a565b610d986113df565b604080516000808252602082019092527f0f000000000000000000000000000000000000000000000000000000000000009c939b5091995046985030975095509350915050565b600080610df18b8b8b8b8b8b8b610661565b9050610e597f5635ac0328a174458ffe72e6c6023489a57ff03280729989530f567288831c9161039986868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525087939250506114309050565b9b9a5050505050505050505050565b60008281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020526040902060010154610ea281610f5a565b6109b68383611036565b7f589d473ba17c0f47d494622893831497bad25919b9afb8e33e9521b8963fccde610ed681610f5a565b60018290556040518281527f1b29ec9f95417d697093ba2f17ce0861fb5bcbb7d5011cdde1020c9263ecc1169060200160405180910390a15050565b600061065b610f1f61145a565b836040517f19010000000000000000000000000000000000000000000000000000000000008152600281019290925260228201526042902090565b610f648133611469565b50565b60008281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602081815260408084206001600160a01b038616855290915282205460ff1661102c576000848152602082815260408083206001600160a01b03871684529091529020805460ff19166001179055610fe23390565b6001600160a01b0316836001600160a01b0316857f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4600191505061065b565b600091505061065b565b60008281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602081815260408084206001600160a01b038616855290915282205460ff161561102c576000848152602082815260408083206001600160a01b0387168085529252808320805460ff1916905551339287917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a4600191505061065b565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148061117557507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166111697f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b6001600160a01b031614155b156111935760405163703e46dd60e11b815260040160405180910390fd5b565b7fcab03bc4dbcc648cd59d6bbe9f848d1e9092f914016aa290ee92e18700d1e6f9610a2881610f5a565b816001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015611219575060408051601f3d908101601f191682019092526112169181019061225e565b60015b61124157604051634c9c8ce360e01b81526001600160a01b0383166004820152602401610770565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc811461129d576040517faa1d49a400000000000000000000000000000000000000000000000000000000815260048101829052602401610770565b610a0883836114f6565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146111935760405163703e46dd60e11b815260040160405180910390fd5b6112f861154c565b610a2882826115b3565b61119361154c565b7fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10280546060917fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1009161135b90612277565b80601f016020809104026020016040519081016040528092919081815260200182805461138790612277565b80156113d45780601f106113a9576101008083540402835291602001916113d4565b820191906000526020600020905b8154815290600101906020018083116113b757829003601f168201915b505050505091505090565b7fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10380546060917fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1009161135b90612277565b6000806000806114408686611626565b9250925092506114508282611673565b5090949350505050565b6000611464611777565b905090565b60008281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602090815260408083206001600160a01b038516845290915290205460ff16610a28576040517fe2517d3f0000000000000000000000000000000000000000000000000000000081526001600160a01b038216600482015260248101839052604401610770565b6114ff826117eb565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a280511561154457610a08828261187a565b610a286118f0565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005468010000000000000000900460ff16611193576040517fd7e6bcf800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6115bb61154c565b7fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1007fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10261160784826122ff565b506003810161161683826122ff565b5060008082556001909101555050565b600080600083516041036116605760208401516040850151606086015160001a61165288828585611928565b95509550955050505061166c565b50508151600091506002905b9250925092565b6000826003811115611687576116876123bf565b03611690575050565b60018260038111156116a4576116a46123bf565b036116db576040517ff645eedf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60028260038111156116ef576116ef6123bf565b03611729576040517ffce698f700000000000000000000000000000000000000000000000000000000815260048101829052602401610770565b600382600381111561173d5761173d6123bf565b03610a28576040517fd78bce0c00000000000000000000000000000000000000000000000000000000815260048101829052602401610770565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6117a26119f7565b6117aa611a73565b60408051602081019490945283019190915260608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b806001600160a01b03163b60000361182157604051634c9c8ce360e01b81526001600160a01b0382166004820152602401610770565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6060600080846001600160a01b03168460405161189791906123d5565b600060405180830381855af49150503d80600081146118d2576040519150601f19603f3d011682016040523d82523d6000602084013e6118d7565b606091505b50915091506118e7858383611ac9565b95945050505050565b3415611193576040517fb398979f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a084111561196357506000915060039050826119ed565b604080516000808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa1580156119b7573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166119e3575060009250600191508290506119ed565b9250600091508190505b9450945094915050565b60007fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10081611a2361130a565b805190915015611a3b57805160209091012092915050565b81548015611a4a579392505050565b7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470935050505090565b60007fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10081611a9f6113df565b805190915015611ab757805160209091012092915050565b60018201548015611a4a579392505050565b606082611ade57611ad982611b41565b611b3a565b8151158015611af557506001600160a01b0384163b155b15611b37576040517f9996b3150000000000000000000000000000000000000000000000000000000081526001600160a01b0385166004820152602401610770565b50805b9392505050565b805115611b515780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060208284031215611b9557600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114611b3a57600080fd5b80356001600160a01b0381168114611bdc57600080fd5b919050565b60008083601f840112611bf357600080fd5b50813567ffffffffffffffff811115611c0b57600080fd5b602083019150836020828501011115611c2357600080fd5b9250929050565b600080600080600080600060c0888a031215611c4557600080fd5b8735965060208801359550611c5c60408901611bc5565b945060608801359350611c7160808901611bc5565b925060a088013567ffffffffffffffff811115611c8d57600080fd5b611c998a828b01611be1565b989b979a50959850939692959293505050565b60008060008060008060008060c0898b031215611cc857600080fd5b8835975060208901359650611cdf60408a01611bc5565b9550611ced60608a01611bc5565b9450608089013567ffffffffffffffff80821115611d0a57600080fd5b611d168c838d01611be1565b909650945060a08b0135915080821115611d2f57600080fd5b818b0191508b601f830112611d4357600080fd5b813581811115611d5257600080fd5b8c60208260051b8501011115611d6757600080fd5b6020830194508093505050509295985092959890939650565b600060208284031215611d9257600080fd5b5035919050565b60008060408385031215611dac57600080fd5b82359150611dbc60208401611bc5565b90509250929050565b634e487b7160e01b600052604160045260246000fd5b60008060408385031215611dee57600080fd5b611df783611bc5565b9150602083013567ffffffffffffffff80821115611e1457600080fd5b818501915085601f830112611e2857600080fd5b813581811115611e3a57611e3a611dc5565b604051601f8201601f19908116603f01168101908382118183101715611e6257611e62611dc5565b81604052828152886020848701011115611e7b57600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b60008060008060608587031215611eb357600080fd5b84359350611ec360208601611bc5565b9250604085013567ffffffffffffffff811115611edf57600080fd5b611eeb87828801611be1565b95989497509550505050565b60005b83811015611f12578181015183820152602001611efa565b50506000910152565b60008151808452611f33816020860160208601611ef7565b601f01601f19169290920160200192915050565b7fff00000000000000000000000000000000000000000000000000000000000000881681526000602060e081840152611f8360e084018a611f1b565b8381036040850152611f95818a611f1b565b606085018990526001600160a01b038816608086015260a0850187905284810360c0860152855180825283870192509083019060005b81811015611fe757835183529284019291840191600101611fcb565b50909c9b505050505050505050505050565b6000806040838503121561200c57600080fd5b50508035926020909101359150565b602081526000611b3a6020830184611f1b565b600080600080600080600080600060e08a8c03121561204c57600080fd5b8935985060208a0135975061206360408b01611bc5565b965060608a0135955061207860808b01611bc5565b945060a08a013567ffffffffffffffff8082111561209557600080fd5b6120a18d838e01611be1565b909650945060c08c01359150808211156120ba57600080fd5b506120c78c828d01611be1565b915080935050809150509295985092959850929598565b8183823760009101908152919050565b634e487b7160e01b600052603260045260246000fd5b6000808335601e1984360301811261211b57600080fd5b83018035915067ffffffffffffffff82111561213657600080fd5b602001915036819003821315611c2357600080fd5b634e487b7160e01b600052601160045260246000fd5b8082018082111561065b5761065b61214b565b6000600182016121865761218661214b565b5060010190565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b8581528460208201526001600160a01b03841660408201526080606082015260006121e560808301848661218d565b979650505050505050565b60006020828403121561220257600080fd5b81518015158114611b3a57600080fd5b87815286602082015260006001600160a01b03808816604084015286606084015280861660808401525060c060a083015261225160c08301848661218d565b9998505050505050505050565b60006020828403121561227057600080fd5b5051919050565b600181811c9082168061228b57607f821691505b6020821081036122ab57634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115610a0857600081815260208120601f850160051c810160208610156122d85750805b601f850160051c820191505b818110156122f7578281556001016122e4565b505050505050565b815167ffffffffffffffff81111561231957612319611dc5565b61232d816123278454612277565b846122b1565b602080601f831160018114612362576000841561234a5750858301515b600019600386901b1c1916600185901b1785556122f7565b600085815260208120601f198616915b8281101561239157888601518255948401946001909101908401612372565b50858210156123af5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b600052602160045260246000fd5b600082516123e7818460208701611ef7565b919091019291505056fea264697066735822122060ec9c9dc88bae34c15afb93a894736dda08a8be657458e7929634163eb3254264736f6c63430008140033", + "deployedBytecode": "0x6080604052600436106101965760003560e01c806384b0196e116100e1578063b908afa81161008a578063c86a64f711610064578063c86a64f714610527578063cc8f426114610554578063d547741f14610588578063fc1711f2146105a857600080fd5b8063b908afa81461049f578063bc5c11aa146104d3578063c49baebe146104f357600080fd5b8063a1aab33f116100bb578063a1aab33f1461041e578063a217fddf14610434578063ad3cb1cc1461044957600080fd5b806384b0196e1461035657806391d148541461037e5780639d449d11146103e357600080fd5b80634f1ef286116101435780636ba3300c1161011d5780636ba3300c146102ed57806375b238fc1461030d5780638129fc1c1461034157600080fd5b80634f1ef286146102af578063529d15cc146102c257806352d1902d146102d857600080fd5b8063248a9ca311610174578063248a9ca3146102205780632f2ff15d1461026f57806336568abe1461028f57600080fd5b806301ffc9a71461019b57806304760f2e146101d05780630d682acb146101fe575b600080fd5b3480156101a757600080fd5b506101bb6101b6366004611b83565b6105c8565b60405190151581526020015b60405180910390f35b3480156101dc57600080fd5b506101f06101eb366004611c2a565b610661565b6040519081526020016101c7565b34801561020a57600080fd5b5061021e610219366004611cac565b61070a565b005b34801561022c57600080fd5b506101f061023b366004611d80565b60009081527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602052604090206001015490565b34801561027b57600080fd5b5061021e61028a366004611d99565b610972565b34801561029b57600080fd5b5061021e6102aa366004611d99565b6109bc565b61021e6102bd366004611ddb565b610a0d565b3480156102ce57600080fd5b506101f060005481565b3480156102e457600080fd5b506101f0610a2c565b3480156102f957600080fd5b506101f0610308366004611e9d565b610a5b565b34801561031957600080fd5b506101f07f589d473ba17c0f47d494622893831497bad25919b9afb8e33e9521b8963fccde81565b34801561034d57600080fd5b5061021e610ae4565b34801561036257600080fd5b5061036b610cfd565b6040516101c79796959493929190611f47565b34801561038a57600080fd5b506101bb610399366004611d99565b60009182527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602090815260408084206001600160a01b0393909316845291905290205460ff1690565b3480156103ef57600080fd5b506101bb6103fe366004611ff9565b600360209081526000928352604080842090915290825290205460ff1681565b34801561042a57600080fd5b506101f060015481565b34801561044057600080fd5b506101f0600081565b34801561045557600080fd5b506104926040518060400160405280600581526020017f352e302e3000000000000000000000000000000000000000000000000000000081525081565b6040516101c7919061201b565b3480156104ab57600080fd5b506101f07fcab03bc4dbcc648cd59d6bbe9f848d1e9092f914016aa290ee92e18700d1e6f981565b3480156104df57600080fd5b506101bb6104ee36600461202e565b610ddf565b3480156104ff57600080fd5b506101f07f5635ac0328a174458ffe72e6c6023489a57ff03280729989530f567288831c9181565b34801561053357600080fd5b506101f0610542366004611d80565b60026020526000908152604090205481565b34801561056057600080fd5b506101f07f17a4f53d2ecdb8066d7886a0e506b8014ce17a9a263db690785538a077e52b0981565b34801561059457600080fd5b5061021e6105a3366004611d99565b610e68565b3480156105b457600080fd5b5061021e6105c3366004611d80565b610eac565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b00000000000000000000000000000000000000000000000000000000148061065b57507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b60006106fe7f17a4f53d2ecdb8066d7886a0e506b8014ce17a9a263db690785538a077e52b098989898989898960405161069c9291906120de565b60408051918290038220602083019890985281019590955260608501939093526001600160a01b03918216608085015260a08401521660c082015260e08101919091526101000160405160208183030381529060405280519060200120610f12565b98975050505050505050565b60008881526003602090815260408083208a845290915290205460ff16156107795760405162461bcd60e51b815260206004820152601960248201527f6e6f6e2d72657065617461626c652070726f63657373696e670000000000000060448201526064015b60405180910390fd5b6000805b828110156107de5760006107b58b8b8b468c8c8c8c8c8b8181106107a3576107a36120ee565b90506020028101906104ee9190612104565b905080156107cb576107c8836001612161565b92505b50806107d681612174565b91505061077d565b506001548110156108315760405162461bcd60e51b815260206004820181905260248201527f766572696679207369676e6174757265732077656967687420696e76616c69646044820152606401610770565b6001600160a01b03861615610924576040517fe09ee8700000000000000000000000000000000000000000000000000000000081526000906001600160a01b0388169063e09ee87090610890908d908d908d908c908c906004016121b6565b6020604051808303816000875af11580156108af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108d391906121f0565b9050806109225760405162461bcd60e51b815260206004820152600b60248201527f43616c6c206661696c65640000000000000000000000000000000000000000006044820152606401610770565b505b7f5849ae3f4bc77f0ebd2d6db4ff282f91f2191d3df4493e63176c2ed22fb81852898989468a8a8a60405161095f9796959493929190612212565b60405180910390a1505050505050505050565b60008281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b62680060205260409020600101546109ac81610f5a565b6109b68383610f67565b50505050565b6001600160a01b03811633146109fe576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a088282611036565b505050565b610a156110dc565b610a1e82611195565b610a2882826111bf565b5050565b6000610a366112a7565b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc90565b600084815260026020526040812080549082610a7683612174565b9091555050600085815260026020526040908190205490517f599c34a8d0b3638870afcfe3d7d8125602721889a7535cda986ea656e63fc38c91610ac69146919033908a908a908a908a90612212565b60405180910390a15050506000918252506002602052604090205490565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff16600081158015610b2f5750825b905060008267ffffffffffffffff166001148015610b4c5750303b155b905081158015610b5a575080155b15610b91576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b845467ffffffffffffffff191660011785558315610bc557845468ff00000000000000001916680100000000000000001785555b610c396040518060400160405280600f81526020017f42324d65737361676542726964676500000000000000000000000000000000008152506040518060400160405280600181526020017f31000000000000000000000000000000000000000000000000000000000000008152506112f0565b610c41611302565b610c49611302565b610c54600033610f67565b50610c7f7f589d473ba17c0f47d494622893831497bad25919b9afb8e33e9521b8963fccde33610f67565b50610caa7fcab03bc4dbcc648cd59d6bbe9f848d1e9092f914016aa290ee92e18700d1e6f933610f67565b508315610cf657845468ff000000000000000019168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050565b600060608082808083817fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1008054909150158015610d3c57506001810154155b610d885760405162461bcd60e51b815260206004820152601560248201527f4549503731323a20556e696e697469616c697a656400000000000000000000006044820152606401610770565b610d9061130a565b610d986113df565b604080516000808252602082019092527f0f000000000000000000000000000000000000000000000000000000000000009c939b5091995046985030975095509350915050565b600080610df18b8b8b8b8b8b8b610661565b9050610e597f5635ac0328a174458ffe72e6c6023489a57ff03280729989530f567288831c9161039986868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525087939250506114309050565b9b9a5050505050505050505050565b60008281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020526040902060010154610ea281610f5a565b6109b68383611036565b7f589d473ba17c0f47d494622893831497bad25919b9afb8e33e9521b8963fccde610ed681610f5a565b60018290556040518281527f1b29ec9f95417d697093ba2f17ce0861fb5bcbb7d5011cdde1020c9263ecc1169060200160405180910390a15050565b600061065b610f1f61145a565b836040517f19010000000000000000000000000000000000000000000000000000000000008152600281019290925260228201526042902090565b610f648133611469565b50565b60008281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602081815260408084206001600160a01b038616855290915282205460ff1661102c576000848152602082815260408083206001600160a01b03871684529091529020805460ff19166001179055610fe23390565b6001600160a01b0316836001600160a01b0316857f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4600191505061065b565b600091505061065b565b60008281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602081815260408084206001600160a01b038616855290915282205460ff161561102c576000848152602082815260408083206001600160a01b0387168085529252808320805460ff1916905551339287917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a4600191505061065b565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148061117557507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166111697f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b6001600160a01b031614155b156111935760405163703e46dd60e11b815260040160405180910390fd5b565b7fcab03bc4dbcc648cd59d6bbe9f848d1e9092f914016aa290ee92e18700d1e6f9610a2881610f5a565b816001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015611219575060408051601f3d908101601f191682019092526112169181019061225e565b60015b61124157604051634c9c8ce360e01b81526001600160a01b0383166004820152602401610770565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc811461129d576040517faa1d49a400000000000000000000000000000000000000000000000000000000815260048101829052602401610770565b610a0883836114f6565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146111935760405163703e46dd60e11b815260040160405180910390fd5b6112f861154c565b610a2882826115b3565b61119361154c565b7fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10280546060917fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1009161135b90612277565b80601f016020809104026020016040519081016040528092919081815260200182805461138790612277565b80156113d45780601f106113a9576101008083540402835291602001916113d4565b820191906000526020600020905b8154815290600101906020018083116113b757829003601f168201915b505050505091505090565b7fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10380546060917fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1009161135b90612277565b6000806000806114408686611626565b9250925092506114508282611673565b5090949350505050565b6000611464611777565b905090565b60008281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602090815260408083206001600160a01b038516845290915290205460ff16610a28576040517fe2517d3f0000000000000000000000000000000000000000000000000000000081526001600160a01b038216600482015260248101839052604401610770565b6114ff826117eb565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a280511561154457610a08828261187a565b610a286118f0565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005468010000000000000000900460ff16611193576040517fd7e6bcf800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6115bb61154c565b7fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1007fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10261160784826122ff565b506003810161161683826122ff565b5060008082556001909101555050565b600080600083516041036116605760208401516040850151606086015160001a61165288828585611928565b95509550955050505061166c565b50508151600091506002905b9250925092565b6000826003811115611687576116876123bf565b03611690575050565b60018260038111156116a4576116a46123bf565b036116db576040517ff645eedf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60028260038111156116ef576116ef6123bf565b03611729576040517ffce698f700000000000000000000000000000000000000000000000000000000815260048101829052602401610770565b600382600381111561173d5761173d6123bf565b03610a28576040517fd78bce0c00000000000000000000000000000000000000000000000000000000815260048101829052602401610770565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6117a26119f7565b6117aa611a73565b60408051602081019490945283019190915260608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b806001600160a01b03163b60000361182157604051634c9c8ce360e01b81526001600160a01b0382166004820152602401610770565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6060600080846001600160a01b03168460405161189791906123d5565b600060405180830381855af49150503d80600081146118d2576040519150601f19603f3d011682016040523d82523d6000602084013e6118d7565b606091505b50915091506118e7858383611ac9565b95945050505050565b3415611193576040517fb398979f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a084111561196357506000915060039050826119ed565b604080516000808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa1580156119b7573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166119e3575060009250600191508290506119ed565b9250600091508190505b9450945094915050565b60007fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10081611a2361130a565b805190915015611a3b57805160209091012092915050565b81548015611a4a579392505050565b7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470935050505090565b60007fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10081611a9f6113df565b805190915015611ab757805160209091012092915050565b60018201548015611a4a579392505050565b606082611ade57611ad982611b41565b611b3a565b8151158015611af557506001600160a01b0384163b155b15611b37576040517f9996b3150000000000000000000000000000000000000000000000000000000081526001600160a01b0385166004820152602401610770565b50805b9392505050565b805115611b515780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060208284031215611b9557600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114611b3a57600080fd5b80356001600160a01b0381168114611bdc57600080fd5b919050565b60008083601f840112611bf357600080fd5b50813567ffffffffffffffff811115611c0b57600080fd5b602083019150836020828501011115611c2357600080fd5b9250929050565b600080600080600080600060c0888a031215611c4557600080fd5b8735965060208801359550611c5c60408901611bc5565b945060608801359350611c7160808901611bc5565b925060a088013567ffffffffffffffff811115611c8d57600080fd5b611c998a828b01611be1565b989b979a50959850939692959293505050565b60008060008060008060008060c0898b031215611cc857600080fd5b8835975060208901359650611cdf60408a01611bc5565b9550611ced60608a01611bc5565b9450608089013567ffffffffffffffff80821115611d0a57600080fd5b611d168c838d01611be1565b909650945060a08b0135915080821115611d2f57600080fd5b818b0191508b601f830112611d4357600080fd5b813581811115611d5257600080fd5b8c60208260051b8501011115611d6757600080fd5b6020830194508093505050509295985092959890939650565b600060208284031215611d9257600080fd5b5035919050565b60008060408385031215611dac57600080fd5b82359150611dbc60208401611bc5565b90509250929050565b634e487b7160e01b600052604160045260246000fd5b60008060408385031215611dee57600080fd5b611df783611bc5565b9150602083013567ffffffffffffffff80821115611e1457600080fd5b818501915085601f830112611e2857600080fd5b813581811115611e3a57611e3a611dc5565b604051601f8201601f19908116603f01168101908382118183101715611e6257611e62611dc5565b81604052828152886020848701011115611e7b57600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b60008060008060608587031215611eb357600080fd5b84359350611ec360208601611bc5565b9250604085013567ffffffffffffffff811115611edf57600080fd5b611eeb87828801611be1565b95989497509550505050565b60005b83811015611f12578181015183820152602001611efa565b50506000910152565b60008151808452611f33816020860160208601611ef7565b601f01601f19169290920160200192915050565b7fff00000000000000000000000000000000000000000000000000000000000000881681526000602060e081840152611f8360e084018a611f1b565b8381036040850152611f95818a611f1b565b606085018990526001600160a01b038816608086015260a0850187905284810360c0860152855180825283870192509083019060005b81811015611fe757835183529284019291840191600101611fcb565b50909c9b505050505050505050505050565b6000806040838503121561200c57600080fd5b50508035926020909101359150565b602081526000611b3a6020830184611f1b565b600080600080600080600080600060e08a8c03121561204c57600080fd5b8935985060208a0135975061206360408b01611bc5565b965060608a0135955061207860808b01611bc5565b945060a08a013567ffffffffffffffff8082111561209557600080fd5b6120a18d838e01611be1565b909650945060c08c01359150808211156120ba57600080fd5b506120c78c828d01611be1565b915080935050809150509295985092959850929598565b8183823760009101908152919050565b634e487b7160e01b600052603260045260246000fd5b6000808335601e1984360301811261211b57600080fd5b83018035915067ffffffffffffffff82111561213657600080fd5b602001915036819003821315611c2357600080fd5b634e487b7160e01b600052601160045260246000fd5b8082018082111561065b5761065b61214b565b6000600182016121865761218661214b565b5060010190565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b8581528460208201526001600160a01b03841660408201526080606082015260006121e560808301848661218d565b979650505050505050565b60006020828403121561220257600080fd5b81518015158114611b3a57600080fd5b87815286602082015260006001600160a01b03808816604084015286606084015280861660808401525060c060a083015261225160c08301848661218d565b9998505050505050505050565b60006020828403121561227057600080fd5b5051919050565b600181811c9082168061228b57607f821691505b6020821081036122ab57634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115610a0857600081815260208120601f850160051c810160208610156122d85750805b601f850160051c820191505b818110156122f7578281556001016122e4565b505050505050565b815167ffffffffffffffff81111561231957612319611dc5565b61232d816123278454612277565b846122b1565b602080601f831160018114612362576000841561234a5750858301515b600019600386901b1c1916600185901b1785556122f7565b600085815260208120601f198616915b8281101561239157888601518255948401946001909101908401612372565b50858210156123af5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b600052602160045260246000fd5b600082516123e7818460208701611ef7565b919091019291505056fea264697066735822122060ec9c9dc88bae34c15afb93a894736dda08a8be657458e7929634163eb3254264736f6c63430008140033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/contracts/artifacts/contracts/message/B2MessageBridge.sol/IBusinessContract.dbg.json b/contracts/artifacts/contracts/message/B2MessageBridge.sol/IBusinessContract.dbg.json index 116ee53e..7447626a 100644 --- a/contracts/artifacts/contracts/message/B2MessageBridge.sol/IBusinessContract.dbg.json +++ b/contracts/artifacts/contracts/message/B2MessageBridge.sol/IBusinessContract.dbg.json @@ -1,4 +1,4 @@ { "_format": "hh-sol-dbg-1", - "buildInfo": "../../../build-info/b6b5a288b7f14e968aadb592e7a63ae5.json" + "buildInfo": "../../../build-info/70e62623267d7ba9585ce6fb07d39bd0.json" } diff --git a/contracts/cache/solidity-files-cache.json b/contracts/cache/solidity-files-cache.json index 535cbab8..0f1e038e 100644 --- a/contracts/cache/solidity-files-cache.json +++ b/contracts/cache/solidity-files-cache.json @@ -732,8 +732,8 @@ ] }, "/Users/m/Workspaces/b2-network/b2-message-channel/contracts/contracts/message/B2MessageBridge.sol": { - "lastModificationDate": 1723514792670, - "contentHash": "b952757f06c05e4d7e0871f9991cfd63", + "lastModificationDate": 1724732070009, + "contentHash": "24a68336c647f62be054d722872d6f87", "sourceName": "contracts/message/B2MessageBridge.sol", "solcConfig": { "version": "0.8.20", diff --git a/contracts/cache/validations.json b/contracts/cache/validations.json index 3ccceba0..09f3c7d1 100644 --- a/contracts/cache/validations.json +++ b/contracts/cache/validations.json @@ -826,6 +826,3378 @@ }, "solcVersion": "0.8.20" }, + "contracts/message/B2MessageBridge.sol:B2MessageBridge": { + "src": "contracts/message/B2MessageBridge.sol:19", + "version": { + "withMetadata": "47af71cc66d954273bae1c277bc6b43d95c3661b83dd66d9f8a345d5f9e68f3a", + "withoutMetadata": "761be4fd462127a5b98506e034b0a1d4d3274a6054936536bee56fb2465e26cb", + "linkedWithoutMetadata": "761be4fd462127a5b98506e034b0a1d4d3274a6054936536bee56fb2465e26cb" + }, + "inherit": [ + "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:AccessControlUpgradeable", + "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol:ERC165Upgradeable", + "@openzeppelin/contracts/utils/introspection/IERC165.sol:IERC165", + "@openzeppelin/contracts/access/IAccessControl.sol:IAccessControl", + "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:ContextUpgradeable", + "@openzeppelin/contracts-upgradeable/utils/cryptography/EIP712Upgradeable.sol:EIP712Upgradeable", + "@openzeppelin/contracts/interfaces/IERC5267.sol:IERC5267", + "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol:UUPSUpgradeable", + "@openzeppelin/contracts/interfaces/draft-IERC1822.sol:IERC1822Proxiable", + "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:Initializable", + "contracts/message/B2MessageBridge.sol:IB2MessageBridge" + ], + "libraries": [ + "@openzeppelin/contracts/utils/cryptography/ECDSA.sol:ECDSA" + ], + "methods": [ + "initialize()", + "setWeight(uint256)", + "send(uint256,uint256,address,address,bytes,bytes[])", + "call(uint256,address,bytes)", + "verify(uint256,uint256,address,uint256,address,bytes,bytes)", + "SendHash(uint256,uint256,address,uint256,address,bytes)" + ], + "linkReferences": [], + "errors": [], + "layout": { + "storage": [ + { + "label": "sequence", + "offset": 0, + "slot": "0", + "type": "t_uint256", + "contract": "B2MessageBridge", + "src": "contracts/message/B2MessageBridge.sol:26" + }, + { + "label": "weight", + "offset": 0, + "slot": "1", + "type": "t_uint256", + "contract": "B2MessageBridge", + "src": "contracts/message/B2MessageBridge.sol:27" + }, + { + "label": "sequences", + "offset": 0, + "slot": "2", + "type": "t_mapping(t_uint256,t_uint256)", + "contract": "B2MessageBridge", + "src": "contracts/message/B2MessageBridge.sol:28" + }, + { + "label": "ids", + "offset": 0, + "slot": "3", + "type": "t_mapping(t_uint256,t_mapping(t_uint256,t_bool))", + "contract": "B2MessageBridge", + "src": "contracts/message/B2MessageBridge.sol:29" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_bytes32,t_struct(RoleData)25_storage)": { + "label": "mapping(bytes32 => struct AccessControlUpgradeable.RoleData)", + "numberOfBytes": "32" + }, + "t_string_storage": { + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(AccessControlStorage)35_storage": { + "label": "struct AccessControlUpgradeable.AccessControlStorage", + "members": [ + { + "label": "_roles", + "type": "t_mapping(t_bytes32,t_struct(RoleData)25_storage)", + "offset": 0, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_struct(EIP712Storage)376_storage": { + "label": "struct EIP712Upgradeable.EIP712Storage", + "members": [ + { + "label": "_hashedName", + "type": "t_bytes32", + "offset": 0, + "slot": "0" + }, + { + "label": "_hashedVersion", + "type": "t_bytes32", + "offset": 0, + "slot": "1" + }, + { + "label": "_name", + "type": "t_string_storage", + "offset": 0, + "slot": "2" + }, + { + "label": "_version", + "type": "t_string_storage", + "offset": 0, + "slot": "3" + } + ], + "numberOfBytes": "128" + }, + "t_struct(InitializableStorage)174_storage": { + "label": "struct Initializable.InitializableStorage", + "members": [ + { + "label": "_initialized", + "type": "t_uint64", + "offset": 0, + "slot": "0" + }, + { + "label": "_initializing", + "type": "t_bool", + "offset": 8, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_struct(RoleData)25_storage": { + "label": "struct AccessControlUpgradeable.RoleData", + "members": [ + { + "label": "hasRole", + "type": "t_mapping(t_address,t_bool)", + "offset": 0, + "slot": "0" + }, + { + "label": "adminRole", + "type": "t_bytes32", + "offset": 0, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_uint64": { + "label": "uint64", + "numberOfBytes": "8" + }, + "t_mapping(t_uint256,t_bool)": { + "label": "mapping(uint256 => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_mapping(t_uint256,t_bool))": { + "label": "mapping(uint256 => mapping(uint256 => bool))", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_uint256)": { + "label": "mapping(uint256 => uint256)", + "numberOfBytes": "32" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + } + }, + "layoutVersion": "1.2", + "flat": true, + "namespaces": { + "erc7201:openzeppelin.storage.AccessControl": [ + { + "contract": "AccessControlUpgradeable", + "label": "_roles", + "type": "t_mapping(t_bytes32,t_struct(RoleData)25_storage)", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:61", + "offset": 0, + "slot": "0" + } + ], + "erc7201:openzeppelin.storage.EIP712": [ + { + "contract": "EIP712Upgradeable", + "label": "_hashedName", + "type": "t_bytes32", + "src": "@openzeppelin/contracts-upgradeable/utils/cryptography/EIP712Upgradeable.sol:39", + "offset": 0, + "slot": "0" + }, + { + "contract": "EIP712Upgradeable", + "label": "_hashedVersion", + "type": "t_bytes32", + "src": "@openzeppelin/contracts-upgradeable/utils/cryptography/EIP712Upgradeable.sol:41", + "offset": 0, + "slot": "1" + }, + { + "contract": "EIP712Upgradeable", + "label": "_name", + "type": "t_string_storage", + "src": "@openzeppelin/contracts-upgradeable/utils/cryptography/EIP712Upgradeable.sol:43", + "offset": 0, + "slot": "2" + }, + { + "contract": "EIP712Upgradeable", + "label": "_version", + "type": "t_string_storage", + "src": "@openzeppelin/contracts-upgradeable/utils/cryptography/EIP712Upgradeable.sol:44", + "offset": 0, + "slot": "3" + } + ], + "erc7201:openzeppelin.storage.Initializable": [ + { + "contract": "Initializable", + "label": "_initialized", + "type": "t_uint64", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:69", + "offset": 0, + "slot": "0" + }, + { + "contract": "Initializable", + "label": "_initializing", + "type": "t_bool", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:73", + "offset": 8, + "slot": "0" + } + ] + } + }, + "solcVersion": "0.8.20" + }, + "contracts/message/B2MessageBridge.sol:IB2MessageBridge": { + "src": "contracts/message/B2MessageBridge.sol:10", + "inherit": [], + "libraries": [], + "methods": [ + "call(uint256,address,bytes)", + "send(uint256,uint256,address,address,bytes,bytes[])" + ], + "linkReferences": [], + "errors": [], + "layout": { + "storage": [], + "types": {}, + "layoutVersion": "1.2", + "flat": false, + "namespaces": {} + }, + "solcVersion": "0.8.20" + }, + "contracts/message/B2MessageBridge.sol:IBusinessContract": { + "src": "contracts/message/B2MessageBridge.sol:15", + "inherit": [], + "libraries": [], + "methods": [ + "send(uint256,uint256,address,bytes)" + ], + "linkReferences": [], + "errors": [], + "layout": { + "storage": [], + "types": {}, + "layoutVersion": "1.2", + "flat": false, + "namespaces": {} + }, + "solcVersion": "0.8.20" + } + }, + { + "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:AccessControlUpgradeable": { + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:50", + "inherit": [ + "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol:ERC165Upgradeable", + "@openzeppelin/contracts/utils/introspection/IERC165.sol:IERC165", + "@openzeppelin/contracts/access/IAccessControl.sol:IAccessControl", + "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:ContextUpgradeable", + "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:Initializable" + ], + "libraries": [], + "methods": [ + "supportsInterface(bytes4)", + "hasRole(bytes32,address)", + "getRoleAdmin(bytes32)", + "grantRole(bytes32,address)", + "revokeRole(bytes32,address)", + "renounceRole(bytes32,address)" + ], + "linkReferences": [], + "errors": [], + "layout": { + "storage": [], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_bytes32,t_struct(RoleData)25_storage)": { + "label": "mapping(bytes32 => struct AccessControlUpgradeable.RoleData)", + "numberOfBytes": "32" + }, + "t_struct(AccessControlStorage)35_storage": { + "label": "struct AccessControlUpgradeable.AccessControlStorage", + "members": [ + { + "label": "_roles", + "type": "t_mapping(t_bytes32,t_struct(RoleData)25_storage)", + "offset": 0, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_struct(InitializableStorage)174_storage": { + "label": "struct Initializable.InitializableStorage", + "members": [ + { + "label": "_initialized", + "type": "t_uint64", + "offset": 0, + "slot": "0" + }, + { + "label": "_initializing", + "type": "t_bool", + "offset": 8, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_struct(RoleData)25_storage": { + "label": "struct AccessControlUpgradeable.RoleData", + "members": [ + { + "label": "hasRole", + "type": "t_mapping(t_address,t_bool)", + "offset": 0, + "slot": "0" + }, + { + "label": "adminRole", + "type": "t_bytes32", + "offset": 0, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_uint64": { + "label": "uint64", + "numberOfBytes": "8" + } + }, + "layoutVersion": "1.2", + "flat": false, + "namespaces": { + "erc7201:openzeppelin.storage.AccessControl": [ + { + "contract": "AccessControlUpgradeable", + "label": "_roles", + "type": "t_mapping(t_bytes32,t_struct(RoleData)25_storage)", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:61", + "offset": 0, + "slot": "0" + } + ], + "erc7201:openzeppelin.storage.Initializable": [ + { + "contract": "Initializable", + "label": "_initialized", + "type": "t_uint64", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:69", + "offset": 0, + "slot": "0" + }, + { + "contract": "Initializable", + "label": "_initializing", + "type": "t_bool", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:73", + "offset": 8, + "slot": "0" + } + ] + } + }, + "solcVersion": "0.8.20" + }, + "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:Initializable": { + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:56", + "inherit": [], + "libraries": [], + "methods": [], + "linkReferences": [], + "errors": [], + "layout": { + "storage": [], + "types": { + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_struct(InitializableStorage)174_storage": { + "label": "struct Initializable.InitializableStorage", + "members": [ + { + "label": "_initialized", + "type": "t_uint64", + "offset": 0, + "slot": "0" + }, + { + "label": "_initializing", + "type": "t_bool", + "offset": 8, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_uint64": { + "label": "uint64", + "numberOfBytes": "8" + } + }, + "layoutVersion": "1.2", + "flat": false, + "namespaces": { + "erc7201:openzeppelin.storage.Initializable": [ + { + "contract": "Initializable", + "label": "_initialized", + "type": "t_uint64", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:69", + "offset": 0, + "slot": "0" + }, + { + "contract": "Initializable", + "label": "_initializing", + "type": "t_bool", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:73", + "offset": 8, + "slot": "0" + } + ] + } + }, + "solcVersion": "0.8.20" + }, + "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol:UUPSUpgradeable": { + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol:20", + "inherit": [ + "@openzeppelin/contracts/interfaces/draft-IERC1822.sol:IERC1822Proxiable", + "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:Initializable" + ], + "libraries": [ + "@openzeppelin/contracts/proxy/ERC1967/ERC1967Utils.sol:ERC1967Utils" + ], + "methods": [ + "proxiableUUID()", + "upgradeToAndCall(address,bytes)" + ], + "linkReferences": [], + "errors": [ + { + "kind": "delegatecall", + "src": "@openzeppelin/contracts/utils/Address.sol:105" + } + ], + "layout": { + "storage": [], + "types": { + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_struct(InitializableStorage)174_storage": { + "label": "struct Initializable.InitializableStorage", + "members": [ + { + "label": "_initialized", + "type": "t_uint64", + "offset": 0, + "slot": "0" + }, + { + "label": "_initializing", + "type": "t_bool", + "offset": 8, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_uint64": { + "label": "uint64", + "numberOfBytes": "8" + } + }, + "layoutVersion": "1.2", + "flat": false, + "namespaces": { + "erc7201:openzeppelin.storage.Initializable": [ + { + "contract": "Initializable", + "label": "_initialized", + "type": "t_uint64", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:69", + "offset": 0, + "slot": "0" + }, + { + "contract": "Initializable", + "label": "_initializing", + "type": "t_bool", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:73", + "offset": 8, + "slot": "0" + } + ] + } + }, + "solcVersion": "0.8.20" + }, + "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:ContextUpgradeable": { + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:17", + "inherit": [ + "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:Initializable" + ], + "libraries": [], + "methods": [], + "linkReferences": [], + "errors": [], + "layout": { + "storage": [], + "types": { + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_struct(InitializableStorage)174_storage": { + "label": "struct Initializable.InitializableStorage", + "members": [ + { + "label": "_initialized", + "type": "t_uint64", + "offset": 0, + "slot": "0" + }, + { + "label": "_initializing", + "type": "t_bool", + "offset": 8, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_uint64": { + "label": "uint64", + "numberOfBytes": "8" + } + }, + "layoutVersion": "1.2", + "flat": false, + "namespaces": { + "erc7201:openzeppelin.storage.Initializable": [ + { + "contract": "Initializable", + "label": "_initialized", + "type": "t_uint64", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:69", + "offset": 0, + "slot": "0" + }, + { + "contract": "Initializable", + "label": "_initializing", + "type": "t_bool", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:73", + "offset": 8, + "slot": "0" + } + ] + } + }, + "solcVersion": "0.8.20" + }, + "@openzeppelin/contracts-upgradeable/utils/cryptography/EIP712Upgradeable.sol:EIP712Upgradeable": { + "src": "@openzeppelin/contracts-upgradeable/utils/cryptography/EIP712Upgradeable.sol:32", + "inherit": [ + "@openzeppelin/contracts/interfaces/IERC5267.sol:IERC5267", + "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:Initializable" + ], + "libraries": [ + "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol:MessageHashUtils" + ], + "methods": [ + "eip712Domain()" + ], + "linkReferences": [], + "errors": [], + "layout": { + "storage": [], + "types": { + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_string_storage": { + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(EIP712Storage)376_storage": { + "label": "struct EIP712Upgradeable.EIP712Storage", + "members": [ + { + "label": "_hashedName", + "type": "t_bytes32", + "offset": 0, + "slot": "0" + }, + { + "label": "_hashedVersion", + "type": "t_bytes32", + "offset": 0, + "slot": "1" + }, + { + "label": "_name", + "type": "t_string_storage", + "offset": 0, + "slot": "2" + }, + { + "label": "_version", + "type": "t_string_storage", + "offset": 0, + "slot": "3" + } + ], + "numberOfBytes": "128" + }, + "t_struct(InitializableStorage)174_storage": { + "label": "struct Initializable.InitializableStorage", + "members": [ + { + "label": "_initialized", + "type": "t_uint64", + "offset": 0, + "slot": "0" + }, + { + "label": "_initializing", + "type": "t_bool", + "offset": 8, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_uint64": { + "label": "uint64", + "numberOfBytes": "8" + } + }, + "layoutVersion": "1.2", + "flat": false, + "namespaces": { + "erc7201:openzeppelin.storage.EIP712": [ + { + "contract": "EIP712Upgradeable", + "label": "_hashedName", + "type": "t_bytes32", + "src": "@openzeppelin/contracts-upgradeable/utils/cryptography/EIP712Upgradeable.sol:39", + "offset": 0, + "slot": "0" + }, + { + "contract": "EIP712Upgradeable", + "label": "_hashedVersion", + "type": "t_bytes32", + "src": "@openzeppelin/contracts-upgradeable/utils/cryptography/EIP712Upgradeable.sol:41", + "offset": 0, + "slot": "1" + }, + { + "contract": "EIP712Upgradeable", + "label": "_name", + "type": "t_string_storage", + "src": "@openzeppelin/contracts-upgradeable/utils/cryptography/EIP712Upgradeable.sol:43", + "offset": 0, + "slot": "2" + }, + { + "contract": "EIP712Upgradeable", + "label": "_version", + "type": "t_string_storage", + "src": "@openzeppelin/contracts-upgradeable/utils/cryptography/EIP712Upgradeable.sol:44", + "offset": 0, + "slot": "3" + } + ], + "erc7201:openzeppelin.storage.Initializable": [ + { + "contract": "Initializable", + "label": "_initialized", + "type": "t_uint64", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:69", + "offset": 0, + "slot": "0" + }, + { + "contract": "Initializable", + "label": "_initializing", + "type": "t_bool", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:73", + "offset": 8, + "slot": "0" + } + ] + } + }, + "solcVersion": "0.8.20" + }, + "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol:ERC165Upgradeable": { + "src": "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol:21", + "inherit": [ + "@openzeppelin/contracts/utils/introspection/IERC165.sol:IERC165", + "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:Initializable" + ], + "libraries": [], + "methods": [ + "supportsInterface(bytes4)" + ], + "linkReferences": [], + "errors": [], + "layout": { + "storage": [], + "types": { + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_struct(InitializableStorage)174_storage": { + "label": "struct Initializable.InitializableStorage", + "members": [ + { + "label": "_initialized", + "type": "t_uint64", + "offset": 0, + "slot": "0" + }, + { + "label": "_initializing", + "type": "t_bool", + "offset": 8, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_uint64": { + "label": "uint64", + "numberOfBytes": "8" + } + }, + "layoutVersion": "1.2", + "flat": false, + "namespaces": { + "erc7201:openzeppelin.storage.Initializable": [ + { + "contract": "Initializable", + "label": "_initialized", + "type": "t_uint64", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:69", + "offset": 0, + "slot": "0" + }, + { + "contract": "Initializable", + "label": "_initializing", + "type": "t_bool", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:73", + "offset": 8, + "slot": "0" + } + ] + } + }, + "solcVersion": "0.8.20" + }, + "@openzeppelin/contracts/access/IAccessControl.sol:IAccessControl": { + "src": "@openzeppelin/contracts/access/IAccessControl.sol:9", + "inherit": [], + "libraries": [], + "methods": [ + "hasRole(bytes32,address)", + "getRoleAdmin(bytes32)", + "grantRole(bytes32,address)", + "revokeRole(bytes32,address)", + "renounceRole(bytes32,address)" + ], + "linkReferences": [], + "errors": [], + "layout": { + "storage": [], + "types": {}, + "layoutVersion": "1.2", + "flat": false, + "namespaces": {} + }, + "solcVersion": "0.8.20" + }, + "@openzeppelin/contracts/interfaces/IERC5267.sol:IERC5267": { + "src": "@openzeppelin/contracts/interfaces/IERC5267.sol:6", + "inherit": [], + "libraries": [], + "methods": [ + "eip712Domain()" + ], + "linkReferences": [], + "errors": [], + "layout": { + "storage": [], + "types": {}, + "layoutVersion": "1.2", + "flat": false, + "namespaces": {} + }, + "solcVersion": "0.8.20" + }, + "@openzeppelin/contracts/interfaces/draft-IERC1822.sol:IERC1822Proxiable": { + "src": "@openzeppelin/contracts/interfaces/draft-IERC1822.sol:10", + "inherit": [], + "libraries": [], + "methods": [ + "proxiableUUID()" + ], + "linkReferences": [], + "errors": [], + "layout": { + "storage": [], + "types": {}, + "layoutVersion": "1.2", + "flat": false, + "namespaces": {} + }, + "solcVersion": "0.8.20" + }, + "@openzeppelin/contracts/proxy/ERC1967/ERC1967Utils.sol:ERC1967Utils": { + "src": "@openzeppelin/contracts/proxy/ERC1967/ERC1967Utils.sol:14", + "version": { + "withMetadata": "da0ca15378c152c2e5da0d6bf0e27590374c4a5c250bc2a82167eedfe4c704bd", + "withoutMetadata": "a64c6cf9c6ba9368f5132c93a0196b3204a7963dbb4dd05dfddb4ab23126b8db", + "linkedWithoutMetadata": "a64c6cf9c6ba9368f5132c93a0196b3204a7963dbb4dd05dfddb4ab23126b8db" + }, + "inherit": [], + "libraries": [ + "@openzeppelin/contracts/utils/StorageSlot.sol:StorageSlot", + "@openzeppelin/contracts/utils/Address.sol:Address" + ], + "methods": [], + "linkReferences": [], + "errors": [ + { + "kind": "delegatecall", + "src": "@openzeppelin/contracts/utils/Address.sol:105" + }, + { + "kind": "delegatecall", + "src": "@openzeppelin/contracts/utils/Address.sol:105" + } + ], + "layout": { + "storage": [], + "types": {}, + "layoutVersion": "1.2", + "flat": false, + "namespaces": {} + }, + "solcVersion": "0.8.20" + }, + "@openzeppelin/contracts/proxy/beacon/IBeacon.sol:IBeacon": { + "src": "@openzeppelin/contracts/proxy/beacon/IBeacon.sol:9", + "inherit": [], + "libraries": [], + "methods": [ + "implementation()" + ], + "linkReferences": [], + "errors": [], + "layout": { + "storage": [], + "types": {}, + "layoutVersion": "1.2", + "flat": false, + "namespaces": {} + }, + "solcVersion": "0.8.20" + }, + "@openzeppelin/contracts/utils/Address.sol:Address": { + "src": "@openzeppelin/contracts/utils/Address.sol:9", + "version": { + "withMetadata": "87fe4495dfc9354a67a3f830c1c6ae271f7d13aa51b702039300545894a3ef6b", + "withoutMetadata": "a64c6cf9c6ba9368f5132c93a0196b3204a7963dbb4dd05dfddb4ab23126b8db", + "linkedWithoutMetadata": "a64c6cf9c6ba9368f5132c93a0196b3204a7963dbb4dd05dfddb4ab23126b8db" + }, + "inherit": [], + "libraries": [], + "methods": [], + "linkReferences": [], + "errors": [ + { + "kind": "delegatecall", + "src": "@openzeppelin/contracts/utils/Address.sol:105" + } + ], + "layout": { + "storage": [], + "types": {}, + "layoutVersion": "1.2", + "flat": false, + "namespaces": {} + }, + "solcVersion": "0.8.20" + }, + "@openzeppelin/contracts/utils/StorageSlot.sol:StorageSlot": { + "src": "@openzeppelin/contracts/utils/StorageSlot.sol:31", + "version": { + "withMetadata": "7265f6e3db839ed1e12b293fcc2217f69e669b109fb6d18bebad36e761707f76", + "withoutMetadata": "a64c6cf9c6ba9368f5132c93a0196b3204a7963dbb4dd05dfddb4ab23126b8db", + "linkedWithoutMetadata": "a64c6cf9c6ba9368f5132c93a0196b3204a7963dbb4dd05dfddb4ab23126b8db" + }, + "inherit": [], + "libraries": [], + "methods": [], + "linkReferences": [], + "errors": [], + "layout": { + "storage": [], + "types": {}, + "layoutVersion": "1.2", + "flat": false, + "namespaces": {} + }, + "solcVersion": "0.8.20" + }, + "@openzeppelin/contracts/utils/Strings.sol:Strings": { + "src": "@openzeppelin/contracts/utils/Strings.sol:12", + "version": { + "withMetadata": "1f077ab1d99a4eecbd37aee047bccfff460c6733303204c2caae630025da1b56", + "withoutMetadata": "a64c6cf9c6ba9368f5132c93a0196b3204a7963dbb4dd05dfddb4ab23126b8db", + "linkedWithoutMetadata": "a64c6cf9c6ba9368f5132c93a0196b3204a7963dbb4dd05dfddb4ab23126b8db" + }, + "inherit": [], + "libraries": [ + "@openzeppelin/contracts/utils/math/Math.sol:Math", + "@openzeppelin/contracts/utils/math/SignedMath.sol:SignedMath" + ], + "methods": [], + "linkReferences": [], + "errors": [], + "layout": { + "storage": [], + "types": {}, + "layoutVersion": "1.2", + "flat": false, + "namespaces": {} + }, + "solcVersion": "0.8.20" + }, + "@openzeppelin/contracts/utils/cryptography/ECDSA.sol:ECDSA": { + "src": "@openzeppelin/contracts/utils/cryptography/ECDSA.sol:12", + "version": { + "withMetadata": "331614b026900e8360111160b80a2ee56153ca66bb73d4aaf42d987a68a589f5", + "withoutMetadata": "a64c6cf9c6ba9368f5132c93a0196b3204a7963dbb4dd05dfddb4ab23126b8db", + "linkedWithoutMetadata": "a64c6cf9c6ba9368f5132c93a0196b3204a7963dbb4dd05dfddb4ab23126b8db" + }, + "inherit": [], + "libraries": [], + "methods": [], + "linkReferences": [], + "errors": [], + "layout": { + "storage": [], + "types": {}, + "layoutVersion": "1.2", + "flat": false, + "namespaces": {} + }, + "solcVersion": "0.8.20" + }, + "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol:MessageHashUtils": { + "src": "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol:15", + "version": { + "withMetadata": "47db2b51fbc9919a71b07ceb1b01998df2a411f6e7e9090a303eca3b7fbe9697", + "withoutMetadata": "a64c6cf9c6ba9368f5132c93a0196b3204a7963dbb4dd05dfddb4ab23126b8db", + "linkedWithoutMetadata": "a64c6cf9c6ba9368f5132c93a0196b3204a7963dbb4dd05dfddb4ab23126b8db" + }, + "inherit": [], + "libraries": [ + "@openzeppelin/contracts/utils/Strings.sol:Strings" + ], + "methods": [], + "linkReferences": [], + "errors": [], + "layout": { + "storage": [], + "types": {}, + "layoutVersion": "1.2", + "flat": false, + "namespaces": {} + }, + "solcVersion": "0.8.20" + }, + "@openzeppelin/contracts/utils/introspection/IERC165.sol:IERC165": { + "src": "@openzeppelin/contracts/utils/introspection/IERC165.sol:15", + "inherit": [], + "libraries": [], + "methods": [ + "supportsInterface(bytes4)" + ], + "linkReferences": [], + "errors": [], + "layout": { + "storage": [], + "types": {}, + "layoutVersion": "1.2", + "flat": false, + "namespaces": {} + }, + "solcVersion": "0.8.20" + }, + "@openzeppelin/contracts/utils/math/Math.sol:Math": { + "src": "@openzeppelin/contracts/utils/math/Math.sol:9", + "version": { + "withMetadata": "5fc8cf4b465bec2619d552a3c06f7fbe2ab2174de540f304fb55b0e888f55edd", + "withoutMetadata": "a64c6cf9c6ba9368f5132c93a0196b3204a7963dbb4dd05dfddb4ab23126b8db", + "linkedWithoutMetadata": "a64c6cf9c6ba9368f5132c93a0196b3204a7963dbb4dd05dfddb4ab23126b8db" + }, + "inherit": [], + "libraries": [], + "methods": [], + "linkReferences": [], + "errors": [], + "layout": { + "storage": [], + "types": {}, + "layoutVersion": "1.2", + "flat": false, + "namespaces": {} + }, + "solcVersion": "0.8.20" + }, + "@openzeppelin/contracts/utils/math/SignedMath.sol:SignedMath": { + "src": "@openzeppelin/contracts/utils/math/SignedMath.sol:9", + "version": { + "withMetadata": "12aecc6841d3169e665dbcd7653533b31894b634fefe854d71d51d046514f633", + "withoutMetadata": "a64c6cf9c6ba9368f5132c93a0196b3204a7963dbb4dd05dfddb4ab23126b8db", + "linkedWithoutMetadata": "a64c6cf9c6ba9368f5132c93a0196b3204a7963dbb4dd05dfddb4ab23126b8db" + }, + "inherit": [], + "libraries": [], + "methods": [], + "linkReferences": [], + "errors": [], + "layout": { + "storage": [], + "types": {}, + "layoutVersion": "1.2", + "flat": false, + "namespaces": {} + }, + "solcVersion": "0.8.20" + }, + "contracts/message/B2MessageBridge.sol:B2MessageBridge": { + "src": "contracts/message/B2MessageBridge.sol:19", + "version": { + "withMetadata": "adb949d155017ead7598ef3aef0d94fffc73897537d13044b5e15ef8658c2206", + "withoutMetadata": "226e38b1100d05b5fd6a3a136524b9ada5f9cb29e7694ba6267a0d254ea05f7b", + "linkedWithoutMetadata": "226e38b1100d05b5fd6a3a136524b9ada5f9cb29e7694ba6267a0d254ea05f7b" + }, + "inherit": [ + "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:AccessControlUpgradeable", + "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol:ERC165Upgradeable", + "@openzeppelin/contracts/utils/introspection/IERC165.sol:IERC165", + "@openzeppelin/contracts/access/IAccessControl.sol:IAccessControl", + "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:ContextUpgradeable", + "@openzeppelin/contracts-upgradeable/utils/cryptography/EIP712Upgradeable.sol:EIP712Upgradeable", + "@openzeppelin/contracts/interfaces/IERC5267.sol:IERC5267", + "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol:UUPSUpgradeable", + "@openzeppelin/contracts/interfaces/draft-IERC1822.sol:IERC1822Proxiable", + "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:Initializable", + "contracts/message/B2MessageBridge.sol:IB2MessageBridge" + ], + "libraries": [ + "@openzeppelin/contracts/utils/cryptography/ECDSA.sol:ECDSA" + ], + "methods": [ + "initialize()", + "setWeight(uint256)", + "send(uint256,uint256,address,address,bytes,bytes[])", + "call(uint256,address,bytes)", + "verify(uint256,uint256,address,uint256,address,bytes,bytes)", + "SendHash(uint256,uint256,address,uint256,address,bytes)" + ], + "linkReferences": [], + "errors": [], + "layout": { + "storage": [ + { + "label": "sequence", + "offset": 0, + "slot": "0", + "type": "t_uint256", + "contract": "B2MessageBridge", + "src": "contracts/message/B2MessageBridge.sol:26" + }, + { + "label": "weight", + "offset": 0, + "slot": "1", + "type": "t_uint256", + "contract": "B2MessageBridge", + "src": "contracts/message/B2MessageBridge.sol:27" + }, + { + "label": "sequences", + "offset": 0, + "slot": "2", + "type": "t_mapping(t_uint256,t_uint256)", + "contract": "B2MessageBridge", + "src": "contracts/message/B2MessageBridge.sol:28" + }, + { + "label": "ids", + "offset": 0, + "slot": "3", + "type": "t_mapping(t_uint256,t_mapping(t_uint256,t_bool))", + "contract": "B2MessageBridge", + "src": "contracts/message/B2MessageBridge.sol:29" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_bytes32,t_struct(RoleData)25_storage)": { + "label": "mapping(bytes32 => struct AccessControlUpgradeable.RoleData)", + "numberOfBytes": "32" + }, + "t_string_storage": { + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(AccessControlStorage)35_storage": { + "label": "struct AccessControlUpgradeable.AccessControlStorage", + "members": [ + { + "label": "_roles", + "type": "t_mapping(t_bytes32,t_struct(RoleData)25_storage)", + "offset": 0, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_struct(EIP712Storage)376_storage": { + "label": "struct EIP712Upgradeable.EIP712Storage", + "members": [ + { + "label": "_hashedName", + "type": "t_bytes32", + "offset": 0, + "slot": "0" + }, + { + "label": "_hashedVersion", + "type": "t_bytes32", + "offset": 0, + "slot": "1" + }, + { + "label": "_name", + "type": "t_string_storage", + "offset": 0, + "slot": "2" + }, + { + "label": "_version", + "type": "t_string_storage", + "offset": 0, + "slot": "3" + } + ], + "numberOfBytes": "128" + }, + "t_struct(InitializableStorage)174_storage": { + "label": "struct Initializable.InitializableStorage", + "members": [ + { + "label": "_initialized", + "type": "t_uint64", + "offset": 0, + "slot": "0" + }, + { + "label": "_initializing", + "type": "t_bool", + "offset": 8, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_struct(RoleData)25_storage": { + "label": "struct AccessControlUpgradeable.RoleData", + "members": [ + { + "label": "hasRole", + "type": "t_mapping(t_address,t_bool)", + "offset": 0, + "slot": "0" + }, + { + "label": "adminRole", + "type": "t_bytes32", + "offset": 0, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_uint64": { + "label": "uint64", + "numberOfBytes": "8" + }, + "t_mapping(t_uint256,t_bool)": { + "label": "mapping(uint256 => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_mapping(t_uint256,t_bool))": { + "label": "mapping(uint256 => mapping(uint256 => bool))", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_uint256)": { + "label": "mapping(uint256 => uint256)", + "numberOfBytes": "32" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + } + }, + "layoutVersion": "1.2", + "flat": true, + "namespaces": { + "erc7201:openzeppelin.storage.AccessControl": [ + { + "contract": "AccessControlUpgradeable", + "label": "_roles", + "type": "t_mapping(t_bytes32,t_struct(RoleData)25_storage)", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:61", + "offset": 0, + "slot": "0" + } + ], + "erc7201:openzeppelin.storage.EIP712": [ + { + "contract": "EIP712Upgradeable", + "label": "_hashedName", + "type": "t_bytes32", + "src": "@openzeppelin/contracts-upgradeable/utils/cryptography/EIP712Upgradeable.sol:39", + "offset": 0, + "slot": "0" + }, + { + "contract": "EIP712Upgradeable", + "label": "_hashedVersion", + "type": "t_bytes32", + "src": "@openzeppelin/contracts-upgradeable/utils/cryptography/EIP712Upgradeable.sol:41", + "offset": 0, + "slot": "1" + }, + { + "contract": "EIP712Upgradeable", + "label": "_name", + "type": "t_string_storage", + "src": "@openzeppelin/contracts-upgradeable/utils/cryptography/EIP712Upgradeable.sol:43", + "offset": 0, + "slot": "2" + }, + { + "contract": "EIP712Upgradeable", + "label": "_version", + "type": "t_string_storage", + "src": "@openzeppelin/contracts-upgradeable/utils/cryptography/EIP712Upgradeable.sol:44", + "offset": 0, + "slot": "3" + } + ], + "erc7201:openzeppelin.storage.Initializable": [ + { + "contract": "Initializable", + "label": "_initialized", + "type": "t_uint64", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:69", + "offset": 0, + "slot": "0" + }, + { + "contract": "Initializable", + "label": "_initializing", + "type": "t_bool", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:73", + "offset": 8, + "slot": "0" + } + ] + } + }, + "solcVersion": "0.8.20" + }, + "contracts/message/B2MessageBridge.sol:IB2MessageBridge": { + "src": "contracts/message/B2MessageBridge.sol:10", + "inherit": [], + "libraries": [], + "methods": [ + "call(uint256,address,bytes)", + "send(uint256,uint256,address,address,bytes,bytes[])" + ], + "linkReferences": [], + "errors": [], + "layout": { + "storage": [], + "types": {}, + "layoutVersion": "1.2", + "flat": false, + "namespaces": {} + }, + "solcVersion": "0.8.20" + }, + "contracts/message/B2MessageBridge.sol:IBusinessContract": { + "src": "contracts/message/B2MessageBridge.sol:15", + "inherit": [], + "libraries": [], + "methods": [ + "send(uint256,uint256,address,bytes)" + ], + "linkReferences": [], + "errors": [], + "layout": { + "storage": [], + "types": {}, + "layoutVersion": "1.2", + "flat": false, + "namespaces": {} + }, + "solcVersion": "0.8.20" + } + }, + { + "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:AccessControlUpgradeable": { + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:50", + "inherit": [ + "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol:ERC165Upgradeable", + "@openzeppelin/contracts/utils/introspection/IERC165.sol:IERC165", + "@openzeppelin/contracts/access/IAccessControl.sol:IAccessControl", + "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:ContextUpgradeable", + "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:Initializable" + ], + "libraries": [], + "methods": [ + "supportsInterface(bytes4)", + "hasRole(bytes32,address)", + "getRoleAdmin(bytes32)", + "grantRole(bytes32,address)", + "revokeRole(bytes32,address)", + "renounceRole(bytes32,address)" + ], + "linkReferences": [], + "errors": [], + "layout": { + "storage": [], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_bytes32,t_struct(RoleData)25_storage)": { + "label": "mapping(bytes32 => struct AccessControlUpgradeable.RoleData)", + "numberOfBytes": "32" + }, + "t_struct(AccessControlStorage)35_storage": { + "label": "struct AccessControlUpgradeable.AccessControlStorage", + "members": [ + { + "label": "_roles", + "type": "t_mapping(t_bytes32,t_struct(RoleData)25_storage)", + "offset": 0, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_struct(InitializableStorage)174_storage": { + "label": "struct Initializable.InitializableStorage", + "members": [ + { + "label": "_initialized", + "type": "t_uint64", + "offset": 0, + "slot": "0" + }, + { + "label": "_initializing", + "type": "t_bool", + "offset": 8, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_struct(RoleData)25_storage": { + "label": "struct AccessControlUpgradeable.RoleData", + "members": [ + { + "label": "hasRole", + "type": "t_mapping(t_address,t_bool)", + "offset": 0, + "slot": "0" + }, + { + "label": "adminRole", + "type": "t_bytes32", + "offset": 0, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_uint64": { + "label": "uint64", + "numberOfBytes": "8" + } + }, + "layoutVersion": "1.2", + "flat": false, + "namespaces": { + "erc7201:openzeppelin.storage.AccessControl": [ + { + "contract": "AccessControlUpgradeable", + "label": "_roles", + "type": "t_mapping(t_bytes32,t_struct(RoleData)25_storage)", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:61", + "offset": 0, + "slot": "0" + } + ], + "erc7201:openzeppelin.storage.Initializable": [ + { + "contract": "Initializable", + "label": "_initialized", + "type": "t_uint64", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:69", + "offset": 0, + "slot": "0" + }, + { + "contract": "Initializable", + "label": "_initializing", + "type": "t_bool", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:73", + "offset": 8, + "slot": "0" + } + ] + } + }, + "solcVersion": "0.8.20" + }, + "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:Initializable": { + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:56", + "inherit": [], + "libraries": [], + "methods": [], + "linkReferences": [], + "errors": [], + "layout": { + "storage": [], + "types": { + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_struct(InitializableStorage)174_storage": { + "label": "struct Initializable.InitializableStorage", + "members": [ + { + "label": "_initialized", + "type": "t_uint64", + "offset": 0, + "slot": "0" + }, + { + "label": "_initializing", + "type": "t_bool", + "offset": 8, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_uint64": { + "label": "uint64", + "numberOfBytes": "8" + } + }, + "layoutVersion": "1.2", + "flat": false, + "namespaces": { + "erc7201:openzeppelin.storage.Initializable": [ + { + "contract": "Initializable", + "label": "_initialized", + "type": "t_uint64", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:69", + "offset": 0, + "slot": "0" + }, + { + "contract": "Initializable", + "label": "_initializing", + "type": "t_bool", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:73", + "offset": 8, + "slot": "0" + } + ] + } + }, + "solcVersion": "0.8.20" + }, + "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol:UUPSUpgradeable": { + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol:20", + "inherit": [ + "@openzeppelin/contracts/interfaces/draft-IERC1822.sol:IERC1822Proxiable", + "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:Initializable" + ], + "libraries": [ + "@openzeppelin/contracts/proxy/ERC1967/ERC1967Utils.sol:ERC1967Utils" + ], + "methods": [ + "proxiableUUID()", + "upgradeToAndCall(address,bytes)" + ], + "linkReferences": [], + "errors": [ + { + "kind": "delegatecall", + "src": "@openzeppelin/contracts/utils/Address.sol:105" + } + ], + "layout": { + "storage": [], + "types": { + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_struct(InitializableStorage)174_storage": { + "label": "struct Initializable.InitializableStorage", + "members": [ + { + "label": "_initialized", + "type": "t_uint64", + "offset": 0, + "slot": "0" + }, + { + "label": "_initializing", + "type": "t_bool", + "offset": 8, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_uint64": { + "label": "uint64", + "numberOfBytes": "8" + } + }, + "layoutVersion": "1.2", + "flat": false, + "namespaces": { + "erc7201:openzeppelin.storage.Initializable": [ + { + "contract": "Initializable", + "label": "_initialized", + "type": "t_uint64", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:69", + "offset": 0, + "slot": "0" + }, + { + "contract": "Initializable", + "label": "_initializing", + "type": "t_bool", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:73", + "offset": 8, + "slot": "0" + } + ] + } + }, + "solcVersion": "0.8.20" + }, + "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:ContextUpgradeable": { + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:17", + "inherit": [ + "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:Initializable" + ], + "libraries": [], + "methods": [], + "linkReferences": [], + "errors": [], + "layout": { + "storage": [], + "types": { + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_struct(InitializableStorage)174_storage": { + "label": "struct Initializable.InitializableStorage", + "members": [ + { + "label": "_initialized", + "type": "t_uint64", + "offset": 0, + "slot": "0" + }, + { + "label": "_initializing", + "type": "t_bool", + "offset": 8, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_uint64": { + "label": "uint64", + "numberOfBytes": "8" + } + }, + "layoutVersion": "1.2", + "flat": false, + "namespaces": { + "erc7201:openzeppelin.storage.Initializable": [ + { + "contract": "Initializable", + "label": "_initialized", + "type": "t_uint64", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:69", + "offset": 0, + "slot": "0" + }, + { + "contract": "Initializable", + "label": "_initializing", + "type": "t_bool", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:73", + "offset": 8, + "slot": "0" + } + ] + } + }, + "solcVersion": "0.8.20" + }, + "@openzeppelin/contracts-upgradeable/utils/cryptography/EIP712Upgradeable.sol:EIP712Upgradeable": { + "src": "@openzeppelin/contracts-upgradeable/utils/cryptography/EIP712Upgradeable.sol:32", + "inherit": [ + "@openzeppelin/contracts/interfaces/IERC5267.sol:IERC5267", + "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:Initializable" + ], + "libraries": [ + "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol:MessageHashUtils" + ], + "methods": [ + "eip712Domain()" + ], + "linkReferences": [], + "errors": [], + "layout": { + "storage": [], + "types": { + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_string_storage": { + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(EIP712Storage)376_storage": { + "label": "struct EIP712Upgradeable.EIP712Storage", + "members": [ + { + "label": "_hashedName", + "type": "t_bytes32", + "offset": 0, + "slot": "0" + }, + { + "label": "_hashedVersion", + "type": "t_bytes32", + "offset": 0, + "slot": "1" + }, + { + "label": "_name", + "type": "t_string_storage", + "offset": 0, + "slot": "2" + }, + { + "label": "_version", + "type": "t_string_storage", + "offset": 0, + "slot": "3" + } + ], + "numberOfBytes": "128" + }, + "t_struct(InitializableStorage)174_storage": { + "label": "struct Initializable.InitializableStorage", + "members": [ + { + "label": "_initialized", + "type": "t_uint64", + "offset": 0, + "slot": "0" + }, + { + "label": "_initializing", + "type": "t_bool", + "offset": 8, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_uint64": { + "label": "uint64", + "numberOfBytes": "8" + } + }, + "layoutVersion": "1.2", + "flat": false, + "namespaces": { + "erc7201:openzeppelin.storage.EIP712": [ + { + "contract": "EIP712Upgradeable", + "label": "_hashedName", + "type": "t_bytes32", + "src": "@openzeppelin/contracts-upgradeable/utils/cryptography/EIP712Upgradeable.sol:39", + "offset": 0, + "slot": "0" + }, + { + "contract": "EIP712Upgradeable", + "label": "_hashedVersion", + "type": "t_bytes32", + "src": "@openzeppelin/contracts-upgradeable/utils/cryptography/EIP712Upgradeable.sol:41", + "offset": 0, + "slot": "1" + }, + { + "contract": "EIP712Upgradeable", + "label": "_name", + "type": "t_string_storage", + "src": "@openzeppelin/contracts-upgradeable/utils/cryptography/EIP712Upgradeable.sol:43", + "offset": 0, + "slot": "2" + }, + { + "contract": "EIP712Upgradeable", + "label": "_version", + "type": "t_string_storage", + "src": "@openzeppelin/contracts-upgradeable/utils/cryptography/EIP712Upgradeable.sol:44", + "offset": 0, + "slot": "3" + } + ], + "erc7201:openzeppelin.storage.Initializable": [ + { + "contract": "Initializable", + "label": "_initialized", + "type": "t_uint64", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:69", + "offset": 0, + "slot": "0" + }, + { + "contract": "Initializable", + "label": "_initializing", + "type": "t_bool", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:73", + "offset": 8, + "slot": "0" + } + ] + } + }, + "solcVersion": "0.8.20" + }, + "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol:ERC165Upgradeable": { + "src": "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol:21", + "inherit": [ + "@openzeppelin/contracts/utils/introspection/IERC165.sol:IERC165", + "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:Initializable" + ], + "libraries": [], + "methods": [ + "supportsInterface(bytes4)" + ], + "linkReferences": [], + "errors": [], + "layout": { + "storage": [], + "types": { + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_struct(InitializableStorage)174_storage": { + "label": "struct Initializable.InitializableStorage", + "members": [ + { + "label": "_initialized", + "type": "t_uint64", + "offset": 0, + "slot": "0" + }, + { + "label": "_initializing", + "type": "t_bool", + "offset": 8, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_uint64": { + "label": "uint64", + "numberOfBytes": "8" + } + }, + "layoutVersion": "1.2", + "flat": false, + "namespaces": { + "erc7201:openzeppelin.storage.Initializable": [ + { + "contract": "Initializable", + "label": "_initialized", + "type": "t_uint64", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:69", + "offset": 0, + "slot": "0" + }, + { + "contract": "Initializable", + "label": "_initializing", + "type": "t_bool", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:73", + "offset": 8, + "slot": "0" + } + ] + } + }, + "solcVersion": "0.8.20" + }, + "@openzeppelin/contracts/access/IAccessControl.sol:IAccessControl": { + "src": "@openzeppelin/contracts/access/IAccessControl.sol:9", + "inherit": [], + "libraries": [], + "methods": [ + "hasRole(bytes32,address)", + "getRoleAdmin(bytes32)", + "grantRole(bytes32,address)", + "revokeRole(bytes32,address)", + "renounceRole(bytes32,address)" + ], + "linkReferences": [], + "errors": [], + "layout": { + "storage": [], + "types": {}, + "layoutVersion": "1.2", + "flat": false, + "namespaces": {} + }, + "solcVersion": "0.8.20" + }, + "@openzeppelin/contracts/interfaces/IERC5267.sol:IERC5267": { + "src": "@openzeppelin/contracts/interfaces/IERC5267.sol:6", + "inherit": [], + "libraries": [], + "methods": [ + "eip712Domain()" + ], + "linkReferences": [], + "errors": [], + "layout": { + "storage": [], + "types": {}, + "layoutVersion": "1.2", + "flat": false, + "namespaces": {} + }, + "solcVersion": "0.8.20" + }, + "@openzeppelin/contracts/interfaces/draft-IERC1822.sol:IERC1822Proxiable": { + "src": "@openzeppelin/contracts/interfaces/draft-IERC1822.sol:10", + "inherit": [], + "libraries": [], + "methods": [ + "proxiableUUID()" + ], + "linkReferences": [], + "errors": [], + "layout": { + "storage": [], + "types": {}, + "layoutVersion": "1.2", + "flat": false, + "namespaces": {} + }, + "solcVersion": "0.8.20" + }, + "@openzeppelin/contracts/proxy/ERC1967/ERC1967Utils.sol:ERC1967Utils": { + "src": "@openzeppelin/contracts/proxy/ERC1967/ERC1967Utils.sol:14", + "version": { + "withMetadata": "da0ca15378c152c2e5da0d6bf0e27590374c4a5c250bc2a82167eedfe4c704bd", + "withoutMetadata": "a64c6cf9c6ba9368f5132c93a0196b3204a7963dbb4dd05dfddb4ab23126b8db", + "linkedWithoutMetadata": "a64c6cf9c6ba9368f5132c93a0196b3204a7963dbb4dd05dfddb4ab23126b8db" + }, + "inherit": [], + "libraries": [ + "@openzeppelin/contracts/utils/StorageSlot.sol:StorageSlot", + "@openzeppelin/contracts/utils/Address.sol:Address" + ], + "methods": [], + "linkReferences": [], + "errors": [ + { + "kind": "delegatecall", + "src": "@openzeppelin/contracts/utils/Address.sol:105" + }, + { + "kind": "delegatecall", + "src": "@openzeppelin/contracts/utils/Address.sol:105" + } + ], + "layout": { + "storage": [], + "types": {}, + "layoutVersion": "1.2", + "flat": false, + "namespaces": {} + }, + "solcVersion": "0.8.20" + }, + "@openzeppelin/contracts/proxy/beacon/IBeacon.sol:IBeacon": { + "src": "@openzeppelin/contracts/proxy/beacon/IBeacon.sol:9", + "inherit": [], + "libraries": [], + "methods": [ + "implementation()" + ], + "linkReferences": [], + "errors": [], + "layout": { + "storage": [], + "types": {}, + "layoutVersion": "1.2", + "flat": false, + "namespaces": {} + }, + "solcVersion": "0.8.20" + }, + "@openzeppelin/contracts/utils/Address.sol:Address": { + "src": "@openzeppelin/contracts/utils/Address.sol:9", + "version": { + "withMetadata": "87fe4495dfc9354a67a3f830c1c6ae271f7d13aa51b702039300545894a3ef6b", + "withoutMetadata": "a64c6cf9c6ba9368f5132c93a0196b3204a7963dbb4dd05dfddb4ab23126b8db", + "linkedWithoutMetadata": "a64c6cf9c6ba9368f5132c93a0196b3204a7963dbb4dd05dfddb4ab23126b8db" + }, + "inherit": [], + "libraries": [], + "methods": [], + "linkReferences": [], + "errors": [ + { + "kind": "delegatecall", + "src": "@openzeppelin/contracts/utils/Address.sol:105" + } + ], + "layout": { + "storage": [], + "types": {}, + "layoutVersion": "1.2", + "flat": false, + "namespaces": {} + }, + "solcVersion": "0.8.20" + }, + "@openzeppelin/contracts/utils/StorageSlot.sol:StorageSlot": { + "src": "@openzeppelin/contracts/utils/StorageSlot.sol:31", + "version": { + "withMetadata": "7265f6e3db839ed1e12b293fcc2217f69e669b109fb6d18bebad36e761707f76", + "withoutMetadata": "a64c6cf9c6ba9368f5132c93a0196b3204a7963dbb4dd05dfddb4ab23126b8db", + "linkedWithoutMetadata": "a64c6cf9c6ba9368f5132c93a0196b3204a7963dbb4dd05dfddb4ab23126b8db" + }, + "inherit": [], + "libraries": [], + "methods": [], + "linkReferences": [], + "errors": [], + "layout": { + "storage": [], + "types": {}, + "layoutVersion": "1.2", + "flat": false, + "namespaces": {} + }, + "solcVersion": "0.8.20" + }, + "@openzeppelin/contracts/utils/Strings.sol:Strings": { + "src": "@openzeppelin/contracts/utils/Strings.sol:12", + "version": { + "withMetadata": "1f077ab1d99a4eecbd37aee047bccfff460c6733303204c2caae630025da1b56", + "withoutMetadata": "a64c6cf9c6ba9368f5132c93a0196b3204a7963dbb4dd05dfddb4ab23126b8db", + "linkedWithoutMetadata": "a64c6cf9c6ba9368f5132c93a0196b3204a7963dbb4dd05dfddb4ab23126b8db" + }, + "inherit": [], + "libraries": [ + "@openzeppelin/contracts/utils/math/Math.sol:Math", + "@openzeppelin/contracts/utils/math/SignedMath.sol:SignedMath" + ], + "methods": [], + "linkReferences": [], + "errors": [], + "layout": { + "storage": [], + "types": {}, + "layoutVersion": "1.2", + "flat": false, + "namespaces": {} + }, + "solcVersion": "0.8.20" + }, + "@openzeppelin/contracts/utils/cryptography/ECDSA.sol:ECDSA": { + "src": "@openzeppelin/contracts/utils/cryptography/ECDSA.sol:12", + "version": { + "withMetadata": "331614b026900e8360111160b80a2ee56153ca66bb73d4aaf42d987a68a589f5", + "withoutMetadata": "a64c6cf9c6ba9368f5132c93a0196b3204a7963dbb4dd05dfddb4ab23126b8db", + "linkedWithoutMetadata": "a64c6cf9c6ba9368f5132c93a0196b3204a7963dbb4dd05dfddb4ab23126b8db" + }, + "inherit": [], + "libraries": [], + "methods": [], + "linkReferences": [], + "errors": [], + "layout": { + "storage": [], + "types": {}, + "layoutVersion": "1.2", + "flat": false, + "namespaces": {} + }, + "solcVersion": "0.8.20" + }, + "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol:MessageHashUtils": { + "src": "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol:15", + "version": { + "withMetadata": "47db2b51fbc9919a71b07ceb1b01998df2a411f6e7e9090a303eca3b7fbe9697", + "withoutMetadata": "a64c6cf9c6ba9368f5132c93a0196b3204a7963dbb4dd05dfddb4ab23126b8db", + "linkedWithoutMetadata": "a64c6cf9c6ba9368f5132c93a0196b3204a7963dbb4dd05dfddb4ab23126b8db" + }, + "inherit": [], + "libraries": [ + "@openzeppelin/contracts/utils/Strings.sol:Strings" + ], + "methods": [], + "linkReferences": [], + "errors": [], + "layout": { + "storage": [], + "types": {}, + "layoutVersion": "1.2", + "flat": false, + "namespaces": {} + }, + "solcVersion": "0.8.20" + }, + "@openzeppelin/contracts/utils/introspection/IERC165.sol:IERC165": { + "src": "@openzeppelin/contracts/utils/introspection/IERC165.sol:15", + "inherit": [], + "libraries": [], + "methods": [ + "supportsInterface(bytes4)" + ], + "linkReferences": [], + "errors": [], + "layout": { + "storage": [], + "types": {}, + "layoutVersion": "1.2", + "flat": false, + "namespaces": {} + }, + "solcVersion": "0.8.20" + }, + "@openzeppelin/contracts/utils/math/Math.sol:Math": { + "src": "@openzeppelin/contracts/utils/math/Math.sol:9", + "version": { + "withMetadata": "5fc8cf4b465bec2619d552a3c06f7fbe2ab2174de540f304fb55b0e888f55edd", + "withoutMetadata": "a64c6cf9c6ba9368f5132c93a0196b3204a7963dbb4dd05dfddb4ab23126b8db", + "linkedWithoutMetadata": "a64c6cf9c6ba9368f5132c93a0196b3204a7963dbb4dd05dfddb4ab23126b8db" + }, + "inherit": [], + "libraries": [], + "methods": [], + "linkReferences": [], + "errors": [], + "layout": { + "storage": [], + "types": {}, + "layoutVersion": "1.2", + "flat": false, + "namespaces": {} + }, + "solcVersion": "0.8.20" + }, + "@openzeppelin/contracts/utils/math/SignedMath.sol:SignedMath": { + "src": "@openzeppelin/contracts/utils/math/SignedMath.sol:9", + "version": { + "withMetadata": "12aecc6841d3169e665dbcd7653533b31894b634fefe854d71d51d046514f633", + "withoutMetadata": "a64c6cf9c6ba9368f5132c93a0196b3204a7963dbb4dd05dfddb4ab23126b8db", + "linkedWithoutMetadata": "a64c6cf9c6ba9368f5132c93a0196b3204a7963dbb4dd05dfddb4ab23126b8db" + }, + "inherit": [], + "libraries": [], + "methods": [], + "linkReferences": [], + "errors": [], + "layout": { + "storage": [], + "types": {}, + "layoutVersion": "1.2", + "flat": false, + "namespaces": {} + }, + "solcVersion": "0.8.20" + }, + "contracts/message/B2MessageBridge.sol:B2MessageBridge": { + "src": "contracts/message/B2MessageBridge.sol:19", + "version": { + "withMetadata": "d9f685a7a64ff1f657265ac8da0def88431f1135f50612a551a143d0f5d4e0ca", + "withoutMetadata": "fd6a3fcc07a72ce9a4d4b587b112ac686c02d216f964ce041e551f07ea1c386d", + "linkedWithoutMetadata": "fd6a3fcc07a72ce9a4d4b587b112ac686c02d216f964ce041e551f07ea1c386d" + }, + "inherit": [ + "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:AccessControlUpgradeable", + "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol:ERC165Upgradeable", + "@openzeppelin/contracts/utils/introspection/IERC165.sol:IERC165", + "@openzeppelin/contracts/access/IAccessControl.sol:IAccessControl", + "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:ContextUpgradeable", + "@openzeppelin/contracts-upgradeable/utils/cryptography/EIP712Upgradeable.sol:EIP712Upgradeable", + "@openzeppelin/contracts/interfaces/IERC5267.sol:IERC5267", + "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol:UUPSUpgradeable", + "@openzeppelin/contracts/interfaces/draft-IERC1822.sol:IERC1822Proxiable", + "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:Initializable", + "contracts/message/B2MessageBridge.sol:IB2MessageBridge" + ], + "libraries": [ + "@openzeppelin/contracts/utils/cryptography/ECDSA.sol:ECDSA" + ], + "methods": [ + "initialize()", + "setWeight(uint256)", + "send(uint256,uint256,address,address,bytes,bytes[])", + "call(uint256,address,bytes)", + "verify(uint256,uint256,address,uint256,address,bytes,bytes)", + "SendHash(uint256,uint256,address,uint256,address,bytes)" + ], + "linkReferences": [], + "errors": [], + "layout": { + "storage": [ + { + "label": "sequence", + "offset": 0, + "slot": "0", + "type": "t_uint256", + "contract": "B2MessageBridge", + "src": "contracts/message/B2MessageBridge.sol:26" + }, + { + "label": "weight", + "offset": 0, + "slot": "1", + "type": "t_uint256", + "contract": "B2MessageBridge", + "src": "contracts/message/B2MessageBridge.sol:27" + }, + { + "label": "sequences", + "offset": 0, + "slot": "2", + "type": "t_mapping(t_uint256,t_uint256)", + "contract": "B2MessageBridge", + "src": "contracts/message/B2MessageBridge.sol:28" + }, + { + "label": "ids", + "offset": 0, + "slot": "3", + "type": "t_mapping(t_uint256,t_mapping(t_uint256,t_bool))", + "contract": "B2MessageBridge", + "src": "contracts/message/B2MessageBridge.sol:29" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_bytes32,t_struct(RoleData)25_storage)": { + "label": "mapping(bytes32 => struct AccessControlUpgradeable.RoleData)", + "numberOfBytes": "32" + }, + "t_string_storage": { + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(AccessControlStorage)35_storage": { + "label": "struct AccessControlUpgradeable.AccessControlStorage", + "members": [ + { + "label": "_roles", + "type": "t_mapping(t_bytes32,t_struct(RoleData)25_storage)", + "offset": 0, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_struct(EIP712Storage)376_storage": { + "label": "struct EIP712Upgradeable.EIP712Storage", + "members": [ + { + "label": "_hashedName", + "type": "t_bytes32", + "offset": 0, + "slot": "0" + }, + { + "label": "_hashedVersion", + "type": "t_bytes32", + "offset": 0, + "slot": "1" + }, + { + "label": "_name", + "type": "t_string_storage", + "offset": 0, + "slot": "2" + }, + { + "label": "_version", + "type": "t_string_storage", + "offset": 0, + "slot": "3" + } + ], + "numberOfBytes": "128" + }, + "t_struct(InitializableStorage)174_storage": { + "label": "struct Initializable.InitializableStorage", + "members": [ + { + "label": "_initialized", + "type": "t_uint64", + "offset": 0, + "slot": "0" + }, + { + "label": "_initializing", + "type": "t_bool", + "offset": 8, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_struct(RoleData)25_storage": { + "label": "struct AccessControlUpgradeable.RoleData", + "members": [ + { + "label": "hasRole", + "type": "t_mapping(t_address,t_bool)", + "offset": 0, + "slot": "0" + }, + { + "label": "adminRole", + "type": "t_bytes32", + "offset": 0, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_uint64": { + "label": "uint64", + "numberOfBytes": "8" + }, + "t_mapping(t_uint256,t_bool)": { + "label": "mapping(uint256 => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_mapping(t_uint256,t_bool))": { + "label": "mapping(uint256 => mapping(uint256 => bool))", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_uint256)": { + "label": "mapping(uint256 => uint256)", + "numberOfBytes": "32" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + } + }, + "layoutVersion": "1.2", + "flat": true, + "namespaces": { + "erc7201:openzeppelin.storage.AccessControl": [ + { + "contract": "AccessControlUpgradeable", + "label": "_roles", + "type": "t_mapping(t_bytes32,t_struct(RoleData)25_storage)", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:61", + "offset": 0, + "slot": "0" + } + ], + "erc7201:openzeppelin.storage.EIP712": [ + { + "contract": "EIP712Upgradeable", + "label": "_hashedName", + "type": "t_bytes32", + "src": "@openzeppelin/contracts-upgradeable/utils/cryptography/EIP712Upgradeable.sol:39", + "offset": 0, + "slot": "0" + }, + { + "contract": "EIP712Upgradeable", + "label": "_hashedVersion", + "type": "t_bytes32", + "src": "@openzeppelin/contracts-upgradeable/utils/cryptography/EIP712Upgradeable.sol:41", + "offset": 0, + "slot": "1" + }, + { + "contract": "EIP712Upgradeable", + "label": "_name", + "type": "t_string_storage", + "src": "@openzeppelin/contracts-upgradeable/utils/cryptography/EIP712Upgradeable.sol:43", + "offset": 0, + "slot": "2" + }, + { + "contract": "EIP712Upgradeable", + "label": "_version", + "type": "t_string_storage", + "src": "@openzeppelin/contracts-upgradeable/utils/cryptography/EIP712Upgradeable.sol:44", + "offset": 0, + "slot": "3" + } + ], + "erc7201:openzeppelin.storage.Initializable": [ + { + "contract": "Initializable", + "label": "_initialized", + "type": "t_uint64", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:69", + "offset": 0, + "slot": "0" + }, + { + "contract": "Initializable", + "label": "_initializing", + "type": "t_bool", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:73", + "offset": 8, + "slot": "0" + } + ] + } + }, + "solcVersion": "0.8.20" + }, + "contracts/message/B2MessageBridge.sol:IB2MessageBridge": { + "src": "contracts/message/B2MessageBridge.sol:10", + "inherit": [], + "libraries": [], + "methods": [ + "call(uint256,address,bytes)", + "send(uint256,uint256,address,address,bytes,bytes[])" + ], + "linkReferences": [], + "errors": [], + "layout": { + "storage": [], + "types": {}, + "layoutVersion": "1.2", + "flat": false, + "namespaces": {} + }, + "solcVersion": "0.8.20" + }, + "contracts/message/B2MessageBridge.sol:IBusinessContract": { + "src": "contracts/message/B2MessageBridge.sol:15", + "inherit": [], + "libraries": [], + "methods": [ + "send(uint256,uint256,address,bytes)" + ], + "linkReferences": [], + "errors": [], + "layout": { + "storage": [], + "types": {}, + "layoutVersion": "1.2", + "flat": false, + "namespaces": {} + }, + "solcVersion": "0.8.20" + } + }, + { + "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:AccessControlUpgradeable": { + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:50", + "inherit": [ + "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol:ERC165Upgradeable", + "@openzeppelin/contracts/utils/introspection/IERC165.sol:IERC165", + "@openzeppelin/contracts/access/IAccessControl.sol:IAccessControl", + "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:ContextUpgradeable", + "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:Initializable" + ], + "libraries": [], + "methods": [ + "supportsInterface(bytes4)", + "hasRole(bytes32,address)", + "getRoleAdmin(bytes32)", + "grantRole(bytes32,address)", + "revokeRole(bytes32,address)", + "renounceRole(bytes32,address)" + ], + "linkReferences": [], + "errors": [], + "layout": { + "storage": [], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_bytes32,t_struct(RoleData)25_storage)": { + "label": "mapping(bytes32 => struct AccessControlUpgradeable.RoleData)", + "numberOfBytes": "32" + }, + "t_struct(AccessControlStorage)35_storage": { + "label": "struct AccessControlUpgradeable.AccessControlStorage", + "members": [ + { + "label": "_roles", + "type": "t_mapping(t_bytes32,t_struct(RoleData)25_storage)", + "offset": 0, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_struct(InitializableStorage)174_storage": { + "label": "struct Initializable.InitializableStorage", + "members": [ + { + "label": "_initialized", + "type": "t_uint64", + "offset": 0, + "slot": "0" + }, + { + "label": "_initializing", + "type": "t_bool", + "offset": 8, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_struct(RoleData)25_storage": { + "label": "struct AccessControlUpgradeable.RoleData", + "members": [ + { + "label": "hasRole", + "type": "t_mapping(t_address,t_bool)", + "offset": 0, + "slot": "0" + }, + { + "label": "adminRole", + "type": "t_bytes32", + "offset": 0, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_uint64": { + "label": "uint64", + "numberOfBytes": "8" + } + }, + "layoutVersion": "1.2", + "flat": false, + "namespaces": { + "erc7201:openzeppelin.storage.AccessControl": [ + { + "contract": "AccessControlUpgradeable", + "label": "_roles", + "type": "t_mapping(t_bytes32,t_struct(RoleData)25_storage)", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:61", + "offset": 0, + "slot": "0" + } + ], + "erc7201:openzeppelin.storage.Initializable": [ + { + "contract": "Initializable", + "label": "_initialized", + "type": "t_uint64", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:69", + "offset": 0, + "slot": "0" + }, + { + "contract": "Initializable", + "label": "_initializing", + "type": "t_bool", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:73", + "offset": 8, + "slot": "0" + } + ] + } + }, + "solcVersion": "0.8.20" + }, + "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:Initializable": { + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:56", + "inherit": [], + "libraries": [], + "methods": [], + "linkReferences": [], + "errors": [], + "layout": { + "storage": [], + "types": { + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_struct(InitializableStorage)174_storage": { + "label": "struct Initializable.InitializableStorage", + "members": [ + { + "label": "_initialized", + "type": "t_uint64", + "offset": 0, + "slot": "0" + }, + { + "label": "_initializing", + "type": "t_bool", + "offset": 8, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_uint64": { + "label": "uint64", + "numberOfBytes": "8" + } + }, + "layoutVersion": "1.2", + "flat": false, + "namespaces": { + "erc7201:openzeppelin.storage.Initializable": [ + { + "contract": "Initializable", + "label": "_initialized", + "type": "t_uint64", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:69", + "offset": 0, + "slot": "0" + }, + { + "contract": "Initializable", + "label": "_initializing", + "type": "t_bool", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:73", + "offset": 8, + "slot": "0" + } + ] + } + }, + "solcVersion": "0.8.20" + }, + "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol:UUPSUpgradeable": { + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol:20", + "inherit": [ + "@openzeppelin/contracts/interfaces/draft-IERC1822.sol:IERC1822Proxiable", + "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:Initializable" + ], + "libraries": [ + "@openzeppelin/contracts/proxy/ERC1967/ERC1967Utils.sol:ERC1967Utils" + ], + "methods": [ + "proxiableUUID()", + "upgradeToAndCall(address,bytes)" + ], + "linkReferences": [], + "errors": [ + { + "kind": "delegatecall", + "src": "@openzeppelin/contracts/utils/Address.sol:105" + } + ], + "layout": { + "storage": [], + "types": { + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_struct(InitializableStorage)174_storage": { + "label": "struct Initializable.InitializableStorage", + "members": [ + { + "label": "_initialized", + "type": "t_uint64", + "offset": 0, + "slot": "0" + }, + { + "label": "_initializing", + "type": "t_bool", + "offset": 8, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_uint64": { + "label": "uint64", + "numberOfBytes": "8" + } + }, + "layoutVersion": "1.2", + "flat": false, + "namespaces": { + "erc7201:openzeppelin.storage.Initializable": [ + { + "contract": "Initializable", + "label": "_initialized", + "type": "t_uint64", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:69", + "offset": 0, + "slot": "0" + }, + { + "contract": "Initializable", + "label": "_initializing", + "type": "t_bool", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:73", + "offset": 8, + "slot": "0" + } + ] + } + }, + "solcVersion": "0.8.20" + }, + "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:ContextUpgradeable": { + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:17", + "inherit": [ + "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:Initializable" + ], + "libraries": [], + "methods": [], + "linkReferences": [], + "errors": [], + "layout": { + "storage": [], + "types": { + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_struct(InitializableStorage)174_storage": { + "label": "struct Initializable.InitializableStorage", + "members": [ + { + "label": "_initialized", + "type": "t_uint64", + "offset": 0, + "slot": "0" + }, + { + "label": "_initializing", + "type": "t_bool", + "offset": 8, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_uint64": { + "label": "uint64", + "numberOfBytes": "8" + } + }, + "layoutVersion": "1.2", + "flat": false, + "namespaces": { + "erc7201:openzeppelin.storage.Initializable": [ + { + "contract": "Initializable", + "label": "_initialized", + "type": "t_uint64", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:69", + "offset": 0, + "slot": "0" + }, + { + "contract": "Initializable", + "label": "_initializing", + "type": "t_bool", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:73", + "offset": 8, + "slot": "0" + } + ] + } + }, + "solcVersion": "0.8.20" + }, + "@openzeppelin/contracts-upgradeable/utils/cryptography/EIP712Upgradeable.sol:EIP712Upgradeable": { + "src": "@openzeppelin/contracts-upgradeable/utils/cryptography/EIP712Upgradeable.sol:32", + "inherit": [ + "@openzeppelin/contracts/interfaces/IERC5267.sol:IERC5267", + "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:Initializable" + ], + "libraries": [ + "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol:MessageHashUtils" + ], + "methods": [ + "eip712Domain()" + ], + "linkReferences": [], + "errors": [], + "layout": { + "storage": [], + "types": { + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_string_storage": { + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(EIP712Storage)376_storage": { + "label": "struct EIP712Upgradeable.EIP712Storage", + "members": [ + { + "label": "_hashedName", + "type": "t_bytes32", + "offset": 0, + "slot": "0" + }, + { + "label": "_hashedVersion", + "type": "t_bytes32", + "offset": 0, + "slot": "1" + }, + { + "label": "_name", + "type": "t_string_storage", + "offset": 0, + "slot": "2" + }, + { + "label": "_version", + "type": "t_string_storage", + "offset": 0, + "slot": "3" + } + ], + "numberOfBytes": "128" + }, + "t_struct(InitializableStorage)174_storage": { + "label": "struct Initializable.InitializableStorage", + "members": [ + { + "label": "_initialized", + "type": "t_uint64", + "offset": 0, + "slot": "0" + }, + { + "label": "_initializing", + "type": "t_bool", + "offset": 8, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_uint64": { + "label": "uint64", + "numberOfBytes": "8" + } + }, + "layoutVersion": "1.2", + "flat": false, + "namespaces": { + "erc7201:openzeppelin.storage.EIP712": [ + { + "contract": "EIP712Upgradeable", + "label": "_hashedName", + "type": "t_bytes32", + "src": "@openzeppelin/contracts-upgradeable/utils/cryptography/EIP712Upgradeable.sol:39", + "offset": 0, + "slot": "0" + }, + { + "contract": "EIP712Upgradeable", + "label": "_hashedVersion", + "type": "t_bytes32", + "src": "@openzeppelin/contracts-upgradeable/utils/cryptography/EIP712Upgradeable.sol:41", + "offset": 0, + "slot": "1" + }, + { + "contract": "EIP712Upgradeable", + "label": "_name", + "type": "t_string_storage", + "src": "@openzeppelin/contracts-upgradeable/utils/cryptography/EIP712Upgradeable.sol:43", + "offset": 0, + "slot": "2" + }, + { + "contract": "EIP712Upgradeable", + "label": "_version", + "type": "t_string_storage", + "src": "@openzeppelin/contracts-upgradeable/utils/cryptography/EIP712Upgradeable.sol:44", + "offset": 0, + "slot": "3" + } + ], + "erc7201:openzeppelin.storage.Initializable": [ + { + "contract": "Initializable", + "label": "_initialized", + "type": "t_uint64", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:69", + "offset": 0, + "slot": "0" + }, + { + "contract": "Initializable", + "label": "_initializing", + "type": "t_bool", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:73", + "offset": 8, + "slot": "0" + } + ] + } + }, + "solcVersion": "0.8.20" + }, + "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol:ERC165Upgradeable": { + "src": "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol:21", + "inherit": [ + "@openzeppelin/contracts/utils/introspection/IERC165.sol:IERC165", + "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:Initializable" + ], + "libraries": [], + "methods": [ + "supportsInterface(bytes4)" + ], + "linkReferences": [], + "errors": [], + "layout": { + "storage": [], + "types": { + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_struct(InitializableStorage)174_storage": { + "label": "struct Initializable.InitializableStorage", + "members": [ + { + "label": "_initialized", + "type": "t_uint64", + "offset": 0, + "slot": "0" + }, + { + "label": "_initializing", + "type": "t_bool", + "offset": 8, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_uint64": { + "label": "uint64", + "numberOfBytes": "8" + } + }, + "layoutVersion": "1.2", + "flat": false, + "namespaces": { + "erc7201:openzeppelin.storage.Initializable": [ + { + "contract": "Initializable", + "label": "_initialized", + "type": "t_uint64", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:69", + "offset": 0, + "slot": "0" + }, + { + "contract": "Initializable", + "label": "_initializing", + "type": "t_bool", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:73", + "offset": 8, + "slot": "0" + } + ] + } + }, + "solcVersion": "0.8.20" + }, + "@openzeppelin/contracts/access/IAccessControl.sol:IAccessControl": { + "src": "@openzeppelin/contracts/access/IAccessControl.sol:9", + "inherit": [], + "libraries": [], + "methods": [ + "hasRole(bytes32,address)", + "getRoleAdmin(bytes32)", + "grantRole(bytes32,address)", + "revokeRole(bytes32,address)", + "renounceRole(bytes32,address)" + ], + "linkReferences": [], + "errors": [], + "layout": { + "storage": [], + "types": {}, + "layoutVersion": "1.2", + "flat": false, + "namespaces": {} + }, + "solcVersion": "0.8.20" + }, + "@openzeppelin/contracts/interfaces/IERC5267.sol:IERC5267": { + "src": "@openzeppelin/contracts/interfaces/IERC5267.sol:6", + "inherit": [], + "libraries": [], + "methods": [ + "eip712Domain()" + ], + "linkReferences": [], + "errors": [], + "layout": { + "storage": [], + "types": {}, + "layoutVersion": "1.2", + "flat": false, + "namespaces": {} + }, + "solcVersion": "0.8.20" + }, + "@openzeppelin/contracts/interfaces/draft-IERC1822.sol:IERC1822Proxiable": { + "src": "@openzeppelin/contracts/interfaces/draft-IERC1822.sol:10", + "inherit": [], + "libraries": [], + "methods": [ + "proxiableUUID()" + ], + "linkReferences": [], + "errors": [], + "layout": { + "storage": [], + "types": {}, + "layoutVersion": "1.2", + "flat": false, + "namespaces": {} + }, + "solcVersion": "0.8.20" + }, + "@openzeppelin/contracts/proxy/ERC1967/ERC1967Utils.sol:ERC1967Utils": { + "src": "@openzeppelin/contracts/proxy/ERC1967/ERC1967Utils.sol:14", + "version": { + "withMetadata": "da0ca15378c152c2e5da0d6bf0e27590374c4a5c250bc2a82167eedfe4c704bd", + "withoutMetadata": "a64c6cf9c6ba9368f5132c93a0196b3204a7963dbb4dd05dfddb4ab23126b8db", + "linkedWithoutMetadata": "a64c6cf9c6ba9368f5132c93a0196b3204a7963dbb4dd05dfddb4ab23126b8db" + }, + "inherit": [], + "libraries": [ + "@openzeppelin/contracts/utils/StorageSlot.sol:StorageSlot", + "@openzeppelin/contracts/utils/Address.sol:Address" + ], + "methods": [], + "linkReferences": [], + "errors": [ + { + "kind": "delegatecall", + "src": "@openzeppelin/contracts/utils/Address.sol:105" + }, + { + "kind": "delegatecall", + "src": "@openzeppelin/contracts/utils/Address.sol:105" + } + ], + "layout": { + "storage": [], + "types": {}, + "layoutVersion": "1.2", + "flat": false, + "namespaces": {} + }, + "solcVersion": "0.8.20" + }, + "@openzeppelin/contracts/proxy/beacon/IBeacon.sol:IBeacon": { + "src": "@openzeppelin/contracts/proxy/beacon/IBeacon.sol:9", + "inherit": [], + "libraries": [], + "methods": [ + "implementation()" + ], + "linkReferences": [], + "errors": [], + "layout": { + "storage": [], + "types": {}, + "layoutVersion": "1.2", + "flat": false, + "namespaces": {} + }, + "solcVersion": "0.8.20" + }, + "@openzeppelin/contracts/utils/Address.sol:Address": { + "src": "@openzeppelin/contracts/utils/Address.sol:9", + "version": { + "withMetadata": "87fe4495dfc9354a67a3f830c1c6ae271f7d13aa51b702039300545894a3ef6b", + "withoutMetadata": "a64c6cf9c6ba9368f5132c93a0196b3204a7963dbb4dd05dfddb4ab23126b8db", + "linkedWithoutMetadata": "a64c6cf9c6ba9368f5132c93a0196b3204a7963dbb4dd05dfddb4ab23126b8db" + }, + "inherit": [], + "libraries": [], + "methods": [], + "linkReferences": [], + "errors": [ + { + "kind": "delegatecall", + "src": "@openzeppelin/contracts/utils/Address.sol:105" + } + ], + "layout": { + "storage": [], + "types": {}, + "layoutVersion": "1.2", + "flat": false, + "namespaces": {} + }, + "solcVersion": "0.8.20" + }, + "@openzeppelin/contracts/utils/StorageSlot.sol:StorageSlot": { + "src": "@openzeppelin/contracts/utils/StorageSlot.sol:31", + "version": { + "withMetadata": "7265f6e3db839ed1e12b293fcc2217f69e669b109fb6d18bebad36e761707f76", + "withoutMetadata": "a64c6cf9c6ba9368f5132c93a0196b3204a7963dbb4dd05dfddb4ab23126b8db", + "linkedWithoutMetadata": "a64c6cf9c6ba9368f5132c93a0196b3204a7963dbb4dd05dfddb4ab23126b8db" + }, + "inherit": [], + "libraries": [], + "methods": [], + "linkReferences": [], + "errors": [], + "layout": { + "storage": [], + "types": {}, + "layoutVersion": "1.2", + "flat": false, + "namespaces": {} + }, + "solcVersion": "0.8.20" + }, + "@openzeppelin/contracts/utils/Strings.sol:Strings": { + "src": "@openzeppelin/contracts/utils/Strings.sol:12", + "version": { + "withMetadata": "1f077ab1d99a4eecbd37aee047bccfff460c6733303204c2caae630025da1b56", + "withoutMetadata": "a64c6cf9c6ba9368f5132c93a0196b3204a7963dbb4dd05dfddb4ab23126b8db", + "linkedWithoutMetadata": "a64c6cf9c6ba9368f5132c93a0196b3204a7963dbb4dd05dfddb4ab23126b8db" + }, + "inherit": [], + "libraries": [ + "@openzeppelin/contracts/utils/math/Math.sol:Math", + "@openzeppelin/contracts/utils/math/SignedMath.sol:SignedMath" + ], + "methods": [], + "linkReferences": [], + "errors": [], + "layout": { + "storage": [], + "types": {}, + "layoutVersion": "1.2", + "flat": false, + "namespaces": {} + }, + "solcVersion": "0.8.20" + }, + "@openzeppelin/contracts/utils/cryptography/ECDSA.sol:ECDSA": { + "src": "@openzeppelin/contracts/utils/cryptography/ECDSA.sol:12", + "version": { + "withMetadata": "331614b026900e8360111160b80a2ee56153ca66bb73d4aaf42d987a68a589f5", + "withoutMetadata": "a64c6cf9c6ba9368f5132c93a0196b3204a7963dbb4dd05dfddb4ab23126b8db", + "linkedWithoutMetadata": "a64c6cf9c6ba9368f5132c93a0196b3204a7963dbb4dd05dfddb4ab23126b8db" + }, + "inherit": [], + "libraries": [], + "methods": [], + "linkReferences": [], + "errors": [], + "layout": { + "storage": [], + "types": {}, + "layoutVersion": "1.2", + "flat": false, + "namespaces": {} + }, + "solcVersion": "0.8.20" + }, + "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol:MessageHashUtils": { + "src": "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol:15", + "version": { + "withMetadata": "47db2b51fbc9919a71b07ceb1b01998df2a411f6e7e9090a303eca3b7fbe9697", + "withoutMetadata": "a64c6cf9c6ba9368f5132c93a0196b3204a7963dbb4dd05dfddb4ab23126b8db", + "linkedWithoutMetadata": "a64c6cf9c6ba9368f5132c93a0196b3204a7963dbb4dd05dfddb4ab23126b8db" + }, + "inherit": [], + "libraries": [ + "@openzeppelin/contracts/utils/Strings.sol:Strings" + ], + "methods": [], + "linkReferences": [], + "errors": [], + "layout": { + "storage": [], + "types": {}, + "layoutVersion": "1.2", + "flat": false, + "namespaces": {} + }, + "solcVersion": "0.8.20" + }, + "@openzeppelin/contracts/utils/introspection/IERC165.sol:IERC165": { + "src": "@openzeppelin/contracts/utils/introspection/IERC165.sol:15", + "inherit": [], + "libraries": [], + "methods": [ + "supportsInterface(bytes4)" + ], + "linkReferences": [], + "errors": [], + "layout": { + "storage": [], + "types": {}, + "layoutVersion": "1.2", + "flat": false, + "namespaces": {} + }, + "solcVersion": "0.8.20" + }, + "@openzeppelin/contracts/utils/math/Math.sol:Math": { + "src": "@openzeppelin/contracts/utils/math/Math.sol:9", + "version": { + "withMetadata": "5fc8cf4b465bec2619d552a3c06f7fbe2ab2174de540f304fb55b0e888f55edd", + "withoutMetadata": "a64c6cf9c6ba9368f5132c93a0196b3204a7963dbb4dd05dfddb4ab23126b8db", + "linkedWithoutMetadata": "a64c6cf9c6ba9368f5132c93a0196b3204a7963dbb4dd05dfddb4ab23126b8db" + }, + "inherit": [], + "libraries": [], + "methods": [], + "linkReferences": [], + "errors": [], + "layout": { + "storage": [], + "types": {}, + "layoutVersion": "1.2", + "flat": false, + "namespaces": {} + }, + "solcVersion": "0.8.20" + }, + "@openzeppelin/contracts/utils/math/SignedMath.sol:SignedMath": { + "src": "@openzeppelin/contracts/utils/math/SignedMath.sol:9", + "version": { + "withMetadata": "12aecc6841d3169e665dbcd7653533b31894b634fefe854d71d51d046514f633", + "withoutMetadata": "a64c6cf9c6ba9368f5132c93a0196b3204a7963dbb4dd05dfddb4ab23126b8db", + "linkedWithoutMetadata": "a64c6cf9c6ba9368f5132c93a0196b3204a7963dbb4dd05dfddb4ab23126b8db" + }, + "inherit": [], + "libraries": [], + "methods": [], + "linkReferences": [], + "errors": [], + "layout": { + "storage": [], + "types": {}, + "layoutVersion": "1.2", + "flat": false, + "namespaces": {} + }, + "solcVersion": "0.8.20" + }, "contracts/message/B2MessageBridge.sol:B2MessageBridge": { "src": "contracts/message/B2MessageBridge.sol:19", "version": { diff --git a/contracts/contracts/message/B2MessageBridge.sol b/contracts/contracts/message/B2MessageBridge.sol index ea143721..65f7687a 100644 --- a/contracts/contracts/message/B2MessageBridge.sol +++ b/contracts/contracts/message/B2MessageBridge.sol @@ -58,7 +58,7 @@ contract B2MessageBridge is IB2MessageBridge, Initializable, UUPSUpgradeable, EI require(!ids[from_chain_id][from_id], "non-repeatable processing"); uint256 weight_ = 0; for(uint256 i = 0; i < signatures.length; i++) { - bool success = verify(from_id, from_chain_id, from_sender, block.chainid, contract_address, data, signatures[i]); + bool success = verify(from_chain_id, from_id, from_sender, block.chainid, contract_address, data, signatures[i]); if (success) { weight_ = weight_ + 1; } @@ -84,7 +84,7 @@ contract B2MessageBridge is IB2MessageBridge, Initializable, UUPSUpgradeable, EI } function SendHash(uint256 from_chain_id, uint256 from_id, address from_sender, uint256 to_chain_id, address contract_address, bytes calldata data) public view returns (bytes32) { - return _hashTypedDataV4(keccak256(abi.encode(SEND_HASH_TYPE,from_chain_id, from_id, from_sender, to_chain_id, contract_address, data))); + return _hashTypedDataV4(keccak256(abi.encode(SEND_HASH_TYPE,from_chain_id, from_id, from_sender, to_chain_id, contract_address, keccak256(data)))); } } \ No newline at end of file diff --git a/contracts/hardhat.config.js b/contracts/hardhat.config.js index 404b69c5..5a9106dd 100644 --- a/contracts/hardhat.config.js +++ b/contracts/hardhat.config.js @@ -3,7 +3,7 @@ require('@openzeppelin/hardhat-upgrades'); // B2_TEST_DEV const B2_DEV = { - RPC_URL: "https://testnet-rpc.bsquared.network", + RPC_URL: "https://b2-testnet.alt.technology", PRIVATE_KEY_LIST: [], } diff --git a/contracts/scripts/message/call.js b/contracts/scripts/message/call.js index dd032dc6..bbd2b91e 100644 --- a/contracts/scripts/message/call.js +++ b/contracts/scripts/message/call.js @@ -1,9 +1,9 @@ const {ethers, upgrades, network} = require("hardhat"); let messageAddress; -let businessAddress; -let to_chain_id; -let data; +// let businessAddress; +// let to_chain_id; +// let data; async function main() { /** @@ -15,23 +15,48 @@ async function main() { console.log("Owner Address:", owner.address); if (network.name == 'b2dev') { - messageAddress = "0xc7441Ac47596D1356fcc70062dA0462FcA98E14e"; - businessAddress = "0x8Ac2C830532d7203a12C4C32C0BE4d3d15917534"; - to_chain_id = 421614; - data = '0x1234'; + messageAddress = "0x5c2646996eEe3ECf865BEfA2De24e5BbE1C552Ba"; + // businessAddress = "0x8Ac2C830532d7203a12C4C32C0BE4d3d15917534"; + // to_chain_id = 421614; + // data = '0x1234567890'; } else if (network.name == 'as') { messageAddress = "0x2A82058E46151E337Baba56620133FC39BD5B71F"; - businessAddress = "0x91171cf194a4B66Bd459Ada038397c7e890FB9D4"; - to_chain_id = 1123; - data = '0x1234'; + // businessAddress = "0x91171cf194a4B66Bd459Ada038397c7e890FB9D4"; + // to_chain_id = 1123; + // data = '0x1234'; } const B2MessageBridge = await ethers.getContractFactory("B2MessageBridge"); const instance = await B2MessageBridge.attach(messageAddress); - let callTx = await instance.call(to_chain_id, businessAddress, data); - const callTxReceipt = await callTx.wait(1); - console.log("callTxReceipt:", callTxReceipt.hash); + // let tx1 = await instance.setWeight(1); + // await tx1.wait(1); + + let tx = await instance.setWeight(1); + await tx.wait(1); + console.log(await instance.weight()); + let from_chain_id = "0"; + let from_id = "68130661828825923178236639338972550787299552799811069952048480569636815930548"; + let from_sender = "0x0000000000000000000000000000000000000000"; + let to_chain_id = "1123"; + let contract_address = "0xAaF7f27EA526B29cF4dA3b957Ed0C388070FcCE5"; + let data = "0x96a0968b0f115755b4f63794cef60c5ce35a8cc9633f2ecbdb4b30ea3f0084b40000000000000000000000000000000000000000000000000000000000000080000000000000000000000000de39679d030c63ae9c5f39d1ba500425e4d6ebe50000000000000000000000000000000000000000000000000000000000989680000000000000000000000000000000000000000000000000000000000000002a746231717a3464337577326330326861736d63733672796c653761326a617678666a6e6a667a7064707a00000000000000000000000000000000000000000000"; + + // 0x9cc4669bb997c40579f89E08980B99218abaE3FE + // 0xfd1d24ee09b1263bcbd62badbd7bb9c295a05eea85126274f36abf20c9b57499 + // 0x940d61022ba8c7cf9784b6e58fb9da6e143e630074e356c2a236b4280b7d688b + // 0x0a048b9daf2b41df9ee6ddaa874c2099636a720f1a539670d8420da9dca410e0 + let hash = await instance.SendHash(from_chain_id, from_id, from_sender, to_chain_id, contract_address, data); + console.log("hash:", hash); + + let signature = "0xa3b185d9dc2a27a4b6af23c03bc4e4a2887a6e769529aa9b967c37d0414a12523b214d3d73dae05acf6122967ef2a00263ccf4ad5a0710470c4639976b3178571b"; + let v = await instance.verify(from_chain_id, from_id, + from_sender, to_chain_id, contract_address, data, signature); + console.log("verify:", v) + + // let callTx = await instance.call(to_chain_id, businessAddress, data); + // const callTxReceipt = await callTx.wait(1); + // console.log("callTxReceipt:", callTxReceipt.hash); } main() diff --git a/contracts/scripts/message/deploy.js b/contracts/scripts/message/deploy.js index 0133a88f..05b664f6 100644 --- a/contracts/scripts/message/deploy.js +++ b/contracts/scripts/message/deploy.js @@ -6,8 +6,6 @@ async function main() { * as: yarn hardhat run scripts/message/deploy.js --network as * b2: yarn hardhat run scripts/message/deploy.js --network b2 */ - // 2445771839062500 - // 991038400000000 const [owner] = await ethers.getSigners() console.log("Owner Address:", owner.address); @@ -19,9 +17,7 @@ async function main() { // Upgrading const simpleBridgeV4 = await ethers.getContractFactory("B2MessageBridge"); - const upgraded = await upgrades.upgradeProxy("0xc7441Ac47596D1356fcc70062dA0462FcA98E14e", simpleBridgeV4, { - gasPrice: ethers.parseUnits('352', 'wei') - }); + const upgraded = await upgrades.upgradeProxy("0x5c2646996eEe3ECf865BEfA2De24e5BbE1C552Ba", simpleBridgeV4); console.log("SimpleBridge upgraded:", upgraded.target); } diff --git a/contracts/scripts/message/grant_role.js b/contracts/scripts/message/grant_role.js new file mode 100644 index 00000000..58f6fd86 --- /dev/null +++ b/contracts/scripts/message/grant_role.js @@ -0,0 +1,53 @@ +const {ethers, network} = require("hardhat"); + +let messageAddress; + +async function main() { + /** + * b2dev: yarn hardhat run scripts/message/grant_role.js --network b2dev + * as: yarn hardhat run scripts/message/grant_role.js --network as + */ + + const [owner] = await ethers.getSigners() + console.log(owner.address) + // return + + if (network.name == 'b2dev') { + messageAddress = "0x5c2646996eEe3ECf865BEfA2De24e5BbE1C552Ba"; + } else if (network.name == 'as') { + messageAddress = "0x2A82058E46151E337Baba56620133FC39BD5B71F"; + } + + // bridge + const bridge = await ethers.getContractFactory("B2MessageBridge"); + const instance = await bridge.attach(messageAddress); + + let grantRole = "0x7e108D9Da2d079cEe26177159c47a2f71EF465B6"; + // const grantRoleTx = await instance.grantRole(await instance.VALIDATOR_ROLE(), grantRole); + // const res = await grantRoleTx.wait(); + // console.log("status:", res.status); + // + hasRole = await instance.hasRole(await instance.VALIDATOR_ROLE(), grantRole); + console.log("hasRole:", hasRole) + + + // const revokeRoleTx = await instance.revokeRole(await instance.ADMIN_ROLE(), grantRole); + // const res = await revokeRoleTx.wait(); + // console.log("status:", res.status); + + // let hasRole = await instance.hasRole(await instance.UPGRADE_ROLE(), grantRole); + // console.log("hasRole:", hasRole) + // if (hasRole) { + // const grantRoleTx = await instance.renounceRole(await instance.UPGRADE_ROLE(), grantRole); + // const res = await grantRoleTx.wait(); + // console.log("status:", res.status); + // } + +} + +main() + .then(() => process.exit(0)) + .catch((error) => { + console.error(error) + process.exit(1) + }) \ No newline at end of file diff --git a/listener/1.txt b/listener/1.txt new file mode 100644 index 00000000..3c834b37 --- /dev/null +++ b/listener/1.txt @@ -0,0 +1,44 @@ +APP_LOG_LEVEL=6 +APP_PARTICLE_URL=https://rpc.particle.network/evm-chain +APP_PARTICLE_CHAINID=1123 +APP_PARTICLE_PROJECTUUID=34c6b829-5b89-44e8-90a9-6d982787b9c9 +APP_PARTICLE_PROJECTKEY=c6Z44Ml4TQeNhctvwYgdSv6DBzfjf6t6CB0JDscR +APP_PARTICLE_AAPUBKEYAPI=https://bridge-aa-dev.bsquared.network +APP_VALIDATOR_BSQUARED=0x67f20dc3b0842117c049b292dd88794b3321c95a1b607e735be88c34327420ba +APP_VALIDATOR_ARBITRUM=0x7990759362da82e88493fd64d058c5e011253ceb45902986590ef4acb0e97706 +APP_BUILDER_BSQUARED=0x67f20dc3b0842117c049b292dd88794b3321c95a1b607e735be88c34327420ba +APP_BUILDER_ARBITRUM=0x7990759362da82e88493fd64d058c5e011253ceb45902986590ef4acb0e97706 +APP_DATABASE_USERNAME=root +APP_DATABASE_PASSWORD=2tRY$q5Ec&%Q +APP_DATABASE_HOST=sg-cdb-7ykkm5v1.sql.tencentcdb.com +APP_DATABASE_PORT=63938 +APP_DATABASE_DBNAME=b2_message +APP_DATABASE_LOGLEVEL=4 +APP_BITCOIN_NAME=bitcoin +APP_BITCOIN_CHAINTYPE=2 +APP_BITCOIN_CHAINID=0 +APP_BITCOIN_MAINNET=false +APP_BITCOIN_RPCURL=divine-patient-meadow.btc-testnet.quiknode.pro/36ade4989e57ddd507d9790dec479606cbe8c0c6 +APP_BITCOIN_SAFEBLOCKNUMBER=3 +APP_BITCOIN_LISTENADDRESS=muGFcyjuyURJJsXaLXHCm43jLBmGPPU7ME +APP_BITCOIN_BLOCKINTERVAL=6000 +APP_BITCOIN_TOCHAINID=1123 +APP_BITCOIN_TOCONTRACTADDRESS=0xAaF7f27EA526B29cF4dA3b957Ed0C388070FcCE5 +APP_BITCOIN_BTCUSER=test +APP_BITCOIN_BTCPASS=test +APP_BSQUARED_NAME=bsquared +APP_BSQUARED_CHAINTYPE=1 +APP_BSQUARED_MAINNET=false +APP_BSQUARED_CHAINID=1123 +APP_BSQUARED_RPCURL=https://b2-testnet.alt.technology +APP_BSQUARED_SAFEBLOCKNUMBER=1 +APP_BSQUARED_LISTENADDRESS=0x5c2646996eEe3ECf865BEfA2De24e5BbE1C552Ba +APP_BSQUARED_BLOCKINTERVAL=2000 +APP_ARBITRUM_NAME=arbitrum +APP_ARBITRUM_CHAINTYPE=1 +APP_ARBITRUM_CHAINID=421614 +APP_ARBITRUM_MAINNET=false +APP_ARBITRUM_RPCURL=https://cosmological-green-spring.arbitrum-sepolia.quiknode.pro/e41990a3263b68eecb26a88d3b3122185798613e +APP_ARBITRUM_SAFEBLOCKNUMBER=1 +APP_ARBITRUM_LISTENADDRESS=0x2A82058E46151E337Baba56620133FC39BD5B71F +APP_ARBITRUM_BLOCKINTERVAL=100 \ No newline at end of file diff --git a/serv/Dockerfile b/listener/Dockerfile similarity index 73% rename from serv/Dockerfile rename to listener/Dockerfile index d6ceca82..49337653 100644 --- a/serv/Dockerfile +++ b/listener/Dockerfile @@ -3,7 +3,8 @@ FROM golang:latest as builder COPY . /src RUN apt-get update && \ cd /src/serv && \ - GO111MODULE=on CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o /src/build/api cmd/app/main.go && GO111MODULE=on CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o /src/build/listener cmd/listener/main.go + GO111MODULE=on CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o /src/build/app cmd/app/main.go +# && GO111MODULE=on CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o /src/build/listener cmd/listener/main.go # RUN apt-get update && apt install -y protobuf-compiler git && \ # cd /tmp && git clone https://github.com/googleapis/googleapis.git && \ # cp -r /tmp/googleapis/* /usr/local/include/ && \ @@ -17,7 +18,7 @@ RUN apt-get update && \ # ===== FROM alpine:latest WORKDIR "/src" -COPY --from=builder /src/build/api /usr/bin/api -COPY --from=builder /src/build/listener /usr/bin/listener +COPY --from=builder /src/build/app /usr/bin/app +#COPY --from=builder /src/build/listener /usr/bin/listener COPY --from=builder /src/serv/config/config.yaml /src/config/config.yaml -CMD ["/usr/bin/listener"] +CMD ["/usr/bin/app"] diff --git a/listener/cmd/app/main.go b/listener/cmd/app/main.go new file mode 100644 index 00000000..71b7d083 --- /dev/null +++ b/listener/cmd/app/main.go @@ -0,0 +1,49 @@ +package main + +import ( + "bsquared.network/b2-message-channel-listener/internal/config" + "bsquared.network/b2-message-channel-listener/internal/initiates" + "bsquared.network/b2-message-channel-listener/internal/serves/builder" + "bsquared.network/b2-message-channel-listener/internal/serves/listener/bitcoin" + "bsquared.network/b2-message-channel-listener/internal/serves/listener/ethereum" + "bsquared.network/b2-message-channel-listener/internal/serves/validator" + "github.com/shopspring/decimal" +) + +func main() { + decimal.DivisionPrecision = 18 + cfg := config.LoadConfig() + + db := initiates.InitDB(cfg.Database) + bsquaredRpc := initiates.InitEthereumRpc(cfg.Bsquared) + arbitrumRpc := initiates.InitEthereumRpc(cfg.Arbitrum) + + // builder + bsquaredBuilder := builder.NewBuilder(cfg.Builder.Bsquared, cfg.Log, cfg.Bsquared, db, bsquaredRpc) + bsquaredBuilder.Start() + + arbitrumBuilder := builder.NewBuilder(cfg.Builder.Arbitrum, cfg.Log, cfg.Arbitrum, db, arbitrumRpc) + arbitrumBuilder.Start() + // listener + //bsquaredRpc := initiates.InitEthereumRpc(cfg.Bsquared) + bsquaredListener := ethereum.NewListener(cfg.Log, cfg.Bsquared, bsquaredRpc, db) + bsquaredListener.Start() + + //arbitrumRpc := initiates.InitEthereumRpc(cfg.Arbitrum) + arbitrumListener := ethereum.NewListener(cfg.Log, cfg.Arbitrum, arbitrumRpc, db) + arbitrumListener.Start() + + bitcoinRpc := initiates.InitBitcoinRpc(cfg.Bitcoin) + bitcoinListener := bitcoin.NewListener(cfg.Log, cfg.Bitcoin, cfg.Particle, bitcoinRpc, db) + bitcoinListener.Start() + // validator + + //bsquaredRpc := initiates.InitEthereumRpc(cfg.Bsquared) + bsquaredValidator := validator.NewValidator(cfg.Validator.Bsquared, cfg.Log, cfg.Bsquared, db, bsquaredRpc) + bsquaredValidator.Start() + + //arbitrumRpc := initiates.InitEthereumRpc(cfg.Arbitrum) + arbitrumValidator := validator.NewValidator(cfg.Validator.Arbitrum, cfg.Log, cfg.Arbitrum, db, arbitrumRpc) + arbitrumValidator.Start() + select {} +} diff --git a/listener/cmd/builder/main.go b/listener/cmd/builder/main.go new file mode 100644 index 00000000..463b2998 --- /dev/null +++ b/listener/cmd/builder/main.go @@ -0,0 +1,23 @@ +package main + +import ( + "bsquared.network/b2-message-channel-listener/internal/config" + "bsquared.network/b2-message-channel-listener/internal/initiates" + "bsquared.network/b2-message-channel-listener/internal/serves/builder" + "github.com/shopspring/decimal" +) + +func main() { + decimal.DivisionPrecision = 18 + cfg := config.LoadConfig() + + db := initiates.InitDB(cfg.Database) + bsquaredRpc := initiates.InitEthereumRpc(cfg.Bsquared) + bsquaredBuilder := builder.NewBuilder(cfg.Builder.Bsquared, cfg.Log, cfg.Bsquared, db, bsquaredRpc) + bsquaredBuilder.Start() + + arbitrumRpc := initiates.InitEthereumRpc(cfg.Arbitrum) + arbitrumBuilder := builder.NewBuilder(cfg.Builder.Arbitrum, cfg.Log, cfg.Arbitrum, db, arbitrumRpc) + arbitrumBuilder.Start() + select {} +} diff --git a/listener/cmd/listener/main.go b/listener/cmd/listener/main.go new file mode 100644 index 00000000..61c72d57 --- /dev/null +++ b/listener/cmd/listener/main.go @@ -0,0 +1,31 @@ +package main + +import ( + "bsquared.network/b2-message-channel-listener/internal/config" + "bsquared.network/b2-message-channel-listener/internal/initiates" + "bsquared.network/b2-message-channel-listener/internal/serves/listener/bitcoin" + "encoding/json" + "fmt" + "github.com/shopspring/decimal" +) + +func main() { + decimal.DivisionPrecision = 18 + cfg := config.LoadConfig() + value, _ := json.Marshal(cfg) + fmt.Println(string(value)) + db := initiates.InitDB(cfg.Database) + + //bsquaredRpc := initiates.InitEthereumRpc(cfg.Bsquared) + //bsquaredListener := ethereum.NewListener(cfg.Log, cfg.Bsquared, bsquaredRpc, db) + //bsquaredListener.Start() + // + //arbitrumRpc := initiates.InitEthereumRpc(cfg.Arbitrum) + //arbitrumListener := ethereum.NewListener(cfg.Log, cfg.Arbitrum, arbitrumRpc, db) + //arbitrumListener.Start() + + bitcoinRpc := initiates.InitBitcoinRpc(cfg.Bitcoin) + bitcoinListener := bitcoin.NewListener(cfg.Log, cfg.Bitcoin, cfg.Particle, bitcoinRpc, db) + bitcoinListener.Start() + select {} +} diff --git a/listener/cmd/test/main.go b/listener/cmd/test/main.go new file mode 100644 index 00000000..71e65be4 --- /dev/null +++ b/listener/cmd/test/main.go @@ -0,0 +1,36 @@ +package main + +import ( + "bsquared.network/b2-message-channel-listener/internal/utils/ethereum/message" + "crypto/ecdsa" + "fmt" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" + "math/big" +) + +func main() { + + var chainId int64 = 1 + var messageContract string = "0xb4a88c4086055b8f546911BaaED28b7CEE134EF9" + var fromChainId int64 = 0 + fromId := big.NewInt(1) + var fromSender string = common.HexToAddress("0x0").Hex() + var toChainId int64 = 1 + var contractAddress string = "0xbf99D4875C47D07Db5381c5092D669D3A0eBfB72" + var data string = "0xbee471d044748a02b1440b19e0e1b4caaccb14d3c9f6f20ec6c02a90445b34c700000000000000000000000000000000000000000000000000000000000000800000000000000000000000000b0c0149d5dbb9eec2c87cff703eadfe428df89100000000000000000000000000000000000000000000000000000000000186a0000000000000000000000000000000000000000000000000000000000000002a746231716b707464737573786b73636176756473326175646663367036377a7533726c307a6d6e377a7500000000000000000000000000000000000000000000" + var key *ecdsa.PrivateKey + key, err := crypto.ToECDSA(common.FromHex("0x67f20dc3b0842117c049b292dd88794b3321c95a1b607e735be88c34327420ba")) + signer := crypto.PubkeyToAddress(key.PublicKey).Hex() + fmt.Println("signer:", signer) + + signature, err := message.SignMessageSend(chainId, messageContract, fromChainId, fromId, fromSender, toChainId, contractAddress, data, key) + if err != nil { + panic(err) + } + verify, err := message.VerifyMessageSend(chainId, messageContract, fromChainId, fromId, fromSender, toChainId, contractAddress, data, signer, signature) + if err != nil { + panic(err) + } + fmt.Println("verify:", verify) +} diff --git a/listener/cmd/validator/main.go b/listener/cmd/validator/main.go new file mode 100644 index 00000000..60052783 --- /dev/null +++ b/listener/cmd/validator/main.go @@ -0,0 +1,25 @@ +package main + +import ( + "bsquared.network/b2-message-channel-listener/internal/config" + "bsquared.network/b2-message-channel-listener/internal/initiates" + "bsquared.network/b2-message-channel-listener/internal/serves/validator" + "github.com/shopspring/decimal" +) + +func main() { + decimal.DivisionPrecision = 18 + cfg := config.LoadConfig() + + db := initiates.InitDB(cfg.Database) + + bsquaredRpc := initiates.InitEthereumRpc(cfg.Bsquared) + bsquaredValidator := validator.NewValidator(cfg.Validator.Bsquared, cfg.Log, cfg.Bsquared, db, bsquaredRpc) + bsquaredValidator.Start() + + arbitrumRpc := initiates.InitEthereumRpc(cfg.Arbitrum) + arbitrumValidator := validator.NewValidator(cfg.Validator.Arbitrum, cfg.Log, cfg.Arbitrum, db, arbitrumRpc) + arbitrumValidator.Start() + + select {} +} diff --git a/listener/config/config.yaml b/listener/config/config.yaml new file mode 100644 index 00000000..e3481328 --- /dev/null +++ b/listener/config/config.yaml @@ -0,0 +1,59 @@ +log: + level: 6 + +particle: + Url: https://rpc.particle.network/evm-chain + ChainId: 1123 + ProjectUuid: 0000000000000000000000000000000000000000 + ProjectKey: 0000000000000000000000000000000000000000 + AAPubKeyAPI: https://bridge-aa-dev.bsquared.network + +validator: + bsquared: 0x0000000000000000000000000000000000000000000000000000000000000000 + arbitrum: 0x0000000000000000000000000000000000000000000000000000000000000000 + +builder: + bsquared: 0x0000000000000000000000000000000000000000000000000000000000000000 + arbitrum: 0x0000000000000000000000000000000000000000000000000000000000000000 + +database: + username: root + password: 123456 + host: 127.0.0.1 + port: 3306 + dbname: b2_message + loglevel: 4 # 1: Silent 2: Error 3: Warn 4: Info + +bitcoin: + name: bitcoin + chaintype: 2 + chainid: 0 + mainnet: false + rpcurl: 127.0.0.1:8085 + safeblocknumber: 3 + ListenAddress: muGFcyjuyURJJsXaLXHCm43jLBmGPPU7ME + BlockInterval: 6000 + ToChainId: 1123 + ToContractAddress: 0xAaF7f27EA526B29cF4dA3b957Ed0C388070FcCE5 + BtcUser: test + BtcPass: test + +bsquared: + name: bsquared + chaintype: 1 + mainnet: false + chainid: 1123 + rpcurl: 127.0.0.1:8084 + safeblocknumber: 1 + ListenAddress: 0x5c2646996eEe3ECf865BEfA2De24e5BbE1C552Ba + BlockInterval: 2000 + +arbitrum: + name: arbitrum + chaintype: 1 + chainid: 421614 + mainnet: false + rpcurl: 127.0.0.1:8083 + safeblocknumber: 1 + ListenAddress: 0x2A82058E46151E337Baba56620133FC39BD5B71F + BlockInterval: 100 diff --git a/listener/go.mod b/listener/go.mod new file mode 100644 index 00000000..dd0eb75f --- /dev/null +++ b/listener/go.mod @@ -0,0 +1,66 @@ +module bsquared.network/b2-message-channel-listener + +go 1.21.1 + +require ( + github.com/btcsuite/btcd v0.24.2 + github.com/btcsuite/btcd/btcutil v1.1.5 + github.com/ethereum/go-ethereum v1.10.20 + github.com/go-resty/resty/v2 v2.14.0 + github.com/jackc/pgx/v5 v5.6.0 + github.com/pkg/errors v0.9.1 + github.com/shopspring/decimal v1.4.0 + github.com/sirupsen/logrus v1.9.3 + github.com/spf13/viper v1.19.0 + github.com/storyicon/sigverify v1.1.0 + gorm.io/driver/mysql v1.5.7 + gorm.io/gorm v1.25.11 +) + +require ( + github.com/StackExchange/wmi v1.2.1 // indirect + github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect + github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 // indirect + github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f // indirect + github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd // indirect + github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 // indirect + github.com/deckarep/golang-set v1.8.0 // indirect + github.com/decred/dcrd/crypto/blake256 v1.0.0 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect + github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/go-ole/go-ole v1.3.0 // indirect + github.com/go-sql-driver/mysql v1.7.0 // indirect + github.com/go-stack/stack v1.8.0 // indirect + github.com/google/uuid v1.4.0 // indirect + github.com/gorilla/websocket v1.5.0 // indirect + github.com/hashicorp/hcl v1.0.0 // indirect + github.com/holiman/uint256 v1.3.1 // indirect + github.com/jackc/pgpassfile v1.0.0 // indirect + github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect + github.com/jinzhu/inflection v1.0.0 // indirect + github.com/jinzhu/now v1.1.5 // indirect + github.com/magiconair/properties v1.8.7 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/pelletier/go-toml/v2 v2.2.2 // indirect + github.com/rjeczalik/notify v0.9.1 // indirect + github.com/sagikazarmark/locafero v0.4.0 // indirect + github.com/sagikazarmark/slog-shim v0.1.0 // indirect + github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect + github.com/sourcegraph/conc v0.3.0 // indirect + github.com/spf13/afero v1.11.0 // indirect + github.com/spf13/cast v1.6.0 // indirect + github.com/spf13/pflag v1.0.5 // indirect + github.com/subosito/gotenv v1.6.0 // indirect + github.com/tklauser/go-sysconf v0.3.12 // indirect + github.com/tklauser/numcpus v0.6.1 // indirect + go.uber.org/atomic v1.9.0 // indirect + go.uber.org/multierr v1.9.0 // indirect + golang.org/x/crypto v0.25.0 // indirect + golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa // indirect + golang.org/x/net v0.27.0 // indirect + golang.org/x/sys v0.22.0 // indirect + golang.org/x/text v0.16.0 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/serv/go.sum b/listener/go.sum similarity index 54% rename from serv/go.sum rename to listener/go.sum index f33631a4..66e720df 100644 --- a/serv/go.sum +++ b/listener/go.sum @@ -1,31 +1,17 @@ -github.com/DataDog/zstd v1.4.5 h1:EndNeuB0l9syBZhut0wns3gV1hL8zX8LIu6ZiVHWLIQ= -github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= -github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= -github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA= github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8= -github.com/VictoriaMetrics/fastcache v1.12.1 h1:i0mICQuojGDL3KblA7wUNlY5lOK6a4bwt3uRKnkZU40= -github.com/VictoriaMetrics/fastcache v1.12.1/go.mod h1:tX04vaqcNoQeGLD+ra5pU5sWkuxnzWhEzLwhP9w653o= +github.com/VictoriaMetrics/fastcache v1.6.0 h1:C/3Oi3EiBCqufydp1neRZkqcwmEiuRT9c3fqvvgKm5o= +github.com/VictoriaMetrics/fastcache v1.6.0/go.mod h1:0qHz5QP0GMX4pfmMA/zt5RgfNuXJrTP0zS7DqpHGGTw= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= -github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= -github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= -github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= -github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bits-and-blooms/bitset v1.10.0 h1:ePXTeiPEazB5+opbv5fr8umg2R/1NlzgDsyepwsSr88= -github.com/bits-and-blooms/bitset v1.10.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= -github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= -github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c= -github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= -github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M= github.com/btcsuite/btcd v0.23.5-0.20231215221805-96c9fd8078fd/go.mod h1:nm3Bko6zh6bWP60UxwoT5LzdGJsQJaPo6HjduXq9p6A= -github.com/btcsuite/btcd v0.24.0 h1:gL3uHE/IaFj6fcZSu03SvqPMSx7s/dPzfpG/atRwWdo= -github.com/btcsuite/btcd v0.24.0/go.mod h1:K4IDc1593s8jKXIF7yS7yCTSxrknB9z0STzc2j6XgE4= +github.com/btcsuite/btcd v0.24.2 h1:aLmxPguqxza+4ag8R1I2nnJjSu2iFn/kqtHTIImswcY= +github.com/btcsuite/btcd v0.24.2/go.mod h1:5C8ChTkl5ejr3WHj8tkQSCmydiMEPB0ZhQhehpq7Dgg= github.com/btcsuite/btcd/btcec/v2 v2.1.0/go.mod h1:2VzYrv4Gm4apmbVVsSq5bqf1Ec8v56E48Vt0Y/umPgA= github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= -github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U= -github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= +github.com/btcsuite/btcd/btcec/v2 v2.3.4 h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurTXGPFfiQ= +github.com/btcsuite/btcd/btcec/v2 v2.3.4/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= github.com/btcsuite/btcd/btcutil v1.0.0/go.mod h1:Uoxwv0pqYWhD//tfTiipkxNfdhG9UrLwaeswfjfdF0A= github.com/btcsuite/btcd/btcutil v1.1.0/go.mod h1:5OapHB7A2hBBWLm48mmw4MOHNJCcUBTwmWH/0Jn8VHE= github.com/btcsuite/btcd/btcutil v1.1.5 h1:+wER79R5670vs/ZusMTF1yTcRYE5GUsFbdjdisflzM8= @@ -46,63 +32,28 @@ github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 h1:R8vQdOQdZ9Y3SkEwmHoWBmX1DNXhXZqlTpq6s4tyJGc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= -github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= -github.com/bytedance/sonic v1.10.0-rc/go.mod h1:ElCzW+ufi8qKqNW0FY314xriJhyJhuoJ3gFZdAHF7NM= -github.com/bytedance/sonic v1.10.2 h1:GQebETVBxYB7JGWJtLBi07OVzWwt+8dWA00gEVW2ZFE= -github.com/bytedance/sonic v1.10.2/go.mod h1:iZcSUejdk5aukTND/Eu/ivjQuEL0Cu9/rf50Hi0u/g4= github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= -github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= -github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY= -github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk= -github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d h1:77cEq6EriyTZ0g/qfRdp61a3Uu/AWrgIq2s0ClJV1g0= -github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d/go.mod h1:8EPpVsBuRksnlj1mLy4AWzRNQYxauNi62uWcE3to6eA= -github.com/chenzhuoyu/iasm v0.9.0/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog= -github.com/chenzhuoyu/iasm v0.9.1 h1:tUHQJXo3NhBqw6s33wkGn9SP3bvrWLdlVIJ3hQBL7P0= -github.com/chenzhuoyu/iasm v0.9.1/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog= -github.com/cockroachdb/errors v1.8.1 h1:A5+txlVZfOqFBDa4mGz2bUWSp0aHElvHX2bKkdbQu+Y= -github.com/cockroachdb/errors v1.8.1/go.mod h1:qGwQn6JmZ+oMjuLwjWzUNqblqk0xl4CVV3SQbGwK7Ac= -github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f h1:o/kfcElHqOiXqcou5a3rIlMc7oJbMQkeLk0VQJ7zgqY= -github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= -github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593 h1:aPEJyR4rPBvDmeyi+l/FS/VtA00IWvjeFvjen1m1l1A= -github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593/go.mod h1:6hk1eMY/u5t+Cf18q5lFMUA1Rc+Sm5I6Ra1QuPyxXCo= -github.com/cockroachdb/redact v1.0.8 h1:8QG/764wK+vmEYoOlfobpe12EQcS81ukx/a4hdVMxNw= -github.com/cockroachdb/redact v1.0.8/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= -github.com/cockroachdb/sentry-go v0.6.1-cockroachdb.2 h1:IKgmqgMQlVJIZj19CdocBeSfSaiCbEBZGKODaixqtHM= -github.com/cockroachdb/sentry-go v0.6.1-cockroachdb.2/go.mod h1:8BT+cPK6xvFOcRlk0R8eg+OTkcqI6baNH4xAkpiYVvQ= -github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= -github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= -github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= -github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= -github.com/consensys/gnark-crypto v0.12.1 h1:lHH39WuuFgVHONRl3J0LRBtuYdQTumFSDtJF7HpyG8M= -github.com/consensys/gnark-crypto v0.12.1/go.mod h1:v2Gy7L/4ZRosZ7Ivs+9SfUDr0f5UlG+EM5t7MPHiLuY= +github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233 h1:d28BXYi+wUpz1KBmiF9bWrjEMacUEREV6MBi2ODnrfQ= -github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233/go.mod h1:geZJZH3SzKCqnz5VT0q/DyIG/tvu/dZk+VIfXicupJs= -github.com/crate-crypto/go-kzg-4844 v0.7.0 h1:C0vgZRk4q4EZ/JgPfzuSoxdCq3C3mOZMBShovmncxvA= -github.com/crate-crypto/go-kzg-4844 v0.7.0/go.mod h1:1kMhvPgI0Ky3yIa+9lFySEBUBXkYxeOi8ZF1sYioxhc= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/deckarep/golang-set/v2 v2.1.0 h1:g47V4Or+DUdzbs8FxCCmgb6VYd+ptPAngjM6dtGktsI= -github.com/deckarep/golang-set/v2 v2.1.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= +github.com/deckarep/golang-set v1.8.0 h1:sk9/l/KqpunDwP7pSjUg0keiOOLEnOBHzykLrsPppp4= +github.com/deckarep/golang-set v1.8.0/go.mod h1:5nI87KwE7wgsBU1F4GKAw2Qod7p5kyS383rP6+o6qqo= github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= -github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= -github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= -github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= -github.com/ethereum/c-kzg-4844 v0.4.0 h1:3MS1s4JtA868KpJxroZoepdV0ZKBp3u/O5HcZ7R3nlY= -github.com/ethereum/c-kzg-4844 v0.4.0/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0= -github.com/ethereum/go-ethereum v1.13.10 h1:Ppdil79nN+Vc+mXfge0AuUgmKWuVv4eMqzoIVSdqZek= -github.com/ethereum/go-ethereum v1.13.10/go.mod h1:sc48XYQxCzH3fG9BcrXCOOgQk2JfZzNAmIKnceogzsA= +github.com/edsrzf/mmap-go v1.0.0 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw= +github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= +github.com/ethereum/go-ethereum v1.10.20 h1:75IW830ClSS40yrQC1ZCMZCt5I+zU16oqId2SiQwdQ4= +github.com/ethereum/go-ethereum v1.10.20/go.mod h1:LWUN82TCHGpxB3En5HVmLLzPD7YSrEUFmFfN1nKkVN0= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= @@ -111,45 +62,19 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= -github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= -github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= -github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46 h1:BAIP2GihuqhwdILrV+7GJel5lyPV3u1+PgzrWLc0TkE= -github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46/go.mod h1:QNpY22eby74jVhqH4WhDLDwxc/vqsern6pW+u2kbkpc= -github.com/getsentry/sentry-go v0.28.1 h1:zzaSm/vHmGllRM6Tpx1492r0YDzauArdBfkJRtY6P5k= -github.com/getsentry/sentry-go v0.28.1/go.mod h1:1fQZ+7l7eeJ3wYi82q5Hg8GqAPgefRq+FP/QhafYVgg= -github.com/gin-contrib/cors v1.5.0 h1:DgGKV7DDoOn36DFkNtbHrjoRiT5ExCe+PC9/xp7aKvk= -github.com/gin-contrib/cors v1.5.0/go.mod h1:TvU7MAZ3EwrPLI2ztzTt3tqgvBCq+wn8WpZmfADjupI= -github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= -github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= -github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg= -github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU= -github.com/go-errors/errors v1.5.1 h1:ZwEMSLRCapFLflTpT7NKaAc7ukJ8ZPEjzlxt8rPN8bk= -github.com/go-errors/errors v1.5.1/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= -github.com/go-ole/go-ole v1.2.5 h1:t4MGB5xEDZvXI+0rMjjsfBsD7yAgp/s9ZDkL1JndXwY= github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= -github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= -github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= -github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= -github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= -github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= -github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= -github.com/go-playground/validator/v10 v10.16.0 h1:x+plE831WK4vaKHO/jpgUGsvLKIqRRkz6M78GuJAfGE= -github.com/go-playground/validator/v10 v10.16.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= +github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= +github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= github.com/go-resty/resty/v2 v2.14.0 h1:/rhkzsAqGQkozwfKS5aFAbb6TyKd3zyFRWcdRXLPCAU= github.com/go-resty/resty/v2 v2.14.0/go.mod h1:IW6mekUOsElt9C7oWr0XRt9BNSD6D5rr9mhk6NjmNHg= +github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc= github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= -github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI= -github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= -github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= -github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= -github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= -github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= -github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= -github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= -github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/golang-jwt/jwt/v4 v4.3.0 h1:kHL1vqdqWNfATmA0FNMdmZNMyZI1U6O31X4rlIPoBog= +github.com/golang-jwt/jwt/v4 v4.3.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= @@ -157,47 +82,36 @@ github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrU github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk= -github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= -github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/subcommands v1.0.1/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= -github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= -github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= -github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/wire v0.5.0 h1:I7ELFeVBr3yfPIcc8+MWvrjk+3VjbcSzoXm3JVa+jD8= -github.com/google/wire v0.5.0/go.mod h1:ngWDr9Qvq3yZA10YrxfyGELY/AFWGVpy9c1LTRi1EoU= +github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= +github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= +github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d h1:dg1dEPuWpEqDnvIw251EVy4zlP8gWbsGj4BsUKCRpYs= +github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7 h1:3JQNjnMRil1yD0IfZKHF9GxxWKDJGj8I0IqOUol//sw= -github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7/go.mod h1:5GuXa7vkL8u9FkFuWdVvfR5ix8hRB7DbOAaYULamFpc= github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA= -github.com/holiman/uint256 v1.2.4 h1:jUc4Nk8fm9jZabQuqr2JzednajVmBpC+oiTiXZJEApU= -github.com/holiman/uint256 v1.2.4/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E= +github.com/holiman/uint256 v1.3.1 h1:JfTzmih28bittyHM8z360dCjIA9dbPIBlcTI6lmctQs= +github.com/holiman/uint256 v1.3.1/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc= -github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= +github.com/huin/goupnp v1.0.3 h1:N8No57ls+MnjlB+JPiCVSOyy/ot7MJTqlo7rn+NYSqQ= +github.com/huin/goupnp v1.0.3/go.mod h1:ZxNlw5WqJj6wSsRK5+YfflQGXYfccj5VgQsMNixHM7Y= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk= github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= -github.com/jackc/pgx/v5 v5.5.4 h1:Xp2aQS8uXButQdnCMWNmvx6UysWQQC+u1EoizjguY+8= -github.com/jackc/pgx/v5 v5.5.4/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A= +github.com/jackc/pgx/v5 v5.6.0 h1:SWJzexBzPL5jb0GEsrPMLIsi/3jOo7RHlzTjcAeDrPY= +github.com/jackc/pgx/v5 v5.6.0/go.mod h1:DNZ/vlrUnhWCoFGxHAG8U2ljioxukquj7utPDgtQdTw= github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= @@ -207,50 +121,23 @@ github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkr github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= -github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= -github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= -github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= -github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= -github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -github.com/klauspost/cpuid/v2 v2.2.6 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/48xc= -github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= -github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= -github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= -github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= -github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= -github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= -github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= -github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= -github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= -github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= +github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= +github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A= github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= -github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY= -github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU= -github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= -github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= @@ -262,30 +149,17 @@ github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5 github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= -github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= -github.com/pelletier/go-toml/v2 v2.1.1 h1:LWAJwfNvjQZCFIDKWYQaM62NcYeYViCmWIwmOStowAI= -github.com/pelletier/go-toml/v2 v2.1.1/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= -github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= -github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= +github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v1.12.0 h1:C+UIj/QWtmqY13Arb8kwMt5j34/0Z2iKamrJ+ryC0Gg= -github.com/prometheus/client_golang v1.12.0/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= -github.com/prometheus/client_model v0.2.1-0.20210607210712-147c58e9608a h1:CmF68hwI0XsOQ5UwlBopMi2Ow4Pbg32akc4KIVCOm+Y= -github.com/prometheus/client_model v0.2.1-0.20210607210712-147c58e9608a/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= -github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4= -github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= -github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/redis/go-redis/v9 v9.4.0 h1:Yzoz33UZw9I/mFhx4MNrB6Fk+XHO1VukNcCa1+lwyKk= -github.com/redis/go-redis/v9 v9.4.0/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M= -github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= -github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/prometheus/tsdb v0.7.1 h1:YZcsG11NqnK4czYLrWd9mpEuAJIHVQLwdrleYfszMAA= +github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/rjeczalik/notify v0.9.1 h1:CLCKso/QK1snAlnhNR/CNvNiFU2saUtjV0bx3EwNeCE= +github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho= github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= @@ -298,8 +172,8 @@ github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6g github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU= github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= -github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= -github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= +github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k= +github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= @@ -310,61 +184,45 @@ github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ= -github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= -github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= -github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg= +github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= +github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg= +github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4 h1:Gb2Tyox57NRNuZ2d3rmvB3pcmbu7O1RS3m8WRx7ilrg= +github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q= github.com/storyicon/sigverify v1.1.0 h1:Fz153Jvloz1P0G3TrG7dHGyAlB3mpjmFeu5IszfJWQ0= github.com/storyicon/sigverify v1.1.0/go.mod h1:q0qxvhdUsMIBAry3h7/IMW7BebRkiT8496TrQP1XW5s= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 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= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= -github.com/supranational/blst v0.3.11 h1:LyU6FolezeWAhvQk0k6O/d49jqgO52MSDDfYgbeoEm4= -github.com/supranational/blst v0.3.11/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= -github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= +github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a h1:1ur3QoCqvE5fl+nylMaIr9PVV1w343YRDtsy+Rwu7XI= +github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48= github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= -github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= -github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= -github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= -github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= -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/urfave/cli/v2 v2.25.7 h1:VAzn5oq403l5pHjc4OhD54+XGO9cdKVL/7lDjF+iKUs= -github.com/urfave/cli/v2 v2.25.7/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= +github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef h1:wHSqTBrZW24CsNJDfeh9Ex6Pm0Rcpc7qrgKBiL44vF4= +github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= +github.com/urfave/cli/v2 v2.10.2 h1:x3p8awjp/2arX+Nl/G2040AZpOCHS/eMJJ1/a+mye4Y= +github.com/urfave/cli/v2 v2.10.2/go.mod h1:f8iq5LtQ/bLxafbdBSLPPNsgaW0l/2fYYEHhAyPlwvo= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= -github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= -go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= -go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= -go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ= -go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.21.0 h1:WefMeulhovoZ2sYXz7st6K0sLj7bBhpiFaud4r4zST8= -go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= -golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= -golang.org/x/arch v0.7.0 h1:pskyeJh/3AmoQ8CPE95vxHLqp1G1GfGNXTmcl9NEKTc= -golang.org/x/arch v0.7.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= +go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= +go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= @@ -374,23 +232,18 @@ golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ= golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= @@ -401,7 +254,6 @@ golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= @@ -419,14 +271,12 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -457,17 +307,12 @@ golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U= golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190422233926-fe54fb35175b/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= @@ -476,34 +321,23 @@ google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQ google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= -google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= -gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= +gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU= +gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gorm.io/driver/mysql v1.5.2 h1:QC2HRskSE75wBuOxe0+iCkyJZ+RqpudsQtqkp+IMuXs= -gorm.io/driver/mysql v1.5.2/go.mod h1:pQLhh1Ut/WUAySdTHwBpBv6+JKcj+ua4ZFx1QQTBzb8= -gorm.io/gorm v1.25.2-0.20230530020048-26663ab9bf55/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= -gorm.io/gorm v1.25.5 h1:zR9lOiiYf09VNh5Q1gphfyia1JpiClIWG9hQaxB/mls= -gorm.io/gorm v1.25.5/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= -nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50= -rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= -rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= -rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA= +gorm.io/driver/mysql v1.5.7 h1:MndhOPYOfEp2rHKgkZIhJ16eVUIRf2HmzgoPmh7FCWo= +gorm.io/driver/mysql v1.5.7/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkDM= +gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= +gorm.io/gorm v1.25.11 h1:/Wfyg1B/je1hnDx3sMkX+gAlxrlZpn6X0BXRlwXlvHg= +gorm.io/gorm v1.25.11/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ= diff --git a/listener/internal/config/config.go b/listener/internal/config/config.go new file mode 100644 index 00000000..a668fe33 --- /dev/null +++ b/listener/internal/config/config.go @@ -0,0 +1,88 @@ +package config + +import ( + "bsquared.network/b2-message-channel-listener/internal/enums" + "github.com/spf13/viper" + "strings" +) + +type AppConfig struct { + Log LogConfig + Database Database + Bsquared Blockchain + Bitcoin Blockchain + Arbitrum Blockchain + Particle Particle + Validator Validator + Builder Builder +} + +type Builder struct { + Bsquared string + Arbitrum string +} + +type Validator struct { + Bsquared string + Arbitrum string +} + +type LogConfig struct { + Level uint32 +} + +type Database struct { + UserName string + Password string + Host string + Port int64 + DbName string + LogLevel int64 +} + +type Blockchain struct { + Name string + ChainType enums.ChainType + ChainId int64 + RpcUrl string + SafeBlockNumber int64 + ListenAddress string + BlockInterval int64 + Mainnet bool + ToChainId int64 + ToContractAddress string + BtcUser string + BtcPass string +} + +type Particle struct { + AAPubKeyAPI string + Url string + ChainId int + ProjectUuid string + ProjectKey string +} + +func LoadConfig() AppConfig { + v := viper.New() + v.SetConfigName("config") + v.AddConfigPath("./config") + v.SetConfigType("yaml") + v.AutomaticEnv() + replacer := strings.NewReplacer(".", "_") + v.SetEnvKeyReplacer(replacer) + + var config AppConfig + + if err := v.ReadInConfig(); err != nil { + panic(err) + } + + v.SetEnvPrefix("app") + + if err := v.Unmarshal(&config); err != nil { + panic(err) + } + + return config +} diff --git a/serv/internal/enums/message.go b/listener/internal/enums/database.go similarity index 74% rename from serv/internal/enums/message.go rename to listener/internal/enums/database.go index 8c186b1c..e98c3f8b 100644 --- a/serv/internal/enums/message.go +++ b/listener/internal/enums/database.go @@ -1,5 +1,22 @@ package enums +type ChainType int64 + +const ( + ChainTypeUnknown ChainType = iota + ChainTypeEVM + ChainTypeUTXO +) + +type TaskStatus int64 + +const ( + TaskStatusUnknown TaskStatus = iota + TaskStatusPending + TaskStatusInvalid + TaskStatusDone +) + type MessageType int64 const ( @@ -11,13 +28,23 @@ const ( type MessageStatus int64 const ( - MessageStatusValidating MessageStatus = iota + MessageStatusUnknown MessageStatus = iota + MessageStatusValidating MessageStatusPending MessageStatusBroadcast MessageStatusValid MessageStatusInvalid ) +type DepositStatus int64 + +const ( + DepositStatusUnknown DepositStatus = iota + DepositStatusPending + DepositStatusValid + DepositStatusInvalid +) + type SignatureStatus int64 const ( @@ -27,20 +54,3 @@ const ( SignatureStatusFailed SignatureStatusInvalid ) - -type ChainType int64 - -const ( - ChainTypeUnknown ChainType = iota - ChainTypeEthereum - ChainTypeBitcoin -) - -type DepositStatus int64 - -const ( - DepositStatusUnknown DepositStatus = iota - DepositStatusPending - DepositStatusValid - DepositStatusInvalid -) diff --git a/listener/internal/initiates/db.go b/listener/internal/initiates/db.go new file mode 100644 index 00000000..59fb6c9d --- /dev/null +++ b/listener/internal/initiates/db.go @@ -0,0 +1,20 @@ +package initiates + +import ( + "bsquared.network/b2-message-channel-listener/internal/config" + "fmt" + "gorm.io/driver/mysql" + "gorm.io/gorm" + "gorm.io/gorm/logger" +) + +func InitDB(database config.Database) *gorm.DB { + dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local", database.UserName, database.Password, database.Host, database.Port, database.DbName) + db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{ + Logger: logger.Default.LogMode(logger.LogLevel(database.LogLevel)), + }) + if err != nil { + panic(err) + } + return db +} diff --git a/listener/internal/initiates/rpc.go b/listener/internal/initiates/rpc.go new file mode 100644 index 00000000..e7d230a4 --- /dev/null +++ b/listener/internal/initiates/rpc.go @@ -0,0 +1,30 @@ +package initiates + +import ( + "bsquared.network/b2-message-channel-listener/internal/config" + "github.com/btcsuite/btcd/rpcclient" + "github.com/ethereum/go-ethereum/ethclient" + log "github.com/sirupsen/logrus" +) + +func InitEthereumRpc(config config.Blockchain) *ethclient.Client { + rpc, err := ethclient.Dial(config.RpcUrl) + if err != nil { + log.Panicf("client dial error: %s\n", err) + } + return rpc +} + +func InitBitcoinRpc(config config.Blockchain) *rpcclient.Client { + rpc, err := rpcclient.New(&rpcclient.ConnConfig{ + Host: config.RpcUrl, + User: config.BtcUser, + Pass: config.BtcPass, + HTTPPostMode: true, // Bitcoin core only supports HTTP POST mode + DisableTLS: false, // Bitcoin core does not provide TLS by default + }, nil) + if err != nil { + log.Panicf("client dial error: %s\n", err) + } + return rpc +} diff --git a/serv/internal/models/base.go b/listener/internal/models/base.go similarity index 100% rename from serv/internal/models/base.go rename to listener/internal/models/base.go diff --git a/serv/internal/models/deposit.go b/listener/internal/models/deposit.go similarity index 99% rename from serv/internal/models/deposit.go rename to listener/internal/models/deposit.go index e2caf645..a18c0691 100644 --- a/serv/internal/models/deposit.go +++ b/listener/internal/models/deposit.go @@ -1,7 +1,7 @@ package models import ( - "bsquared.network/b2-message-channel-serv/internal/enums" + "bsquared.network/b2-message-channel-listener/internal/enums" "time" ) diff --git a/serv/internal/models/messages.go b/listener/internal/models/messages.go similarity index 92% rename from serv/internal/models/messages.go rename to listener/internal/models/messages.go index cdfefa35..5cea9cb1 100644 --- a/serv/internal/models/messages.go +++ b/listener/internal/models/messages.go @@ -1,6 +1,6 @@ package models -import "bsquared.network/b2-message-channel-serv/internal/enums" +import "bsquared.network/b2-message-channel-listener/internal/enums" type Message struct { Base diff --git a/serv/internal/models/signatures.go b/listener/internal/models/signatures.go similarity index 90% rename from serv/internal/models/signatures.go rename to listener/internal/models/signatures.go index dd0d073d..4be65882 100644 --- a/serv/internal/models/signatures.go +++ b/listener/internal/models/signatures.go @@ -1,7 +1,7 @@ package models import ( - "bsquared.network/b2-message-channel-serv/internal/enums" + "bsquared.network/b2-message-channel-listener/internal/enums" "github.com/shopspring/decimal" ) diff --git a/serv/internal/models/sync_events.go b/listener/internal/models/sync_events.go similarity index 100% rename from serv/internal/models/sync_events.go rename to listener/internal/models/sync_events.go diff --git a/listener/internal/models/sync_tasks.go b/listener/internal/models/sync_tasks.go new file mode 100644 index 00000000..6f7f53ee --- /dev/null +++ b/listener/internal/models/sync_tasks.go @@ -0,0 +1,20 @@ +package models + +import "bsquared.network/b2-message-channel-listener/internal/enums" + +type SyncTask struct { + Base + ChainType enums.ChainType `json:"chain_type"` + ChainId int64 `json:"chain_id"` + LatestBlock int64 `json:"latest_block"` + LatestTx int64 `json:"latest_tx"` + StartBlock int64 `json:"start_block"` + EndBlock int64 `json:"end_block"` + HandleNum int64 `json:"handle_num"` + Contracts string `json:"contracts"` + Status enums.TaskStatus `json:"status"` +} + +func (SyncTask) TableName() string { + return "`sync_tasks`" +} diff --git a/listener/internal/serves/builder/builder.go b/listener/internal/serves/builder/builder.go new file mode 100644 index 00000000..31417b89 --- /dev/null +++ b/listener/internal/serves/builder/builder.go @@ -0,0 +1,382 @@ +package builder + +import ( + "bsquared.network/b2-message-channel-listener/internal/config" + "bsquared.network/b2-message-channel-listener/internal/enums" + "bsquared.network/b2-message-channel-listener/internal/models" + msg "bsquared.network/b2-message-channel-listener/internal/utils/ethereum/message" + "bsquared.network/b2-message-channel-listener/internal/utils/log" + "bytes" + "context" + "crypto/ecdsa" + "encoding/hex" + "encoding/json" + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + _types "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/ethereum/go-ethereum/rlp" + "github.com/pkg/errors" + "github.com/shopspring/decimal" + "gorm.io/gorm" + "math/big" + "sync" + "time" +) + +type Builder struct { + rpc *ethclient.Client + db *gorm.DB + config config.Blockchain + mu sync.Mutex + key string + logger *log.Logger +} + +func NewBuilder(key string, logConfig config.LogConfig, config config.Blockchain, db *gorm.DB, rpc *ethclient.Client) *Builder { + return &Builder{ + db: db, + rpc: rpc, + config: config, + key: key, + logger: log.NewLogger(config.Name, logConfig.Level), + } +} + +func (b *Builder) Start() { + go b.build() + go b.broadcast() +} + +func (b *Builder) build() { + duration := time.Millisecond * time.Duration(b.config.BlockInterval) + for { + list, err := b.pendingCallMessage(10) + if err != nil { + b.logger.Errorf("et pending call message err: %s", err) + time.Sleep(duration) + continue + } + if len(list) == 0 { + b.logger.Infof("Get pending call message length is 0") + time.Sleep(duration) + continue + } + + for _, message := range list { + err = b.buildMessage(message) + if err != nil { + b.logger.Errorf("Handle err: %v, %v", err, message) + } + } + //var wg sync.WaitGroup + //for _, message := range list { + // wg.Add(1) + // go func(_wg *sync.WaitGroup, message models.Message) { + // defer _wg.Done() + // err = b.buildMessage(message) + // if err != nil { + // b.logger.Errorf("Handle err: %v, %v", err, message) + // } + // }(&wg, message) + //} + //wg.Wait() + } +} + +func (b *Builder) buildMessage(message models.Message) error { + UserAddress, UserKey, err := b.BorrowAccount() + if err != nil { + b.logger.Errorf("borrow account err: %s\n", err) + return errors.WithStack(err) + } + defer b.mu.Unlock() + b.logger.Errorf("UserAddress: %s", UserAddress) + + //lock, err := b.LockUser(UserAddress, time.Minute*2) + //if err != nil { + // b.logger.Errorf("lock err: %s\n", err) + // return errors.WithStack(err) + //} + //if !lock { + // b.logger.Infof("load result: %v\n", lock) + // return errors.WithStack(err) + //} + //defer b.UnlockUser(UserAddress) + + gasPrice, err := b.GasPrice() + if err != nil { + return errors.WithStack(err) + } + //gasPrice := big.NewInt(1000) + b.logger.Debugf("gasPrice: %v\n", gasPrice) + + toAddress := common.HexToAddress(b.config.ListenAddress) + b.logger.Debugf("toAddress: %v\n", toAddress) + + var signatures []string + err = json.Unmarshal([]byte(message.Signatures), &signatures) + if err != nil { + return errors.WithStack(err) + } + b.logger.Infof("FromChainId: %s,FromId: %s, FromSender: %s, ToContractAddress: %s, ToBytes: %s", message.FromChainId, common.HexToHash(message.FromId).Big().Text(10), message.FromSender, message.ToContractAddress, message.ToBytes) + data := msg.Send(message.FromChainId, common.HexToHash(message.FromId).Big(), message.FromSender, message.ToContractAddress, message.ToBytes, signatures) + b.logger.Debugf("data: %x\n", data) + gasLimit, err := b.rpc.EstimateGas(context.Background(), ethereum.CallMsg{ + From: common.HexToAddress(UserAddress), + To: &toAddress, + GasPrice: gasPrice, + Value: big.NewInt(0), + Data: data, + }) + if err != nil { + b.logger.Errorf("Get gasLimit err: %s\n", err) + return errors.WithStack(err) + } + b.logger.Debugf("gasLimit: %v\n", gasLimit) + err = b.db.Transaction(func(tx *gorm.DB) error { + // nonce + nonce, err := b.GetNonce(UserAddress) + if err != nil { + b.logger.Errorf("get nonce err: %s\n", err) + return errors.WithStack(err) + } + b.logger.Debugf("nonce: %v\n", nonce) + // signTx + _signature, err := b.SignTx(UserAddress, UserKey, nonce, toAddress.Hex(), big.NewInt(0), gasLimit, gasPrice, data, b.config.ChainId) + if err != nil { + b.logger.Errorf("sign tx err: %s\n", err) + return errors.WithStack(err) + } + _txHash := crypto.Keccak256Hash(_signature) + b.logger.Debugf("txHash: %s, signature: %s\n", _txHash, hex.EncodeToString(_signature)) + + // create signature + err = b.CreateSignature(tx, message.ToChainId, message.FromId, UserAddress, int64(nonce), enums.MessageTypeSend, hex.EncodeToString(data), decimal.Zero, hex.EncodeToString(_signature), _txHash.Hex()) + if err != nil { + b.logger.Errorf("create signature err: %s\n", err) + return errors.WithStack(err) + } + // broadcast + message.Status = enums.MessageStatusBroadcast + err = tx.Save(&message).Error + if err != nil { + b.logger.Errorf("broadcast approve err: %s", err) + return errors.WithStack(err) + } + b.logger.Infof("broadcast approve success") + return nil + }) + if err != nil { + //log.Errorf("Handle approve err: %s\n", err) + return errors.WithStack(err) + } + return nil +} + +func (b *Builder) pendingCallMessage(limit int) ([]models.Message, error) { + var list []models.Message + err := b.db.Where("`to_chain_id`=? AND `type`=? AND `status`=?", b.config.ChainId, enums.MessageTypeCall, enums.MessageStatusPending).Limit(limit).Find(&list).Error + if err != nil { + return nil, err + } + return list, nil +} + +func (b *Builder) SignTx(accountAddress string, accountKey *ecdsa.PrivateKey, nonce uint64, toAddress string, value *big.Int, gasLimit uint64, gasPrice *big.Int, bytecode []byte, chainID int64) ([]byte, error) { + //senderKey, err := b.getKeyByAddress(accountAddress) + //if err != nil { + // return nil, errors.WithStack(err) + //} + _signature, err := b._signTx(accountAddress, accountKey, nonce, toAddress, value, gasLimit, gasPrice, bytecode, chainID) + if err != nil { + return nil, errors.WithStack(err) + } + return _signature, nil +} + +func (b *Builder) _signTx(accountAddress string, accountKey *ecdsa.PrivateKey, nonce uint64, toAddress string, value *big.Int, gasLimit uint64, gasPrice *big.Int, bytecode []byte, chainID int64) ([]byte, error) { + if crypto.PubkeyToAddress(accountKey.PublicKey) != common.HexToAddress(accountAddress) { + return nil, errors.New(" address and index do not match ") + } + tx := types.NewTransaction( + nonce, + common.HexToAddress(toAddress), + value, + gasLimit, + gasPrice, + bytecode, + ) + signedTx, err := types.SignTx(tx, types.NewEIP155Signer(big.NewInt(chainID)), accountKey) + if err != nil { + return nil, err + } + ts := types.Transactions{signedTx} + var rawTxBytes bytes.Buffer + ts.EncodeIndex(0, &rawTxBytes) + return rawTxBytes.Bytes(), nil +} + +func (b *Builder) GetNonce(userAddress string) (uint64, error) { + var signature models.Signature + err := b.db.Raw("SELECT * FROM signatures WHERE `status`!=? AND `address`=? ORDER BY nonce DESC FOR UPDATE ", + enums.SignatureStatusInvalid, userAddress).First(&signature).Error + if err != nil && err != gorm.ErrRecordNotFound { + return 0, err + } else if err == gorm.ErrRecordNotFound { + nonce, err := b.rpc.NonceAt(context.Background(), common.HexToAddress(userAddress), nil) + if err != nil { + return 0, err + } + return nonce, nil + } else { + if signature.Status != enums.SignatureStatusSuccess && signature.Status != enums.SignatureStatusFailed { + return 0, errors.New("The current user has pending transactions ") + } + nonce, err := b.rpc.NonceAt(context.Background(), common.HexToAddress(userAddress), nil) + if err != nil { + return 0, err + } + return nonce, nil + } +} + +func (b *Builder) CreateSignature(tx *gorm.DB, chainId int64, referId string, address string, nonce int64, signatureType enums.MessageType, data string, value decimal.Decimal, signature string, txHash string) error { + err := tx.Create(&models.Signature{ + ChainId: chainId, + ReferId: referId, + Address: address, + Nonce: nonce, + Type: signatureType, + Data: data, + Value: value, + Signature: signature, + Status: enums.SignatureStatusPending, + Blockchain: models.Blockchain{ + EventId: 0, + BlockTime: 0, + BlockNumber: 0, + LogIndex: 0, + TxHash: txHash, + }, + }).Error + if err != nil { + return err + } + return nil +} + +func (b *Builder) GasPrice() (*big.Int, error) { + gasPrice, err := b.rpc.SuggestGasPrice(context.Background()) + if err != nil { + return nil, errors.WithStack(err) + } + return gasPrice, nil +} + +func (b *Builder) LockUser(key string, duration time.Duration) (bool, error) { + //return l.Cache.Client.SetNX(context.Background(), key, true, duration).Result() + return false, nil +} + +func (b *Builder) UnlockUser(key string) error { + //_, err := l.Cache.Client.Del(context.Background(), key).Result() + //return err + return nil +} + +func (b *Builder) BorrowAccount() (string, *ecdsa.PrivateKey, error) { + if b.mu.TryLock() { + _key, err := crypto.ToECDSA(common.FromHex(b.key)) + if err != nil { + return "", nil, err + } + return crypto.PubkeyToAddress(_key.PublicKey).Hex(), _key, nil + } else { + return "", nil, errors.New("account is locked") + } +} + +//func (b *Builder) getKeyByAddress(accountAddress string) (string, error) { +// if key, ok := l.DataMap.SenderMap[accountAddress]; ok { +// return key, nil +// } else { +// return "", errors.New("account not found") +// } +// return "", nil +//} + +func (b *Builder) broadcast() { + duration := time.Millisecond * time.Duration(b.config.BlockInterval) + for { + var signatures []models.Signature + err := b.db.Where("`chain_id`=? AND `status`=?", b.config.ChainId, enums.SignatureStatusPending).Order("id").Limit(100).Find(&signatures).Error + if err != nil { + time.Sleep(duration) + continue + } + if len(signatures) == 0 { + time.Sleep(duration) + continue + } + + var wg sync.WaitGroup + for _, signature := range signatures { + wg.Add(1) + go func(_wg *sync.WaitGroup, signature models.Signature) { + defer _wg.Done() + err = b.broadcastSignature(signature) + if err != nil { + b.logger.Errorf("Broadcast signature err[%d]: %s\n", signature.Id, err) + } + }(&wg, signature) + } + wg.Wait() + } +} + +func (b *Builder) broadcastSignature(signature models.Signature) error { + err := b._broadcast(signature.Signature) + if err != nil && err.Error() != "nonce too low" && err.Error() != "already known" { + return errors.WithStack(err) + } else if err != nil && err.Error() == "nonce too low" { + // _, err := ctx.RPC.TransactionReceipt(context.Background(), common.HexToHash(signature.TxHash)) + // if err != nil { + // log.Errorf("Get TransactionReceipt err[%d]: %s\n", signature.Id, err) + // return err + // } + err = b.db.Model(&models.Signature{}).Where("id = ?", signature.Id).Update("status", enums.SignatureStatusBroadcast).Error + if err != nil { + return errors.WithStack(err) + } + } else if err != nil && err.Error() == "already known" { + err = b.db.Model(&models.Signature{}).Where("id = ?", signature.Id).Update("status", enums.SignatureStatusBroadcast).Error + if err != nil { + return errors.WithStack(err) + } + } else { + err = b.db.Model(&models.Signature{}).Where("id = ?", signature.Id).Update("status", enums.SignatureStatusBroadcast).Error + if err != nil { + return errors.WithStack(err) + } + return nil + } + return nil +} + +func (b *Builder) _broadcast(signature string) error { + rawTxBytes, err := hex.DecodeString(signature) + if err != nil { + b.logger.Errorf("Decode signature err[%d]: %s\n", signature, err) + return err + } + tx := new(_types.Transaction) + rlp.DecodeBytes(rawTxBytes, &tx) + err = b.rpc.SendTransaction(context.Background(), tx) + if err != nil { + return err + } + return nil +} diff --git a/serv/internal/listener/bitcoin/syncTask.go b/listener/internal/serves/listener/bitcoin/bitcoin.go similarity index 55% rename from serv/internal/listener/bitcoin/syncTask.go rename to listener/internal/serves/listener/bitcoin/bitcoin.go index 07cfeaf7..dec02f9f 100644 --- a/serv/internal/listener/bitcoin/syncTask.go +++ b/listener/internal/serves/listener/bitcoin/bitcoin.go @@ -1,35 +1,103 @@ package bitcoin import ( - "bsquared.network/b2-message-channel-serv/internal/enums" - "bsquared.network/b2-message-channel-serv/internal/models" - "bsquared.network/b2-message-channel-serv/internal/types" + "bsquared.network/b2-message-channel-listener/internal/config" + "bsquared.network/b2-message-channel-listener/internal/enums" + "bsquared.network/b2-message-channel-listener/internal/models" + "bsquared.network/b2-message-channel-listener/internal/types" + "bsquared.network/b2-message-channel-listener/internal/utils/aa" + "bsquared.network/b2-message-channel-listener/internal/utils/ethereum/message" + "bsquared.network/b2-message-channel-listener/internal/utils/log" "bytes" "encoding/hex" "encoding/json" "fmt" + "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/chaincfg" + "github.com/btcsuite/btcd/rpcclient" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" "github.com/jackc/pgx/v5/pgconn" "github.com/pkg/errors" - log "github.com/sirupsen/logrus" + "github.com/shopspring/decimal" "gorm.io/gorm" "sync" "time" ) -func (l *Listener) syncTask() { +var ( + ErrParsePkScript = errors.New("parse pkscript err") + ErrDecodeListenAddress = errors.New("decode listen address err") + ErrTargetConfirmations = errors.New("target confirmation number was not reached") + ErrParsePubKey = errors.New("parse pubkey failed, not found pubkey or nonsupport ") + ErrParsePkScriptNullData = errors.New("parse pkscript null data err") + ErrParsePkScriptNotNullData = errors.New("parse pkscript not null data err") +) + +const ( + // tx type + TxTypeTransfer = "transfer" // btc transfer + TxTypeWithdraw = "withdraw" // btc withdraw +) + +type BitcoinListener struct { + config config.Blockchain + particle config.Particle + rpc *rpcclient.Client + db *gorm.DB + logger *log.Logger + latestBlock int64 +} + +func NewListener(logConfig config.LogConfig, config config.Blockchain, particle config.Particle, rpc *rpcclient.Client, db *gorm.DB) *BitcoinListener { + return &BitcoinListener{ + config: config, + particle: particle, + rpc: rpc, + db: db, + logger: log.NewLogger(config.Name, logConfig.Level), + } +} + +func (l *BitcoinListener) Name() string { + return l.config.Name +} + +func (l *BitcoinListener) Start() { + go l.syncLatestBlock() + go l.syncTask() + go l.handDeposit() +} + +func (l *BitcoinListener) syncLatestBlock() { for { - duration := time.Millisecond * time.Duration(l.Blockchain.BlockInterval) + duration := time.Millisecond * time.Duration(l.config.BlockInterval) * 10 + latest, err := l.rpc.GetBlockCount() + if err != nil { + l.logger.Errorf("sync latest block failed, err: %v", err) + time.Sleep(duration) + continue + } + l.latestBlock = int64(latest) - l.config.SafeBlockNumber + l.logger.Infof("sync latest block success, latest block: %d", l.latestBlock) + time.Sleep(duration) + } +} + +func (l *BitcoinListener) syncTask() { + for { + duration := time.Millisecond * time.Duration(l.config.BlockInterval) var tasks []models.SyncTask - err := l.Db.Where("`chain_type`=? AND `chain_id`=? AND `status`=?", enums.ChainTypeBitcoin, l.Blockchain.ChainId, models.SyncTaskPending).Limit(20).Find(&tasks).Error + err := l.db.Where("`chain_type`=? AND `chain_id`=? AND `status`=?", enums.ChainTypeUTXO, l.config.ChainId, enums.TaskStatusPending).Limit(20).Find(&tasks).Error if err != nil { + l.logger.Errorf("get task list err: %s", err) time.Sleep(duration) continue } if len(tasks) == 0 { - log.Infof("[Handler.syncTask] Pending tasks count is 0\n") + l.logger.Infof("no task to handle") time.Sleep(duration) continue } @@ -38,9 +106,9 @@ func (l *Listener) syncTask() { wg.Add(1) go func(take models.SyncTask, wg *sync.WaitGroup) { defer wg.Done() - err := l.HandleTask(task) + err := l.handleTask(task) if err != nil { - log.Errorf("[Handler.SyncTask] HandleTask ID: %d , err: %s \n", task.Id, err) + l.logger.Errorf("handle task err: %s", err) } }(task, &wg) } @@ -48,8 +116,8 @@ func (l *Listener) syncTask() { } } -func (l *Listener) HandleTask(task models.SyncTask) error { - +func (l *BitcoinListener) handleTask(task models.SyncTask) error { + l.logger.Infof("start handle task, task id: %d", task.Id) var ( currentBlock int64 // index current block number currentTxIndex int64 // index current block tx index @@ -62,16 +130,8 @@ func (l *Listener) HandleTask(task models.SyncTask) error { currentTxIndex = task.LatestTx for { - if l.LatestBlockNumber <= currentBlock { - //<-ticker.C - //ticker.Reset(NewBlockWaitTimeout) - // - //// update latest block - //latestBlock, err = bis.txIdxr.LatestBlock() - //if err != nil { - // bis.log.Errorw("bitcoin indexer latestBlock", "error", err.Error()) - //} - time.Sleep(time.Second * 10) + if l.latestBlock <= currentBlock { + //time.Sleep(time.Second * time.Duration(l.config.BlockInterval)) continue } if currentTxIndex == 0 { @@ -79,14 +139,16 @@ func (l *Listener) HandleTask(task models.SyncTask) error { } else { currentTxIndex++ } - for i := currentBlock; i <= l.LatestBlockNumber; i++ { + + for i := currentBlock; i <= l.latestBlock; i++ { + l.logger.Infof("start sync task, task id: %d, current block: %d, current tx index: %d", task.Id, currentBlock, currentTxIndex) txResults, blockHeader, err := l.ParseBlock(i, currentTxIndex) if err != nil { if errors.Is(err, ErrTargetConfirmations) { - //bis.log.Warnw("parse block confirmations", "error", err.Error(), "currentBlock", i, "currentTxIndex", currentTxIndex) - time.Sleep(NewBlockWaitTimeout) + l.logger.Errorf("parse block err: %s", err) + //time.Sleep(time.Second * time.Duration(l.config.BlockInterval)) } else { - //bis.log.Errorw("parse block unknown err", "error", err.Error(), "currentBlock", i, "currentTxIndex", currentTxIndex) + l.logger.Errorf("parse block unknown err: %s", err) } if currentTxIndex == 0 { currentBlock = i - 1 @@ -100,6 +162,7 @@ func (l *Listener) HandleTask(task models.SyncTask) error { if len(txResults) > 0 { currentBlock, currentTxIndex, err = l.HandleResults(txResults, task, blockHeader.Timestamp, i) if err != nil { + l.logger.Errorf("handle results err: %s", err) //bis.log.Errorw("failed to handle results", "error", err, // "currentBlock", currentBlock, "currentTxIndex", currentTxIndex, "latestBlock", latestBlock) rollback := true @@ -126,22 +189,24 @@ func (l *Listener) HandleTask(task models.SyncTask) error { currentTxIndex = 0 task.LatestBlock = currentBlock task.LatestTx = currentTxIndex - if err := l.Db.Save(&task).Error; err != nil { + if err := l.db.Save(&task).Error; err != nil { + l.logger.Errorf("save task err: %s", err) //bis.log.Errorw("failed to save bitcoin index block", "error", err, "currentBlock", i, // "currentTxIndex", currentTxIndex, "latestBlock", latestBlock) // rollback currentBlock = i - 1 break } + //l.logger.Infof("bitcoin indexer parsed currentBlock, i) //bis.log.Infow("bitcoin indexer parsed", "currentBlock", i, // "currentTxIndex", currentTxIndex, "latestBlock", latestBlock) - time.Sleep(IndexBlockTimeout) + time.Sleep(time.Millisecond * time.Duration(l.config.BlockInterval)) } } return nil } -func (l *Listener) ParseBlock(height int64, txIndex int64) ([]*types.BitcoinTxParseResult, *wire.BlockHeader, error) { +func (l *BitcoinListener) ParseBlock(height int64, txIndex int64) ([]*types.BitcoinTxParseResult, *wire.BlockHeader, error) { blockResult, err := l.getBlockByHeight(height) if err != nil { return nil, nil, err @@ -168,18 +233,18 @@ func (l *Listener) ParseBlock(height int64, txIndex int64) ([]*types.BitcoinTxPa } // getBlockByHeight returns a raw block from the server given its height -func (l *Listener) getBlockByHeight(height int64) (*wire.MsgBlock, error) { - blockhash, err := l.Rpc.GetBlockHash(height) +func (l *BitcoinListener) getBlockByHeight(height int64) (*wire.MsgBlock, error) { + blockhash, err := l.rpc.GetBlockHash(height) if err != nil { return nil, err } - msgBlock, err := l.Rpc.GetBlock(blockhash) + msgBlock, err := l.rpc.GetBlock(blockhash) if err != nil { return nil, err } return msgBlock, nil } -func (l *Listener) parseTx(txResult *wire.MsgTx, index int) (*types.BitcoinTxParseResult, error) { +func (l *BitcoinListener) parseTx(txResult *wire.MsgTx, index int) (*types.BitcoinTxParseResult, error) { listenAddress := false var totalValue int64 tos := make([]types.BitcoinTo, 0) @@ -210,8 +275,17 @@ func (l *Listener) parseTx(txResult *wire.MsgTx, index int) (*types.BitcoinTxPar } tos = append(tos, parseTo) } + + var chainParams *chaincfg.Params + if l.config.Mainnet { + chainParams = &chaincfg.MainNetParams + } else { + chainParams = &chaincfg.TestNet3Params + } + _listenAddress, err := btcutil.DecodeAddress(l.config.ListenAddress, chainParams) + // if pk address eq dest listened address, after parse from address by vin prev tx - if pkAddress == l.listenAddress.EncodeAddress() { + if pkAddress == _listenAddress.EncodeAddress() { listenAddress = true totalValue += v.Value } @@ -230,20 +304,28 @@ func (l *Listener) parseTx(txResult *wire.MsgTx, index int) (*types.BitcoinTxPar return nil, nil } + var chainParams *chaincfg.Params + if l.config.Mainnet { + chainParams = &chaincfg.MainNetParams + } else { + chainParams = &chaincfg.TestNet3Params + } + _listenAddress, err := btcutil.DecodeAddress(l.config.ListenAddress, chainParams) + return &types.BitcoinTxParseResult{ TxID: txResult.TxHash().String(), TxType: TxTypeTransfer, Index: int64(index), Value: totalValue, From: fromAddress, - To: l.listenAddress.EncodeAddress(), + To: _listenAddress.EncodeAddress(), Tos: tos, }, nil } return nil, nil } -func (l *Listener) parseAddress(pkScript []byte) (string, error) { +func (l *BitcoinListener) parseAddress(pkScript []byte) (string, error) { pk, err := txscript.ParsePkScript(pkScript) if err != nil { scriptClass := txscript.GetScriptClass(pkScript) @@ -258,7 +340,14 @@ func (l *Listener) parseAddress(pkScript []byte) (string, error) { } // encodes the script into an address for the given chain. - pkAddress, err := pk.Address(l.ChainParams) + + var chainParams *chaincfg.Params + if l.config.Mainnet { + chainParams = &chaincfg.MainNetParams + } else { + chainParams = &chaincfg.TestNet3Params + } + pkAddress, err := pk.Address(chainParams) if err != nil { return "", fmt.Errorf("PKScript to address err:%w", err) } @@ -266,18 +355,18 @@ func (l *Listener) parseAddress(pkScript []byte) (string, error) { } // parseNullData from pkscript parse null data -func (l *Listener) parseNullData(pkScript []byte) (string, error) { +func (l *BitcoinListener) parseNullData(pkScript []byte) (string, error) { if !txscript.IsNullData(pkScript) { return "", ErrParsePkScriptNotNullData } return hex.EncodeToString(pkScript[1:]), nil } -func (l *Listener) parseFromAddress(txResult *wire.MsgTx) (fromAddress []types.BitcoinFrom, err error) { +func (l *BitcoinListener) parseFromAddress(txResult *wire.MsgTx) (fromAddress []types.BitcoinFrom, err error) { for _, vin := range txResult.TxIn { // get prev tx hash prevTxID := vin.PreviousOutPoint.Hash - vinResult, err := l.Rpc.GetRawTransaction(&prevTxID) + vinResult, err := l.rpc.GetRawTransaction(&prevTxID) if err != nil { return nil, fmt.Errorf("vin get raw transaction err:%w", err) } @@ -303,7 +392,7 @@ func (l *Listener) parseFromAddress(txResult *wire.MsgTx) (fromAddress []types.B return fromAddress, nil } -func (l *Listener) HandleResults( +func (l *BitcoinListener) HandleResults( txResults []*types.BitcoinTxParseResult, syncTask models.SyncTask, btcBlockTime time.Time, @@ -332,12 +421,12 @@ func (l *Listener) HandleResults( return currentBlock, v.Index, err } //bis.log.Infow("save bitcoin index tx success", "currentBlock", currentBlock, "currentTxIndex", v.Index, "data", v) - time.Sleep(IndexTxTimeout) + time.Sleep(time.Second * 2) } return currentBlock, 0, nil } -func (l *Listener) ToInFroms(a []types.BitcoinFrom, s string) bool { +func (l *BitcoinListener) ToInFroms(a []types.BitcoinFrom, s string) bool { for _, i := range a { if i.Address == s { return true @@ -346,7 +435,7 @@ func (l *Listener) ToInFroms(a []types.BitcoinFrom, s string) bool { return false } -func (l *Listener) SaveParsedResult( +func (l *BitcoinListener) SaveParsedResult( parseResult *types.BitcoinTxParseResult, btcBlockNumber int64, b2TxStatus int, @@ -354,7 +443,7 @@ func (l *Listener) SaveParsedResult( syncTask models.SyncTask, ) error { // write db - err := l.Db.Transaction(func(tx *gorm.DB) error { + err := l.db.Transaction(func(tx *gorm.DB) error { if len(parseResult.From) == 0 { return fmt.Errorf("parse result from empty") } @@ -466,3 +555,114 @@ func (l *Listener) SaveParsedResult( }) return err } + +func (l *BitcoinListener) handDeposit() { + duration := time.Millisecond * time.Duration(l.config.BlockInterval) * 10 + for { + var list []models.Deposit + err := l.db.Where("status=?", enums.DepositStatusPending).Find(&list).Error + if err != nil { + l.logger.Errorf("[Handler.handDeposit] err: %s", err) + time.Sleep(duration) + continue + } + if len(list) == 0 { + l.logger.Info("[Handler.handDeposit] deposit list is empty") + time.Sleep(duration) + continue + } + + wg := sync.WaitGroup{} + for _, one := range list { + wg.Add(1) + go func(one models.Deposit, wg *sync.WaitGroup) { + defer wg.Done() + err := l.handleMessage(one) + if err != nil { + l.logger.Errorf("[Handler.handDeposit] Deposit ID: %d , err: %s \n", one.Id, err) + } + }(one, &wg) + } + wg.Wait() + } +} + +func (l *BitcoinListener) GetDepositAddress(deposit models.Deposit) (string, error) { + if deposit.BtcFromEvmAddress != "" && common.IsHexAddress(deposit.BtcFromEvmAddress) { + return deposit.BtcFromEvmAddress, nil + } else { + evmAddress, err := aa.BitcoinAddressToEthAddress(l.particle.AAPubKeyAPI, deposit.BtcFrom, + l.particle.Url, l.particle.ChainId, l.particle.ProjectUuid, l.particle.ProjectKey) + if err != nil { + l.logger.Errorf("[Handler.GetDepositAddress] Deposit ID: %d , err: %s \n", deposit.Id, err) + return "", err + } + return evmAddress, nil + } +} + +func (l *BitcoinListener) handleMessage(deposit models.Deposit) error { + toChainId := l.config.ToChainId + toContractAddress := l.config.ToContractAddress + + depositAddress, err := l.GetDepositAddress(deposit) + if err != nil && err.Error() != "AAGetBTCAccount not found" { + l.logger.Errorf("[Handler.handleMessage] GetDepositAddress err: %s \n", err) + return err + } else if err != nil && err.Error() == "AAGetBTCAccount not found" { + err = l.db.Model(models.Deposit{}). + Where("id=?", deposit.Id). + Update("status", enums.MessageStatusInvalid).Error + return nil + } + + data := message.EncodeSendData(deposit.BtcTxHash, deposit.BtcFrom, depositAddress, decimal.New(deposit.BtcValue, 0)) + msg := models.Message{ + ChainId: l.config.ChainId, + Type: enums.MessageTypeCall, + FromChainId: l.config.ChainId, + FromSender: common.HexToAddress("0x0").Hex(), + FromContractAddress: common.HexToAddress("0x0").Hex(), + FromId: common.HexToHash(deposit.BtcTxHash).Hex(), + ToChainId: toChainId, + ToContractAddress: toContractAddress, + ToBytes: hexutil.Encode(data), + Signatures: "{}", + Status: enums.MessageStatusValidating, + Blockchain: models.Blockchain{ + EventId: deposit.Id, + BlockTime: deposit.BtcBlockTime.Unix(), + BlockNumber: deposit.BtcBlockNumber, + LogIndex: deposit.BtcTxIndex, + TxHash: common.HexToHash(deposit.BtcTxHash).Hex(), + }, + } + err = l.db.Transaction(func(tx *gorm.DB) error { + err := tx.Create(&msg).Error + if err != nil { + l.logger.Errorf("create message failed: %s", err.Error()) + return err + } + + if deposit.BtcFromEvmAddress != "" { + err = tx.Model(models.Deposit{}). + Where("id=?", deposit.Id). + Update("status", enums.MessageStatusValid).Error + } else { + err = tx.Model(models.Deposit{}). + Where("id=?", deposit.Id). + Update("btc_from_aa_address", depositAddress). + Update("status", enums.MessageStatusValid).Error + } + if err != nil { + l.logger.Errorf("update deposit failed: %s", err.Error()) + return err + } + return nil + }) + if err != nil { + l.logger.Errorf("error: %s\n", err) + return err + } + return nil +} diff --git a/listener/internal/serves/listener/ethereum/ethereum.go b/listener/internal/serves/listener/ethereum/ethereum.go new file mode 100644 index 00000000..7f6f633e --- /dev/null +++ b/listener/internal/serves/listener/ethereum/ethereum.go @@ -0,0 +1,483 @@ +package ethereum + +import ( + "bsquared.network/b2-message-channel-listener/internal/config" + "bsquared.network/b2-message-channel-listener/internal/enums" + "bsquared.network/b2-message-channel-listener/internal/models" + "bsquared.network/b2-message-channel-listener/internal/utils/ethereum/event" + "bsquared.network/b2-message-channel-listener/internal/utils/ethereum/event/message" + "bsquared.network/b2-message-channel-listener/internal/utils/log" + "context" + "fmt" + "github.com/ethereum/go-ethereum" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/pkg/errors" + "gorm.io/gorm" + "math/big" + "strings" + "sync" + "time" +) + +type EthereumListener struct { + config config.Blockchain + rpc *ethclient.Client + db *gorm.DB + logger *log.Logger + latestBlock int64 +} + +func NewListener(logConfig config.LogConfig, config config.Blockchain, rpc *ethclient.Client, db *gorm.DB) *EthereumListener { + return &EthereumListener{ + config: config, + rpc: rpc, + db: db, + logger: log.NewLogger(config.Name, logConfig.Level), + } +} + +func (l *EthereumListener) Name() string { + return l.config.Name +} + +func (l *EthereumListener) Start() { + go l.syncLastBlock() + go l.syncTask() + go l.handEvent() + go l.confirm() +} + +func (l *EthereumListener) syncLastBlock() { + for { + duration := time.Millisecond * time.Duration(l.config.BlockInterval) + latest, err := l.rpc.BlockNumber(context.Background()) + if err != nil { + l.logger.Errorf("sync latest block error: %s", err.Error()) + time.Sleep(duration) + continue + } + l.latestBlock = int64(latest) + l.logger.Infof("sync latest block: %d", l.latestBlock) + time.Sleep(duration) + } +} + +func (l *EthereumListener) syncTask() { + for { + duration := time.Millisecond * time.Duration(l.config.BlockInterval) * 10 + var tasks []models.SyncTask + err := l.db.Where("`chain_type`=? AND chain_id=? AND status=?", enums.ChainTypeEVM, l.config.ChainId, enums.TaskStatusPending).Limit(20).Find(&tasks).Error + if err != nil { + l.logger.Errorf("task list error: %s\n", err) + time.Sleep(duration) + continue + } + if len(tasks) == 0 { + l.logger.Info("task list is empty") + time.Sleep(duration) + continue + } + wg := sync.WaitGroup{} + for _, task := range tasks { + wg.Add(1) + go func(take models.SyncTask, wg *sync.WaitGroup) { + defer wg.Done() + err := l.handleTask(take) + if err != nil { + l.logger.Errorf("handle task error: %s", err.Error()) + } + }(task, &wg) + + } + wg.Wait() + } +} + +func (l *EthereumListener) handleTask(task models.SyncTask) error { + start := task.LatestBlock + if task.StartBlock > start { + start = task.StartBlock + } + + if task.EndBlock > 0 && start > task.EndBlock { + task.Status = enums.TaskStatusDone + l.db.Save(&task) + return nil + } + end := start + if task.HandleNum > 0 { + end = start + task.HandleNum - 1 + } + if task.EndBlock > 0 && end > task.EndBlock { + end = task.EndBlock + } + if end > l.latestBlock { + end = l.latestBlock + } + if start > end { + return nil + } + + //Contracts := strings.Split(task.Contracts, ",") + //if len(Contracts) == 0 { + // //Contracts = l.GetContracts() + // //log.Infof("[Handler.SyncTask] Contracts invalid") + // ////task.UpdateTime = time.Now() + // //task.Status = models.SyncTaskInvalid + // //ctx.Db.Save(&task) + // //return nil + //} + + logs, err := l.rpc.FilterLogs(context.Background(), ethereum.FilterQuery{ + FromBlock: big.NewInt(start), + ToBlock: big.NewInt(end), + Topics: [][]common.Hash{ + { + common.BytesToHash(message.MessageCallHash), + common.BytesToHash(message.MessageSendHash), + }, + }, + Addresses: []common.Address{ + common.HexToAddress(l.config.ListenAddress), + }, + }) + l.logger.Infof(" start: %d, end: %d\n", start, end) + if err != nil { + l.logger.Errorf("[Handler.SyncTask] FilterLogs error: %v", err) + return errors.WithStack(err) + } + + events, err := l.LogsToEvents(logs) + if err != nil { + l.logger.Errorf("[Handler.SyncTask] LogsToEvents error: %v", err) + return errors.WithStack(err) + } + BatchCreateEvents := make([]*models.SyncEvent, 0) + BatchUpdateEventIds := make([]int64, 0) + for _, event := range events { + var one models.SyncEvent + err = l.db.Select("id").Where("block_number=? AND block_log_indexed=? AND tx_hash=? AND event_hash=?", + event.BlockNumber, event.BlockLogIndexed, event.TxHash, event.EventHash).First(&one).Error + if err != nil && err != gorm.ErrRecordNotFound { + l.logger.Errorf("[Handler.SyncTask] Get event err: %s\n", err) + return errors.WithStack(err) + } else if err == gorm.ErrRecordNotFound { + BatchCreateEvents = append(BatchCreateEvents, event) + } else { + BatchUpdateEventIds = append(BatchUpdateEventIds, one.Id) + } + } + + err = l.db.Transaction(func(tx *gorm.DB) error { + if len(BatchCreateEvents) > 0 { + err = tx.CreateInBatches(&BatchCreateEvents, 100).Error + if err != nil { + l.logger.Errorf("[Handler.SyncEvent]Create SyncEvent err: %s\n", err) + return errors.WithStack(err) + } + } + if len(BatchUpdateEventIds) > 0 { + err = tx.Model(models.SyncEvent{}). + Where("id in ?", BatchUpdateEventIds). + Update("status", models.EventPending).Error + if err != nil { + l.logger.Errorf("[Handler.SyncEvent]Update SyncEvent err: %s\n,", err) + return errors.WithStack(err) + } + } + task.LatestBlock = end + 1 + err = tx.Save(&task).Error + if err != nil { + l.logger.Errorf("[Handler.SyncEvent]Update SyncTask err: %s\n,", err) + return errors.WithStack(err) + } + return nil + }) + if err != nil { + l.logger.Errorf("[Handler.SyncEvent]Update SyncTask err: %s\n,", err) + return errors.WithStack(err) + } + return nil +} + +func (l *EthereumListener) handEvent() { + duration := time.Millisecond * time.Duration(l.config.BlockInterval) * 10 + for { + var events []models.SyncEvent + err := l.db.Model(models.SyncEvent{}).Where("`chain_id`=? AND `event_hash` in ? AND `status`=?", + l.config.ChainId, []string{ + common.BytesToHash(message.MessageCallHash).Hex(), + common.BytesToHash(message.MessageSendHash).Hex(), + }, models.EventPending). + Limit(500).Find(&events).Error + if err != nil { + l.logger.Errorf("[Handler.SyncEvent] err: %s\n", err) + time.Sleep(duration) + continue + } + if len(events) == 0 { + l.logger.Errorf("[Handler.SyncEvent] no event\n") + time.Sleep(duration) + continue + } + valids := make([]int64, 0) + invalids := make([]int64, 0) + messages := make([]models.Message, 0) + handles := make(map[string]bool) + + var Type enums.MessageType + var FromChainId int64 + var FromSender string + var FromId string + var ToChainId int64 + var ToContractAddress string + var ToBytes string + var status enums.MessageStatus + + for _, event := range events { + key := fmt.Sprintf("%s#%d", event.TxHash, event.BlockLogIndexed) + if handles[key] { + invalids = append(invalids, event.Id) + continue + } + + if event.EventName == message.MessageCallName { + var messageCall message.MessageCall + err := (&messageCall).ToObj(event.Data) + if err != nil { + l.logger.Errorf("to obj err: %s\n", err.Error()) + time.Sleep(duration) + continue + } + FromChainId = messageCall.FromChainId + FromSender = messageCall.FromSender + FromId = common.BytesToHash(messageCall.FromId.BigInt().Bytes()).Hex() + ToChainId = messageCall.ToChainId + ToContractAddress = messageCall.ContractAddress + ToBytes = messageCall.Bytes + Type = enums.MessageTypeCall + status = enums.MessageStatusValidating + } else if event.EventName == message.MessageSendName { + var messageSend message.MessageSend + err := (&messageSend).ToObj(event.Data) + if err != nil { + l.logger.Errorf("event to data err: %v, data: %v\n", err, event) + continue + } + FromChainId = messageSend.FromChainId + FromSender = messageSend.FromSender + FromId = common.BytesToHash(messageSend.FromId.BigInt().Bytes()).Hex() + ToChainId = messageSend.ToChainId + ToContractAddress = messageSend.ContractAddress + ToBytes = messageSend.Bytes + Type = enums.MessageTypeSend + status = enums.MessageStatusPending + } + + var message models.Message + err = l.db.Where("`tx_hash`=? AND `log_index`=?", event.TxHash, event.BlockLogIndexed).First(&message).Error + if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) { + l.logger.Errorf("query message err: %v, data: %v\n", err, event) + time.Sleep(duration) + continue + } else if errors.Is(err, gorm.ErrRecordNotFound) { + handles[key] = true + message = models.Message{ + ChainId: event.ChainId, + Type: Type, + FromChainId: FromChainId, + FromSender: FromSender, + FromContractAddress: event.ContractAddress, + FromId: FromId, + ToChainId: ToChainId, + ToContractAddress: ToContractAddress, + ToBytes: ToBytes, + Signatures: "[]", + Status: status, + Blockchain: models.Blockchain{ + EventId: event.Id, + BlockTime: event.BlockTime, + BlockNumber: event.BlockNumber, + LogIndex: event.BlockLogIndexed, + TxHash: event.TxHash, + }, + } + messages = append(messages, message) + valids = append(valids, event.Id) + } else { + invalids = append(invalids, event.Id) + } + + } + err = l.db.Transaction(func(tx *gorm.DB) error { + if len(valids) > 0 { + err = tx.Model(models.SyncEvent{}).Where("id in ?", valids).Update("status", models.EventValid).Error + if err != nil { + l.logger.Errorf("update valid Event err: %v, data: %v\n", err, valids) + return err + } + } + if len(invalids) > 0 { + err = tx.Model(models.SyncEvent{}).Where("id in ?", invalids).Update("status", models.EventInvalid).Error + if err != nil { + l.logger.Errorf("update invalid Event err: %v, data: %v\n", err, invalids) + return err + } + } + if len(messages) > 0 { + err = tx.CreateInBatches(messages, 100).Error + if err != nil { + l.logger.Errorf("create messages err: %v, data: %v\n", err, messages) + return err + } + } + return nil + }) + if err != nil { + l.logger.Errorf("update valid Event err: %v\n", err) + time.Sleep(duration) + } + } +} + +func (l *EthereumListener) LogsToEvents(logs []types.Log) ([]*models.SyncEvent, error) { + var events []*models.SyncEvent + blockTimes := make(map[int64]int64) + for _, vlog := range logs { + eventHash := event.TopicToHash(vlog, 0) + contractAddress := vlog.Address + + var eventName string + var data string + if eventHash == common.BytesToHash(message.MessageCallHash) { + eventName = message.MessageCallName + e := &message.MessageCall{} + _data, err := e.Data(vlog) + if err != nil { + l.logger.Errorf("parse message call err: %v, data: %v\n", err, vlog) + return nil, err + } + data = _data + } else if eventHash == common.BytesToHash(message.MessageSendHash) { + eventName = message.MessageSendName + e := &message.MessageSend{} + _data, err := e.Data(vlog) + if err != nil { + l.logger.Errorf("parse message send err: %v, data: %v\n", err, vlog) + return nil, err + } + data = _data + } + blockTime := blockTimes[int64(vlog.BlockNumber)] + if blockTime == 0 { + // blockJson, err := rpc2.HttpPostJson("", l.Blockchain.RpcUrl, "{\"jsonrpc\":\"2.0\",\"method\":\"eth_getBlockByNumber\",\"params\":[\""+fmt.Sprintf("0x%X", vlog.BlockNumber)+"\", true],\"id\":1}") + // if err != nil { + // log.Errorf("[Handler.SyncBlock] Syncing block by number error: %s\n", errors.WithStack(err)) + // time.Sleep(3 * time.Second) + // continue + // } + // block := rpc2.ParseJsonBlock(string(blockJson)) + // // + //block, err := l.rpc.BlockByNumber(context.Background(), big.NewInt(int64(vlog.BlockNumber))) + //if err != nil { + // l.logger.Errorf("Syncing block by number error: %s\n", errors.WithStack(err)) + // return nil, errors.WithStack(err) + //} + //blockTime = int64(block.Time()) + //blockTimes[int64(vlog.BlockNumber)] = blockTime + } + events = append(events, &models.SyncEvent{ + ChainId: l.config.ChainId, + BlockTime: blockTime, + BlockNumber: int64(vlog.BlockNumber), + BlockHash: vlog.BlockHash.Hex(), + BlockLogIndexed: int64(vlog.Index), + TxIndex: int64(vlog.TxIndex), + TxHash: vlog.TxHash.Hex(), + EventName: eventName, + EventHash: eventHash.Hex(), + ContractAddress: strings.ToLower(contractAddress.Hex()), + Data: data, + Status: models.EventPending, + }) + } + return events, nil +} + +func (l *EthereumListener) confirm() { + duration := time.Millisecond * time.Duration(l.config.BlockInterval) * 10 + for { + list, err := l.pendingSendMessage(10) + if err != nil { + l.logger.Errorf("Get pending send message error: %s\n", err) + time.Sleep(duration) + continue + } + if len(list) == 0 { + time.Sleep(duration) + continue + } + var wg sync.WaitGroup + for _, message := range list { + wg.Add(1) + go func(_wg *sync.WaitGroup, message models.Message) { + defer _wg.Done() + err = l.confirmMessage(message) + if err != nil { + l.logger.Errorf("") + } + }(&wg, message) + } + wg.Wait() + } +} + +func (l *EthereumListener) confirmMessage(message models.Message) error { + var callMessage models.Message + err := l.db.Where("type=? AND from_chain_id=? AND from_id=?", enums.MessageTypeCall, message.FromChainId, message.FromId).First(&callMessage).Error + if err != nil { + return err + } + err = l.db.Transaction(func(tx *gorm.DB) error { + err := tx.Model(models.Message{}).Where("id=?", + callMessage.Id). + Update("status", enums.MessageStatusValid).Error + if err != nil { + return err + } + err = tx.Model(models.Message{}).Where("id=? AND status=?", message.Id, message.Status). + Update("status", enums.MessageStatusValid).Error + if err != nil { + return err + } + err = tx.Model(models.Signature{}).Where("chain_id=? AND refer_id=?", message.ChainId, message.FromId). + Updates(map[string]interface{}{ + "status": enums.SignatureStatusSuccess, + "event_id": message.EventId, + "block_time": message.BlockTime, + "block_number": message.BlockNumber, + "log_index": message.LogIndex, + "tx_hash": message.TxHash, + }).Error + if err != nil { + return err + } + return nil + }) + if err != nil { + return err + } + return nil +} + +func (l *EthereumListener) pendingSendMessage(limit int) ([]models.Message, error) { + var list []models.Message + err := l.db.Where("`to_chain_id`=? AND `type`=? AND status=?", l.config.ChainId, enums.MessageTypeSend, enums.MessageStatusPending).Limit(limit).Find(&list).Error + if err != nil { + return nil, err + } + return list, nil +} diff --git a/listener/internal/serves/validator/validator.go b/listener/internal/serves/validator/validator.go new file mode 100644 index 00000000..958abb09 --- /dev/null +++ b/listener/internal/serves/validator/validator.go @@ -0,0 +1,111 @@ +package validator + +import ( + "bsquared.network/b2-message-channel-listener/internal/config" + "bsquared.network/b2-message-channel-listener/internal/enums" + "bsquared.network/b2-message-channel-listener/internal/models" + "bsquared.network/b2-message-channel-listener/internal/utils/ethereum/message" + "bsquared.network/b2-message-channel-listener/internal/utils/log" + "encoding/json" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/pkg/errors" + "gorm.io/gorm" + "sync" + "time" +) + +type Validator struct { + config config.Blockchain + db *gorm.DB + rpc *ethclient.Client + key string + logger *log.Logger +} + +func NewValidator(key string, logConfig config.LogConfig, config config.Blockchain, db *gorm.DB, rpc *ethclient.Client) *Validator { + return &Validator{ + config: config, + db: db, + rpc: rpc, + key: key, + logger: log.NewLogger(config.Name, logConfig.Level), + } +} + +func (v *Validator) Start() { + go v.validate() +} + +func (v *Validator) validate() { + duration := time.Millisecond * time.Duration(v.config.BlockInterval) + for { + list, err := v.validatingCallMessage(10) + if err != nil { + v.logger.Errorf("Get pending call message error: %v\n", err) + time.Sleep(duration) + continue + } + if len(list) == 0 { + v.logger.Error("Get pending call message list length is 0\n") + time.Sleep(duration) + continue + } + + var wg sync.WaitGroup + for _, message := range list { + wg.Add(1) + go func(_wg *sync.WaitGroup, message models.Message) { + defer _wg.Done() + err = v.validateMessage(message) + if err != nil { + v.logger.Errorf("Validate message error: %v\n", err) + } + }(&wg, message) + } + wg.Wait() + } +} + +func (v *Validator) validateMessage(msg models.Message) error { + var signatures []string + //var ValidatorMap map[string]string + //for _, validatorKey := range ValidatorMap { + _key, err := crypto.ToECDSA(common.FromHex(v.key)) + if err != nil { + v.logger.Errorf("ToECDSA error: %v\n", err) + return errors.WithStack(err) + } + signature, err := message.SignMessageSend(v.config.ChainId, v.config.ListenAddress, msg.FromChainId, common.HexToHash(msg.FromId).Big(), msg.FromSender, msg.ToChainId, msg.ToContractAddress, msg.ToBytes, _key) + if err != nil { + v.logger.Errorf("Sign message error: %v\n", err) + return errors.WithStack(err) + } + signatures = append(signatures, signature) + //} + + _signatures, err := json.Marshal(&signatures) + if err != nil { + v.logger.Errorf("Marshal signatures error: %v\n", err) + return errors.WithStack(err) + } + + err = v.db.Model(models.Message{}).Where("`id`=? AND `status`=?", msg.Id, enums.MessageStatusValidating). + Update("signatures", string(_signatures)). + Update("status", enums.MessageStatusPending).Error + if err != nil { + v.logger.Errorf("Update message error: %v\n", err) + return errors.WithStack(err) + } + return nil +} + +func (v *Validator) validatingCallMessage(limit int) ([]models.Message, error) { + var list []models.Message + err := v.db.Where("`to_chain_id`=? AND `type`=? AND `status`=?", v.config.ChainId, enums.MessageTypeCall, enums.MessageStatusValidating).Limit(limit).Find(&list).Error + if err != nil { + return nil, errors.WithStack(err) + } + return list, nil +} diff --git a/serv/internal/types/bitcoin_indexer.go b/listener/internal/types/bitcoin.go similarity index 77% rename from serv/internal/types/bitcoin_indexer.go rename to listener/internal/types/bitcoin.go index 4edbe21f..aeb2a8ef 100644 --- a/serv/internal/types/bitcoin_indexer.go +++ b/listener/internal/types/bitcoin.go @@ -3,22 +3,18 @@ package types import ( "bytes" "encoding/hex" - - "github.com/btcsuite/btcd/wire" "github.com/ethereum/go-ethereum/common" ) -// BITCOINTxIndexer defines the interface of custom bitcoin tx indexer. -type BITCOINTxIndexer interface { - // ParseBlock parse bitcoin block tx - ParseBlock(int64, int64) ([]*BitcoinTxParseResult, *wire.BlockHeader, error) - // LatestBlock get latest block height in the longest block chain. - LatestBlock() (int64, error) - // CheckConfirmations get tx detail info - CheckConfirmations(txHash string) error - // ParseTx parse bitcoin tx - ParseTx(txHash string) (*BitcoinTxParseResult, error) -} +const ( + BitcoinFromTypeBtc = 0 + BitcoinFromTypeEvm = 1 +) + +const ( + BitcoinToTypeNormal = 0 + BitcoinToTypeNullData = 1 +) type BitcoinTxParseResult struct { // from is l2 user address, by parse bitcoin get the address @@ -37,22 +33,12 @@ type BitcoinTxParseResult struct { Tos []BitcoinTo } -const ( - BitcoinFromTypeBtc = 0 - BitcoinFromTypeEvm = 1 -) - type BitcoinFrom struct { Address string Type int EvmAddress string } -const ( - BitcoinToTypeNormal = 0 - BitcoinToTypeNullData = 1 -) - type BitcoinTo struct { Address string Value int64 diff --git a/serv/internal/utils/aa/aa.go b/listener/internal/utils/aa/aa.go similarity index 95% rename from serv/internal/utils/aa/aa.go rename to listener/internal/utils/aa/aa.go index 1ad6c2e2..a1fe6a85 100644 --- a/serv/internal/utils/aa/aa.go +++ b/listener/internal/utils/aa/aa.go @@ -1,7 +1,7 @@ package aa import ( - "bsquared.network/b2-message-channel-serv/internal/utils/particle" + "bsquared.network/b2-message-channel-listener/internal/utils/particle" "encoding/json" "fmt" "io/ioutil" diff --git a/serv/internal/event/vlog.go b/listener/internal/utils/ethereum/event/event.go similarity index 100% rename from serv/internal/event/vlog.go rename to listener/internal/utils/ethereum/event/event.go diff --git a/serv/internal/event/message/call.go b/listener/internal/utils/ethereum/event/message/call.go similarity index 94% rename from serv/internal/event/message/call.go rename to listener/internal/utils/ethereum/event/message/call.go index 9d2f717c..70cbcd18 100644 --- a/serv/internal/event/message/call.go +++ b/listener/internal/utils/ethereum/event/message/call.go @@ -1,7 +1,7 @@ package message import ( - "bsquared.network/b2-message-channel-serv/internal/event" + "bsquared.network/b2-message-channel-listener/internal/utils/ethereum/event" "encoding/json" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" diff --git a/serv/internal/event/message/send.go b/listener/internal/utils/ethereum/event/message/send.go similarity index 94% rename from serv/internal/event/message/send.go rename to listener/internal/utils/ethereum/event/message/send.go index 7c2b5ea9..33c6bb91 100644 --- a/serv/internal/event/message/send.go +++ b/listener/internal/utils/ethereum/event/message/send.go @@ -1,7 +1,7 @@ package message import ( - "bsquared.network/b2-message-channel-serv/internal/event" + "bsquared.network/b2-message-channel-listener/internal/utils/ethereum/event" "encoding/json" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" diff --git a/listener/internal/utils/ethereum/message/message.go b/listener/internal/utils/ethereum/message/message.go new file mode 100644 index 00000000..8abfea9f --- /dev/null +++ b/listener/internal/utils/ethereum/message/message.go @@ -0,0 +1,211 @@ +package message + +import ( + "crypto/ecdsa" + "encoding/json" + "fmt" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/signer/core/apitypes" + "github.com/pkg/errors" + "github.com/shopspring/decimal" + "github.com/storyicon/sigverify" + "math/big" + "strings" +) + +const MessageSendTypedData = `{ + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "version", + "type": "string" + }, + { + "name": "chainId", + "type": "uint256" + }, + { + "name": "verifyingContract", + "type": "address" + } + ], + "Send": [ + { + "name": "from_chain_id", + "type": "uint256" + }, + { + "name": "from_id", + "type": "uint256" + }, + { + "name": "from_sender", + "type": "address" + }, + { + "name": "to_chain_id", + "type": "uint256" + }, + { + "name": "contract_address", + "type": "address" + }, + { + "name": "data", + "type": "bytes" + } + ] + }, + "domain": { + "name": "B2MessageBridge", + "version": "1", + "chainId": "%d", + "verifyingContract": "%s" + }, + "primaryType": "Send", + "message": { + "from_chain_id": "%d", + "from_id": "%s", + "from_sender": "%s", + "to_chain_id": "%d", + "contract_address": "%s", + "data": "%s" + } +}` + +func SignMessageSend(chainId int64, messageContract string, fromChainId int64, fromId *big.Int, fromSender string, toChainId int64, contractAddress string, data string, key *ecdsa.PrivateKey) (string, error) { + _data := fmt.Sprintf(MessageSendTypedData, chainId, messageContract, fromChainId, fromId.Text(10), fromSender, toChainId, contractAddress, data) + fmt.Println("_data", _data) + var typedData apitypes.TypedData + if err := json.Unmarshal([]byte(_data), &typedData); err != nil { + return "", errors.WithStack(err) + } + msgHash, originHash, err := sigverify.HashTypedData(typedData) + fmt.Println("msgHash", common.Bytes2Hex(msgHash)) + fmt.Println("originHash", common.Bytes2Hex(originHash)) + if err != nil { + return "", errors.WithStack(err) + } + sig, err := crypto.Sign(originHash, key) + if err != nil { + return "", errors.WithStack(err) + } + if sig[64] == 0 { + sig[64] = 27 + } else if sig[64] == 1 { + sig[64] = 28 + } + return "0x" + common.Bytes2Hex(sig), nil +} + +func VerifyMessageSend(chainId int64, messageContract string, fromChainId int64, fromId *big.Int, fromSender string, toChainId int64, contractAddress string, data string, signer, signature string) (bool, error) { + if !strings.HasPrefix(signature, "0x") { + signature = "0x" + signature + } + _signature, err := hexutil.Decode(signature) + if err != nil { + return false, errors.WithStack(err) + } + if _signature[64] == 27 || _signature[64] == 28 { + _signature[64] = _signature[64] - 27 + } + //fmt.Println("_signature:", hexutil.Encode(_signature)) + _data := fmt.Sprintf(MessageSendTypedData, chainId, messageContract, fromChainId, fromId.Text(10), fromSender, toChainId, contractAddress, data) + //fmt.Println("data:", data) + var typedData apitypes.TypedData + if err := json.Unmarshal([]byte(_data), &typedData); err != nil { + return false, errors.WithStack(err) + } + verify, err := sigverify.VerifyTypedDataSignatureEx( + common.HexToAddress(signer), + typedData, + _signature, + ) + if err != nil || !verify { + fmt.Errorf("Verify signature error: %v\n", err) + return false, errors.New("Verify signature failed") + } + return true, nil +} + +func Send(fromChainId int64, fromId *big.Int, fromSender string, contractAddress string, toBytes string, signatures []string) []byte { + // function send(uint256 from_chain_id, uint256 from_id, address from_sender, address contract_address, bytes calldata data, bytes[] calldata signatures) external + Method := crypto.Keccak256([]byte("send(uint256,uint256,address,address,bytes,bytes[])"))[:4] + FromChainId := common.BytesToHash(big.NewInt(fromChainId).Bytes()).Bytes() + FromId := common.BytesToHash(fromId.Bytes()).Bytes() + FromSender := common.BytesToHash(common.HexToAddress(fromSender).Bytes()).Bytes() + ContractAddress := common.BytesToHash(common.HexToAddress(contractAddress).Bytes()).Bytes() + + ToBytes := common.FromHex(toBytes) + ToBytesDataOffset := common.BytesToHash(big.NewInt(192).Bytes()).Bytes() + ToBytesDataLength := common.BytesToHash(big.NewInt(int64(len(ToBytes))).Bytes()).Bytes() + + if len(ToBytes)%32 > 0 { + ToBytes = append(ToBytes, make([]byte, 32-len(ToBytes)%32)...) + } + + SignaturesDataOffset := common.BytesToHash(big.NewInt(int64(224 + len(ToBytes))).Bytes()).Bytes() + SignaturesDataLength := common.BytesToHash(big.NewInt(int64(len(signatures))).Bytes()).Bytes() + + var streamOffsets []byte + var streamData []byte + streamIndex := int64(32 * len(signatures)) + for _, _signature := range signatures { + signatureDataOffset := common.BytesToHash(big.NewInt(streamIndex).Bytes()).Bytes() + streamOffsets = append(streamOffsets, signatureDataOffset...) + + signature := common.FromHex(_signature) + signatureDataLength := common.BytesToHash(big.NewInt(int64(len(signature))).Bytes()).Bytes() + streamData = append(streamData, signatureDataLength...) + if len(signature)%32 > 0 { + signature = append(signature, make([]byte, 32-len(signature)%32)...) + } + streamData = append(streamData, signature...) + streamIndex = int64(32*len(signatures) + len(streamData)) + } + + var stream []byte + stream = append(stream, Method...) + stream = append(stream, FromChainId...) + stream = append(stream, FromId...) + stream = append(stream, FromSender...) + stream = append(stream, ContractAddress...) + stream = append(stream, ToBytesDataOffset...) + stream = append(stream, SignaturesDataOffset...) + stream = append(stream, ToBytesDataLength...) + stream = append(stream, ToBytes...) + stream = append(stream, SignaturesDataLength...) + stream = append(stream, streamOffsets...) + stream = append(stream, streamData...) + return stream +} + +func EncodeSendData(txId string, fromAddress string, toAddress string, amount decimal.Decimal) []byte { + TxId := common.HexToHash(txId).Bytes() + + ToAddress := common.BytesToHash(common.HexToAddress(toAddress).Bytes()).Bytes() + Amount := common.BytesToHash(amount.BigInt().Bytes()).Bytes() + + FromAddress := []byte(fromAddress) + FromAddressOffset := common.BytesToHash(big.NewInt(128).Bytes()).Bytes() + FromAddressLength := common.BytesToHash(big.NewInt(int64(len(FromAddress))).Bytes()).Bytes() + if len(FromAddress)%32 > 0 { + FromAddress = append(FromAddress, make([]byte, 32-len(FromAddress)%32)...) + } + + var stream []byte + stream = append(stream, TxId...) + stream = append(stream, FromAddressOffset...) + stream = append(stream, ToAddress...) + stream = append(stream, Amount...) + stream = append(stream, FromAddressLength...) + stream = append(stream, FromAddress...) + + return stream +} diff --git a/listener/internal/utils/log/log.go b/listener/internal/utils/log/log.go new file mode 100644 index 00000000..08020b61 --- /dev/null +++ b/listener/internal/utils/log/log.go @@ -0,0 +1,60 @@ +package log + +import ( + log "github.com/sirupsen/logrus" + "os" +) + +type Logger struct { + Name string +} + +func NewLogger(name string, logLevel uint32) *Logger { + log.SetFormatter(&log.JSONFormatter{}) + log.SetOutput(os.Stdout) + + log.SetLevel(log.Level(logLevel)) + return &Logger{ + Name: name, + } +} + +func (l *Logger) Debug(args ...interface{}) { + log.WithField("name", l.Name).Debug(args...) +} + +func (l *Logger) Warn(args ...interface{}) { + log.WithField("name", l.Name).Warn(args...) +} + +func (l *Logger) Info(args ...interface{}) { + log.WithField("name", l.Name).Info(args...) +} + +func (l *Logger) Error(args ...interface{}) { + log.WithField("name", l.Name).Error(args...) +} + +func (l *Logger) Panic(args ...interface{}) { + log.WithField("name", l.Name).Panic(args...) +} + +func (l *Logger) Debugf(format string, args ...interface{}) { + log.WithField("name", l.Name).Debugf(format, args...) +} + +func (l *Logger) Warnf(format string, args ...interface{}) { + log.WithField("name", l.Name).Warnf(format, args...) +} + +func (l *Logger) Infof(format string, args ...interface{}) { + log.WithField("name", l.Name).Infof(format, args...) +} + +func (l *Logger) Errorf(format string, args ...interface{}) { + log.WithField("name", l.Name).Errorf(format, args...) +} + +func (l *Logger) Panicf(format string, args ...interface{}) { + log.WithField("name", l.Name).Panicf(format, args...) +} diff --git a/serv/internal/utils/particle/particle.go b/listener/internal/utils/particle/particle.go similarity index 100% rename from serv/internal/utils/particle/particle.go rename to listener/internal/utils/particle/particle.go diff --git a/serv/README.md b/serv/README.md deleted file mode 100644 index d1e257d1..00000000 --- a/serv/README.md +++ /dev/null @@ -1,29 +0,0 @@ -# serv - -``` -APP_SERVER_PORT=8085 -APP_SERVER_LOGLEVEL=6 - -APP_DATABASE_USERNAME=root -APP_DATABASE_PASSWORD=2tRY$q5Ec&%Q -APP_DATABASE_HOST=sg-cdb-7ykkm5v1.sql.tencentcdb.com -APP_DATABASE_PORT=63938 -APP_DATABASE_DBNAME=b2_message -APP_DATABASE_LOGLEVEL=4 - -APP_REDIS_HOST=127.0.0.1 -APP_REDIS_PORT=6379 -APP_REDIS_PASSWORD="passw0rd" -APP_REDIS_DB="0" -APP_REDIS_INSECURESKIP=false -APP_REDIS_ISCLUSTERMODE=false -APP_REDIS_CLUSTERADDRESSES="" - -APP_PARTICLE_URL=https://rpc.particle.network/evm-chain -APP_PARTICLE_CHAINID=1123 -APP_PARTICLE_PROJECTUUID=34c6b829-5b89-44e8-90a9-6d982787b9c9 -APP_PARTICLE_PROJECTKEY=c6Z44Ml4TQeNhctvwYgdSv6DBzfjf6t6CB0JDscR -APP_PARTICLE_AAPUBKEYAPI=https://bridge-mainnet-aa.bsquared.network - -APP_BLOCKCHAINS='[{"ChainId":1,"Rollback":false,"RpcUrl":"indulgent-floral-bird.btc.quiknode.pro/1df147114bdfd6f119d1a5eef706c91b3710ca6e","InitBlockNumber":0,"InitBlockHash":"","MessageAddress":"","Events":"","Senders":"","Validators":"","BlockInterval":10000,"ToChainId":1123,"ToContractAddress":"0xD90832B1a8f4Fa6F55ea36589b5439cc0E6CA46C","ListenBtcAddress":"131fpYjELat58RVzPp2A9Bo8oNuKiP4vxg","BtcUser":"bnan","BtcPass":"bnan2021"},{"ChainId":1123,"Rollback":false,"RpcUrl":"https://testnet-rpc.bsquared.network","InitBlockNumber":4577994,"InitBlockHash":"0x25fc3eee09cdba915458cf3c5a836e06eb9835596426347f2a5b0e70b0a58cf8","MessageAddress":"0xc7441Ac47596D1356fcc70062dA0462FcA98E14e","Events":"0x599c34a8d0b3638870afcfe3d7d8125602721889a7535cda986ea656e63fc38c,0x5849ae3f4bc77f0ebd2d6db4ff282f91f2191d3df4493e63176c2ed22fb81852","Senders":"67f20dc3b0842117c049b292dd88794b3321c95a1b607e735be88c34327420ba","Validators":"67f20dc3b0842117c049b292dd88794b3321c95a1b607e735be88c34327420ba","BlockInterval":1000,"ToChainId":0,"ToContractAddress":"","ListenBtcAddress":"","BtcUser":"","BtcPass":""},{"ChainId":421614,"Rollback":false,"RpcUrl":"https://cosmological-green-spring.arbitrum-sepolia.quiknode.pro/e41990a3263b68eecb26a88d3b3122185798613e/","InitBlockNumber":68116018,"InitBlockHash":"0xf9e7820aca608ccb6131b56ade99617bca6e96b91cca80b92e026cd26cc91714","MessageAddress":"0x2A82058E46151E337Baba56620133FC39BD5B71F","Events":"0x599c34a8d0b3638870afcfe3d7d8125602721889a7535cda986ea656e63fc38c,0x5849ae3f4bc77f0ebd2d6db4ff282f91f2191d3df4493e63176c2ed22fb81852","Senders":"0x7990759362da82e88493fd64d058c5e011253ceb45902986590ef4acb0e97706","Validators":"0x7990759362da82e88493fd64d058c5e011253ceb45902986590ef4acb0e97706","BlockInterval":100,"ToChainId":0,"ToContractAddress":"","ListenBtcAddress":"","BtcUser":"","BtcPass":""}]' -``` \ No newline at end of file diff --git a/serv/cmd/app/main.go b/serv/cmd/app/main.go deleted file mode 100644 index c2ae98a1..00000000 --- a/serv/cmd/app/main.go +++ /dev/null @@ -1,33 +0,0 @@ -package main - -import ( - "bsquared.network/b2-message-channel-serv/internal/boot" - "bsquared.network/b2-message-channel-serv/internal/config" - "bsquared.network/b2-message-channel-serv/internal/router" - "bsquared.network/b2-message-channel-serv/internal/validators" - "github.com/gin-gonic/gin/binding" - "github.com/go-playground/validator/v10" - "github.com/shopspring/decimal" -) - -func main() { - decimal.DivisionPrecision = 18 - cfg := config.LoadConfig() - config.InitLog(cfg.Server.LogLevel) - - if v, ok := binding.Validator.Engine().(*validator.Validate); ok { - validators.RegisterValidators(v) - } - - db := config.ConnectToDB(cfg) - cache := config.InitCache(cfg) - - initVal := boot.Init(db, cache, cfg) - - r := router.InitRoutes(initVal, cfg) - - err := r.Run(":" + cfg.Server.Port) - if err != nil { - return - } -} diff --git a/serv/cmd/listener/main.go b/serv/cmd/listener/main.go deleted file mode 100644 index 4b156202..00000000 --- a/serv/cmd/listener/main.go +++ /dev/null @@ -1,23 +0,0 @@ -package main - -import ( - "bsquared.network/b2-message-channel-serv/internal/config" - "bsquared.network/b2-message-channel-serv/internal/job" - "bsquared.network/b2-message-channel-serv/internal/validators" - "github.com/gin-gonic/gin/binding" - "github.com/go-playground/validator/v10" - "github.com/shopspring/decimal" -) - -func main() { - decimal.DivisionPrecision = 18 - cfg := config.LoadConfig() - config.InitLog(cfg.Server.LogLevel) - if v, ok := binding.Validator.Engine().(*validator.Validate); ok { - validators.RegisterValidators(v) - } - db := config.ConnectToDB(cfg) - cache := config.InitCache(cfg) - job.Run(db, cache, cfg) - select {} -} diff --git a/serv/cmd/test/main.go b/serv/cmd/test/main.go deleted file mode 100644 index af5d01be..00000000 --- a/serv/cmd/test/main.go +++ /dev/null @@ -1,42 +0,0 @@ -package main - -import ( - "fmt" - "github.com/ethereum/go-ethereum/common" -) - -func main() { - txId := "fee63a7c0cf184824ba4fb5ea0be625ac673ab0e97ecf5e386b6805ac6ab869e" - //fromAddress := "bc1q2uduc360s3s3jww4nwnzn3yhad7ry0ldjkfr79" - //toAddress := "0xeF9B26046a2392C956320200eE0818543aA96aB7" - //amount := decimal.New(1212, 0) - //data := message.EncodeSendData(txId, fromAddress, toAddress, amount) - //fmt.Println(hexutil.Encode(data)) - - //num := big.NewInt(0) - //num.SetBytes(hexutil.MustDecode(txId)) - //fmt.Println(num.Text(16)) - fmt.Println(common.HexToHash(txId)) - - // 0xfee63a7c0cf184824ba4fb5ea0be625ac673ab0e97ecf5e386b6805ac6ab869e0000000000000000000000000000000000000000000000000000000000000080000000000000000000000000ef9b26046a2392c956320200ee0818543aa96ab700000000000000000000000000000000000000000000000000000000000004bc000000000000000000000000000000000000000000000000000000000000002a626331713275647563333630733373336a7777346e776e7a6e3379686164377279306c646a6b6672373900000000000000000000000000000000000000000000 - // 0xfee63a7c0cf184824ba4fb5ea0be625ac673ab0e97ecf5e386b6805ac6ab869e0000000000000000000000000000000000000000000000000000000000000080000000000000000000000000ef9b26046a2392c956320200ee0818543aa96ab700000000000000000000000000000000000000000000000000000000000004bc000000000000000000000000000000000000000000000000000000000000002a626331713275647563333630733373336a7777346e776e7a6e3379686164377279306c646a6b6672373900000000000000000000000000000000000000000000 - //bclient, err := rpcclient.New(&rpcclient.ConnConfig{ - // Host: "129.226.198.246:8332", - // Host: "indulgent-floral-bird.btc.quiknode.pro/1df147114bdfd6f119d1a5eef706c91b3710ca6e", - // //Host: "divine-patient-meadow.btc-testnet.quiknode.pro/36ade4989e57ddd507d9790dec479606cbe8c0c6", - // User: "bnan", - // Pass: "bnan2021", - // HTTPPostMode: true, // Bitcoin core only supports HTTP POST mode - // DisableTLS: false, // Bitcoin core does not provide TLS by default - //}, nil) - //if err != nil { - // fmt.Println("new: ", err.Error()) - // return - //} - //ChainInfo, err := bclient.GetBlockCount() - //if err != nil { - // fmt.Println("get: ", err.Error()) - // return - //} - //fmt.Println("ChainInfo: ", ChainInfo) -} diff --git a/serv/config/config.yaml b/serv/config/config.yaml deleted file mode 100644 index 876c202d..00000000 --- a/serv/config/config.yaml +++ /dev/null @@ -1,61 +0,0 @@ -server: - port: 8085 - # 0: panic 1: fatal 2: error 3: warn 4: info 5: debug 6: trace - LogLevel: 6 - -database: - username: root - password: root - host: 127.0.0.1 - port: 3306 - DbName: b2_message - LogLevel: 4 # 1: Silent 2: Error 3: Warn 4: Info - -redis: - host: 127.0.0.1 - port: 6379 - password: "passw0rd" - db: "0" - InsecureSkip: false - IsClusterMode: false - ClusterAddresses: "" - - -Particle: - Url: https://rpc.particle.network/evm-chain - ChainId: 1123 - ProjectUuid: 1111 - ProjectKey: 1111 - AAPubKeyAPI: https://bridge-mainnet-aa.bsquared.network - -blockchain: - - ChainId: 1 - RpcUrl: indulgent-floral-bird.btc.quiknode.pro/1df147114bdfd6f119d1a5eef706c91b3710ca6e - BlockInterval: 10000 - ToChainId: 1123 - ToContractAddress: 0xD90832B1a8f4Fa6F55ea36589b5439cc0E6CA46C - ListenBtcAddress: 131fpYjELat58RVzPp2A9Bo8oNuKiP4vxg - BtcUser: bnan - BtcPass: bnan2021 - - ChainId: 1123 - Rollback: false - RpcUrl: https://testnet-rpc.bsquared.network - InitBlockNumber: 4577994 - InitBlockHash: 0x25fc3eee09cdba915458cf3c5a836e06eb9835596426347f2a5b0e70b0a58cf8 - MessageAddress: 0xc7441Ac47596D1356fcc70062dA0462FcA98E14e - Senders: 0x599c34a8d0b3638870afcfe3d7d8125602721889a7535cda986ea656e63fc38c - Validators: 0x599c34a8d0b3638870afcfe3d7d8125602721889a7535cda986ea656e63fc38c - BlockInterval: 1000 - # BusinessContract: 0x91171cf194a4B66Bd459Ada038397c7e890FB9D4 - Events: 0x599c34a8d0b3638870afcfe3d7d8125602721889a7535cda986ea656e63fc38c,0x5849ae3f4bc77f0ebd2d6db4ff282f91f2191d3df4493e63176c2ed22fb81852 - - ChainId: 421614 - Rollback: false - RpcUrl: https://cosmological-green-spring.arbitrum-sepolia.quiknode.pro/e41990a3263b68eecb26a88d3b3122185798613e/ - InitBlockNumber: 68116018 - InitBlockHash: 0xf9e7820aca608ccb6131b56ade99617bca6e96b91cca80b92e026cd26cc91714 - MessageAddress: 0x2A82058E46151E337Baba56620133FC39BD5B71F - Senders: 0x599c34a8d0b3638870afcfe3d7d8125602721889a7535cda986ea656e63fc38c - Validators: 0x599c34a8d0b3638870afcfe3d7d8125602721889a7535cda986ea656e63fc38c - BlockInterval: 100 - # BusinessContract: 0x8Ac2C830532d7203a12C4C32C0BE4d3d15917534 - Events: 0x599c34a8d0b3638870afcfe3d7d8125602721889a7535cda986ea656e63fc38c,0x5849ae3f4bc77f0ebd2d6db4ff282f91f2191d3df4493e63176c2ed22fb81852 \ No newline at end of file diff --git a/serv/docs/flow/invitation/invite-count.png b/serv/docs/flow/invitation/invite-count.png deleted file mode 100644 index 8dc4283b..00000000 Binary files a/serv/docs/flow/invitation/invite-count.png and /dev/null differ diff --git a/serv/docs/flow/invitation/invite-count.puml b/serv/docs/flow/invitation/invite-count.puml deleted file mode 100644 index a01e705e..00000000 --- a/serv/docs/flow/invitation/invite-count.puml +++ /dev/null @@ -1,16 +0,0 @@ -@startuml - -note right - 黄色表示有交互数据库的操作 - 红色表示跟keycloak服务有交互的操作 -end note -start -:解析、校验参数; -if (token无效?) then (yes) - :提示token失效; - stop -endif -#yellow:查询用户id在传参的数组中的邀请记录,并且以user_id分组,统计计数; -:返回结果数据; -stop -@enduml \ No newline at end of file diff --git a/serv/docs/flow/invitation/invite-trace.png b/serv/docs/flow/invitation/invite-trace.png deleted file mode 100644 index 898775d7..00000000 Binary files a/serv/docs/flow/invitation/invite-trace.png and /dev/null differ diff --git a/serv/docs/flow/invitation/invite-trace.puml b/serv/docs/flow/invitation/invite-trace.puml deleted file mode 100644 index 65d1fb03..00000000 --- a/serv/docs/flow/invitation/invite-trace.puml +++ /dev/null @@ -1,26 +0,0 @@ -@startuml - -note right - 黄色表示有交互数据库的操作 - 红色表示跟keycloak服务有交互的操作 -end note -start -:解析、校验参数; -if (token无效?) then (yes) - :提示token失效; - stop -endif -if (id不为空?) then (yes) - #yellow:通过uuid查询用户记录; -endif -if (username不为空?) then (yes) - #yellow:通过username查询用户记录; -endif -if (用户记录未找到?) then (yes) - :返回用户不存在错误; - stop -endif -#yellow:查询邀请记录表,注册用户id为用户记录uuid,深度 == depth; -:返回结果数据; -stop -@enduml \ No newline at end of file diff --git a/serv/docs/flow/invitation/ranking.png b/serv/docs/flow/invitation/ranking.png deleted file mode 100644 index 29b60b61..00000000 Binary files a/serv/docs/flow/invitation/ranking.png and /dev/null differ diff --git a/serv/docs/flow/invitation/ranking.puml b/serv/docs/flow/invitation/ranking.puml deleted file mode 100644 index 9f86902b..00000000 --- a/serv/docs/flow/invitation/ranking.puml +++ /dev/null @@ -1,17 +0,0 @@ -@startuml - -note right - 黄色表示有交互数据库的操作 - 红色表示跟keycloak服务有交互的操作 -end note -start -:解析、校验参数; -if (token无效?) then (yes) - :提示token失效; - stop -endif -#yellow:用户邀请记录表,基于邀请人ID分组,按照排序规则,查询count条记录; -:返回结果数据; -stop - -@enduml \ No newline at end of file diff --git a/serv/docs/flow/user/bind-wallet.png b/serv/docs/flow/user/bind-wallet.png deleted file mode 100644 index 7fad07be..00000000 Binary files a/serv/docs/flow/user/bind-wallet.png and /dev/null differ diff --git a/serv/docs/flow/user/bind-wallet.puml b/serv/docs/flow/user/bind-wallet.puml deleted file mode 100644 index df2045f7..00000000 --- a/serv/docs/flow/user/bind-wallet.puml +++ /dev/null @@ -1,34 +0,0 @@ -@startuml -note right - 黄色表示有交互数据库的操作 - 红色表示跟keycloak服务有交互的操作 -end note -start -:解析、校验参数; -if (token无效?) then (yes) - :提示token失效; - stop -endif -#yellow:根据用户id获取用户记录; -:切分钱包地址字段,转换为地址数组; -#yellow:根据钱包地址,查询绑定关系记录; -if (关系记录存在?) then (yes) - if (关系记录数 == 钱包地址数量?) then (yes) - :返回错误,提示钱包已经绑定; - note left - 这里不做判断,是否绑定的用户是自己还是别人, - 统一返回已绑定错误 - end note - else (no) - :过滤出没有绑定的钱包地址; - #yellow:插入未绑定钱包的关系记录; - #green:(异步)转换sca地址; - endif - stop -else (no) - #yellow:插入绑定关系记录; - #green:(异步)转换sca地址; - :返回成功; -endif -stop -@enduml \ No newline at end of file diff --git a/serv/docs/flow/user/login.png b/serv/docs/flow/user/login.png deleted file mode 100644 index 5c69a21f..00000000 Binary files a/serv/docs/flow/user/login.png and /dev/null differ diff --git a/serv/docs/flow/user/login.puml b/serv/docs/flow/user/login.puml deleted file mode 100644 index 433093cc..00000000 --- a/serv/docs/flow/user/login.puml +++ /dev/null @@ -1,94 +0,0 @@ -@startuml - -'一旦接口秘钥被破解,那是可以任意绑定账号和钱包 -'可能最好还是有签名信息,去验证签名,但是所有其他服务接口调用这个登录的时候,就必须有用户的签名 -note right - 黄色表示有交互数据库的操作 - 红色表示跟keycloak服务有交互的操作 - 绿色表示异步操作 -end note -start -:解析、校验参数; -if (token无效?) then (yes) - :提示token失效; - stop -endif -:初始化用户是否新注册为1; -:初始化用户名为twitter_id字段; -:切分钱包地址字段,转换为地址数组; -if (twitter_id不为空?) then (yes) - partition "处理twitter id不为空的登录" { - #yellow:查询数据库用户名是twitter_id的记录; - if (用户记录存在?) then (yes) - :更新用户是否新注册为0; - if (wallet_address为空?) then (yes) - #red:使用twitter_id用户名,登录keycloak,获取用户token; - :构建返回体,返回; - stop - endif - endif - #yellow:根据钱包地址,查询绑定关系记录; - if (关系记录存在?) then (no) - if (是否新注册用户?) then (yes) - if (邀请码 != 系统初始邀请码) then (yes) - #yellow:查询用户记录表,邀请码为请求邀请码的用户记录; - if (邀请码用户记录不存在?) then (yes) - :返回用户邀请码无效错误; - stop - endif - endif - :生成随机的邀请码串; - #red:调用keycloak接口, 创建用户; - #yellow:插入用户记录信息; - #green:(异步)插入邀请关系记录; - #green:(异步)转换sca地址; - endif - #yellow:插入用户钱包绑定关系记录; - #red:调用keycloak更新用户属性,添加钱包地址列表属性; - else (yes) - if (绑定钱包的用户id与用户记录的id不一致?) then (yes) - #yellow:查询用户信息记录; - if (用户记录的username != twitter_id) then (yes) - #red:调用keycloak接口, 更新用户的用户名; - #yellow:更新用户信息记录的username字段为twitter_id; - endif -' #yellow:查找绑定钱包用户id的记录; -' if (绑定钱包的用户注册方式是wallet?) then (yes) -' #yellow:查询出所有绑定的钱包地址; -' #yellow:更新所有绑定钱包用户id的绑定记录为新的用户ID; -' #red:调用keycloak更新用户属性,添加钱包地址列表属性; -' endif -' note left -' 只有当之前绑定的用户是只有钱包注册的时候,才会全部替换 -' end note - endif - endif - } -else (no) - partition "处理只有钱包地址的登录" { - #yellow:根据钱包地址,查询绑定关系记录; - if (关系记录存在?) then (yes) - #yellow:查找关联用户信息记录; - :设置用户名为关联用户的用户名; - else (no) - if (邀请码 != 系统初始邀请码) then (yes) - #yellow:查询用户记录表,邀请码为请求邀请码的用户记录; - if (邀请码用户记录不存在?) then (yes) - :返回用户邀请码无效错误; - stop - endif - endif - :生成随机的邀请码串; - :设置用户名为随机字符串; - #red:调用keycloak接口, 创建用户; - #yellow:插入用户记录信息; - #green:(异步)插入邀请关系记录; - #green:(异步)转换sca地址; - endif - } -endif -#red:使用twitter_id用户名,登录keycloak,获取用户token; -:构建返回体,返回; -stop - -@enduml \ No newline at end of file diff --git a/serv/docs/flow/user/user-register-status.png b/serv/docs/flow/user/user-register-status.png deleted file mode 100644 index 6109a0fd..00000000 Binary files a/serv/docs/flow/user/user-register-status.png and /dev/null differ diff --git a/serv/docs/flow/user/user-register-status.puml b/serv/docs/flow/user/user-register-status.puml deleted file mode 100644 index 31087eca..00000000 --- a/serv/docs/flow/user/user-register-status.puml +++ /dev/null @@ -1,31 +0,0 @@ -@startuml -note right - 黄色表示有交互数据库的操作 - 红色表示跟keycloak服务有交互的操作 -end note -start -:解析、校验参数; -if (token无效?) then (yes) - :提示token失效; - stop -endif -:初始化已注册为0; -if (用户名字段不为空?) then (yes) - #yellow:根据用户名以及注册方式为twitter, 查找用户记录; - if (用户记录存在?) then (yes) - :设置已注册为1; - endif -endif -if (钱包地址字段不为空?) then (yes) - :通过","切分地址字段为数组; - #yellow:查询在钱包地址数组中绑定的用户id; - if (已绑定用户ID不为空?) then (yes) - #yellow:查询用户信息; - if (用户注册方式为twitter?) then (yes) - :设置已注册为1; - endif - endif -endif -:根据已注册字段返回; -stop -@enduml \ No newline at end of file diff --git a/serv/docs/flow/wallet_address/wallet-addresses.png b/serv/docs/flow/wallet_address/wallet-addresses.png deleted file mode 100644 index c3a1e8b6..00000000 Binary files a/serv/docs/flow/wallet_address/wallet-addresses.png and /dev/null differ diff --git a/serv/docs/flow/wallet_address/wallet-addresses.puml b/serv/docs/flow/wallet_address/wallet-addresses.puml deleted file mode 100644 index 9d0f80ec..00000000 --- a/serv/docs/flow/wallet_address/wallet-addresses.puml +++ /dev/null @@ -1,27 +0,0 @@ -@startuml -note right - 黄色表示有交互数据库的操作 - 红色表示跟keycloak服务有交互的操作 -end note -start -:解析、校验参数; -if (token无效?) then (yes) - :提示token失效; - stop -endif -:初始化钱包地址列表为空列表; -:初始化总数为0; -if (id不为空?) then (yes) - #yellow:通过sso_user_id查询用户记录; -endif -if (username不为空?) then (yes) - #yellow:通过username查询用户记录; -endif -if (用户记录存在?) then (yes) - #yellow:通过用户ID查找所有的钱包地址信息; - :更新钱包地址列表数据; - :更新总数; -endif -:返回数据; -stop -@enduml diff --git a/serv/docs/flow/wallet_address/wallet-bind-status.png b/serv/docs/flow/wallet_address/wallet-bind-status.png deleted file mode 100644 index 3e8fe19a..00000000 Binary files a/serv/docs/flow/wallet_address/wallet-bind-status.png and /dev/null differ diff --git a/serv/docs/flow/wallet_address/wallet-bind-status.puml b/serv/docs/flow/wallet_address/wallet-bind-status.puml deleted file mode 100644 index f99ad0bb..00000000 --- a/serv/docs/flow/wallet_address/wallet-bind-status.puml +++ /dev/null @@ -1,20 +0,0 @@ -@startuml -note right - 黄色表示有交互数据库的操作 - 红色表示跟keycloak服务有交互的操作 -end note -start -:解析、校验参数; -if (token无效?) then (yes) - :提示token失效; - stop -endif -:根据","分割地址字段为数组; -#yellow:基于钱包地址数组查找绑定关系记录以及关联用于sso_user_id; -:初始化钱包绑定信息数组; -repeat :遍历绑定关系记录列表; - :添加钱包绑定信息记录; -repeat while (更多数据?) -:返回结果数据; -stop -@enduml diff --git a/serv/go.mod b/serv/go.mod deleted file mode 100644 index cbb4882c..00000000 --- a/serv/go.mod +++ /dev/null @@ -1,106 +0,0 @@ -module bsquared.network/b2-message-channel-serv - -go 1.21.5 - -require ( - github.com/btcsuite/btcd v0.24.0 - github.com/btcsuite/btcd/btcutil v1.1.5 - github.com/dgrijalva/jwt-go v3.2.0+incompatible - github.com/ethereum/go-ethereum v1.13.10 - github.com/getsentry/sentry-go v0.28.1 - github.com/gin-contrib/cors v1.5.0 - github.com/gin-gonic/gin v1.9.1 - github.com/go-playground/validator/v10 v10.16.0 - github.com/go-resty/resty/v2 v2.14.0 - github.com/golang-jwt/jwt/v4 v4.5.0 - github.com/google/wire v0.5.0 - github.com/jackc/pgx/v5 v5.5.4 - github.com/patrickmn/go-cache v2.1.0+incompatible - github.com/pkg/errors v0.9.1 - github.com/redis/go-redis/v9 v9.4.0 - github.com/shopspring/decimal v1.3.1 - github.com/sirupsen/logrus v1.9.3 - github.com/spf13/viper v1.18.2 - github.com/storyicon/sigverify v1.1.0 - go.uber.org/zap v1.21.0 - gorm.io/driver/mysql v1.5.2 - gorm.io/gorm v1.25.5 -) - -require ( - github.com/Microsoft/go-winio v0.6.1 // indirect - github.com/StackExchange/wmi v1.2.1 // indirect - github.com/bits-and-blooms/bitset v1.10.0 // indirect - github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect - github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 // indirect - github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f // indirect - github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd // indirect - github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 // indirect - github.com/bytedance/sonic v1.10.2 // indirect - github.com/cespare/xxhash/v2 v2.2.0 // indirect - github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect - github.com/chenzhuoyu/iasm v0.9.1 // indirect - github.com/consensys/bavard v0.1.13 // indirect - github.com/consensys/gnark-crypto v0.12.1 // indirect - github.com/crate-crypto/go-kzg-4844 v0.7.0 // indirect - github.com/deckarep/golang-set/v2 v2.1.0 // indirect - github.com/decred/dcrd/crypto/blake256 v1.0.0 // indirect - github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect - github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect - github.com/ethereum/c-kzg-4844 v0.4.0 // indirect - github.com/fsnotify/fsnotify v1.7.0 // indirect - github.com/gabriel-vasile/mimetype v1.4.3 // indirect - github.com/gin-contrib/sse v0.1.0 // indirect - github.com/go-errors/errors v1.5.1 // indirect - github.com/go-ole/go-ole v1.2.5 // indirect - github.com/go-playground/locales v0.14.1 // indirect - github.com/go-playground/universal-translator v0.18.1 // indirect - github.com/go-sql-driver/mysql v1.7.1 // indirect - github.com/goccy/go-json v0.10.2 // indirect - github.com/google/uuid v1.6.0 // indirect - github.com/gorilla/websocket v1.5.0 // indirect - github.com/hashicorp/hcl v1.0.0 // indirect - github.com/holiman/uint256 v1.2.4 // indirect - github.com/jackc/pgpassfile v1.0.0 // indirect - github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect - github.com/jinzhu/inflection v1.0.0 // indirect - github.com/jinzhu/now v1.1.5 // indirect - github.com/json-iterator/go v1.1.12 // indirect - github.com/klauspost/cpuid/v2 v2.2.6 // indirect - github.com/leodido/go-urn v1.2.4 // indirect - github.com/magiconair/properties v1.8.7 // indirect - github.com/mattn/go-isatty v0.0.20 // indirect - github.com/mitchellh/mapstructure v1.5.0 // indirect - github.com/mmcloughlin/addchain v0.4.0 // indirect - github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/pelletier/go-toml/v2 v2.1.1 // indirect - github.com/sagikazarmark/locafero v0.4.0 // indirect - github.com/sagikazarmark/slog-shim v0.1.0 // indirect - github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect - github.com/sourcegraph/conc v0.3.0 // indirect - github.com/spf13/afero v1.11.0 // indirect - github.com/spf13/cast v1.6.0 // indirect - github.com/spf13/pflag v1.0.5 // indirect - github.com/subosito/gotenv v1.6.0 // indirect - github.com/supranational/blst v0.3.11 // indirect - github.com/tklauser/go-sysconf v0.3.12 // indirect - github.com/tklauser/numcpus v0.6.1 // indirect - github.com/twitchyliquid64/golang-asm v0.15.1 // indirect - github.com/ugorji/go/codec v1.2.12 // indirect - go.uber.org/atomic v1.9.0 // indirect - go.uber.org/multierr v1.10.0 // indirect - golang.org/x/arch v0.7.0 // indirect - golang.org/x/crypto v0.25.0 // indirect - golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa // indirect - golang.org/x/mod v0.17.0 // indirect - golang.org/x/net v0.27.0 // indirect - golang.org/x/sync v0.7.0 // indirect - golang.org/x/sys v0.22.0 // indirect - golang.org/x/text v0.16.0 // indirect - golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect - google.golang.org/protobuf v1.32.0 // indirect - gopkg.in/ini.v1 v1.67.0 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect - rsc.io/tmplfunc v0.0.3 // indirect -) diff --git a/serv/internal/boot/init.go b/serv/internal/boot/init.go deleted file mode 100644 index e70b494c..00000000 --- a/serv/internal/boot/init.go +++ /dev/null @@ -1,31 +0,0 @@ -package boot - -import ( - "bsquared.network/b2-message-channel-serv/internal/controllers" - "bsquared.network/b2-message-channel-serv/internal/repository" - "bsquared.network/b2-message-channel-serv/internal/services" -) - -type Initialization struct { - MessageInit *MessageInitialization -} - -type MessageInitialization struct { - MessageRepo repository.MessageRepository - MessageSvc services.MessageService - MessageCtrl controllers.MessageController -} - -func NewMessageInitialization(MessageRepo repository.MessageRepository, MessageSvc services.MessageService, MessageCtrl controllers.MessageController) *MessageInitialization { - return &MessageInitialization{ - MessageRepo: MessageRepo, - MessageSvc: MessageSvc, - MessageCtrl: MessageCtrl, - } -} - -func NewInitialization(MessageInit *MessageInitialization) *Initialization { - return &Initialization{ - MessageInit: MessageInit, - } -} diff --git a/serv/internal/boot/injector.go b/serv/internal/boot/injector.go deleted file mode 100644 index 43828cc4..00000000 --- a/serv/internal/boot/injector.go +++ /dev/null @@ -1,32 +0,0 @@ -//go:build wireinject -// +build wireinject - -// go:build wireinject -package boot - -import ( - "bsquared.network/b2-message-channel-serv/internal/config" - "bsquared.network/b2-message-channel-serv/internal/controllers" - "bsquared.network/b2-message-channel-serv/internal/repository" - "bsquared.network/b2-message-channel-serv/internal/services" - "github.com/google/wire" - "gorm.io/gorm" -) - -var appConfig = wire.NewSet(config.LoadConfig) - -var MessageInitSet = wire.NewSet(NewMessageInitialization) - -var MessageServiceSet = wire.NewSet(services.MessageServiceInit, wire.Bind(new(services.MessageService), new(*services.MessageServiceImpl))) - -var MessageRepoSet = wire.NewSet(repository.MessageRepositoryInit, wire.Bind(new(repository.MessageRepository), new(*repository.MessageRepositoryImpl))) - -var MessageCtrlSet = wire.NewSet(controllers.MessageControllerInit, wire.Bind(new(controllers.MessageController), new(*controllers.MessageControllerImpl))) - -func Init(db *gorm.DB, cache *config.Cache, cfg config.AppConfig) *Initialization { - wire.Build(NewInitialization, - MessageInitSet, - MessageCtrlSet, MessageServiceSet, MessageRepoSet, - ) - return nil -} diff --git a/serv/internal/boot/wire_gen.go b/serv/internal/boot/wire_gen.go deleted file mode 100644 index 7ab4fe53..00000000 --- a/serv/internal/boot/wire_gen.go +++ /dev/null @@ -1,39 +0,0 @@ -// Code generated by Wire. DO NOT EDIT. - -//go:generate go run github.com/google/wire/cmd/wire -//go:build !wireinject -// +build !wireinject - -package boot - -import ( - "bsquared.network/b2-message-channel-serv/internal/config" - "bsquared.network/b2-message-channel-serv/internal/controllers" - "bsquared.network/b2-message-channel-serv/internal/repository" - "bsquared.network/b2-message-channel-serv/internal/services" - "github.com/google/wire" - "gorm.io/gorm" -) - -// Injectors from injector.go: - -func Init(db *gorm.DB, cache *config.Cache, cfg config.AppConfig) *Initialization { - messageRepositoryImpl := repository.MessageRepositoryInit(db) - messageServiceImpl := services.MessageServiceInit(messageRepositoryImpl) - messageControllerImpl := controllers.MessageControllerInit(messageServiceImpl, db, cfg) - messageInitialization := NewMessageInitialization(messageRepositoryImpl, messageServiceImpl, messageControllerImpl) - initialization := NewInitialization(messageInitialization) - return initialization -} - -// injector.go: - -var appConfig = wire.NewSet(config.LoadConfig) - -var MessageInitSet = wire.NewSet(NewMessageInitialization) - -var MessageServiceSet = wire.NewSet(services.MessageServiceInit, wire.Bind(new(services.MessageService), new(*services.MessageServiceImpl))) - -var MessageRepoSet = wire.NewSet(repository.MessageRepositoryInit, wire.Bind(new(repository.MessageRepository), new(*repository.MessageRepositoryImpl))) - -var MessageCtrlSet = wire.NewSet(controllers.MessageControllerInit, wire.Bind(new(controllers.MessageController), new(*controllers.MessageControllerImpl))) diff --git a/serv/internal/btc/btc.go b/serv/internal/btc/btc.go deleted file mode 100644 index 37f35e01..00000000 --- a/serv/internal/btc/btc.go +++ /dev/null @@ -1,30 +0,0 @@ -package btc - -//import "github.com/btcsuite/btcd/rpcclient" -// -//type Config struct { -// RPCHost string -// RPCPort string -// RPCUser string -// RPCPass string -// DisableTLS bool -//} -// -//func NewBtcClient(bitcoinCfg Config) (*rpcclient.Client, error) { -// bclient, err := rpcclient.New(&rpcclient.ConnConfig{ -// Host: bitcoinCfg.RPCHost + ":" + bitcoinCfg.RPCPort, -// User: bitcoinCfg.RPCUser, -// Pass: bitcoinCfg.RPCPass, -// HTTPPostMode: true, // Bitcoin core only supports HTTP POST mode -// DisableTLS: bitcoinCfg.DisableTLS, // Bitcoin core does not provide TLS by default -// }, nil) -// return bclient, err -//} -// -//func NewBitcoinIndexer() { -// bidxer, err := bitcoin.NewBitcoinIndexer(bidxLogger, bclient, bitcoinParam, bitcoinCfg.IndexerListenAddress, bitcoinCfg.IndexerListenTargetConfirmations) -// if err != nil { -// logger.Errorw("failed to new bitcoin indexer indexer", "error", err.Error()) -// return err -// } -//} diff --git a/serv/internal/config/b2rpc.go b/serv/internal/config/b2rpc.go deleted file mode 100644 index b24f453f..00000000 --- a/serv/internal/config/b2rpc.go +++ /dev/null @@ -1,14 +0,0 @@ -package config - -import ( - "github.com/ethereum/go-ethereum/ethclient" - log "github.com/sirupsen/logrus" -) - -func InitB2Rpc(rpcUrl string) *ethclient.Client { - rpc, err := ethclient.Dial(rpcUrl) - if err != nil { - log.Panicf("b2 client dial error: %s\n", err) - } - return rpc -} diff --git a/serv/internal/config/config.go b/serv/internal/config/config.go deleted file mode 100644 index 16e69def..00000000 --- a/serv/internal/config/config.go +++ /dev/null @@ -1,187 +0,0 @@ -package config - -import ( - "encoding/json" - "github.com/spf13/viper" - "strings" -) - -type Server struct { - Port string - LogLevel uint32 - BybitPrivateKey string -} - -type Database struct { - UserName string - Password string - Host string - Port int64 - DbName string - LogLevel int64 -} - -type Redis struct { - Host string - Port string - Password string - DB int - TlsInsecureSkip bool - IsClusterMode bool - ClusterAddresses string -} - -type Blockchain struct { - ChainId int64 - Rollback bool - RpcUrl string - InitBlockNumber int64 - InitBlockHash string - MessageAddress string - Events string - Senders string - Validators string - BlockInterval int64 - ToChainId int64 - ToContractAddress string - ListenBtcAddress string - BtcUser string - BtcPass string -} - -type Particle struct { - AAPubKeyAPI string - Url string - ChainId int - ProjectUuid string - ProjectKey string -} - -type SentryConfig struct { - Url string - SampleRate float64 - Env string - Release string -} - -type AppConfig struct { - Server Server - Database Database - Redis Redis - Particle Particle - Blockchain []Blockchain - Sentry SentryConfig -} - -func LoadConfig() AppConfig { - v := viper.New() - v.SetConfigName("config") - v.AddConfigPath("./config") - v.SetConfigType("yaml") - v.AutomaticEnv() - replacer := strings.NewReplacer(".", "_") - v.SetEnvKeyReplacer(replacer) - - var config AppConfig - - if err := v.ReadInConfig(); err != nil { - panic(err) - } - - v.SetEnvPrefix("app") - err := v.BindEnv("server.port") - if err != nil { - return AppConfig{} - } - err = v.BindEnv("server.loglevel") - - err = v.BindEnv("api.secret") - if err != nil { - return AppConfig{} - } - - if err != nil { - return AppConfig{} - } - err = v.BindEnv("database.host") - if err != nil { - return AppConfig{} - } - err = v.BindEnv("database.dbname") - if err != nil { - return AppConfig{} - } - err = v.BindEnv("database.username") - if err != nil { - return AppConfig{} - } - err = v.BindEnv("database.password") - if err != nil { - return AppConfig{} - } - err = v.BindEnv("database.loglevel") - if err != nil { - return AppConfig{} - } - - err = v.BindEnv("redis.host") - if err != nil { - return AppConfig{} - } - err = v.BindEnv("redis.port") - if err != nil { - return AppConfig{} - } - err = v.BindEnv("redis.password") - if err != nil { - return AppConfig{} - } - err = v.BindEnv("redis.db") - if err != nil { - return AppConfig{} - } - err = v.BindEnv("redis.tls_insecure_skip") - if err != nil { - return AppConfig{} - } - err = v.BindEnv("redis.is_cluster_mode") - if err != nil { - return AppConfig{} - } - err = v.BindEnv("redis.cluster_addresses") - if err != nil { - return AppConfig{} - } - - err = v.BindEnv("sentry.url") - if err != nil { - return AppConfig{} - } - err = v.BindEnv("sentry.SampleRate") - if err != nil { - return AppConfig{} - } - err = v.BindEnv("sentry.env") - if err != nil { - return AppConfig{} - } - err = v.BindEnv("sentry.release") - if err != nil { - return AppConfig{} - } - - if err := v.Unmarshal(&config); err != nil { - panic(err) - } - - blockchainsJson := v.GetString("BLOCKCHAINS") - if blockchainsJson != "" { - var blockchains []Blockchain - err = json.Unmarshal([]byte(blockchainsJson), &blockchains) - if err != nil { - panic(err) - } - config.Blockchain = blockchains - } - return config -} diff --git a/serv/internal/config/db.go b/serv/internal/config/db.go deleted file mode 100644 index b03441e4..00000000 --- a/serv/internal/config/db.go +++ /dev/null @@ -1,21 +0,0 @@ -package config - -import ( - "fmt" - log "github.com/sirupsen/logrus" - "gorm.io/driver/mysql" - "gorm.io/gorm" - "gorm.io/gorm/logger" -) - -func ConnectToDB(cfg AppConfig) *gorm.DB { - dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local", cfg.Database.UserName, cfg.Database.Password, cfg.Database.Host, cfg.Database.Port, cfg.Database.DbName) - log.Info("connect to ", dsn) - db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{ - Logger: logger.Default.LogMode(logger.LogLevel(cfg.Database.LogLevel)), - }) - if err != nil { - panic(err) - } - return db -} diff --git a/serv/internal/config/log.go b/serv/internal/config/log.go deleted file mode 100644 index a934ae42..00000000 --- a/serv/internal/config/log.go +++ /dev/null @@ -1,13 +0,0 @@ -package config - -import ( - log "github.com/sirupsen/logrus" - "os" -) - -func InitLog(logLevel uint32) { - log.SetFormatter(&log.JSONFormatter{}) - log.SetOutput(os.Stdout) - - log.SetLevel(log.Level(logLevel)) -} diff --git a/serv/internal/config/redis.go b/serv/internal/config/redis.go deleted file mode 100644 index 80488c38..00000000 --- a/serv/internal/config/redis.go +++ /dev/null @@ -1,34 +0,0 @@ -package config - -import ( - "bsquared.network/b2-message-channel-serv/internal/utils" - localcache "github.com/patrickmn/go-cache" - "github.com/redis/go-redis/v9" - "time" -) - -func InitCache(cfg AppConfig) *Cache { - err := utils.InitRedis(cfg.Redis.IsClusterMode, cfg.Redis.ClusterAddresses, cfg.Redis.Password, - cfg.Redis.TlsInsecureSkip, cfg.Redis.Host, cfg.Redis.Port, cfg.Redis.DB) - if err != nil { - panic(err) - } - c, err := newCache(utils.GetClient()) - if err != nil { - panic(err) - } - return c - return nil -} - -type Cache struct { - Client redis.Cmdable - local *localcache.Cache -} - -func newCache(client redis.Cmdable) (*Cache, error) { - return &Cache{ - Client: client, - local: localcache.New(15*time.Minute, 20*time.Minute), - }, nil -} diff --git a/serv/internal/contract/message/send.go b/serv/internal/contract/message/send.go deleted file mode 100644 index d84df69b..00000000 --- a/serv/internal/contract/message/send.go +++ /dev/null @@ -1,88 +0,0 @@ -package message - -import ( - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto" - "github.com/shopspring/decimal" - "math/big" -) - -func Send(fromChainId int64, fromId *big.Int, fromSender string, contractAddress string, toBytes string, signatures []string) []byte { - // function send(uint256 from_chain_id, uint256 from_id, address from_sender, address contract_address, bytes calldata data, bytes[] calldata signatures) external - Method := crypto.Keccak256([]byte("send(uint256,uint256,address,address,bytes,bytes[])"))[:4] - FromChainId := common.BytesToHash(big.NewInt(fromChainId).Bytes()).Bytes() - FromId := common.BytesToHash(fromId.Bytes()).Bytes() - FromSender := common.BytesToHash(common.HexToAddress(fromSender).Bytes()).Bytes() - ContractAddress := common.BytesToHash(common.HexToAddress(contractAddress).Bytes()).Bytes() - - ToBytes := common.FromHex(toBytes) - ToBytesDataOffset := common.BytesToHash(big.NewInt(192).Bytes()).Bytes() - ToBytesDataLength := common.BytesToHash(big.NewInt(int64(len(ToBytes))).Bytes()).Bytes() - - if len(ToBytes)%32 > 0 { - ToBytes = append(ToBytes, make([]byte, 32-len(ToBytes)%32)...) - } - - SignaturesDataOffset := common.BytesToHash(big.NewInt(int64(224 + len(ToBytes))).Bytes()).Bytes() - SignaturesDataLength := common.BytesToHash(big.NewInt(int64(len(signatures))).Bytes()).Bytes() - - var streamOffsets []byte - var streamData []byte - streamIndex := int64(32 * len(signatures)) - for _, _signature := range signatures { - signatureDataOffset := common.BytesToHash(big.NewInt(streamIndex).Bytes()).Bytes() - streamOffsets = append(streamOffsets, signatureDataOffset...) - - signature := common.FromHex(_signature) - signatureDataLength := common.BytesToHash(big.NewInt(int64(len(signature))).Bytes()).Bytes() - streamData = append(streamData, signatureDataLength...) - if len(signature)%32 > 0 { - signature = append(signature, make([]byte, 32-len(signature)%32)...) - } - streamData = append(streamData, signature...) - streamIndex = int64(32*len(signatures) + len(streamData)) - } - - var stream []byte - stream = append(stream, Method...) - stream = append(stream, FromChainId...) - stream = append(stream, FromId...) - stream = append(stream, FromSender...) - stream = append(stream, ContractAddress...) - stream = append(stream, ToBytesDataOffset...) - stream = append(stream, SignaturesDataOffset...) - stream = append(stream, ToBytesDataLength...) - stream = append(stream, ToBytes...) - stream = append(stream, SignaturesDataLength...) - stream = append(stream, streamOffsets...) - stream = append(stream, streamData...) - return stream -} - -func EncodeSendData(txId string, fromAddress string, toAddress string, amount decimal.Decimal) []byte { - TxId := common.HexToHash(txId).Bytes() - - ToAddress := common.BytesToHash(common.HexToAddress(toAddress).Bytes()).Bytes() - Amount := common.BytesToHash(amount.BigInt().Bytes()).Bytes() - - FromAddress := []byte(fromAddress) - FromAddressOffset := common.BytesToHash(big.NewInt(128).Bytes()).Bytes() - FromAddressLength := common.BytesToHash(big.NewInt(int64(len(FromAddress))).Bytes()).Bytes() - if len(FromAddress)%32 > 0 { - FromAddress = append(FromAddress, make([]byte, 32-len(FromAddress)%32)...) - } - - var stream []byte - stream = append(stream, TxId...) - stream = append(stream, FromAddressOffset...) - stream = append(stream, ToAddress...) - stream = append(stream, Amount...) - stream = append(stream, FromAddressLength...) - stream = append(stream, FromAddress...) - - return stream -} - -//function encodeData3(bytes32 tx_id, string memory from_address, address to_address, uint256 amount) public pure returns (bytes memory) { -//return abi.encode(tx_id,from_address,to_address,amount); -//} diff --git a/serv/internal/controllers/basic.go b/serv/internal/controllers/basic.go deleted file mode 100644 index 2e1d77de..00000000 --- a/serv/internal/controllers/basic.go +++ /dev/null @@ -1,55 +0,0 @@ -package controllers - -import ( - "bsquared.network/b2-message-channel-serv/internal/middlewares" - "bsquared.network/b2-message-channel-serv/internal/utils/sso" - "fmt" - log "github.com/sirupsen/logrus" - "net/http" - "strings" - - "github.com/gin-gonic/gin" -) - -type BasicController struct{} - -func (c *BasicController) Authorization(ctx *gin.Context, secret string) (*sso.UserClaims, error) { - authorization := ctx.GetHeader("Authorization") - if strings.HasPrefix(authorization, "Bearer ") { - authorization = strings.ReplaceAll(authorization, "Bearer ", "") - } - claims, err := sso.VerifyToken(secret, authorization) - if err != nil { - return nil, err - } - return claims, nil -} - -func (c *BasicController) Return(ctx *gin.Context, data interface{}) { - ctx.AbortWithStatusJSON(http.StatusOK, data) -} - -func (c *BasicController) Success(ctx *gin.Context, data ...interface{}) { - var d interface{} - if len(data) > 0 { - d = data[0] - } - res := struct { - Code int `json:"code"` - Msg string `json:"msg"` - Data interface{} `json:"data,omitempty"` - }{ - Code: 0, - Msg: "success", - Data: d, - } - ctx.AbortWithStatusJSON(http.StatusOK, res) -} - -func (c *BasicController) Error(ctx *gin.Context, statusCode int, message string, key string, code int, reason error) { - log.Errorf("[%s]code: %d, reason: %v\n", key, code, reason) - err := middlewares.ErrorResponse{Status: statusCode} - err.Msg = fmt.Sprintf("%s[%d]", message, code) - err.Reason = fmt.Sprintf("[%s]code: %d, reason: %v\n", key, code, reason) - panic(err) -} diff --git a/serv/internal/controllers/message.go b/serv/internal/controllers/message.go deleted file mode 100644 index 380df6f6..00000000 --- a/serv/internal/controllers/message.go +++ /dev/null @@ -1,33 +0,0 @@ -package controllers - -import ( - "bsquared.network/b2-message-channel-serv/internal/config" - "bsquared.network/b2-message-channel-serv/internal/services" - "github.com/gin-gonic/gin" - "gorm.io/gorm" -) - -type MessageController interface { - Records(c *gin.Context) -} - -type MessageControllerImpl struct { - BasicController - svc services.MessageService - db *gorm.DB - cache *config.Cache - cfg config.AppConfig -} - -func MessageControllerInit(MessageService services.MessageService, db *gorm.DB, cfg config.AppConfig) *MessageControllerImpl { - return &MessageControllerImpl{ - svc: MessageService, - db: db, - cache: config.InitCache(cfg), - cfg: cfg, - } -} - -func (c *MessageControllerImpl) Records(ctx *gin.Context) { - -} diff --git a/serv/internal/job/handler.go b/serv/internal/job/handler.go deleted file mode 100644 index 6fcc24ab..00000000 --- a/serv/internal/job/handler.go +++ /dev/null @@ -1,38 +0,0 @@ -package job - -import ( - "bsquared.network/b2-message-channel-serv/internal/config" - "bsquared.network/b2-message-channel-serv/internal/listener/bitcoin" - "bsquared.network/b2-message-channel-serv/internal/listener/eth" - svc "bsquared.network/b2-message-channel-serv/internal/utils/ctx" - "fmt" - "github.com/btcsuite/btcd/rpcclient" - "gorm.io/gorm" -) - -var ( - ctx *svc.ServiceContext -) - -func Run(db *gorm.DB, cache *config.Cache, cfg config.AppConfig) { - for _, blockchain := range cfg.Blockchain { - if blockchain.ChainId == 1 { - bclient, err := rpcclient.New(&rpcclient.ConnConfig{ - Host: blockchain.RpcUrl, - User: blockchain.BtcUser, - Pass: blockchain.BtcPass, - HTTPPostMode: true, // Bitcoin core only supports HTTP POST mode - DisableTLS: false, // Bitcoin core does not provide TLS by default - }, nil) - if err != nil { - fmt.Println("new: ", err.Error()) - return - } - listener := bitcoin.NewListener(db, cache, blockchain, cfg.Particle, bclient) - listener.Run() - } else { - listener := eth.NewListener(db, cache, blockchain) - listener.Run() - } - } -} diff --git a/serv/internal/listener/bitcoin/handleDepositAddress.go b/serv/internal/listener/bitcoin/handleDepositAddress.go deleted file mode 100644 index 543b2d05..00000000 --- a/serv/internal/listener/bitcoin/handleDepositAddress.go +++ /dev/null @@ -1 +0,0 @@ -package bitcoin diff --git a/serv/internal/listener/bitcoin/indexer.go b/serv/internal/listener/bitcoin/indexer.go deleted file mode 100644 index ba5e3660..00000000 --- a/serv/internal/listener/bitcoin/indexer.go +++ /dev/null @@ -1,281 +0,0 @@ -package bitcoin - -import "github.com/pkg/errors" - -// import ( -// -// "bsquared.network/b2-message-channel-serv/internal/types" -// "encoding/hex" -// "errors" -// "fmt" -// log "github.com/sirupsen/logrus" -// -// "github.com/btcsuite/btcd/btcjson" -// "github.com/btcsuite/btcd/btcutil" -// "github.com/btcsuite/btcd/chaincfg" -// "github.com/btcsuite/btcd/chaincfg/chainhash" -// "github.com/btcsuite/btcd/rpcclient" -// "github.com/btcsuite/btcd/txscript" -// "github.com/btcsuite/btcd/wire" -// -// ) -var ( - ErrParsePkScript = errors.New("parse pkscript err") - ErrDecodeListenAddress = errors.New("decode listen address err") - ErrTargetConfirmations = errors.New("target confirmation number was not reached") - ErrParsePubKey = errors.New("parse pubkey failed, not found pubkey or nonsupport ") - ErrParsePkScriptNullData = errors.New("parse pkscript null data err") - ErrParsePkScriptNotNullData = errors.New("parse pkscript not null data err") -) - -const ( - // tx type - TxTypeTransfer = "transfer" // btc transfer - TxTypeWithdraw = "withdraw" // btc withdraw -) - -// -//// Indexer bitcoin indexer, parse and forward data -//type Indexer struct { -// client *rpcclient.Client // call bitcoin rpc client -// chainParams *chaincfg.Params // bitcoin network params, e.g. mainnet, testnet, etc. -// listenAddress btcutil.Address // need listened bitcoin address -// targetConfirmations uint64 -// logger log.Logger -//} -// -//// NewBitcoinIndexer new bitcoin indexer -//func NewBitcoinIndexer( -// log log.Logger, -// client *rpcclient.Client, -// chainParams *chaincfg.Params, -// listenAddress string, -// targetConfirmations uint64, -//) (*Indexer, error) { -// // check listenAddress -// address, err := btcutil.DecodeAddress(listenAddress, chainParams) -// if err != nil { -// return nil, fmt.Errorf("%w:%s", ErrDecodeListenAddress, err.Error()) -// } -// return &Indexer{ -// logger: log, -// client: client, -// chainParams: chainParams, -// listenAddress: address, -// targetConfirmations: targetConfirmations, -// }, nil -//} -// -//// ParseBlock parse block data by block height -//// NOTE: Currently, only transfer transactions are supported. -//func (b *Indexer) ParseBlock(height int64, txIndex int64) ([]*types.BitcoinTxParseResult, *wire.BlockHeader, error) { -// blockResult, err := b.getBlockByHeight(height) -// if err != nil { -// return nil, nil, err -// } -// -// blockParsedResult := make([]*types.BitcoinTxParseResult, 0) -// for k, v := range blockResult.Transactions { -// if int64(k) < txIndex { -// continue -// } -// -// //b.logger.Debugw("parse block", "k", k, "height", height, "txIndex", txIndex, "tx", v.TxHash().String()) -// -// parseTxs, err := b.parseTx(v, k) -// if err != nil { -// return nil, nil, err -// } -// if parseTxs != nil { -// blockParsedResult = append(blockParsedResult, parseTxs) -// } -// } -// -// return blockParsedResult, &blockResult.Header, nil -//} -// -//// getBlockByHeight returns a raw block from the server given its height -//func (b *Indexer) getBlockByHeight(height int64) (*wire.MsgBlock, error) { -// blockhash, err := b.client.GetBlockHash(height) -// if err != nil { -// return nil, err -// } -// msgBlock, err := b.client.GetBlock(blockhash) -// if err != nil { -// return nil, err -// } -// return msgBlock, nil -//} -// -//func (b *Indexer) CheckConfirmations(hash string) error { -// txHash, err := chainhash.NewHashFromStr(hash) -// if err != nil { -// return err -// } -// txVerbose, err := b.client.GetRawTransactionVerbose(txHash) -// if err != nil { -// return err -// } -// -// if txVerbose.Confirmations < b.targetConfirmations { -// return fmt.Errorf("%w, current confirmations:%d target confirmations: %d", -// ErrTargetConfirmations, txVerbose.Confirmations, b.targetConfirmations) -// } -// return nil -//} -// -//func (b *Indexer) ParseTx(hash string) (*types.BitcoinTxParseResult, error) { -// txHash, err := chainhash.NewHashFromStr(hash) -// if err != nil { -// return nil, err -// } -// tx, err := b.client.GetRawTransaction(txHash) -// if err != nil { -// return nil, err -// } -// return b.parseTx(tx.MsgTx(), 0) -//} -// -//// parseTx parse transaction data -//func (b *Indexer) parseTx(txResult *wire.MsgTx, index int) (*types.BitcoinTxParseResult, error) { -// listenAddress := false -// var totalValue int64 -// tos := make([]types.BitcoinTo, 0) -// for _, v := range txResult.TxOut { -// pkAddress, err := b.parseAddress(v.PkScript) -// if err != nil { -// if errors.Is(err, ErrParsePkScript) { -// continue -// } -// // parse null data -// if errors.Is(err, ErrParsePkScriptNullData) { -// nullData, err := b.parseNullData(v.PkScript) -// if err != nil { -// continue -// } -// tos = append(tos, types.BitcoinTo{ -// Type: types.BitcoinToTypeNullData, -// NullData: nullData, -// }) -// } else { -// return nil, err -// } -// } else { -// parseTo := types.BitcoinTo{ -// Address: pkAddress, -// Value: v.Value, -// Type: types.BitcoinToTypeNormal, -// } -// tos = append(tos, parseTo) -// } -// // if pk address eq dest listened address, after parse from address by vin prev tx -// if pkAddress == b.listenAddress.EncodeAddress() { -// listenAddress = true -// totalValue += v.Value -// } -// } -// if listenAddress { -// fromAddress, err := b.parseFromAddress(txResult) -// if err != nil { -// return nil, fmt.Errorf("vin parse err:%w", err) -// } -// -// // TODO: temp fix, if from is listened address, continue -// if len(fromAddress) == 0 { -// //b.logger.Warnw("parse from address empty or nonsupport tx type", -// // "txId", txResult.TxHash().String(), -// // "listenAddress", b.listenAddress.EncodeAddress()) -// return nil, nil -// } -// -// return &types.BitcoinTxParseResult{ -// TxID: txResult.TxHash().String(), -// TxType: TxTypeTransfer, -// Index: int64(index), -// Value: totalValue, -// From: fromAddress, -// To: b.listenAddress.EncodeAddress(), -// Tos: tos, -// }, nil -// } -// return nil, nil -//} -// -//// parseFromAddress from vin parse from address -//// return all possible values parsed from address -//// TODO: at present, it is assumed that it is a single from, and multiple from needs to be tested later -//func (b *Indexer) parseFromAddress(txResult *wire.MsgTx) (fromAddress []types.BitcoinFrom, err error) { -// for _, vin := range txResult.TxIn { -// // get prev tx hash -// prevTxID := vin.PreviousOutPoint.Hash -// vinResult, err := b.client.GetRawTransaction(&prevTxID) -// if err != nil { -// return nil, fmt.Errorf("vin get raw transaction err:%w", err) -// } -// if len(vinResult.MsgTx().TxOut) == 0 { -// return nil, fmt.Errorf("vin txOut is null") -// } -// vinPKScript := vinResult.MsgTx().TxOut[vin.PreviousOutPoint.Index].PkScript -// // script to address -// vinPkAddress, err := b.parseAddress(vinPKScript) -// if err != nil { -// //b.logger.Errorw("vin parse address", "error", err) -// if errors.Is(err, ErrParsePkScript) || errors.Is(err, ErrParsePkScriptNullData) { -// continue -// } -// return nil, err -// } -// -// fromAddress = append(fromAddress, types.BitcoinFrom{ -// Address: vinPkAddress, -// Type: types.BitcoinFromTypeBtc, -// }) -// } -// return fromAddress, nil -//} -// -//// parseAddress from pkscript parse address -//func (b *Indexer) ParseAddress(pkScript []byte) (string, error) { -// return b.parseAddress(pkScript) -//} -// -//// parseNullData from pkscript parse null data -//func (b *Indexer) parseNullData(pkScript []byte) (string, error) { -// if !txscript.IsNullData(pkScript) { -// return "", ErrParsePkScriptNotNullData -// } -// return hex.EncodeToString(pkScript[1:]), nil -//} -// -//// parseAddress from pkscript parse address -//func (b *Indexer) parseAddress(pkScript []byte) (string, error) { -// pk, err := txscript.ParsePkScript(pkScript) -// if err != nil { -// scriptClass := txscript.GetScriptClass(pkScript) -// if scriptClass == txscript.NullDataTy { -// return "", ErrParsePkScriptNullData -// } -// return "", fmt.Errorf("%w:%s", ErrParsePkScript, err.Error()) -// } -// -// if pk.Class() == txscript.NullDataTy { -// return "", ErrParsePkScriptNullData -// } -// -// // encodes the script into an address for the given chain. -// pkAddress, err := pk.Address(b.chainParams) -// if err != nil { -// return "", fmt.Errorf("PKScript to address err:%w", err) -// } -// return pkAddress.EncodeAddress(), nil -//} -// -//// LatestBlock get latest block height in the longest block chain. -//func (b *Indexer) LatestBlock() (int64, error) { -// return b.client.GetBlockCount() -//} -// -//// BlockChainInfo get block chain info -//func (b *Indexer) BlockChainInfo() (*btcjson.GetBlockChainInfoResult, error) { -// return b.client.GetBlockChainInfo() -//} diff --git a/serv/internal/listener/bitcoin/indexer_service.go b/serv/internal/listener/bitcoin/indexer_service.go deleted file mode 100644 index 9506f451..00000000 --- a/serv/internal/listener/bitcoin/indexer_service.go +++ /dev/null @@ -1,354 +0,0 @@ -package bitcoin - -import ( - "time" -) - -const ( - ServiceName = "BitcoinIndexerService" - - NewBlockWaitTimeout = 60 * time.Second - - IndexTxTimeout = 100 * time.Millisecond - IndexBlockTimeout = 2 * time.Second -) - -// IndexerService indexes transactions for json-rpc service. -//type IndexerService struct { -// service.BaseService -// -// txIdxr types.BITCOINTxIndexer -// -// db *gorm.DB -// log log.Logger -//} -// -//// NewIndexerService returns a new service instance. -//func NewIndexerService( -// txIdxr types.BITCOINTxIndexer, -// db *gorm.DB, -// logger log.Logger, -//) *IndexerService { -// is := &IndexerService{txIdxr: txIdxr, db: db, log: logger} -// is.BaseService = *service.NewBaseService(nil, ServiceName, is) -// return is -//} -// -//// OnStart -//func (bis *IndexerService) OnStart() error { -// latestBlock, err := bis.txIdxr.LatestBlock() -// if err != nil { -// //bis.log.Errorw("bitcoin indexer latestBlock", "error", err.Error()) -// return err -// } -// -// var ( -// currentBlock int64 // index current block number -// currentTxIndex int64 // index current block tx index -// ) -// // if !bis.db.Migrator().HasTable(&model.Deposit{}) { -// // err = bis.db.AutoMigrate(&model.Deposit{}) -// // if err != nil { -// // bis.log.Errorw("bitcoin indexer create table", "error", err.Error()) -// // return err -// // } -// // } -// -// // if !bis.db.Migrator().HasTable(&model.BtcIndex{}) { -// // err = bis.db.AutoMigrate(&model.BtcIndex{}) -// // if err != nil { -// // bis.log.Errorw("bitcoin indexer create table", "error", err.Error()) -// // return err -// // } -// // } -// -// // if !bis.db.Migrator().HasTable(&model.Sinohope{}) { -// // err = bis.db.AutoMigrate(&model.Sinohope{}) -// // if err != nil { -// // bis.log.Errorw("bitcoin indexer create table", "error", err.Error()) -// // return err -// // } -// // } -// -// // if !bis.db.Migrator().HasTable(&model.RollupDeposit{}) { -// // err = bis.db.AutoMigrate(&model.RollupDeposit{}) -// // if err != nil { -// // bis.log.Errorw("bitcoin indexer create table", "error", err.Error()) -// // return err -// // } -// // } -// -// var btcIndex models.BtcIndex -// if err := bis.db.First(&btcIndex, 1).Error; err != nil { -// if errors.Is(err, gorm.ErrRecordNotFound) { -// btcIndex = models.BtcIndex{ -// Base: models.Base{ -// Id: 1, -// }, -// BtcIndexBlock: latestBlock, -// BtcIndexTx: 0, -// } -// if err := bis.db.Create(&btcIndex).Error; err != nil { -// return err -// } -// } else { -// return err -// } -// } -// -// //bis.log.Infow("bitcoin indexer load db", "data", btcIndex) -// -// // set default value -// currentBlock = btcIndex.BtcIndexBlock -// currentTxIndex = btcIndex.BtcIndexTx -// -// ticker := time.NewTicker(NewBlockWaitTimeout) -// for { -// //bis.log.Infow("bitcoin indexer", "latestBlock", -// // latestBlock, "currentBlock", currentBlock, "currentTxIndex", currentTxIndex) -// -// if latestBlock <= currentBlock { -// <-ticker.C -// ticker.Reset(NewBlockWaitTimeout) -// -// // update latest block -// latestBlock, err = bis.txIdxr.LatestBlock() -// if err != nil { -// //bis.log.Errorw("bitcoin indexer latestBlock", "error", err.Error()) -// } -// continue -// } -// // index > 0, start index from currentBlock currentTxIndex + 1 -// // index == 0, start index from currentBlock + 1 -// if currentTxIndex == 0 { -// currentBlock++ -// } else { -// currentTxIndex++ -// } -// -// for i := currentBlock; i <= latestBlock; i++ { -// //bis.log.Infow("start parse block", "currentBlock", i, "currentTxIndex", currentTxIndex) -// txResults, blockHeader, err := bis.txIdxr.ParseBlock(i, currentTxIndex) -// if err != nil { -// if errors.Is(err, ErrTargetConfirmations) { -// //bis.log.Warnw("parse block confirmations", "error", err.Error(), "currentBlock", i, "currentTxIndex", currentTxIndex) -// time.Sleep(NewBlockWaitTimeout) -// } else { -// //bis.log.Errorw("parse block unknown err", "error", err.Error(), "currentBlock", i, "currentTxIndex", currentTxIndex) -// } -// if currentTxIndex == 0 { -// currentBlock = i - 1 -// } else { -// currentBlock = i -// currentTxIndex-- -// } -// -// break -// } -// if len(txResults) > 0 { -// currentBlock, currentTxIndex, err = bis.HandleResults(txResults, btcIndex, blockHeader.Timestamp, i) -// if err != nil { -// //bis.log.Errorw("failed to handle results", "error", err, -// // "currentBlock", currentBlock, "currentTxIndex", currentTxIndex, "latestBlock", latestBlock) -// rollback := true -// // not duplicated key, rollback index -// if pgErr, ok := err.(*pgconn.PgError); ok { -// // 23505 duplicate key value violates unique constraint , continue -// if pgErr.Code == "23505" { -// rollback = false -// } -// } -// -// if rollback { -// if currentTxIndex == 0 { -// currentBlock = i - 1 -// } else { -// currentBlock = i -// currentTxIndex-- -// } -// break -// } -// } -// } -// currentBlock = i -// currentTxIndex = 0 -// btcIndex.BtcIndexBlock = currentBlock -// btcIndex.BtcIndexTx = currentTxIndex -// if err := bis.db.Save(&btcIndex).Error; err != nil { -// //bis.log.Errorw("failed to save bitcoin index block", "error", err, "currentBlock", i, -// // "currentTxIndex", currentTxIndex, "latestBlock", latestBlock) -// // rollback -// currentBlock = i - 1 -// break -// } -// //bis.log.Infow("bitcoin indexer parsed", "currentBlock", i, -// // "currentTxIndex", currentTxIndex, "latestBlock", latestBlock) -// time.Sleep(IndexBlockTimeout) -// } -// } -//} -// -//// save index tx to db -//func (bis *IndexerService) SaveParsedResult( -// parseResult *types.BitcoinTxParseResult, -// btcBlockNumber int64, -// b2TxStatus int, -// btcBlockTime time.Time, -// btcIndex models.BtcIndex, -//) error { -// // write db -// err := bis.db.Transaction(func(tx *gorm.DB) error { -// if len(parseResult.From) == 0 { -// return fmt.Errorf("parse result from empty") -// } -// -// if len(parseResult.To) == 0 { -// return fmt.Errorf("parse result to empty") -// } -// -// if len(parseResult.Tos) == 0 { -// return fmt.Errorf("parse result to empty") -// } -// -// //bis.log.Infow("parseResult:", "result", parseResult) -// existsEvmAddressData := false // The evm address is processed only if it exists. Otherwise, aa is used -// parsedEvmAddress := "" // evm address -// for _, v := range parseResult.Tos { -// // only handle first null data -// if existsEvmAddressData { -// continue -// } -// if v.Type == types.BitcoinToTypeNullData { -// decodeNullData, err := hex.DecodeString(v.NullData) -// if err != nil { -// //bis.log.Errorw("decode null data err", "error", err, "nullData", v.NullData) -// continue -// } -// evmAddress := bytes.TrimSpace(decodeNullData[1:]) -// if common.IsHexAddress(string(evmAddress)) { -// existsEvmAddressData = true -// parsedEvmAddress = string(evmAddress) -// for k := range parseResult.From { -// parseResult.From[k].Type = types.BitcoinFromTypeEvm -// parseResult.From[k].EvmAddress = parsedEvmAddress -// } -// } -// } -// } -// froms, err := json.Marshal(parseResult.From) -// if err != nil { -// return err -// } -// tos, err := json.Marshal(parseResult.Tos) -// if err != nil { -// return err -// } -// // if existed, update deposit record -// var deposit models.Deposit -// err = tx. -// Set("gorm:query_option", "FOR UPDATE"). -// First(&deposit, -// fmt.Sprintf("%s = ?", models.Deposit{}.Column().BtcTxHash), -// parseResult.TxID).Error -// if err != nil { -// if !errors.Is(err, gorm.ErrRecordNotFound) { -// return err -// } -// deposit := models.Deposit{ -// BtcBlockNumber: btcBlockNumber, -// BtcTxIndex: parseResult.Index, -// BtcTxHash: parseResult.TxID, -// BtcFrom: parseResult.From[0].Address, -// BtcTos: string(tos), -// BtcTo: parseResult.To, -// BtcValue: parseResult.Value, -// BtcFroms: string(froms), -// B2TxStatus: b2TxStatus, -// BtcBlockTime: btcBlockTime, -// B2TxRetry: 0, -// ListenerStatus: models.ListenerStatusSuccess, -// CallbackStatus: models.CallbackStatusPending, -// } -// if existsEvmAddressData { -// deposit.BtcFromEvmAddress = parsedEvmAddress -// } -// err = tx.Create(&deposit).Error -// if err != nil { -// //bis.log.Errorw("failed to save tx parsed result", "error", err) -// return err -// } -// } else if deposit.CallbackStatus == models.CallbackStatusSuccess && -// deposit.ListenerStatus == models.ListenerStatusPending { -// if deposit.BtcValue != parseResult.Value || deposit.BtcFrom != parseResult.From[0].Address { -// return fmt.Errorf("invalid parameter") -// } -// // if existed, update deposit record -// updateFields := map[string]interface{}{ -// models.Deposit{}.Column().BtcBlockNumber: btcBlockNumber, -// models.Deposit{}.Column().BtcTxIndex: parseResult.Index, -// models.Deposit{}.Column().BtcFroms: string(froms), -// models.Deposit{}.Column().BtcTos: string(tos), -// models.Deposit{}.Column().BtcBlockTime: btcBlockTime, -// models.Deposit{}.Column().ListenerStatus: models.ListenerStatusSuccess, -// } -// if existsEvmAddressData { -// updateFields[models.Deposit{}.Column().BtcFromEvmAddress] = parsedEvmAddress -// } -// err = tx.Model(&models.Deposit{}).Where("id = ?", deposit.Id).Updates(updateFields).Error -// if err != nil { -// //bis.log.Errorw("failed to update tx parsed result", "error", err) -// return err -// } -// } -// -// if err := tx.Save(&btcIndex).Error; err != nil { -// //bis.log.Errorw("failed to save bitcoin tx index", "error", err) -// return err -// } -// return nil -// }) -// return err -//} -// -//func (bis *IndexerService) HandleResults( -// txResults []*types.BitcoinTxParseResult, -// btcIndex models.BtcIndex, -// btcBlockTime time.Time, -// currentBlock int64, -//) (int64, int64, error) { -// for _, v := range txResults { -// // if from is listen address, skip -// if bis.ToInFroms(v.From, v.To) { -// //bis.log.Infow("current transaction from is listen address", "currentBlock", currentBlock, "currentTxIndex", v.Index, "data", v) -// continue -// } -// -// btcIndex.BtcIndexBlock = currentBlock -// btcIndex.BtcIndexTx = v.Index -// // write db -// err := bis.SaveParsedResult( -// v, -// currentBlock, -// models.DepositB2TxStatusPending, -// btcBlockTime, -// btcIndex, -// ) -// if err != nil { -// //bis.log.Errorw("failed to save bitcoin index tx", "error", err, -// // "data", v) -// return currentBlock, v.Index, err -// } -// //bis.log.Infow("save bitcoin index tx success", "currentBlock", currentBlock, "currentTxIndex", v.Index, "data", v) -// time.Sleep(IndexTxTimeout) -// } -// return currentBlock, 0, nil -//} -// -//func (bis *IndexerService) ToInFroms(a []types.BitcoinFrom, s string) bool { -// for _, i := range a { -// if i.Address == s { -// return true -// } -// } -// return false -//} diff --git a/serv/internal/listener/bitcoin/listener.go b/serv/internal/listener/bitcoin/listener.go deleted file mode 100644 index 837fc6fa..00000000 --- a/serv/internal/listener/bitcoin/listener.go +++ /dev/null @@ -1,46 +0,0 @@ -package bitcoin - -import ( - "bsquared.network/b2-message-channel-serv/internal/config" - "github.com/btcsuite/btcd/btcutil" - "github.com/btcsuite/btcd/chaincfg" - "github.com/btcsuite/btcd/rpcclient" - "gorm.io/gorm" -) - -type Listener struct { - Blockchain config.Blockchain - Particle config.Particle - Db *gorm.DB - Cache *config.Cache - Rpc *rpcclient.Client - LatestBlockNumber int64 - ChainParams *chaincfg.Params // bitcoin network params, e.g. mainnet, testnet, etc. - listenAddress btcutil.Address // need listened bitcoin address -} - -func NewListener(db *gorm.DB, cache *config.Cache, blockchain config.Blockchain, particle config.Particle, rpc *rpcclient.Client) *Listener { - listenAddress, _ := btcutil.DecodeAddress(blockchain.ListenBtcAddress, &chaincfg.MainNetParams) - var ChainParams *chaincfg.Params - if blockchain.ChainId == 1 { - ChainParams = &chaincfg.MainNetParams - } else { - ChainParams = &chaincfg.TestNet3Params - } - return &Listener{ - Blockchain: blockchain, - Particle: particle, - Db: db, - Cache: cache, - Rpc: rpc, - LatestBlockNumber: 0, - ChainParams: ChainParams, - listenAddress: listenAddress, - } -} - -func (l *Listener) Run() { - //go l.syncLatestBlockNumber() - //go l.syncTask() - //go l.syncMessage() -} diff --git a/serv/internal/listener/bitcoin/syncLatestBlockNumber.go b/serv/internal/listener/bitcoin/syncLatestBlockNumber.go deleted file mode 100644 index def15854..00000000 --- a/serv/internal/listener/bitcoin/syncLatestBlockNumber.go +++ /dev/null @@ -1,21 +0,0 @@ -package bitcoin - -import ( - log "github.com/sirupsen/logrus" - "time" -) - -func (l *Listener) syncLatestBlockNumber() { - for { - duration := time.Millisecond * time.Duration(l.Blockchain.BlockInterval) - latest, err := l.Rpc.GetBlockCount() - if err != nil { - log.Errorf("[Handle.LatestBlackNumber][%d]Syncing latest block number error: %s\n", l.Blockchain.ChainId, err) - time.Sleep(duration) - continue - } - l.LatestBlockNumber = int64(latest) - 3 - log.Infof("[Handle.LatestBlackNumber][%d]Syncing latest block number: %d \n", l.Blockchain.ChainId, latest) - time.Sleep(duration) - } -} diff --git a/serv/internal/listener/bitcoin/syncMessage.go b/serv/internal/listener/bitcoin/syncMessage.go deleted file mode 100644 index a9b554d1..00000000 --- a/serv/internal/listener/bitcoin/syncMessage.go +++ /dev/null @@ -1,108 +0,0 @@ -package bitcoin - -import ( - "bsquared.network/b2-message-channel-serv/internal/contract/message" - "bsquared.network/b2-message-channel-serv/internal/enums" - "bsquared.network/b2-message-channel-serv/internal/models" - "bsquared.network/b2-message-channel-serv/internal/utils/aa" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/shopspring/decimal" - log "github.com/sirupsen/logrus" - "gorm.io/gorm" - "sync" - "time" -) - -func (l *Listener) syncMessage() { - for { - var list []models.Deposit - err := l.Db.Where("status=?", enums.DepositStatusPending).First(&list).Error - if err != nil { - continue - } - wg := sync.WaitGroup{} - for _, one := range list { - wg.Add(1) - go func(one models.Deposit, wg *sync.WaitGroup) { - defer wg.Done() - err := l.handleMessage(one) - if err != nil { - log.Errorf("[Handler.syncMessage] Deposit ID: %d , err: %s \n", one.Id, err) - } - }(one, &wg) - } - wg.Wait() - time.Sleep(time.Second * 10) - } -} - -func (l *Listener) handleMessage(deposit models.Deposit) error { - toChainId := l.Blockchain.ToChainId - toContractAddress := l.Blockchain.ToContractAddress - - depositAddress, err := l.GetDepositAddress(deposit) - if err != nil { - return err - } - - data := message.EncodeSendData(deposit.BtcTxHash, deposit.BtcFrom, depositAddress, decimal.New(deposit.BtcValue, 0)) - msg := models.Message{ - ChainId: l.Blockchain.ChainId, - Type: enums.MessageTypeCall, - FromChainId: l.Blockchain.ChainId, - FromSender: common.HexToAddress("0x0").Hex(), - FromContractAddress: common.HexToAddress("0x0").Hex(), - FromId: common.HexToHash(deposit.BtcTxHash).Hex(), - ToChainId: toChainId, - ToContractAddress: toContractAddress, - ToBytes: hexutil.Encode(data), - Signatures: "{}", - Status: enums.MessageStatusValidating, - Blockchain: models.Blockchain{ - EventId: deposit.Id, - BlockTime: deposit.BtcBlockTime.Unix(), - BlockNumber: deposit.BtcBlockNumber, - LogIndex: deposit.BtcTxIndex, - TxHash: common.HexToHash(deposit.BtcTxHash).Hex(), - }, - } - err = l.Db.Transaction(func(tx *gorm.DB) error { - err := tx.Create(&msg).Error - if err != nil { - return err - } - - if deposit.BtcFromEvmAddress != "" { - err = tx.Model(models.Deposit{}). - Where("id=?", deposit.Id). - Update("status", enums.MessageStatusValid).Error - } else { - err = tx.Model(models.Deposit{}). - Where("id=?", deposit.Id). - Update("btc_from_aa_address", depositAddress). - Update("status", enums.MessageStatusValid).Error - } - if err != nil { - return err - } - return nil - }) - if err != nil { - return err - } - return nil -} - -func (l *Listener) GetDepositAddress(deposit models.Deposit) (string, error) { - if deposit.BtcFromEvmAddress != "" && common.IsHexAddress(deposit.BtcFromEvmAddress) { - return deposit.BtcFromEvmAddress, nil - } else { - evmAddress, err := aa.BitcoinAddressToEthAddress(l.Particle.AAPubKeyAPI, deposit.BtcFrom, - l.Particle.Url, l.Particle.ChainId, l.Particle.ProjectUuid, l.Particle.ProjectKey) - if err != nil { - return "", err - } - return evmAddress, nil - } -} diff --git a/serv/internal/listener/eth/broadcast.go b/serv/internal/listener/eth/broadcast.go deleted file mode 100644 index 4860f464..00000000 --- a/serv/internal/listener/eth/broadcast.go +++ /dev/null @@ -1,95 +0,0 @@ -package eth - -import ( - "bsquared.network/b2-message-channel-serv/internal/enums" - "bsquared.network/b2-message-channel-serv/internal/models" - "context" - "encoding/hex" - _types "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/rlp" - log "github.com/sirupsen/logrus" - "sync" - "time" -) - -func (l *Listener) broadcast() { - duration := time.Millisecond * time.Duration(l.Blockchain.BlockInterval) - for { - var signatures []models.Signature - err := l.Db.Where("`chain_id`=? AND `status`=?", l.Blockchain.ChainId, enums.SignatureStatusPending).Order("id").Limit(100).Find(&signatures).Error - if err != nil { - log.Errorf("Get signatures err: %s\n", err) - time.Sleep(duration) - continue - } - if len(signatures) == 0 { - log.Infof("Get signatures length is 0\n") - time.Sleep(duration) - continue - } - - var wg sync.WaitGroup - for _, signature := range signatures { - wg.Add(1) - go func(_wg *sync.WaitGroup, signature models.Signature) { - defer _wg.Done() - err = l.broadcastSignature(signature) - if err != nil { - log.Errorf("Broadcast signature err[%d]: %s\n", signature.Id, err) - } - }(&wg, signature) - } - wg.Wait() - } -} - -func (l *Listener) broadcastSignature(signature models.Signature) error { - log.Infof("signature: %v\n", signature) - err := l._broadcast(signature.Signature) - if err != nil && err.Error() != "nonce too low" && err.Error() != "already known" { - log.Errorf("Broadcast err[%d]: %s\n", signature.Id, err) - return err - } else if err != nil && err.Error() == "nonce too low" { - // _, err := ctx.RPC.TransactionReceipt(context.Background(), common.HexToHash(signature.TxHash)) - // if err != nil { - // log.Errorf("Get TransactionReceipt err[%d]: %s\n", signature.Id, err) - // return err - // } - err = l.Db.Model(&models.Signature{}).Where("id = ?", signature.Id).Update("status", enums.SignatureStatusBroadcast).Error - if err != nil { - log.Errorf("update signature status broadcast err[%d]: %s\n", signature.Id, err) - return err - } - } else if err != nil && err.Error() == "already known" { - err = l.Db.Model(&models.Signature{}).Where("id = ?", signature.Id).Update("status", enums.SignatureStatusBroadcast).Error - if err != nil { - log.Errorf("update signature status broadcast err[%d]: %s\n", signature.Id, err) - return err - } - } else { - err = l.Db.Model(&models.Signature{}).Where("id = ?", signature.Id).Update("status", enums.SignatureStatusBroadcast).Error - if err != nil { - log.Errorf("Broadcast signature err[%d]: %s\n", signature.Id, err) - return err - } - log.Infof("signature success\n") - return nil - } - return nil -} - -func (l *Listener) _broadcast(signature string) error { - rawTxBytes, err := hex.DecodeString(signature) - if err != nil { - log.Errorf("[Broadcast]Decode string err: %s\n", err) - return err - } - tx := new(_types.Transaction) - rlp.DecodeBytes(rawTxBytes, &tx) - err = l.RPC.SendTransaction(context.Background(), tx) - if err != nil { - log.Errorf("[Broadcast]Send transaction err: %s\n", err) - return err - } - return nil -} diff --git a/serv/internal/listener/eth/build.go b/serv/internal/listener/eth/build.go deleted file mode 100644 index 42b2c67c..00000000 --- a/serv/internal/listener/eth/build.go +++ /dev/null @@ -1,267 +0,0 @@ -package eth - -import ( - msg "bsquared.network/b2-message-channel-serv/internal/contract/message" - "bsquared.network/b2-message-channel-serv/internal/enums" - "bsquared.network/b2-message-channel-serv/internal/models" - "bytes" - "context" - "encoding/hex" - "encoding/json" - "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/pkg/errors" - "github.com/shopspring/decimal" - log "github.com/sirupsen/logrus" - "gorm.io/gorm" - "math/big" - "sync" - "time" -) - -func (l *Listener) build() { - duration := time.Millisecond * time.Duration(l.Blockchain.BlockInterval) - for { - list, err := l.pendingCallMessage(10) - if err != nil { - log.Errorf("Get pending call message err: %s\n", err) - time.Sleep(duration) - continue - } - if len(list) == 0 { - log.Infof("Get pending call message length is 0\n") - time.Sleep(duration) - continue - } - - var wg sync.WaitGroup - for _, message := range list { - wg.Add(1) - go func(_wg *sync.WaitGroup, message models.Message) { - defer _wg.Done() - err = l.buildMessage(message) - if err != nil { - log.Errorf("Handle err: %v, %v\n", err, message) - } - }(&wg, message) - } - wg.Wait() - } -} - -func (l *Listener) buildMessage(message models.Message) error { - UserAddress, err := l.BorrowAccount() - if err != nil { - log.Errorf("borrow account err: %s\n", err) - return errors.WithStack(err) - } - lock, err := l.LockUser(UserAddress, time.Minute*2) - if err != nil { - log.Errorf("lock err: %s\n", err) - return errors.WithStack(err) - } - if !lock { - log.Infof("load result: %v\n", lock) - return errors.WithStack(err) - } - defer l.UnlockUser(UserAddress) - - gasPrice, err := l.GasPrice() - if err != nil { - return errors.WithStack(err) - } - //gasPrice := big.NewInt(1000) - log.Debugf("gasPrice: %v\n", gasPrice) - - toAddress := common.HexToAddress(l.Blockchain.MessageAddress) - log.Debugf("toAddress: %v\n", toAddress) - - var signatures []string - err = json.Unmarshal([]byte(message.Signatures), &signatures) - if err != nil { - return errors.WithStack(err) - } - - data := msg.Send(message.FromChainId, common.HexToHash(message.FromId).Big(), message.FromSender, message.ToContractAddress, message.ToBytes, signatures) - log.Debugf("data: %x\n", data) - gasLimit, err := l.RPC.EstimateGas(context.Background(), ethereum.CallMsg{ - From: common.HexToAddress(UserAddress), - To: &toAddress, - GasPrice: gasPrice, - Value: big.NewInt(0), - Data: data, - }) - if err != nil { - log.Errorf("Get gasLimit err: %s\n", err) - return errors.WithStack(err) - } - log.Debugf("gasLimit: %v\n", gasLimit) - err = l.Db.Transaction(func(tx *gorm.DB) error { - // nonce - nonce, err := l.GetNonce(UserAddress) - if err != nil { - log.Errorf("Get nonce err: %s\n", err) - return errors.WithStack(err) - } - log.Debugf("nonce: %v\n", nonce) - // signTx - _signature, err := l.SignTx(UserAddress, nonce, toAddress.Hex(), big.NewInt(0), gasLimit, gasPrice, data, l.Blockchain.ChainId) - if err != nil { - log.Errorf("Sign Tx err: %s\n", err) - return errors.WithStack(err) - } - _txHash := crypto.Keccak256Hash(_signature) - log.Debugf("txHash: %s, signature: %s\n", _txHash, hex.EncodeToString(_signature)) - - // create signature - err = l.CreateSignature(tx, message.ToChainId, message.FromId, UserAddress, int64(nonce), enums.MessageTypeSend, hex.EncodeToString(data), decimal.Zero, hex.EncodeToString(_signature), _txHash.Hex()) - if err != nil { - log.Errorf("Create signature err: %s\n", err) - return errors.WithStack(err) - } - log.Infof("create signature success\n") - // broadcast - message.Status = enums.MessageStatusBroadcast - err = tx.Save(&message).Error - if err != nil { - log.Errorf("Broadcast approve err: %s\n", err) - return errors.WithStack(err) - } - log.Infof("handle approve success\n") - return nil - }) - if err != nil { - log.Errorf("Handle approve err: %s\n", err) - return errors.WithStack(err) - } - return nil -} - -func (l *Listener) pendingCallMessage(limit int) ([]models.Message, error) { - var list []models.Message - err := l.Db.Where("`to_chain_id`=? AND `type`=? AND `status`=?", l.Blockchain.ChainId, enums.MessageTypeCall, enums.MessageStatusPending).Limit(limit).Find(&list).Error - if err != nil { - return nil, err - } - return list, nil -} - -func (l *Listener) SignTx(accountAddress string, nonce uint64, toAddress string, value *big.Int, gasLimit uint64, gasPrice *big.Int, bytecode []byte, chainID int64) ([]byte, error) { - senderKey, err := l.getKeyByAddress(accountAddress) - if err != nil { - return nil, errors.WithStack(err) - } - _signature, err := l._signTx(accountAddress, senderKey, nonce, toAddress, value, gasLimit, gasPrice, bytecode, chainID) - if err != nil { - return nil, errors.WithStack(err) - } - return _signature, nil -} - -func (l *Listener) _signTx(accountAddress, accountKey string, nonce uint64, toAddress string, value *big.Int, gasLimit uint64, gasPrice *big.Int, bytecode []byte, chainID int64) ([]byte, error) { - _key, err := crypto.ToECDSA(common.FromHex(accountKey)) - if crypto.PubkeyToAddress(_key.PublicKey) != common.HexToAddress(accountAddress) { - return nil, errors.New(" address and index do not match ") - } - tx := types.NewTransaction( - nonce, - common.HexToAddress(toAddress), - value, - gasLimit, - gasPrice, - bytecode, - ) - signedTx, err := types.SignTx(tx, types.NewEIP155Signer(big.NewInt(chainID)), _key) - if err != nil { - return nil, err - } - ts := types.Transactions{signedTx} - var rawTxBytes bytes.Buffer - ts.EncodeIndex(0, &rawTxBytes) - return rawTxBytes.Bytes(), nil -} - -func (l *Listener) GetNonce(userAddress string) (uint64, error) { - var signature models.Signature - err := l.Db.Raw("SELECT * FROM signatures WHERE `status`!=? AND `address`=? ORDER BY nonce DESC FOR UPDATE ", - enums.SignatureStatusInvalid, userAddress).First(&signature).Error - if err != nil && err != gorm.ErrRecordNotFound { - return 0, err - } else if err == gorm.ErrRecordNotFound { - nonce, err := l.RPC.NonceAt(context.Background(), common.HexToAddress(userAddress), nil) - if err != nil { - return 0, err - } - log.Infof("==========nonce: %v\n", nonce) - return nonce, nil - } else { - if signature.Status != enums.SignatureStatusSuccess && signature.Status != enums.SignatureStatusFailed { - return 0, errors.New("The current user has pending transactions ") - } - nonce, err := l.RPC.NonceAt(context.Background(), common.HexToAddress(userAddress), nil) - if err != nil { - return 0, err - } - log.Infof("==========nonce: %v\n", nonce) - return nonce, nil - } -} - -func (l *Listener) CreateSignature(tx *gorm.DB, chainId int64, referId string, address string, nonce int64, signatureType enums.MessageType, data string, value decimal.Decimal, signature string, txHash string) error { - err := tx.Create(&models.Signature{ - ChainId: chainId, - ReferId: referId, - Address: address, - Nonce: nonce, - Type: signatureType, - Data: data, - Value: value, - Signature: signature, - Status: enums.SignatureStatusPending, - Blockchain: models.Blockchain{ - EventId: 0, - BlockTime: 0, - BlockNumber: 0, - LogIndex: 0, - TxHash: txHash, - }, - }).Error - if err != nil { - return err - } - return nil -} - -func (l *Listener) GasPrice() (*big.Int, error) { - gasPrice, err := l.RPC.SuggestGasPrice(context.Background()) - if err != nil { - return nil, errors.WithStack(err) - } - return gasPrice, nil -} - -func (l *Listener) LockUser(key string, duration time.Duration) (bool, error) { - return l.Cache.Client.SetNX(context.Background(), key, true, duration).Result() -} - -func (l *Listener) UnlockUser(key string) error { - _, err := l.Cache.Client.Del(context.Background(), key).Result() - return err -} - -func (l *Listener) BorrowAccount() (string, error) { - for address, _ := range l.DataMap.SenderMap { - return address, nil - } - return "", errors.New("account not found") -} - -func (l *Listener) getKeyByAddress(accountAddress string) (string, error) { - if key, ok := l.DataMap.SenderMap[accountAddress]; ok { - return key, nil - } else { - return "", errors.New("account not found") - } -} diff --git a/serv/internal/listener/eth/checkBlock.go b/serv/internal/listener/eth/checkBlock.go deleted file mode 100644 index e71291de..00000000 --- a/serv/internal/listener/eth/checkBlock.go +++ /dev/null @@ -1,106 +0,0 @@ -package eth - -import ( - "bsquared.network/b2-message-channel-serv/internal/models" - "github.com/ethereum/go-ethereum/common" - "github.com/pkg/errors" - log "github.com/sirupsen/logrus" - "gorm.io/gorm" - "time" -) - -func (l *Listener) checkBlock() { - duration := time.Millisecond * time.Duration(l.Blockchain.BlockInterval) - for { - var blocks []models.SyncBlock - // only check last 1000 block and event_count is 0 and Valid - start := l.SyncedBlockNumber - 1000 - if start < 0 { - start = 0 - } - end := l.SyncedBlockNumber - 100 - if end < 0 { - end = 0 - } - if start < end { - err := l.Db.Where("block_number BETWEEN ? AND ? AND status = ? AND event_count=? AND check_count<10", - start, end, models.BlockValid, 0).Order("block_number").Order("check_count").Find(&blocks).Error - if err != nil { - log.Errorf("[Handle.CheckBlock] Find Block err: %s\n", errors.WithStack(err)) - time.Sleep(duration) - continue - } - log.Errorf("[Handle.CheckBlock] Blocks Length is: %d", len(blocks)) - if len(blocks) == 0 { - time.Sleep(duration) - continue - } - for k, _ := range blocks { - block := blocks[k] - err = l.HandleCheckBlock(block) - if err != nil { - log.Errorf("[Handle.CheckBlock] Check Block err: %s\n", errors.WithStack(err)) - } - } - } else { - time.Sleep(duration) - } - } -} - -func (l *Listener) HandleCheckBlock(block models.SyncBlock) error { - log.Infof("[Handle.CheckBlock] Check Block: %d, %s\n", block.BlockNumber, block.BlockHash) - events, err := l.LogFilter(block, l.GetContracts(), [][]common.Hash{l.GetEvents()}) - if err != nil { - log.Errorf("[Handle.CheckBlock] Log filter err: %s\n", err) - return errors.WithStack(err) - } - eventCount := len(events) - if eventCount > 0 && events[0].BlockHash != block.BlockHash { - log.Errorf("[Handle.CheckBlock]Don't match block hash\n") - return nil - } else if eventCount > 0 && events[0].BlockHash == block.BlockHash { - BatchEvents := make([]*models.SyncEvent, 0) - for _, event := range events { - var one models.SyncEvent - err = l.Db.Where("sync_block_id=? AND block_log_indexed=? AND tx_hash=? AND event_hash=? ", - block.Id, event.BlockLogIndexed, event.TxHash, event.EventHash).First(&one).Error - if err != nil && err != gorm.ErrRecordNotFound { - log.Errorf("[Handle.CheckBlock]Query SyncEvent Is err %s\n", err) - return errors.WithStack(err) - } else if err == gorm.ErrRecordNotFound { - BatchEvents = append(BatchEvents, event) - } - } - if len(BatchEvents) > 0 { - err = l.Db.Transaction(func(tx *gorm.DB) error { - err = tx.CreateInBatches(&BatchEvents, 100).Error - if err != nil { - log.Errorf("[Handle.CheckBlock]CreateInBatches Is err %s\n", err) - return errors.WithStack(err) - } - block.Status = models.BlockValid - block.EventCount = int64(eventCount) - block.CheckCount = block.CheckCount + 1 - err = tx.Save(&block).Error - if err != nil { - return errors.WithStack(err) - } - return nil - }) - if err != nil { - return err - } - return nil - } - } - block.Status = models.BlockValid - block.EventCount = int64(eventCount) - block.CheckCount = block.CheckCount + 1 - //block - err = l.Db.Save(&block).Error - if err != nil { - return errors.WithStack(err) - } - return nil -} diff --git a/serv/internal/listener/eth/confirm.go b/serv/internal/listener/eth/confirm.go deleted file mode 100644 index f5bb5946..00000000 --- a/serv/internal/listener/eth/confirm.go +++ /dev/null @@ -1,81 +0,0 @@ -package eth - -import ( - "bsquared.network/b2-message-channel-serv/internal/enums" - "bsquared.network/b2-message-channel-serv/internal/models" - log "github.com/sirupsen/logrus" - "gorm.io/gorm" - "sync" - "time" -) - -func (l *Listener) confirm() { - duration := time.Millisecond * time.Duration(l.Blockchain.BlockInterval) - for { - list, err := l.pendingSendMessage(10) - if err != nil { - log.Errorf("Get pending call message err: %s\n", err) - time.Sleep(duration) - continue - } - if len(list) == 0 { - log.Infof("Get pending call message length is 0\n") - time.Sleep(duration) - continue - } - var wg sync.WaitGroup - for _, message := range list { - wg.Add(1) - go func(_wg *sync.WaitGroup, message models.Message) { - defer _wg.Done() - err = l.confirmMessage(message) - if err != nil { - log.Errorf("Handle err: %v, %v\n", err, message) - } - }(&wg, message) - } - wg.Wait() - } -} - -func (l *Listener) confirmMessage(message models.Message) error { - err := l.Db.Transaction(func(tx *gorm.DB) error { - err := tx.Model(models.Message{}).Where("type=? AND from_chain_id=? AND from_id=? AND status=?", - enums.MessageTypeCall, message.FromChainId, message.FromId, enums.MessageStatusBroadcast). - Update("status", enums.MessageStatusValid).Error - if err != nil { - return err - } - err = tx.Model(models.Message{}).Where("id=? AND status=?", message.Id, message.Status). - Update("status", enums.MessageStatusValid).Error - if err != nil { - return err - } - err = tx.Model(models.Signature{}).Where("chain_id=? AND refer_id=?", message.ChainId, message.FromId). - Updates(map[string]interface{}{ - "status": enums.SignatureStatusSuccess, - "event_id": message.EventId, - "block_time": message.BlockTime, - "block_number": message.BlockNumber, - "log_index": message.LogIndex, - "tx_hash": message.TxHash, - }).Error - if err != nil { - return err - } - return nil - }) - if err != nil { - return err - } - return nil -} - -func (l *Listener) pendingSendMessage(limit int) ([]models.Message, error) { - var list []models.Message - err := l.Db.Where("`to_chain_id`=? AND `type`=? AND status=?", l.Blockchain.ChainId, enums.MessageTypeSend, enums.MessageStatusPending).Limit(limit).Find(&list).Error - if err != nil { - return nil, err - } - return list, nil -} diff --git a/serv/internal/listener/eth/consume.go b/serv/internal/listener/eth/consume.go deleted file mode 100644 index be7267bc..00000000 --- a/serv/internal/listener/eth/consume.go +++ /dev/null @@ -1,158 +0,0 @@ -package eth - -import ( - "bsquared.network/b2-message-channel-serv/internal/enums" - "bsquared.network/b2-message-channel-serv/internal/event/message" - "bsquared.network/b2-message-channel-serv/internal/models" - "fmt" - "github.com/ethereum/go-ethereum/common" - "github.com/pkg/errors" - log "github.com/sirupsen/logrus" - "gorm.io/gorm" - "time" -) - -func (l *Listener) consume() { - duration := time.Millisecond * time.Duration(l.Blockchain.BlockInterval) - for { - events, err := l.listPendingEvent(500) - if err != nil { - log.Errorf("list pending event err: %v\n", err) - time.Sleep(duration) - continue - } - if len(events) == 0 { - log.Infof("list pending event length is 0\n") - time.Sleep(duration) - continue - } - valids := make([]int64, 0) - invalids := make([]int64, 0) - messages := make([]models.Message, 0) - handles := make(map[string]bool) - - var Type enums.MessageType - var FromChainId int64 - var FromSender string - var FromId string - var ToChainId int64 - var ToContractAddress string - var ToBytes string - var status enums.MessageStatus - - for _, event := range events { - key := fmt.Sprintf("%s#%d", event.TxHash, event.BlockLogIndexed) - if handles[key] { - invalids = append(invalids, event.Id) - continue - } - - if event.EventName == message.MessageCallName { - var messageCall message.MessageCall - err := (&messageCall).ToObj(event.Data) - if err != nil { - log.Errorf("event to data err: %v, data: %v\n", err, event) - time.Sleep(duration) - continue - } - FromChainId = messageCall.FromChainId - FromSender = messageCall.FromSender - FromId = common.BytesToHash(messageCall.FromId.BigInt().Bytes()).Hex() - ToChainId = messageCall.ToChainId - ToContractAddress = messageCall.ContractAddress - ToBytes = messageCall.Bytes - Type = enums.MessageTypeCall - status = enums.MessageStatusValidating - } else if event.EventName == message.MessageSendName { - var messageSend message.MessageSend - err := (&messageSend).ToObj(event.Data) - if err != nil { - log.Errorf("event to data err: %v, data: %v\n", err, event) - continue - } - FromChainId = messageSend.FromChainId - FromSender = messageSend.FromSender - FromId = common.BytesToHash(messageSend.FromId.BigInt().Bytes()).Hex() - ToChainId = messageSend.ToChainId - ToContractAddress = messageSend.ContractAddress - ToBytes = messageSend.Bytes - Type = enums.MessageTypeSend - status = enums.MessageStatusPending - } - - var message models.Message - err = l.Db.Where("`tx_hash`=? AND `log_index`=?", event.TxHash, event.BlockLogIndexed).First(&message).Error - if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) { - log.Errorf("get message err: %v, data: %v\n", err, event) - time.Sleep(duration) - continue - } else if errors.Is(err, gorm.ErrRecordNotFound) { - handles[key] = true - message = models.Message{ - ChainId: event.ChainId, - Type: Type, - FromChainId: FromChainId, - FromSender: FromSender, - FromContractAddress: event.ContractAddress, - FromId: FromId, - ToChainId: ToChainId, - ToContractAddress: ToContractAddress, - ToBytes: ToBytes, - Signatures: "[]", - Status: status, - Blockchain: models.Blockchain{ - EventId: event.Id, - BlockTime: event.BlockTime, - BlockNumber: event.BlockNumber, - LogIndex: event.BlockLogIndexed, - TxHash: event.TxHash, - }, - } - messages = append(messages, message) - valids = append(valids, event.Id) - } else { - invalids = append(invalids, event.Id) - } - - } - err = l.Db.Transaction(func(tx *gorm.DB) error { - if len(valids) > 0 { - err = tx.Model(models.SyncEvent{}).Where("id in (?)", valids).Update("status", models.EventValid).Error - if err != nil { - log.Errorf("update valid Event err: %v, data: %v\n", err, valids) - return err - } - } - if len(invalids) > 0 { - err = tx.Model(models.SyncEvent{}).Where("id in (?)", invalids).Update("status", models.EventInvalid).Error - if err != nil { - log.Errorf("update invalid Event err: %v, data: %v\n", err, invalids) - return err - } - } - if len(messages) > 0 { - err = tx.CreateInBatches(messages, 100).Error - if err != nil { - log.Errorf("create in batches err: %v\n", err) - return err - } - } - return nil - }) - if err != nil { - log.Errorf("consume events err: %v\n", err) - time.Sleep(duration) - } - } -} - -func (l *Listener) listPendingEvent(limit int) ([]models.SyncEvent, error) { - var list []models.SyncEvent - err := l.Db.Model(models.SyncEvent{}).Where("`chain_id`=? AND `event_hash` in ? AND `status`=?", - l.Blockchain.ChainId, l.GetEventStrs(), models.EventPending). - Limit(limit).Find(&list).Error - if err != nil { - return nil, errors.WithStack(err) - } - return list, nil -} diff --git a/serv/internal/listener/eth/listener.go b/serv/internal/listener/eth/listener.go deleted file mode 100644 index ffc91cae..00000000 --- a/serv/internal/listener/eth/listener.go +++ /dev/null @@ -1,66 +0,0 @@ -package eth - -import ( - "bsquared.network/b2-message-channel-serv/internal/config" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/ethclient" - "gorm.io/gorm" -) - -type DataMap struct { - Events []common.Hash - Contracts []common.Address - EventMap map[common.Hash][]Event - SenderMap map[string]string - ValidatorMap map[string]string -} - -type Listener struct { - DataMap DataMap - Blockchain config.Blockchain - Db *gorm.DB - Cache *config.Cache - RPC *ethclient.Client - LatestBlockNumber int64 - SyncedBlockNumber int64 - SyncedBlockHash common.Hash -} - -func NewListener(db *gorm.DB, cache *config.Cache, blockchain config.Blockchain) *Listener { - rpc := config.InitB2Rpc(blockchain.RpcUrl) - return &Listener{ - Blockchain: blockchain, - Db: db, - Cache: cache, - RPC: rpc, - LatestBlockNumber: blockchain.InitBlockNumber, - SyncedBlockNumber: 0, - SyncedBlockHash: common.HexToHash("0x0"), - DataMap: DataMap{ - Events: make([]common.Hash, 0), - Contracts: make([]common.Address, 0), - EventMap: make(map[common.Hash][]Event, 0), - SenderMap: make(map[string]string, 0), - ValidatorMap: make(map[string]string, 0), - }, - } -} - -func (l *Listener) Run() { - l.loadAccounts() - l.AutoRegister() - if l.Blockchain.Rollback { - go l.syncBlock() - go l.syncEvent() - go l.checkBlock() - go l.migrateBlock() - go l.migrateEvent() - } - go l.syncLatestBlockNumber() - go l.syncTask() - go l.consume() - go l.confirm() - go l.broadcast() - go l.build() - go l.validate() -} diff --git a/serv/internal/listener/eth/logFilter.go b/serv/internal/listener/eth/logFilter.go deleted file mode 100644 index f158f62a..00000000 --- a/serv/internal/listener/eth/logFilter.go +++ /dev/null @@ -1,102 +0,0 @@ -package eth - -import ( - "bsquared.network/b2-message-channel-serv/internal/event" - "bsquared.network/b2-message-channel-serv/internal/models" - rpc2 "bsquared.network/b2-message-channel-serv/internal/utils/rpc" - "context" - "fmt" - "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/pkg/errors" - log "github.com/sirupsen/logrus" - "math/big" - "strings" - "time" -) - -func (l *Listener) LogBatchFilter(startBlock, endBlock int64, addresses []common.Address, topics [][]common.Hash) ([]*models.SyncEvent, error) { - query := ethereum.FilterQuery{ - FromBlock: big.NewInt(startBlock), - ToBlock: big.NewInt(endBlock), - Topics: topics, - Addresses: addresses, - } - logs, err := l.RPC.FilterLogs(context.Background(), query) - if err != nil { - return nil, errors.WithStack(err) - } - return l.LogsToEvents(logs, startBlock) -} - -func (l *Listener) LogFilter(block models.SyncBlock, addresses []common.Address, topics [][]common.Hash) ([]*models.SyncEvent, error) { - query := ethereum.FilterQuery{ - FromBlock: big.NewInt(block.BlockNumber), - ToBlock: big.NewInt(block.BlockNumber), - Topics: topics, - Addresses: addresses, - } - logs, err := l.RPC.FilterLogs(context.Background(), query) - if err != nil { - return nil, errors.WithStack(err) - } - log.Infof("[CancelOrder.Handle] Cancel Pending List Length is %d ,block number is %d \n", len(logs), block.BlockNumber) - return l.LogsToEvents(logs, block.Id) -} - -func (l *Listener) LogsToEvents(logs []types.Log, syncBlockId int64) ([]*models.SyncEvent, error) { - var events []*models.SyncEvent - blockTimes := make(map[int64]int64) - for _, vlog := range logs { - eventHash := event.TopicToHash(vlog, 0) - contractAddress := vlog.Address - Event := l.GetEvent(eventHash, contractAddress) - if Event == nil { - log.Infof("[LogsToEvents] logs[txHash: %s, contractAddress:%s, eventHash: %s]\n", vlog.TxHash, strings.ToLower(contractAddress.Hex()), eventHash) - continue - } - - blockTime := blockTimes[int64(vlog.BlockNumber)] - if blockTime == 0 { - blockJson, err := rpc2.HttpPostJson("", l.Blockchain.RpcUrl, "{\"jsonrpc\":\"2.0\",\"method\":\"eth_getBlockByNumber\",\"params\":[\""+fmt.Sprintf("0x%X", vlog.BlockNumber)+"\", true],\"id\":1}") - if err != nil { - log.Errorf("[Handler.SyncBlock] Syncing block by number error: %s\n", errors.WithStack(err)) - time.Sleep(3 * time.Second) - continue - } - block := rpc2.ParseJsonBlock(string(blockJson)) - // - //block, err := ctx.RPC.BlockByNumber(context.Background(), big.NewInt(int64(vlog.BlockNumber))) - //if err != nil { - // return nil, errors.WithStack(err) - //} - blockTime = int64(block.Timestamp()) - blockTimes[int64(vlog.BlockNumber)] = blockTime - } - - data, err := Event.Data(vlog) - if err != nil { - log.Errorf("[LogsToEvents] logs[txHash: %s, contractAddress:%s, eventHash: %s]\n", vlog.TxHash, strings.ToLower(contractAddress.Hex()), eventHash) - log.Errorf("[LogsToEvents] data err: %s\n", errors.WithStack(err)) - continue - } - - events = append(events, &models.SyncEvent{ - ChainId: l.Blockchain.ChainId, - SyncBlockId: syncBlockId, - BlockTime: blockTime, - BlockNumber: int64(vlog.BlockNumber), - BlockHash: vlog.BlockHash.Hex(), - BlockLogIndexed: int64(vlog.Index), - TxIndex: int64(vlog.TxIndex), - TxHash: vlog.TxHash.Hex(), - EventName: Event.Name(), - EventHash: eventHash.Hex(), - ContractAddress: strings.ToLower(contractAddress.Hex()), - Data: data, - Status: models.EventPending, - }) - } - return events, nil -} diff --git a/serv/internal/listener/eth/migrateBlock.go b/serv/internal/listener/eth/migrateBlock.go deleted file mode 100644 index ab4dcaa7..00000000 --- a/serv/internal/listener/eth/migrateBlock.go +++ /dev/null @@ -1,77 +0,0 @@ -package eth - -import ( - "bsquared.network/b2-message-channel-serv/internal/models" - "github.com/pkg/errors" - log "github.com/sirupsen/logrus" - "gorm.io/gorm" - "strings" - "time" -) - -func (l *Listener) migrateBlock() { - duration := time.Millisecond * time.Duration(l.Blockchain.BlockInterval) - for { - queryBlockNum := l.SyncedBlockNumber - 100000 - if queryBlockNum < 100 { - time.Sleep(duration) - continue - } - var blocks []models.SyncBlock - err := l.Db.Model(models.SyncBlock{}).Where("chain_id=? AND (status=? OR status=?) AND block_number < ?", - l.Blockchain.ChainId, models.BlockValid, models.BlockInvalid, queryBlockNum). - Order("block_number").Limit(400).Find(&blocks).Error - if err != nil { - log.Errorf("[Handler.MigrateBlock] Find Blocks err: %s\n", err) - time.Sleep(duration) - continue - } - if len(blocks) == 0 { - time.Sleep(duration) - continue - } - - delIds := make([]int64, len(blocks), len(blocks)) - blocksHis := make([]*models.SyncBlockHistory, len(blocks), len(blocks)) - for i, v := range blocks { - delIds[i] = v.Id - blocksHis[i] = &models.SyncBlockHistory{ - Base: models.Base{ - Id: v.Id, - CreatedAt: v.CreatedAt, - UpdatedAt: v.UpdatedAt, - }, - ChainId: v.ChainId, - Miner: v.Miner, - BlockTime: v.BlockTime, - BlockNumber: v.BlockNumber, - BlockHash: v.BlockHash, - TxCount: v.TxCount, - EventCount: v.EventCount, - ParentHash: v.ParentHash, - Status: v.Status, - } - } - - err = l.Db.Transaction(func(tx *gorm.DB) error { - err := tx.CreateInBatches(blocksHis, 100).Error - if err != nil && strings.Index(err.Error(), "Duplicate") == -1 { - log.Errorf("[Handler.MigrateBlock] CreateInBatches err: %s\n", err) - return errors.WithStack(err) - } - err = tx.Where("id in ?", delIds).Delete(models.SyncBlock{}).Error - if err != nil { - log.Errorf("[Handler.MigrateBlock] Delete SyncBlock err: %s\n", err) - return errors.WithStack(err) - } - return nil - }) - - if err != nil { - log.Errorf("[Handler.MigrateBlock] err: %s\n", err) - time.Sleep(duration) - continue - } - - } -} diff --git a/serv/internal/listener/eth/migrateEvent.go b/serv/internal/listener/eth/migrateEvent.go deleted file mode 100644 index a0dc510c..00000000 --- a/serv/internal/listener/eth/migrateEvent.go +++ /dev/null @@ -1,81 +0,0 @@ -package eth - -import ( - "bsquared.network/b2-message-channel-serv/internal/models" - "github.com/pkg/errors" - log "github.com/sirupsen/logrus" - "gorm.io/gorm" - "strings" - "time" -) - -func (l *Listener) migrateEvent() { - duration := time.Millisecond * time.Duration(l.Blockchain.BlockInterval) - for { - queryBlockNum := l.SyncedBlockNumber - 100000 - if queryBlockNum < 100 { - time.Sleep(duration) - continue - } - var events []models.SyncEvent - err := l.Db.Model(models.SyncEvent{}).Where("chain_id=? AND (status=? OR status=?) AND block_number < ?", - l.Blockchain.ChainId, models.EventValid, models.EventInvalid, queryBlockNum). - Order("block_number").Order("block_log_indexed").Limit(400).Find(&events).Error - if err != nil { - log.Errorf("[Handler.MigrateEvent] Find Events err: %s\n", errors.WithStack(err)) - time.Sleep(duration) - continue - } - if len(events) == 0 { - time.Sleep(duration) - continue - } - - delIds := make([]int64, len(events), len(events)) - eventsHis := make([]*models.SyncEventHistory, len(events), len(events)) - for i, v := range events { - delIds[i] = v.Id - eventsHis[i] = &models.SyncEventHistory{ - Base: models.Base{ - Id: v.Id, - CreatedAt: v.CreatedAt, - UpdatedAt: v.UpdatedAt, - }, - SyncBlockId: v.SyncBlockId, - ChainId: v.ChainId, - BlockTime: v.BlockTime, - BlockNumber: v.BlockNumber, - BlockHash: v.BlockHash, - BlockLogIndexed: v.BlockLogIndexed, - TxIndex: v.TxIndex, - TxHash: v.TxHash, - EventName: v.EventName, - EventHash: v.EventHash, - ContractAddress: v.ContractAddress, - Data: v.Data, - Status: v.Status, - } - } - - err = l.Db.Transaction(func(tx *gorm.DB) error { - err := tx.CreateInBatches(eventsHis, 100).Error - if err != nil && strings.Index(err.Error(), "Duplicate") == -1 { - log.Errorf("[Handler.MigrateEvent] CreateInBatches err: %s\n", err) - return errors.WithStack(err) - } - - err = tx.Where("id in ?", delIds).Delete(models.SyncEvent{}).Error - if err != nil { - return errors.WithStack(err) - } - return nil - }) - - if err != nil { - log.Errorf("[Handler.MigrateEvent] err: %s\n", err) - time.Sleep(duration) - continue - } - - } -} diff --git a/serv/internal/listener/eth/register.go b/serv/internal/listener/eth/register.go deleted file mode 100644 index 011cd250..00000000 --- a/serv/internal/listener/eth/register.go +++ /dev/null @@ -1,96 +0,0 @@ -package eth - -import ( - "bsquared.network/b2-message-channel-serv/internal/event/message" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - log "github.com/sirupsen/logrus" - "strings" -) - -type Event interface { - Name() string - EventHash() common.Hash - Data(log types.Log) (string, error) - ToObj(data string) error -} - -func (l *Listener) AutoRegister() { - events := strings.Split(l.Blockchain.Events, ",") - for _, event := range events { - switch common.HexToHash(event) { - case common.BytesToHash(message.MessageCallHash): - l.Register(&message.MessageCall{}) - case common.BytesToHash(message.MessageSendHash): - l.Register(&message.MessageSend{}) - } - } - l.AddContract(l.Blockchain.MessageAddress) -} - -func (l *Listener) loadAccounts() { - senders := strings.Split(l.Blockchain.Senders, ",") - for i, accountKey := range senders { - accountAddress, err := l.ToAddress(accountKey) - if err != nil { - log.Panicf("senders[%d] invalid", i) - continue - } - l.DataMap.SenderMap[accountAddress] = accountKey - } - validators := strings.Split(l.Blockchain.Validators, ",") - for i, accountKey := range validators { - accountAddress, err := l.ToAddress(accountKey) - if err != nil { - log.Panicf("validators[%d] invalid", i) - continue - } - l.DataMap.ValidatorMap[accountAddress] = accountKey - } -} - -func (l *Listener) ToAddress(accountKey string) (string, error) { - _key, err := crypto.ToECDSA(common.FromHex(accountKey)) - if err != nil { - return "", err - } - return crypto.PubkeyToAddress(_key.PublicKey).Hex(), nil -} - -func (l *Listener) Register(event Event) { - if len(l.DataMap.EventMap[event.EventHash()]) == 0 { - l.DataMap.Events = append(l.DataMap.Events, event.EventHash()) - } - l.DataMap.EventMap[event.EventHash()] = append(l.DataMap.EventMap[event.EventHash()], event) -} - -func (l *Listener) AddContract(contract string) { - l.DataMap.Contracts = append(l.DataMap.Contracts, common.HexToAddress(contract)) -} - -func (l *Listener) GetContracts() []common.Address { - return l.DataMap.Contracts -} - -func (l *Listener) GetEvents() []common.Hash { - return l.DataMap.Events -} - -func (l *Listener) GetEventStrs() []string { - strs := make([]string, 0) - for _, event := range l.DataMap.Events { - strs = append(strs, event.Hex()) - } - return strs -} - -func (l *Listener) GetEventsByTask() []common.Hash { - return l.DataMap.Events -} - -func (l *Listener) GetEvent(eventHash common.Hash, contractAddress common.Address) Event { - EventList := l.DataMap.EventMap[eventHash] - Event := EventList[0] - return Event -} diff --git a/serv/internal/listener/eth/syncBlock.go b/serv/internal/listener/eth/syncBlock.go deleted file mode 100644 index d5b62366..00000000 --- a/serv/internal/listener/eth/syncBlock.go +++ /dev/null @@ -1,119 +0,0 @@ -package eth - -import ( - "bsquared.network/b2-message-channel-serv/internal/models" - rpc2 "bsquared.network/b2-message-channel-serv/internal/utils/rpc" - "fmt" - "github.com/ethereum/go-ethereum/common" - "github.com/pkg/errors" - log "github.com/sirupsen/logrus" - "gorm.io/gorm" - "time" -) - -func (l *Listener) syncBlock() { - duration := time.Millisecond * time.Duration(l.Blockchain.BlockInterval) - var syncedBlock models.SyncBlock - err := l.Db.Where("chain_id =? AND (status = ? or status = ?) ", l.Blockchain.ChainId, models.BlockValid, models.BlockPending).Order("block_number desc").First(&syncedBlock).Error - if err != nil && err != gorm.ErrRecordNotFound { - panic(err) - } else if err == gorm.ErrRecordNotFound { - l.SyncedBlockNumber = l.Blockchain.InitBlockNumber - l.SyncedBlockHash = common.HexToHash(l.Blockchain.InitBlockHash) - } else { - l.SyncedBlockNumber = syncedBlock.BlockNumber - l.SyncedBlockHash = common.HexToHash(syncedBlock.BlockHash) - } - log.Infof("[Handler.SyncBlock] blockNumber: %d, blockHash:%s \n", l.SyncedBlockNumber, l.SyncedBlockHash) - - for { - syncingBlockNumber := l.SyncedBlockNumber + 1 - log.Infof("[Handler.SyncBlock] Try to sync block number: %d\n", syncingBlockNumber) - - if syncingBlockNumber > l.LatestBlockNumber { - time.Sleep(duration) - continue - } - - //block, err := ctx.RPC.BlockByNumber(context.Background(), big.NewInt(syncingBlockNumber)) - blockJson, err := rpc2.HttpPostJson("", l.Blockchain.RpcUrl, "{\"jsonrpc\":\"2.0\",\"method\":\"eth_getBlockByNumber\",\"params\":[\""+fmt.Sprintf("0x%X", syncingBlockNumber)+"\", true],\"id\":1}") - if err != nil { - log.Errorf("[Handler.SyncBlock] Syncing block by number error: %s\n", errors.WithStack(err)) - time.Sleep(duration) - continue - } - block := rpc2.ParseJsonBlock(string(blockJson)) - log.Infof("[Handler.SyncBlock] Syncing block number: %d, hash: %s, parent hash: %s,synced parent hash: %s \n", block.Number(), block.Hash(), block.ParentHash(), l.SyncedBlockHash) - - // 回滚判断 - if common.HexToHash(block.ParentHash()) != l.SyncedBlockHash { - log.Errorf("[Handler.SyncBlock] ParentHash of the block being synchronized is inconsistent: %s \n", l.SyncedBlockHash) - l.rollbackBlock() - time.Sleep(duration) - continue - } - - /* Create SyncBlock start */ - err = l.Db.Create(&models.SyncBlock{ - Miner: block.Result.Miner, - ChainId: l.Blockchain.ChainId, - BlockTime: int64(block.Timestamp()), - BlockNumber: block.Number(), - BlockHash: block.Hash(), - TxCount: int64(len(block.Result.Transactions)), - EventCount: 0, - ParentHash: block.ParentHash(), - Status: models.BlockPending, - }).Error - if err != nil { - log.Errorf("[Handler.SyncBlock] Db Create SyncBlock error: %s\n", errors.WithStack(err)) - time.Sleep(duration) - continue - } - /* Create SyncBlock end */ - l.SyncedBlockNumber = block.Number() - l.SyncedBlockHash = common.HexToHash(block.Hash()) - } -} - -func (l *Listener) rollbackBlock() { - for { - rollbackBlockNumber := l.SyncedBlockNumber - - log.Infof("[Handler.SyncBlock.RollRackBlock] Try to rollback block number: %d\n", rollbackBlockNumber) - - //rollbackBlock, err := ctx.RPC.BlockByNumber(context.Background(), big.NewInt(rollbackBlockNumber)) - blockJson, err := rpc2.HttpPostJson("", l.Blockchain.RpcUrl, "{\"jsonrpc\":\"2.0\",\"method\":\"eth_getBlockByNumber\",\"params\":[\""+fmt.Sprintf("0x%X", rollbackBlockNumber)+"\", true],\"id\":1}") - if err != nil { - log.Errorf("[Handler.SyncBlock.RollRackBlock]Rollback block by number error: %s\n", errors.WithStack(err)) - continue - } - rollbackBlock := rpc2.ParseJsonBlock(string(blockJson)) - log.Errorf("[Handler.SyncBlock.RollRackBlock] rollbackBlock: %s, syncedBlockHash: %s \n", rollbackBlock.Hash(), l.SyncedBlockHash) - - if common.HexToHash(rollbackBlock.Hash()) == l.SyncedBlockHash { - err = l.Db.Transaction(func(tx *gorm.DB) error { - err = tx.Model(models.SyncBlock{}).Where("`chain_id`=? AND (status = ? or status = ?) AND block_number>?", models.BlockValid, models.BlockPending, l.SyncedBlockNumber).Update("status", models.BlockRollback).Error - if err != nil { - log.Errorf("[Handler.SyncBlock.RollRackBlock] Rollback Block err: %s\n", errors.WithStack(err)) - return err - } - return nil - }) - if err != nil { - log.Errorf("[Handler.SyncBlock.RollRackBlock] Rollback db transaction err: %s\n", errors.WithStack(err)) - continue - } - log.Infof("[Handler.SyncBlock.RollRackBlock] Rollback blocks is Stop\n") - return - } - var previousBlock models.SyncBlock - rest := l.Db.Where("`chain_id`=? AND `block_number`=? AND (status=? or status=?) ", l.Blockchain.ChainId, rollbackBlockNumber-1, models.BlockValid, models.BlockPending).First(&previousBlock) - if rest.Error != nil { - log.Errorf("[Handler.RollRackBlock] Previous block by number error: %s\n", errors.WithStack(rest.Error)) - continue - } - l.SyncedBlockNumber = previousBlock.BlockNumber - l.SyncedBlockHash = common.HexToHash(previousBlock.BlockHash) - } -} diff --git a/serv/internal/listener/eth/syncEvent.go b/serv/internal/listener/eth/syncEvent.go deleted file mode 100644 index 65be5bfd..00000000 --- a/serv/internal/listener/eth/syncEvent.go +++ /dev/null @@ -1,139 +0,0 @@ -package eth - -import ( - "bsquared.network/b2-message-channel-serv/internal/models" - "github.com/ethereum/go-ethereum/common" - "github.com/pkg/errors" - log "github.com/sirupsen/logrus" - "gorm.io/gorm" - "sync" - "time" -) - -func (l *Listener) syncEvent() { - for { - duration := time.Millisecond * time.Duration(l.Blockchain.BlockInterval) - var blocks []models.SyncBlock - err := l.Db.Where("chain_id=? AND (status=? OR status=?)", l.Blockchain.ChainId, models.BlockPending, models.BlockRollback).Order("block_number").Limit(50).Find(&blocks).Error - if err != nil { - log.Errorf("[Handler.SyncEvent] Pending and rollback blocks err: %s\n", errors.WithStack(err)) - time.Sleep(duration) - continue - } - if len(blocks) == 0 { - log.Infof("[Handler.SyncEvent] Pending blocks count is 0\n") - time.Sleep(duration) - continue - } - - var wg sync.WaitGroup - for _, block := range blocks { - wg.Add(1) - go func(_wg *sync.WaitGroup, block models.SyncBlock) { - defer _wg.Done() - if block.Status == models.BlockPending { - // add events & block.status= valid - err = l.handlePendingBlock(block) - if err != nil { - log.Errorf("[Handler.SyncEvent] HandlePendingBlock err: %s\n", errors.WithStack(err)) - } - } else if block.Status == models.BlockRollback { - // event.status=rollback & block.status=invalid - err = l.handleRollbackBlock(block) - if err != nil { - log.Errorf("[Handler.SyncEvent] HandleRollbackBlock err: %s\n", errors.WithStack(err)) - } - } - }(&wg, block) - } - wg.Wait() - } -} - -func (l *Listener) handlePendingBlock(block models.SyncBlock) error { - log.Infof("[Handler.SyncEvent.PendingBlock]Start: %d, %s \n", block.BlockNumber, block.BlockHash) - log.Infof("[Handler.SyncEvent.PendingBlock]GetContracts: %v\n", l.GetContracts()) - log.Infof("[Handler.SyncEvent.PendingBlock]GetEvents: %v\n", l.GetEvents()) - events, err := l.LogFilter(block, l.GetContracts(), [][]common.Hash{l.GetEvents()}) - log.Infof("[Handler.SyncEvent.PendingBlock] block %d, events number is %d:", block.BlockNumber, len(events)) - if err != nil { - log.Errorf("[Handler.SyncEvent.PendingBlock] Log filter err: %s\n", err) - return errors.WithStack(err) - } - eventCount := len(events) - if eventCount > 0 && events[0].BlockHash != block.BlockHash { - log.Infof("[Handler.SyncEvent.PendingBlock]Don't match block hash\n") - return nil - } else if eventCount > 0 && events[0].BlockHash == block.BlockHash { - BatchEvents := make([]*models.SyncEvent, 0) - for _, event := range events { - var one models.SyncEvent - log.Infof("[Handler.SyncEvent.PendingBlock]BlockLogIndexed: %d ,TxHash: %s,EventHash: %s\n", event.BlockLogIndexed, event.TxHash, event.EventHash) - err = l.Db.Select("id").Where("sync_block_id=? AND block_log_indexed=? AND tx_hash=? AND event_hash=? ", - block.Id, event.BlockLogIndexed, event.TxHash, event.EventHash).First(&one).Error - if err != nil && err != gorm.ErrRecordNotFound { - log.Errorf("[Handler.SyncEvent.PendingBlock]Query SyncEvent err: %s\n ", err) - return errors.WithStack(err) - } else if err == gorm.ErrRecordNotFound { - BatchEvents = append(BatchEvents, event) - log.Infof("[Handler.SyncEvent.PendingBlock]block %d, BatchEvents len is %d:", block.BlockNumber, len(BatchEvents)) - } - } - if len(BatchEvents) > 0 { - err = l.Db.Transaction(func(tx *gorm.DB) error { - err = tx.CreateInBatches(&BatchEvents, 200).Error - if err != nil { - log.Errorf("[Handler.SyncEvent.PendingBlock]CreateInBatches err: %s\n ", err) - return errors.WithStack(err) - } - block.Status = models.BlockValid - block.EventCount = int64(eventCount) - err = tx.Save(&block).Error - if err != nil { - log.Errorf("[Handler.SyncEvent.PendingBlock]Batch Events Update SyncBlock Status err: %s\n ", err) - return errors.WithStack(err) - } - return nil - }) - if err != nil { - return err - } - return nil - } - } - block.Status = models.BlockValid - block.EventCount = int64(eventCount) - err = l.Db.Save(&block).Error - if err != nil { - log.Errorf("[Handler.PendingBlock]Update SyncBlock Status err: %s\n ", err) - return errors.WithStack(err) - } - log.Infof("[Handler.SyncEvent.PendingBlock]End: %d, %s \n", block.BlockNumber, block.BlockHash) - return nil -} - -func (l *Listener) handleRollbackBlock(block models.SyncBlock) error { - log.Infof("[Handler.RollbackBlock] Start: %d, %s\n", block.BlockNumber, block.BlockHash) - err := l.Db.Transaction(func(tx *gorm.DB) error { - now := time.Now() - // event.status=rollback by syncBlockId - err := tx.Model(models.SyncEvent{}).Where("sync_block_id=?", block.Id). - Updates(map[string]interface{}{"status": models.EventRollback, "updated_at": now}).Error - if err != nil { - log.Errorf("[Handler.RollbackBlock]Query SyncBlock Status err: %s ,id : %d \n", err, block.Id) - return errors.WithStack(err) - } - block.Status = models.BlockInvalid - err = tx.Save(&block).Error - if err != nil { - log.Errorf("[Handler.RollbackBlock]Save SyncBlock Status err: %s\n ", err) - return errors.WithStack(err) - } - return nil - }) - if err != nil { - log.Errorf("[Handler.RollbackBlock] err: %s\n ", err) - return errors.WithStack(err) - } - return nil -} diff --git a/serv/internal/listener/eth/syncLatestBlockNumber.go b/serv/internal/listener/eth/syncLatestBlockNumber.go deleted file mode 100644 index 3fcda7f3..00000000 --- a/serv/internal/listener/eth/syncLatestBlockNumber.go +++ /dev/null @@ -1,22 +0,0 @@ -package eth - -import ( - "context" - log "github.com/sirupsen/logrus" - "time" -) - -func (l *Listener) syncLatestBlockNumber() { - for { - duration := time.Millisecond * time.Duration(l.Blockchain.BlockInterval) - latest, err := l.RPC.BlockNumber(context.Background()) - if err != nil { - log.Errorf("[Handle.LatestBlackNumber][%d]Syncing latest block number error: %s\n", l.Blockchain.ChainId, err) - time.Sleep(duration) - continue - } - l.LatestBlockNumber = int64(latest) - log.Infof("[Handle.LatestBlackNumber][%d]Syncing latest block number: %d \n", l.Blockchain.ChainId, latest) - time.Sleep(duration) - } -} diff --git a/serv/internal/listener/eth/syncTask.go b/serv/internal/listener/eth/syncTask.go deleted file mode 100644 index 2651a777..00000000 --- a/serv/internal/listener/eth/syncTask.go +++ /dev/null @@ -1,139 +0,0 @@ -package eth - -import ( - "bsquared.network/b2-message-channel-serv/internal/enums" - "bsquared.network/b2-message-channel-serv/internal/models" - "github.com/ethereum/go-ethereum/common" - "github.com/pkg/errors" - log "github.com/sirupsen/logrus" - "gorm.io/gorm" - "strings" - "sync" - "time" -) - -func (l *Listener) syncTask() { - for { - duration := time.Millisecond * time.Duration(l.Blockchain.BlockInterval) - var tasks []models.SyncTask - err := l.Db.Where("`chain_type`=? AND chain_id=? AND status=?", enums.ChainTypeEthereum, l.Blockchain.ChainId, models.SyncTaskPending).Limit(20).Find(&tasks).Error - if err != nil { - time.Sleep(duration) - continue - } - if len(tasks) == 0 { - log.Infof("[Handler.syncTask] Pending tasks count is 0\n") - time.Sleep(duration) - continue - } - wg := sync.WaitGroup{} - for _, task := range tasks { - wg.Add(1) - go func(take models.SyncTask, wg *sync.WaitGroup) { - defer wg.Done() - err := l.HandleTake(take) - if err != nil { - log.Errorf("[Handler.SyncTask] HandleTask ID: %d , err: %s \n", task.Id, err) - } - }(task, &wg) - - } - wg.Wait() - } -} - -func GetContracts(Contracts string) []common.Address { - list := strings.Split(Contracts, ",") - AddressList := make([]common.Address, 0) - for _, one := range list { - if one != "" { - AddressList = append(AddressList, common.HexToAddress(one)) - } - } - return AddressList -} - -func (l *Listener) HandleTake(task models.SyncTask) error { - start := task.LatestBlock - if task.StartBlock > start { - start = task.StartBlock - } - - if task.EndBlock > 0 && start > task.EndBlock { - log.Infof("[Handler.SyncTask] Handle task has done") - task.Status = models.SyncTaskDone - l.Db.Save(&task) - return nil - } - end := start - if task.HandleNum > 0 { - end = start + task.HandleNum - 1 - } - if task.EndBlock > 0 && end > task.EndBlock { - end = task.EndBlock - } - if end > l.LatestBlockNumber { - end = l.LatestBlockNumber - } - - Contracts := GetContracts(task.Contracts) - if len(Contracts) == 0 { - Contracts = l.GetContracts() - //log.Infof("[Handler.SyncTask] Contracts invalid") - ////task.UpdateTime = time.Now() - //task.Status = models.SyncTaskInvalid - //ctx.Db.Save(&task) - //return nil - } - events, err := l.LogBatchFilter(start, end, Contracts, [][]common.Hash{l.GetEventsByTask()}) - if err != nil { - log.Infof("[Handler.SyncTask] Log filter err: %s\n", err) - return errors.WithStack(err) - } - BatchCreateEvents := make([]*models.SyncEvent, 0) - BatchUpdateEventIds := make([]int64, 0) - for _, event := range events { - var one models.SyncEvent - err = l.Db.Select("id").Where("block_number=? AND block_log_indexed=? AND tx_hash=? AND event_hash=? ", - event.BlockNumber, event.BlockLogIndexed, event.TxHash, event.EventHash).First(&one).Error - if err != nil && err != gorm.ErrRecordNotFound { - log.Errorf("[Handler.SyncTask]Query SyncEvent err: %s\n", err) - return errors.WithStack(err) - } else if err == gorm.ErrRecordNotFound { - BatchCreateEvents = append(BatchCreateEvents, event) - } else { - BatchUpdateEventIds = append(BatchUpdateEventIds, one.Id) - } - } - - err = l.Db.Transaction(func(tx *gorm.DB) error { - if len(BatchCreateEvents) > 0 { - err = tx.CreateInBatches(&BatchCreateEvents, 100).Error - if err != nil { - log.Errorf("[Handler.SyncEvent]CreateInBatches err: %s\n", err) - return errors.WithStack(err) - } - } - if len(BatchUpdateEventIds) > 0 { - err = tx.Model(models.SyncEvent{}). - Where("id in ?", BatchUpdateEventIds). - Update("status", models.EventPending).Error - if err != nil { - log.Errorf("[Handler.SyncEvent]BatchUpdateEvents err: %s\n", err) - return errors.WithStack(err) - } - } - task.LatestBlock = end + 1 - err = tx.Save(&task).Error - if err != nil { - log.Errorf("[Handler.SyncEvent]Update SyncTask err: %s\n", err) - return errors.WithStack(err) - } - return nil - }) - if err != nil { - log.Errorf("[Handler.SyncEvent] err: %s\n", err) - return err - } - return nil -} diff --git a/serv/internal/listener/eth/validate.go b/serv/internal/listener/eth/validate.go deleted file mode 100644 index 2615dd9f..00000000 --- a/serv/internal/listener/eth/validate.go +++ /dev/null @@ -1,87 +0,0 @@ -package eth - -import ( - "bsquared.network/b2-message-channel-serv/internal/enums" - "bsquared.network/b2-message-channel-serv/internal/models" - "bsquared.network/b2-message-channel-serv/internal/utils/message" - "encoding/json" - "fmt" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto" - "github.com/pkg/errors" - log "github.com/sirupsen/logrus" - "sync" - "time" -) - -func (l *Listener) validate() { - duration := time.Millisecond * time.Duration(l.Blockchain.BlockInterval) - for { - list, err := l.validatingCallMessage(10) - if err != nil { - log.Errorf("Get pending call message err: %s\n", err) - time.Sleep(duration) - continue - } - if len(list) == 0 { - log.Infof("Get pending call message length is 0\n") - time.Sleep(duration) - continue - } - - var wg sync.WaitGroup - for _, message := range list { - wg.Add(1) - go func(_wg *sync.WaitGroup, message models.Message) { - defer _wg.Done() - err = l.validateMessage(message) - if err != nil { - log.Errorf("Handle err: %v, %v\n", err, message) - } - }(&wg, message) - } - wg.Wait() - } -} - -func (l *Listener) validateMessage(msg models.Message) error { - log.Infof("handle validateMessage\n") - var signatures []string - for _, validatorKey := range l.DataMap.ValidatorMap { - _key, err := crypto.ToECDSA(common.FromHex(validatorKey)) - if err != nil { - return errors.WithStack(err) - } - log.Infof("key:%v\n", _key) - signature, err := message.SignMessageSend(l.Blockchain.ChainId, l.Blockchain.MessageAddress, msg.FromChainId, common.HexToHash(msg.FromId).Big(), msg.FromSender, msg.ToChainId, msg.ToContractAddress, msg.ToBytes, _key) - if err != nil { - return errors.WithStack(err) - } - //if signature - signatures = append(signatures, signature) - } - - _signatures, err := json.Marshal(&signatures) - if err != nil { - return errors.WithStack(err) - } - //log.Infof("validateMessage signatures:%s\n", string(_signatures)) - fmt.Println("signatures:", string(_signatures)) - - err = l.Db.Model(models.Message{}).Where("`id`=? AND `status`=?", msg.Id, enums.MessageStatusValidating). - Update("signatures", string(_signatures)). - Update("status", enums.MessageStatusPending).Error - if err != nil { - return errors.WithStack(err) - } - return nil -} - -func (l *Listener) validatingCallMessage(limit int) ([]models.Message, error) { - var list []models.Message - err := l.Db.Where("`to_chain_id`=? AND `type`=? AND `status`=?", l.Blockchain.ChainId, enums.MessageTypeCall, enums.MessageStatusValidating).Limit(limit).Find(&list).Error - if err != nil { - return nil, err - } - return list, nil -} diff --git a/serv/internal/middlewares/error.go b/serv/internal/middlewares/error.go deleted file mode 100644 index 46bef522..00000000 --- a/serv/internal/middlewares/error.go +++ /dev/null @@ -1,29 +0,0 @@ -package middlewares - -import ( - "github.com/getsentry/sentry-go" - "github.com/gin-gonic/gin" -) - -type customResponse struct { - Code int `json:"code"` - Msg string `json:"msg"` - Data interface{} `json:"data,omitempty"` - Reason string `json:"reason,omitempty"` -} - -type ErrorResponse struct { - Status int `json:"-"` - customResponse -} - -func (e ErrorResponse) Error() string { - return e.Msg -} - -func ErrorHandler(c *gin.Context, err any) { - resErr := err.(ErrorResponse) - sentry.CaptureException(resErr) - resErr.Reason = "" - c.AbortWithStatusJSON(resErr.Status, resErr.customResponse) -} diff --git a/serv/internal/middlewares/fix_token.go b/serv/internal/middlewares/fix_token.go deleted file mode 100644 index 64959853..00000000 --- a/serv/internal/middlewares/fix_token.go +++ /dev/null @@ -1,23 +0,0 @@ -package middlewares - -import ( - "github.com/gin-gonic/gin" - "net/http" -) - -func FixTokenMiddleWare(secretString string) gin.HandlerFunc { - return func(c *gin.Context) { - tokenString := c.GetHeader("Authorization") - - if tokenString == "" { - c.JSON(http.StatusUnauthorized, gin.H{"error": "Authorization header missing"}) - c.Abort() - return - } - if tokenString != secretString { - c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid token"}) - c.Abort() - return - } - } -} diff --git a/serv/internal/middlewares/jwt.go b/serv/internal/middlewares/jwt.go deleted file mode 100644 index 337952df..00000000 --- a/serv/internal/middlewares/jwt.go +++ /dev/null @@ -1,48 +0,0 @@ -package middlewares - -import ( - "github.com/dgrijalva/jwt-go" - "github.com/gin-gonic/gin" - "net/http" -) - -// CustomClaims 自定义的JWT声明 -type CustomClaims struct { - ClientID string `json:"client_id"` - jwt.StandardClaims -} - -//var SecretKey = []byte("Lr2E52Y0XPleQi5w277b7w0bH9W7ia4wewxGszr5QH0=") - -func JwtMiddleWare(secretString string) gin.HandlerFunc { - var SecretKey = []byte(secretString) - return func(c *gin.Context) { - tokenString := c.GetHeader("Authorization") - - if tokenString == "" { - c.JSON(http.StatusUnauthorized, gin.H{"error": "Authorization header missing"}) - c.Abort() - return - } - - token, err := jwt.ParseWithClaims(tokenString, &CustomClaims{}, func(token *jwt.Token) (interface{}, error) { - return SecretKey, nil - }) - - if err != nil || !token.Valid { - c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid token"}) - c.Abort() - return - } - - // 在请求上下文中存储解析后的声明,以便后续处理函数使用 - claims, ok := token.Claims.(*CustomClaims) - if !ok { - c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid token claims"}) - c.Abort() - return - } - - c.Set("claims", claims) - } -} diff --git a/serv/internal/models/rollbacks.go b/serv/internal/models/rollbacks.go deleted file mode 100644 index 670ab936..00000000 --- a/serv/internal/models/rollbacks.go +++ /dev/null @@ -1,11 +0,0 @@ -package models - -type Rollback struct { - Base - ChainId int64 `json:"chain_id"` - EventId int64 `json:"event_id"` -} - -func (Rollback) TableName() string { - return "`rollbacks`" -} diff --git a/serv/internal/models/sync_blocks.go b/serv/internal/models/sync_blocks.go deleted file mode 100644 index 150eda76..00000000 --- a/serv/internal/models/sync_blocks.go +++ /dev/null @@ -1,32 +0,0 @@ -package models - -const ( - BlockPending = "pending" - BlockValid = "valid" - BlockRollback = "rollback" - BlockInvalid = "invalid" -) - -type SyncBlock struct { - Base - ChainId int64 `json:"chain_id"` - Miner string `json:"miner"` - BlockTime int64 `json:"block_time"` - BlockNumber int64 `json:"block_number"` - BlockHash string `json:"block_hash"` - TxCount int64 `json:"tx_count"` - EventCount int64 `json:"event_count"` - ParentHash string `json:"parent_hash"` - Status string `json:"status"` - CheckCount int64 `json:"check_count"` -} - -func (SyncBlock) TableName() string { - return "`sync_blocks`" -} - -type SyncBlockHistory SyncBlock - -func (SyncBlockHistory) TableName() string { - return "`sync_blocks_history`" -} diff --git a/serv/internal/models/sync_tasks.go b/serv/internal/models/sync_tasks.go deleted file mode 100644 index 0b9ba228..00000000 --- a/serv/internal/models/sync_tasks.go +++ /dev/null @@ -1,24 +0,0 @@ -package models - -const ( - SyncTaskInvalid = "invalid" - SyncTaskPending = "pending" - SyncTaskDone = "done" -) - -type SyncTask struct { - Base - ChainType int64 `json:"chain_type"` - ChainId int64 `json:"chain_id"` - LatestBlock int64 `json:"latest_block"` - LatestTx int64 `json:"latest_tx"` - StartBlock int64 `json:"start_block"` - EndBlock int64 `json:"end_block"` - HandleNum int64 `json:"handle_num"` - Contracts string `json:"contracts"` - Status string `json:"status"` -} - -func (SyncTask) TableName() string { - return "`sync_tasks`" -} diff --git a/serv/internal/models/validators.go b/serv/internal/models/validators.go deleted file mode 100644 index 650031c0..00000000 --- a/serv/internal/models/validators.go +++ /dev/null @@ -1,12 +0,0 @@ -package models - -type Validator struct { - Base - ChainId int64 `json:"chain_id"` - Address string `json:"address"` - Status bool `json:"status"` -} - -func (Validator) TableName() string { - return "`validators`" -} diff --git a/serv/internal/repository/message.go b/serv/internal/repository/message.go deleted file mode 100644 index aa9cd924..00000000 --- a/serv/internal/repository/message.go +++ /dev/null @@ -1,16 +0,0 @@ -package repository - -import ( - "gorm.io/gorm" -) - -type MessageRepository interface { -} - -type MessageRepositoryImpl struct { - db *gorm.DB -} - -func MessageRepositoryInit(db *gorm.DB) *MessageRepositoryImpl { - return &MessageRepositoryImpl{db: db} -} diff --git a/serv/internal/router/router.go b/serv/internal/router/router.go deleted file mode 100644 index 3d8162ee..00000000 --- a/serv/internal/router/router.go +++ /dev/null @@ -1,62 +0,0 @@ -package router - -import ( - "bsquared.network/b2-message-channel-serv/internal/boot" - "bsquared.network/b2-message-channel-serv/internal/config" - "github.com/gin-contrib/cors" - "github.com/gin-gonic/gin" - "time" -) - -func InitRoutes(initVal *boot.Initialization, cfg config.AppConfig) *gin.Engine { - r := gin.Default() - r.Use(cors.New(cors.Config{ - AllowOrigins: []string{"*"}, - AllowMethods: []string{"POST", "GET", "OPTIONS", "PUT", "DELETE", "UPDATE", "PATCH"}, - AllowHeaders: []string{"Origin, X-Requested-With, APP-ID, APP-SECRET, Content-Type, Accept, Authorization"}, - ExposeHeaders: []string{"Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Cache-Control, Content-Language, Content-Type"}, - AllowCredentials: true, - AllowOriginFunc: func(origin string) bool { - return true - }, - MaxAge: 12 * time.Hour, - })) - //r.Use(sentrygin.New(sentrygin.Options{ - // Repanic: true, - //})) - // - //r.Use(sentrygin.New(sentrygin.Options{ - // Repanic: true, - //})) - //r.Use(gin.CustomRecovery(middlewares.ErrorHandler)) - //if err := sentry.Init(sentry.ClientOptions{ - // Dsn: cfg.Sentry.Url, - // EnableTracing: true, - // // Set TracesSampleRate to 1.0 to capture 100% - // // of transactions for performance monitoring. - // // We recommend adjusting this value in production, - // TracesSampleRate: cfg.Sentry.SampleRate, - // Debug: cfg.Sentry.Env != "prod", - // Environment: cfg.Sentry.Env, - // Release: cfg.Sentry.Release, - //}); err != nil { - // log.Error("Sentry initialization failed: %v", err) - //} - //r.Use(middlewares.JwtMiddleWare(cfg.Api.Secret)) - //r.Use(middlewares.FixTokenMiddleWare(cfg.Api.Secret)) - //BybitApi := r.Group("/api/bybit") - //{ - // BybitApi.GET("/verify-by-wallet", initVal.BybitInit.BybitCtrl.VerifyByWallet) - //} - //StakeApi := r.Group("/stake") - //{ - // StakeApi.GET("/rewords", initVal.StakeInit.StakeCtrl.Rewords) - // StakeApi.GET("/histories", initVal.StakeInit.StakeCtrl.Histories) - // StakeApi.GET("/statistical", initVal.StakeInit.StakeCtrl.Statistical) - //} - MessageApi := r.Group("/message") - { - MessageApi.GET("/records", initVal.MessageInit.MessageCtrl.Records) - } - return r -} diff --git a/serv/internal/services/message.go b/serv/internal/services/message.go deleted file mode 100644 index 3d405ac2..00000000 --- a/serv/internal/services/message.go +++ /dev/null @@ -1,18 +0,0 @@ -package services - -import ( - "bsquared.network/b2-message-channel-serv/internal/repository" -) - -type MessageService interface { -} - -type MessageServiceImpl struct { - MessageRepository repository.MessageRepository -} - -func MessageServiceInit(MessageRepository repository.MessageRepository) *MessageServiceImpl { - return &MessageServiceImpl{ - MessageRepository: MessageRepository, - } -} diff --git a/serv/internal/types/bitcoin_bridge.go b/serv/internal/types/bitcoin_bridge.go deleted file mode 100644 index abf34eb6..00000000 --- a/serv/internal/types/bitcoin_bridge.go +++ /dev/null @@ -1,24 +0,0 @@ -package types - -import ( - "context" - - "github.com/ethereum/go-ethereum/core/types" -) - -// BITCOINBridge defines the interface of custom bitcoin bridge. -type BITCOINBridge interface { - // Deposit transfers amout to address - Deposit(string, BitcoinFrom, int64, *types.Transaction, uint64, bool) (*types.Transaction, []byte, string, string, error) - // Transfer amount to address - Transfer(BitcoinFrom, int64, *types.Transaction, uint64, bool) (*types.Transaction, string, error) - // WaitMined wait mined - WaitMined(context.Context, *types.Transaction, []byte) (*types.Receipt, error) - // TransactionReceipt - TransactionReceipt(hash string) (*types.Receipt, error) - // TransactionByHash - TransactionByHash(hash string) (*types.Transaction, bool, error) - // EnableEoaTransfer - EnableEoaTransfer() bool - FromAddress() string -} diff --git a/serv/internal/utils/coinmarketcap/price.go b/serv/internal/utils/coinmarketcap/price.go deleted file mode 100644 index d16e7108..00000000 --- a/serv/internal/utils/coinmarketcap/price.go +++ /dev/null @@ -1,54 +0,0 @@ -package coinmarketcap - -import ( - "encoding/json" - "errors" - "io/ioutil" - "net/http" -) - -func GetBTCPrice() (float64, error) { - url := "https://pro-api.coinmarketcap.com/v1/cryptocurrency/quotes/latest?symbol=BTC&convert=USD" - client := &http.Client{} - req, err := http.NewRequest("GET", url, nil) - if err != nil { - return 0, err - } - req.Header.Add("X-CMC_PRO_API_KEY", "461ba055-ebed-45d7-8366-5efcf57a0acf") - req.Header.Add("Host", "pro-api.coinmarketcap.com") - - res, err := client.Do(req) - if err != nil { - return 0, err - } - defer res.Body.Close() - - body, err := ioutil.ReadAll(res.Body) - if err != nil { - return 0, err - } - var data DataPrice - err = json.Unmarshal(body, &data) - if err != nil { - return 0, err - } - if data.Status.ErrorCode != 0 { - return 0, errors.New("Error getting price") - } - return data.Data.BTC.Quote.USD.Price, nil -} - -type DataPrice struct { - Status struct { - ErrorCode int `json:"error_code"` - } `json:"status"` - Data struct { - BTC struct { - Quote struct { - USD struct { - Price float64 `json:"price"` - } `json:"USD"` - } `json:"quote"` - } `json:"BTC"` - } `json:"data"` -} diff --git a/serv/internal/utils/ctx/ctx.go b/serv/internal/utils/ctx/ctx.go deleted file mode 100644 index 15a8bbb9..00000000 --- a/serv/internal/utils/ctx/ctx.go +++ /dev/null @@ -1,41 +0,0 @@ -package ctx - -import ( - "bsquared.network/b2-message-channel-serv/internal/config" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/ethclient" - "gorm.io/gorm" -) - -type Blockchain struct { - RPC *ethclient.Client - LatestBlockNumber int64 - SyncedBlockNumber int64 - SyncedBlockHash common.Hash -} - -type ServiceContext struct { - Config config.AppConfig - Db *gorm.DB - Cache *config.Cache - Blockchains []Blockchain -} - -func NewServiceContext(db *gorm.DB, cache *config.Cache, cfg config.AppConfig) *ServiceContext { - blockchains := make([]Blockchain, 0) - for _, blockchain := range cfg.Blockchain { - b2Rpc := config.InitB2Rpc(blockchain.RpcUrl) - blockchains = append(blockchains, Blockchain{ - RPC: b2Rpc, - LatestBlockNumber: blockchain.InitBlockNumber, - SyncedBlockNumber: 0, - SyncedBlockHash: common.HexToHash("0x0"), - }) - } - return &ServiceContext{ - Config: cfg, - Db: db, - Cache: cache, - Blockchains: blockchains, - } -} diff --git a/serv/internal/utils/log/encoder.go b/serv/internal/utils/log/encoder.go deleted file mode 100644 index 9c7a11d4..00000000 --- a/serv/internal/utils/log/encoder.go +++ /dev/null @@ -1,15 +0,0 @@ -package log - -import ( - "time" - - "go.uber.org/zap/zapcore" -) - -func timeEncoder(t time.Time, enc zapcore.PrimitiveArrayEncoder) { - enc.AppendString(t.Format(time.RFC1123)) -} - -func milliSecondsDurationEncoder(d time.Duration, enc zapcore.PrimitiveArrayEncoder) { - enc.AppendFloat64(float64(d) / float64(time.Millisecond)) -} diff --git a/serv/internal/utils/log/log.go b/serv/internal/utils/log/log.go deleted file mode 100644 index 64f8ea4b..00000000 --- a/serv/internal/utils/log/log.go +++ /dev/null @@ -1,373 +0,0 @@ -package log - -import ( - "fmt" - "sync" - - "go.uber.org/zap" - "go.uber.org/zap/zapcore" -) - -// Logger represents the ability to log messages, both errcode and not. -type Logger interface { - // info level - Info(msg string, fields ...Field) - Infof(format string, v ...interface{}) - Infow(msg string, keysAndValues ...interface{}) - // debug level - Debug(msg string, fields ...Field) - Debugf(format string, v ...interface{}) - Debugw(msg string, keysAndValues ...interface{}) - // warn level - Warn(msg string, fields ...Field) - Warnf(format string, v ...interface{}) - Warnw(msg string, keysAndValues ...interface{}) - // error level - Error(msg string, fields ...Field) - Errorf(format string, v ...interface{}) - Errorw(msg string, keysAndValues ...interface{}) - ErrorR(format string, v ...interface{}) error - // panic level - Panic(msg string, fields ...Field) - Panicf(format string, v ...interface{}) - Panicw(msg string, keysAndValues ...interface{}) - // fatal level - Fatal(msg string, fields ...Field) - Fatalf(format string, v ...interface{}) - Fatalw(msg string, keysAndValues ...interface{}) - - // WithValues adds some key-value pairs of context to a logger. - WithValues(keysAndValues ...interface{}) Logger - - // WithName adds a new element to the logger's name. - // Successive calls with WithName continue to append - // suffixes to the logger's name. It's strongly recommended - // that name segments contain only letters, digits, and hyphens - // (see the package documentation for more information). - WithName(name string) Logger - - // Flush calls the underlying Core's Sync method, flushing any buffered - // log entries. Applications should take care to call Sync before exiting. - Flush() -} - -type ZapLogger struct { - zapLogger *zap.Logger - level zapcore.Level -} - -// wrap interface value with zap.Any for performance -func handleFields(l *zap.Logger, args []interface{}, additional ...zap.Field) []zap.Field { - if len(args) == 0 { - return additional - } - - fields := make([]zap.Field, 0, len(args)/2+len(additional)) - for i := 0; i < len(args); { - if _, ok := args[i].(zap.Field); ok { - l.DPanic("strongly-typed Zap Field passed to log", zap.Any("zap field", args[i])) - break - } - - key, val := args[i], args[i+1] - keyStr, isString := key.(string) - if !isString { - l.DPanic( - "non-string key argument passed to logging, ignoring all later arguments", - zap.Any("invalid key", key), - ) - - break - } - fields = append(fields, zap.Any(keyStr, val)) - i += 2 - } - return append(fields, additional...) -} - -var ( - std = New(NewOptions()) - mu sync.Mutex -) - -// init logger. level should be one of "debug", "info", "warn", "error", "panic", "fatal", format should be oneof "console","json" -func Init(level, format string) { - mu.Lock() - defer mu.Unlock() - options := NewOptions() - options.Level = level - options.Format = format - err := options.Validate() - if err != nil { - panic(err) - } - std = New(options) -} - -// New create logger by opts which can customized by command arguments. -func New(opts *Options) *ZapLogger { - if opts == nil { - opts = NewOptions() - } - - var zapLevel zapcore.Level - if err := zapLevel.UnmarshalText([]byte(opts.Level)); err != nil { - zapLevel = zapcore.InfoLevel - } - encodeLevel := zapcore.CapitalLevelEncoder - // when output to local path, with color is forbidden - if opts.Format == consoleFormat && opts.EnableColor { - encodeLevel = zapcore.CapitalColorLevelEncoder - } - - encoderConfig := zapcore.EncoderConfig{ - MessageKey: "message", - LevelKey: "level", - TimeKey: "timestamp", - NameKey: "logger", - CallerKey: "caller", - StacktraceKey: "stacktrace", - LineEnding: zapcore.DefaultLineEnding, - EncodeLevel: encodeLevel, - EncodeTime: timeEncoder, - EncodeDuration: milliSecondsDurationEncoder, - EncodeCaller: zapcore.ShortCallerEncoder, - } - - loggerConfig := &zap.Config{ - Level: zap.NewAtomicLevelAt(zapLevel), - Development: opts.Development, - DisableCaller: opts.DisableCaller, - DisableStacktrace: opts.DisableStacktrace, - Sampling: &zap.SamplingConfig{ - Initial: 100, - Thereafter: 100, - }, - Encoding: opts.Format, - EncoderConfig: encoderConfig, - OutputPaths: opts.OutputPaths, - ErrorOutputPaths: opts.ErrorOutputPaths, - } - - var err error - l, err := loggerConfig.Build(zap.AddStacktrace(zapcore.PanicLevel), zap.AddCallerSkip(1)) - if err != nil { - panic(err) - } - logger := &ZapLogger{ - zapLogger: l.Named(opts.Name), - level: loggerConfig.Level.Level(), - } - - return logger -} - -// WithValues creates a child logger and adds adds Zap fields to it. -func WithValues(keysAndValues ...interface{}) Logger { return std.WithValues(keysAndValues...) } - -func (l *ZapLogger) WithValues(keysAndValues ...interface{}) Logger { - newLogger := l.zapLogger.With(handleFields(l.zapLogger, keysAndValues)...) - - return &ZapLogger{ - zapLogger: newLogger, - } -} - -// WithName adds a new path segment to the logger's name. Segments are joined by -// periods. By default, Loggers are unnamed. -func WithName(s string) Logger { return std.WithName(s) } - -func (l *ZapLogger) WithName(name string) Logger { - newLogger := l.zapLogger.Named(name) - - return &ZapLogger{ - zapLogger: newLogger, - } -} - -// Flush calls the underlying Core's Sync method, flushing any buffered -// log entries. Applications should take care to call Sync before exiting. -func Flush() { std.Flush() } - -func (l *ZapLogger) Flush() { - _ = l.zapLogger.Sync() -} - -// Debug method output debug level log. -func Debug(msg string, fields ...Field) { - std.zapLogger.Debug(msg, fields...) -} - -func (l *ZapLogger) Debug(msg string, fields ...Field) { - l.zapLogger.Debug(msg, fields...) -} - -// Debugf method output debug level log. -func Debugf(format string, v ...interface{}) { - std.zapLogger.Sugar().Debugf(format, v...) -} - -func (l *ZapLogger) Debugf(format string, v ...interface{}) { - l.zapLogger.Sugar().Debugf(format, v...) -} - -// Debugw method output debug level log. -func Debugw(msg string, keysAndValues ...interface{}) { - std.zapLogger.Sugar().Debugw(msg, keysAndValues...) -} - -func (l *ZapLogger) Debugw(msg string, keysAndValues ...interface{}) { - l.zapLogger.Sugar().Debugw(msg, keysAndValues...) -} - -// Info method output info level log. -func Info(msg string, fields ...Field) { - std.zapLogger.Info(msg, fields...) -} - -func (l *ZapLogger) Info(msg string, fields ...Field) { - l.zapLogger.Info(msg, fields...) -} - -// Infof method output info level log. -func Infof(format string, v ...interface{}) { - std.zapLogger.Sugar().Infof(format, v...) -} - -func (l *ZapLogger) Infof(format string, v ...interface{}) { - l.zapLogger.Sugar().Infof(format, v...) -} - -// Infow method output info level log. -func Infow(msg string, keysAndValues ...interface{}) { - std.zapLogger.Sugar().Infow(msg, keysAndValues...) -} - -func (l *ZapLogger) Infow(msg string, keysAndValues ...interface{}) { - l.zapLogger.Sugar().Infow(msg, keysAndValues...) -} - -// Warn method output warning level log. -func Warn(msg string, fields ...Field) { - std.zapLogger.Warn(msg, fields...) -} - -func (l *ZapLogger) Warn(msg string, fields ...Field) { - l.zapLogger.Warn(msg, fields...) -} - -// Warnf method output warning level log. -func Warnf(format string, v ...interface{}) { - std.zapLogger.Sugar().Warnf(format, v...) -} - -func (l *ZapLogger) Warnf(format string, v ...interface{}) { - l.zapLogger.Sugar().Warnf(format, v...) -} - -// Warnw method output warning level log. -func Warnw(msg string, keysAndValues ...interface{}) { - std.zapLogger.Sugar().Warnw(msg, keysAndValues...) -} - -func (l *ZapLogger) Warnw(msg string, keysAndValues ...interface{}) { - l.zapLogger.Sugar().Warnw(msg, keysAndValues...) -} - -// Error method output error level log. -func Error(msg string, fields ...Field) { - std.zapLogger.Error(msg, fields...) -} - -func (l *ZapLogger) Error(msg string, fields ...Field) { - l.zapLogger.Error(msg, fields...) -} - -// Errorf method output error level log. -func Errorf(format string, v ...interface{}) { - std.zapLogger.Sugar().Errorf(format, v...) -} - -func (l *ZapLogger) Errorf(format string, v ...interface{}) { - l.zapLogger.Sugar().Errorf(format, v...) -} - -func ErrorR(format string, v ...interface{}) error { - std.zapLogger.Sugar().Errorf(format, v...) - return fmt.Errorf(format, v...) -} - -func (l *ZapLogger) ErrorR(format string, v ...interface{}) error { - l.zapLogger.Sugar().Errorf(format, v...) - return fmt.Errorf(format, v...) -} - -// Errorw method output error level log. -func Errorw(msg string, keysAndValues ...interface{}) { - std.zapLogger.Sugar().Errorw(msg, keysAndValues...) -} - -func (l *ZapLogger) Errorw(msg string, keysAndValues ...interface{}) { - l.zapLogger.Sugar().Errorw(msg, keysAndValues...) -} - -// Panic method output panic level log and shutdown application. -func Panic(msg string, fields ...Field) { - std.zapLogger.Panic(msg, fields...) -} - -func (l *ZapLogger) Panic(msg string, fields ...Field) { - l.zapLogger.Panic(msg, fields...) -} - -// Panicf method output panic level log and shutdown application. -func Panicf(format string, v ...interface{}) { - std.zapLogger.Sugar().Panicf(format, v...) -} - -func (l *ZapLogger) Panicf(format string, v ...interface{}) { - l.zapLogger.Sugar().Panicf(format, v...) -} - -// Panicw method output panic level log. -func Panicw(msg string, keysAndValues ...interface{}) { - std.zapLogger.Sugar().Panicw(msg, keysAndValues...) -} - -func (l *ZapLogger) Panicw(msg string, keysAndValues ...interface{}) { - l.zapLogger.Sugar().Panicw(msg, keysAndValues...) -} - -// Fatal method output fatal level log. -func Fatal(msg string, fields ...Field) { - std.zapLogger.Fatal(msg, fields...) -} - -func (l *ZapLogger) Fatal(msg string, fields ...Field) { - l.zapLogger.Fatal(msg, fields...) -} - -// Fatalf method output fatal level log. -func Fatalf(format string, v ...interface{}) { - std.zapLogger.Sugar().Fatalf(format, v...) -} - -func (l *ZapLogger) Fatalf(format string, v ...interface{}) { - l.zapLogger.Sugar().Fatalf(format, v...) -} - -// Fatalw method output Fatalw level log. -func Fatalw(msg string, keysAndValues ...interface{}) { - std.zapLogger.Sugar().Fatalw(msg, keysAndValues...) -} - -func (l *ZapLogger) Fatalw(msg string, keysAndValues ...interface{}) { - l.zapLogger.Sugar().Fatalw(msg, keysAndValues...) -} - -// //nolint:predeclared -// func (l *ZapLogger) clone() *ZapLogger { -// copy := *l - -// return © -// } diff --git a/serv/internal/utils/log/nop_logger.go b/serv/internal/utils/log/nop_logger.go deleted file mode 100644 index 738b1145..00000000 --- a/serv/internal/utils/log/nop_logger.go +++ /dev/null @@ -1,46 +0,0 @@ -package log - -type nopLogger struct{} - -// Interface assertions -var _ Logger = (*nopLogger)(nil) - -// NewNopLogger returns a logger that doesn't do anything. -func NewNopLogger() Logger { return &nopLogger{} } - -// info level -func (nopLogger) Info(_ string, _ ...Field) {} -func (nopLogger) Infof(_ string, _ ...interface{}) {} -func (nopLogger) Infow(_ string, _ ...interface{}) {} - -// debug level -func (nopLogger) Debug(_ string, _ ...Field) {} -func (nopLogger) Debugf(_ string, _ ...interface{}) {} -func (nopLogger) Debugw(_ string, _ ...interface{}) {} - -// warn level -func (nopLogger) Warn(_ string, _ ...Field) {} -func (nopLogger) Warnf(_ string, _ ...interface{}) {} -func (nopLogger) Warnw(_ string, _ ...interface{}) {} - -// error level -func (nopLogger) Error(_ string, _ ...Field) {} -func (nopLogger) Errorf(_ string, _ ...interface{}) {} -func (nopLogger) Errorw(_ string, _ ...interface{}) {} -func (nopLogger) ErrorR(_ string, _ ...interface{}) error { return nil } - -// panic level -func (nopLogger) Panic(_ string, _ ...Field) {} -func (nopLogger) Panicf(_ string, _ ...interface{}) {} -func (nopLogger) Panicw(_ string, _ ...interface{}) {} - -// fatal level -func (nopLogger) Fatal(_ string, _ ...Field) {} -func (nopLogger) Fatalf(_ string, _ ...interface{}) {} -func (nopLogger) Fatalw(_ string, _ ...interface{}) {} - -func (nopLogger) WithValues(_ ...interface{}) Logger { return nopLogger{} } - -func (nopLogger) WithName(_ string) Logger { return nopLogger{} } - -func (nopLogger) Flush() {} diff --git a/serv/internal/utils/log/options.go b/serv/internal/utils/log/options.go deleted file mode 100644 index f4a775c6..00000000 --- a/serv/internal/utils/log/options.go +++ /dev/null @@ -1,69 +0,0 @@ -package log - -import ( - "errors" - "fmt" - "strings" - - "go.uber.org/zap/zapcore" -) - -const ( - consoleFormat = "console" - jsonFormat = "json" -) - -var validLevels = []string{"debug", "info", "warn", "error", "panic", "fatal"} - -// options for create log -type Options struct { - // destination of log - OutputPaths []string `json:"output-paths"` - // the error log of zap - ErrorOutputPaths []string `json:"error-output-paths"` - // log level "info debug warn error panic fatal" - Level string `json:"level"` - // json or console - Format string `json:"format"` - // show file, function, line number in log - DisableCaller bool `json:"disable-caller"` - DisableStacktrace bool `json:"disable-stacktrace"` - // console format can enable color - EnableColor bool `json:"enable-color"` - Development bool `json:"development"` - Name string `json:"name"` -} - -func NewOptions() *Options { - return &Options{ - Level: zapcore.InfoLevel.String(), - DisableCaller: false, - DisableStacktrace: false, - Format: consoleFormat, - EnableColor: false, - Development: false, - OutputPaths: []string{"stdout"}, - ErrorOutputPaths: []string{"stderr"}, - } -} - -func (opt *Options) Validate() error { - errorMsg := make([]string, 0) - if opt.Format != consoleFormat && opt.Format != jsonFormat { - errorMsg = append(errorMsg, fmt.Sprintf("Invalid format, should be: %v or %v", consoleFormat, jsonFormat)) - } - valid := false - for _, val := range validLevels { - if val == opt.Level { - valid = true - break - } - } - if !valid { - errorMsg = append(errorMsg, fmt.Sprintf("Invalid level, should be one of %v", strings.Join(validLevels, ","))) - } - if len(errorMsg) != 0 { - return errors.New(strings.Join(validLevels, ";")) - } - return nil -} diff --git a/serv/internal/utils/log/types.go b/serv/internal/utils/log/types.go deleted file mode 100644 index c69cca4d..00000000 --- a/serv/internal/utils/log/types.go +++ /dev/null @@ -1,73 +0,0 @@ -package log - -import ( - "go.uber.org/zap" - "go.uber.org/zap/zapcore" -) - -type Field = zapcore.Field - -type Level = zapcore.Level - -var ( - DebugLevel = zapcore.DebugLevel - InfoLevel = zapcore.InfoLevel - WarnLevel = zapcore.WarnLevel - ErrorLevel = zapcore.ErrorLevel - PanicLevel = zapcore.PanicLevel - FatalLevel = zapcore.FatalLevel -) - -// Alias for zap type functions. -var ( - Any = zap.Any - Array = zap.Array - Object = zap.Object - Binary = zap.Binary - Bool = zap.Bool - Bools = zap.Bools - ByteString = zap.ByteString - ByteStrings = zap.ByteStrings - Complex64 = zap.Complex64 - Complex64s = zap.Complex64s - Complex128 = zap.Complex128 - Complex128s = zap.Complex128s - Duration = zap.Duration - Durations = zap.Durations - Err = zap.Error - Errors = zap.Errors - Float32 = zap.Float32 - Float32s = zap.Float32s - Float64 = zap.Float64 - Float64s = zap.Float64s - Int = zap.Int - Ints = zap.Ints - Int8 = zap.Int8 - Int8s = zap.Int8s - Int16 = zap.Int16 - Int16s = zap.Int16s - Int32 = zap.Int32 - Int32s = zap.Int32s - Int64 = zap.Int64 - Int64s = zap.Int64s - Namespace = zap.Namespace - Reflect = zap.Reflect - Stack = zap.Stack - String = zap.String - Stringer = zap.Stringer - Strings = zap.Strings - Time = zap.Time - Times = zap.Times - Uint = zap.Uint - Uints = zap.Uints - Uint8 = zap.Uint8 - Uint8s = zap.Uint8s - Uint16 = zap.Uint16 - Uint16s = zap.Uint16s - Uint32 = zap.Uint32 - Uint32s = zap.Uint32s - Uint64 = zap.Uint64 - Uint64s = zap.Uint64s - Uintptr = zap.Uintptr - Uintptrs = zap.Uintptrs -) diff --git a/serv/internal/utils/message/message.go b/serv/internal/utils/message/message.go deleted file mode 100644 index 3551e234..00000000 --- a/serv/internal/utils/message/message.go +++ /dev/null @@ -1,100 +0,0 @@ -package message - -import ( - "crypto/ecdsa" - "encoding/json" - "fmt" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/signer/core/apitypes" - "github.com/pkg/errors" - "github.com/storyicon/sigverify" - "math/big" -) - -const MessageSendTypedData = `{ - "types":{ - "EIP712Domain":[ - { - "name":"name", - "type":"string" - }, - { - "name":"version", - "type":"string" - }, - { - "name":"chainId", - "type":"uint256" - }, - { - "name":"verifyingContract", - "type":"address" - } - ], - "Send":[ - { - "name":"from_chain_id", - "type":"uint256" - }, - { - "name":"from_id", - "type":"uint256" - }, - { - "name":"from_sender", - "type":"address" - }, - { - "name":"to_chain_id", - "type":"uint256" - }, - { - "name":"contract_address", - "type":"address" - }, - { - "name":"data", - "type":"bytes" - } - ] - }, - "domain":{ - "name":"B2MessageBridge", - "version":"1", - "chainId":"%d", - "verifyingContract":"%s" - }, - "primaryType":"Send", - "message":{ - "from_chain_id":"%d", - "from_id":"%s", - "from_sender":"%s", - "to_chain_id":"%d", - "contract_address":"%s", - "data":"%s" - } -}` - -func SignMessageSend(chainId int64, messageContract string, fromChainId int64, fromId *big.Int, fromSender string, toChainId int64, contractAddress string, data string, key *ecdsa.PrivateKey) (string, error) { - _data := fmt.Sprintf(MessageSendTypedData, chainId, messageContract, fromChainId, fromId.Text(10), fromSender, toChainId, contractAddress, data) - var typedData apitypes.TypedData - if err := json.Unmarshal([]byte(_data), &typedData); err != nil { - return "", errors.WithStack(err) - } - _, originHash, err := sigverify.HashTypedData(typedData) - fmt.Println("originHash", common.Bytes2Hex(originHash)) - if err != nil { - return "", errors.WithStack(err) - } - sig, err := crypto.Sign(originHash, key) - if err != nil { - return "", errors.WithStack(err) - } - if sig[64] == 0 { - sig[64] = 27 - } else if sig[64] == 1 { - sig[64] = 28 - } - return "0x" + common.Bytes2Hex(sig), nil -} diff --git a/serv/internal/utils/random_string.go b/serv/internal/utils/random_string.go deleted file mode 100644 index 4848b82f..00000000 --- a/serv/internal/utils/random_string.go +++ /dev/null @@ -1,23 +0,0 @@ -package utils - -import ( - "math/rand" - "time" -) - -func StringWithCharset(length int, charset string) string { - var seededRand *rand.Rand = rand.New( - rand.NewSource(time.Now().UnixNano())) - - b := make([]byte, length) - for i := range b { - b[i] = charset[seededRand.Intn(len(charset))] - } - return string(b) -} - -func RandomString(len int) string { - const charset = "abcdefghijklmnopqrstuvwxyz" + - "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" - return StringWithCharset(len, charset) -} diff --git a/serv/internal/utils/redis.go b/serv/internal/utils/redis.go deleted file mode 100644 index 23a5c624..00000000 --- a/serv/internal/utils/redis.go +++ /dev/null @@ -1,70 +0,0 @@ -package utils - -import ( - "context" - "crypto/tls" - "fmt" - "github.com/redis/go-redis/v9" - "strings" -) - -type Manager struct { - singleNodeClient *redis.Client - clusterClient *redis.ClusterClient - Client redis.Cmdable -} - -var ( - ManagerClient *Manager -) - -func GetClient() redis.Cmdable { - return ManagerClient.Client -} - -func InitRedis(redisIsClusterMode bool, redisClusterAddresses, redisPassword string, tlsInsecureSkip bool, redisHost, redisPort string, redisDB int) error { - m := &Manager{} - if redisIsClusterMode { - //集群模式 - opt := &redis.ClusterOptions{ - Addrs: strings.Split(redisClusterAddresses, ","), - Password: redisPassword, - } - if tlsInsecureSkip { - opt.TLSConfig = &tls.Config{ - InsecureSkipVerify: true, - } - } - cli := redis.NewClusterClient(opt) - _, err := cli.Ping(context.Background()).Result() - if err != nil { - return err - } - m.clusterClient = cli - m.Client = cli - - } else { - - //单节点模式 - opt := &redis.Options{ - Addr: fmt.Sprintf("%s:%s", redisHost, redisPort), - Password: redisPassword, - DB: redisDB, - } - if tlsInsecureSkip { - opt.TLSConfig = &tls.Config{ - InsecureSkipVerify: true, - } - } - cli := redis.NewClient(opt) - _, err := cli.Ping(context.Background()).Result() - if err != nil { - return err - } - m.singleNodeClient = cli - m.Client = cli - } - - ManagerClient = m - return nil -} diff --git a/serv/internal/utils/response.go b/serv/internal/utils/response.go deleted file mode 100644 index f8727150..00000000 --- a/serv/internal/utils/response.go +++ /dev/null @@ -1,53 +0,0 @@ -package utils - -import ( - "github.com/gin-gonic/gin" - "net/http" - "reflect" -) - -type ResponseJson struct { - Status int `json:"-"` - Code int `json:"code"` - Msg string `json:"msg"` - Data any `json:"data,omitempty"` -} - -// IsEmpty 判断结构体是否为空 -func (r ResponseJson) IsEmpty() bool { - return reflect.DeepEqual(r, ResponseJson{}) -} - -// 构建状态码 ,如果 传入的ResponseJson没有Status 就使用默认的状态码 -func buildStatus(resp ResponseJson, defaultStatus int) int { - if resp.Status == 0 { - return defaultStatus - } - return resp.Status -} - -func HttpResponse(ctx *gin.Context, status int, resp ResponseJson) { - if resp.IsEmpty() { - ctx.AbortWithStatus(status) - return - } - ctx.AbortWithStatusJSON(status, resp) -} - -func Success(ctx *gin.Context, data any) { - resp := ResponseJson{ - Code: 0, - Msg: "", - Data: data, - } - HttpResponse(ctx, buildStatus(resp, http.StatusOK), resp) -} - -func Fail(ctx *gin.Context, resp ResponseJson) { - HttpResponse(ctx, buildStatus(resp, http.StatusBadRequest), resp) -} - -func ServerFail(ctx *gin.Context, resp ResponseJson) { - HttpResponse(ctx, buildStatus(resp, http.StatusInternalServerError), resp) - -} diff --git a/serv/internal/utils/rpc/http.go b/serv/internal/utils/rpc/http.go deleted file mode 100644 index e9d01231..00000000 --- a/serv/internal/utils/rpc/http.go +++ /dev/null @@ -1,44 +0,0 @@ -package rpc - -import ( - "errors" - "fmt" - "io/ioutil" - "net/http" - "net/url" - "strings" - "time" -) - -func HttpPostJson(proxyUrl, httpUrl, bodyJson string) ([]byte, error) { - httpClient := &http.Client{ - Timeout: time.Second * 10, - } - if proxyUrl != "" { - proxy, err := url.Parse(proxyUrl) - if err != nil { - return nil, err - } - netTransport := &http.Transport{ - Proxy: http.ProxyURL(proxy), - MaxIdleConnsPerHost: 10, - ResponseHeaderTimeout: time.Second * time.Duration(10), - } - httpClient.Transport = netTransport - } - b := strings.NewReader(bodyJson) - res, err := httpClient.Post(httpUrl, "application/json", b) - if err != nil { - return nil, err - } - defer res.Body.Close() - if res.StatusCode != http.StatusOK { - return nil, errors.New(fmt.Sprintf("StatusCode: %d", res.StatusCode)) - } - body, err := ioutil.ReadAll(res.Body) - if err != nil { - return nil, err - } - return body, nil - -} diff --git a/serv/internal/utils/rpc/struct.go b/serv/internal/utils/rpc/struct.go deleted file mode 100644 index b72bf920..00000000 --- a/serv/internal/utils/rpc/struct.go +++ /dev/null @@ -1,67 +0,0 @@ -package rpc - -import ( - "encoding/json" - "fmt" - "strconv" - "strings" -) - -type Block struct { - ID int64 `json:"id"` - Jsonrpc string `json:"jsonrpc"` - Result struct { - Difficulty string `json:"difficulty"` - ExtraData string `json:"extraData"` - GasLimit string `json:"gasLimit"` - GasUsed string `json:"gasUsed"` - Hash string `json:"hash"` - LogsBloom string `json:"logsBloom"` - Miner string `json:"miner"` - MixHash string `json:"mixHash"` - Nonce string `json:"nonce"` - Number string `json:"number"` - ParentHash string `json:"parentHash"` - ReceiptsRoot string `json:"receiptsRoot"` - Sha3Uncles string `json:"sha3Uncles"` - Size string `json:"size"` - StateRoot string `json:"stateRoot"` - Timestamp string `json:"timestamp"` - TotalDifficulty string `json:"totalDifficulty"` - Transactions []interface{} `json:"transactions"` - TransactionsRoot string `json:"transactionsRoot"` - Uncles []interface{} `json:"uncles"` - } `json:"result"` -} - -func (b Block) ParentHash() string { - return b.Result.ParentHash -} -func (b Block) Hash() string { - return b.Result.Hash -} -func (b Block) Miner() string { - return b.Result.Miner -} -func (b Block) Number() int64 { - value, err := strconv.ParseInt(strings.ReplaceAll(b.Result.Number, "0x", ""), 16, 64) - if err != nil { - return 0 - } - return value -} -func (b Block) Timestamp() int64 { - value, err := strconv.ParseInt(strings.ReplaceAll(b.Result.Timestamp, "0x", ""), 16, 64) - if err != nil { - return 0 - } - return value -} -func ParseJsonBlock(data string) Block { - var c Block - if err := json.Unmarshal([]byte(data), &c); err != nil { - fmt.Println("Error =", err) - return c - } - return c -} diff --git a/serv/internal/utils/sso/token.go b/serv/internal/utils/sso/token.go deleted file mode 100644 index fe2df4b3..00000000 --- a/serv/internal/utils/sso/token.go +++ /dev/null @@ -1,92 +0,0 @@ -package sso - -import ( - "bsquared.network/b2-message-channel-serv/internal/middlewares" - "github.com/gin-gonic/gin" - "github.com/golang-jwt/jwt/v4" - "github.com/pkg/errors" - "net/http" - "time" -) - -type Wallet struct { - WalletAddress string `json:"wallet_address"` - ScaAddress string `json:"sca_address"` - ParticleAddress string `json:"particle_address"` -} - -type User struct { - Name string `json:"name,omitempty"` - Wallets []Wallet `json:"wallets,omitempty"` -} - -type UserClaims struct { - User User `json:"user,omitempty"` - Sub string `json:"sub"` - IsRefreshToken uint8 `json:"is_refresh_token,omitempty"` - jwt.RegisteredClaims -} - -type JwtToken struct { - AccessToken string `json:"access_token"` - RefreshToken string `json:"refresh_token"` -} - -func GenerateToken(secretKey string, user User, sub string, isRefreshToken uint8) (string, error) { - expiredAt := time.Now().Add(7 * 24 * time.Hour) - if isRefreshToken == 1 { - expiredAt = time.Now().Add(14 * 24 * time.Hour) - } - numericExpiredAt := jwt.NewNumericDate(expiredAt) - var userClaims UserClaims - if isRefreshToken == 0 { - userClaims = UserClaims{ - User: user, - Sub: sub, - RegisteredClaims: jwt.RegisteredClaims{ - ExpiresAt: numericExpiredAt, - Issuer: "b2network", - }, - } - } else { - userClaims = UserClaims{ - Sub: sub, - IsRefreshToken: isRefreshToken, - RegisteredClaims: jwt.RegisteredClaims{ - ExpiresAt: numericExpiredAt, - Issuer: "b2network", - }, - } - } - t := jwt.NewWithClaims(jwt.SigningMethodHS256, userClaims) - tokenString, err := t.SignedString([]byte(secretKey)) - if err != nil { - return "", err - } - return tokenString, err -} - -func VerifyToken(secretKey string, tokenString string) (*UserClaims, error) { - token, err := jwt.ParseWithClaims(tokenString, &UserClaims{}, func(token *jwt.Token) (interface{}, error) { - return []byte(secretKey), nil - }) - if err != nil { - return nil, err - } - if userClaims, ok := token.Claims.(*UserClaims); ok && token.Valid { - return userClaims, nil - } else { - return nil, errors.New("token invald") - } -} - -func ValidateToken(c *gin.Context) string { - claims, exists := c.Get("claims") - if !exists { - c.JSON(http.StatusInternalServerError, gin.H{"error": "Claims not found in context"}) - return "" - } - - clientID := claims.(*middlewares.CustomClaims).ClientID - return clientID -} diff --git a/serv/internal/utils/token.go b/serv/internal/utils/token.go deleted file mode 100644 index 54c5a1cc..00000000 --- a/serv/internal/utils/token.go +++ /dev/null @@ -1,18 +0,0 @@ -package utils - -import ( - "bsquared.network/b2-message-channel-serv/internal/middlewares" - "github.com/gin-gonic/gin" - "net/http" -) - -func ValidateToken(c *gin.Context) string { - claims, exists := c.Get("claims") - if !exists { - c.JSON(http.StatusInternalServerError, gin.H{"error": "Claims not found in context"}) - return "" - } - - clientID := claims.(*middlewares.CustomClaims).ClientID - return clientID -} diff --git a/serv/internal/validators/stake.go b/serv/internal/validators/stake.go deleted file mode 100644 index 07ef7063..00000000 --- a/serv/internal/validators/stake.go +++ /dev/null @@ -1,43 +0,0 @@ -package validators - -import ( - "github.com/go-playground/validator/v10" - "strings" -) - -type BridgeValidator struct { - validator *validator.Validate -} - -func (v *BridgeValidator) EthAddressValidate(fl validator.FieldLevel) bool { - ethAddress := strings.ToLower(fl.Field().String()) - return strings.HasPrefix(ethAddress, "0x") && len(ethAddress) == 42 -} - -func (v *BridgeValidator) BtcAddressValidate(fl validator.FieldLevel) bool { - btcAddress := strings.ToLower(fl.Field().String()) - return (strings.HasPrefix(btcAddress, "2") && len(btcAddress) == 35) || - (strings.HasPrefix(btcAddress, "m") && len(btcAddress) == 34) || - (strings.HasPrefix(btcAddress, "tb1") && (len(btcAddress) == 42 || len(btcAddress) == 62)) -} - -func (v *BridgeValidator) LogIndexValidate(fl validator.FieldLevel) bool { - logIndex := fl.Field().Int() - - return logIndex >= 0 -} - -func RegisterBridgeValidators(v *validator.Validate) { - err := v.RegisterValidation("logIndex", (&BridgeValidator{v}).LogIndexValidate) - if err != nil { - return - } - err = v.RegisterValidation("ethAddress", (&BridgeValidator{v}).EthAddressValidate) - if err != nil { - return - } - err = v.RegisterValidation("btcAddress", (&BridgeValidator{v}).BtcAddressValidate) - if err != nil { - return - } -} diff --git a/serv/internal/validators/validators.go b/serv/internal/validators/validators.go deleted file mode 100644 index 3d41fd5a..00000000 --- a/serv/internal/validators/validators.go +++ /dev/null @@ -1,7 +0,0 @@ -package validators - -import "github.com/go-playground/validator/v10" - -func RegisterValidators(v *validator.Validate) { - RegisterBridgeValidators(v) -} diff --git a/serv/internal/vo/farm.go b/serv/internal/vo/farm.go deleted file mode 100644 index a56fb537..00000000 --- a/serv/internal/vo/farm.go +++ /dev/null @@ -1,173 +0,0 @@ -package vo - -import "github.com/shopspring/decimal" - -type DepositRecordsRequest struct { - //PoolId int64 `json:"pool_id" form:"pool_id"` - //StrategyId int64 `json:"strategy_id" form:"strategy_id"` - Owner string `json:"owner" form:"owner"` - Page int64 `json:"page" form:"page"` - PageSize int64 `json:"page_size" form:"page_size"` -} - -type DepositRecordsResponse struct { - Code int `json:"code"` - Msg string `json:"msg"` - Data DepositRecordsResponseData `json:"data"` -} - -type DepositRecordsResponseData struct { - Total int64 `json:"total"` - TotalAmount decimal.Decimal `json:"total_amount"` - List []DepositRecordsResponseList `json:"list"` -} - -type DepositRecordsResponseList struct { - Id int64 `json:"id"` - PoolId int64 `json:"pool_id"` - StrategyId int64 `json:"strategy_id"` - Amount decimal.Decimal `json:"amount"` - Timestamp int64 `json:"timestamp"` - TxHash string `json:"tx_hash"` -} - -/////////////////////////////////////////////////// - -type WithdrawRecordsRequest struct { - //PoolId int64 `json:"pool_id" form:"pool_id"` - //StrategyId int64 `json:"strategy_id" form:"strategy_id"` - Owner string `json:"owner" form:"owner"` - Page int64 `json:"page" form:"page"` - PageSize int64 `json:"page_size" form:"page_size"` -} - -type WithdrawRecordsResponse struct { - Code int `json:"code"` - Msg string `json:"msg"` - Data WithdrawRecordsResponseData `json:"data"` -} - -type WithdrawRecordsResponseData struct { - Total int64 `json:"total"` - TotalAmount decimal.Decimal `json:"total_amount"` - List []WithdrawRecordsResponseList `json:"list"` -} - -type WithdrawRecordsResponseList struct { - Id int64 `json:"id"` - PoolId int64 `json:"pool_id"` - StrategyId int64 `json:"strategy_id"` - Amount decimal.Decimal `json:"amount"` - Timestamp int64 `json:"timestamp"` - TxHash string `json:"tx_hash"` -} - -/////////////////////////////////////////////////// - -type ClaimRecordsRequest struct { - PoolId int64 `json:"pool_id" form:"pool_id"` - Owner string `json:"owner" form:"owner"` -} - -type ClaimRecordsResponse struct { - Code int `json:"code"` - Msg string `json:"msg"` - Data ClaimRecordsResponseData `json:"data"` -} - -type ClaimRecordsResponseData struct { - List []ClaimRecordsResponseList `json:"list"` -} - -type ClaimRecordsResponseList struct { - Id int64 `json:"id"` - PoolId int64 `json:"pool_id"` - StrategyId int64 `json:"strategy_id"` - Amount decimal.Decimal `json:"amount"` - Timestamp int64 `json:"timestamp"` - TxHash string `json:"tx_hash"` -} - -/////////////////////////////////////////////////// - -type FarmStatsRequest struct { - Owner string `json:"owner" form:"owner"` -} - -type FarmStatsResponse struct { - Code int `json:"code"` - Msg string `json:"msg"` - Data FarmStatsResponseData `json:"data"` -} - -type FarmStatsResponseData struct { - TotalDeposited decimal.Decimal `json:"total_deposited"` - TotalUserCount int64 `json:"total_user_count"` - List []FarmStatsResponseList `json:"list"` -} - -type FarmStatsResponseList struct { - PoolId int64 `json:"pool_id"` - StrategyId int64 `json:"strategy_id"` - TotalDeposited decimal.Decimal `json:"total_deposited"` - CurrentDeposited decimal.Decimal `json:"current_deposited"` - TVL decimal.Decimal `json:"tvl"` - TotalWithdraw decimal.Decimal `json:"total_withdraw"` - RequestWithdraw decimal.Decimal `json:"request_withdraw"` - TotalUserCount int64 `json:"total_user_count"` - CurrentUserCount int64 `json:"current_user_count"` -} - -/////////////////////////////////////////////////// - -type UserDetailsRequest struct { - Owner string `json:"owner" form:"owner"` -} - -type UserDetailsResponse struct { - Code int `json:"code"` - Msg string `json:"msg"` - Data UserDetailsResponseData `json:"data"` -} - -type UserDetailsResponseData struct { - List []UserDetailsResponseList `json:"list"` -} - -type UserDetailsResponseList struct { - PoolId int64 `json:"pool_id"` - StrategyId int64 `json:"strategy_id"` - TotalDeposited decimal.Decimal `json:"total_deposited"` - CurrentDeposited decimal.Decimal `json:"current_deposited"` - RequestWithdraw decimal.Decimal `json:"request_withdraw"` - TotalWithdraw decimal.Decimal `json:"total_withdraw"` -} - -/////////////////////////////////////////////////// - -type TransactionRecordsRequest struct { - Owner string `json:"owner" form:"owner"` - Page int64 `json:"page" form:"page"` - PageSize int64 `json:"page_size" form:"page_size"` -} - -type TransactionRecordsResponse struct { - Code int `json:"code"` - Msg string `json:"msg"` - Data TransactionRecordsResponseData `json:"data"` -} - -type TransactionRecordsResponseData struct { - Total int64 `json:"total"` - List []TransactionRecordsResponseList `json:"list"` -} - -type TransactionRecordsResponseList struct { - Id int64 `json:"id"` - PoolId int64 `json:"pool_id"` - StrategyId int64 `json:"strategy_id"` - Type string `json:"type"` - Amount decimal.Decimal `json:"amount"` - Timestamp int64 `json:"timestamp"` - TxHash string `json:"tx_hash"` -} diff --git a/serv/internal/vo/message.go b/serv/internal/vo/message.go deleted file mode 100644 index d685e691..00000000 --- a/serv/internal/vo/message.go +++ /dev/null @@ -1 +0,0 @@ -package vo