Check that hooks are called in order and the chain exits correctly We start two nodes, l2 will have two plugins registering the same hook (`htlc_accepted`) but handle different cases: - the `odd` plugin only handles the "AA"*32 preimage - the `even` plugin only handles the "BB"*32
(node_factory)
| 1927 | |
| 1928 | |
| 1929 | def test_hook_chaining(node_factory): |
| 1930 | """Check that hooks are called in order and the chain exits correctly |
| 1931 | |
| 1932 | We start two nodes, l2 will have two plugins registering the same hook |
| 1933 | (`htlc_accepted`) but handle different cases: |
| 1934 | |
| 1935 | - the `odd` plugin only handles the "AA"*32 preimage |
| 1936 | - the `even` plugin only handles the "BB"*32 preimage |
| 1937 | |
| 1938 | We check that plugins are called in the order they are registering the |
| 1939 | hook, and that they exit the call chain as soon as one plugin returns a |
| 1940 | result that isn't `continue`. On exiting the chain the remaining plugins |
| 1941 | are not called. If no plugin exits the chain we continue to handle |
| 1942 | internally as usual. |
| 1943 | |
| 1944 | """ |
| 1945 | l1, l2 = node_factory.line_graph(2) |
| 1946 | |
| 1947 | # Start the plugins manually instead of specifying them on the command |
| 1948 | # line, otherwise we cannot guarantee the order in which the hooks are |
| 1949 | # registered. |
| 1950 | p1 = os.path.join(os.path.dirname(__file__), "plugins/hook-chain-odd.py") |
| 1951 | p2 = os.path.join(os.path.dirname(__file__), "plugins/hook-chain-even.py") |
| 1952 | l2.rpc.plugin_start(p1) |
| 1953 | l2.rpc.plugin_start(p2) |
| 1954 | |
| 1955 | preimage1 = b'\xAA' * 32 |
| 1956 | preimage2 = b'\xBB' * 32 |
| 1957 | preimage3 = b'\xCC' * 32 |
| 1958 | hash1 = sha256(preimage1).hexdigest() |
| 1959 | hash2 = sha256(preimage2).hexdigest() |
| 1960 | hash3 = sha256(preimage3).hexdigest() |
| 1961 | |
| 1962 | inv = l2.rpc.invoice(123, 'odd', "Odd payment handled by the first plugin", |
| 1963 | preimage="AA" * 32)['bolt11'] |
| 1964 | l1.rpc.xpay(inv) |
| 1965 | |
| 1966 | # The first plugin will handle this, the second one should not be called. |
| 1967 | assert(l2.daemon.is_in_log( |
| 1968 | r'plugin-hook-chain-odd.py: htlc_accepted called for payment_hash {}'.format(hash1) |
| 1969 | )) |
| 1970 | assert(not l2.daemon.is_in_log( |
| 1971 | r'plugin-hook-chain-even.py: htlc_accepted called for payment_hash {}'.format(hash1) |
| 1972 | )) |
| 1973 | |
| 1974 | # The second run is with a payment_hash that `hook-chain-even.py` knows |
| 1975 | # about. `hook-chain-odd.py` is called, it returns a `continue`, and then |
| 1976 | # `hook-chain-even.py` resolves it. |
| 1977 | inv = l2.rpc.invoice( |
| 1978 | 123, 'even', "Even payment handled by the second plugin", preimage="BB" * 32 |
| 1979 | )['bolt11'] |
| 1980 | l1.rpc.xpay(inv) |
| 1981 | assert(l2.daemon.is_in_log( |
| 1982 | r'plugin-hook-chain-odd.py: htlc_accepted called for payment_hash {}'.format(hash2) |
| 1983 | )) |
| 1984 | assert(l2.daemon.is_in_log( |
| 1985 | r'plugin-hook-chain-even.py: htlc_accepted called for payment_hash {}'.format(hash2) |
| 1986 | )) |
nothing calls this directly
no test coverage detected