{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
module Cardano.Wallet.Address.Pool
( Pool
, addressFromIx
, addresses
, usedAddresses
, gap
, lookup
, size
, successor
, new
, load
, update
, clear
, discover
, loadUnsafe
, prop_sequence
, prop_gap
, prop_fresh
, prop_fromIx
, prop_consistent
)
where
import Prelude hiding
( last, lookup )
import Cardano.Wallet.Primitive.Types.Address
( AddressState (..) )
import Control.DeepSeq
( NFData )
import Data.Map.Strict
( Map )
import Data.Ord
( Down (..) )
import Fmt
( Buildable (..) )
import GHC.Generics
( Generic )
import qualified Data.List as List
import qualified Data.Map.Strict as Map
data Pool addr ix = Pool
{ Pool addr ix -> ix -> addr
addressFromIx :: ix -> addr
, Pool addr ix -> Int
gap :: Int
, Pool addr ix -> Map addr (ix, AddressState)
addresses :: Map addr (ix, AddressState)
} deriving ((forall x. Pool addr ix -> Rep (Pool addr ix) x)
-> (forall x. Rep (Pool addr ix) x -> Pool addr ix)
-> Generic (Pool addr ix)
forall x. Rep (Pool addr ix) x -> Pool addr ix
forall x. Pool addr ix -> Rep (Pool addr ix) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall addr ix x. Rep (Pool addr ix) x -> Pool addr ix
forall addr ix x. Pool addr ix -> Rep (Pool addr ix) x
$cto :: forall addr ix x. Rep (Pool addr ix) x -> Pool addr ix
$cfrom :: forall addr ix x. Pool addr ix -> Rep (Pool addr ix) x
Generic)
instance (NFData addr, NFData ix) => NFData (Pool addr ix)
prop_sequence :: (Ord ix, Enum ix) => Pool addr ix -> Bool
prop_sequence :: Pool addr ix -> Bool
prop_sequence Pool{Map addr (ix, AddressState)
addresses :: Map addr (ix, AddressState)
addresses :: forall addr ix. Pool addr ix -> Map addr (ix, AddressState)
addresses} =
[ix]
indices [ix] -> [ix] -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`List.isPrefixOf` [Int -> ix
forall a. Enum a => Int -> a
toEnum Int
0..]
where
indices :: [ix]
indices = [ix] -> [ix]
forall a. Ord a => [a] -> [a]
List.sort ([ix] -> [ix]) -> [ix] -> [ix]
forall a b. (a -> b) -> a -> b
$ ((ix, AddressState) -> ix) -> [(ix, AddressState)] -> [ix]
forall a b. (a -> b) -> [a] -> [b]
map (ix, AddressState) -> ix
forall a b. (a, b) -> a
fst ([(ix, AddressState)] -> [ix]) -> [(ix, AddressState)] -> [ix]
forall a b. (a -> b) -> a -> b
$ Map addr (ix, AddressState) -> [(ix, AddressState)]
forall k a. Map k a -> [a]
Map.elems Map addr (ix, AddressState)
addresses
prop_gap :: Ord ix => Pool addr ix -> Bool
prop_gap :: Pool addr ix -> Bool
prop_gap Pool{Int
gap :: Int
gap :: forall addr ix. Pool addr ix -> Int
gap,Map addr (ix, AddressState)
addresses :: Map addr (ix, AddressState)
addresses :: forall addr ix. Pool addr ix -> Map addr (ix, AddressState)
addresses}
= (Int -> Bool) -> [Int] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
gap) ([Int] -> Bool)
-> ([AddressState] -> [Int]) -> [AddressState] -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [[AddressState]] -> [Int]
consecutiveUnused ([[AddressState]] -> [Int])
-> ([AddressState] -> [[AddressState]]) -> [AddressState] -> [Int]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [AddressState] -> [[AddressState]]
forall a. Eq a => [a] -> [[a]]
List.group ([AddressState] -> Bool) -> [AddressState] -> Bool
forall a b. (a -> b) -> a -> b
$ [AddressState]
statuses
where
consecutiveUnused :: [[AddressState]] -> [Int]
consecutiveUnused ((AddressState
Used:[AddressState]
_):[[AddressState]]
xs) = [[AddressState]] -> [Int]
consecutiveUnused [[AddressState]]
xs
consecutiveUnused (x :: [AddressState]
x@(AddressState
Unused:[AddressState]
_):(AddressState
Used:[AddressState]
_):[[AddressState]]
xs) =
[AddressState] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [AddressState]
x Int -> [Int] -> [Int]
forall a. a -> [a] -> [a]
: [[AddressState]] -> [Int]
consecutiveUnused [[AddressState]]
xs
consecutiveUnused [[AddressState]]
_ = []
statuses :: [AddressState]
statuses = ((ix, AddressState) -> AddressState)
-> [(ix, AddressState)] -> [AddressState]
forall a b. (a -> b) -> [a] -> [b]
map (ix, AddressState) -> AddressState
forall a b. (a, b) -> b
snd ([(ix, AddressState)] -> [AddressState])
-> [(ix, AddressState)] -> [AddressState]
forall a b. (a -> b) -> a -> b
$ ((ix, AddressState) -> ix)
-> [(ix, AddressState)] -> [(ix, AddressState)]
forall b a. Ord b => (a -> b) -> [a] -> [a]
List.sortOn (ix, AddressState) -> ix
forall a b. (a, b) -> a
fst ([(ix, AddressState)] -> [(ix, AddressState)])
-> [(ix, AddressState)] -> [(ix, AddressState)]
forall a b. (a -> b) -> a -> b
$ Map addr (ix, AddressState) -> [(ix, AddressState)]
forall k a. Map k a -> [a]
Map.elems Map addr (ix, AddressState)
addresses
prop_fresh :: Ord ix => Pool addr ix -> Bool
prop_fresh :: Pool addr ix -> Bool
prop_fresh Pool{Int
gap :: Int
gap :: forall addr ix. Pool addr ix -> Int
gap,Map addr (ix, AddressState)
addresses :: Map addr (ix, AddressState)
addresses :: forall addr ix. Pool addr ix -> Map addr (ix, AddressState)
addresses} =
(AddressState -> Bool) -> [AddressState] -> [AddressState]
forall a. (a -> Bool) -> [a] -> [a]
takeWhile (AddressState -> AddressState -> Bool
forall a. Eq a => a -> a -> Bool
== AddressState
Unused) [AddressState]
end [AddressState] -> [AddressState] -> Bool
forall a. Eq a => a -> a -> Bool
== Int -> AddressState -> [AddressState]
forall a. Int -> a -> [a]
replicate Int
gap AddressState
Unused
where
end :: [AddressState]
end = ((ix, AddressState) -> AddressState)
-> [(ix, AddressState)] -> [AddressState]
forall a b. (a -> b) -> [a] -> [b]
map (ix, AddressState) -> AddressState
forall a b. (a, b) -> b
snd ([(ix, AddressState)] -> [AddressState])
-> [(ix, AddressState)] -> [AddressState]
forall a b. (a -> b) -> a -> b
$ ((ix, AddressState) -> Down ix)
-> [(ix, AddressState)] -> [(ix, AddressState)]
forall b a. Ord b => (a -> b) -> [a] -> [a]
List.sortOn (ix -> Down ix
forall a. a -> Down a
Down (ix -> Down ix)
-> ((ix, AddressState) -> ix) -> (ix, AddressState) -> Down ix
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ix, AddressState) -> ix
forall a b. (a, b) -> a
fst) ([(ix, AddressState)] -> [(ix, AddressState)])
-> [(ix, AddressState)] -> [(ix, AddressState)]
forall a b. (a -> b) -> a -> b
$ Map addr (ix, AddressState) -> [(ix, AddressState)]
forall k a. Map k a -> [a]
Map.elems Map addr (ix, AddressState)
addresses
prop_fromIx :: Eq addr => Pool addr ix -> Bool
prop_fromIx :: Pool addr ix -> Bool
prop_fromIx Pool{ix -> addr
addressFromIx :: ix -> addr
addressFromIx :: forall addr ix. Pool addr ix -> ix -> addr
addressFromIx,Map addr (ix, AddressState)
addresses :: Map addr (ix, AddressState)
addresses :: forall addr ix. Pool addr ix -> Map addr (ix, AddressState)
addresses} =
Map addr Bool -> Bool
forall (t :: * -> *). Foldable t => t Bool -> Bool
and (Map addr Bool -> Bool) -> Map addr Bool -> Bool
forall a b. (a -> b) -> a -> b
$ (addr -> (ix, AddressState) -> Bool)
-> Map addr (ix, AddressState) -> Map addr Bool
forall k a b. (k -> a -> b) -> Map k a -> Map k b
Map.mapWithKey addr -> (ix, AddressState) -> Bool
isGenerated Map addr (ix, AddressState)
addresses
where
isGenerated :: addr -> (ix, AddressState) -> Bool
isGenerated addr
addr (ix
ix,AddressState
_) = ix -> addr
addressFromIx ix
ix addr -> addr -> Bool
forall a. Eq a => a -> a -> Bool
== addr
addr
prop_consistent :: (Ord ix, Enum ix, Eq addr) => Pool addr ix -> Bool
prop_consistent :: Pool addr ix -> Bool
prop_consistent Pool addr ix
p =
((Pool addr ix -> Bool) -> Bool) -> [Pool addr ix -> Bool] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all ((Pool addr ix -> Bool) -> Pool addr ix -> Bool
forall a b. (a -> b) -> a -> b
$ Pool addr ix
p) [Pool addr ix -> Bool
forall ix addr. (Ord ix, Enum ix) => Pool addr ix -> Bool
prop_sequence, Pool addr ix -> Bool
forall ix addr. Ord ix => Pool addr ix -> Bool
prop_gap, Pool addr ix -> Bool
forall ix addr. Ord ix => Pool addr ix -> Bool
prop_fresh, Pool addr ix -> Bool
forall addr ix. Eq addr => Pool addr ix -> Bool
prop_fromIx]
instance Buildable (Pool addr ix) where
build :: Pool addr ix -> Builder
build Pool addr ix
pool = Builder
"AddressPool "
Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
"{ " Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Int -> Builder
forall p. Buildable p => p -> Builder
build (Pool addr ix -> Int
forall addr ix. Pool addr ix -> Int
size Pool addr ix
pool) Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
" addresses"
Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
", gap = " Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Int -> Builder
forall p. Buildable p => p -> Builder
build (Pool addr ix -> Int
forall addr ix. Pool addr ix -> Int
gap Pool addr ix
pool)
Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
"}"
instance (Show addr, Show ix) => Show (Pool addr ix) where
show :: Pool addr ix -> String
show Pool addr ix
pool = String
"AddressPool"
String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
"{ addressFromIx = <<function>>"
String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
", gap = " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Int -> String
forall a. Show a => a -> String
show (Pool addr ix -> Int
forall addr ix. Pool addr ix -> Int
gap Pool addr ix
pool)
String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
", addresses = " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Map addr (ix, AddressState) -> String
forall a. Show a => a -> String
show (Pool addr ix -> Map addr (ix, AddressState)
forall addr ix. Pool addr ix -> Map addr (ix, AddressState)
addresses Pool addr ix
pool)
String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
"}"
new :: (Ord addr, Enum ix) => (ix -> addr) -> Int -> Pool addr ix
new :: (ix -> addr) -> Int -> Pool addr ix
new ix -> addr
addressFromIx Int
gap
= ix -> Pool addr ix -> Pool addr ix
forall addr ix.
(Ord addr, Enum ix) =>
ix -> Pool addr ix -> Pool addr ix
ensureFresh (Int -> ix
forall a. Enum a => Int -> a
toEnum Int
0) (Pool addr ix -> Pool addr ix) -> Pool addr ix -> Pool addr ix
forall a b. (a -> b) -> a -> b
$ Pool :: forall addr ix.
(ix -> addr) -> Int -> Map addr (ix, AddressState) -> Pool addr ix
Pool{ ix -> addr
addressFromIx :: ix -> addr
addressFromIx :: ix -> addr
addressFromIx, Int
gap :: Int
gap :: Int
gap, addresses :: Map addr (ix, AddressState)
addresses = Map addr (ix, AddressState)
forall k a. Map k a
Map.empty }
load
:: (Ord addr, Ord ix, Enum ix)
=> Pool addr ix -> Map addr (ix,AddressState) -> Maybe (Pool addr ix)
load :: Pool addr ix -> Map addr (ix, AddressState) -> Maybe (Pool addr ix)
load Pool addr ix
pool0 Map addr (ix, AddressState)
addrs = if Pool addr ix -> Bool
forall ix addr. (Ord ix, Enum ix, Eq addr) => Pool addr ix -> Bool
prop_consistent Pool addr ix
pool then Pool addr ix -> Maybe (Pool addr ix)
forall a. a -> Maybe a
Just Pool addr ix
pool else Maybe (Pool addr ix)
forall a. Maybe a
Nothing
where pool :: Pool addr ix
pool = Pool addr ix -> Map addr (ix, AddressState) -> Pool addr ix
forall addr ix.
Pool addr ix -> Map addr (ix, AddressState) -> Pool addr ix
loadUnsafe Pool addr ix
pool0 Map addr (ix, AddressState)
addrs
loadUnsafe :: Pool addr ix -> Map addr (ix,AddressState) -> Pool addr ix
loadUnsafe :: Pool addr ix -> Map addr (ix, AddressState) -> Pool addr ix
loadUnsafe Pool addr ix
pool Map addr (ix, AddressState)
addrs = Pool addr ix
pool{ addresses :: Map addr (ix, AddressState)
addresses = Map addr (ix, AddressState)
addrs }
clear :: (Ord addr, Enum ix) => Pool addr ix -> Pool addr ix
clear :: Pool addr ix -> Pool addr ix
clear Pool{ix -> addr
addressFromIx :: ix -> addr
addressFromIx :: forall addr ix. Pool addr ix -> ix -> addr
addressFromIx,Int
gap :: Int
gap :: forall addr ix. Pool addr ix -> Int
gap} = (ix -> addr) -> Int -> Pool addr ix
forall addr ix.
(Ord addr, Enum ix) =>
(ix -> addr) -> Int -> Pool addr ix
new ix -> addr
addressFromIx Int
gap
lookup :: Ord addr => addr -> Pool addr ix -> Maybe ix
lookup :: addr -> Pool addr ix -> Maybe ix
lookup addr
addr Pool{Map addr (ix, AddressState)
addresses :: Map addr (ix, AddressState)
addresses :: forall addr ix. Pool addr ix -> Map addr (ix, AddressState)
addresses} = (ix, AddressState) -> ix
forall a b. (a, b) -> a
fst ((ix, AddressState) -> ix) -> Maybe (ix, AddressState) -> Maybe ix
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> addr -> Map addr (ix, AddressState) -> Maybe (ix, AddressState)
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup addr
addr Map addr (ix, AddressState)
addresses
usedAddresses :: Pool addr ix -> [addr]
usedAddresses :: Pool addr ix -> [addr]
usedAddresses Pool addr ix
pool =
[ addr
addr | (addr
addr,(ix
_,AddressState
Used)) <- Map addr (ix, AddressState) -> [(addr, (ix, AddressState))]
forall k a. Map k a -> [(k, a)]
Map.toList (Map addr (ix, AddressState) -> [(addr, (ix, AddressState))])
-> Map addr (ix, AddressState) -> [(addr, (ix, AddressState))]
forall a b. (a -> b) -> a -> b
$ Pool addr ix -> Map addr (ix, AddressState)
forall addr ix. Pool addr ix -> Map addr (ix, AddressState)
addresses Pool addr ix
pool ]
size :: Pool addr ix -> Int
size :: Pool addr ix -> Int
size = Map addr (ix, AddressState) -> Int
forall k a. Map k a -> Int
Map.size (Map addr (ix, AddressState) -> Int)
-> (Pool addr ix -> Map addr (ix, AddressState))
-> Pool addr ix
-> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Pool addr ix -> Map addr (ix, AddressState)
forall addr ix. Pool addr ix -> Map addr (ix, AddressState)
addresses
successor :: Enum ix => Pool addr ix -> ix -> Maybe ix
successor :: Pool addr ix -> ix -> Maybe ix
successor Pool{Map addr (ix, AddressState)
addresses :: Map addr (ix, AddressState)
addresses :: forall addr ix. Pool addr ix -> Map addr (ix, AddressState)
addresses} ix
ix = let jx :: ix
jx = ix -> ix
forall a. Enum a => a -> a
succ ix
ix in
if ix -> Int
forall a. Enum a => a -> Int
fromEnum ix
jx Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Map addr (ix, AddressState) -> Int
forall k a. Map k a -> Int
Map.size Map addr (ix, AddressState)
addresses then Maybe ix
forall a. Maybe a
Nothing else ix -> Maybe ix
forall a. a -> Maybe a
Just ix
jx
update :: (Ord addr, Enum ix) => addr -> Pool addr ix -> Pool addr ix
update :: addr -> Pool addr ix -> Pool addr ix
update addr
addr pool :: Pool addr ix
pool@Pool{Map addr (ix, AddressState)
addresses :: Map addr (ix, AddressState)
addresses :: forall addr ix. Pool addr ix -> Map addr (ix, AddressState)
addresses} =
case addr -> Map addr (ix, AddressState) -> Maybe (ix, AddressState)
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup addr
addr Map addr (ix, AddressState)
addresses of
Maybe (ix, AddressState)
Nothing -> Pool addr ix
pool
Just (ix
ix,AddressState
_) -> ix -> Pool addr ix -> Pool addr ix
forall addr ix.
(Ord addr, Enum ix) =>
ix -> Pool addr ix -> Pool addr ix
ensureFresh (ix -> ix
forall a. Enum a => a -> a
succ ix
ix) (Pool addr ix -> Pool addr ix) -> Pool addr ix -> Pool addr ix
forall a b. (a -> b) -> a -> b
$ Pool addr ix
pool
{ addresses :: Map addr (ix, AddressState)
addresses = ((ix, AddressState) -> (ix, AddressState))
-> addr
-> Map addr (ix, AddressState)
-> Map addr (ix, AddressState)
forall k a. Ord k => (a -> a) -> k -> Map k a -> Map k a
Map.adjust (\(ix
i,AddressState
_) -> (ix
i, AddressState
Used)) addr
addr Map addr (ix, AddressState)
addresses }
ensureFresh :: (Ord addr, Enum ix) => ix -> Pool addr ix -> Pool addr ix
ensureFresh :: ix -> Pool addr ix -> Pool addr ix
ensureFresh ix
ix pool :: Pool addr ix
pool@Pool{ix -> addr
addressFromIx :: ix -> addr
addressFromIx :: forall addr ix. Pool addr ix -> ix -> addr
addressFromIx,Int
gap :: Int
gap :: forall addr ix. Pool addr ix -> Int
gap,Map addr (ix, AddressState)
addresses :: Map addr (ix, AddressState)
addresses :: forall addr ix. Pool addr ix -> Map addr (ix, AddressState)
addresses}
= Pool addr ix
pool { addresses :: Map addr (ix, AddressState)
addresses = Map addr (ix, AddressState)
-> Map addr (ix, AddressState) -> Map addr (ix, AddressState)
forall k a. Ord k => Map k a -> Map k a -> Map k a
Map.union Map addr (ix, AddressState)
addresses Map addr (ix, AddressState)
nexts }
where
fresh :: ix
fresh = Int -> ix
forall a. Enum a => Int -> a
toEnum (Int -> ix) -> Int -> ix
forall a b. (a -> b) -> a -> b
$ Map addr (ix, AddressState) -> Int
forall k a. Map k a -> Int
Map.size Map addr (ix, AddressState)
addresses
nexts :: Map addr (ix, AddressState)
nexts = [(addr, (ix, AddressState))] -> Map addr (ix, AddressState)
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList
[ (ix -> addr
addressFromIx ix
i, (ix
i, AddressState
Unused)) | ix
i <- [ix
fresh .. ix
to] ]
where
to :: ix
to = Int -> ix
forall a. Enum a => Int -> a
toEnum (Int -> ix) -> Int -> ix
forall a b. (a -> b) -> a -> b
$ ix -> Int
forall a. Enum a => a -> Int
fromEnum ix
ix Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
gap Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1
discover
:: (Enum ix, Ord addr, Monad m, Monoid txs, Eq txs)
=> (addr -> m txs) -> Pool addr ix -> m (txs, Pool addr ix)
discover :: (addr -> m txs) -> Pool addr ix -> m (txs, Pool addr ix)
discover addr -> m txs
query Pool addr ix
pool0 =
txs -> Pool addr ix -> ix -> m (txs, Pool addr ix)
go txs
forall a. Monoid a => a
mempty Pool addr ix
pool0 (ix -> m (txs, Pool addr ix)) -> ix -> m (txs, Pool addr ix)
forall a b. (a -> b) -> a -> b
$ Int -> ix
forall a. Enum a => Int -> a
toEnum Int
0
where
go :: txs -> Pool addr ix -> ix -> m (txs, Pool addr ix)
go !txs
txs1 !Pool addr ix
pool1 ix
old = do
let addr :: addr
addr = Pool addr ix -> ix -> addr
forall addr ix. Pool addr ix -> ix -> addr
addressFromIx Pool addr ix
pool0 ix
old
txs
newtxs <- addr -> m txs
query addr
addr
let (Pool addr ix
pool2, txs
txs2) = if txs
forall a. Monoid a => a
mempty txs -> txs -> Bool
forall a. Eq a => a -> a -> Bool
== txs
newtxs
then (Pool addr ix
pool1, txs
txs1)
else (addr -> Pool addr ix -> Pool addr ix
forall addr ix.
(Ord addr, Enum ix) =>
addr -> Pool addr ix -> Pool addr ix
update addr
addr Pool addr ix
pool1, txs
txs1 txs -> txs -> txs
forall a. Semigroup a => a -> a -> a
<> txs
newtxs)
case Pool addr ix -> ix -> Maybe ix
forall ix addr. Enum ix => Pool addr ix -> ix -> Maybe ix
successor Pool addr ix
pool2 ix
old of
Maybe ix
Nothing -> (txs, Pool addr ix) -> m (txs, Pool addr ix)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (txs
txs2, Pool addr ix
pool2)
Just ix
next -> txs -> Pool addr ix -> ix -> m (txs, Pool addr ix)
go txs
txs2 Pool addr ix
pool2 ix
next