From 4901f31babf84f8b003c6220f7ace5306c6d6196 Mon Sep 17 00:00:00 2001 From: 0xd34df00d <0xd34df00d@gmail.com> Date: Tue, 5 Dec 2023 14:51:16 -0600 Subject: [PATCH 01/20] Remove a trivial todo that relies on un-enforced namespaced keysets --- pact-core-tests/pact-tests/namespaces.repl | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pact-core-tests/pact-tests/namespaces.repl b/pact-core-tests/pact-tests/namespaces.repl index 8d41539bb..62ddd7841 100644 --- a/pact-core-tests/pact-tests/namespaces.repl +++ b/pact-core-tests/pact-tests/namespaces.repl @@ -126,8 +126,7 @@ (defconst TBOOL true) ) -; Todo: namespaced keysets here -; (env-exec-config ['DisablePact44]) +(env-exec-config []) (env-data { "test-keys" : ["test"] }) (define-keyset 'test-keys) (env-keys ["test"]) From dda53cc9a9e40d13213c8bb07fa9cdd2239d4b79 Mon Sep 17 00:00:00 2001 From: 0xd34df00d <0xd34df00d@gmail.com> Date: Tue, 5 Dec 2023 15:14:39 -0600 Subject: [PATCH 02/20] This TODO is also easy since the legacy test disables namespaces check here --- pact-core-tests/pact-tests/namespaces.repl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pact-core-tests/pact-tests/namespaces.repl b/pact-core-tests/pact-tests/namespaces.repl index 62ddd7841..866efd21f 100644 --- a/pact-core-tests/pact-tests/namespaces.repl +++ b/pact-core-tests/pact-tests/namespaces.repl @@ -178,7 +178,7 @@ ) (begin-tx) -; Todo: namespaced keysets here +(env-exec-config []) (env-data { 'user: ["user"], 'admin: ["admin"] }) (define-namespace 'ns-user-behavior (read-keyset 'user) (read-keyset 'admin)) (namespace 'ns-user-behavior) From 2d1a4fcd686326edc53da3ddf6f895a89b877eb5 Mon Sep 17 00:00:00 2001 From: 0xd34df00d <0xd34df00d@gmail.com> Date: Tue, 5 Dec 2023 15:22:09 -0600 Subject: [PATCH 03/20] =?UTF-8?q?=E2=80=A6and=20this=20one=20does=20enable?= =?UTF-8?q?=20them,=20so=20require=20namespaced=20keysets=20here?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pact-core-tests/pact-tests/namespaces.repl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pact-core-tests/pact-tests/namespaces.repl b/pact-core-tests/pact-tests/namespaces.repl index 866efd21f..38cace397 100644 --- a/pact-core-tests/pact-tests/namespaces.repl +++ b/pact-core-tests/pact-tests/namespaces.repl @@ -197,7 +197,7 @@ (begin-tx) (env-data { 'user: ["user"], 'admin: ["admin"] }) (env-keys []) -(env-exec-config []) +(env-exec-config ['RequireKeysetNs]) (expect-failure "ensure user keyset does not pass" (enforce-keyset (read-keyset 'user))) From 3e092f315d7feff56b03409adc942bad3b930539 Mon Sep 17 00:00:00 2001 From: 0xd34df00d <0xd34df00d@gmail.com> Date: Tue, 5 Dec 2023 15:40:11 -0600 Subject: [PATCH 04/20] This test actually implies namespaced keysets should be on, so set the flag --- pact-core-tests/pact-tests/namespaces.repl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pact-core-tests/pact-tests/namespaces.repl b/pact-core-tests/pact-tests/namespaces.repl index 38cace397..2f60b19fd 100644 --- a/pact-core-tests/pact-tests/namespaces.repl +++ b/pact-core-tests/pact-tests/namespaces.repl @@ -75,6 +75,8 @@ (commit-tx) (begin-tx) +(env-exec-config ['RequireKeysetNs]) + (env-data { "carl-keys" : ["carl"] , "carl.carl-keys": ["carl"] From ccc84fb2474c27b356acc8a3c2a37ada688be097 Mon Sep 17 00:00:00 2001 From: 0xd34df00d <0xd34df00d@gmail.com> Date: Tue, 5 Dec 2023 16:17:45 -0600 Subject: [PATCH 05/20] Enable the namespaced keysets for consistency in the final test Although they aren't mentioned here explicitly, it's probably a good idea nevertheless for consistency with legacy pact tests' behaviour. --- pact-core-tests/pact-tests/namespaces.repl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pact-core-tests/pact-tests/namespaces.repl b/pact-core-tests/pact-tests/namespaces.repl index 2f60b19fd..c36fa88be 100644 --- a/pact-core-tests/pact-tests/namespaces.repl +++ b/pact-core-tests/pact-tests/namespaces.repl @@ -278,7 +278,7 @@ (begin-tx) -(env-exec-config []) +(env-exec-config ['RequireKeysetNs]) (expect "Setting namespace back to root namespace post-Pact 4.7 fork succeeds" From da9632077f47d6e8a47b01199032104ddf349543 Mon Sep 17 00:00:00 2001 From: jmcardon Date: Thu, 7 Dec 2023 13:10:43 -0500 Subject: [PATCH 06/20] Wip more missing stuff --- .../Pact/Core/Test/LexerParserTests.hs | 18 ++++---- pact-core-tests/Pact/Core/Test/ReplTests.hs | 14 +++--- pact-core.cabal | 29 ++++++++++++ pact-core/Pact/Core/Compile.hs | 8 ++-- pact-core/Pact/Core/IR/Eval/RawBuiltin.hs | 27 +++++++----- pact-core/Pact/Core/Repl/Compile.hs | 4 +- pact-core/Pact/Core/Repl/Utils.hs | 3 +- pact-core/Pact/Core/Syntax/LexUtils.hs | 44 +++++++++++++++---- pact-core/Pact/Core/Syntax/Lexer.x | 29 ++++++------ pact-core/Pact/Core/Syntax/ParseTree.hs | 11 ++++- pact-core/Pact/Core/Syntax/Parser.y | 17 ++++--- 11 files changed, 133 insertions(+), 71 deletions(-) diff --git a/pact-core-tests/Pact/Core/Test/LexerParserTests.hs b/pact-core-tests/Pact/Core/Test/LexerParserTests.hs index c1f1d0699..f6c06734a 100644 --- a/pact-core-tests/Pact/Core/Test/LexerParserTests.hs +++ b/pact-core-tests/Pact/Core/Test/LexerParserTests.hs @@ -7,8 +7,6 @@ import Control.Applicative ((<|>)) import qualified Hedgehog.Gen as Gen import qualified Hedgehog.Range as Range import qualified Data.Text as T -import Data.Text.Encoding (encodeUtf8) -import qualified Data.ByteString.Char8 as BS import Data.Decimal(DecimalRaw(..)) import Pact.Core.Names @@ -20,14 +18,14 @@ import Pact.Core.Syntax.LexUtils (Token(..)) import Pact.Core.Literal import Pact.Core.Pretty -showPretty :: Pretty a => a -> BS.ByteString -showPretty = BS.pack . show . pretty +showPretty :: Pretty a => a -> T.Text +showPretty = T.pack . show . pretty -tokenToSrc :: Token -> BS.ByteString +tokenToSrc :: Token -> T.Text tokenToSrc = \case TokenString s -> "\"" <> showPretty s <> "\"" - TokenIdent n -> encodeUtf8 n - TokenNumber n -> encodeUtf8 n + TokenIdent n -> n + TokenNumber n -> n tok -> showPretty tok identGen :: Gen T.Text @@ -86,7 +84,7 @@ tokenGen = Gen.choice $ unary ++ [ TokenIdent <$> identGen, number, string] lexerRoundtrip :: Property lexerRoundtrip = property $ do toks <- forAll $ Gen.list (Range.constant 0 10) tokenGen - ptoks <- evalEither $ Lisp.lexer (BS.unlines (tokenToSrc <$> toks)) + ptoks <- evalEither $ Lisp.lexer (T.unlines (tokenToSrc <$> toks)) toks === (Lisp._ptToken <$> ptoks) @@ -95,8 +93,8 @@ type ParserGen = Gen (Lisp.Expr ()) toUnitExpr :: Lisp.ParsedExpr -> Lisp.Expr () toUnitExpr = fmap $ const () -parsedExprToSrc :: Lisp.Expr () -> BS.ByteString -parsedExprToSrc = BS.pack . show . pretty +parsedExprToSrc :: Lisp.Expr () -> T.Text +parsedExprToSrc = T.pack . show . pretty varGen :: ParserGen varGen = (`Lisp.Var` ()) <$> parsedNameGen diff --git a/pact-core-tests/Pact/Core/Test/ReplTests.hs b/pact-core-tests/Pact/Core/Test/ReplTests.hs index c3f174b0e..bb719c723 100644 --- a/pact-core-tests/Pact/Core/Test/ReplTests.hs +++ b/pact-core-tests/Pact/Core/Test/ReplTests.hs @@ -6,14 +6,13 @@ import Test.Tasty.HUnit import Control.Monad(when) import Data.IORef import Data.Default -import Data.ByteString(ByteString) +import Data.Text(Text) import Data.Foldable(traverse_) -import Data.Text.Encoding(decodeUtf8) import System.Directory import System.FilePath import qualified Data.Text as T -import qualified Data.ByteString as B +import qualified Data.Text.IO as T import Pact.Core.Gas import Pact.Core.Literal @@ -42,9 +41,9 @@ replTestFiles = do filter (\f -> isExtensionOf "repl" f || isExtensionOf "pact" f) <$> getDirectoryContents replTestDir runFileReplTest :: TestName -> TestTree -runFileReplTest file = testCase file $ B.readFile (replTestDir file) >>= runReplTest file +runFileReplTest file = testCase file $ T.readFile (replTestDir file) >>= runReplTest file -runReplTest :: FilePath -> ByteString -> Assertion +runReplTest :: FilePath -> Text -> Assertion runReplTest file src = do gasRef <- newIORef (Gas 0) gasLog <- newIORef Nothing @@ -64,15 +63,14 @@ runReplTest file src = do stateRef <- newIORef rstate runReplT stateRef (interpretReplProgram source (const (pure ()))) >>= \case Left e -> let - rendered = replError (ReplSource (T.pack file) (decodeUtf8 src)) e + rendered = replError (ReplSource (T.pack file) src) e in assertFailure (T.unpack rendered) Right output -> traverse_ ensurePassing output where ensurePassing = \case RCompileValue (InterpretValue (IPV v i)) -> case v of PLiteral (LString msg) -> do - let render = replError (ReplSource (T.pack file) (decodeUtf8 src)) (PEExecutionError (EvalError msg) i) + let render = replError (ReplSource (T.pack file) src) (PEExecutionError (EvalError msg) i) when (T.isPrefixOf "FAILURE:" msg) $ assertFailure (T.unpack render) _ -> pure () _ -> pure () - diff --git a/pact-core.cabal b/pact-core.cabal index aaa206612..873e663fd 100644 --- a/pact-core.cabal +++ b/pact-core.cabal @@ -17,6 +17,14 @@ copyright: Copyright (C) 2022 Kadena category: Language build-type: Simple +extra-source-files: + cbits/musl/libm.h + cbits/musl/endian.h + cbits/musl/exp_data.h + cbits/musl/log_data.h + cbits/musl/pow_data.h + cbits/musl/sqrt_data.h + common pact-core-common build-depends: , Decimal @@ -57,6 +65,9 @@ common pact-core-common , pact-json , scientific , unordered-containers + , groups + , poly + , mod ghc-options: -Wall -Werror -Wincomplete-record-updates -Wincomplete-uni-patterns -Wredundant-constraints ghc-prof-options: -fprof-auto -fprof-auto-calls @@ -80,6 +91,21 @@ library , alex:alex , happy:happy + c-sources: + cbits/musl/__math_invalid.c + cbits/musl/__math_divzero.c + cbits/musl/__math_oflow.c + cbits/musl/__math_uflow.c + cbits/musl/__math_xflow.c + cbits/musl/exp.c + cbits/musl/exp_data.c + cbits/musl/log.c + cbits/musl/log_data.c + cbits/musl/pow.c + cbits/musl/pow_data.c + cbits/musl/sqrt.c + cbits/musl/sqrt_data.c + exposed-modules: Pact.Core.Compile Pact.Core.Builtin @@ -108,6 +134,7 @@ library Pact.Core.Principal Pact.Core.Namespace Pact.Core.RuntimeParsers + Pact.Core.Pairing -- Syntax modules Pact.Core.Syntax.ParseTree @@ -128,6 +155,8 @@ library Pact.Core.IR.ModuleHashing Pact.Core.IR.ConstEval + Pact.Core.Trans.TOps + -- Repl Pact.Core.Repl.Utils Pact.Core.Repl.Runtime.ReplBuiltin diff --git a/pact-core/Pact/Core/Compile.hs b/pact-core/Pact/Core/Compile.hs index c788082f0..b009ef219 100644 --- a/pact-core/Pact/Core/Compile.hs +++ b/pact-core/Pact/Core/Compile.hs @@ -17,10 +17,10 @@ import Control.Lens import Control.Monad.Except import Control.Monad import Data.Maybe(mapMaybe) -import Data.ByteString(ByteString) +import Data.Text(Text) import qualified Data.Map.Strict as M -import qualified Data.ByteString as B import qualified Data.Set as S +import qualified Data.Text.IO as T import Pact.Core.Debug import Pact.Core.Builtin @@ -54,13 +54,13 @@ type HasCompileEnv b i m , PhaseDebug b i m) _parseOnly - :: ByteString -> Either PactErrorI [Lisp.TopLevel SpanInfo] + :: Text -> Either PactErrorI [Lisp.TopLevel SpanInfo] _parseOnly source = do lexed <- liftEither (Lisp.lexer source) liftEither (Lisp.parseProgram lexed) _parseOnlyFile :: FilePath -> IO (Either PactErrorI [Lisp.TopLevel SpanInfo]) -_parseOnlyFile fp = _parseOnly <$> B.readFile fp +_parseOnlyFile fp = _parseOnly <$> T.readFile fp data CompileValue b = LoadedModule ModuleName ModuleHash diff --git a/pact-core/Pact/Core/IR/Eval/RawBuiltin.hs b/pact-core/Pact/Core/IR/Eval/RawBuiltin.hs index b7c50af5c..a2d125b4d 100644 --- a/pact-core/Pact/Core/IR/Eval/RawBuiltin.hs +++ b/pact-core/Pact/Core/IR/Eval/RawBuiltin.hs @@ -44,6 +44,7 @@ import qualified Data.Set as S import qualified Data.Char as Char import qualified Data.ByteString as BS import qualified Pact.Time as PactTime +import qualified Pact.Core.Trans.TOps as Musl import Pact.Core.Builtin import Pact.Core.Literal @@ -125,9 +126,10 @@ rawPow :: (IsBuiltin b, MonadEval b i m) => NativeFunction b i m rawPow info b cont handler _env = \case [VLiteral (LInteger i), VLiteral (LInteger i')] -> do when (i' < 0) $ throwExecutionError info (ArithmeticException "negative exponent in integer power") + -- Todo: move to iterated pow returnCEKValue cont handler (VLiteral (LInteger (i ^ i'))) [VLiteral (LDecimal l), VLiteral (LDecimal r)] -> do - let result = dec2F l ** dec2F r + let result = Musl.trans_pow (dec2F l) (dec2F r) guardNanOrInf info result returnCEKValue cont handler (VLiteral (LDecimal (f2Dec result))) args -> argsError info b args @@ -138,13 +140,13 @@ rawLogBase info b cont handler _env = \case when (base < 0 || n <= 0) $ throwExecutionError info (ArithmeticException "Illegal log base") let base' = fromIntegral base :: Double n' = fromIntegral n - out = round (logBase base' n') + out = round (Musl.trans_logBase base' n') returnCEKValue cont handler (VLiteral (LInteger out)) -- if i' == 0 then throwExecutionError' (ArithmeticException "div by zero") -- else returnCEKValue cont handler (VLiteral (LInteger (div i i'))) [VLiteral (LDecimal base), VLiteral (LDecimal arg)] -> do when (base < 0 || arg <= 0) $ throwExecutionError info (ArithmeticException "Invalid base or argument in log") - let result = logBase (dec2F base) (dec2F arg) + let result = Musl.trans_logBase (dec2F base) (dec2F arg) guardNanOrInf info result returnCEKValue cont handler (VLiteral (LDecimal (f2Dec result))) args -> argsError info b args @@ -235,11 +237,11 @@ rawAbs info b cont handler _env = \case rawExp :: (IsBuiltin b, MonadEval b i m) => NativeFunction b i m rawExp info b cont handler _env = \case [VLiteral (LInteger i)] -> do - let result = exp (fromIntegral i) + let result = Musl.trans_exp (fromIntegral i) guardNanOrInf info result returnCEKValue cont handler (VLiteral (LDecimal (f2Dec result))) [VLiteral (LDecimal e)] -> do - let result = exp (dec2F e) + let result = Musl.trans_exp (dec2F e) guardNanOrInf info result returnCEKValue cont handler (VLiteral (LDecimal (f2Dec result))) args -> argsError info b args @@ -247,11 +249,11 @@ rawExp info b cont handler _env = \case rawLn :: (IsBuiltin b, MonadEval b i m) => NativeFunction b i m rawLn info b cont handler _env = \case [VLiteral (LInteger i)] -> do - let result = log (fromIntegral i) + let result = Musl.trans_ln (fromIntegral i) guardNanOrInf info result returnCEKValue cont handler (VLiteral (LDecimal (f2Dec result))) [VLiteral (LDecimal e)] -> do - let result = log (dec2F e) + let result = Musl.trans_ln (dec2F e) guardNanOrInf info result returnCEKValue cont handler (VLiteral (LDecimal (f2Dec result))) args -> argsError info b args @@ -260,12 +262,12 @@ rawSqrt :: (IsBuiltin b, MonadEval b i m) => NativeFunction b i m rawSqrt info b cont handler _env = \case [VLiteral (LInteger i)] -> do when (i < 0) $ throwExecutionError info (ArithmeticException "Square root must be non-negative") - let result = sqrt (fromIntegral i) + let result = Musl.trans_sqrt (fromIntegral i) guardNanOrInf info result returnCEKValue cont handler (VLiteral (LDecimal (f2Dec result))) [VLiteral (LDecimal e)] -> do when (e < 0) $ throwExecutionError info (ArithmeticException "Square root must be non-negative") - let result = sqrt (dec2F e) + let result = Musl.trans_sqrt (dec2F e) guardNanOrInf info result returnCEKValue cont handler (VLiteral (LDecimal (f2Dec result))) args -> argsError info b args @@ -1603,8 +1605,13 @@ coreDescribeNamespace info b cont handler _env = \case returnCEK cont handler (VError ("Namespace not defined " <> n) info) args -> argsError info b args + +-- ------------------------- +-- ZK defns +-- ------------------------- + ----------------------------------- --- Core definitions +-- Builtin exports ----------------------------------- rawBuiltinEnv diff --git a/pact-core/Pact/Core/Repl/Compile.hs b/pact-core/Pact/Core/Repl/Compile.hs index 3a0d162b0..c4389990b 100644 --- a/pact-core/Pact/Core/Repl/Compile.hs +++ b/pact-core/Pact/Core/Repl/Compile.hs @@ -20,8 +20,8 @@ import System.FilePath(takeFileName) import qualified Data.Map.Strict as M -import qualified Data.ByteString as B import qualified Data.Text as T +import qualified Data.Text.IO as T import Pact.Core.Persistence import Pact.Core.Builtin @@ -57,7 +57,7 @@ loadFile -> (ReplCompileValue -> ReplM ReplRawBuiltin ()) -> ReplM ReplRawBuiltin [ReplCompileValue] loadFile loc display = do - source <- SourceCode (takeFileName loc) <$> liftIO (B.readFile loc) + source <- SourceCode (takeFileName loc) <$> liftIO (T.readFile loc) replCurrSource .= source interpretReplProgram source display diff --git a/pact-core/Pact/Core/Repl/Utils.hs b/pact-core/Pact/Core/Repl/Utils.hs index 8a2d8bc9e..94d19cbfe 100644 --- a/pact-core/Pact/Core/Repl/Utils.hs +++ b/pact-core/Pact/Core/Repl/Utils.hs @@ -48,7 +48,6 @@ import Data.Set(Set) import Data.Text(Text) import Data.List(isPrefixOf) import Data.Maybe(mapMaybe) -import Data.ByteString(ByteString) import qualified Data.Set as Set import qualified Data.Map.Strict as M import qualified Data.Text as T @@ -72,7 +71,7 @@ import System.Console.Haskeline.Completion data SourceCode = SourceCode { _scFileName :: String - , _scPayload :: ByteString } + , _scPayload :: Text } deriving Show data ReplDebugFlag diff --git a/pact-core/Pact/Core/Syntax/LexUtils.hs b/pact-core/Pact/Core/Syntax/LexUtils.hs index f898814e9..d4f7d2c57 100644 --- a/pact-core/Pact/Core/Syntax/LexUtils.hs +++ b/pact-core/Pact/Core/Syntax/LexUtils.hs @@ -15,12 +15,10 @@ import Control.Monad.State.Strict import Data.Word (Word8) import Data.Text(Text) import Data.List(intersperse) -import Data.ByteString.Internal(w2c) -import Data.ByteString(ByteString) import Data.Default -import qualified Data.ByteString as B import qualified Data.Text as T +import qualified Data.Char as C import Pact.Core.Info import Pact.Core.Errors @@ -68,6 +66,7 @@ data Token | TokenDefSchema | TokenDefTable | TokenDefProperty + | TokenProperty | TokenBless | TokenImplements -- Annotations @@ -133,7 +132,7 @@ data AlexInput { _inpLine :: {-# UNPACK #-} !Int , _inpColumn :: {-# UNPACK #-} !Int , _inpLast :: {-# UNPACK #-} !Char - , _inpStream :: ByteString + , _inpStream :: Text } deriving (Eq, Show) @@ -142,11 +141,37 @@ makeLenses ''AlexInput alexPrevInputChar :: AlexInput -> Char alexPrevInputChar = _inpLast +c2w :: Char -> Word8 +c2w = fromIntegral . C.ord + +w2c :: Word8 -> Char +w2c = C.chr . fromIntegral + alexGetByte :: AlexInput -> Maybe (Word8, AlexInput) alexGetByte (AlexInput line col _ stream) = - advance <$> B.uncons stream + advance <$> T.uncons stream + where + advance (c, rest) | c == '\n' = + (c2w c + , AlexInput + { _inpLine = line +1 + , _inpColumn = 0 + , _inpLast = '\n' + , _inpStream = rest}) + + advance (c, rest) = + (c2w c + , AlexInput + { _inpLine = line + , _inpColumn = col +1 + , _inpLast = c + , _inpStream = rest}) + +lexerGetChar :: AlexInput -> Maybe (Char, AlexInput) +lexerGetChar (AlexInput line col _ stream) = + advance <$> T.uncons stream where - advance (c, rest) | w2c c == '\n' = + advance (c, rest) | c == '\n' = (c , AlexInput { _inpLine = line +1 @@ -159,7 +184,7 @@ alexGetByte (AlexInput line col _ stream) = , AlexInput { _inpLine = line , _inpColumn = col +1 - , _inpLast = w2c c + , _inpLast = c , _inpStream = rest}) newtype Layout @@ -176,7 +201,7 @@ newtype LexerM a = via (StateT AlexInput (Either PactErrorI)) -initState :: ByteString -> AlexInput +initState :: Text -> AlexInput initState = AlexInput 0 0 '\n' getSpanInfo :: LexerM SpanInfo @@ -249,7 +274,7 @@ parseError (remaining, exps) = [] -> def x:_ -> _ptInfo x -runLexerT :: LexerM a -> ByteString -> Either PactErrorI a +runLexerT :: LexerM a -> Text -> Either PactErrorI a runLexerT (LexerM act) s = evalStateT act (initState s) renderTokenText :: Token -> Text @@ -290,6 +315,7 @@ renderTokenText = \case TokenDot -> "." TokenBindAssign -> ":=" TokenDynAcc -> "::" + TokenProperty -> "property" -- TokenEq -> "=" -- TokenNeq -> "!=" -- TokenGT -> ">" diff --git a/pact-core/Pact/Core/Syntax/Lexer.x b/pact-core/Pact/Core/Syntax/Lexer.x index 02701ad08..c4ed5b040 100644 --- a/pact-core/Pact/Core/Syntax/Lexer.x +++ b/pact-core/Pact/Core/Syntax/Lexer.x @@ -11,12 +11,8 @@ import Control.Monad.State.Strict import Control.Exception(throwIO) import Data.Char(isSpace) import Data.Text(Text) -import Data.ByteString(ByteString) -import Data.ByteString.Internal(w2c) -import qualified Data.ByteString as B import qualified Data.Text as T -import qualified Data.Text.Encoding as T import Pact.Core.Info import Pact.Core.Errors @@ -62,6 +58,7 @@ tokens :- defcap { token TokenDefCap } defpact { token TokenDefPact } defproperty { token TokenDefProperty } + property { token TokenProperty } interface { token TokenInterface } module { token TokenModule } bless { token TokenBless } @@ -116,15 +113,15 @@ tokens :- -- TODO: non-horrible errors scan :: LexerM PosToken scan = do - input@(AlexInput sLine sCol _ bs) <- get + input@(AlexInput sLine sCol _ txt) <- get case alexScan input 0 of AlexEOF -> pure (PosToken TokenEOF (SpanInfo sLine sCol (sLine+1) 0)) AlexError (AlexInput eLine eCol _last inp) -> let li = SpanInfo sLine sCol eLine eCol - in case B.uncons inp of + in case T.uncons inp of Just (h, _) -> - throwLexerError (LexicalError (w2c h) _last) li + throwLexerError (LexicalError h _last) li Nothing -> throwLexerError (OutOfInputError _last) li AlexSkip input' _ -> do put input' @@ -133,7 +130,7 @@ scan = do put input' let span' = SpanInfo sLine sCol eLine eCol - t = T.decodeLatin1 (B.take (fromIntegral tokl) bs) + t = T.take (fromIntegral tokl) txt action t span' stringLiteral :: Text -> SpanInfo -> LexerM PosToken @@ -143,9 +140,9 @@ stringLiteral _ info = do pure (PosToken (TokenString (T.pack body)) info) where loop acc inp = - case alexGetByte inp of + case lexerGetChar inp of Just (c, rest) -> - handleChar acc (w2c c) rest + handleChar acc c rest Nothing -> throwLexerError' $ StringLiteralError "did not close string literal" handleChar acc c rest | c == '\\' = escape acc rest @@ -154,15 +151,15 @@ stringLiteral _ info = do | c == '\"' = reverse acc <$ put rest | otherwise = loop (c:acc) rest multiLine acc inp = - case alexGetByte inp of - Just (w2c -> c, rest) + case lexerGetChar inp of + Just (c, rest) | isSpace c -> multiLine acc rest | c == '\\' -> loop acc rest | otherwise -> throwLexerError' $ StringLiteralError "Invalid multiline string" Nothing -> throwLexerError' $ StringLiteralError "did not close string literal" escape acc inp = - case alexGetByte inp of - Just (w2c -> c, rest) + case lexerGetChar inp of + Just (c, rest) | isSpace c -> multiLine acc rest | c == 'n' -> loop ('\n':acc) rest | c == 't' -> loop ('\t':acc) rest @@ -183,9 +180,9 @@ scanTokens = scan' [] PosToken TokenEOF _ -> pure (reverse acc) tok -> scan' (tok:acc) -lexer :: ByteString -> Either PactErrorI [PosToken] +lexer :: Text -> Either PactErrorI [PosToken] lexer bs = runLexerT scanTokens bs -runLexerIO :: ByteString -> IO [PosToken] +runLexerIO :: Text -> IO [PosToken] runLexerIO bs = either throwIO pure (lexer bs) } diff --git a/pact-core/Pact/Core/Syntax/ParseTree.hs b/pact-core/Pact/Core/Syntax/ParseTree.hs index 172a9a465..60c36dd82 100644 --- a/pact-core/Pact/Core/Syntax/ParseTree.hs +++ b/pact-core/Pact/Core/Syntax/ParseTree.hs @@ -195,6 +195,15 @@ data DefProperty i , _dpropExp :: Expr i } deriving Show +newtype Property i + = Property (Expr i) + deriving Show + +data FVModel i + = FVDefProperty (DefProperty i) + | FVProperty (Property i) + deriving Show + data Module i = Module { _mName :: ModuleName @@ -202,7 +211,7 @@ data Module i , _mExternal :: [ExtDecl] , _mDefs :: NonEmpty (Def i) , _mDoc :: Maybe Text - , _mModel :: [DefProperty i] + , _mModel :: [FVModel i] , _mInfo :: i } deriving Show diff --git a/pact-core/Pact/Core/Syntax/Parser.y b/pact-core/Pact/Core/Syntax/Parser.y index dd68b51bc..9e3e8c444 100644 --- a/pact-core/Pact/Core/Syntax/Parser.y +++ b/pact-core/Pact/Core/Syntax/Parser.y @@ -61,6 +61,7 @@ import Pact.Core.Syntax.LexUtils deftable { PosToken TokenDefTable _ } defpact { PosToken TokenDefPact _ } defprop { PosToken TokenDefProperty _} + property { PosToken TokenProperty _ } bless { PosToken TokenBless _} implements { PosToken TokenImplements _ } true { PosToken TokenTrue _ } @@ -76,10 +77,6 @@ import Pact.Core.Syntax.LexUtils managedAnn { PosToken TokenManagedAnn _ } withcap { PosToken TokenWithCapability _ } c_usr_grd { PosToken TokenCreateUserGuard _} - -- reqcap { PosToken TokenRequireCapability _} - -- installcap { PosToken TokenInstallCapability _ } - -- composecap { PosToken TokenComposeCapability _ } - -- emitevent { PosToken TokenEmitEvent _ } step { PosToken TokenStep _ } steprb { PosToken TokenStepWithRollback _ } '{' { PosToken TokenOpenBrace _ } @@ -158,7 +155,7 @@ Interface :: { ParsedInterface } { Interface (ModuleName (getIdent $3) Nothing) (reverse (lefts $5)) (reverse (rights $5)) (fst $4) (snd $4) (combineSpan (_ptInfo $1) (_ptInfo $2)) } -MDocOrModuleModel :: { (Maybe Text, [DefProperty SpanInfo])} +MDocOrModuleModel :: { (Maybe Text, [FVModel SpanInfo])} : DocAnn ModuleModel { (Just $1, $2)} | ModuleModel DocAnn { (Just $2, $1) } | DocAnn { (Just $1, [])} @@ -167,15 +164,16 @@ MDocOrModuleModel :: { (Maybe Text, [DefProperty SpanInfo])} | {- empty -} { (Nothing, []) } -ModuleModel :: { [DefProperty SpanInfo] } +ModuleModel :: { [FVModel SpanInfo] } : modelAnn '[' DefProperties ']' { reverse $3 } -DefProperties :: { [DefProperty SpanInfo] } +DefProperties :: { [FVModel SpanInfo] } : DefProperties DefProperty { $2:$1 } | {- empty -} { [] } -DefProperty :: { DefProperty SpanInfo } - : '(' defprop IDENT DPropArgList ')' { DefProperty (getIdent $3) (fst $4) (snd $4) } +DefProperty :: { FVModel SpanInfo } + : '(' defprop IDENT DPropArgList ')' { FVDefProperty (DefProperty (getIdent $3) (fst $4) (snd $4)) } + | '(' property Expr ')' { FVProperty (Property $3) } -- This rule seems gnarly, but essentially -- happy needs to resolve whether the arglist is present or not @@ -584,3 +582,4 @@ mkBarename tx = BareName tx } + From deb2ad2ea318aef1fc600df6c102e405629e29e4 Mon Sep 17 00:00:00 2001 From: jmcardon Date: Fri, 8 Dec 2023 12:09:43 -0500 Subject: [PATCH 07/20] wip ZKspec and poseidonspec --- cbits/musl/__math_divzero.c | 6 + cbits/musl/__math_invalid.c | 6 + cbits/musl/__math_oflow.c | 6 + cbits/musl/__math_uflow.c | 6 + cbits/musl/__math_xflow.c | 6 + cbits/musl/endian.h | 80 + cbits/musl/exp.c | 134 + cbits/musl/exp_data.c | 182 + cbits/musl/exp_data.h | 26 + cbits/musl/libm.h | 265 ++ cbits/musl/log.c | 112 + cbits/musl/log_data.c | 328 ++ cbits/musl/log_data.h | 28 + cbits/musl/pow.c | 344 ++ cbits/musl/pow_data.c | 180 + cbits/musl/pow_data.h | 22 + cbits/musl/sqrt.c | 158 + cbits/musl/sqrt_data.c | 19 + cbits/musl/sqrt_data.h | 13 + crypto/Pact/Core/Crypto/Hash/Poseidon.hs | 3240 +++++++++++++++++ crypto/Pact/Core/Crypto/Pairing.hs | 743 ++++ crypto/Pact/Core/Crypto/Pairing/Fields.hs | 81 + pact-core-tests/Pact/Core/Test/ZkTests.hs | 325 ++ pact-core.cabal | 23 +- pact-core/Pact/Core/Builtin.hs | 14 + pact-core/Pact/Core/Environment/Types.hs | 4 +- pact-core/Pact/Core/IR/Desugar.hs | 2 + pact-core/Pact/Core/IR/Eval/RawBuiltin.hs | 229 +- pact-core/Pact/Core/PactValue.hs | 13 +- .../Pact/Core/Repl/Runtime/ReplBuiltin.hs | 2 +- 30 files changed, 6577 insertions(+), 20 deletions(-) create mode 100644 cbits/musl/__math_divzero.c create mode 100644 cbits/musl/__math_invalid.c create mode 100644 cbits/musl/__math_oflow.c create mode 100644 cbits/musl/__math_uflow.c create mode 100644 cbits/musl/__math_xflow.c create mode 100644 cbits/musl/endian.h create mode 100644 cbits/musl/exp.c create mode 100644 cbits/musl/exp_data.c create mode 100644 cbits/musl/exp_data.h create mode 100644 cbits/musl/libm.h create mode 100644 cbits/musl/log.c create mode 100644 cbits/musl/log_data.c create mode 100644 cbits/musl/log_data.h create mode 100644 cbits/musl/pow.c create mode 100644 cbits/musl/pow_data.c create mode 100644 cbits/musl/pow_data.h create mode 100644 cbits/musl/sqrt.c create mode 100644 cbits/musl/sqrt_data.c create mode 100644 cbits/musl/sqrt_data.h create mode 100644 crypto/Pact/Core/Crypto/Hash/Poseidon.hs create mode 100644 crypto/Pact/Core/Crypto/Pairing.hs create mode 100644 crypto/Pact/Core/Crypto/Pairing/Fields.hs create mode 100644 pact-core-tests/Pact/Core/Test/ZkTests.hs diff --git a/cbits/musl/__math_divzero.c b/cbits/musl/__math_divzero.c new file mode 100644 index 000000000..568ee07cc --- /dev/null +++ b/cbits/musl/__math_divzero.c @@ -0,0 +1,6 @@ +#include "libm.h" + +double __kadena_math_divzero(uint32_t sign) +{ + return fp_barrier(sign ? -1.0 : 1.0) / 0.0; +} diff --git a/cbits/musl/__math_invalid.c b/cbits/musl/__math_invalid.c new file mode 100644 index 000000000..ca1f3aff9 --- /dev/null +++ b/cbits/musl/__math_invalid.c @@ -0,0 +1,6 @@ +#include "libm.h" + +double __kadena_math_invalid(double x) +{ + return (x - x) / (x - x); +} diff --git a/cbits/musl/__math_oflow.c b/cbits/musl/__math_oflow.c new file mode 100644 index 000000000..cfc67dab3 --- /dev/null +++ b/cbits/musl/__math_oflow.c @@ -0,0 +1,6 @@ +#include "libm.h" + +double __kadena_math_oflow(uint32_t sign) +{ + return __kadena_math_xflow(sign, 0x1p769); +} diff --git a/cbits/musl/__math_uflow.c b/cbits/musl/__math_uflow.c new file mode 100644 index 000000000..cb2860343 --- /dev/null +++ b/cbits/musl/__math_uflow.c @@ -0,0 +1,6 @@ +#include "libm.h" + +double __kadena_math_uflow(uint32_t sign) +{ + return __kadena_math_xflow(sign, 0x1p-767); +} diff --git a/cbits/musl/__math_xflow.c b/cbits/musl/__math_xflow.c new file mode 100644 index 000000000..5defc0d21 --- /dev/null +++ b/cbits/musl/__math_xflow.c @@ -0,0 +1,6 @@ +#include "libm.h" + +double __kadena_math_xflow(uint32_t sign, double y) +{ + return eval_as_double(fp_barrier(sign ? -y : y) * y); +} diff --git a/cbits/musl/endian.h b/cbits/musl/endian.h new file mode 100644 index 000000000..eb788e6fd --- /dev/null +++ b/cbits/musl/endian.h @@ -0,0 +1,80 @@ +#ifndef _ENDIAN_H +#define _ENDIAN_H + +/*#include */ + +#define __NEED_uint16_t +#define __NEED_uint32_t +#define __NEED_uint64_t + +/*#include */ + +#define __PDP_ENDIAN 3412 + +#define BIG_ENDIAN __BIG_ENDIAN +#define LITTLE_ENDIAN __LITTLE_ENDIAN +#define PDP_ENDIAN __PDP_ENDIAN +#define BYTE_ORDER __BYTE_ORDER + +static __inline uint16_t __bswap16(uint16_t __x) +{ + return __x<<8 | __x>>8; +} + +static __inline uint32_t __bswap32(uint32_t __x) +{ + return __x>>24 | __x>>8&0xff00 | __x<<8&0xff0000 | __x<<24; +} + +static __inline uint64_t __bswap64(uint64_t __x) +{ + return __bswap32(__x)+0ULL<<32 | __bswap32(__x>>32); +} + +#if __BYTE_ORDER == __LITTLE_ENDIAN +#define htobe16(x) __bswap16(x) +#define be16toh(x) __bswap16(x) +#define htobe32(x) __bswap32(x) +#define be32toh(x) __bswap32(x) +#define htobe64(x) __bswap64(x) +#define be64toh(x) __bswap64(x) +#define htole16(x) (uint16_t)(x) +#define le16toh(x) (uint16_t)(x) +#define htole32(x) (uint32_t)(x) +#define le32toh(x) (uint32_t)(x) +#define htole64(x) (uint64_t)(x) +#define le64toh(x) (uint64_t)(x) +#else +#define htobe16(x) (uint16_t)(x) +#define be16toh(x) (uint16_t)(x) +#define htobe32(x) (uint32_t)(x) +#define be32toh(x) (uint32_t)(x) +#define htobe64(x) (uint64_t)(x) +#define be64toh(x) (uint64_t)(x) +#define htole16(x) __bswap16(x) +#define le16toh(x) __bswap16(x) +#define htole32(x) __bswap32(x) +#define le32toh(x) __bswap32(x) +#define htole64(x) __bswap64(x) +#define le64toh(x) __bswap64(x) +#endif + +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +#if __BYTE_ORDER == __LITTLE_ENDIAN +#define betoh16(x) __bswap16(x) +#define betoh32(x) __bswap32(x) +#define betoh64(x) __bswap64(x) +#define letoh16(x) (uint16_t)(x) +#define letoh32(x) (uint32_t)(x) +#define letoh64(x) (uint64_t)(x) +#else +#define betoh16(x) (uint16_t)(x) +#define betoh32(x) (uint32_t)(x) +#define betoh64(x) (uint64_t)(x) +#define letoh16(x) __bswap16(x) +#define letoh32(x) __bswap32(x) +#define letoh64(x) __bswap64(x) +#endif +#endif + +#endif diff --git a/cbits/musl/exp.c b/cbits/musl/exp.c new file mode 100644 index 000000000..8a5633148 --- /dev/null +++ b/cbits/musl/exp.c @@ -0,0 +1,134 @@ +/* + * Double-precision e^x function. + * + * Copyright (c) 2018, Arm Limited. + * SPDX-License-Identifier: MIT + */ + +#include +#include +#include "libm.h" +#include "exp_data.h" + +#define N (1 << EXP_TABLE_BITS) +#define InvLn2N __kadena_exp_data.invln2N +#define NegLn2hiN __kadena_exp_data.negln2hiN +#define NegLn2loN __kadena_exp_data.negln2loN +#define Shift __kadena_exp_data.shift +#define T __kadena_exp_data.tab +#define C2 __kadena_exp_data.poly[5 - EXP_POLY_ORDER] +#define C3 __kadena_exp_data.poly[6 - EXP_POLY_ORDER] +#define C4 __kadena_exp_data.poly[7 - EXP_POLY_ORDER] +#define C5 __kadena_exp_data.poly[8 - EXP_POLY_ORDER] + +/* Handle cases that may overflow or underflow when computing the result that + is scale*(1+TMP) without intermediate rounding. The bit representation of + scale is in SBITS, however it has a computed exponent that may have + overflown into the sign bit so that needs to be adjusted before using it as + a double. (int32_t)KI is the k used in the argument reduction and exponent + adjustment of scale, positive k here means the result may overflow and + negative k means the result may underflow. */ +static inline double specialcase(double_t tmp, uint64_t sbits, uint64_t ki) +{ + double_t scale, y; + + if ((ki & 0x80000000) == 0) { + /* k > 0, the exponent of scale might have overflowed by <= 460. */ + sbits -= 1009ull << 52; + scale = asdouble(sbits); + y = 0x1p1009 * (scale + scale * tmp); + return eval_as_double(y); + } + /* k < 0, need special care in the subnormal range. */ + sbits += 1022ull << 52; + scale = asdouble(sbits); + y = scale + scale * tmp; + if (y < 1.0) { + /* Round y to the right precision before scaling it into the subnormal + range to avoid double rounding that can cause 0.5+E/2 ulp error where + E is the worst-case ulp error outside the subnormal range. So this + is only useful if the goal is better than 1 ulp worst-case error. */ + double_t hi, lo; + lo = scale - y + scale * tmp; + hi = 1.0 + y; + lo = 1.0 - hi + y + lo; + y = eval_as_double(hi + lo) - 1.0; + /* Avoid -0.0 with downward rounding. */ + if (WANT_ROUNDING && y == 0.0) + y = 0.0; + /* The underflow exception needs to be signaled explicitly. */ + fp_force_eval(fp_barrier(0x1p-1022) * 0x1p-1022); + } + y = 0x1p-1022 * y; + return eval_as_double(y); +} + +/* Top 12 bits of a double (sign and exponent bits). */ +static inline uint32_t top12(double x) +{ + return asuint64(x) >> 52; +} + +double musl_exp(double x) +{ + uint32_t abstop; + uint64_t ki, idx, top, sbits; + double_t kd, z, r, r2, scale, tail, tmp; + + abstop = top12(x) & 0x7ff; + if (predict_false(abstop - top12(0x1p-54) >= top12(512.0) - top12(0x1p-54))) { + if (abstop - top12(0x1p-54) >= 0x80000000) + /* Avoid spurious underflow for tiny x. */ + /* Note: 0 is common input. */ + return WANT_ROUNDING ? 1.0 + x : 1.0; + if (abstop >= top12(1024.0)) { + if (asuint64(x) == asuint64(-INFINITY)) + return 0.0; + if (abstop >= top12(INFINITY)) + return 1.0 + x; + if (asuint64(x) >> 63) + return __kadena_math_uflow(0); + else + return __kadena_math_oflow(0); + } + /* Large x is special cased below. */ + abstop = 0; + } + + /* exp(x) = 2^(k/N) * exp(r), with exp(r) in [2^(-1/2N),2^(1/2N)]. */ + /* x = ln2/N*k + r, with int k and r in [-ln2/2N, ln2/2N]. */ + z = InvLn2N * x; +#if TOINT_INTRINSICS + kd = roundtoint(z); + ki = converttoint(z); +#elif EXP_USE_TOINT_NARROW + /* z - kd is in [-0.5-2^-16, 0.5] in all rounding modes. */ + kd = eval_as_double(z + Shift); + ki = asuint64(kd) >> 16; + kd = (double_t)(int32_t)ki; +#else + /* z - kd is in [-1, 1] in non-nearest rounding modes. */ + kd = eval_as_double(z + Shift); + ki = asuint64(kd); + kd -= Shift; +#endif + r = x + kd * NegLn2hiN + kd * NegLn2loN; + /* 2^(k/N) ~= scale * (1 + tail). */ + idx = 2 * (ki % N); + top = ki << (52 - EXP_TABLE_BITS); + tail = asdouble(T[idx]); + /* This is only a valid scale when -1023*N < k < 1024*N. */ + sbits = T[idx + 1] + top; + /* exp(x) = 2^(k/N) * exp(r) ~= scale + scale * (tail + exp(r) - 1). */ + /* Evaluation is optimized assuming superscalar pipelined execution. */ + r2 = r * r; + /* Without fma the worst case error is 0.25/N ulp larger. */ + /* Worst case error is less than 0.5+1.11/N+(abs poly error * 2^53) ulp. */ + tmp = tail + r + r2 * (C2 + r * C3) + r2 * r2 * (C4 + r * C5); + if (predict_false(abstop == 0)) + return specialcase(tmp, sbits, ki); + scale = asdouble(sbits); + /* Note: tmp == 0 or |tmp| > 2^-200 and scale > 2^-739, so there + is no spurious underflow here even without fma. */ + return eval_as_double(scale + scale * tmp); +} diff --git a/cbits/musl/exp_data.c b/cbits/musl/exp_data.c new file mode 100644 index 000000000..33cc0fab4 --- /dev/null +++ b/cbits/musl/exp_data.c @@ -0,0 +1,182 @@ +/* + * Shared data between exp, exp2 and pow. + * + * Copyright (c) 2018, Arm Limited. + * SPDX-License-Identifier: MIT + */ + +#include "exp_data.h" + +#define N (1 << EXP_TABLE_BITS) + +const struct exp_data __kadena_exp_data = { +// N/ln2 +.invln2N = 0x1.71547652b82fep0 * N, +// -ln2/N +.negln2hiN = -0x1.62e42fefa0000p-8, +.negln2loN = -0x1.cf79abc9e3b3ap-47, +// Used for rounding when !TOINT_INTRINSICS +#if EXP_USE_TOINT_NARROW +.shift = 0x1800000000.8p0, +#else +.shift = 0x1.8p52, +#endif +// exp polynomial coefficients. +.poly = { +// abs error: 1.555*2^-66 +// ulp error: 0.509 (0.511 without fma) +// if |x| < ln2/256+eps +// abs error if |x| < ln2/256+0x1p-15: 1.09*2^-65 +// abs error if |x| < ln2/128: 1.7145*2^-56 +0x1.ffffffffffdbdp-2, +0x1.555555555543cp-3, +0x1.55555cf172b91p-5, +0x1.1111167a4d017p-7, +}, +.exp2_shift = 0x1.8p52 / N, +// exp2 polynomial coefficients. +.exp2_poly = { +// abs error: 1.2195*2^-65 +// ulp error: 0.507 (0.511 without fma) +// if |x| < 1/256 +// abs error if |x| < 1/128: 1.9941*2^-56 +0x1.62e42fefa39efp-1, +0x1.ebfbdff82c424p-3, +0x1.c6b08d70cf4b5p-5, +0x1.3b2abd24650ccp-7, +0x1.5d7e09b4e3a84p-10, +}, +// 2^(k/N) ~= H[k]*(1 + T[k]) for int k in [0,N) +// tab[2*k] = asuint64(T[k]) +// tab[2*k+1] = asuint64(H[k]) - (k << 52)/N +.tab = { +0x0, 0x3ff0000000000000, +0x3c9b3b4f1a88bf6e, 0x3feff63da9fb3335, +0xbc7160139cd8dc5d, 0x3fefec9a3e778061, +0xbc905e7a108766d1, 0x3fefe315e86e7f85, +0x3c8cd2523567f613, 0x3fefd9b0d3158574, +0xbc8bce8023f98efa, 0x3fefd06b29ddf6de, +0x3c60f74e61e6c861, 0x3fefc74518759bc8, +0x3c90a3e45b33d399, 0x3fefbe3ecac6f383, +0x3c979aa65d837b6d, 0x3fefb5586cf9890f, +0x3c8eb51a92fdeffc, 0x3fefac922b7247f7, +0x3c3ebe3d702f9cd1, 0x3fefa3ec32d3d1a2, +0xbc6a033489906e0b, 0x3fef9b66affed31b, +0xbc9556522a2fbd0e, 0x3fef9301d0125b51, +0xbc5080ef8c4eea55, 0x3fef8abdc06c31cc, +0xbc91c923b9d5f416, 0x3fef829aaea92de0, +0x3c80d3e3e95c55af, 0x3fef7a98c8a58e51, +0xbc801b15eaa59348, 0x3fef72b83c7d517b, +0xbc8f1ff055de323d, 0x3fef6af9388c8dea, +0x3c8b898c3f1353bf, 0x3fef635beb6fcb75, +0xbc96d99c7611eb26, 0x3fef5be084045cd4, +0x3c9aecf73e3a2f60, 0x3fef54873168b9aa, +0xbc8fe782cb86389d, 0x3fef4d5022fcd91d, +0x3c8a6f4144a6c38d, 0x3fef463b88628cd6, +0x3c807a05b0e4047d, 0x3fef3f49917ddc96, +0x3c968efde3a8a894, 0x3fef387a6e756238, +0x3c875e18f274487d, 0x3fef31ce4fb2a63f, +0x3c80472b981fe7f2, 0x3fef2b4565e27cdd, +0xbc96b87b3f71085e, 0x3fef24dfe1f56381, +0x3c82f7e16d09ab31, 0x3fef1e9df51fdee1, +0xbc3d219b1a6fbffa, 0x3fef187fd0dad990, +0x3c8b3782720c0ab4, 0x3fef1285a6e4030b, +0x3c6e149289cecb8f, 0x3fef0cafa93e2f56, +0x3c834d754db0abb6, 0x3fef06fe0a31b715, +0x3c864201e2ac744c, 0x3fef0170fc4cd831, +0x3c8fdd395dd3f84a, 0x3feefc08b26416ff, +0xbc86a3803b8e5b04, 0x3feef6c55f929ff1, +0xbc924aedcc4b5068, 0x3feef1a7373aa9cb, +0xbc9907f81b512d8e, 0x3feeecae6d05d866, +0xbc71d1e83e9436d2, 0x3feee7db34e59ff7, +0xbc991919b3ce1b15, 0x3feee32dc313a8e5, +0x3c859f48a72a4c6d, 0x3feedea64c123422, +0xbc9312607a28698a, 0x3feeda4504ac801c, +0xbc58a78f4817895b, 0x3feed60a21f72e2a, +0xbc7c2c9b67499a1b, 0x3feed1f5d950a897, +0x3c4363ed60c2ac11, 0x3feece086061892d, +0x3c9666093b0664ef, 0x3feeca41ed1d0057, +0x3c6ecce1daa10379, 0x3feec6a2b5c13cd0, +0x3c93ff8e3f0f1230, 0x3feec32af0d7d3de, +0x3c7690cebb7aafb0, 0x3feebfdad5362a27, +0x3c931dbdeb54e077, 0x3feebcb299fddd0d, +0xbc8f94340071a38e, 0x3feeb9b2769d2ca7, +0xbc87deccdc93a349, 0x3feeb6daa2cf6642, +0xbc78dec6bd0f385f, 0x3feeb42b569d4f82, +0xbc861246ec7b5cf6, 0x3feeb1a4ca5d920f, +0x3c93350518fdd78e, 0x3feeaf4736b527da, +0x3c7b98b72f8a9b05, 0x3feead12d497c7fd, +0x3c9063e1e21c5409, 0x3feeab07dd485429, +0x3c34c7855019c6ea, 0x3feea9268a5946b7, +0x3c9432e62b64c035, 0x3feea76f15ad2148, +0xbc8ce44a6199769f, 0x3feea5e1b976dc09, +0xbc8c33c53bef4da8, 0x3feea47eb03a5585, +0xbc845378892be9ae, 0x3feea34634ccc320, +0xbc93cedd78565858, 0x3feea23882552225, +0x3c5710aa807e1964, 0x3feea155d44ca973, +0xbc93b3efbf5e2228, 0x3feea09e667f3bcd, +0xbc6a12ad8734b982, 0x3feea012750bdabf, +0xbc6367efb86da9ee, 0x3fee9fb23c651a2f, +0xbc80dc3d54e08851, 0x3fee9f7df9519484, +0xbc781f647e5a3ecf, 0x3fee9f75e8ec5f74, +0xbc86ee4ac08b7db0, 0x3fee9f9a48a58174, +0xbc8619321e55e68a, 0x3fee9feb564267c9, +0x3c909ccb5e09d4d3, 0x3feea0694fde5d3f, +0xbc7b32dcb94da51d, 0x3feea11473eb0187, +0x3c94ecfd5467c06b, 0x3feea1ed0130c132, +0x3c65ebe1abd66c55, 0x3feea2f336cf4e62, +0xbc88a1c52fb3cf42, 0x3feea427543e1a12, +0xbc9369b6f13b3734, 0x3feea589994cce13, +0xbc805e843a19ff1e, 0x3feea71a4623c7ad, +0xbc94d450d872576e, 0x3feea8d99b4492ed, +0x3c90ad675b0e8a00, 0x3feeaac7d98a6699, +0x3c8db72fc1f0eab4, 0x3feeace5422aa0db, +0xbc65b6609cc5e7ff, 0x3feeaf3216b5448c, +0x3c7bf68359f35f44, 0x3feeb1ae99157736, +0xbc93091fa71e3d83, 0x3feeb45b0b91ffc6, +0xbc5da9b88b6c1e29, 0x3feeb737b0cdc5e5, +0xbc6c23f97c90b959, 0x3feeba44cbc8520f, +0xbc92434322f4f9aa, 0x3feebd829fde4e50, +0xbc85ca6cd7668e4b, 0x3feec0f170ca07ba, +0x3c71affc2b91ce27, 0x3feec49182a3f090, +0x3c6dd235e10a73bb, 0x3feec86319e32323, +0xbc87c50422622263, 0x3feecc667b5de565, +0x3c8b1c86e3e231d5, 0x3feed09bec4a2d33, +0xbc91bbd1d3bcbb15, 0x3feed503b23e255d, +0x3c90cc319cee31d2, 0x3feed99e1330b358, +0x3c8469846e735ab3, 0x3feede6b5579fdbf, +0xbc82dfcd978e9db4, 0x3feee36bbfd3f37a, +0x3c8c1a7792cb3387, 0x3feee89f995ad3ad, +0xbc907b8f4ad1d9fa, 0x3feeee07298db666, +0xbc55c3d956dcaeba, 0x3feef3a2b84f15fb, +0xbc90a40e3da6f640, 0x3feef9728de5593a, +0xbc68d6f438ad9334, 0x3feeff76f2fb5e47, +0xbc91eee26b588a35, 0x3fef05b030a1064a, +0x3c74ffd70a5fddcd, 0x3fef0c1e904bc1d2, +0xbc91bdfbfa9298ac, 0x3fef12c25bd71e09, +0x3c736eae30af0cb3, 0x3fef199bdd85529c, +0x3c8ee3325c9ffd94, 0x3fef20ab5fffd07a, +0x3c84e08fd10959ac, 0x3fef27f12e57d14b, +0x3c63cdaf384e1a67, 0x3fef2f6d9406e7b5, +0x3c676b2c6c921968, 0x3fef3720dcef9069, +0xbc808a1883ccb5d2, 0x3fef3f0b555dc3fa, +0xbc8fad5d3ffffa6f, 0x3fef472d4a07897c, +0xbc900dae3875a949, 0x3fef4f87080d89f2, +0x3c74a385a63d07a7, 0x3fef5818dcfba487, +0xbc82919e2040220f, 0x3fef60e316c98398, +0x3c8e5a50d5c192ac, 0x3fef69e603db3285, +0x3c843a59ac016b4b, 0x3fef7321f301b460, +0xbc82d52107b43e1f, 0x3fef7c97337b9b5f, +0xbc892ab93b470dc9, 0x3fef864614f5a129, +0x3c74b604603a88d3, 0x3fef902ee78b3ff6, +0x3c83c5ec519d7271, 0x3fef9a51fbc74c83, +0xbc8ff7128fd391f0, 0x3fefa4afa2a490da, +0xbc8dae98e223747d, 0x3fefaf482d8e67f1, +0x3c8ec3bc41aa2008, 0x3fefba1bee615a27, +0x3c842b94c3a9eb32, 0x3fefc52b376bba97, +0x3c8a64a931d185ee, 0x3fefd0765b6e4540, +0xbc8e37bae43be3ed, 0x3fefdbfdad9cbe14, +0x3c77893b4d91cd9d, 0x3fefe7c1819e90d8, +0x3c5305c14160cc89, 0x3feff3c22b8f71f1, +}, +}; diff --git a/cbits/musl/exp_data.h b/cbits/musl/exp_data.h new file mode 100644 index 000000000..4edff5600 --- /dev/null +++ b/cbits/musl/exp_data.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2018, Arm Limited. + * SPDX-License-Identifier: MIT + */ +#ifndef _EXP_DATA_H +#define _EXP_DATA_H + +/*#include */ +#include + +#define EXP_TABLE_BITS 7 +#define EXP_POLY_ORDER 5 +#define EXP_USE_TOINT_NARROW 0 +#define EXP2_POLY_ORDER 5 +extern const struct exp_data { + double invln2N; + double shift; + double negln2hiN; + double negln2loN; + double poly[4]; /* Last four coefficients. */ + double exp2_shift; + double exp2_poly[EXP2_POLY_ORDER]; + uint64_t tab[2*(1 << EXP_TABLE_BITS)]; +} __kadena_exp_data; + +#endif diff --git a/cbits/musl/libm.h b/cbits/musl/libm.h new file mode 100644 index 000000000..11bc25689 --- /dev/null +++ b/cbits/musl/libm.h @@ -0,0 +1,265 @@ +#ifndef _LIBM_H +#define _LIBM_H + +#include +#include +#include +#include "endian.h" +/*#include "fp_arch.h"*/ + +#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 +#elif LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384 && __BYTE_ORDER == __LITTLE_ENDIAN +union ldshape { + long double f; + struct { + uint64_t m; + uint16_t se; + } i; +}; +#elif LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384 && __BYTE_ORDER == __BIG_ENDIAN +/* This is the m68k variant of 80-bit long double, and this definition only works + * on archs where the alignment requirement of uint64_t is <= 4. */ +union ldshape { + long double f; + struct { + uint16_t se; + uint16_t pad; + uint64_t m; + } i; +}; +#elif LDBL_MANT_DIG == 113 && LDBL_MAX_EXP == 16384 && __BYTE_ORDER == __LITTLE_ENDIAN +union ldshape { + long double f; + struct { + uint64_t lo; + uint32_t mid; + uint16_t top; + uint16_t se; + } i; + struct { + uint64_t lo; + uint64_t hi; + } i2; +}; +#elif LDBL_MANT_DIG == 113 && LDBL_MAX_EXP == 16384 && __BYTE_ORDER == __BIG_ENDIAN +union ldshape { + long double f; + struct { + uint16_t se; + uint16_t top; + uint32_t mid; + uint64_t lo; + } i; + struct { + uint64_t hi; + uint64_t lo; + } i2; +}; +#else +#error Unsupported long double representation +#endif + +/* Support non-nearest rounding mode. */ +#define WANT_ROUNDING 1 +/* Support signaling NaNs. */ +#define WANT_SNAN 0 + +#if WANT_SNAN +#error SNaN is unsupported +#else +#define issignalingf_inline(x) 0 +#define issignaling_inline(x) 0 +#endif + +#ifndef TOINT_INTRINSICS +#define TOINT_INTRINSICS 0 +#endif + +#if TOINT_INTRINSICS +/* Round x to nearest int in all rounding modes, ties have to be rounded + consistently with converttoint so the results match. If the result + would be outside of [-2^31, 2^31-1] then the semantics is unspecified. */ +static double_t roundtoint(double_t); + +/* Convert x to nearest int in all rounding modes, ties have to be rounded + consistently with roundtoint. If the result is not representible in an + int32_t then the semantics is unspecified. */ +static int32_t converttoint(double_t); +#endif + +/* Helps static branch prediction so hot path can be better optimized. */ +#ifdef __GNUC__ +#define predict_true(x) __builtin_expect(!!(x), 1) +#define predict_false(x) __builtin_expect(x, 0) +#else +#define predict_true(x) (x) +#define predict_false(x) (x) +#endif + +/* Evaluate an expression as the specified type. With standard excess + precision handling a type cast or assignment is enough (with + -ffloat-store an assignment is required, in old compilers argument + passing and return statement may not drop excess precision). */ + +static inline float eval_as_float(float x) +{ + float y = x; + return y; +} + +static inline double eval_as_double(double x) +{ + double y = x; + return y; +} + +/* fp_barrier returns its input, but limits code transformations + as if it had a side-effect (e.g. observable io) and returned + an arbitrary value. */ + +#ifndef fp_barrierf +#define fp_barrierf fp_barrierf +static inline float fp_barrierf(float x) +{ + volatile float y = x; + return y; +} +#endif + +#ifndef fp_barrier +#define fp_barrier fp_barrier +static inline double fp_barrier(double x) +{ + volatile double y = x; + return y; +} +#endif + +#ifndef fp_barrierl +#define fp_barrierl fp_barrierl +static inline long double fp_barrierl(long double x) +{ + volatile long double y = x; + return y; +} +#endif + +/* fp_force_eval ensures that the input value is computed when that's + otherwise unused. To prevent the constant folding of the input + expression, an additional fp_barrier may be needed or a compilation + mode that does so (e.g. -frounding-math in gcc). Then it can be + used to evaluate an expression for its fenv side-effects only. */ + +#ifndef fp_force_evalf +#define fp_force_evalf fp_force_evalf +static inline void fp_force_evalf(float x) +{ + volatile float y; + y = x; +} +#endif + +#ifndef fp_force_eval +#define fp_force_eval fp_force_eval +static inline void fp_force_eval(double x) +{ + volatile double y; + y = x; +} +#endif + +#ifndef fp_force_evall +#define fp_force_evall fp_force_evall +static inline void fp_force_evall(long double x) +{ + volatile long double y; + y = x; +} +#endif + +#define FORCE_EVAL(x) do { \ + if (sizeof(x) == sizeof(float)) { \ + fp_force_evalf(x); \ + } else if (sizeof(x) == sizeof(double)) { \ + fp_force_eval(x); \ + } else { \ + fp_force_evall(x); \ + } \ +} while(0) + +#define asuint(f) ((union{float _f; uint32_t _i;}){f})._i +#define asfloat(i) ((union{uint32_t _i; float _f;}){i})._f +#define asuint64(f) ((union{double _f; uint64_t _i;}){f})._i +#define asdouble(i) ((union{uint64_t _i; double _f;}){i})._f + +#define EXTRACT_WORDS(hi,lo,d) \ +do { \ + uint64_t __u = asuint64(d); \ + (hi) = __u >> 32; \ + (lo) = (uint32_t)__u; \ +} while (0) + +#define GET_HIGH_WORD(hi,d) \ +do { \ + (hi) = asuint64(d) >> 32; \ +} while (0) + +#define GET_LOW_WORD(lo,d) \ +do { \ + (lo) = (uint32_t)asuint64(d); \ +} while (0) + +#define INSERT_WORDS(d,hi,lo) \ +do { \ + (d) = asdouble(((uint64_t)(hi)<<32) | (uint32_t)(lo)); \ +} while (0) + +#define SET_HIGH_WORD(d,hi) \ + INSERT_WORDS(d, hi, (uint32_t)asuint64(d)) + +#define SET_LOW_WORD(d,lo) \ + INSERT_WORDS(d, asuint64(d)>>32, lo) + +#define GET_FLOAT_WORD(w,d) \ +do { \ + (w) = asuint(d); \ +} while (0) + +#define SET_FLOAT_WORD(d,w) \ +do { \ + (d) = asfloat(w); \ +} while (0) + +int __rem_pio2_large(double*,double*,int,int,int); + +int __rem_pio2(double,double*); +double __expo2(double,double); + +int __rem_pio2f(float,double*); +float __expo2f(float,float); + +int __rem_pio2l(long double, long double *); + +long double __polevll(long double, const long double *, int); +long double __p1evll(long double, const long double *, int); + +extern int __signgam; +double __lgamma_r(double, int *); +float __lgammaf_r(float, int *); + +/* error handling functions */ +float __math_xflowf(uint32_t, float); +float __math_uflowf(uint32_t); +float __math_oflowf(uint32_t); +float __math_divzerof(uint32_t); +float __math_invalidf(float); +double __kadena_math_xflow(uint32_t, double); +double __kadena_math_uflow(uint32_t); +double __kadena_math_oflow(uint32_t); +double __kadena_math_divzero(uint32_t); +double __kadena_math_invalid(double); +#if LDBL_MANT_DIG != DBL_MANT_DIG +long double __math_invalidl(long double); +#endif + +#endif diff --git a/cbits/musl/log.c b/cbits/musl/log.c new file mode 100644 index 000000000..443cfccea --- /dev/null +++ b/cbits/musl/log.c @@ -0,0 +1,112 @@ +/* + * Double-precision log(x) function. + * + * Copyright (c) 2018, Arm Limited. + * SPDX-License-Identifier: MIT + */ + +#include +#include +#include "libm.h" +#include "log_data.h" + +#define T __kadena_log_data.tab +#define T2 __kadena_log_data.tab2 +#define B __kadena_log_data.poly1 +#define A __kadena_log_data.poly +#define Ln2hi __kadena_log_data.ln2hi +#define Ln2lo __kadena_log_data.ln2lo +#define N (1 << LOG_TABLE_BITS) +#define OFF 0x3fe6000000000000 + +/* Top 16 bits of a double. */ +static inline uint32_t top16(double x) +{ + return asuint64(x) >> 48; +} + +double musl_log(double x) +{ + double_t w, z, r, r2, r3, y, invc, logc, kd, hi, lo; + uint64_t ix, iz, tmp; + uint32_t top; + int k, i; + + ix = asuint64(x); + top = top16(x); +#define LO asuint64(1.0 - 0x1p-4) +#define HI asuint64(1.0 + 0x1.09p-4) + if (predict_false(ix - LO < HI - LO)) { + /* Handle close to 1.0 inputs separately. */ + /* Fix sign of zero with downward rounding when x==1. */ + if (WANT_ROUNDING && predict_false(ix == asuint64(1.0))) + return 0; + r = x - 1.0; + r2 = r * r; + r3 = r * r2; + y = r3 * + (B[1] + r * B[2] + r2 * B[3] + + r3 * (B[4] + r * B[5] + r2 * B[6] + + r3 * (B[7] + r * B[8] + r2 * B[9] + r3 * B[10]))); + /* Worst-case error is around 0.507 ULP. */ + w = r * 0x1p27; + double_t rhi = r + w - w; + double_t rlo = r - rhi; + w = rhi * rhi * B[0]; /* B[0] == -0.5. */ + hi = r + w; + lo = r - hi + w; + lo += B[0] * rlo * (rhi + r); + y += lo; + y += hi; + return eval_as_double(y); + } + if (predict_false(top - 0x0010 >= 0x7ff0 - 0x0010)) { + /* x < 0x1p-1022 or inf or nan. */ + if (ix * 2 == 0) + return __kadena_math_divzero(1); + if (ix == asuint64(INFINITY)) /* log(inf) == inf. */ + return x; + if ((top & 0x8000) || (top & 0x7ff0) == 0x7ff0) + return __kadena_math_invalid(x); + /* x is subnormal, normalize it. */ + ix = asuint64(x * 0x1p52); + ix -= 52ULL << 52; + } + + /* x = 2^k z; where z is in range [OFF,2*OFF) and exact. + The range is split into N subintervals. + The ith subinterval contains z and c is near its center. */ + tmp = ix - OFF; + i = (tmp >> (52 - LOG_TABLE_BITS)) % N; + k = (int64_t)tmp >> 52; /* arithmetic shift */ + iz = ix - (tmp & 0xfffULL << 52); + invc = T[i].invc; + logc = T[i].logc; + z = asdouble(iz); + + /* log(x) = log1p(z/c-1) + log(c) + k*Ln2. */ + /* r ~= z/c - 1, |r| < 1/(2*N). */ +#if __FP_FAST_FMA + /* rounding error: 0x1p-55/N. */ + r = __builtin_fma(z, invc, -1.0); +#else + /* rounding error: 0x1p-55/N + 0x1p-66. */ + r = (z - T2[i].chi - T2[i].clo) * invc; +#endif + kd = (double_t)k; + + /* hi + lo = r + log(c) + k*Ln2. */ + w = kd * Ln2hi + logc; + hi = w + r; + lo = w - hi + r + kd * Ln2lo; + + /* log(x) = lo + (log1p(r) - r) + hi. */ + r2 = r * r; /* rounding error: 0x1p-54/N^2. */ + /* Worst case error if |y| > 0x1p-5: + 0.5 + 4.13/N + abs-poly-error*2^57 ULP (+ 0.002 ULP without fma) + Worst case error if |y| > 0x1p-4: + 0.5 + 2.06/N + abs-poly-error*2^56 ULP (+ 0.001 ULP without fma). */ + y = lo + r2 * A[0] + + r * r2 * (A[1] + r * A[2] + r2 * (A[3] + r * A[4])) + hi; + return eval_as_double(y); +} diff --git a/cbits/musl/log_data.c b/cbits/musl/log_data.c new file mode 100644 index 000000000..70322b4df --- /dev/null +++ b/cbits/musl/log_data.c @@ -0,0 +1,328 @@ +/* + * Data for log. + * + * Copyright (c) 2018, Arm Limited. + * SPDX-License-Identifier: MIT + */ + +#include "log_data.h" + +#define N (1 << LOG_TABLE_BITS) + +const struct log_data __kadena_log_data = { +.ln2hi = 0x1.62e42fefa3800p-1, +.ln2lo = 0x1.ef35793c76730p-45, +.poly1 = { +// relative error: 0x1.c04d76cp-63 +// in -0x1p-4 0x1.09p-4 (|log(1+x)| > 0x1p-4 outside the interval) +-0x1p-1, +0x1.5555555555577p-2, +-0x1.ffffffffffdcbp-3, +0x1.999999995dd0cp-3, +-0x1.55555556745a7p-3, +0x1.24924a344de3p-3, +-0x1.fffffa4423d65p-4, +0x1.c7184282ad6cap-4, +-0x1.999eb43b068ffp-4, +0x1.78182f7afd085p-4, +-0x1.5521375d145cdp-4, +}, +.poly = { +// relative error: 0x1.926199e8p-56 +// abs error: 0x1.882ff33p-65 +// in -0x1.fp-9 0x1.fp-9 +-0x1.0000000000001p-1, +0x1.555555551305bp-2, +-0x1.fffffffeb459p-3, +0x1.999b324f10111p-3, +-0x1.55575e506c89fp-3, +}, +/* Algorithm: + + x = 2^k z + log(x) = k ln2 + log(c) + log(z/c) + log(z/c) = poly(z/c - 1) + +where z is in [1.6p-1; 1.6p0] which is split into N subintervals and z falls +into the ith one, then table entries are computed as + + tab[i].invc = 1/c + tab[i].logc = (double)log(c) + tab2[i].chi = (double)c + tab2[i].clo = (double)(c - (double)c) + +where c is near the center of the subinterval and is chosen by trying +-2^29 +floating point invc candidates around 1/center and selecting one for which + + 1) the rounding error in 0x1.8p9 + logc is 0, + 2) the rounding error in z - chi - clo is < 0x1p-66 and + 3) the rounding error in (double)log(c) is minimized (< 0x1p-66). + +Note: 1) ensures that k*ln2hi + logc can be computed without rounding error, +2) ensures that z/c - 1 can be computed as (z - chi - clo)*invc with close to +a single rounding error when there is no fast fma for z*invc - 1, 3) ensures +that logc + poly(z/c - 1) has small error, however near x == 1 when +|log(x)| < 0x1p-4, this is not enough so that is special cased. */ +.tab = { +{0x1.734f0c3e0de9fp+0, -0x1.7cc7f79e69000p-2}, +{0x1.713786a2ce91fp+0, -0x1.76feec20d0000p-2}, +{0x1.6f26008fab5a0p+0, -0x1.713e31351e000p-2}, +{0x1.6d1a61f138c7dp+0, -0x1.6b85b38287800p-2}, +{0x1.6b1490bc5b4d1p+0, -0x1.65d5590807800p-2}, +{0x1.69147332f0cbap+0, -0x1.602d076180000p-2}, +{0x1.6719f18224223p+0, -0x1.5a8ca86909000p-2}, +{0x1.6524f99a51ed9p+0, -0x1.54f4356035000p-2}, +{0x1.63356aa8f24c4p+0, -0x1.4f637c36b4000p-2}, +{0x1.614b36b9ddc14p+0, -0x1.49da7fda85000p-2}, +{0x1.5f66452c65c4cp+0, -0x1.445923989a800p-2}, +{0x1.5d867b5912c4fp+0, -0x1.3edf439b0b800p-2}, +{0x1.5babccb5b90dep+0, -0x1.396ce448f7000p-2}, +{0x1.59d61f2d91a78p+0, -0x1.3401e17bda000p-2}, +{0x1.5805612465687p+0, -0x1.2e9e2ef468000p-2}, +{0x1.56397cee76bd3p+0, -0x1.2941b3830e000p-2}, +{0x1.54725e2a77f93p+0, -0x1.23ec58cda8800p-2}, +{0x1.52aff42064583p+0, -0x1.1e9e129279000p-2}, +{0x1.50f22dbb2bddfp+0, -0x1.1956d2b48f800p-2}, +{0x1.4f38f4734ded7p+0, -0x1.141679ab9f800p-2}, +{0x1.4d843cfde2840p+0, -0x1.0edd094ef9800p-2}, +{0x1.4bd3ec078a3c8p+0, -0x1.09aa518db1000p-2}, +{0x1.4a27fc3e0258ap+0, -0x1.047e65263b800p-2}, +{0x1.4880524d48434p+0, -0x1.feb224586f000p-3}, +{0x1.46dce1b192d0bp+0, -0x1.f474a7517b000p-3}, +{0x1.453d9d3391854p+0, -0x1.ea4443d103000p-3}, +{0x1.43a2744b4845ap+0, -0x1.e020d44e9b000p-3}, +{0x1.420b54115f8fbp+0, -0x1.d60a22977f000p-3}, +{0x1.40782da3ef4b1p+0, -0x1.cc00104959000p-3}, +{0x1.3ee8f5d57fe8fp+0, -0x1.c202956891000p-3}, +{0x1.3d5d9a00b4ce9p+0, -0x1.b81178d811000p-3}, +{0x1.3bd60c010c12bp+0, -0x1.ae2c9ccd3d000p-3}, +{0x1.3a5242b75dab8p+0, -0x1.a45402e129000p-3}, +{0x1.38d22cd9fd002p+0, -0x1.9a877681df000p-3}, +{0x1.3755bc5847a1cp+0, -0x1.90c6d69483000p-3}, +{0x1.35dce49ad36e2p+0, -0x1.87120a645c000p-3}, +{0x1.34679984dd440p+0, -0x1.7d68fb4143000p-3}, +{0x1.32f5cceffcb24p+0, -0x1.73cb83c627000p-3}, +{0x1.3187775a10d49p+0, -0x1.6a39a9b376000p-3}, +{0x1.301c8373e3990p+0, -0x1.60b3154b7a000p-3}, +{0x1.2eb4ebb95f841p+0, -0x1.5737d76243000p-3}, +{0x1.2d50a0219a9d1p+0, -0x1.4dc7b8fc23000p-3}, +{0x1.2bef9a8b7fd2ap+0, -0x1.4462c51d20000p-3}, +{0x1.2a91c7a0c1babp+0, -0x1.3b08abc830000p-3}, +{0x1.293726014b530p+0, -0x1.31b996b490000p-3}, +{0x1.27dfa5757a1f5p+0, -0x1.2875490a44000p-3}, +{0x1.268b39b1d3bbfp+0, -0x1.1f3b9f879a000p-3}, +{0x1.2539d838ff5bdp+0, -0x1.160c8252ca000p-3}, +{0x1.23eb7aac9083bp+0, -0x1.0ce7f57f72000p-3}, +{0x1.22a012ba940b6p+0, -0x1.03cdc49fea000p-3}, +{0x1.2157996cc4132p+0, -0x1.f57bdbc4b8000p-4}, +{0x1.201201dd2fc9bp+0, -0x1.e370896404000p-4}, +{0x1.1ecf4494d480bp+0, -0x1.d17983ef94000p-4}, +{0x1.1d8f5528f6569p+0, -0x1.bf9674ed8a000p-4}, +{0x1.1c52311577e7cp+0, -0x1.adc79202f6000p-4}, +{0x1.1b17c74cb26e9p+0, -0x1.9c0c3e7288000p-4}, +{0x1.19e010c2c1ab6p+0, -0x1.8a646b372c000p-4}, +{0x1.18ab07bb670bdp+0, -0x1.78d01b3ac0000p-4}, +{0x1.1778a25efbcb6p+0, -0x1.674f145380000p-4}, +{0x1.1648d354c31dap+0, -0x1.55e0e6d878000p-4}, +{0x1.151b990275fddp+0, -0x1.4485cdea1e000p-4}, +{0x1.13f0ea432d24cp+0, -0x1.333d94d6aa000p-4}, +{0x1.12c8b7210f9dap+0, -0x1.22079f8c56000p-4}, +{0x1.11a3028ecb531p+0, -0x1.10e4698622000p-4}, +{0x1.107fbda8434afp+0, -0x1.ffa6c6ad20000p-5}, +{0x1.0f5ee0f4e6bb3p+0, -0x1.dda8d4a774000p-5}, +{0x1.0e4065d2a9fcep+0, -0x1.bbcece4850000p-5}, +{0x1.0d244632ca521p+0, -0x1.9a1894012c000p-5}, +{0x1.0c0a77ce2981ap+0, -0x1.788583302c000p-5}, +{0x1.0af2f83c636d1p+0, -0x1.5715e67d68000p-5}, +{0x1.09ddb98a01339p+0, -0x1.35c8a49658000p-5}, +{0x1.08cabaf52e7dfp+0, -0x1.149e364154000p-5}, +{0x1.07b9f2f4e28fbp+0, -0x1.e72c082eb8000p-6}, +{0x1.06ab58c358f19p+0, -0x1.a55f152528000p-6}, +{0x1.059eea5ecf92cp+0, -0x1.63d62cf818000p-6}, +{0x1.04949cdd12c90p+0, -0x1.228fb8caa0000p-6}, +{0x1.038c6c6f0ada9p+0, -0x1.c317b20f90000p-7}, +{0x1.02865137932a9p+0, -0x1.419355daa0000p-7}, +{0x1.0182427ea7348p+0, -0x1.81203c2ec0000p-8}, +{0x1.008040614b195p+0, -0x1.0040979240000p-9}, +{0x1.fe01ff726fa1ap-1, 0x1.feff384900000p-9}, +{0x1.fa11cc261ea74p-1, 0x1.7dc41353d0000p-7}, +{0x1.f6310b081992ep-1, 0x1.3cea3c4c28000p-6}, +{0x1.f25f63ceeadcdp-1, 0x1.b9fc114890000p-6}, +{0x1.ee9c8039113e7p-1, 0x1.1b0d8ce110000p-5}, +{0x1.eae8078cbb1abp-1, 0x1.58a5bd001c000p-5}, +{0x1.e741aa29d0c9bp-1, 0x1.95c8340d88000p-5}, +{0x1.e3a91830a99b5p-1, 0x1.d276aef578000p-5}, +{0x1.e01e009609a56p-1, 0x1.07598e598c000p-4}, +{0x1.dca01e577bb98p-1, 0x1.253f5e30d2000p-4}, +{0x1.d92f20b7c9103p-1, 0x1.42edd8b380000p-4}, +{0x1.d5cac66fb5ccep-1, 0x1.606598757c000p-4}, +{0x1.d272caa5ede9dp-1, 0x1.7da76356a0000p-4}, +{0x1.cf26e3e6b2ccdp-1, 0x1.9ab434e1c6000p-4}, +{0x1.cbe6da2a77902p-1, 0x1.b78c7bb0d6000p-4}, +{0x1.c8b266d37086dp-1, 0x1.d431332e72000p-4}, +{0x1.c5894bd5d5804p-1, 0x1.f0a3171de6000p-4}, +{0x1.c26b533bb9f8cp-1, 0x1.067152b914000p-3}, +{0x1.bf583eeece73fp-1, 0x1.147858292b000p-3}, +{0x1.bc4fd75db96c1p-1, 0x1.2266ecdca3000p-3}, +{0x1.b951e0c864a28p-1, 0x1.303d7a6c55000p-3}, +{0x1.b65e2c5ef3e2cp-1, 0x1.3dfc33c331000p-3}, +{0x1.b374867c9888bp-1, 0x1.4ba366b7a8000p-3}, +{0x1.b094b211d304ap-1, 0x1.5933928d1f000p-3}, +{0x1.adbe885f2ef7ep-1, 0x1.66acd2418f000p-3}, +{0x1.aaf1d31603da2p-1, 0x1.740f8ec669000p-3}, +{0x1.a82e63fd358a7p-1, 0x1.815c0f51af000p-3}, +{0x1.a5740ef09738bp-1, 0x1.8e92954f68000p-3}, +{0x1.a2c2a90ab4b27p-1, 0x1.9bb3602f84000p-3}, +{0x1.a01a01393f2d1p-1, 0x1.a8bed1c2c0000p-3}, +{0x1.9d79f24db3c1bp-1, 0x1.b5b515c01d000p-3}, +{0x1.9ae2505c7b190p-1, 0x1.c2967ccbcc000p-3}, +{0x1.9852ef297ce2fp-1, 0x1.cf635d5486000p-3}, +{0x1.95cbaeea44b75p-1, 0x1.dc1bd3446c000p-3}, +{0x1.934c69de74838p-1, 0x1.e8c01b8cfe000p-3}, +{0x1.90d4f2f6752e6p-1, 0x1.f5509c0179000p-3}, +{0x1.8e6528effd79dp-1, 0x1.00e6c121fb800p-2}, +{0x1.8bfce9fcc007cp-1, 0x1.071b80e93d000p-2}, +{0x1.899c0dabec30ep-1, 0x1.0d46b9e867000p-2}, +{0x1.87427aa2317fbp-1, 0x1.13687334bd000p-2}, +{0x1.84f00acb39a08p-1, 0x1.1980d67234800p-2}, +{0x1.82a49e8653e55p-1, 0x1.1f8ffe0cc8000p-2}, +{0x1.8060195f40260p-1, 0x1.2595fd7636800p-2}, +{0x1.7e22563e0a329p-1, 0x1.2b9300914a800p-2}, +{0x1.7beb377dcb5adp-1, 0x1.3187210436000p-2}, +{0x1.79baa679725c2p-1, 0x1.377266dec1800p-2}, +{0x1.77907f2170657p-1, 0x1.3d54ffbaf3000p-2}, +{0x1.756cadbd6130cp-1, 0x1.432eee32fe000p-2}, +}, +#if !__FP_FAST_FMA +.tab2 = { +{0x1.61000014fb66bp-1, 0x1.e026c91425b3cp-56}, +{0x1.63000034db495p-1, 0x1.dbfea48005d41p-55}, +{0x1.650000d94d478p-1, 0x1.e7fa786d6a5b7p-55}, +{0x1.67000074e6fadp-1, 0x1.1fcea6b54254cp-57}, +{0x1.68ffffedf0faep-1, -0x1.c7e274c590efdp-56}, +{0x1.6b0000763c5bcp-1, -0x1.ac16848dcda01p-55}, +{0x1.6d0001e5cc1f6p-1, 0x1.33f1c9d499311p-55}, +{0x1.6efffeb05f63ep-1, -0x1.e80041ae22d53p-56}, +{0x1.710000e86978p-1, 0x1.bff6671097952p-56}, +{0x1.72ffffc67e912p-1, 0x1.c00e226bd8724p-55}, +{0x1.74fffdf81116ap-1, -0x1.e02916ef101d2p-57}, +{0x1.770000f679c9p-1, -0x1.7fc71cd549c74p-57}, +{0x1.78ffffa7ec835p-1, 0x1.1bec19ef50483p-55}, +{0x1.7affffe20c2e6p-1, -0x1.07e1729cc6465p-56}, +{0x1.7cfffed3fc9p-1, -0x1.08072087b8b1cp-55}, +{0x1.7efffe9261a76p-1, 0x1.dc0286d9df9aep-55}, +{0x1.81000049ca3e8p-1, 0x1.97fd251e54c33p-55}, +{0x1.8300017932c8fp-1, -0x1.afee9b630f381p-55}, +{0x1.850000633739cp-1, 0x1.9bfbf6b6535bcp-55}, +{0x1.87000204289c6p-1, -0x1.bbf65f3117b75p-55}, +{0x1.88fffebf57904p-1, -0x1.9006ea23dcb57p-55}, +{0x1.8b00022bc04dfp-1, -0x1.d00df38e04b0ap-56}, +{0x1.8cfffe50c1b8ap-1, -0x1.8007146ff9f05p-55}, +{0x1.8effffc918e43p-1, 0x1.3817bd07a7038p-55}, +{0x1.910001efa5fc7p-1, 0x1.93e9176dfb403p-55}, +{0x1.9300013467bb9p-1, 0x1.f804e4b980276p-56}, +{0x1.94fffe6ee076fp-1, -0x1.f7ef0d9ff622ep-55}, +{0x1.96fffde3c12d1p-1, -0x1.082aa962638bap-56}, +{0x1.98ffff4458a0dp-1, -0x1.7801b9164a8efp-55}, +{0x1.9afffdd982e3ep-1, -0x1.740e08a5a9337p-55}, +{0x1.9cfffed49fb66p-1, 0x1.fce08c19bep-60}, +{0x1.9f00020f19c51p-1, -0x1.a3faa27885b0ap-55}, +{0x1.a10001145b006p-1, 0x1.4ff489958da56p-56}, +{0x1.a300007bbf6fap-1, 0x1.cbeab8a2b6d18p-55}, +{0x1.a500010971d79p-1, 0x1.8fecadd78793p-55}, +{0x1.a70001df52e48p-1, -0x1.f41763dd8abdbp-55}, +{0x1.a90001c593352p-1, -0x1.ebf0284c27612p-55}, +{0x1.ab0002a4f3e4bp-1, -0x1.9fd043cff3f5fp-57}, +{0x1.acfffd7ae1ed1p-1, -0x1.23ee7129070b4p-55}, +{0x1.aefffee510478p-1, 0x1.a063ee00edea3p-57}, +{0x1.b0fffdb650d5bp-1, 0x1.a06c8381f0ab9p-58}, +{0x1.b2ffffeaaca57p-1, -0x1.9011e74233c1dp-56}, +{0x1.b4fffd995badcp-1, -0x1.9ff1068862a9fp-56}, +{0x1.b7000249e659cp-1, 0x1.aff45d0864f3ep-55}, +{0x1.b8ffff987164p-1, 0x1.cfe7796c2c3f9p-56}, +{0x1.bafffd204cb4fp-1, -0x1.3ff27eef22bc4p-57}, +{0x1.bcfffd2415c45p-1, -0x1.cffb7ee3bea21p-57}, +{0x1.beffff86309dfp-1, -0x1.14103972e0b5cp-55}, +{0x1.c0fffe1b57653p-1, 0x1.bc16494b76a19p-55}, +{0x1.c2ffff1fa57e3p-1, -0x1.4feef8d30c6edp-57}, +{0x1.c4fffdcbfe424p-1, -0x1.43f68bcec4775p-55}, +{0x1.c6fffed54b9f7p-1, 0x1.47ea3f053e0ecp-55}, +{0x1.c8fffeb998fd5p-1, 0x1.383068df992f1p-56}, +{0x1.cb0002125219ap-1, -0x1.8fd8e64180e04p-57}, +{0x1.ccfffdd94469cp-1, 0x1.e7ebe1cc7ea72p-55}, +{0x1.cefffeafdc476p-1, 0x1.ebe39ad9f88fep-55}, +{0x1.d1000169af82bp-1, 0x1.57d91a8b95a71p-56}, +{0x1.d30000d0ff71dp-1, 0x1.9c1906970c7dap-55}, +{0x1.d4fffea790fc4p-1, -0x1.80e37c558fe0cp-58}, +{0x1.d70002edc87e5p-1, -0x1.f80d64dc10f44p-56}, +{0x1.d900021dc82aap-1, -0x1.47c8f94fd5c5cp-56}, +{0x1.dafffd86b0283p-1, 0x1.c7f1dc521617ep-55}, +{0x1.dd000296c4739p-1, 0x1.8019eb2ffb153p-55}, +{0x1.defffe54490f5p-1, 0x1.e00d2c652cc89p-57}, +{0x1.e0fffcdabf694p-1, -0x1.f8340202d69d2p-56}, +{0x1.e2fffdb52c8ddp-1, 0x1.b00c1ca1b0864p-56}, +{0x1.e4ffff24216efp-1, 0x1.2ffa8b094ab51p-56}, +{0x1.e6fffe88a5e11p-1, -0x1.7f673b1efbe59p-58}, +{0x1.e9000119eff0dp-1, -0x1.4808d5e0bc801p-55}, +{0x1.eafffdfa51744p-1, 0x1.80006d54320b5p-56}, +{0x1.ed0001a127fa1p-1, -0x1.002f860565c92p-58}, +{0x1.ef00007babcc4p-1, -0x1.540445d35e611p-55}, +{0x1.f0ffff57a8d02p-1, -0x1.ffb3139ef9105p-59}, +{0x1.f30001ee58ac7p-1, 0x1.a81acf2731155p-55}, +{0x1.f4ffff5823494p-1, 0x1.a3f41d4d7c743p-55}, +{0x1.f6ffffca94c6bp-1, -0x1.202f41c987875p-57}, +{0x1.f8fffe1f9c441p-1, 0x1.77dd1f477e74bp-56}, +{0x1.fafffd2e0e37ep-1, -0x1.f01199a7ca331p-57}, +{0x1.fd0001c77e49ep-1, 0x1.181ee4bceacb1p-56}, +{0x1.feffff7e0c331p-1, -0x1.e05370170875ap-57}, +{0x1.00ffff465606ep+0, -0x1.a7ead491c0adap-55}, +{0x1.02ffff3867a58p+0, -0x1.77f69c3fcb2ep-54}, +{0x1.04ffffdfc0d17p+0, 0x1.7bffe34cb945bp-54}, +{0x1.0700003cd4d82p+0, 0x1.20083c0e456cbp-55}, +{0x1.08ffff9f2cbe8p+0, -0x1.dffdfbe37751ap-57}, +{0x1.0b000010cda65p+0, -0x1.13f7faee626ebp-54}, +{0x1.0d00001a4d338p+0, 0x1.07dfa79489ff7p-55}, +{0x1.0effffadafdfdp+0, -0x1.7040570d66bcp-56}, +{0x1.110000bbafd96p+0, 0x1.e80d4846d0b62p-55}, +{0x1.12ffffae5f45dp+0, 0x1.dbffa64fd36efp-54}, +{0x1.150000dd59ad9p+0, 0x1.a0077701250aep-54}, +{0x1.170000f21559ap+0, 0x1.dfdf9e2e3deeep-55}, +{0x1.18ffffc275426p+0, 0x1.10030dc3b7273p-54}, +{0x1.1b000123d3c59p+0, 0x1.97f7980030188p-54}, +{0x1.1cffff8299eb7p+0, -0x1.5f932ab9f8c67p-57}, +{0x1.1effff48ad4p+0, 0x1.37fbf9da75bebp-54}, +{0x1.210000c8b86a4p+0, 0x1.f806b91fd5b22p-54}, +{0x1.2300003854303p+0, 0x1.3ffc2eb9fbf33p-54}, +{0x1.24fffffbcf684p+0, 0x1.601e77e2e2e72p-56}, +{0x1.26ffff52921d9p+0, 0x1.ffcbb767f0c61p-56}, +{0x1.2900014933a3cp+0, -0x1.202ca3c02412bp-56}, +{0x1.2b00014556313p+0, -0x1.2808233f21f02p-54}, +{0x1.2cfffebfe523bp+0, -0x1.8ff7e384fdcf2p-55}, +{0x1.2f0000bb8ad96p+0, -0x1.5ff51503041c5p-55}, +{0x1.30ffffb7ae2afp+0, -0x1.10071885e289dp-55}, +{0x1.32ffffeac5f7fp+0, -0x1.1ff5d3fb7b715p-54}, +{0x1.350000ca66756p+0, 0x1.57f82228b82bdp-54}, +{0x1.3700011fbf721p+0, 0x1.000bac40dd5ccp-55}, +{0x1.38ffff9592fb9p+0, -0x1.43f9d2db2a751p-54}, +{0x1.3b00004ddd242p+0, 0x1.57f6b707638e1p-55}, +{0x1.3cffff5b2c957p+0, 0x1.a023a10bf1231p-56}, +{0x1.3efffeab0b418p+0, 0x1.87f6d66b152bp-54}, +{0x1.410001532aff4p+0, 0x1.7f8375f198524p-57}, +{0x1.4300017478b29p+0, 0x1.301e672dc5143p-55}, +{0x1.44fffe795b463p+0, 0x1.9ff69b8b2895ap-55}, +{0x1.46fffe80475ep+0, -0x1.5c0b19bc2f254p-54}, +{0x1.48fffef6fc1e7p+0, 0x1.b4009f23a2a72p-54}, +{0x1.4afffe5bea704p+0, -0x1.4ffb7bf0d7d45p-54}, +{0x1.4d000171027dep+0, -0x1.9c06471dc6a3dp-54}, +{0x1.4f0000ff03ee2p+0, 0x1.77f890b85531cp-54}, +{0x1.5100012dc4bd1p+0, 0x1.004657166a436p-57}, +{0x1.530001605277ap+0, -0x1.6bfcece233209p-54}, +{0x1.54fffecdb704cp+0, -0x1.902720505a1d7p-55}, +{0x1.56fffef5f54a9p+0, 0x1.bbfe60ec96412p-54}, +{0x1.5900017e61012p+0, 0x1.87ec581afef9p-55}, +{0x1.5b00003c93e92p+0, -0x1.f41080abf0ccp-54}, +{0x1.5d0001d4919bcp+0, -0x1.8812afb254729p-54}, +{0x1.5efffe7b87a89p+0, -0x1.47eb780ed6904p-54}, +}, +#endif +}; diff --git a/cbits/musl/log_data.h b/cbits/musl/log_data.h new file mode 100644 index 000000000..8d26fcff3 --- /dev/null +++ b/cbits/musl/log_data.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2018, Arm Limited. + * SPDX-License-Identifier: MIT + */ +#ifndef _LOG_DATA_H +#define _LOG_DATA_H + +/* #include */ + +#define LOG_TABLE_BITS 7 +#define LOG_POLY_ORDER 6 +#define LOG_POLY1_ORDER 12 +extern const struct log_data { + double ln2hi; + double ln2lo; + double poly[LOG_POLY_ORDER - 1]; /* First coefficient is 1. */ + double poly1[LOG_POLY1_ORDER - 1]; + struct { + double invc, logc; + } tab[1 << LOG_TABLE_BITS]; +#if !__FP_FAST_FMA + struct { + double chi, clo; + } tab2[1 << LOG_TABLE_BITS]; +#endif +} __kadena_log_data; + +#endif diff --git a/cbits/musl/pow.c b/cbits/musl/pow.c new file mode 100644 index 000000000..9c730f7b7 --- /dev/null +++ b/cbits/musl/pow.c @@ -0,0 +1,344 @@ +/* + * Double-precision x^y function. + * + * Copyright (c) 2018, Arm Limited. + * SPDX-License-Identifier: MIT + */ + +#include +#include +#include "libm.h" +#include "exp_data.h" +#include "pow_data.h" + +#define WANT_ROUNDING 1 +/* +Worst-case error: 0.54 ULP (~= ulperr_exp + 1024*Ln2*relerr_log*2^53) +relerr_log: 1.3 * 2^-68 (Relative error of log, 1.5 * 2^-68 without fma) +ulperr_exp: 0.509 ULP (ULP error of exp, 0.511 ULP without fma) +*/ + +#define T __kadena_pow_log_data.tab +#define A __kadena_pow_log_data.poly +#define Ln2hi __kadena_pow_log_data.ln2hi +#define Ln2lo __kadena_pow_log_data.ln2lo +#define N (1 << POW_LOG_TABLE_BITS) +#define OFF 0x3fe6955500000000 + +/* Top 12 bits of a double (sign and exponent bits). */ +static inline uint32_t top12(double x) +{ + return asuint64(x) >> 52; +} + +/* Compute y+TAIL = log(x) where the rounded result is y and TAIL has about + additional 15 bits precision. IX is the bit representation of x, but + normalized in the subnormal range using the sign bit for the exponent. */ +static inline double_t log_inline(uint64_t ix, double_t *tail) +{ + /* double_t for better performance on targets with FLT_EVAL_METHOD==2. */ + double_t z, r, y, invc, logc, logctail, kd, hi, t1, t2, lo, lo1, lo2, p; + uint64_t iz, tmp; + int k, i; + + /* x = 2^k z; where z is in range [OFF,2*OFF) and exact. + The range is split into N subintervals. + The ith subinterval contains z and c is near its center. */ + tmp = ix - OFF; + i = (tmp >> (52 - POW_LOG_TABLE_BITS)) % N; + k = (int64_t)tmp >> 52; /* arithmetic shift */ + iz = ix - (tmp & 0xfffULL << 52); + z = asdouble(iz); + kd = (double_t)k; + + /* log(x) = k*Ln2 + log(c) + log1p(z/c-1). */ + invc = T[i].invc; + logc = T[i].logc; + logctail = T[i].logctail; + + /* Note: 1/c is j/N or j/N/2 where j is an integer in [N,2N) and + |z/c - 1| < 1/N, so r = z/c - 1 is exactly representible. */ +#if __FP_FAST_FMA + r = __builtin_fma(z, invc, -1.0); +#else + /* Split z such that rhi, rlo and rhi*rhi are exact and |rlo| <= |r|. */ + double_t zhi = asdouble((iz + (1ULL << 31)) & (-1ULL << 32)); + double_t zlo = z - zhi; + double_t rhi = zhi * invc - 1.0; + double_t rlo = zlo * invc; + r = rhi + rlo; +#endif + + /* k*Ln2 + log(c) + r. */ + t1 = kd * Ln2hi + logc; + t2 = t1 + r; + lo1 = kd * Ln2lo + logctail; + lo2 = t1 - t2 + r; + + /* Evaluation is optimized assuming superscalar pipelined execution. */ + double_t ar, ar2, ar3, lo3, lo4; + ar = A[0] * r; /* A[0] = -0.5. */ + ar2 = r * ar; + ar3 = r * ar2; + /* k*Ln2 + log(c) + r + A[0]*r*r. */ +#if __FP_FAST_FMA + hi = t2 + ar2; + lo3 = __builtin_fma(ar, r, -ar2); + lo4 = t2 - hi + ar2; +#else + double_t arhi = A[0] * rhi; + double_t arhi2 = rhi * arhi; + hi = t2 + arhi2; + lo3 = rlo * (ar + arhi); + lo4 = t2 - hi + arhi2; +#endif + /* p = log1p(r) - r - A[0]*r*r. */ + p = (ar3 * (A[1] + r * A[2] + + ar2 * (A[3] + r * A[4] + ar2 * (A[5] + r * A[6])))); + lo = lo1 + lo2 + lo3 + lo4 + p; + y = hi + lo; + *tail = hi - y + lo; + return y; +} + +#undef N +#undef T +#define N (1 << EXP_TABLE_BITS) +#define InvLn2N __kadena_exp_data.invln2N +#define NegLn2hiN __kadena_exp_data.negln2hiN +#define NegLn2loN __kadena_exp_data.negln2loN +#define Shift __kadena_exp_data.shift +#define T __kadena_exp_data.tab +#define C2 __kadena_exp_data.poly[5 - EXP_POLY_ORDER] +#define C3 __kadena_exp_data.poly[6 - EXP_POLY_ORDER] +#define C4 __kadena_exp_data.poly[7 - EXP_POLY_ORDER] +#define C5 __kadena_exp_data.poly[8 - EXP_POLY_ORDER] +#define C6 __kadena_exp_data.poly[9 - EXP_POLY_ORDER] + +/* Handle cases that may overflow or underflow when computing the result that + is scale*(1+TMP) without intermediate rounding. The bit representation of + scale is in SBITS, however it has a computed exponent that may have + overflown into the sign bit so that needs to be adjusted before using it as + a double. (int32_t)KI is the k used in the argument reduction and exponent + adjustment of scale, positive k here means the result may overflow and + negative k means the result may underflow. */ +static inline double specialcase(double_t tmp, uint64_t sbits, uint64_t ki) +{ + double_t scale, y; + + if ((ki & 0x80000000) == 0) { + /* k > 0, the exponent of scale might have overflowed by <= 460. */ + sbits -= 1009ull << 52; + scale = asdouble(sbits); + y = 0x1p1009 * (scale + scale * tmp); + return eval_as_double(y); + } + /* k < 0, need special care in the subnormal range. */ + sbits += 1022ull << 52; + /* Note: sbits is signed scale. */ + scale = asdouble(sbits); + y = scale + scale * tmp; + if (fabs(y) < 1.0) { + /* Round y to the right precision before scaling it into the subnormal + range to avoid double rounding that can cause 0.5+E/2 ulp error where + E is the worst-case ulp error outside the subnormal range. So this + is only useful if the goal is better than 1 ulp worst-case error. */ + double_t hi, lo, one = 1.0; + if (y < 0.0) + one = -1.0; + lo = scale - y + scale * tmp; + hi = one + y; + lo = one - hi + y + lo; + y = eval_as_double(hi + lo) - one; + /* Fix the sign of 0. */ + if (y == 0.0) + y = asdouble(sbits & 0x8000000000000000); + /* The underflow exception needs to be signaled explicitly. */ + fp_force_eval(fp_barrier(0x1p-1022) * 0x1p-1022); + } + y = 0x1p-1022 * y; + return eval_as_double(y); +} + +#define SIGN_BIAS (0x800 << EXP_TABLE_BITS) + +/* Computes sign*exp(x+xtail) where |xtail| < 2^-8/N and |xtail| <= |x|. + The sign_bias argument is SIGN_BIAS or 0 and sets the sign to -1 or 1. */ +static inline double exp_inline(double_t x, double_t xtail, uint32_t sign_bias) +{ + uint32_t abstop; + uint64_t ki, idx, top, sbits; + /* double_t for better performance on targets with FLT_EVAL_METHOD==2. */ + double_t kd, z, r, r2, scale, tail, tmp; + + abstop = top12(x) & 0x7ff; + if (predict_false(abstop - top12(0x1p-54) >= + top12(512.0) - top12(0x1p-54))) { + if (abstop - top12(0x1p-54) >= 0x80000000) { + /* Avoid spurious underflow for tiny x. */ + /* Note: 0 is common input. */ + double_t one = WANT_ROUNDING ? 1.0 + x : 1.0; + return sign_bias ? -one : one; + } + if (abstop >= top12(1024.0)) { + /* Note: inf and nan are already handled. */ + if (asuint64(x) >> 63) + return __kadena_math_uflow(sign_bias); + else + return __kadena_math_oflow(sign_bias); + } + /* Large x is special cased below. */ + abstop = 0; + } + + /* exp(x) = 2^(k/N) * exp(r), with exp(r) in [2^(-1/2N),2^(1/2N)]. */ + /* x = ln2/N*k + r, with int k and r in [-ln2/2N, ln2/2N]. */ + z = InvLn2N * x; +#if TOINT_INTRINSICS + kd = roundtoint(z); + ki = converttoint(z); +#elif EXP_USE_TOINT_NARROW + /* z - kd is in [-0.5-2^-16, 0.5] in all rounding modes. */ + kd = eval_as_double(z + Shift); + ki = asuint64(kd) >> 16; + kd = (double_t)(int32_t)ki; +#else + /* z - kd is in [-1, 1] in non-nearest rounding modes. */ + kd = eval_as_double(z + Shift); + ki = asuint64(kd); + kd -= Shift; +#endif + r = x + kd * NegLn2hiN + kd * NegLn2loN; + /* The code assumes 2^-200 < |xtail| < 2^-8/N. */ + r += xtail; + /* 2^(k/N) ~= scale * (1 + tail). */ + idx = 2 * (ki % N); + top = (ki + sign_bias) << (52 - EXP_TABLE_BITS); + tail = asdouble(T[idx]); + /* This is only a valid scale when -1023*N < k < 1024*N. */ + sbits = T[idx + 1] + top; + /* exp(x) = 2^(k/N) * exp(r) ~= scale + scale * (tail + exp(r) - 1). */ + /* Evaluation is optimized assuming superscalar pipelined execution. */ + r2 = r * r; + /* Without fma the worst case error is 0.25/N ulp larger. */ + /* Worst case error is less than 0.5+1.11/N+(abs poly error * 2^53) ulp. */ + tmp = tail + r + r2 * (C2 + r * C3) + r2 * r2 * (C4 + r * C5); + if (predict_false(abstop == 0)) + return specialcase(tmp, sbits, ki); + scale = asdouble(sbits); + /* Note: tmp == 0 or |tmp| > 2^-200 and scale > 2^-739, so there + is no spurious underflow here even without fma. */ + return eval_as_double(scale + scale * tmp); +} + +/* Returns 0 if not int, 1 if odd int, 2 if even int. The argument is + the bit representation of a non-zero finite floating-point value. */ +static inline int checkint(uint64_t iy) +{ + int e = iy >> 52 & 0x7ff; + if (e < 0x3ff) + return 0; + if (e > 0x3ff + 52) + return 2; + if (iy & ((1ULL << (0x3ff + 52 - e)) - 1)) + return 0; + if (iy & (1ULL << (0x3ff + 52 - e))) + return 1; + return 2; +} + +/* Returns 1 if input is the bit representation of 0, infinity or nan. */ +static inline int zeroinfnan(uint64_t i) +{ + return 2 * i - 1 >= 2 * asuint64(INFINITY) - 1; +} + +double musl_pow(double x, double y) +{ + uint32_t sign_bias = 0; + uint64_t ix, iy; + uint32_t topx, topy; + + ix = asuint64(x); + iy = asuint64(y); + topx = top12(x); + topy = top12(y); + if (predict_false(topx - 0x001 >= 0x7ff - 0x001 || + (topy & 0x7ff) - 0x3be >= 0x43e - 0x3be)) { + /* Note: if |y| > 1075 * ln2 * 2^53 ~= 0x1.749p62 then pow(x,y) = inf/0 + and if |y| < 2^-54 / 1075 ~= 0x1.e7b6p-65 then pow(x,y) = +-1. */ + /* Special cases: (x < 0x1p-126 or inf or nan) or + (|y| < 0x1p-65 or |y| >= 0x1p63 or nan). */ + if (predict_false(zeroinfnan(iy))) { + if (2 * iy == 0) + return issignaling_inline(x) ? x + y : 1.0; + if (ix == asuint64(1.0)) + return issignaling_inline(y) ? x + y : 1.0; + if (2 * ix > 2 * asuint64(INFINITY) || + 2 * iy > 2 * asuint64(INFINITY)) + return x + y; + if (2 * ix == 2 * asuint64(1.0)) + return 1.0; + if ((2 * ix < 2 * asuint64(1.0)) == !(iy >> 63)) + return 0.0; /* |x|<1 && y==inf or |x|>1 && y==-inf. */ + return y * y; + } + if (predict_false(zeroinfnan(ix))) { + double_t x2 = x * x; + if (ix >> 63 && checkint(iy) == 1) + x2 = -x2; + /* Without the barrier some versions of clang hoist the 1/x2 and + thus division by zero exception can be signaled spuriously. */ + return iy >> 63 ? fp_barrier(1 / x2) : x2; + } + /* Here x and y are non-zero finite. */ + if (ix >> 63) { + /* Finite x < 0. */ + int yint = checkint(iy); + if (yint == 0) + return __kadena_math_invalid(x); + if (yint == 1) + sign_bias = SIGN_BIAS; + ix &= 0x7fffffffffffffff; + topx &= 0x7ff; + } + if ((topy & 0x7ff) - 0x3be >= 0x43e - 0x3be) { + /* Note: sign_bias == 0 here because y is not odd. */ + if (ix == asuint64(1.0)) + return 1.0; + if ((topy & 0x7ff) < 0x3be) { + /* |y| < 2^-65, x^y ~= 1 + y*log(x). */ + if (WANT_ROUNDING) + return ix > asuint64(1.0) ? 1.0 + y : + 1.0 - y; + else + return 1.0; + } + return (ix > asuint64(1.0)) == (topy < 0x800) ? + __kadena_math_oflow(0) : + __kadena_math_uflow(0); + } + if (topx == 0) { + /* Normalize subnormal x so exponent becomes negative. */ + ix = asuint64(x * 0x1p52); + ix &= 0x7fffffffffffffff; + ix -= 52ULL << 52; + } + } + + double_t lo; + double_t hi = log_inline(ix, &lo); + double_t ehi, elo; +#if __FP_FAST_FMA + ehi = y * hi; + elo = y * lo + __builtin_fma(y, hi, -ehi); +#else + double_t yhi = asdouble(iy & -1ULL << 27); + double_t ylo = y - yhi; + double_t lhi = asdouble(asuint64(hi) & -1ULL << 27); + double_t llo = hi - lhi + lo; + ehi = yhi * lhi; + elo = ylo * lhi + y * llo; /* |elo| < |ehi| * 2^-25. */ +#endif + return exp_inline(ehi, elo, sign_bias); +} diff --git a/cbits/musl/pow_data.c b/cbits/musl/pow_data.c new file mode 100644 index 000000000..c0517648b --- /dev/null +++ b/cbits/musl/pow_data.c @@ -0,0 +1,180 @@ +/* + * Data for the log part of pow. + * + * Copyright (c) 2018, Arm Limited. + * SPDX-License-Identifier: MIT + */ + +#include "pow_data.h" + +#define N (1 << POW_LOG_TABLE_BITS) + +const struct pow_log_data __kadena_pow_log_data = { +.ln2hi = 0x1.62e42fefa3800p-1, +.ln2lo = 0x1.ef35793c76730p-45, +.poly = { +// relative error: 0x1.11922ap-70 +// in -0x1.6bp-8 0x1.6bp-8 +// Coefficients are scaled to match the scaling during evaluation. +-0x1p-1, +0x1.555555555556p-2 * -2, +-0x1.0000000000006p-2 * -2, +0x1.999999959554ep-3 * 4, +-0x1.555555529a47ap-3 * 4, +0x1.2495b9b4845e9p-3 * -8, +-0x1.0002b8b263fc3p-3 * -8, +}, +/* Algorithm: + + x = 2^k z + log(x) = k ln2 + log(c) + log(z/c) + log(z/c) = poly(z/c - 1) + +where z is in [0x1.69555p-1; 0x1.69555p0] which is split into N subintervals +and z falls into the ith one, then table entries are computed as + + tab[i].invc = 1/c + tab[i].logc = round(0x1p43*log(c))/0x1p43 + tab[i].logctail = (double)(log(c) - logc) + +where c is chosen near the center of the subinterval such that 1/c has only a +few precision bits so z/c - 1 is exactly representible as double: + + 1/c = center < 1 ? round(N/center)/N : round(2*N/center)/N/2 + +Note: |z/c - 1| < 1/N for the chosen c, |log(c) - logc - logctail| < 0x1p-97, +the last few bits of logc are rounded away so k*ln2hi + logc has no rounding +error and the interval for z is selected such that near x == 1, where log(x) +is tiny, large cancellation error is avoided in logc + poly(z/c - 1). */ +.tab = { +#define A(a, b, c) {a, 0, b, c}, +A(0x1.6a00000000000p+0, -0x1.62c82f2b9c800p-2, 0x1.ab42428375680p-48) +A(0x1.6800000000000p+0, -0x1.5d1bdbf580800p-2, -0x1.ca508d8e0f720p-46) +A(0x1.6600000000000p+0, -0x1.5767717455800p-2, -0x1.362a4d5b6506dp-45) +A(0x1.6400000000000p+0, -0x1.51aad872df800p-2, -0x1.684e49eb067d5p-49) +A(0x1.6200000000000p+0, -0x1.4be5f95777800p-2, -0x1.41b6993293ee0p-47) +A(0x1.6000000000000p+0, -0x1.4618bc21c6000p-2, 0x1.3d82f484c84ccp-46) +A(0x1.5e00000000000p+0, -0x1.404308686a800p-2, 0x1.c42f3ed820b3ap-50) +A(0x1.5c00000000000p+0, -0x1.3a64c55694800p-2, 0x1.0b1c686519460p-45) +A(0x1.5a00000000000p+0, -0x1.347dd9a988000p-2, 0x1.5594dd4c58092p-45) +A(0x1.5800000000000p+0, -0x1.2e8e2bae12000p-2, 0x1.67b1e99b72bd8p-45) +A(0x1.5600000000000p+0, -0x1.2895a13de8800p-2, 0x1.5ca14b6cfb03fp-46) +A(0x1.5600000000000p+0, -0x1.2895a13de8800p-2, 0x1.5ca14b6cfb03fp-46) +A(0x1.5400000000000p+0, -0x1.22941fbcf7800p-2, -0x1.65a242853da76p-46) +A(0x1.5200000000000p+0, -0x1.1c898c1699800p-2, -0x1.fafbc68e75404p-46) +A(0x1.5000000000000p+0, -0x1.1675cababa800p-2, 0x1.f1fc63382a8f0p-46) +A(0x1.4e00000000000p+0, -0x1.1058bf9ae4800p-2, -0x1.6a8c4fd055a66p-45) +A(0x1.4c00000000000p+0, -0x1.0a324e2739000p-2, -0x1.c6bee7ef4030ep-47) +A(0x1.4a00000000000p+0, -0x1.0402594b4d000p-2, -0x1.036b89ef42d7fp-48) +A(0x1.4a00000000000p+0, -0x1.0402594b4d000p-2, -0x1.036b89ef42d7fp-48) +A(0x1.4800000000000p+0, -0x1.fb9186d5e4000p-3, 0x1.d572aab993c87p-47) +A(0x1.4600000000000p+0, -0x1.ef0adcbdc6000p-3, 0x1.b26b79c86af24p-45) +A(0x1.4400000000000p+0, -0x1.e27076e2af000p-3, -0x1.72f4f543fff10p-46) +A(0x1.4200000000000p+0, -0x1.d5c216b4fc000p-3, 0x1.1ba91bbca681bp-45) +A(0x1.4000000000000p+0, -0x1.c8ff7c79aa000p-3, 0x1.7794f689f8434p-45) +A(0x1.4000000000000p+0, -0x1.c8ff7c79aa000p-3, 0x1.7794f689f8434p-45) +A(0x1.3e00000000000p+0, -0x1.bc286742d9000p-3, 0x1.94eb0318bb78fp-46) +A(0x1.3c00000000000p+0, -0x1.af3c94e80c000p-3, 0x1.a4e633fcd9066p-52) +A(0x1.3a00000000000p+0, -0x1.a23bc1fe2b000p-3, -0x1.58c64dc46c1eap-45) +A(0x1.3a00000000000p+0, -0x1.a23bc1fe2b000p-3, -0x1.58c64dc46c1eap-45) +A(0x1.3800000000000p+0, -0x1.9525a9cf45000p-3, -0x1.ad1d904c1d4e3p-45) +A(0x1.3600000000000p+0, -0x1.87fa06520d000p-3, 0x1.bbdbf7fdbfa09p-45) +A(0x1.3400000000000p+0, -0x1.7ab890210e000p-3, 0x1.bdb9072534a58p-45) +A(0x1.3400000000000p+0, -0x1.7ab890210e000p-3, 0x1.bdb9072534a58p-45) +A(0x1.3200000000000p+0, -0x1.6d60fe719d000p-3, -0x1.0e46aa3b2e266p-46) +A(0x1.3000000000000p+0, -0x1.5ff3070a79000p-3, -0x1.e9e439f105039p-46) +A(0x1.3000000000000p+0, -0x1.5ff3070a79000p-3, -0x1.e9e439f105039p-46) +A(0x1.2e00000000000p+0, -0x1.526e5e3a1b000p-3, -0x1.0de8b90075b8fp-45) +A(0x1.2c00000000000p+0, -0x1.44d2b6ccb8000p-3, 0x1.70cc16135783cp-46) +A(0x1.2c00000000000p+0, -0x1.44d2b6ccb8000p-3, 0x1.70cc16135783cp-46) +A(0x1.2a00000000000p+0, -0x1.371fc201e9000p-3, 0x1.178864d27543ap-48) +A(0x1.2800000000000p+0, -0x1.29552f81ff000p-3, -0x1.48d301771c408p-45) +A(0x1.2600000000000p+0, -0x1.1b72ad52f6000p-3, -0x1.e80a41811a396p-45) +A(0x1.2600000000000p+0, -0x1.1b72ad52f6000p-3, -0x1.e80a41811a396p-45) +A(0x1.2400000000000p+0, -0x1.0d77e7cd09000p-3, 0x1.a699688e85bf4p-47) +A(0x1.2400000000000p+0, -0x1.0d77e7cd09000p-3, 0x1.a699688e85bf4p-47) +A(0x1.2200000000000p+0, -0x1.fec9131dbe000p-4, -0x1.575545ca333f2p-45) +A(0x1.2000000000000p+0, -0x1.e27076e2b0000p-4, 0x1.a342c2af0003cp-45) +A(0x1.2000000000000p+0, -0x1.e27076e2b0000p-4, 0x1.a342c2af0003cp-45) +A(0x1.1e00000000000p+0, -0x1.c5e548f5bc000p-4, -0x1.d0c57585fbe06p-46) +A(0x1.1c00000000000p+0, -0x1.a926d3a4ae000p-4, 0x1.53935e85baac8p-45) +A(0x1.1c00000000000p+0, -0x1.a926d3a4ae000p-4, 0x1.53935e85baac8p-45) +A(0x1.1a00000000000p+0, -0x1.8c345d631a000p-4, 0x1.37c294d2f5668p-46) +A(0x1.1a00000000000p+0, -0x1.8c345d631a000p-4, 0x1.37c294d2f5668p-46) +A(0x1.1800000000000p+0, -0x1.6f0d28ae56000p-4, -0x1.69737c93373dap-45) +A(0x1.1600000000000p+0, -0x1.51b073f062000p-4, 0x1.f025b61c65e57p-46) +A(0x1.1600000000000p+0, -0x1.51b073f062000p-4, 0x1.f025b61c65e57p-46) +A(0x1.1400000000000p+0, -0x1.341d7961be000p-4, 0x1.c5edaccf913dfp-45) +A(0x1.1400000000000p+0, -0x1.341d7961be000p-4, 0x1.c5edaccf913dfp-45) +A(0x1.1200000000000p+0, -0x1.16536eea38000p-4, 0x1.47c5e768fa309p-46) +A(0x1.1000000000000p+0, -0x1.f0a30c0118000p-5, 0x1.d599e83368e91p-45) +A(0x1.1000000000000p+0, -0x1.f0a30c0118000p-5, 0x1.d599e83368e91p-45) +A(0x1.0e00000000000p+0, -0x1.b42dd71198000p-5, 0x1.c827ae5d6704cp-46) +A(0x1.0e00000000000p+0, -0x1.b42dd71198000p-5, 0x1.c827ae5d6704cp-46) +A(0x1.0c00000000000p+0, -0x1.77458f632c000p-5, -0x1.cfc4634f2a1eep-45) +A(0x1.0c00000000000p+0, -0x1.77458f632c000p-5, -0x1.cfc4634f2a1eep-45) +A(0x1.0a00000000000p+0, -0x1.39e87b9fec000p-5, 0x1.502b7f526feaap-48) +A(0x1.0a00000000000p+0, -0x1.39e87b9fec000p-5, 0x1.502b7f526feaap-48) +A(0x1.0800000000000p+0, -0x1.f829b0e780000p-6, -0x1.980267c7e09e4p-45) +A(0x1.0800000000000p+0, -0x1.f829b0e780000p-6, -0x1.980267c7e09e4p-45) +A(0x1.0600000000000p+0, -0x1.7b91b07d58000p-6, -0x1.88d5493faa639p-45) +A(0x1.0400000000000p+0, -0x1.fc0a8b0fc0000p-7, -0x1.f1e7cf6d3a69cp-50) +A(0x1.0400000000000p+0, -0x1.fc0a8b0fc0000p-7, -0x1.f1e7cf6d3a69cp-50) +A(0x1.0200000000000p+0, -0x1.fe02a6b100000p-8, -0x1.9e23f0dda40e4p-46) +A(0x1.0200000000000p+0, -0x1.fe02a6b100000p-8, -0x1.9e23f0dda40e4p-46) +A(0x1.0000000000000p+0, 0x0.0000000000000p+0, 0x0.0000000000000p+0) +A(0x1.0000000000000p+0, 0x0.0000000000000p+0, 0x0.0000000000000p+0) +A(0x1.fc00000000000p-1, 0x1.0101575890000p-7, -0x1.0c76b999d2be8p-46) +A(0x1.f800000000000p-1, 0x1.0205658938000p-6, -0x1.3dc5b06e2f7d2p-45) +A(0x1.f400000000000p-1, 0x1.8492528c90000p-6, -0x1.aa0ba325a0c34p-45) +A(0x1.f000000000000p-1, 0x1.0415d89e74000p-5, 0x1.111c05cf1d753p-47) +A(0x1.ec00000000000p-1, 0x1.466aed42e0000p-5, -0x1.c167375bdfd28p-45) +A(0x1.e800000000000p-1, 0x1.894aa149fc000p-5, -0x1.97995d05a267dp-46) +A(0x1.e400000000000p-1, 0x1.ccb73cdddc000p-5, -0x1.a68f247d82807p-46) +A(0x1.e200000000000p-1, 0x1.eea31c006c000p-5, -0x1.e113e4fc93b7bp-47) +A(0x1.de00000000000p-1, 0x1.1973bd1466000p-4, -0x1.5325d560d9e9bp-45) +A(0x1.da00000000000p-1, 0x1.3bdf5a7d1e000p-4, 0x1.cc85ea5db4ed7p-45) +A(0x1.d600000000000p-1, 0x1.5e95a4d97a000p-4, -0x1.c69063c5d1d1ep-45) +A(0x1.d400000000000p-1, 0x1.700d30aeac000p-4, 0x1.c1e8da99ded32p-49) +A(0x1.d000000000000p-1, 0x1.9335e5d594000p-4, 0x1.3115c3abd47dap-45) +A(0x1.cc00000000000p-1, 0x1.b6ac88dad6000p-4, -0x1.390802bf768e5p-46) +A(0x1.ca00000000000p-1, 0x1.c885801bc4000p-4, 0x1.646d1c65aacd3p-45) +A(0x1.c600000000000p-1, 0x1.ec739830a2000p-4, -0x1.dc068afe645e0p-45) +A(0x1.c400000000000p-1, 0x1.fe89139dbe000p-4, -0x1.534d64fa10afdp-45) +A(0x1.c000000000000p-1, 0x1.1178e8227e000p-3, 0x1.1ef78ce2d07f2p-45) +A(0x1.be00000000000p-1, 0x1.1aa2b7e23f000p-3, 0x1.ca78e44389934p-45) +A(0x1.ba00000000000p-1, 0x1.2d1610c868000p-3, 0x1.39d6ccb81b4a1p-47) +A(0x1.b800000000000p-1, 0x1.365fcb0159000p-3, 0x1.62fa8234b7289p-51) +A(0x1.b400000000000p-1, 0x1.4913d8333b000p-3, 0x1.5837954fdb678p-45) +A(0x1.b200000000000p-1, 0x1.527e5e4a1b000p-3, 0x1.633e8e5697dc7p-45) +A(0x1.ae00000000000p-1, 0x1.6574ebe8c1000p-3, 0x1.9cf8b2c3c2e78p-46) +A(0x1.ac00000000000p-1, 0x1.6f0128b757000p-3, -0x1.5118de59c21e1p-45) +A(0x1.aa00000000000p-1, 0x1.7898d85445000p-3, -0x1.c661070914305p-46) +A(0x1.a600000000000p-1, 0x1.8beafeb390000p-3, -0x1.73d54aae92cd1p-47) +A(0x1.a400000000000p-1, 0x1.95a5adcf70000p-3, 0x1.7f22858a0ff6fp-47) +A(0x1.a000000000000p-1, 0x1.a93ed3c8ae000p-3, -0x1.8724350562169p-45) +A(0x1.9e00000000000p-1, 0x1.b31d8575bd000p-3, -0x1.c358d4eace1aap-47) +A(0x1.9c00000000000p-1, 0x1.bd087383be000p-3, -0x1.d4bc4595412b6p-45) +A(0x1.9a00000000000p-1, 0x1.c6ffbc6f01000p-3, -0x1.1ec72c5962bd2p-48) +A(0x1.9600000000000p-1, 0x1.db13db0d49000p-3, -0x1.aff2af715b035p-45) +A(0x1.9400000000000p-1, 0x1.e530effe71000p-3, 0x1.212276041f430p-51) +A(0x1.9200000000000p-1, 0x1.ef5ade4dd0000p-3, -0x1.a211565bb8e11p-51) +A(0x1.9000000000000p-1, 0x1.f991c6cb3b000p-3, 0x1.bcbecca0cdf30p-46) +A(0x1.8c00000000000p-1, 0x1.07138604d5800p-2, 0x1.89cdb16ed4e91p-48) +A(0x1.8a00000000000p-1, 0x1.0c42d67616000p-2, 0x1.7188b163ceae9p-45) +A(0x1.8800000000000p-1, 0x1.1178e8227e800p-2, -0x1.c210e63a5f01cp-45) +A(0x1.8600000000000p-1, 0x1.16b5ccbacf800p-2, 0x1.b9acdf7a51681p-45) +A(0x1.8400000000000p-1, 0x1.1bf99635a6800p-2, 0x1.ca6ed5147bdb7p-45) +A(0x1.8200000000000p-1, 0x1.214456d0eb800p-2, 0x1.a87deba46baeap-47) +A(0x1.7e00000000000p-1, 0x1.2bef07cdc9000p-2, 0x1.a9cfa4a5004f4p-45) +A(0x1.7c00000000000p-1, 0x1.314f1e1d36000p-2, -0x1.8e27ad3213cb8p-45) +A(0x1.7a00000000000p-1, 0x1.36b6776be1000p-2, 0x1.16ecdb0f177c8p-46) +A(0x1.7800000000000p-1, 0x1.3c25277333000p-2, 0x1.83b54b606bd5cp-46) +A(0x1.7600000000000p-1, 0x1.419b423d5e800p-2, 0x1.8e436ec90e09dp-47) +A(0x1.7400000000000p-1, 0x1.4718dc271c800p-2, -0x1.f27ce0967d675p-45) +A(0x1.7200000000000p-1, 0x1.4c9e09e173000p-2, -0x1.e20891b0ad8a4p-45) +A(0x1.7000000000000p-1, 0x1.522ae0738a000p-2, 0x1.ebe708164c759p-45) +A(0x1.6e00000000000p-1, 0x1.57bf753c8d000p-2, 0x1.fadedee5d40efp-46) +A(0x1.6c00000000000p-1, 0x1.5d5bddf596000p-2, -0x1.a0b2a08a465dcp-47) +}, +}; diff --git a/cbits/musl/pow_data.h b/cbits/musl/pow_data.h new file mode 100644 index 000000000..c94ad6891 --- /dev/null +++ b/cbits/musl/pow_data.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2018, Arm Limited. + * SPDX-License-Identifier: MIT + */ +#ifndef _POW_DATA_H +#define _POW_DATA_H + +/*#include */ + +#define POW_LOG_TABLE_BITS 7 +#define POW_LOG_POLY_ORDER 8 +extern const struct pow_log_data { + double ln2hi; + double ln2lo; + double poly[POW_LOG_POLY_ORDER - 1]; /* First coefficient is 1. */ + /* Note: the pad field is unused, but allows slightly faster indexing. */ + struct { + double invc, pad, logc, logctail; + } tab[1 << POW_LOG_TABLE_BITS]; +} __kadena_pow_log_data; + +#endif diff --git a/cbits/musl/sqrt.c b/cbits/musl/sqrt.c new file mode 100644 index 000000000..dbd7797ac --- /dev/null +++ b/cbits/musl/sqrt.c @@ -0,0 +1,158 @@ +#include +#include +#include "libm.h" +#include "sqrt_data.h" + +#define FENV_SUPPORT 1 + +/* returns a*b*2^-32 - e, with error 0 <= e < 1. */ +static inline uint32_t mul32(uint32_t a, uint32_t b) +{ + return (uint64_t)a*b >> 32; +} + +/* returns a*b*2^-64 - e, with error 0 <= e < 3. */ +static inline uint64_t mul64(uint64_t a, uint64_t b) +{ + uint64_t ahi = a>>32; + uint64_t alo = a&0xffffffff; + uint64_t bhi = b>>32; + uint64_t blo = b&0xffffffff; + return ahi*bhi + (ahi*blo >> 32) + (alo*bhi >> 32); +} + +double musl_sqrt(double x) +{ + uint64_t ix, top, m; + + /* special case handling. */ + ix = asuint64(x); + top = ix >> 52; + if (predict_false(top - 0x001 >= 0x7ff - 0x001)) { + /* x < 0x1p-1022 or inf or nan. */ + if (ix * 2 == 0) + return x; + if (ix == 0x7ff0000000000000) + return x; + if (ix > 0x7ff0000000000000) + return __kadena_math_invalid(x); + /* x is subnormal, normalize it. */ + ix = asuint64(x * 0x1p52); + top = ix >> 52; + top -= 52; + } + + /* argument reduction: + x = 4^e m; with integer e, and m in [1, 4) + m: fixed point representation [2.62] + 2^e is the exponent part of the result. */ + int even = top & 1; + m = (ix << 11) | 0x8000000000000000; + if (even) m >>= 1; + top = (top + 0x3ff) >> 1; + + /* approximate r ~ 1/sqrt(m) and s ~ sqrt(m) when m in [1,4) + + initial estimate: + 7bit table lookup (1bit exponent and 6bit significand). + + iterative approximation: + using 2 goldschmidt iterations with 32bit int arithmetics + and a final iteration with 64bit int arithmetics. + + details: + + the relative error (e = r0 sqrt(m)-1) of a linear estimate + (r0 = a m + b) is |e| < 0.085955 ~ 0x1.6p-4 at best, + a table lookup is faster and needs one less iteration + 6 bit lookup table (128b) gives |e| < 0x1.f9p-8 + 7 bit lookup table (256b) gives |e| < 0x1.fdp-9 + for single and double prec 6bit is enough but for quad + prec 7bit is needed (or modified iterations). to avoid + one more iteration >=13bit table would be needed (16k). + + a newton-raphson iteration for r is + w = r*r + u = 3 - m*w + r = r*u/2 + can use a goldschmidt iteration for s at the end or + s = m*r + + first goldschmidt iteration is + s = m*r + u = 3 - s*r + r = r*u/2 + s = s*u/2 + next goldschmidt iteration is + u = 3 - s*r + r = r*u/2 + s = s*u/2 + and at the end r is not computed only s. + + they use the same amount of operations and converge at the + same quadratic rate, i.e. if + r1 sqrt(m) - 1 = e, then + r2 sqrt(m) - 1 = -3/2 e^2 - 1/2 e^3 + the advantage of goldschmidt is that the mul for s and r + are independent (computed in parallel), however it is not + "self synchronizing": it only uses the input m in the + first iteration so rounding errors accumulate. at the end + or when switching to larger precision arithmetics rounding + errors dominate so the first iteration should be used. + + the fixed point representations are + m: 2.30 r: 0.32, s: 2.30, d: 2.30, u: 2.30, three: 2.30 + and after switching to 64 bit + m: 2.62 r: 0.64, s: 2.62, d: 2.62, u: 2.62, three: 2.62 */ + + static const uint64_t three = 0xc0000000; + uint64_t r, s, d, u, i; + + i = (ix >> 46) % 128; + r = (uint32_t)__kadena_rsqrt_tab[i] << 16; + /* |r sqrt(m) - 1| < 0x1.fdp-9 */ + s = mul32(m>>32, r); + /* |s/sqrt(m) - 1| < 0x1.fdp-9 */ + d = mul32(s, r); + u = three - d; + r = mul32(r, u) << 1; + /* |r sqrt(m) - 1| < 0x1.7bp-16 */ + s = mul32(s, u) << 1; + /* |s/sqrt(m) - 1| < 0x1.7bp-16 */ + d = mul32(s, r); + u = three - d; + r = mul32(r, u) << 1; + /* |r sqrt(m) - 1| < 0x1.3704p-29 (measured worst-case) */ + r = r << 32; + s = mul64(m, r); + d = mul64(s, r); + u = (three<<32) - d; + s = mul64(s, u); /* repr: 3.61 */ + /* -0x1p-57 < s - sqrt(m) < 0x1.8001p-61 */ + s = (s - 2) >> 9; /* repr: 12.52 */ + /* -0x1.09p-52 < s - sqrt(m) < -0x1.fffcp-63 */ + + /* s < sqrt(m) < s + 0x1.09p-52, + compute nearest rounded result: + the nearest result to 52 bits is either s or s+0x1p-52, + we can decide by comparing (2^52 s + 0.5)^2 to 2^104 m. */ + uint64_t d0, d1, d2; + double y, t; + d0 = (m << 42) - s*s; + d1 = s - d0; + d2 = d1 + s + 1; + s += d1 >> 63; + s &= 0x000fffffffffffff; + s |= top << 52; + y = asdouble(s); + if (FENV_SUPPORT) { + /* handle rounding modes and inexact exception: + only (s+1)^2 == 2^42 m case is exact otherwise + add a tiny value to cause the fenv effects. */ + uint64_t tiny = predict_false(d2==0) ? 0 : 0x0010000000000000; + tiny |= (d1^d2) & 0x8000000000000000; + t = asdouble(tiny); + y = eval_as_double(y + t); + } + return y; +} diff --git a/cbits/musl/sqrt_data.c b/cbits/musl/sqrt_data.c new file mode 100644 index 000000000..8c22f1972 --- /dev/null +++ b/cbits/musl/sqrt_data.c @@ -0,0 +1,19 @@ +#include "sqrt_data.h" +const uint16_t __kadena_rsqrt_tab[128] = { +0xb451,0xb2f0,0xb196,0xb044,0xaef9,0xadb6,0xac79,0xab43, +0xaa14,0xa8eb,0xa7c8,0xa6aa,0xa592,0xa480,0xa373,0xa26b, +0xa168,0xa06a,0x9f70,0x9e7b,0x9d8a,0x9c9d,0x9bb5,0x9ad1, +0x99f0,0x9913,0x983a,0x9765,0x9693,0x95c4,0x94f8,0x9430, +0x936b,0x92a9,0x91ea,0x912e,0x9075,0x8fbe,0x8f0a,0x8e59, +0x8daa,0x8cfe,0x8c54,0x8bac,0x8b07,0x8a64,0x89c4,0x8925, +0x8889,0x87ee,0x8756,0x86c0,0x862b,0x8599,0x8508,0x8479, +0x83ec,0x8361,0x82d8,0x8250,0x81c9,0x8145,0x80c2,0x8040, +0xff02,0xfd0e,0xfb25,0xf947,0xf773,0xf5aa,0xf3ea,0xf234, +0xf087,0xeee3,0xed47,0xebb3,0xea27,0xe8a3,0xe727,0xe5b2, +0xe443,0xe2dc,0xe17a,0xe020,0xdecb,0xdd7d,0xdc34,0xdaf1, +0xd9b3,0xd87b,0xd748,0xd61a,0xd4f1,0xd3cd,0xd2ad,0xd192, +0xd07b,0xcf69,0xce5b,0xcd51,0xcc4a,0xcb48,0xca4a,0xc94f, +0xc858,0xc764,0xc674,0xc587,0xc49d,0xc3b7,0xc2d4,0xc1f4, +0xc116,0xc03c,0xbf65,0xbe90,0xbdbe,0xbcef,0xbc23,0xbb59, +0xba91,0xb9cc,0xb90a,0xb84a,0xb78c,0xb6d0,0xb617,0xb560, +}; diff --git a/cbits/musl/sqrt_data.h b/cbits/musl/sqrt_data.h new file mode 100644 index 000000000..3280296c9 --- /dev/null +++ b/cbits/musl/sqrt_data.h @@ -0,0 +1,13 @@ +#ifndef _SQRT_DATA_H +#define _SQRT_DATA_H + +/* #include */ +#include + +/* if x in [1,2): i = (int)(64*x); + if x in [2,4): i = (int)(32*x-64); + __kadena_rsqrt_tab[i]*2^-16 is estimating 1/sqrt(x) with small relative error: + |__kadena_rsqrt_tab[i]*0x1p-16*sqrt(x) - 1| < -0x1.fdp-9 < 2^-8 */ +extern const uint16_t __kadena_rsqrt_tab[128]; + +#endif diff --git a/crypto/Pact/Core/Crypto/Hash/Poseidon.hs b/crypto/Pact/Core/Crypto/Hash/Poseidon.hs new file mode 100644 index 000000000..c348272d9 --- /dev/null +++ b/crypto/Pact/Core/Crypto/Hash/Poseidon.hs @@ -0,0 +1,3240 @@ +{-# LANGUAGE BangPatterns #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE TypeOperators #-} +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE DeriveAnyClass #-} +{-# LANGUAGE DeriveGeneric #-} + +module Pact.Core.Crypto.Hash.Poseidon (poseidon) where + +import Data.List(foldl') +import qualified Data.Primitive.Array as Array +import qualified Data.Primitive.SmallArray as SmallArray + +modulus :: Integer +modulus = 21888242871839275222246405745257275088548364400416034343698204186575808495617 + +mulmod :: Integer -> Integer -> Integer +mulmod a b = (a * b) `mod` modulus + +summod :: Integer -> Integer -> Integer +summod a b = (a + b) `mod` modulus + +sig :: Integer -> Integer +sig inVal = + let in2 = mulmod inVal inVal + in4 = mulmod in2 in2 + in mulmod in4 inVal + +ark :: Integer -> Integer -> Integer +ark inVal cc = summod inVal cc + +data NineRings = + NineRings !Integer !Integer !Integer !Integer !Integer !Integer !Integer !Integer !Integer + +-- the real constructor for NineRings +tabulateRingsTo :: Int -> (Int -> Integer) -> NineRings +tabulateRingsTo n f = + NineRings + (ifGTE 0) + (ifGTE 1) + (ifGTE 2) + (ifGTE 3) + (ifGTE 4) + (ifGTE 5) + (ifGTE 6) + (ifGTE 7) + (ifGTE 8) + where + ifGTE k = if n >= k then f k else 0 +{-# inline conlike tabulateRingsTo #-} + +-- without inlining this and `ca`, NineRings is never unpacked into arguments +mix :: Int -> NineRings -> Int -> Integer +mix nInputs (NineRings in1 in2 in3 in4 in5 in6 in7 in8 in9) i = + foldl' + (\acc (k, ring) -> summod acc (mulmod ring (getMatrix (nInputs - 1) i k))) + 0 + ([0..nInputs] `zip` [in1,in2,in3,in4,in5,in6,in7,in8,in9]) +{-# inline mix #-} + +ca :: Int -> Int -> NineRings -> Int -> Int -> Integer +ca nInputs t nr j i = ark (mix nInputs nr j) (getC (nInputs - 1) (j + (t * i))) +{-# inline ca #-} + +poseidonWithRounds :: Int -> Int -> [Integer] -> Integer +poseidonWithRounds nRoundsF nRoundsP inputs = + let + -- initial state + ms = tabulateRingsTo nInputs $ \n -> + sig $ + if n == 0 then ark 0 (getC (nInputs - 1) 0) + else ark (inputs !! (n - 1)) (getC (nInputs - 1) n) + + rounds = (nRoundsF + nRoundsP) - 1 + + -- iterative rounds + outRings = + foldl' applyRound ms [1..rounds] + + -- return + out = mix nInputs outRings 0 + in + out + where + nInputs = length inputs + shouldApplySig roundNumber = + (roundNumber < nRoundsF `div` 2) || (roundNumber >= nRoundsP + nRoundsF `div` 2) + applyRound :: NineRings -> Int -> NineRings + applyRound rings roundNumber = + let t = nInputs + 1 + sigIfIShould = if shouldApplySig roundNumber then sig else id + in tabulateRingsTo nInputs $ \n -> + if n == 0 then sig (ca nInputs t rings 0 roundNumber) + else sigIfIShould (ca nInputs t rings n roundNumber) + +poseidon :: [Integer] -> Integer +poseidon inputs = + if nInputs > 8 || nInputs == 0 + then error $ "poseidon: number of inputs not between 0 and 8: " <> show nInputs + else poseidonWithRounds nRoundsF nRoundsP inputs + where + nInputs = length inputs + nRoundsF = 8 + aRoundsP = [56, 57, 56, 60, 60, 63, 64, 63] + nRoundsP = aRoundsP !! (nInputs - 1) + + +-- constants courtesy of https://github.com/iden3/circomlibjs/blob/main/src/poseidon_constants.js, trimmed for only 8 inputs. + +getMatrix :: Int -> Int -> Int -> Integer +getMatrix = \ti i j -> + m_data `SmallArray.indexSmallArray` ti `SmallArray.indexSmallArray` i `SmallArray.indexSmallArray` j + where + m_data = + SmallArray.smallArrayFromList $ map (SmallArray.smallArrayFromList . map SmallArray.smallArrayFromList) + [ + [ + [0x066f6f85d6f68a85ec10345351a23a3aaf07f38af8c952a7bceca70bd2af7ad5, 0x2b9d4b4110c9ae997782e1509b1d0fdb20a7c02bbd8bea7305462b9f8125b1e8], + [0x0cc57cdbb08507d62bf67a4493cc262fb6c09d557013fff1f573f431221f8ff9, 0x1274e649a32ed355a31a6ed69724e1adade857e86eb5c3a121bcd147943203c8] + ], + [ + [0x109b7f411ba0e4c9b2b70caf5c36a7b194be7c11ad24378bfedb68592ba8118b, 0x16ed41e13bb9c0c66ae119424fddbcbc9314dc9fdbdeea55d6c64543dc4903e0, 0x2b90bba00fca0589f617e7dcbfe82e0df706ab640ceb247b791a93b74e36736d], + [0x2969f27eed31a480b9c36c764379dbca2cc8fdd1415c3dded62940bcde0bd771, 0x2e2419f9ec02ec394c9871c832963dc1b89d743c8c7b964029b2311687b1fe23, 0x101071f0032379b697315876690f053d148d4e109f5fb065c8aacc55a0f89bfa], + [0x143021ec686a3f330d5f9e654638065ce6cd79e28c5b3753326244ee65a1b1a7, 0x176cc029695ad02582a70eff08a6fd99d057e12e58e7d7b6b16cdfabc8ee2911, 0x19a3fc0a56702bf417ba7fee3802593fa644470307043f7773279cd71d25d5e0] + ], + [ + [0x236d13393ef85cc48a351dd786dd7a1de5e39942296127fd87947223ae5108ad, 0x277686494f7644bbc4a9b194e10724eb967f1dc58718e59e3cedc821b2a7ae19, 0x023db68784e3f0cc0b85618826a9b3505129c16479973b0a84a4529e66b09c62, 0x1d359d245f286c12d50d663bae733f978af08cdbd63017c57b3a75646ff382c1], + [0x2a75a171563b807db525be259699ab28fe9bc7fb1f70943ff049bc970e841a0c, 0x083abff5e10051f078e2827d092e1ae808b4dd3e15ccc3706f38ce4157b6770e, 0x1a5ad71bbbecd8a97dc49cfdbae303ad24d5c4741eab8b7568a9ff8253a1eb6f, 0x0d745fd00dd167fb86772133640f02ce945004a7bc2c59e8790f725c5d84f0af], + [0x2070679e798782ef592a52ca9cef820d497ad2eecbaa7e42f366b3e521c4ed42, 0x2e18c8570d20bf5df800739a53da75d906ece318cd224ab6b3a2be979e2d7eab, 0x0fa86f0f27e4d3dd7f3367ce86f684f1f2e4386d3e5b9f38fa283c6aa723b608, 0x03f3e6fab791f16628168e4b14dbaeb657035ee3da6b2ca83f0c2491e0b403eb], + [0x2f545e578202c9732488540e41f783b68ff0613fd79375f8ba8b3d30958e7677, 0x23810bf82877fc19bff7eefeae3faf4bb8104c32ba4cd701596a15623d01476e, 0x014fcd5eb0be6d5beeafc4944034cf321c068ef930f10be2207ed58d2a34cdd6, 0x00c15fc3a1d5733dd835eae0823e377f8ba4a8b627627cc2bb661c25d20fb52a] + ], + [ + [0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1, 0x25fb50b65acf4fb047cbd3b1c17d97c7fe26ea9ca238d6e348550486e91c7765, 0x293d617d7da72102355f39ebf62f91b06deb5325f367a4556ea1e31ed5767833, 0x104d0295ab00c85e960111ac25da474366599e575a9b7edf6145f14ba6d3c1c4, 0x0aaa35e2c84baf117dea3e336cd96a39792b3813954fe9bf3ed5b90f2f69c977], + [0x2a70b9f1d4bbccdbc03e17c1d1dcdb02052903dc6609ea6969f661b2eb74c839, 0x281154651c921e746315a9934f1b8a1bba9f92ad8ef4b979115b8e2e991ccd7a, 0x28c2be2f8264f95f0b53c732134efa338ccd8fdb9ee2b45fb86a894f7db36c37, 0x21888041e6febd546d427c890b1883bb9b626d8cb4dc18dcc4ec8fa75e530a13, 0x14ddb5fada0171db80195b9592d8cf2be810930e3ea4574a350d65e2cbff4941], + [0x2f69a7198e1fbcc7dea43265306a37ed55b91bff652ad69aa4fa8478970d401d, 0x001c1edd62645b73ad931ab80e37bbb267ba312b34140e716d6a3747594d3052, 0x15b98ce93e47bc64ce2f2c96c69663c439c40c603049466fa7f9a4b228bfc32b, 0x12c7e2adfa524e5958f65be2fbac809fcba8458b28e44d9265051de33163cf9c, 0x2efc2b90d688134849018222e7b8922eaf67ce79816ef468531ec2de53bbd167], + [0x0c3f050a6bf5af151981e55e3e1a29a13c3ffa4550bd2514f1afd6c5f721f830, 0x0dec54e6dbf75205fa75ba7992bd34f08b2efe2ecd424a73eda7784320a1a36e, 0x1c482a25a729f5df20225815034b196098364a11f4d988fb7cc75cf32d8136fa, 0x2625ce48a7b39a4252732624e4ab94360812ac2fc9a14a5fb8b607ae9fd8514a, 0x07f017a7ebd56dd086f7cd4fd710c509ed7ef8e300b9a8bb9fb9f28af710251f], + [0x2a20e3a4a0e57d92f97c9d6186c6c3ea7c5e55c20146259be2f78c2ccc2e3595, 0x1049f8210566b51faafb1e9a5d63c0ee701673aed820d9c4403b01feb727a549, 0x02ecac687ef5b4b568002bd9d1b96b4bef357a69e3e86b5561b9299b82d69c8e, 0x2d3a1aea2e6d44466808f88c9ba903d3bdcb6b58ba40441ed4ebcf11bbe1e37b, 0x14074bb14c982c81c9ad171e4f35fe49b39c4a7a72dbb6d9c98d803bfed65e64] + ], + [ + [0x124666f80561ed5916f2f070b1bd248c6d53f44d273d956a0c87b917692a4d18, 0x11924f02fd19b09255aaa1cf46ea0518e3d7bfeef47421609491011db0bd0b02, 0x247fa7f022304a1994ff505456c2201ef9b717369498d3ffce446601ed9df845, 0x03fd7b19ef2c861f22f77ff810f54e277bc94eb76c02d79d986be3dcdf051c3f, 0x18bd41239c3e71579a677443ecffbd555a81eeeea69352a68b67c8563c0c2a06, 0x2d78c3a5d28de9ff35bf0a257635196e5730ca7f40493277078cd75da8b4ebdc], + [0x0a514a5c227f4cec95dfa029e8dd124c34895aa46bb27c0911f3780d5015540a, 0x192e16d17d956b257b85a652eefdf2ee09589eac5be80915775723d2cb1da06d, 0x298ce0c1e3113bb935c7058e7772b533b1aa9db0c0926bdc8917e5605ca3ac10, 0x094cb4e83621afd271e41bc71727f0158ebd612239ac9d698b17fe4be05b7fc8, 0x03d880395be93c27d649af5fd142e76b33918cb8841d5a28173bd5cf7d328791, 0x28eeae6b5866ad68e443bbaf91680db7d7e2b3037e38fef61b42cbccffceca81], + [0x278bb49a7b4e44aea46eb0f882cb692801a6e60fdd5b5c23c63cd65ccce4fe0a, 0x063edec1bed831f506af8db648d6fdea145345887e8bdcff109035a1d9b674d7, 0x1baef1cb5509b526a42061fb53657f99b3232500e855192cbe8c940e068c475f, 0x1324564ac7bdf9e22164e9858d7fa8e368b165eaea3daf4eb67ee59c0df2e5d4, 0x005761b8c6aecb1a8ca4ea4dfc2c8376064a4a8004ceeda210a55240562ddc13, 0x10c9e283159d58cb4cb2e35fde83a3ba1fdc28002ed9963d2a99f186178a148d], + [0x0c399e9f67aa40707a203feefb0b958bbdadcec5ca34901d253d026a2419f6a2, 0x083f0df3f1a0351d0330ec3ff602ca8cc353b7f6e762c7107184cd7b423449f6, 0x1a6764d5943fc4a720b4c0a19fdb8c711984307287a58b9b5f9f5d58212cb263, 0x011a63a26feabf87fa66bde66cc25a922c96382d76c6a7ff48f1537beaed683a, 0x08ca7b64657c3548f32bef5b63ad24288a41c0b251099ad27f9434307e3e64d4, 0x01998270471e9361955446b0cdb8bea915ec0675f1cd648ddcb04303507a4489], + [0x1d6b3d5f6ea369c26f825d2362933eaa31ea35ec0a77c1fbd9e01ca1523e4432, 0x119ef188bb3dd0d32306976c19941e8664be687e7a69692da27da215a6f06d40, 0x2d9e0ab5c06893dfdfd03481381ba86b6e6292df5609d71f2c64b2d9a79f809e, 0x25f16631bf77060f7ea34087c025bf135784319ef08cda2e31419ee0a529e658, 0x144c7a11da5a7c5dabae3f33fbd03cad86d18bc594c79a497ecb9894edb554f1, 0x0f971162627723f3feadacb28b0c104cb8f74de508752fa8d7c0db2af13de8ee], + [0x24be510095436206dd0abd0b0cbb95c883ab304aa52598b1a69306ec981a688d, 0x211610e2ad4a377426fadf7068b0c1a6c299a164c1c1a603eaed944870d0b9b9, 0x15a67d981041b1f6f09f3f9ebefd864e779d3af08157786ac077505e50ec79fc, 0x049327fa79d28c12a2c82406947f77f06775b0287468b3136877701dbe7c9598, 0x230940dcc5232658ff9c29697a3fd416d170e8c998f1aa85dea0c42d79f951aa, 0x1b121c049cd1159e289007e0c9da9995cc4bab4c26fb888ec3972a8a2e656964] + ], + [ + [0x2abd9e16b7b48289aa19cdfec726fa3fa15cc1625102ae511bca45f39d337e9d, 0x1b4bc5885d1cfc8eb691875300db5a0c7362ae381898acaf8b63cad04ecb36c6, 0x08a72fbb55dde3e93c5818571a424a54953695029eedbcf91eaeb012751c7f83, 0x0f95359a1f6845d4921892f83e500bbb1b3d3763d8fc762400af039b0abb83f5, 0x16f01751ce985328afde34d81619defb43e6c7b5dadf52d0f82472fbce7770d9, 0x1c391626328457fcafa629f3e6d33e2555e8d885e3c07cecc8af1f4d56596417, 0x00970f671b9ba35e3e3c642d1e0b8032023ed5bac91c2c1056f03965a42c5297], + [0x1fe9feb5c7f7c7a426bff032cd6a3158278b6c6b2cc57a871213fcafd6427989, 0x0cc7eabb154aa7955eac47a19f6437a2b8dec0fe9e5686150ff6e88b1a7b4bc4, 0x0393efd96399aa0726ef9af79be8b6c715e429906ca0d15076b5a990fea75ace, 0x0871233835b752ea030cf8a4f43771296eeb33f697d1b0825db47d39ac9e5955, 0x1a02798f047a51baaea34fcfb26ca6afe96a5fad1d2db4270497b6e6504891cb, 0x055665d76df3cd0fcb713c234ea79d06a31d6e3e4c3bcc657dba4c664d5a0da0, 0x26ee9691a638edc7c91887e302fc55e8e7758286a44845ad88fd7de3bb1052c1], + [0x00cdb2db9e4f9d732d217c5e3114821165d49e5a2d41556bcd53d0c4d433224c, 0x012f3bb29c972793182123f5c49306e16a3a787c4bcd9c798a131b70856d1cbe, 0x0bba9006404c5ede82b527677daf444ed43fd1e0dbdc5528dd2cd1f17ad73481, 0x17e4e73bf701f88d219acf1ca6390cc1e17c9f84b1713820837ca070be84a2dc, 0x234b8a077ef52b53a343b8da5b20cc358ad60760dd60276d485015f73d53d207, 0x2dc3fd77394b7b5ac1cbd1b46e6ded5b835d7217a4c50a487ae9a35a7fd45d9d, 0x1668477640fab14c72b1c16ff0192e48cf882f12276bd12f97f82c6ee2e61e48], + [0x09664216ca565c1a44fc2b98347ea8b36904b3877f2159dcc999895adeb4d70b, 0x111fd8dfce2bd3b7ba0cfa93e20fb685abf76d77305857b8df30914e4849ecef, 0x19f53c0a592b3ea93497a511e56f66753598265b1ab6774da48eec04e4d93426, 0x19b683c39d3b002fc3523b7bee5a60148b1dbdf18dd1c318e6a541e8cf66a174, 0x2547113a818779f13e3448719c7ef100b8036bb3e882dd5e6456c35311c1bd5b, 0x00cf148f8045cdbe7bb1013f72ebd4126a3e35cba9a970441ba8d5bc76943b0b, 0x3008421eed767a093322a09c3733973a038168cb28cd2e1f709076c00b869599], + [0x1463f51d4a4cb1eba16dbc115566aa48fe77b43c244c9988a3c658d2f56493d6, 0x16afd8f4c39038b8006a59d292aea84731c0f83832a61b82250ed90118e8fec2, 0x2296361f3bf154efbab996921936e9b1dff8352711f958638172055333e07579, 0x1c3160ebaeb10f809f69843cf8d5bbaca198d1f8e3439be29beb92d909ec891c, 0x094c66bdcff54382cd9213abe43312edb5b4d414c6e09acca24912a7635404c6, 0x2e883bd408c4c826d004ff777d7c0938434ab5bb84f3420e5d94b853b1746f89, 0x228af6d425e91a783dd18fd89a6b38bda053f2f23c094b875f27cb3abba2030b], + [0x214e41788bd2b990347c7f2a8f47612d4dfceb1a1e6da38165873df66ce51f59, 0x03fba82d3f783620873da94e9f4e84c8b529d76f54e4b5d7d4805272af9b9775, 0x066782fe3e869de2cebd7ebbf60fb435785329dfb12ad9bd1b4e46ed36289511, 0x1c5cd6b23ef336be01efa37a27e6b7aae5d1643fceeb212cdff51588835fb537, 0x2f3b4bf0f105f88e27248af094e29feed9ff3fad9a794e15830bd2b311539453, 0x2f4085eaa9f80a69b739fc23f2fe4057f64729b311783fcfab3a0a36fc1ff432, 0x2363603349e94f520fa1f98fe2507f6aae361934078aa59a16214c088185638b], + [0x0548541724f64e20128260899abe8fbcdff184a1957a9385fb715923bf0fc79d, 0x21c5e25a6991364e59a205e5b01c811deeb095680a72928369cfd2de71b14f98, 0x11c5cc53f6338c825817aff7792a2efbce8fff171300d41455a2edac37663d02, 0x27a0949fdc9f10495c4ee7214aa0edd2ad8eef68f577da8b96f9d87a39504bf9, 0x1c7fc68f3fbde4a23c455ef0d0dbce0ce556a0194e6d552c0455cbb5b0c230e2, 0x11d0f56fc00e7d85b3a2939fd33991dc8abc1ced0c3f3c530cbfb4500d63de9c, 0x01b2e9d20d9b55deb048cabe1636f0e96363bec886679cbd91f332fb2bade44f] + ], + [ + [0x1aa4d470abeaa2357079129d114bab1170944f929fc178216ad847d4430f3f27, 0x0e1f4e4d26e9da5f8ee3deaf48b493610be61d7d3db1d9754feca30879adc644, 0x0c298c14356a5a7f226c5a549e59184900385aafd8ea41d9746729964ef75f34, 0x19e070982d3ee675e1622ca20d13b2375e528b676706882eb8f1afe1c5045ea1, 0x0333e2923992e89dee570a650125eda75a20a72e69e10863a19d17b7beea9295, 0x1944aac72bf6fbcdec04361238c3c4d9510d5f07439a1b6ff41f652990be0139, 0x27d802ad019a42fd04892ad167d9e83596a730605890401319661675736359f3, 0x2bd05a040a0987ac6bc01f67242d54b7a2c527a970ad2815b273471eb9623e73], + [0x254b8126f45243f14dd8211df41fe5516b35952d56c62678c148e73cdbad3718, 0x2089c597feaa4ca9a202edfbc823763100e294c9e33000e513b2a216491d474a, 0x0ddeaa906cb65f3e9c9bea6344dda8db90c253c0f7f99ecef88786fefe0e5cc3, 0x1114c9120442750493d999d4dd45dbd4f3b75ab183209235396ce83d8ee9916f, 0x2e8b35a8c29e639dde8dfd49b4b347f00ee467863f6efcb355fa1534ef70783f, 0x20e6cc613ae6cb0a518425f53db1298a7f8859ee20aad08320d0a4f9bbfe8512, 0x2420dd1281fc0dfac176a752d15906b55f137b9cc320d5d5daa9df3f3d43d3e6, 0x17bd4f2726748d99925af9a2f2929e231c1869428c13b1e397bb0099191723a3], + [0x270712f18b1518fafe093660f492cdbc2fb70ffab31d8a4d8a1934be68792369, 0x107cfefa1e864045a668396526ed9f675b2bbf272ca635d8d3e8801099bb97d0, 0x04b96a296a35acf415929b8784b6bba64a630d29dff28b628fc98ef708230b57, 0x1f0465a9c133a1c6805d705be6b3ea9912a2d062c34dbef92de46955b83e7bd9, 0x27a2b7f5549e5eedb90105c0f8e20f0571ab7af0801f1bdd23eaad91f2229a13, 0x031b0afb7ab2f1d241f882178f7dcdad48591cc67905d651dbcafce94b14d073, 0x22e0323bbbdace5fbc74a0b3dedea6e1e3bf10e84dfc71fe395089ac197af744, 0x1eef36d62f3f864eae67c63324e47a6344e33a2d5bfb82f05bef9900c54e745a], + [0x2bfc3981a249aeaaec4ab9001727d32d4e6fe75598ee964fc85cf30d50df584b, 0x021630ec3f236ed219f73cc617b9f8b267dbee99a63c528544ea31b27cde49fb, 0x28890a03199b727fede5ed0090ed69494c053c97930fbb6c52358b0d7d104c16, 0x1b80f3f439396c2f466b8e9b25765a014970455a1beaed7a6fa308dac75fb582, 0x2a4bbad245a33e5d9701537f751410e4ff297b8f1d1d9098fe9c518c261a1b0a, 0x1e431f2b1b7edae4f8cbb5d307bf5131c352c2a215a870d739617f4b017c6d16, 0x255639889a259ebe59f74a8fdf2efce7fde1e3a666b35d8e6ec601d4d0b22689, 0x2d0d8a814cfa16c2323f174be2dcbe0c295829fc59bf2a89f13b4ead0eb056a8], + [0x16060a17e1b11f851ceab20464572b3d78d582ea050014843101485f65ab723d, 0x2741203d66c523c7639ea713b20346119c961cc1e9659a458af74cbee16d71bf, 0x2208c5004806c7aaf58314590bcbea16168fe62ec0497afc6bdd2938c12d9a23, 0x1c01f6db435dc4885eef9cdfed193250b9d3eb4cee366674b07bdd194ff349fd, 0x1f0e36c2cf9ac2c4388e74966d9ee7d1a0b3186916a08cfa306f6bb36d21e548, 0x199fc2be60e49e679ec2ede6cf3345dcb3b918e5b3e07c2cd8141333934e178f, 0x0a38d163b8a2fa3092999c1797b1af909bd971a25a656baefbdbdfa3628e678f, 0x198949eef2b27c2b9c3d699e3fe57da3d5b509c2b670afce400aba1aaa9ed51f], + [0x00e73217a106c402e4c6c166cd9ef1fd2a0b16ac1cb43646bc1c726f83177770, 0x17b2092b0f634576b654c6de21a1a8d812bd4c01559fff83217129082e2b2b20, 0x2f24d609cb23720eda55fae29ec6f19902c42d8bf904fb656202736d97b2eb69, 0x2df183fe2bc9b8b75773fa961c8d4117e582a80b656af5c58763e7024ea4189c, 0x15fe963f5bd0d92878c10a894e118018db82e63528afa4d4703e9881eda118d1, 0x0af594dc4030e8509701fbd3d8995f73126ad72a7af0fff344eee82a31ce77ff, 0x0b8e857d9fb1d554f3a4ec307ad907de7a436438603af1b28d4e4ee379960ce7, 0x07ebcd25a10e56693a28155fcdaf7b3519d9e0e08241e21789696cb76ee06297], + [0x04b959ca07e7182ca08f2351a03545bd7ab676f740b02331637ea1434c8545ec, 0x068e8e63411df2b3a9d7c567f66419a580d3ba15bbfdd1226effa3fd6bd47b3c, 0x0344d0c772c2f053664a7b9266b19d48ae5d2ab3d1c1a18150754ab4b836afd3, 0x07e0cca1a35ed15fbdb619bfaecc7a9a8f4c51293927562acea8eab817c6b84b, 0x222edf3e26bf74b2f503983189201d4ee8e6d6fad341d7ff50748dd739749df6, 0x2d4308b4823b465db653d36818181209d23cd12f844f72f7548d49e55055a601, 0x2e8e67fc85f9b4d00e9e1197b35bedf55afd7300a4c370987c83c15cf73cae3c, 0x22f1bc4ec138b596128ce5ee5b8184964cc262318e17ad21d45c552477f53e61], + [0x0fc9cc95222f92715cf7476010225e14cc38f314071e50e0f3bc9ec674a8aacc, 0x2f5a2a0cd0cb24896c94878a8106d57e82c68dcf1e209167a45ae9cf8570fed2, 0x2cd19b5c55bab1809e52cc9fc1a038c08935da19cfc563e7048d6bd1970a0c8e, 0x24ff2986781fe40ae61e8f5ca0ef17c5a5ea7bddbc127d431547c1f6a8f5cedd, 0x12a87d0c5419f448419840e5e5a92d276ace00963d987f2a1008913d98a27114, 0x0af3ceff2c865a901b9406d5d9b2fc58833d642f46c6493ca030ef595061ec6c, 0x27f42d86842f4d8a8c3aff2f47ffc1e179f097aaecce55bba0b0fdfd5b190aa7, 0x2b6b3bc340d4119e57831e4a2187013f1216ab3b639945dd92a984943241f1d0] + ], + [ + [0x0190f922d97c8a7dcf0a142a3be27749d1c64bc22f1c556aaa24925d158cac56, 0x1f8d3a9d2d31ab32d9bdb6375170dbba89f6f8f74d16e4fd02f3675d5fe2baad, 0x230c694139416f40422d713e13c056c45c3c631b346854523970eaea58a37df4, 0x2063a461ad06315ae5992a53a14bb598367624afc2833ccbb83af92ca0f6a334, 0x0c574e628f84b6ba9d17b9d2bfd4747e06dd68cda2383d64ce365927098c046f, 0x276428d88040a3e0f442424d2ffcb8d19becf3fb6ca02c1b5c61b5ddc53ceb90, 0x24bdf6101b2f223174e869d6aecbe8ea5b04a14c38fdf1494393cc6fdb3e42a5, 0x180fca184150c0e354b4b3a4a075824d4b68e8274943f4dd8b0c64eca25dc68e, 0x10726dcff87299c8532159976607633f1bc2ad24453c1bab26b726b82d756ebb], + [0x0607cd8ff9b889773c9eb68b8a4366469d470cd7c6004106caae95c10c424419, 0x2591580b73e7b5d5f34d9fdc0cf7fe3de7f6a18a255e4376fde3eb31dfa51d79, 0x093cff12150aecb3465c4c99f044be85dcc1eba21d429132c2260dd3d12ea441, 0x059116da88a081267dd888204fc6fb79046c3297ccb65f9e0fe0d50b4db44ec6, 0x2c948497373514e7d9846dea9ddf5755337ddb661043d6c628cecb8f55173bd8, 0x2c2729812be9ed432e75709133119cb0a14e1b6ea31c1279b7c3e495deaf108e, 0x2280d6d4718f9f06b551a988408f0515070e455ed63377e910be087fb79bd191, 0x1b1bba125505ae9675bcec7c9af579c5cc83533c9d555be398afa09cbf95d6a7, 0x17013257716d3cbae28e1c272cb6aaa2844136049ffbca05ca201523032c64d4], + [0x1da524cff60b64856dc1f5dde0ff62da7b182da26908f6ba6e590adebf91b40c, 0x2bb4565893b6ffc5799139cdc151158749c2c65db48672abaf24c5b3813c0e2b, 0x25081a00fc20ae366b1fe7ea6b09e62a51f6fd377f608368c12ba4e3bf89935f, 0x1b43719cd10b60c5647c097d1fa84b8f3c12c9c475ade13b388c7ec47240be11, 0x22dd201ecbab94a2ee393796fefcca63aa54d9a19ab9c7f20a0bedcfb9d191f2, 0x0b8e79838cd30707999c621621e77e69c0f433d543b79c668cf379b6623bac84, 0x02082d5647658eae648936cefbedfad2cd0538572aa6122ca68ccced68f432f4, 0x277bae2fc597a536adbe9c24bc8ee81731eddb574c6a5142c1c5a48c51f82e81, 0x30354c9f29c920c05e99d7cc747510e76f7fa69a71594a290eae7293c5a48441], + [0x22f33eaee3c481e65801b761a72832908f066fe21dab5fa5ec1d4c6e99dd6dfc, 0x1c5ce77776893d48147444b9f6d66a4da29c95707de832756c739eab8e87658f, 0x2ab8edd22fbe2a1cd3ce9a4212d0efb282ccac28af4d876fc946203070c920bd, 0x26e49154acca24424d5f8d29f650f9824de82eb7887329cbc83a56ae01dee4a2, 0x0badd77f516d4fa321d1099bc1e51909001591ad9919f08ce9718aeeb2bca4d6, 0x23671c5d1fb556063a64b5f664340936dc5ffedd4bdbaa2e96205704da5864f5, 0x020d7202ccde24901d6ce2d107e79e1fd78d6c9398ba7a4996f116adef14def3, 0x1d86496995f14264e7a054cc8224900368775c3e5ac6b5f54285f4a73c2171ae, 0x136961746d34fd196025173c4d79bf8b3d1d05291c584928d97258fd5fb4fb4e], + [0x075f84e9c719bb8de8e61083290daff19aaa4337454e5ba804257787470f2f54, 0x175505391c619b75530fa83e513184381e603d8449d1e070017ee8ec0a4d25f9, 0x29c5ce97710c1578a0990d862cf881badf10e4f6bde629199e803cd1c426be4e, 0x2caf86cff60521ccc5ec6e2e2c83b4707bb90f948644bfaa8f80b0afcd4cde10, 0x24f92793d67638b4abfdf48ce3b62ab5d0e1b250dc274d746f2f7d0544185b62, 0x02809dfe24c7fd7cd49b97b27150f4d38a340b60f0733fd4530cd4269b4811e4, 0x26709688150ed035f959687edf7747ee8ee946b770173dbe50390ab8c08c5f9c, 0x1e5ae4c295ad5a17e00f973f136f1230a6fb85637631b306d3705f80effac24a, 0x2310e2337e4d53c1635da18a2722178d55af583591bcc317eba842df247deaa9], + [0x2084be9a57e9adb80303a8dcaffd4bb77adb6815168b36a1d363b38425437135, 0x06ed1d14dedf763a3065f27e7a46d7fbf20d2b4e86a0db86692a269767d577e3, 0x1324544a54174cf7b3cd8ffc4b86320f2319d9b88c1779b89b1916018f3fb9b7, 0x2e923ea46d492247e12e0a7dccf6620f5eea6629b7532b3af246809398859633, 0x000bbbbb87eccc91d5fb07b6c55088ca514d68ddd93cf31c8ed2d2cc7f23b22b, 0x26010a3f5295bb4481310cbca5384a47af0f9905e4c76bf54b870ef0ffefa1c8, 0x0751a4a4af246255ce412c4bb47fa34a51b8628f3cd902077775c8fa488e7519, 0x28d2351619ccc6fb31ad4206e2c064bf4d9b2292b28463e53e4771f10670ddbf, 0x1815e4f7b40a7027878640a6cdc4b2854300cf6fd4953c2ac2c77625ef44ae04], + [0x0b303449f1bf4b92d2cbc26ab34b4215b6dd7af010747a705b2a6e3398882922, 0x140cdda33bb7a79b2baa851df5ad459e7df569b9f2c3da542d3b8d5b76b356ce, 0x1d18b25aac98b282e10b5a3a74ce5caa169a5c30bae52bba280ed517f3f82fef, 0x1ec6c32f513b8f30c7aab42e7d91aecbe54aeb188a84f8ca46bd7e9741b9a389, 0x089beeb21c346cb9bc182aa2b70f853f1a2258d56893ce5a948d9c645ecbc9bb, 0x2790643a66038cce4a6488847d8d2da2eea84961f8134b1be36947f803527e67, 0x159e25e00326a76f25c1143a5be6f53fa51ccf368d9974cc6d93cce8eb81d37c, 0x2486b884370d49a003fd041e800f0a898ab61b5e947997461ee3284241f3baaa, 0x111efc136a9dfe0ebcffae8943e679cc0fbf62fd0ce03b409fecd932a8281b10], + [0x0c099bc68243537203f97254f08dfb7efc09de8f96d72f3b3e0aaded45e18b4a, 0x035e9ecc464cb431cc92c3356e8a98547e843ed1324c1e971179fd1ad9fd51a0, 0x02f35e921dae87f1284c0c8ae737dbdc4936cbbb03a03a5918552fe565270a8d, 0x23a72c27f4f5e6ea5325d5b368f98b40693b2db1e8ca3d096739753dc5678303, 0x0e07b1d22eed54fdf966ffdfbcebb653b5dac3b2a91f50272876efb17158be2c, 0x05fa56d431d4bd09625a86d3623464dc90bd541ea41748f2026f65025ea9d2f2, 0x2d6f3e0e98413d5d6a1101b245c9e711bb2e956e27a5870784fd5403b39867cc, 0x213176bc1a04939fe7d6bc30691aabd6152ed24f309bff3939a0d91d54c67a66, 0x0a5a1148dad4562eab18162b3914b64d5753e9617a5154e93f7e43e6860687ea], + [0x1c5fd9060d4e0d999264429a5004c165570bd1675b09f977708b1ca48e616388, 0x129f06c930edd36fc2fb7044a6332751a2e3bcdbe756d883716cead6bc7063cb, 0x14a5ce1603228d6e6fade57c1da536659ba46d1b25566f12c28debcbedc5b4f4, 0x143617efcdbbc0d27a091f28039eba8abb39392e2a462850b1f9cd8532f5075f, 0x2885f2d44be0ecff57d92a4384edb5bebfb585bb23eae2a2ea50806bab8b7bd7, 0x04715db6d86b513d002589f1f9522f7de3b1a8bd702c167559ede97da2c0076d, 0x088887966c079d2e689a8d6d7bd913e92d326959bada59b99a653feaadf6c467, 0x12ded41f8047da3e6c22bfed3ec5bb52d027e560048db4c0f96ca9fa85e17bc3, 0x1f47c67a4325672f17b8bd1ddbd80e4e9e6c62419a9c204cc7e8821892431aae] + ] + ] + +getC :: Int -> Int -> Integer +getC = \ti i -> + cData `SmallArray.indexSmallArray` ti `Array.indexArray` i + where + cData = SmallArray.smallArrayFromList $ map Array.arrayFromList + [ + [ + 0x09c46e9ec68e9bd4fe1faaba294cba38a71aa177534cdd1b6c7dc0dbd0abd7a7, + 0x0c0356530896eec42a97ed937f3135cfc5142b3ae405b8343c1d83ffa604cb81, + 0x1e28a1d935698ad1142e51182bb54cf4a00ea5aabd6268bd317ea977cc154a30, + 0x27af2d831a9d2748080965db30e298e40e5757c3e008db964cf9e2b12b91251f, + 0x1e6f11ce60fc8f513a6a3cfe16ae175a41291462f214cd0879aaf43545b74e03, + 0x2a67384d3bbd5e438541819cb681f0be04462ed14c3613d8f719206268d142d3, + 0x0b66fdf356093a611609f8e12fbfecf0b985e381f025188936408f5d5c9f45d0, + 0x012ee3ec1e78d470830c61093c2ade370b26c83cc5cebeeddaa6852dbdb09e21, + 0x0252ba5f6760bfbdfd88f67f8175e3fd6cd1c431b099b6bb2d108e7b445bb1b9, + 0x179474cceca5ff676c6bec3cef54296354391a8935ff71d6ef5aeaad7ca932f1, + 0x2c24261379a51bfa9228ff4a503fd4ed9c1f974a264969b37e1a2589bbed2b91, + 0x1cc1d7b62692e63eac2f288bd0695b43c2f63f5001fc0fc553e66c0551801b05, + 0x255059301aada98bb2ed55f852979e9600784dbf17fbacd05d9eff5fd9c91b56, + 0x28437be3ac1cb2e479e1f5c0eccd32b3aea24234970a8193b11c29ce7e59efd9, + 0x28216a442f2e1f711ca4fa6b53766eb118548da8fb4f78d4338762c37f5f2043, + 0x2c1f47cd17fa5adf1f39f4e7056dd03feee1efce03094581131f2377323482c9, + 0x07abad02b7a5ebc48632bcc9356ceb7dd9dafca276638a63646b8566a621afc9, + 0x0230264601ffdf29275b33ffaab51dfe9429f90880a69cd137da0c4d15f96c3c, + 0x1bc973054e51d905a0f168656497ca40a864414557ee289e717e5d66899aa0a9, + 0x2e1c22f964435008206c3157e86341edd249aff5c2d8421f2a6b22288f0a67fc, + 0x1224f38df67c5378121c1d5f461bbc509e8ea1598e46c9f7a70452bc2bba86b8, + 0x02e4e69d8ba59e519280b4bd9ed0068fd7bfe8cd9dfeda1969d2989186cde20e, + 0x1f1eccc34aaba0137f5df81fc04ff3ee4f19ee364e653f076d47e9735d98018e, + 0x1672ad3d709a353974266c3039a9a7311424448032cd1819eacb8a4d4284f582, + 0x283e3fdc2c6e420c56f44af5192b4ae9cda6961f284d24991d2ed602df8c8fc7, + 0x1c2a3d120c550ecfd0db0957170fa013683751f8fdff59d6614fbd69ff394bcc, + 0x216f84877aac6172f7897a7323456efe143a9a43773ea6f296cb6b8177653fbd, + 0x2c0d272becf2a75764ba7e8e3e28d12bceaa47ea61ca59a411a1f51552f94788, + 0x16e34299865c0e28484ee7a74c454e9f170a5480abe0508fcb4a6c3d89546f43, + 0x175ceba599e96f5b375a232a6fb9cc71772047765802290f48cd939755488fc5, + 0x0c7594440dc48c16fead9e1758b028066aa410bfbc354f54d8c5ffbb44a1ee32, + 0x1a3c29bc39f21bb5c466db7d7eb6fd8f760e20013ccf912c92479882d919fd8d, + 0x0ccfdd906f3426e5c0986ea049b253400855d349074f5a6695c8eeabcd22e68f, + 0x14f6bc81d9f186f62bdb475ce6c9411866a7a8a3fd065b3ce0e699b67dd9e796, + 0x0962b82789fb3d129702ca70b2f6c5aacc099810c9c495c888edeb7386b97052, + 0x1a880af7074d18b3bf20c79de25127bc13284ab01ef02575afef0c8f6a31a86d, + 0x10cba18419a6a332cd5e77f0211c154b20af2924fc20ff3f4c3012bb7ae9311b, + 0x057e62a9a8f89b3ebdc76ba63a9eaca8fa27b7319cae3406756a2849f302f10d, + 0x287c971de91dc0abd44adf5384b4988cb961303bbf65cff5afa0413b44280cee, + 0x21df3388af1687bbb3bca9da0cca908f1e562bc46d4aba4e6f7f7960e306891d, + 0x1be5c887d25bce703e25cc974d0934cd789df8f70b498fd83eff8b560e1682b3, + 0x268da36f76e568fb68117175cea2cd0dd2cb5d42fda5acea48d59c2706a0d5c1, + 0x0e17ab091f6eae50c609beaf5510ececc5d8bb74135ebd05bd06460cc26a5ed6, + 0x04d727e728ffa0a67aee535ab074a43091ef62d8cf83d270040f5caa1f62af40, + 0x0ddbd7bf9c29341581b549762bc022ed33702ac10f1bfd862b15417d7e39ca6e, + 0x2790eb3351621752768162e82989c6c234f5b0d1d3af9b588a29c49c8789654b, + 0x1e457c601a63b73e4471950193d8a570395f3d9ab8b2fd0984b764206142f9e9, + 0x21ae64301dca9625638d6ab2bbe7135ffa90ecd0c43ff91fc4c686fc46e091b0, + 0x0379f63c8ce3468d4da293166f494928854be9e3432e09555858534eed8d350b, + 0x002d56420359d0266a744a080809e054ca0e4921a46686ac8c9f58a324c35049, + 0x123158e5965b5d9b1d68b3cd32e10bbeda8d62459e21f4090fc2c5af963515a6, + 0x0be29fc40847a941661d14bbf6cbe0420fbb2b6f52836d4e60c80eb49cad9ec1, + 0x1ac96991dec2bb0557716142015a453c36db9d859cad5f9a233802f24fdf4c1a, + 0x1596443f763dbcc25f4964fc61d23b3e5e12c9fa97f18a9251ca3355bcb0627e, + 0x12e0bcd3654bdfa76b2861d4ec3aeae0f1857d9f17e715aed6d049eae3ba3212, + 0x0fc92b4f1bbea82b9ea73d4af9af2a50ceabac7f37154b1904e6c76c7cf964ba, + 0x1f9c0b1610446442d6f2e592a8013f40b14f7c7722236f4f9c7e965233872762, + 0x0ebd74244ae72675f8cde06157a782f4050d914da38b4c058d159f643dbbf4d3, + 0x2cb7f0ed39e16e9f69a9fafd4ab951c03b0671e97346ee397a839839dccfc6d1, + 0x1a9d6e2ecff022cc5605443ee41bab20ce761d0514ce526690c72bca7352d9bf, + 0x2a115439607f335a5ea83c3bc44a9331d0c13326a9a7ba3087da182d648ec72f, + 0x23f9b6529b5d040d15b8fa7aee3e3410e738b56305cd44f29535c115c5a4c060, + 0x05872c16db0f72a2249ac6ba484bb9c3a3ce97c16d58b68b260eb939f0e6e8a7, + 0x1300bdee08bb7824ca20fb80118075f40219b6151d55b5c52b624a7cdeddf6a7, + 0x19b9b63d2f108e17e63817863a8f6c288d7ad29916d98cb1072e4e7b7d52b376, + 0x015bee1357e3c015b5bda237668522f613d1c88726b5ec4224a20128481b4f7f, + 0x2953736e94bb6b9f1b9707a4f1615e4efe1e1ce4bab218cbea92c785b128ffd1, + 0x0b069353ba091618862f806180c0385f851b98d372b45f544ce7266ed6608dfc, + 0x304f74d461ccc13115e4e0bcfb93817e55aeb7eb9306b64e4f588ac97d81f429, + 0x15bbf146ce9bca09e8a33f5e77dfe4f5aad2a164a4617a4cb8ee5415cde913fc, + 0x0ab4dfe0c2742cde44901031487964ed9b8f4b850405c10ca9ff23859572c8c6, + 0x0e32db320a044e3197f45f7649a19675ef5eedfea546dea9251de39f9639779a, + 0x0a1756aa1f378ca4b27635a78b6888e66797733a82774896a3078efa516da016, + 0x044c4a33b10f693447fd17177f952ef895e61d328f85efa94254d6a2a25d93ef, + 0x2ed3611b725b8a70be655b537f66f700fe0879d79a496891d37b07b5466c4b8b, + 0x1f9ba4e8bab7ce42c8ecc3d722aa2e0eadfdeb9cfdd347b5d8339ea7120858aa, + 0x1b233043052e8c288f7ee907a84e518aa38e82ac4502066db74056f865c5d3da, + 0x2431e1cc164bb8d074031ab72bd55b4c902053bfc0f14db0ca2f97b020875954, + 0x082f934c91f5aac330cd6953a0a7db45a13e322097583319a791f273965801fd, + 0x2b9a0a223e7538b0a34be074315542a3c77245e2ae7cbe999ad6bb930c48997c, + 0x0e1cd91edd2cfa2cceb85483b887a9be8164163e75a8a00eb0b589cc70214e7d, + 0x2e1eac0f2bfdfd63c951f61477e3698999774f19854d00f588d324601cebe2f9, + 0x0cbfa95f37fb74060c76158e769d6d157345784d8efdb33c23d748115b500b83, + 0x08f05b3be923ed44d65ad49d8a61e9a676d991e3a77513d9980c232dfa4a4f84, + 0x22719e2a070bcd0852bf8e21984d0443e7284925dc0758a325a2dd510c047ef6, + 0x041f596a9ee1cb2bc060f7fcc3a1ab4c7bdbf036119982c0f41f62b2f26830c0, + 0x233fd35de1be520a87628eb06f6b1d4c021be1c2d0dc464a19fcdd0986b10f89, + 0x0524b46d1aa87a5e4325e0a423ebc810d31e078aa1b4707eefcb453c61c9c267, + 0x2c34f424c81e5716ce47fcac894b85824227bb954b0f3199cc4486237c515211, + 0x0b5f2a4b63387819207effc2b5541fb72dd2025b5457cc97f33010327de4915e, + 0x22207856082ccc54c5b72fe439d2cfd6c17435d2f57af6ceaefac41fe05c659f, + 0x24d57a8bf5da63fe4e24159b7f8950b5cdfb210194caf79f27854048ce2c8171, + 0x0afab181fdd5e0583b371d75bd693f98374ad7097bb01a8573919bb23b79396e, + 0x2dba9b108f208772998a52efac7cbd5676c0057194c16c0bf16290d62b1128ee, + 0x26349b66edb8b16f56f881c788f53f83cbb83de0bd592b255aff13e6bce420b3, + 0x25af7ce0e5e10357685e95f92339753ad81a56d28ecc193b235288a3e6f137db, + 0x25b4ce7bd2294390c094d6a55edd68b970eed7aae88b2bff1f7c0187fe35011f, + 0x22c543f10f6c89ec387e53f1908a88e5de9cef28ebdf30b18cb9d54c1e02b631, + 0x0236f93e7789c4724fc7908a9f191e1e425e906a919d7a34df668e74882f87a9, + 0x29350b401166ca010e7d27e37d05da99652bdae114eb01659cb497af980c4b52, + 0x0eed787d65820d3f6bd31bbab547f75a65edb75d844ebb89ee1260916652363f, + 0x07cc1170f13b46f2036a753f520b3291fdcd0e99bd94297d1906f656f4de6fad, + 0x22b939233b1d7205f49bcf613a3d30b1908786d7f9f5d10c2059435689e8acea, + 0x01451762a0aab81c8aad1dc8bc33e870740f083a5aa85438add650ace60ae5a6, + 0x23506bb5d8727d4461fabf1025d46d1fe32eaa61dec7da57e704fec0892fce89, + 0x2e484c44e838aea0bac06ae3f71bdd092a3709531e1efea97f8bd68907355522, + 0x0f4bc7d07ebafd64379e78c50bd2e42baf4a594545cedc2545418da26835b54c, + 0x1f4d3c8f6583e9e5fa76637862faaee851582388725df460e620996d50d8e74e, + 0x093514e0c70711f82660d07be0e4a988fae02abc7b681d9153eb9bcb48fe7389, + 0x1adab0c8e2b3bad346699a2b5f3bc03643ee83ece47228f24a58e0a347e153d8, + 0x1672b1726057d99dd14709ebb474641a378c1b94b8072bac1a22dbef9e80dad2, + 0x1dfd53d4576af2e38f44f53fdcab468cc5d8e2fae0acc4ee30d47b239b479c14, + 0x0c6888a10b75b0f3a70a36263a37e17fe6d77d640f6fc3debc7f207753205c60, + 0x1addb933a65be77092b34a7e77d12fe8611a61e00ee6848b85091ecca9d1e508, + 0x00d7540dcd268a845c10ae18d1de933cf638ff5425f0afff7935628e299d1791, + 0x140c0e42687e9ead01b2827a5664ca9c26fedde4acd99db1d316939d20b82c0e, + 0x2f0c3a115d4317d191ba89b8d13d1806c20a0f9b24f8c5edc091e2ae56565984, + 0x0c4ee778ff7c14553006ed220cf9c81008a0cff670b22b82d8c538a1dc958c61, + 0x1704f2766d46f82c3693f00440ccc3609424ed26c0acc66227c3d7485de74c69, + 0x2f2d19cc3ea5d78ea7a02c1b51d244abf0769c9f8544e40239b66fe9009c3cfa, + 0x1ae03853b75fcaba5053f112e2a8e8dcdd7ee6cb9cfed9c7d6c766a806fc6629, + 0x0971aabf795241df51d131d0fa61aa5f3556921b2d6f014e4e41a86ddaf056d5, + 0x1408c316e6014e1a91d4cf6b6e0de73eda624f8380df1c875f5c29f7bfe2f646, + 0x1667f3fe2edbe850248abe42b543093b6c89f1f773ef285341691f39822ef5bd, + 0x13bf7c5d0d2c4376a48b0a03557cdf915b81718409e5c133424c69576500fe37, + 0x07620a6dfb0b6cec3016adf3d3533c24024b95347856b79719bc0ba743a62c2c, + 0x1574c7ef0c43545f36a8ca08bdbdd8b075d2959e2f322b731675de3e1982b4d0, + 0x269e4b5b7a2eb21afd567970a717ceec5bd4184571c254fdc06e03a7ff8378f0 + ], + [ + 0x0ee9a592ba9a9518d05986d656f40c2114c4993c11bb29938d21d47304cd8e6e, + 0x00f1445235f2148c5986587169fc1bcd887b08d4d00868df5696fff40956e864, + 0x08dff3487e8ac99e1f29a058d0fa80b930c728730b7ab36ce879f3890ecf73f5, + 0x2f27be690fdaee46c3ce28f7532b13c856c35342c84bda6e20966310fadc01d0, + 0x2b2ae1acf68b7b8d2416bebf3d4f6234b763fe04b8043ee48b8327bebca16cf2, + 0x0319d062072bef7ecca5eac06f97d4d55952c175ab6b03eae64b44c7dbf11cfa, + 0x28813dcaebaeaa828a376df87af4a63bc8b7bf27ad49c6298ef7b387bf28526d, + 0x2727673b2ccbc903f181bf38e1c1d40d2033865200c352bc150928adddf9cb78, + 0x234ec45ca27727c2e74abd2b2a1494cd6efbd43e340587d6b8fb9e31e65cc632, + 0x15b52534031ae18f7f862cb2cf7cf760ab10a8150a337b1ccd99ff6e8797d428, + 0x0dc8fad6d9e4b35f5ed9a3d186b79ce38e0e8a8d1b58b132d701d4eecf68d1f6, + 0x1bcd95ffc211fbca600f705fad3fb567ea4eb378f62e1fec97805518a47e4d9c, + 0x10520b0ab721cadfe9eff81b016fc34dc76da36c2578937817cb978d069de559, + 0x1f6d48149b8e7f7d9b257d8ed5fbbaf42932498075fed0ace88a9eb81f5627f6, + 0x1d9655f652309014d29e00ef35a2089bfff8dc1c816f0dc9ca34bdb5460c8705, + 0x04df5a56ff95bcafb051f7b1cd43a99ba731ff67e47032058fe3d4185697cc7d, + 0x0672d995f8fff640151b3d290cedaf148690a10a8c8424a7f6ec282b6e4be828, + 0x099952b414884454b21200d7ffafdd5f0c9a9dcc06f2708e9fc1d8209b5c75b9, + 0x052cba2255dfd00c7c483143ba8d469448e43586a9b4cd9183fd0e843a6b9fa6, + 0x0b8badee690adb8eb0bd74712b7999af82de55707251ad7716077cb93c464ddc, + 0x119b1590f13307af5a1ee651020c07c749c15d60683a8050b963d0a8e4b2bdd1, + 0x03150b7cd6d5d17b2529d36be0f67b832c4acfc884ef4ee5ce15be0bfb4a8d09, + 0x2cc6182c5e14546e3cf1951f173912355374efb83d80898abe69cb317c9ea565, + 0x005032551e6378c450cfe129a404b3764218cadedac14e2b92d2cd73111bf0f9, + 0x233237e3289baa34bb147e972ebcb9516469c399fcc069fb88f9da2cc28276b5, + 0x05c8f4f4ebd4a6e3c980d31674bfbe6323037f21b34ae5a4e80c2d4c24d60280, + 0x0a7b1db13042d396ba05d818a319f25252bcf35ef3aeed91ee1f09b2590fc65b, + 0x2a73b71f9b210cf5b14296572c9d32dbf156e2b086ff47dc5df542365a404ec0, + 0x1ac9b0417abcc9a1935107e9ffc91dc3ec18f2c4dbe7f22976a760bb5c50c460, + 0x12c0339ae08374823fabb076707ef479269f3e4d6cb104349015ee046dc93fc0, + 0x0b7475b102a165ad7f5b18db4e1e704f52900aa3253baac68246682e56e9a28e, + 0x037c2849e191ca3edb1c5e49f6e8b8917c843e379366f2ea32ab3aa88d7f8448, + 0x05a6811f8556f014e92674661e217e9bd5206c5c93a07dc145fdb176a716346f, + 0x29a795e7d98028946e947b75d54e9f044076e87a7b2883b47b675ef5f38bd66e, + 0x20439a0c84b322eb45a3857afc18f5826e8c7382c8a1585c507be199981fd22f, + 0x2e0ba8d94d9ecf4a94ec2050c7371ff1bb50f27799a84b6d4a2a6f2a0982c887, + 0x143fd115ce08fb27ca38eb7cce822b4517822cd2109048d2e6d0ddcca17d71c8, + 0x0c64cbecb1c734b857968dbbdcf813cdf8611659323dbcbfc84323623be9caf1, + 0x028a305847c683f646fca925c163ff5ae74f348d62c2b670f1426cef9403da53, + 0x2e4ef510ff0b6fda5fa940ab4c4380f26a6bcb64d89427b824d6755b5db9e30c, + 0x0081c95bc43384e663d79270c956ce3b8925b4f6d033b078b96384f50579400e, + 0x2ed5f0c91cbd9749187e2fade687e05ee2491b349c039a0bba8a9f4023a0bb38, + 0x30509991f88da3504bbf374ed5aae2f03448a22c76234c8c990f01f33a735206, + 0x1c3f20fd55409a53221b7c4d49a356b9f0a1119fb2067b41a7529094424ec6ad, + 0x10b4e7f3ab5df003049514459b6e18eec46bb2213e8e131e170887b47ddcb96c, + 0x2a1982979c3ff7f43ddd543d891c2abddd80f804c077d775039aa3502e43adef, + 0x1c74ee64f15e1db6feddbead56d6d55dba431ebc396c9af95cad0f1315bd5c91, + 0x07533ec850ba7f98eab9303cace01b4b9e4f2e8b82708cfa9c2fe45a0ae146a0, + 0x21576b438e500449a151e4eeaf17b154285c68f42d42c1808a11abf3764c0750, + 0x2f17c0559b8fe79608ad5ca193d62f10bce8384c815f0906743d6930836d4a9e, + 0x2d477e3862d07708a79e8aae946170bc9775a4201318474ae665b0b1b7e2730e, + 0x162f5243967064c390e095577984f291afba2266c38f5abcd89be0f5b2747eab, + 0x2b4cb233ede9ba48264ecd2c8ae50d1ad7a8596a87f29f8a7777a70092393311, + 0x2c8fbcb2dd8573dc1dbaf8f4622854776db2eece6d85c4cf4254e7c35e03b07a, + 0x1d6f347725e4816af2ff453f0cd56b199e1b61e9f601e9ade5e88db870949da9, + 0x204b0c397f4ebe71ebc2d8b3df5b913df9e6ac02b68d31324cd49af5c4565529, + 0x0c4cb9dc3c4fd8174f1149b3c63c3c2f9ecb827cd7dc25534ff8fb75bc79c502, + 0x174ad61a1448c899a25416474f4930301e5c49475279e0639a616ddc45bc7b54, + 0x1a96177bcf4d8d89f759df4ec2f3cde2eaaa28c177cc0fa13a9816d49a38d2ef, + 0x066d04b24331d71cd0ef8054bc60c4ff05202c126a233c1a8242ace360b8a30a, + 0x2a4c4fc6ec0b0cf52195782871c6dd3b381cc65f72e02ad527037a62aa1bd804, + 0x13ab2d136ccf37d447e9f2e14a7cedc95e727f8446f6d9d7e55afc01219fd649, + 0x1121552fca26061619d24d843dc82769c1b04fcec26f55194c2e3e869acc6a9a, + 0x00ef653322b13d6c889bc81715c37d77a6cd267d595c4a8909a5546c7c97cff1, + 0x0e25483e45a665208b261d8ba74051e6400c776d652595d9845aca35d8a397d3, + 0x29f536dcb9dd7682245264659e15d88e395ac3d4dde92d8c46448db979eeba89, + 0x2a56ef9f2c53febadfda33575dbdbd885a124e2780bbea170e456baace0fa5be, + 0x1c8361c78eb5cf5decfb7a2d17b5c409f2ae2999a46762e8ee416240a8cb9af1, + 0x151aff5f38b20a0fc0473089aaf0206b83e8e68a764507bfd3d0ab4be74319c5, + 0x04c6187e41ed881dc1b239c88f7f9d43a9f52fc8c8b6cdd1e76e47615b51f100, + 0x13b37bd80f4d27fb10d84331f6fb6d534b81c61ed15776449e801b7ddc9c2967, + 0x01a5c536273c2d9df578bfbd32c17b7a2ce3664c2a52032c9321ceb1c4e8a8e4, + 0x2ab3561834ca73835ad05f5d7acb950b4a9a2c666b9726da832239065b7c3b02, + 0x1d4d8ec291e720db200fe6d686c0d613acaf6af4e95d3bf69f7ed516a597b646, + 0x041294d2cc484d228f5784fe7919fd2bb925351240a04b711514c9c80b65af1d, + 0x154ac98e01708c611c4fa715991f004898f57939d126e392042971dd90e81fc6, + 0x0b339d8acca7d4f83eedd84093aef51050b3684c88f8b0b04524563bc6ea4da4, + 0x0955e49e6610c94254a4f84cfbab344598f0e71eaff4a7dd81ed95b50839c82e, + 0x06746a6156eba54426b9e22206f15abca9a6f41e6f535c6f3525401ea0654626, + 0x0f18f5a0ecd1423c496f3820c549c27838e5790e2bd0a196ac917c7ff32077fb, + 0x04f6eeca1751f7308ac59eff5beb261e4bb563583ede7bc92a738223d6f76e13, + 0x2b56973364c4c4f5c1a3ec4da3cdce038811eb116fb3e45bc1768d26fc0b3758, + 0x123769dd49d5b054dcd76b89804b1bcb8e1392b385716a5d83feb65d437f29ef, + 0x2147b424fc48c80a88ee52b91169aacea989f6446471150994257b2fb01c63e9, + 0x0fdc1f58548b85701a6c5505ea332a29647e6f34ad4243c2ea54ad897cebe54d, + 0x12373a8251fea004df68abcf0f7786d4bceff28c5dbbe0c3944f685cc0a0b1f2, + 0x21e4f4ea5f35f85bad7ea52ff742c9e8a642756b6af44203dd8a1f35c1a90035, + 0x16243916d69d2ca3dfb4722224d4c462b57366492f45e90d8a81934f1bc3b147, + 0x1efbe46dd7a578b4f66f9adbc88b4378abc21566e1a0453ca13a4159cac04ac2, + 0x07ea5e8537cf5dd08886020e23a7f387d468d5525be66f853b672cc96a88969a, + 0x05a8c4f9968b8aa3b7b478a30f9a5b63650f19a75e7ce11ca9fe16c0b76c00bc, + 0x20f057712cc21654fbfe59bd345e8dac3f7818c701b9c7882d9d57b72a32e83f, + 0x04a12ededa9dfd689672f8c67fee31636dcd8e88d01d49019bd90b33eb33db69, + 0x27e88d8c15f37dcee44f1e5425a51decbd136ce5091a6767e49ec9544ccd101a, + 0x2feed17b84285ed9b8a5c8c5e95a41f66e096619a7703223176c41ee433de4d1, + 0x1ed7cc76edf45c7c404241420f729cf394e5942911312a0d6972b8bd53aff2b8, + 0x15742e99b9bfa323157ff8c586f5660eac6783476144cdcadf2874be45466b1a, + 0x1aac285387f65e82c895fc6887ddf40577107454c6ec0317284f033f27d0c785, + 0x25851c3c845d4790f9ddadbdb6057357832e2e7a49775f71ec75a96554d67c77, + 0x15a5821565cc2ec2ce78457db197edf353b7ebba2c5523370ddccc3d9f146a67, + 0x2411d57a4813b9980efa7e31a1db5966dcf64f36044277502f15485f28c71727, + 0x002e6f8d6520cd4713e335b8c0b6d2e647e9a98e12f4cd2558828b5ef6cb4c9b, + 0x2ff7bc8f4380cde997da00b616b0fcd1af8f0e91e2fe1ed7398834609e0315d2, + 0x00b9831b948525595ee02724471bcd182e9521f6b7bb68f1e93be4febb0d3cbe, + 0x0a2f53768b8ebf6a86913b0e57c04e011ca408648a4743a87d77adbf0c9c3512, + 0x00248156142fd0373a479f91ff239e960f599ff7e94be69b7f2a290305e1198d, + 0x171d5620b87bfb1328cf8c02ab3f0c9a397196aa6a542c2350eb512a2b2bcda9, + 0x170a4f55536f7dc970087c7c10d6fad760c952172dd54dd99d1045e4ec34a808, + 0x29aba33f799fe66c2ef3134aea04336ecc37e38c1cd211ba482eca17e2dbfae1, + 0x1e9bc179a4fdd758fdd1bb1945088d47e70d114a03f6a0e8b5ba650369e64973, + 0x1dd269799b660fad58f7f4892dfb0b5afeaad869a9c4b44f9c9e1c43bdaf8f09, + 0x22cdbc8b70117ad1401181d02e15459e7ccd426fe869c7c95d1dd2cb0f24af38, + 0x0ef042e454771c533a9f57a55c503fcefd3150f52ed94a7cd5ba93b9c7dacefd, + 0x11609e06ad6c8fe2f287f3036037e8851318e8b08a0359a03b304ffca62e8284, + 0x1166d9e554616dba9e753eea427c17b7fecd58c076dfe42708b08f5b783aa9af, + 0x2de52989431a859593413026354413db177fbf4cd2ac0b56f855a888357ee466, + 0x3006eb4ffc7a85819a6da492f3a8ac1df51aee5b17b8e89d74bf01cf5f71e9ad, + 0x2af41fbb61ba8a80fdcf6fff9e3f6f422993fe8f0a4639f962344c8225145086, + 0x119e684de476155fe5a6b41a8ebc85db8718ab27889e85e781b214bace4827c3, + 0x1835b786e2e8925e188bea59ae363537b51248c23828f047cff784b97b3fd800, + 0x28201a34c594dfa34d794996c6433a20d152bac2a7905c926c40e285ab32eeb6, + 0x083efd7a27d1751094e80fefaf78b000864c82eb571187724a761f88c22cc4e7, + 0x0b6f88a3577199526158e61ceea27be811c16df7774dd8519e079564f61fd13b, + 0x0ec868e6d15e51d9644f66e1d6471a94589511ca00d29e1014390e6ee4254f5b, + 0x2af33e3f866771271ac0c9b3ed2e1142ecd3e74b939cd40d00d937ab84c98591, + 0x0b520211f904b5e7d09b5d961c6ace7734568c547dd6858b364ce5e47951f178, + 0x0b2d722d0919a1aad8db58f10062a92ea0c56ac4270e822cca228620188a1d40, + 0x1f790d4d7f8cf094d980ceb37c2453e957b54a9991ca38bbe0061d1ed6e562d4, + 0x0171eb95dfbf7d1eaea97cd385f780150885c16235a2a6a8da92ceb01e504233, + 0x0c2d0e3b5fd57549329bf6885da66b9b790b40defd2c8650762305381b168873, + 0x1162fb28689c27154e5a8228b4e72b377cbcafa589e283c35d3803054407a18d, + 0x2f1459b65dee441b64ad386a91e8310f282c5a92a89e19921623ef8249711bc0, + 0x1e6ff3216b688c3d996d74367d5cd4c1bc489d46754eb712c243f70d1b53cfbb, + 0x01ca8be73832b8d0681487d27d157802d741a6f36cdc2a0576881f9326478875, + 0x1f7735706ffe9fc586f976d5bdf223dc680286080b10cea00b9b5de315f9650e, + 0x2522b60f4ea3307640a0c2dce041fba921ac10a3d5f096ef4745ca838285f019, + 0x23f0bee001b1029d5255075ddc957f833418cad4f52b6c3f8ce16c235572575b, + 0x2bc1ae8b8ddbb81fcaac2d44555ed5685d142633e9df905f66d9401093082d59, + 0x0f9406b8296564a37304507b8dba3ed162371273a07b1fc98011fcd6ad72205f, + 0x2360a8eb0cc7defa67b72998de90714e17e75b174a52ee4acb126c8cd995f0a8, + 0x15871a5cddead976804c803cbaef255eb4815a5e96df8b006dcbbc2767f88948, + 0x193a56766998ee9e0a8652dd2f3b1da0362f4f54f72379544f957ccdeefb420f, + 0x2a394a43934f86982f9be56ff4fab1703b2e63c8ad334834e4309805e777ae0f, + 0x1859954cfeb8695f3e8b635dcb345192892cd11223443ba7b4166e8876c0d142, + 0x04e1181763050e58013444dbcb99f1902b11bc25d90bbdca408d3819f4fed32b, + 0x0fdb253dee83869d40c335ea64de8c5bb10eb82db08b5e8b1f5e5552bfd05f23, + 0x058cbe8a9a5027bdaa4efb623adead6275f08686f1c08984a9d7c5bae9b4f1c0, + 0x1382edce9971e186497eadb1aeb1f52b23b4b83bef023ab0d15228b4cceca59a, + 0x03464990f045c6ee0819ca51fd11b0be7f61b8eb99f14b77e1e6634601d9e8b5, + 0x23f7bfc8720dc296fff33b41f98ff83c6fcab4605db2eb5aaa5bc137aeb70a58, + 0x0a59a158e3eec2117e6e94e7f0e9decf18c3ffd5e1531a9219636158bbaf62f2, + 0x06ec54c80381c052b58bf23b312ffd3ce2c4eba065420af8f4c23ed0075fd07b, + 0x118872dc832e0eb5476b56648e867ec8b09340f7a7bcb1b4962f0ff9ed1f9d01, + 0x13d69fa127d834165ad5c7cba7ad59ed52e0b0f0e42d7fea95e1906b520921b1, + 0x169a177f63ea681270b1c6877a73d21bde143942fb71dc55fd8a49f19f10c77b, + 0x04ef51591c6ead97ef42f287adce40d93abeb032b922f66ffb7e9a5a7450544d, + 0x256e175a1dc079390ecd7ca703fb2e3b19ec61805d4f03ced5f45ee6dd0f69ec, + 0x30102d28636abd5fe5f2af412ff6004f75cc360d3205dd2da002813d3e2ceeb2, + 0x10998e42dfcd3bbf1c0714bc73eb1bf40443a3fa99bef4a31fd31be182fcc792, + 0x193edd8e9fcf3d7625fa7d24b598a1d89f3362eaf4d582efecad76f879e36860, + 0x18168afd34f2d915d0368ce80b7b3347d1c7a561ce611425f2664d7aa51f0b5d, + 0x29383c01ebd3b6ab0c017656ebe658b6a328ec77bc33626e29e2e95b33ea6111, + 0x10646d2f2603de39a1f4ae5e7771a64a702db6e86fb76ab600bf573f9010c711, + 0x0beb5e07d1b27145f575f1395a55bf132f90c25b40da7b3864d0242dcb1117fb, + 0x16d685252078c133dc0d3ecad62b5c8830f95bb2e54b59abdffbf018d96fa336, + 0x0a6abd1d833938f33c74154e0404b4b40a555bbbec21ddfafd672dd62047f01a, + 0x1a679f5d36eb7b5c8ea12a4c2dedc8feb12dffeec450317270a6f19b34cf1860, + 0x0980fb233bd456c23974d50e0ebfde4726a423eada4e8f6ffbc7592e3f1b93d6, + 0x161b42232e61b84cbf1810af93a38fc0cece3d5628c9282003ebacb5c312c72b, + 0x0ada10a90c7f0520950f7d47a60d5e6a493f09787f1564e5d09203db47de1a0b, + 0x1a730d372310ba82320345a29ac4238ed3f07a8a2b4e121bb50ddb9af407f451, + 0x2c8120f268ef054f817064c369dda7ea908377feaba5c4dffbda10ef58e8c556, + 0x1c7c8824f758753fa57c00789c684217b930e95313bcb73e6e7b8649a4968f70, + 0x2cd9ed31f5f8691c8e39e4077a74faa0f400ad8b491eb3f7b47b27fa3fd1cf77, + 0x23ff4f9d46813457cf60d92f57618399a5e022ac321ca550854ae23918a22eea, + 0x09945a5d147a4f66ceece6405dddd9d0af5a2c5103529407dff1ea58f180426d, + 0x188d9c528025d4c2b67660c6b771b90f7c7da6eaa29d3f268a6dd223ec6fc630, + 0x3050e37996596b7f81f68311431d8734dba7d926d3633595e0c0d8ddf4f0f47f, + 0x15af1169396830a91600ca8102c35c426ceae5461e3f95d89d829518d30afd78, + 0x1da6d09885432ea9a06d9f37f873d985dae933e351466b2904284da3320d8acc, + 0x2796ea90d269af29f5f8acf33921124e4e4fad3dbe658945e546ee411ddaa9cb, + 0x202d7dd1da0f6b4b0325c8b3307742f01e15612ec8e9304a7cb0319e01d32d60, + 0x096d6790d05bb759156a952ba263d672a2d7f9c788f4c831a29dace4c0f8be5f, + 0x054efa1f65b0fce283808965275d877b438da23ce5b13e1963798cb1447d25a4, + 0x1b162f83d917e93edb3308c29802deb9d8aa690113b2e14864ccf6e18e4165f1, + 0x21e5241e12564dd6fd9f1cdd2a0de39eedfefc1466cc568ec5ceb745a0506edc, + 0x1cfb5662e8cf5ac9226a80ee17b36abecb73ab5f87e161927b4349e10e4bdf08, + 0x0f21177e302a771bbae6d8d1ecb373b62c99af346220ac0129c53f666eb24100, + 0x1671522374606992affb0dd7f71b12bec4236aede6290546bcef7e1f515c2320, + 0x0fa3ec5b9488259c2eb4cf24501bfad9be2ec9e42c5cc8ccd419d2a692cad870, + 0x193c0e04e0bd298357cb266c1506080ed36edce85c648cc085e8c57b1ab54bba, + 0x102adf8ef74735a27e9128306dcbc3c99f6f7291cd406578ce14ea2adaba68f8, + 0x0fe0af7858e49859e2a54d6f1ad945b1316aa24bfbdd23ae40a6d0cb70c3eab1, + 0x216f6717bbc7dedb08536a2220843f4e2da5f1daa9ebdefde8a5ea7344798d22, + 0x1da55cc900f0d21f4a3e694391918a1b3c23b2ac773c6b3ef88e2e4228325161 + ], + [ + 0x19b849f69450b06848da1d39bd5e4a4302bb86744edc26238b0878e269ed23e5, + 0x265ddfe127dd51bd7239347b758f0a1320eb2cc7450acc1dad47f80c8dcf34d6, + 0x199750ec472f1809e0f66a545e1e51624108ac845015c2aa3dfc36bab497d8aa, + 0x157ff3fe65ac7208110f06a5f74302b14d743ea25067f0ffd032f787c7f1cdf8, + 0x2e49c43c4569dd9c5fd35ac45fca33f10b15c590692f8beefe18f4896ac94902, + 0x0e35fb89981890520d4aef2b6d6506c3cb2f0b6973c24fa82731345ffa2d1f1e, + 0x251ad47cb15c4f1105f109ae5e944f1ba9d9e7806d667ffec6fe723002e0b996, + 0x13da07dc64d428369873e97160234641f8beb56fdd05e5f3563fa39d9c22df4e, + 0x0c009b84e650e6d23dc00c7dccef7483a553939689d350cd46e7b89055fd4738, + 0x011f16b1c63a854f01992e3956f42d8b04eb650c6d535eb0203dec74befdca06, + 0x0ed69e5e383a688f209d9a561daa79612f3f78d0467ad45485df07093f367549, + 0x04dba94a7b0ce9e221acad41472b6bbe3aec507f5eb3d33f463672264c9f789b, + 0x0a3f2637d840f3a16eb094271c9d237b6036757d4bb50bf7ce732ff1d4fa28e8, + 0x259a666f129eea198f8a1c502fdb38fa39b1f075569564b6e54a485d1182323f, + 0x28bf7459c9b2f4c6d8e7d06a4ee3a47f7745d4271038e5157a32fdf7ede0d6a1, + 0x0a1ca941f057037526ea200f489be8d4c37c85bbcce6a2aeec91bd6941432447, + 0x0c6f8f958be0e93053d7fd4fc54512855535ed1539f051dcb43a26fd926361cf, + 0x123106a93cd17578d426e8128ac9d90aa9e8a00708e296e084dd57e69caaf811, + 0x26e1ba52ad9285d97dd3ab52f8e840085e8fa83ff1e8f1877b074867cd2dee75, + 0x1cb55cad7bd133de18a64c5c47b9c97cbe4d8b7bf9e095864471537e6a4ae2c5, + 0x1dcd73e46acd8f8e0e2c7ce04bde7f6d2a53043d5060a41c7143f08e6e9055d0, + 0x011003e32f6d9c66f5852f05474a4def0cda294a0eb4e9b9b12b9bb4512e5574, + 0x2b1e809ac1d10ab29ad5f20d03a57dfebadfe5903f58bafed7c508dd2287ae8c, + 0x2539de1785b735999fb4dac35ee17ed0ef995d05ab2fc5faeaa69ae87bcec0a5, + 0x0c246c5a2ef8ee0126497f222b3e0a0ef4e1c3d41c86d46e43982cb11d77951d, + 0x192089c4974f68e95408148f7c0632edbb09e6a6ad1a1c2f3f0305f5d03b527b, + 0x1eae0ad8ab68b2f06a0ee36eeb0d0c058529097d91096b756d8fdc2fb5a60d85, + 0x179190e5d0e22179e46f8282872abc88db6e2fdc0dee99e69768bd98c5d06bfb, + 0x29bb9e2c9076732576e9a81c7ac4b83214528f7db00f31bf6cafe794a9b3cd1c, + 0x225d394e42207599403efd0c2464a90d52652645882aac35b10e590e6e691e08, + 0x064760623c25c8cf753d238055b444532be13557451c087de09efd454b23fd59, + 0x10ba3a0e01df92e87f301c4b716d8a394d67f4bf42a75c10922910a78f6b5b87, + 0x0e070bf53f8451b24f9c6e96b0c2a801cb511bc0c242eb9d361b77693f21471c, + 0x1b94cd61b051b04dd39755ff93821a73ccd6cb11d2491d8aa7f921014de252fb, + 0x1d7cb39bafb8c744e148787a2e70230f9d4e917d5713bb050487b5aa7d74070b, + 0x2ec93189bd1ab4f69117d0fe980c80ff8785c2961829f701bb74ac1f303b17db, + 0x2db366bfdd36d277a692bb825b86275beac404a19ae07a9082ea46bd83517926, + 0x062100eb485db06269655cf186a68532985275428450359adc99cec6960711b8, + 0x0761d33c66614aaa570e7f1e8244ca1120243f92fa59e4f900c567bf41f5a59b, + 0x20fc411a114d13992c2705aa034e3f315d78608a0f7de4ccf7a72e494855ad0d, + 0x25b5c004a4bdfcb5add9ec4e9ab219ba102c67e8b3effb5fc3a30f317250bc5a, + 0x23b1822d278ed632a494e58f6df6f5ed038b186d8474155ad87e7dff62b37f4b, + 0x22734b4c5c3f9493606c4ba9012499bf0f14d13bfcfcccaa16102a29cc2f69e0, + 0x26c0c8fe09eb30b7e27a74dc33492347e5bdff409aa3610254413d3fad795ce5, + 0x070dd0ccb6bd7bbae88eac03fa1fbb26196be3083a809829bbd626df348ccad9, + 0x12b6595bdb329b6fb043ba78bb28c3bec2c0a6de46d8c5ad6067c4ebfd4250da, + 0x248d97d7f76283d63bec30e7a5876c11c06fca9b275c671c5e33d95bb7e8d729, + 0x1a306d439d463b0816fc6fd64cc939318b45eb759ddde4aa106d15d9bd9baaaa, + 0x28a8f8372e3c38daced7c00421cb4621f4f1b54ddc27821b0d62d3d6ec7c56cf, + 0x0094975717f9a8a8bb35152f24d43294071ce320c829f388bc852183e1e2ce7e, + 0x04d5ee4c3aa78f7d80fde60d716480d3593f74d4f653ae83f4103246db2e8d65, + 0x2a6cf5e9aa03d4336349ad6fb8ed2269c7bef54b8822cc76d08495c12efde187, + 0x2304d31eaab960ba9274da43e19ddeb7f792180808fd6e43baae48d7efcba3f3, + 0x03fd9ac865a4b2a6d5e7009785817249bff08a7e0726fcb4e1c11d39d199f0b0, + 0x00b7258ded52bbda2248404d55ee5044798afc3a209193073f7954d4d63b0b64, + 0x159f81ada0771799ec38fca2d4bf65ebb13d3a74f3298db36272c5ca65e92d9a, + 0x1ef90e67437fbc8550237a75bc28e3bb9000130ea25f0c5471e144cf4264431f, + 0x1e65f838515e5ff0196b49aa41a2d2568df739bc176b08ec95a79ed82932e30d, + 0x2b1b045def3a166cec6ce768d079ba74b18c844e570e1f826575c1068c94c33f, + 0x0832e5753ceb0ff6402543b1109229c165dc2d73bef715e3f1c6e07c168bb173, + 0x02f614e9cedfb3dc6b762ae0a37d41bab1b841c2e8b6451bc5a8e3c390b6ad16, + 0x0e2427d38bd46a60dd640b8e362cad967370ebb777bedff40f6a0be27e7ed705, + 0x0493630b7c670b6deb7c84d414e7ce79049f0ec098c3c7c50768bbe29214a53a, + 0x22ead100e8e482674decdab17066c5a26bb1515355d5461a3dc06cc85327cea9, + 0x25b3e56e655b42cdaae2626ed2554d48583f1ae35626d04de5084e0b6d2a6f16, + 0x1e32752ada8836ef5837a6cde8ff13dbb599c336349e4c584b4fdc0a0cf6f9d0, + 0x2fa2a871c15a387cc50f68f6f3c3455b23c00995f05078f672a9864074d412e5, + 0x2f569b8a9a4424c9278e1db7311e889f54ccbf10661bab7fcd18e7c7a7d83505, + 0x044cb455110a8fdd531ade530234c518a7df93f7332ffd2144165374b246b43d, + 0x227808de93906d5d420246157f2e42b191fe8c90adfe118178ddc723a5319025, + 0x02fcca2934e046bc623adead873579865d03781ae090ad4a8579d2e7a6800355, + 0x0ef915f0ac120b876abccceb344a1d36bad3f3c5ab91a8ddcbec2e060d8befac, + 0x1797130f4b7a3e1777eb757bc6f287f6ab0fb85f6be63b09f3b16ef2b1405d38, + 0x0a76225dc04170ae3306c85abab59e608c7f497c20156d4d36c668555decc6e5, + 0x1fffb9ec1992d66ba1e77a7b93209af6f8fa76d48acb664796174b5326a31a5c, + 0x25721c4fc15a3f2853b57c338fa538d85f8fbba6c6b9c6090611889b797b9c5f, + 0x0c817fd42d5f7a41215e3d07ba197216adb4c3790705da95eb63b982bfcaf75a, + 0x13abe3f5239915d39f7e13c2c24970b6df8cf86ce00a22002bc15866e52b5a96, + 0x2106feea546224ea12ef7f39987a46c85c1bc3dc29bdbd7a92cd60acb4d391ce, + 0x21ca859468a746b6aaa79474a37dab49f1ca5a28c748bc7157e1b3345bb0f959, + 0x05ccd6255c1e6f0c5cf1f0df934194c62911d14d0321662a8f1a48999e34185b, + 0x0f0e34a64b70a626e464d846674c4c8816c4fb267fe44fe6ea28678cb09490a4, + 0x0558531a4e25470c6157794ca36d0e9647dbfcfe350d64838f5b1a8a2de0d4bf, + 0x09d3dca9173ed2faceea125157683d18924cadad3f655a60b72f5864961f1455, + 0x0328cbd54e8c0913493f866ed03d218bf23f92d68aaec48617d4c722e5bd4335, + 0x2bf07216e2aff0a223a487b1a7094e07e79e7bcc9798c648ee3347dd5329d34b, + 0x1daf345a58006b736499c583cb76c316d6f78ed6a6dffc82111e11a63fe412df, + 0x176563472456aaa746b694c60e1823611ef39039b2edc7ff391e6f2293d2c404, + 0x2ef1e0fad9f08e87a3bb5e47d7e33538ca964d2b7d1083d4fb0225035bd3f8db, + 0x226c9b1af95babcf17b2b1f57c7310179c1803dec5ae8f0a1779ed36c817ae2a, + 0x14bce3549cc3db7428126b4c3a15ae0ff8148c89f13fb35d35734eb5d4ad0def, + 0x2debff156e276bb5742c3373f2635b48b8e923d301f372f8e550cfd4034212c7, + 0x2d4083cf5a87f5b6fc2395b22e356b6441afe1b6b29c47add7d0432d1d4760c7, + 0x0c225b7bcd04bf9c34b911262fdc9c1b91bf79a10c0184d89c317c53d7161c29, + 0x03152169d4f3d06ec33a79bfac91a02c99aa0200db66d5aa7b835265f9c9c8f3, + 0x0b61811a9210be78b05974587486d58bddc8f51bfdfebbb87afe8b7aa7d3199c, + 0x203e000cad298daaf7eba6a5c5921878b8ae48acf7048f16046d637a533b6f78, + 0x1a44bf0937c722d1376672b69f6c9655ba7ee386fda1112c0757143d1bfa9146, + 0x0376b4fae08cb03d3500afec1a1f56acb8e0fde75a2106d7002f59c5611d4daa, + 0x00780af2ca1cad6465a2171250fdfc32d6fc241d3214177f3d553ef363182185, + 0x10774d9ab80c25bdeb808bedfd72a8d9b75dbe18d5221c87e9d857079bdc31d5, + 0x10dc6e9c006ea38b04b1e03b4bd9490c0d03f98929ca1d7fb56821fd19d3b6e8, + 0x00544b8338791518b2c7645a50392798b21f75bb60e3596170067d00141cac16, + 0x222c01175718386f2e2e82eb122789e352e105a3b8fa852613bc534433ee428c, + 0x2840d045e9bc22b259cfb8811b1e0f45b77f7bdb7f7e2b46151a1430f608e3c5, + 0x062752f86eebe11a009c937e468c335b04554574c2990196508e01fa5860186b, + 0x06041bdac48205ac87adb87c20a478a71c9950c12a80bc0a55a8e83eaaf04746, + 0x04a533f236c422d1ff900a368949b0022c7a2ae092f308d82b1dcbbf51f5000d, + 0x13e31d7a67232fd811d6a955b3d4f25dfe066d1e7dc33df04bde50a2b2d05b2a, + 0x011c2683ae91eb4dfbc13d6357e8599a9279d1648ff2c95d2f79905bb13920f1, + 0x0b0d219346b8574525b1a270e0b4cba5d56c928e3e2c2bd0a1ecaed015aaf6ae, + 0x14abdec8db9c6dc970291ee638690209b65080781ef9fd13d84c7a726b5f1364, + 0x1a0b70b4b26fdc28fcd32aa3d266478801eb12202ef47ced988d0376610be106, + 0x278543721f96d1307b6943f9804e7fe56401deb2ef99c4d12704882e7278b607, + 0x16eb59494a9776cf57866214dbd1473f3f0738a325638d8ba36535e011d58259, + 0x2567a658a81ffb444f240088fa5524c69a9e53eeab6b7f8c41c3479dcf8c644a, + 0x29aa1d7c151e9ad0a7ab39f1abd9cf77ab78e0215a5715a6b882ade840bb13d8, + 0x15c091233e60efe0d4bbfce2b36415006a4f017f9a85388ce206b91f99f2c984, + 0x16bd7d22ff858e5e0882c2c999558d77e7673ad5f1915f9feb679a8115f014cf, + 0x02db50480a07be0eb2c2e13ed6ef4074c0182d9b668b8e08ffe6769250042025, + 0x05e4a220e6a3bc9f7b6806ec9d6cdba186330ef2bf7adb4c13ba866343b73119, + 0x1dda05ebc30170bc98cbf2a5ee3b50e8b5f70bc424d39fa4104d37f1cbcf7a42, + 0x0184bef721888187f645b6fee3667f3c91da214414d89ba5cd301f22b0de8990, + 0x1498a307e68900065f5e8276f62aef1c37414b84494e1577ad1a6d64341b78ec, + 0x25f40f82b31dacc4f4939800b9d2c3eacef737b8fab1f864fe33548ad46bd49d, + 0x09d317cc670251943f6f5862a30d2ea9e83056ce4907bfbbcb1ff31ce5bb9650, + 0x2f77d77786d979b23ba4ce4a4c1b3bd0a41132cd467a86ab29b913b6cf3149d0, + 0x0f53dafd535a9f4473dc266b6fccc6841bbd336963f254c152f89e785f729bbf, + 0x25c1fd72e223045265c3a099e17526fa0e6976e1c00baf16de96de85deef2fa2, + 0x2a902c8980c17faae368d385d52d16be41af95c84eaea3cf893e65d6ce4a8f62, + 0x1ce1580a3452ecf302878c8976b82be96676dd114d1dc8d25527405762f83529, + 0x24a6073f91addc33a49a1fa306df008801c5ec569609034d2fc50f7f0f4d0056, + 0x25e52dbd6124530d9fc27fe306d71d4583e07ca554b5d1577f256c68b0be2b74, + 0x23dffae3c423fa7a93468dbccfb029855974be4d0a7b29946796e5b6cd70f15d, + 0x06342da370cc0d8c49b77594f6b027c480615d50be36243a99591bc9924ed6f5, + 0x2754114281286546b75f09f115fc751b4778303d0405c1b4cc7df0d8e9f63925, + 0x15c19e8534c5c1a8862c2bc1d119eddeabf214153833d7bdb59ee197f8187cf5, + 0x265fe062766d08fab4c78d0d9ef3cabe366f3be0a821061679b4b3d2d77d5f3e, + 0x13ccf689d67a3ec9f22cb7cd0ac3a327d377ac5cd0146f048debfd098d3ec7be, + 0x17662f7456789739f81cd3974827a887d92a5e05bdf3fe6b9fbccca4524aaebd, + 0x21b29c76329b31c8ef18631e515f7f2f82ca6a5cca70cee4e809fd624be7ad5d, + 0x18137478382aadba441eb97fe27901989c06738165215319939eb17b01fa975c, + 0x2bc07ea2bfad68e8dc724f5fef2b37c2d34f761935ffd3b739ceec4668f37e88, + 0x2ddb2e376f54d64a563840480df993feb4173203c2bd94ad0e602077aef9a03e, + 0x277eb50f2baa706106b41cb24c602609e8a20f8d72f613708adb25373596c3f7, + 0x0d4de47e1aba34269d0c620904f01a56b33fc4b450c0db50bb7f87734c9a1fe5, + 0x0b8442bfe9e4a1b4428673b6bd3eea6f9f445697058f134aae908d0279a29f0c, + 0x11fe5b18fbbea1a86e06930cb89f7d4a26e186a65945e96574247fddb720f8f5, + 0x224026f6dfaf71e24d25d8f6d9f90021df5b774dcad4d883170e4ad89c33a0d6, + 0x0b2ca6a999fe6887e0704dad58d03465a96bc9e37d1091f61bc9f9c62bbeb824, + 0x221b63d66f0b45f9d40c54053a28a06b1d0a4ce41d364797a1a7e0c96529f421, + 0x30185c48b7b2f1d53d4120801b047d087493bce64d4d24aedce2f4836bb84ad4, + 0x23f5d372a3f0e3cba989e223056227d3533356f0faa48f27f8267318632a61f0, + 0x2716683b32c755fd1bf8235ea162b1f388e1e0090d06162e8e6dfbe4328f3e3b, + 0x0977545836866fa204ca1d853ec0909e3d140770c80ac67dc930c69748d5d4bc, + 0x1444e8f592bdbfd8025d91ab4982dd425f51682d31472b05e81c43c0f9434b31, + 0x26e04b65e9ca8270beb74a1c5cb8fee8be3ffbfe583f7012a00f874e7718fbe3, + 0x22a5c2fa860d11fe34ee47a5cd9f869800f48f4febe29ad6df69816fb1a914d2, + 0x174b54d9907d8f5c6afd672a738f42737ec338f3a0964c629f7474dd44c5c8d7, + 0x1db1db8aa45283f31168fa66694cf2808d2189b87c8c8143d56c871907b39b87, + 0x1530bf0f46527e889030b8c7b7dfde126f65faf8cce0ab66387341d813d1bfd1, + 0x0b73f613993229f59f01c1cec8760e9936ead9edc8f2814889330a2f2bade457, + 0x29c25a22fe2164604552aaea377f448d587ab977fc8227787bd2dc0f36bcf41e, + 0x2b30d53ed1759bfb8503da66c92cf4077abe82795dc272b377df57d77c875526, + 0x12f6d703b5702aab7b7b7e69359d53a2756c08c85ede7227cf5f0a2916787cd2, + 0x2520e18300afda3f61a40a0b8837293a55ad01071028d4841ffa9ac706364113, + 0x1ec9daea860971ecdda8ed4f346fa967ac9bc59278277393c68f09fa03b8b95f, + 0x0a99b3e178db2e2e432f5cd5bef8fe4483bf5cbf70ed407c08aae24b830ad725, + 0x07cda9e63db6e39f086b89b601c2bbe407ee0abac3c817a1317abad7c5778492, + 0x08c9c65a4f955e8952d571b191bb0adb49bd8290963203b35d48aab38f8fc3a3, + 0x2737f8ce1d5a67b349590ddbfbd709ed9af54a2a3f2719d33801c9c17bdd9c9e, + 0x1049a6c65ff019f0d28770072798e8b7909432bd0c129813a9f179ba627f7d6a, + 0x18b4fe968732c462c0ea5a9beb27cecbde8868944fdf64ee60a5122361daeddb, + 0x2ff2b6fd22df49d2440b2eaeeefa8c02a6f478cfcf11f1b2a4f7473483885d19, + 0x2ec5f2f1928fe932e56c789b8f6bbcb3e8be4057cbd8dbd18a1b352f5cef42ff, + 0x265a5eccd8b92975e33ad9f75bf3426d424a4c6a7794ee3f08c1d100378e545e, + 0x2405eaa4c0bde1129d6242bb5ada0e68778e656cfcb366bf20517da1dfd4279c, + 0x094c97d8c194c42e88018004cbbf2bc5fdb51955d8b2d66b76dd98a2dbf60417, + 0x2c30d5f33bb32c5c22b9979a605bf64d508b705221e6a686330c9625c2afe0b8, + 0x01a75666f6241f6825d01cc6dcb1622d4886ea583e87299e6aa2fc716fdb6cf5, + 0x0a3290e8398113ea4d12ac091e87be7c6d359ab9a66979fcf47bf2e87d382fcb, + 0x154ade9ca36e268dfeb38461425bb0d8c31219d8fa0dfc75ecd21bf69aa0cc74, + 0x27aa8d3e25380c0b1b172d79c6f22eee99231ef5dc69d8dc13a4b5095d028772, + 0x2cf4051e6cab48301a8b2e3bca6099d756bbdf485afa1f549d395bbcbd806461, + 0x301e70f729f3c94b1d3f517ddff9f2015131feab8afa5eebb0843d7f84b23e71, + 0x298beb64f812d25d8b4d9620347ab02332dc4cef113ae60d17a8d7a4c91f83bc, + 0x1b362e72a5f847f84d03fd291c3c471ed1c14a15b221680acf11a3f02e46aa95, + 0x0dc8a2146110c0b375432902999223d5aa1ef6e78e1e5ebcbc1d9ba41dc1c737, + 0x0a48663b34ce5e1c05dc93092cb69778cb21729a72ddc03a08afa1eb922ff279, + 0x0a87391fb1cd8cdf6096b64a82f9e95f0fe46f143b702d74545bb314881098ee, + 0x1b5b2946f7c28975f0512ff8e6ca362f8826edd7ea9c29f382ba8a2a0892fd5d, + 0x01001cf512ac241d47ebe2239219bc6a173a8bbcb8a5b987b4eac1f533315b6b, + 0x2fd977c70f645db4f704fa7d7693da727ac093d3fb5f5febc72beb17d8358a32, + 0x23c0039a3fab4ad3c2d7cc688164f39e761d5355c05444d99be763a97793a9c4, + 0x19d43ee0c6081c052c9c0df6161eaac1aec356cf435888e79f27f22ff03fa25d, + 0x2d9b10c2f2e7ac1afddccffd94a563028bf29b646d020830919f9d5ca1cefe59, + 0x2457ca6c2f2aa30ec47e4aff5a66f5ce2799283e166fc81cdae2f2b9f83e4267, + 0x0abc392fe85eda855820592445094022811ee8676ed6f0c3044dfb54a7c10b35, + 0x19d2cc5ca549d1d40cebcd37f3ea54f31161ac3993acf3101d2c2bc30eac1eb0, + 0x0f97ae3033ffa01608aafb26ae13cd393ee0e4ec041ba644a3d3ab546e98c9c8, + 0x16dbc78fd28b7fb8260e404cf1d427a7fa15537ea4e168e88a166496e88cfeca, + 0x240faf28f11499b916f085f73bc4f22eef8344e576f8ad3d1827820366d5e07b, + 0x0a1bb075aa37ff0cfe6c8531e55e1770eaba808c8fdb6dbf46f8cab58d9ef1af, + 0x2e47e15ea4a47ff1a6a853aaf3a644ca38d5b085ac1042fdc4a705a7ce089f4d, + 0x166e5bf073378348860ca4a9c09d39e1673ab059935f4df35fb14528375772b6, + 0x18b42d7ffdd2ea4faf235902f057a2740cacccd027233001ed10f96538f0916f, + 0x089cb1b032238f5e4914788e3e3c7ead4fc368020b3ed38221deab1051c37702, + 0x242acd3eb3a2f72baf7c7076dd165adf89f9339c7b971921d9e70863451dd8d1, + 0x174fbb104a4ee302bf47f2bd82fce896eac9a068283f326474af860457245c3b, + 0x17340e71d96f466d61f3058ce092c67d2891fb2bb318613f780c275fe1116c6b, + 0x1e8e40ac853b7d42f00f2e383982d024f098b9f8fd455953a2fd380c4df7f6b2, + 0x0529898dc0649907e1d4d5e284b8d1075198c55cad66e8a9bf40f92938e2e961, + 0x2162754db0baa030bf7de5bb797364dce8c77aa017ee1d7bf65f21c4d4e5df8f, + 0x12c7553698c4bf6f3ceb250ae00c58c2a9f9291efbde4c8421bef44741752ec6, + 0x292643e3ba2026affcb8c5279313bd51a733c93353e9d9c79cb723136526508e, + 0x00ccf13e0cb6f9d81d52951bea990bd5b6c07c5d98e66ff71db6e74d5b87d158, + 0x185d1e20e23b0917dd654128cf2f3aaab6723873cb30fc22b0f86c15ab645b4b, + 0x14c61c836d55d3df742bdf11c60efa186778e3de0f024c0f13fe53f8d8764e1f, + 0x0f356841b3f556fce5dbe4680457691c2919e2af53008184d03ee1195d72449e, + 0x1b8fd9ff39714e075df124f887bf40b383143374fd2080ba0c0a6b6e8fa5b3e8, + 0x0e86a8c2009c140ca3f873924e2aaa14fc3c8ae04e9df0b3e9103418796f6024, + 0x2e6c5e898f5547770e5462ad932fcdd2373fc43820ca2b16b0861421e79155c8, + 0x05d797f1ab3647237c14f9d1df032bc9ff9fe1a0ecd377972ce5fd5a0c014604, + 0x29a3110463a5aae76c3d152875981d0c1daf2dcd65519ef5ca8929851da8c008, + 0x2974da7bc074322273c3a4b91c05354cdc71640a8bbd1f864b732f8163883314, + 0x1ed0fb06699ba249b2a30621c05eb12ca29cb91aa082c8bfcce9c522889b47dc, + 0x1c793ef0dcc51123654ff26d8d863feeae29e8c572eca912d80c8ae36e40fe9b, + 0x1e6aac1c6d3dd3157956257d3d234ef18c91e82589a78169fbb4a8770977dc2f, + 0x1a20ada7576234eee6273dd6fa98b25ed037748080a47d948fcda33256fb6bf5, + 0x191033d6d85ceaa6fc7a9a23a6fd9996642d772045ece51335d49306728af96c, + 0x006e5979da7e7ef53a825aa6fddc3abfc76f200b3740b8b232ef481f5d06297b, + 0x0b0d7e69c651910bbef3e68d417e9fa0fbd57f596c8f29831eff8c0174cdb06d, + 0x25caf5b0c1b93bc516435ec084e2ecd44ac46dbbb033c5112c4b20a25c9cdf9d, + 0x12c1ea892cc31e0d9af8b796d9645872f7f77442d62fd4c8085b2f150f72472a, + 0x16af29695157aba9b8bbe3afeb245feee5a929d9f928b9b81de6dadc78c32aae, + 0x0136df457c80588dd687fb2f3be18691705b87ec5a4cfdc168d31084256b67dc, + 0x1639a28c5b4c81166aea984fba6e71479e07b1efbc74434db95a285060e7b089, + 0x03d62fbf82fd1d4313f8e650f587ec06816c28b700bdc50f7e232bd9b5ca9b76, + 0x11aeeb527dc8ce44b4d14aaddca3cfe2f77a1e40fc6da97c249830de1edfde54, + 0x13f9b9a41274129479c5e6138c6c8ee36a670e6bc68c7a49642b645807bfc824, + 0x0e4772fa3d75179dc8484cd26c7c1f635ddeeed7a939440c506cae8b7ebcd15b, + 0x1b39a00cbc81e427de4bdec58febe8d8b5971752067a612b39fc46a68c5d4db4, + 0x2bedb66e1ad5a1d571e16e2953f48731f66463c2eb54a245444d1c0a3a25707e, + 0x2cf0a09a55ca93af8abd068f06a7287fb08b193b608582a27379ce35da915dec, + 0x2d1bd78fa90e77aa88830cabfef2f8d27d1a512050ba7db0753c8fb863efb387, + 0x065610c6f4f92491f423d3071eb83539f7c0d49c1387062e630d7fd283dc3394, + 0x2d933ff19217a5545013b12873452bebcc5f9969033f15ec642fb464bd607368, + 0x1aa9d3fe4c644910f76b92b3e13b30d500dae5354e79508c3c49c8aa99e0258b, + 0x027ef04869e482b1c748638c59111c6b27095fa773e1aca078cea1f1c8450bdd, + 0x2b7d524c5172cbbb15db4e00668a8c449f67a2605d9ec03802e3fa136ad0b8fb, + 0x0c7c382443c6aa787c8718d86747c7f74693ae25b1e55df13f7c3c1dd735db0f, + 0x00b4567186bc3f7c62a7b56acf4f76207a1f43c2d30d0fe4a627dcdd9bd79078, + 0x1e41fc29b825454fe6d61737fe08b47fb07fe739e4c1e61d0337490883db4fd5, + 0x12507cd556b7bbcc72ee6dafc616584421e1af872d8c0e89002ae8d3ba0653b6, + 0x13d437083553006bcef312e5e6f52a5d97eb36617ef36fe4d77d3e97f71cb5db, + 0x163ec73251f85443687222487dda9a65467d90b22f0b38664686077c6a4486d5 + ], + [ + 0x0eb544fee2815dda7f53e29ccac98ed7d889bb4ebd47c3864f3c2bd81a6da891, + 0x0554d736315b8662f02fdba7dd737fbca197aeb12ea64713ba733f28475128cb, + 0x2f83b9df259b2b68bcd748056307c37754907df0c0fb0035f5087c58d5e8c2d4, + 0x2ca70e2e8d7f39a12447ac83052451b461f15f8b41a75ef31915208f5aba9683, + 0x1cb5f9319be6a45e91b04d7222271c94994196f12ed22c5d4ec719cb83ecfea9, + 0x2eb4f99c69f966ebf8a42192de7ff61621c7bb47b93750c2b9ea08d18446c122, + 0x224a28e5a35385a7c5198169e405d9ea0fc7da8b93ee13b6d5f7d099e299520e, + 0x0f7411b465e600eed8afdd6afca49c3036f33ecbd9a0f97823796b993bbd82f7, + 0x0f9d0d5aad2c9555a2be7150392d8d9819b208ae3370f99a0626f9ff5d90e4e3, + 0x1e9a96dc8292bb596f52a59538d329229732b25259cf744b6a12d30702d6fba0, + 0x08780514ccd90380887d578c45555e593cfe52eab4b945c6c2cd4d528fb3fe3c, + 0x272498fced686c7ac8149fa3f73ef8c2ced64717e3556d5a59f119d629ccb5fc, + 0x01ef8f9dd7c93aac4b7cb80930bd06eb45bd350aff585f10e3d0ef8a782ef7df, + 0x045b9f59b6595e614dc08f222b469b138e886e64bf3c40aa97ea0ae754934d30, + 0x0ac1e91c57d9da919fd6f59d2a40ff8ea3e41e24e247a387adf2584295d61c66, + 0x028a1621a94054b0c7f9a421353cd89d0fd67061aee99979d12e68f04e62d134, + 0x26b41802c071ea4c9632647ed059236e50c19c3fb3c96d09d02aae2a0dcd9dbc, + 0x2fb5dda8072bb72cbaac2f63e468215e05c9de06758db6a94af34384aedb462b, + 0x2212d3a0f5fccaf244ff3547fd823249ad8ab8ba2a18d383dd05c56ee894d850, + 0x1b041ad5b2f0684258e4dfaeea09be56a3276fdb19f44c015cd0c7eed465e2e3, + 0x0a01776bb22f4b6b8eccff33e76fded3144fb7e3ac14e846a91e64afb1500eff, + 0x2b7b5674aaecc3cbf34d3f275066d549a4f33ae8c15cf827f7936440810ace43, + 0x29d299b80cd4489e4cf75779ed54b48c60b042257b78fc004c1b803381a3bdfd, + 0x1c46831d9a74529357641c219d721a74a427110032b5e1dd19dde30424be401e, + 0x06d7626c953ccb72f37141dc34d578e036296c0657674f80739ae1d883e91269, + 0x28ffddc86f18c136c54002748e0c410edc5c440a3022cd960f108c71cda2930c, + 0x2e67f7ee5e4aa295f85deed09e400b17be67f1b7ed2ab6adb8ec0619f6fbc5e9, + 0x26ce38fa636c90630e97f25114a79a2dca56859ef759e53ce7abf22c24e80f27, + 0x2e6e07c3c95bf7c34dd7a01d00a7ffec42cb3d16a1f72721afacb4c4cfd35db1, + 0x2aa74f7597f0c9f45f91d7961c3a54fb8890d276612e1246384b1470da24d8cc, + 0x287d681a46a2faae2c7c090f668ab45b8a71313c1509183e2ec0ca639b7f73fe, + 0x212bd19df812eaaef4a40600528f3d7da5d3106ff565aa3b11e29f3305e73c04, + 0x1154f7cf519186bf1aafb14b350eb860f97fd9740926dab93809c28404713504, + 0x1dff6385cb31f1c24637810a4bd1b16fbf5152905be36583da747e79661fc207, + 0x0e444582d22b4e76c081d34c44c18e424011a34d5476252863ea3c606b551e5c, + 0x0323c9e433ba66c4abab6638328f02f1815773e9c2846323ff72d3aab7e4eff8, + 0x12746bbd71791059193bba79cdec448f25b8cf002740112db70f2c6876a9c29d, + 0x1173b7d112c2a798fd9b9d3751842c75d466c837cf50d73efd049eb4438a2240, + 0x13d51c1090a1ad4876d1e555d7fed13da8e5713b25026ebe5fdb4808703243da, + 0x00874c1344a4ad51ff8dcb7cbd2d9743cb72743f0394efe7f4a58ebeb956baa1, + 0x22df22131aaab85865ce236b07f244fa0eea48d3546e97d6a32a562074fef08f, + 0x0bf964d2dbd25b908708b437a445fc3e984524a59101e6c18bf5eb05a919f155, + 0x09b18d9b917a55bca302be1f7f181e0e640b9d73a9ab298c69b435b5fc502f32, + 0x094f5534444fae36a4bfc1d5bf3dc05bfbbbc70a6365366dd6745a5067289e43, + 0x2999bab1a5f25210519fa6622af53a15a3e240c0da5701cb784fddc0dc23f01f, + 0x2f6898c07581f6371ca94db73710e88084301bce8a93d13669575a11b03a3d23, + 0x07268eaaba08bc19ec16d7e1318a4740565deb1e8e5742f862174b1a6866fccb, + 0x186279b003454db01339ff77113bc9eb62603e078e1c6689a6c9582c41a0529f, + 0x18a3f736509197d6e4915bdd04d3e5ddb67e2cc5de9a22750768e5524737172c, + 0x0a21fa1988cf38d877cc1e2ed24c808c725e2d4bcb2d3a007b5987b87085671d, + 0x15b285cbe26c467f1faf5ef6a64625228328c184a2c43bc00b36a135e785fba2, + 0x164b7062c4671cf08c08b8c3f9806d560b7775b7c902f5788cd28de3e779f161, + 0x0890ba0819ac0a6f86d9865fe7e50ef361c61d3d43b6e65d7a24f651249baa70, + 0x2fbea4d65d7ed425a42712e5a721e4eaa627ac5cb0eb878ccc2ee0aed543e922, + 0x0492bf383c36fa55540303a3b536f85e7b70a58e854ab9b9103d7f5f379abaaa, + 0x05e91fe944e944104e20251c565142d61d6185a9ce85675f6a969d56292dc24e, + 0x12fe5c2029e4b33893d463cb041acad0995b9621e6e49c3b7e380a76e36e6c1c, + 0x024154adf0255d47958f7723921474131f2629fadc89496906cd01dc6fa0784e, + 0x18824a09e6afaf4a36ed2462a86bd0bad798815644f2bbde8813c13457a45550, + 0x0c8b482dba0ad51be9f255de0c3dbddddf84a630af68d50bbb06983e3d5d58a5, + 0x17325fd0ab635871363e0a1667d3b67c5a4fa67fcd6aaf86441392878fdb05e6, + 0x050ae95f6d2f1519122f5af67b690f31e550773fa8d18bf71cc6d0e911fa402e, + 0x0f0d139a0e81e943038cb288d62636764bbb6295f07569885771ec84edc50c40, + 0x1c0f8697795689cdf70fd2f2c0f93d1a79b39ebc7a1b1c549dbbca7b8e747cd6, + 0x2bd0f940ad936b796d2bc2e048bc979e49be23a4b13598f9fe536a16dc1d81e6, + 0x27eb1be27c9c4e934778c09a0053337fa06ebb275e096d167ce54d1e96ee62cb, + 0x2e4889d830a67e5a8f96bdd3155a7ca3284fbd307d1f71b0f151be62548e2aea, + 0x193fe3db0ab47d3c5d2ec5e9c5bd9983c9891f2cadc165db6064bbe6fcc1e305, + 0x2bf3086e96c36c7bce415907ad0c40ed6e9661c009679e4e37cb13027c83e525, + 0x12f16e2de6d4ad46a98cdb697c6cad5dd5e7e413f741ccf29ff2ea486e59bb28, + 0x2a72147d230119f3a0262e3653ddd19f33f3d5d6ec6c4bf0ad919b0343b92d2f, + 0x21be0e2c4bfd64e56dc47f957806dc5f0a2d9bcc26412e2977df79acc10ba974, + 0x0e2d7e1dc946d70b2749a3b54367b25a71b84fb911aa57ae137fd4b6c21b444a, + 0x2667f7fb5a4fa1246170a745d8a4188cc31adb0eae3325dc9f3f07d4b92b3e2e, + 0x2ccc6f431fb7400730a783b66064697a1550c12b08dfeb72830e107da78e3405, + 0x08888a94fc5a2ca34f0201462420001fae6dbee9e8ca0c242ec50621e38e6e5d, + 0x02977b34eeaa3cb6ad40dd42c9b6fdd7a0d2fbe753af88b36acfcd3ccbc53f2a, + 0x120ccce13d28b75cfd6fb6c9ea13a648bfcfe0d7e6ff8e9610b5e9f971e16b9a, + 0x09fad2269c4a8e93c81e1b9770ea098c92787a4575b2bd73a0bf2af32f86ff3c, + 0x026091fd3d4c44d50a4b310e4ac6f0fa0debdb70775eeb8af630cffb60092d6f, + 0x29404aa2ba565b77bb7fba9dfb6fc3212543cc56afad6afcb904fd2bca893994, + 0x2749475c399aaf39d4e87c2548695b4ef1ffd86590e0827de7201351b7c883f9, + 0x098c842322479f7239912b50424685cba2ebe2dc2e4da70ac7557dab65ffa222, + 0x18cef581222b647e31238e57fead7d5c758ace14c93c4da40191d0c053b51936, + 0x13177839c68a5080d4e746745e43711d3cbc0ca4a108f98d63b2aa681698de60, + 0x020ca696f531e43ec088f56f4b74325626cc4df712c0e5f0a907d88e5f0deffd, + 0x27230eede9cccfc9fa805a30fc548db693d13708c646841d16e028387c7ac022, + 0x01645911c1198b01d64fde34a342a1786497c05969a015439057d2fe75bb281c, + 0x2c323fe16481bf496e439c88341ce25f198971e14487056cfdca4a451a5d8643, + 0x0fc082dfe70728e8450bd2074c3e22e1b022c124d3bffe8b5af88ae6db5085c8, + 0x2052c174800db209d8cdca568dcc25b3be9642116ac4c77efe8a488b423521ee, + 0x28e420e10df2fbb5af96d621d55423190be351ce8129065a8dd9fd05b3ece9c0, + 0x25698ca5e24a1b799f783c4462a24db655d6ae1bdacd1cb549d6e0bc3ae5069a, + 0x160a9981a5c89a57cf8ffbfa57d51049a297b61074422ac134d9b857d6984d35, + 0x21c91a39e145c3bc34d9b694b843f3bf8b7cebf59ddbb0a064642b069997f3d4, + 0x1ac8d80dcd5ee876d2b09345ef112345d6eaa029d93f03b6d10975461e41734c, + 0x0ab3e6ad0ecf8b8e7c1662a4174c52225d822895e2755544b8dbcea5657ce02c, + 0x1c675182512620ae27e3b0b917b3a21ca52ef3ef5909b4e1c5b2237cbdab3377, + 0x2cdbc998dfd7affd3d948d0c85bad2e2e37a4a3e07a7d75d0c8a9092ac2bed45, + 0x23b584a56e2117b0774bf67cc0dee33324337350309dff833e491a133bb63b2e, + 0x1e9e2b310f60ba9f8cb73030a3c9d2a10d133bc6ba4ec1152f3d20de1465e9a5, + 0x0e01e365ba5b3031abc3e720140ae746c9ab5dab987520c460bcd4f1fa5b22db, + 0x040884cdcfc64bfc7b7127340498d5c443382011b61c9a4b1387d85bc1264e68, + 0x190b1ee1205eb9500c74a3998f2bea36353f1724d6067ed0a0a17de311ef9668, + 0x1647c72aec6c4388d04f52fc23cd9c08c1dfcf65ce61e165fc28d1f832bd3b2c, + 0x2430006346a0145f799880cc4c8736269f5494d89fb48b02842e595b71e4541d, + 0x177b9a08343917e1365107a3da3ae7f69d853902bb16bacb3221850252b757af, + 0x04a420e642b11ae94e58862a68f5e32609cd53d0ae29423439b11d04666df4f8, + 0x25d0e0f739fb39fc105a88fab0afd810de2461858e956ccccdfabeddb6a25c8f, + 0x04476d91b7eff2fd85905cbf58651edc320cb15610eaed452c4d4ffa0c740a27, + 0x1090c0b68b3d7d7b8bc9ca2419eb8dea1c28f6d5e1250cb5e9780fd9ca286fae, + 0x25393ce3b9256d50448a725c5c7cd5ad376f2d435855c10ebf2899cb5c6617be, + 0x25931c0c7371f4f1fc862f306e6e5830ed824388d6b9342697d144f0fab46630, + 0x2396cb501700bbe6c82aad51b0fb79cf8a4d353185d5808203f73f22afbf62f6, + 0x26a363483348b58954ea748a7129a7b0a3dc9068c3cca7b5b3f0ce03b8724884, + 0x27ca107ca204f2a18d6f1535b92c5478c99b893334215f6ba7a0e5b45fcd6897, + 0x26da28fc097ed77ce4662bde326b2cceac15f7301178581d8d2d02b3b2d91056, + 0x056ab351691d8bb3703e3055070ac9cc655774c1bb35d57572971ba56ee0cb89, + 0x2638b57f23b754aec76d109a2f481aa3c22547a11ffc50152d729af632376a90, + 0x304754bb8c57d60732f492c2605184fdc33e46a532bdec80ea7bc5519ede7cef, + 0x00d1727f8457ee03514f155b5806cbf748ec6857fc554010752ac93a9b7619ac, + 0x00ee1f3c66fbc05c43ba295a303c72fab5bca86805ec9419c588e50947761fa3, + 0x0afafadcf5b4dd4a4a76b5a1d82415fd10a19fbcfc59078c61f9297eb675d972, + 0x0b2449f39746085e86ce45e8eed108ee65a234835a0a6a5ea8996d124dd04d0a, + 0x206b0ce2f1b2c5b7c9f37b0045227095f6c6f071ec3bdda76a7ddf4823dd5dd6, + 0x0feba4fb87834c7cb696e67433628cd6caffc3a4ef20fea852c7e1029459409c, + 0x254dbfac74c49b0b8926752e084e02513b06f1315e6d70e18173e972336e55d3, + 0x0addb1372cee4e164655168c367559e19606c5bd17910aeb37719edfa0ca8762, + 0x26b25b7e257f3e97c799024fb019f65c6ca4d8d81b1ae16221a589d68831d759, + 0x090995b79acec240413b8d4c658787e5a4657b9ab00bdb5b1960b1059e113ba3, + 0x08dbdc2e21ef11f2c57299687843cea3eb0d8e40e99131f42974178d44f73b7b, + 0x09e8aba671481197679faf752a0f78e342fe9c491596ab6758f170939785179f, + 0x1deb05180e833e45659052a7ebaf816c7efd12a7f9eec94b7bc7c683f1363d5c, + 0x19a70ec6bdfc9098a926efbcc04aa9ee248997e8b2c24af335fd6523e5250879, + 0x21d773660adafb8a879986f9aab4890566353a3777d8a3f1eb93abe10bbf1f64, + 0x09f1890f72e9dc713e20ba637b89d5d397a6b01fcd667347f6f46617841c3901, + 0x05af459361eb454d2a300c61e446998d48fa1f897bf219d608c2145c33b111c3, + 0x0fa1a1d6829f0345664a66dc75a657335f336f15f340756cfa12fc850cc8b513, + 0x02e47a35bcc0c3a0bda0b1c0307ad543f4280fcf87f636f853655cf97a628bb0, + 0x14f773e9834c6bdeb8f90e78bf4c24b7203411460112491036621895204d0f12, + 0x102d98cf502ed843255cf19d29bc7d8e642abe7cfd639992ffb091962fc8f7cc, + 0x043dd5f4aa5a76dd4c47f6c65da7ca2320d4c73ad3294738cba686a7e91373c2, + 0x21833819c3337194a6c0d29a48d4f2676f0e7c79743a306f4cfdb2b26bd11efa, + 0x0f281925cf5ee649b474a6819d116ca3eb4eca246c311ecadc53262a3cff2b53, + 0x0d3e2477a7b10beb44709c7746d6824edf625dd60504d5dc93ce662f15c238d6, + 0x2cd7f641bedbf66956ff8a01be9cde35d80f80ab51e73b49acbfc3eff5aefc44, + 0x29e95b492bf2f95f4d09380f98b74e389149d24045811d7a86dd861310463cf8, + 0x22da66bc62e8f011266efca86a6c810f9ae4c51af6ffeb57f8b3c50df83cc13e, + 0x0fe6d30de7a82d163023491794f4aca3220db79e8129df3643072d841925554a, + 0x0050e842a1299909123c46eff185c23ad312d03fef1adfecc7e07ecb298fd67f, + 0x2130a3a7b3221222be34cc53a42d7733666f9ddf714ed7c5885cbbdb63108c21, + 0x2df9ee294edf99e3d8d5883fe0566c24aa66731f34a93280e1d328e67b33c9fa, + 0x1bf7d6e489ad8c0cf26eb68cc21ff54158132396dc250aeba4b6fc5fc3372762, + 0x0c602fa155be958761eaf739617ab136cf7b807728bf7fe35d4778d311780e54, + 0x2e50e2c5b36aa20532407d86b8d22d7d5154080a24972faeb63faf0121ed7f21, + 0x17c2510982a7b5825710d6290ec4f782f674995ee8409b42b459123b180332e1, + 0x0b0d52f03c8af7276803ecf2465b885b21337b538eabd2f6b2ab255f376b42a8, + 0x0f5633df1972b9455953d88a63f80647a9ac77c6c0f85d4561972dd8fab8bd14, + 0x0ebf7ad29ca13804e1422e939681155124780ff43e76e929035498130a7f1572, + 0x1aff13c81bda47e80b02962173bba343e18f94bee27c8a57661b1103a720ffe2, + 0x210449dbf5cf3061da2465be85505862d3f31de1a3b58ff35713be57efac6c07, + 0x088230c2794e50c57d75cd6d3c7b9dbe19d1e2f1d3001044b93ad1c3ee629817, + 0x1c408c256490b0a1da08dc464138dfc78cce9a9e16c7705617a4d6dbb20e7e3a, + 0x074517e081eb4c1f22d1771200fb07658f7c77654d58440490dd6f557e9e3903, + 0x02d04e9c21df1dbd88524bdb203691b4cee5530559d6cf0fa05adf61e12fdcbf, + 0x2eb7a011b8bce91082e13ebd75de3b58eb9b4650dae9f11aa81db32cf1b67b13, + 0x2efda77ed35f4af0299f75d6e8a849b54d2ac6bf95368304e6030c18f0cf17b5, + 0x09199dcafd50ce642eddbeda65206d4f61a73d10852b8114c51b2440192ae064, + 0x268c5cfc446d399c4dd319db666a75b5cb655d8c1797e9fa76181cb4216e1562, + 0x2303a652c949071826b0e9a36c80578697b44e912cce6687012854eda11a18dc, + 0x27c53563b12a6ee2c3f041f31dc45922bc5353eb110868d237073f4efb35fbdf, + 0x1201a87eaf4ae618f02bd82d0a5109049969b5248cfe90f42c278f22615d2b0e, + 0x2c43169439fcd69ead8214997bb069becafcb1ba2c51e5706cb4b43dab2a443d, + 0x0683597315359040ea03c45d6984c6894f46cbb36d702e3c4fb9847e6304d944, + 0x03545706706eab36afb93b128febd16fb0425e158314197b77795ad3a798d183, + 0x1a33c254ec117619d35f1fc051b31728740bed23a6a37870edb393b71a0c0e6b, + 0x1ffe6968a4470cd567b0c002281caf996e88f71e759b87e6f338e517f1690c78, + 0x0fd66e03ba8808ffecb059c899fd80f4140ddd5d2a5c4483107f4e02e355b393, + 0x263ab69f13b966f8197394552906b17e6c8617a7bdd5d74a7be3396b7fe013ab, + 0x16a425e47d1110625054d5a165de413e3bd87d5aa3958fdd6eb7e03e39ba4046, + 0x2dc510a4719ec10cad752f03c673f0e253cc31d13e39e909fcc5f73af9138d9a, + 0x24df8e8d856c5b5e1bd1cad23d07dda3423c5179329b7a82cb4aa709a94576e5, + 0x2bcc94ff4fc3c76f3cd5c68915a042e87628249a01b09561bdf24a6cdce5620f, + 0x076c1e88dc540c8d8de54e343df7c429d3295f52c38cffe6b48be86852da97df, + 0x09b5f209a451ac431c051fb12d9a5e4fe40ee1601120947da990fb8e12cb46e1, + 0x205f17b0d8729e2eaa88d6a44135a6ab64e9424f55b0f1ea0683af75eb677c07, + 0x281c5c688836f6cf912638c38be046cd091681f0a41761720cdd1edf9f237029, + 0x1a053e6878e900f45f4d67448c471cf3009a44e7a02ea50e4afa44f2592621f5, + 0x100dc7d426debe3007fb7ceac84e4f5468efcb897e7bbee981742839d59e064c, + 0x17022672a016a957bb87e2cfadc8b75fb28905bdb62c82c80b1cb31b411e49c8, + 0x1086db7e2760fc8b71053a87ebe151239fb8b547182b170de0c27203f954f4d2, + 0x15384fe39d73b63302460ae4c2942fac2b41fb65a185536fb85dd24fd7584064, + 0x2ebb599fe9136d424bf4abc5342c6c7447b1a853205fcfb5519e551357709008, + 0x1b4b5e87cfb9262cfec3c0f0542e4c5a4cf278292b4ce3eed996fac6f4d37288, + 0x2465053ae50b6885801f3f82e302cafbbb4a7581bb4fba60b637febe659e5057, + 0x114f32edcdea09cd095c5bb5d38f1b97da9f05e18b3708bf6e0ab9d3d54859ef, + 0x2bc70dfeb2baab2f6b387cd77be779ac2e5e5519f3d18123ee28d8c2543c7148, + 0x01c9bf7a203ce22b775e3a61ad7e77b6a78348b9f6ec68a412e49bfe32c05415, + 0x0514b0fe5909ea887bedb0295fbbcec355cfb575ff6a97cd9f4ad00ccb57ee9b, + 0x267c76ec81934cc81a132a8b058910a12092520b12a201af03e3202d7b6c1b7e, + 0x29170e3322b3d8d5c78c84babbb470adf1622493ce83e95cfb151cf757bde5d6, + 0x019f6a8124b19e33af33e5d3873f9c335c6f09a45486cab536dd596ca41d9519, + 0x1904aa4d6908544a8b348e9db1981c27009ed8ea171518ae5405d036242b60e9, + 0x26f17873949bc679f7f043956694e422b3cee1de9dd6f6473b932a476455ff1a, + 0x1ac668f612b8243c193b33720b8aa54040c476031197131ebdcac9b18bc48f75, + 0x0996d961a75c0d07196dae45bf624766ccfbf8555be9796da52f81568ef0663d, + 0x030c97e1b8cad1d4fd50d1b4383fbe6674d171f99c63febb5425b395c24fc819, + 0x06e3ad6a46900e2d3953370255b68f89b3e523f1fe502642ee226f2d8bd0848f, + 0x1d6b3755331cd0216b6880e42f9880f565cb94b0e0455153a329890588cc916e, + 0x28e4dcba4b96f12a59b041535e730ac8c35189dc0b85ac033dd38c08bae531f2, + 0x08b6086046a835508ccf484f2974b6a6b0712a476260376c7a3b3e4bc4a47a14, + 0x162cd2ca7fe3b5f1444bcec97812019bb6fd85fba6a0536a89643e15b9bb3b52, + 0x28f1e03baaea9bbc05af5b11937e4f5cb5c9a9c1192063d1998c01c64d483a76, + 0x1bdb062778d7c15da395af2734c25faa0127d2aab4aa71366031a0bb6791ce10, + 0x2375839502e09890cb2914e829627e0e0fc98870b2324a8b50329ebdd24749cb, + 0x1fa8662fbcb61fb3ad7c55668dc9423a332dc87cfb2df456e92d33611ed7bb50, + 0x1e4fad2dd6b0a6f1f8707f721716c8a446e2fb2c47a5138f3f7f9736079d7694, + 0x211256d16c7269fd6df6f5fcdd1fa788ba3bd050059f53d261b0f5f13731ffe7, + 0x2e49084b336eceaa4f8e2a2e6af08318f42060e574dda341f4a1079b12bcc5a5, + 0x0ce19f54cdc39f7f3bf35192ac6808211aecea08dfe14cab758d25891fb00bb9, + 0x0011c5d56c390e893cc394221261d8748dc60451e4ae4e1c84a8468bab2c14cb, + 0x17d79ff06b63ac2a8a9e05ee6af3dbb7ca60e17bfa39b47514a8cd8051579b4c, + 0x19a7d3a446cb5393dc74560093592b06b1a8b35cd6416a2ecab00173639015fa, + 0x030c00a0933dcdba2a808b2e1b9282f331f04596d8928da7aa6c3c97237037a6, + 0x16bcb447ce2d50f3ae25ad080695382e935d2d00184c4acc9370be8aab64139c, + 0x12341b46b0150aa25ea4ec8715312997e62124f37cab7b6d39255b7cd66feb1d, + 0x0e86d13917f44050b72a97b2bf610c84002fc28e296d1044dc89212db6a49ff4, + 0x08e6eb4089d37d66d357e00b53d7f30d1052a181f8f2eb14d059025b110c7262, + 0x2ea123856245f6c84738d15dd1481a0c0415ccb351a1e0cee10c48ce97ca7b18, + 0x2dca72b2ebcab8c23446e00330b163104195789025413abf664db0f9c84dfa6f, + 0x06ff9ed50d327e8463329f585ec924b3f2f6b4235f036fa4c64a26cbd42b6a6b, + 0x246a10b7e3e0089947f7c9bda3d54df8e2a60e0cca84ea2ac630a4535afbf730, + 0x22a63501c5f04b9018719ed99d700ee52f846a715ae67ad75c96b39d688b6691, + 0x2f4c50477f7fd9c671799ac5d2e224cdb9164f58351d8aa140ec07e514fae937, + 0x10ffb7aad1f51c7d13b17f4d876d9a1e38f0ba8a4a23d4b50cda32cad851567e, + 0x0e9cefddc3c2d3bea4d39722532d5420784027352187e7af1a056935c35803ae, + 0x07af84a4d3141e7ac23352e6dc6ea4afa1656f96a33c8978a3e83bdd4ba62b41, + 0x2d9e31a10aebc761f8de00d14b1e566d1a39323d6e89b638e940f3ec8a22c3c5, + 0x27f19a6532e66b5333db1afd592f66f1d36034b314dad8447656747be27e64c7, + 0x0058fa3c8454d63354b2024c3b4a577a180ed99f8f3155cd7e4d617d47d07ffd, + 0x041627b6715b780967957c080699343eb0414a205d3a175d708964956816a5d5, + 0x006ac49dd9253edc7f632e57b958ccecd98201471cf1f66589888f12b727c52d, + 0x0131adffd8bd7254b1d8c3616bbe3386ec0c9c0d6d25a9a4ec46a6bf18301398, + 0x1c4a6f52c9fccf7a4138e413ef62a28377977ad7e25e49a3cf030e1cd8f9f5b6, + 0x03f2a6be51ec677f946551b3860ea479fee048ae2078aeb7d1f7958d2c2645f6, + 0x2da770aad2c2eb09391a0cb78ef3a9648a1372d8543119564d7376396b8ddc62, + 0x15278463665f74cddc1802febfab02cec9d45fe866c359c738062afb75d64a03, + 0x12fe278aa36544eac9731027090518d434e38ea966a08a6f8d580638ac54c773, + 0x149b9c802182558a4c45d119d3f4cc7fd8587604ca4f0d6e21b06ff30b6a23b6, + 0x0812e7b4d847bc8517d19319772f3c9855e044fd60dbac9a0adc4959b691dfe4, + 0x02ed8d8ddeafe3d9d8df7f28a0bfaa7f555813c7e7503aea2a66973703a0c61b, + 0x0ebd073ba0537b514deb6029f921029e55e5e4d9a03d6b6ba1304038662d4db8, + 0x15c754d5b14b2c4205c6ba8d2ccd028255b3e792c6afa08b44ee75b62eff9f59, + 0x169515c89ac5479db0ed8fa6fa311b391cc1235270f4cbc5c29e7cbc30e8732a, + 0x25479fbfb3a68f982388f2621001101608bdc29f6ff037696d9161f5cd9a4fef, + 0x14475c4bd520451f3c852cb0311a578ca7f8e6e972182196ce09486e94be6071, + 0x045a691066cc66bec9baf2798833a1dfd3a847502aec8d5f5c4e73363d097799, + 0x26029c0c267c799fb833ac8a11e3a3f0147a8ca037221b90013b8bcb37eba683, + 0x163facb34ff572fbf7c946969c1c260873ce12a6a94a3e45b8101d5b948d1641, + 0x2c714e96e1913b351d969320cc69d5ec13e06a6275e58688af8ee00c4240ee28, + 0x1c1661e2a7ce74b75aba84665ecd2bf9ddd6268f06debfe2d52b804eff1d5fa6, + 0x06a69ae795ee9bfe5e5af3e6619a47d26635b34c2a0889fea8c3c068b7dc2c71, + 0x113d58535d892115c5d28b4c19a3609374dbdbadf54195c731416c85d731d46a, + 0x2ab89102e2b8d5e638ff97d761da6042e534f1ff47f7917a2ca1a74063b46101, + 0x03c11ca79e41fdfe962730c45e699546349031893da2b4fd39804fd6a15ad1b3, + 0x27096c672621403888014ddbbbfc9da1f7f67b4d4cfe846c6adf040faaf2669c, + 0x2de32ad15497aef4d504d4deeb53b13c66db790ce486130caa9dc2b57ef5be0d, + 0x0dc108f2b0a280d2fd5d341310722a2d28c738dddaec9f3d255754448eefd001, + 0x1869f3b763fe8164c96858a1bb9efad5bcdc3eebc409be7c7d34ca50365d832f, + 0x022ed3a2d9ff31cbf82559fe6a911843b616945e16a568d48c6d33767129682d, + 0x2155d6005210169e3944ed1365bd0e7292fca1f27c19c26610c6aec077d026bc, + 0x0de1ba7a562a8f7acae93263f5f1b4bbec0c0556c91af3db3ea5928c8caeae85, + 0x05dbb4406024beabcfce5bf46ec7da38126f740bce8d637b6351dfa7da902563, + 0x05d4149baac413bed4d8dc8ad778d32c00e789e3fcd72dccc97e5427a368fd5e, + 0x01cdf8b452d97c2b9be5046e7397e76ff0b6802fa941c7879212e22172c27b2e, + 0x1fc6a71867027f56af8085ff81adce33c4d7c5015eced8c71b0a22279d46c07c, + 0x1040bef4c642d0345d4d59a5a7a3a42ba9e185b75306d9c3568e0fda96aaafc2, + 0x16b79c3a6bf316e0ff2c91b289334a4d2b21e95676431918a8081475ab8fad0d, + 0x20dff1bc30f6db6b434b3a1387e3c8c6a34070e52b601fc13cbe1cdcd59f474e, + 0x0212ac2ab7a6eaaec254955030a970f8062dd4171a726a8bdfb7fd8512ae060d, + 0x2f29377491474442869a109c9215637cb02dc03134f0044213c8119f6996ae09, + 0x0984ca6a5f9185d525ec93c33fea603273be9f3866aa284c5837d9f32d814bfa, + 0x0d080a6b6b3b60700d299bd6fa81220de491361c8a6bd19ceb0ee9294b24f028, + 0x0e65cd99e84b052f6789530638cb0ad821acc85b6400264dce929ed7c85a4544, + 0x2e208875bc7ac1224808f72c716cd05ee30e3d20380ff6a655975da12736920b, + 0x2989f3ae477c2fd376a0b0ff3d7dfac1ae2e3b894afd29f64a60d1aa8592bad5, + 0x11361ce544e941379222d101e6fac0ce918106a463290a3e3a74c3cea7189459, + 0x1e8d014b86cb5a7da539e10c173f6a75d122a822b8fb366c34c8bd05a2061438, + 0x173f65adec8deee27ba812ad29558e23a0c2324167ef6c91212ee2c28ee98733, + 0x01c36daaf9f01f1bafee8bd0c779ac3e5da5df7ad45499d0991bd695310eddd9, + 0x1353acb08c05adb4aa9ab1c485bb85fff277d1a3f2fc89944a6f5741f381e562, + 0x2e5abd2537207cad1860e71ea1188ee4009d33deb4f93aeb20f1c87a3b064d34, + 0x191d5c5edaef42d3d02eedbb7ab8562513deb4eb34913a13421726ba8f69455c, + 0x11d7f8d1f269264282a263fea6d7599d82a04c74c127de9dee7939dd2dcd089e, + 0x04218fde366829ed90f79ad5e67997973445cb4cd6bc6f951bad085286cac971, + 0x0070772f7cf52453048397ca5f47a202027b73b489301c3227b71c730d76d6dd, + 0x038a389baef5d9a7c865b065687a1d9b67681a98cd051634c1dc04dbe3d2b861, + 0x09a5eefab8b36a80cda446b2b4b59ccd0f39d00966a50beaf19860789015a6e5, + 0x01b588848b8b47c8b969c145109b4b583d9ec99edfacb7489d16212c7584cd8c, + 0x0b846e4a390e560f6e1af6dfc3341419545e5abfa323d817fed91e30d42954a6, + 0x23a6679c7d9adb660d43a02ddb900040eb1513bc394fc4f985cabfe85ce72fe3, + 0x2e0374a699197e343e5caa35f1351e9f4c3402fb7c85ecccf72f31d6fe089254, + 0x0752cd899e52dc4d7f7a08af4cde3ff64b8cc0b1176bb9ec37d41913a7a27b48, + 0x068f8813127299dac349a2b6d57397a50275142b664b802c99e2873dd7ae55a7, + 0x2ba70a102355d549677574167434b3f986872d04a295b5b8b374330f2da202b5, + 0x2c467af88748abf6a334d1df03b5521309f9099b825dd289b8609e70a0b50828, + 0x05c5f20bef1bd82701009a2b448ae881e3a52c2d1a31957296d29e5763e8f497, + 0x0dc6385fdc567be5842a381f6006e2c60cd083a2c649d9f23ac8c9fe61b73871, + 0x142d3983f3dc7f7e19d49911b8670fa70378d5b84150d25ed255baa8114b369c, + 0x29a01efb2f6aa894fd7e6d98c96a0fa0f36f86a7a99aa35c00fa18c1b2df67bf, + 0x0525ffee737d605138c4a5066644ec630ab9e8afc64555b7d2a1af04eb613a76, + 0x1e807dca81d79581f076677ca0e822767e164f614910264ef177cf4238301dc8, + 0x0385fb3f89c74dc993510816472474d34c0223e0f733a52fdba56082dbd8757c, + 0x037640dc1afc0143e1a6298e53cae59fcfabd7016fd6ef1af558f337bab0ea01, + 0x1341999a1ed86919f12a6c5260829eee5fd56cf031da8050b7e4c0de896074b4, + 0x069eb075866b0af356906d4bafb10ad773afd642efdcc5657b244f65bed8ece7, + 0x171c0b81e62136e395b38e8e08b3e646d2726101d3afaa02ea1909a619033696, + 0x2c81814c9453f51cb6eb55c311753e84cbbdcb39bfe696f95575107502acced8, + 0x29d843c0415d35d9e3b33fadcf274b2ab04b39032adca92ce39b8a86a7c3a604, + 0x085d6a1070f3513d8436bccdabb78750d8e15ea5947f2cdaa7669cf3fae7728b, + 0x11820363ed541daa10a44ba665bf302cdbf1dd4e6706b02c9e2a5cda412fc394, + 0x201935a58f5c57fc02b60d61a83785bddfd3150e05f1df5d105840b751a16317, + 0x0a8c2820c56971aae27a952abd33a03d46794eedd686cd8ecfed610e87c02e9a, + 0x180638ff301a64ca04abd6d0bd7500b6650b65ff33e6be1fd50dbc163a281877, + 0x095c716266f1de59044f97114a4158a3f85ca8a937cfbec63e9b321a812dd36b, + 0x17c31ea02fbc378320d86ffed6c7ca1583b618c5c1a687818d4087a497d73490, + 0x05b86c4bb8ef318b6a7227e4192d149d3c17a9764ccd660de4d50a77f192a91b, + 0x265bc95df4a4c4876ff70d7ea2fde2c7ab15f4a6ae0d237cd6ce74ba986c7a7b, + 0x24752b47bc6c6bc8d9bbe48f5fef2f6908701739c5f5b4b3d6c886d4715c7929, + 0x14814a1e0f492a4ea0d86e527a96482178d624b98da96ee5e583b9324d974efe, + 0x10def931073b6479bd60577378f29381997c8e041d3cfb3dc7523bca906f00bd, + 0x14f7ae770bf7e95f7f706c0d8ab4ed03fa0b880d28c69d031b4592c98610175f, + 0x1aef50a0cee751b59f926af40e8035d19decc9d428ebe4e775c5cc9dce1ce589, + 0x041935607172f68eba65ca60068dfe3b086c2a2d57d09602951214b57e73cf5a, + 0x26863e9dd24255d1573bd083959b856c0493fbefe83c819837a151d3bf452cb8, + 0x2036efb6f9830965eb3d7a068bd087c9f5adf251ba62052c652738e63ff8b3af, + 0x0c712a975b74dc9d766b639a029969ca30be4f75a753f854b00fa4f1b4f4ee9b, + 0x08014dab3cd1667e27afc99bfac1e6807afdff6456492ca3375731d387539699, + 0x198d07192db4fac2a82a4a79839d6a2b97c4dd4d37b4e8f3b53009f79b34e6a4, + 0x29eb1de42a3ad381b23b4131426897a32709b29d53bb946dfd15784d1f63e572 + ], + [ + 0x1448614598e00f98e7ae7dea45fbd83bd968653ef8390cde2e86b706ad40c651, + 0x0ab7b291388e5c9e43c0dc1f591fb83ecdb65022e1b70af43b8a7b40c1dff7c3, + 0x2b7cbb217896f52c9a8c088e654af21e84cde754a3cef5b15c4d5466612d6adf, + 0x2bc6b0ddbe1d701b6570428bdc1ca1bf0da59ff3bbbb95fc2bc71c0c6e67a65c, + 0x123a55a31980384f3d20b2cecbc44ed60c38c11f7d20e9271efab9a905eefd3c, + 0x037501cc8c9dc819309a769f4df098e588b01858bc8eb7e279e2883be9fb8c53, + 0x1c2116e47e03a86bb11695b0a5f6dab6b9a460b1eb951ab01c259eca3fd47d51, + 0x2c18213489032e85a9c8cb8e9a65839bfaed13e57bc0fae49dbdaebf54f56f93, + 0x2ee8fed3d4d2c71a0429eafd8e5db1718f29e2227985fdf2ad8703c835b9e031, + 0x28c64d8f5ed7aac004c92029d9e9bf91ba9436d1cce94b9316d111c70a0c1714, + 0x18a01d9ffb747ae0de3e83c707f8b24f682c84f15abf571b34254a03478665e0, + 0x1c21d92bef197e73b234e4777b60db14e642a56cee71515d54e1ac71cde72bd3, + 0x0ad404ccbcb1e195897cb60c80981ebb9d66a6677dbbedad8b6455fe62d807b1, + 0x0a9b6de833064f93b6adb99af6c005945cb654cb7bd14c8b97af8b60cc1fb387, + 0x13129e3f930aed6d47690331ff09dc5160efa58ddce2c3e6180d45bec3aa3a6f, + 0x0d7a614c8991508ab1ce4895813bb1c82f18bf7bfc9e280ccca18079839387f1, + 0x0532f7ec36e30041b0486986875c913a49bddf2f5af5febe8c31f2f4094ffea5, + 0x06bbcb8e8e180201293e712f4950f1b0bbee808c9d64263c84d9d8ae155cb892, + 0x0f558a4db1a3ac07f61e2e6bee947f73586bf40f211ceb4f687ca5678a9dcb33, + 0x2be140a60b5b5f2f8edd78a818a969b20c643e419bcf0b577c24a0d0e7acfe98, + 0x1c49c4b9a9f09f7b9ad5f74ebacc710512b8e867bace27cb0dea06e89b96f631, + 0x170c1a732721b12cde7f33e476a39a1aa77a81c06e2eac503847b00d597652db, + 0x19c27d0e52f65ca34f4e31a068e49331c6bfc39d9241f9d4c302041615cf27f1, + 0x2f1bdc5254f9220c1a731fc5276964dab26b385fa40b6b04bed9960e2543ba08, + 0x05b42d2fbccbf4d39d2be9339cabe9d0dc6d921e855cd91154b639d28d4a1cf0, + 0x1220040715a41ad59f4f410e0c05a42c5fd32ac52fe9d06f88188d71f61e0935, + 0x25f9526526155b83946609f7bb9507dd4925ef871dee916d9144ebb4ece1343c, + 0x017bfe4284299ae7740b6d0e204951e314a8a5d0452419147978a95b34742444, + 0x2a5d4764021ca71d78a9674cb6708f1588d2ceaf3578c4111cf8b359eef089cf, + 0x17f02dab745fbe3c081321fe5cef845e7b8d070b2514d29b2a7b7d89cc0815da, + 0x19da62626db7199b65f4adcf57fa4a3dbaa1764a7bd155708ee6f378c89ef013, + 0x0f88e295fa2ed81b426c91fa69366a73edf75f39bf18634cd266ec4038829e05, + 0x1fe31c5548546c7948fe4ee1bd7412e3280eff7d20cb09aa85f49f2766148017, + 0x10fdc1613bdbf67f38bdde561b2f91e4cc48b59f98d643638fdc0afadbfe126e, + 0x1f2618c2ebe9574508b9c52f0000e33ebfddad1a03fdd6bca6ef7f0093127bef, + 0x129fe7fc3efac6a8ab23dba6d886f394da11f5953cf98e28269a0dba2a745dd3, + 0x15afd4cdf1e4f820c1631d4ab85ca4ba3bafcfee72beade9fae60523102448e3, + 0x1f2c74ba5c367e370d728e71e15b268851a7bb8b45528cb734956079ac99b012, + 0x1130e1872d76f2f9369cf59b95edf9ce19f01fa89c9c36b26e09def6786dad3c, + 0x13523d173f7e6badb73b63fc1c9bbdbee242c61bc68656493327533a5c1b1dca, + 0x14da40d0af427a65f1841b5adc96538653368f7254cb5667ddadbbad7a574cd4, + 0x0091f96400e4297ea85bb186c17b304e82638e57fd631ff6315976e1a5dd8b86, + 0x303329bf9031c5515b9a34d49a64bb6a0267bc7b54a0deca5c450277a002cdcb, + 0x14ed47e55c1da1c2f05d3c1a1b2e6c18509fc8336ecfe9db737916e283fa821b, + 0x1161f10b357775d810ad53bcc4a20d5add2b03251c747deb04ee94c565e58d6b, + 0x17a8a50ae72ce707f22bc070eb992851ca914eb94cc68eafbb8a96a714eb8221, + 0x1a6c61d795dbaf62f99250b37ec5df88645a1c153791db6312b932dc250e4f62, + 0x1f8bd2ab8aa840664c4eee198c4684dc4b05772bb2a0869da6722b15f447a133, + 0x1ffcb852a4f0027a9799f131cd74b98ccfb8cbc06349d8fefcc62f10c8fb3e2f, + 0x035e742ec52f19b36d489c720f467ffad77cd53bc2db5dddb246b23021f79f18, + 0x1dfaaee41bdf94d783aa29fc62b7ec7b55673aa818d305fd42d175a05f2e3d86, + 0x2821378477a02e995005a5635088540945bd333f2d1455f038a219b8c4796b3a, + 0x1db4a4d0f238a570b1061c6eec81c02f31ffdd4a7c19e763174f238d04897421, + 0x14bf7889457b20b7a1367b34a3a538217d693b52426aff40a4bb72893b1784ca, + 0x2ced52c2bf296f87e57410c3ec9a9483a796d164f6049127109ff0d3a9c08465, + 0x1ddeac5805a7f4ada4d0441ed108e3149d4ce6584f49ae5bdfd46d6766eea334, + 0x2e36b4e5e9c97b462304e8e2b5f9dc88e1c9f2161ba040673f911123f042ae70, + 0x0c6840d1cb0666dc59e89b1865275d8a164b447c5ed64347caee63502c238d5e, + 0x137e2e3e89e71d461f4c9bc3e8f12183262a4d1db55c589b2caeaac01238f58c, + 0x250932e7b0adcf2c84ed4bfb60a36b6b82e55aa94751157b1d45794b081c8aad, + 0x170a7292f5634c06dd3bf09ab5c9c4ecd4b00d5ce2f35f972b4555391f16b42d, + 0x0d68cbbe77289e78d5cbf51d70f1b75ba215df4e7bd0149d10b2c50f2a4f3b81, + 0x0caf74563b90525f645a6d2036ecd1306fa1dc680b49d9ce4ed24c9749973178, + 0x20a7d1c0a27fcce78ffe372f4c58306b166f9456ed46cdeb255e395b7d30d42a, + 0x0623f3226b5470b2789b8a53040e44443385e96b9cfa0be4d35015158a468465, + 0x1632308688c25e790f57d68a5350241242a56305347de4a5009ce46b8cdcb91f, + 0x2de4793a6f99cd14e3f6642211f4d0b7bcfa361597c544ffcb5a567e9076f47f, + 0x1d4d06d19ea1b09cad79086d51bde11725a554fa99559ca2f09f3bb73d728c66, + 0x0480e7479a66a7cd9ea61c8b28974389908350abc4aafc18cd75e33dd130c144, + 0x30430b03368ebcaa91246960490bcf917d78681463e2e7d744bfb44335dac24d, + 0x0b57b37320127d4c50f269124b0dbdcb2b1f1352241a5d12103283e089c0c742, + 0x2cf4890650d27240e195f60a4f698eda249b8dd614b23376b50178d2df6d2b8f, + 0x1e221c5526898bfd12de86851a0d9703751a2f239008ab5f9b7d3b6911c64184, + 0x28e07485ad7d992ed1a58f329ca12adce4ec693ebddbb2952e54d339f2eebda5, + 0x2f44d64f84de16dc67bd5ead51efb1dc8381c84520c12854dd5ef3a079acd4e0, + 0x050a76bc32ebd1dfe2be330f304edc7ace7167ab7ba1516f4021c62cf0d4fac2, + 0x2f58c45e5d659a67d781367241f6c35d8cb46361d97b28947d29421c270594a9, + 0x25e8da9ae0e42e840e04b230370e782bdb67534844325ba36fc7e5e160c66a74, + 0x2fec734da20fe32003ea04f127f844724f38a368ba10c29544252be796040f7f, + 0x288a6778f3a83988a8ed1727f15e93b4cb14f4e3a3bbb91dd6d1facafffd5eef, + 0x20dcc6c75fd89259be7f406750b3db679a25a8cd2715d245b9175390ac922c84, + 0x17f42ba10942df25cb8a541782a18b6fd31cf965d11178c7b04ac45b4dea5dd3, + 0x028eeb85d115a904020e0c6148eec6603e9cedabc664abee764aafd455986ba5, + 0x0b1d7cecf3a79b2ad3fa298f6cea7ae95d80c0299ecc918e9f8c9c3d38d59d40, + 0x0440339c9764cec79c16efdb834a26261db8e3f12ce1cf722d23c0e11ff4cf07, + 0x06ca647c29727c1962a002177da2d504f4b07a5f7eb57c79b88e6b7abbbdad5c, + 0x2ea120a864f5c4093dd1a962e8f013c7b8ef778b04d2ba5bfc3cab28619ba9e3, + 0x2bb737546c4aee7c0cc2ba87c1157e2a77c479ebfb5dc76adbb39cf8697633fd, + 0x0e30da6490625d33e79cd50176f568f9a2c28c2f449a2bd51a25d15686803a93, + 0x0df7ca7278a13650b919d85497b2ebb0f71035a7c20430d4131d903ab7f57521, + 0x27cc589f5bf585794abace589fb8a74a2f784c0990b80fcaa6944097f870e2d5, + 0x2255c36a38c8735de45cedf452afa842332d33042f78e60c43c7455421b325bf, + 0x133d9602bd3378d69f681c27b05bdffc98b7d86cca63d73a60caed485784d087, + 0x0e1548e942ae9d3e26860699b93727c817a9948616c93ef4accd981b1dc3d78a, + 0x0f20f0e55d93689fe09ec312f6af47627482e4bde0a1602a8e2c8d6e84e8a6ae, + 0x2e52328483cb5b7ff2eb4e45b12e51b26232c9bc17b7292954c0a9f6bfa51bb9, + 0x02b2162d533e059a6eda2abb74712edb3a7860beea95dd8a4abfc957660804f4, + 0x19e0927715d1cc6d389429947fb3737dad733974c6b2e13e5b3d432519516c74, + 0x0d3a800457d77785636303b8b94f17dcffcb46048872ac9f74ef7f27ee573705, + 0x2c974d1952557a1aac5f7bae4996616da619b73f441c4e504dc8fe9cfb559e32, + 0x0766bfeeede2ccf3708e1b4ff30714c22c1d434cdbe8f55514babc2dd5d97bef, + 0x23dac8ea54082fc131e173ae55e4630cd4ca7c871b2a0a479c1e74e7f191e62c, + 0x17d5fb6c2cb37010e3e358ab2d575376870ed33186b8eae49ad3b47e340a8d7f, + 0x175dcac76d8a8126139b583ae38853290246e43e783fa6903ec8007f178c0023, + 0x0c4fd08fede5d221adb7abf549898c91e5be7e85bf1fd2a611bf182cc2e71655, + 0x277934b909e72d3a3475bb1ec766ab7a38ad59b128303fc5002f02a65bdfe729, + 0x0e88349998dfe703f1b184524f9c394d6004ccacf9cb952896e8cfdb0b078b68, + 0x1f1b2078b60b0fce07824e2a2bc8cae8ee673514b0070a8b45710cc78cbb9942, + 0x2eb1559566c536ddbc316f6482d51fa340557657700f5b8a846e812a0ed334d1, + 0x1c4dbdc335cf6764355208b4c9d243d34541d623c669dec2c3ba066bbeaf6773, + 0x2374a6b2da6f8cab8e5cfe8d805dd3a2dfca1e8b7eba5dc8574021fd1241e3b4, + 0x19dd342533ccc603a99738e3fb5a569b94ef71b3e49f90fb874f6161733072f4, + 0x217d66db6c7fb3effa508800587d2eb3c6d03d8385132f2fcce7f35f2705cccf, + 0x0815fb8591fe01038cd3a3b38b236f9efca77c618d3bfc6c2a7fa89296c7e64f, + 0x2bb943b40c2bd456a6c17853b1ca88eb0ff36f5974b2ff9a5f5093e9bf63a16f, + 0x11a5153fce659513ee7cb9974ae6cba581e3b4cd14570c5709fec3d8d3fc82e9, + 0x1b72bfd07635d8501b2eff8785a2495bae74c7653cf90e6d5c9f144426836df4, + 0x14902c0700eec897ae178ba8caf850d793f1d87512bea0ecea39cf6b1fee233d, + 0x09c138c6e0a616a49ff90d43a6b043f3b745b78865856dc4c1a45e2fd84cb3f4, + 0x05b58a3dce57b281a271d69895052d887458a715783e8317e024a61a35ec10bc, + 0x2be8d29525c0cfdd5e6b3125e3bde3bf558e55fbe867f024457a96765474d037, + 0x061d72f78f1ba9dc6b4d7f7784225d6a81bdfc1b5ad6c24369f9c0560523d9ad, + 0x0bf18aefcacffabdf4112eddadca6145738b4803b36145bb9516db501a0692e9, + 0x2e73dd105fa8b2ec931d8cdf29ec679e3a9801a93071a7d5ea30659255f03bc6, + 0x0f8440ef667c9ae81337ba5d8c927a5347de7296860b211cad1ecbfb5d3598ef, + 0x004d303b2dea627b2731be83f93ac34e7d14d178a13800558ca7396395eb118f, + 0x234541ad72040a70da2996a35269230c94699eef313a4d480508008cbc3d37c1, + 0x0d123f1e72d26b92bdd8fd73d14286c312ad4c23acb46b2e08c157104409e174, + 0x2fb360776f0de79d7098ee7aa4123c05ee6b05a8be460a774f3a048e138545bb, + 0x03685c079434e167276c57d3cc79703b7dfdc41c156ea1e8b7f99b6956a55326, + 0x260af0e0fffcc9772c1631b179344566b47aaada3681eb9034c6f75c3705c1c7, + 0x2862b41374f89b695274b33b773f2554916e2bff9ff672545fc2f49563f62767, + 0x02a9912fe170310227189ea1e691d0362f18b38b400b0eff192ca59513eba8d5, + 0x08e513ade694a0d8ac1f3ebf1a96440d32c713d5058e1224e070348c281f4a6f, + 0x140a4a431e2ee79400ed7465978d84773213c628264ff80f21ac7a6b673d09ab, + 0x296af4d019cb5df7d959b29d549c3f071202b4eba8b53dc5ee979ed143377927, + 0x01832e284a7f4c81614882b6939fc0f185573bd2023e3e505765470bb812b349, + 0x1a84d56a67bfdd3d965abdcd329aa78d4fe93434496f2d103861fd19d66d7260, + 0x040cb82847773927d2aefdc07489037a9d1f7631eca75c9fb0dda0cb9dbde143, + 0x010dcf084cc29cb7caecf26aa633bce4ed2b019f2887cee7b1a78f89d3fabe2f, + 0x07edc22a0911ea214425ef542b776db23b0fe5817810d40c72ca98aabd9afa83, + 0x2eea4ab08aec775f2148479ea36fbb96936da58ba48bd1d2d3acd48173aaabe7, + 0x1e40c0e8257fe4a61005cdcfad148cf7f47d1b5cfddfaa082738695518245f19, + 0x23a27809583bd1ea51f436de5443e108f69d44cdf51dc1f03e21948b4980b876, + 0x2e4652b044dbfe40e63b6b232fcd5f3f39abfbd2051ee68adc754080d49250a9, + 0x11e7abdb6ecbafc2e7d8cdefe9c7b9c50475eb475db3c2caf7f7d67f485775f2, + 0x199d52350cc30e8c73821f802096f0e547a13551b27bf6b899396f63ac5cf8e7, + 0x0f575d6ee67cbecd98345624e032a37c859a7cbef30b3fddc949cd0978484101, + 0x1c4b6f9a2ae2b418e6265acba9c96b06184d07028e5fb784f3475ae7772ff057, + 0x2dcb5cf8896de39f228e157c0c5593f4626fb9bc225206383db20360abf0c925, + 0x1340abb9f4e113186bdc26cbdf4bcca50b531a107f863ca544575e3cf870f8e1, + 0x2368e692b72787cb8870ea888e714e006f59d2b4460cfb74c48a8cc73b1d1a5b, + 0x1fab9add9baa4a4f56f23165775c6f2d922a7632a94f96374b7dc852756f54b6, + 0x0c7f7b82300d3c6ce3f8957ba1e4add54c4c015e20d9765d220571c16ab8680f, + 0x15d63e86beacd93c6083688e5d9c8f3c6947929f9f1f99ab578a4c3a922eff03, + 0x0be843ae5f9b07e52572178af7dae8ed05d36b12c0607862929355ea74023d9e, + 0x1332749c523694cb6935e0963a07e81b05967ce1d950c0b731058ec92a7a0c9a, + 0x25439408810e074c0bdd4598b9815fee892bb95ca51029ecf009bffa5b9b9682, + 0x057e8d19dd999a918da29b0940b383ba9fd15db0b0f64996dff67feb55f9a742, + 0x1e014e37e9b117cf3b4870d999f2b55d3534d0a6be98e9e357fa43f01e70a29d, + 0x1a4ed24e6e03aebcd6bdb100533dc966597afe15c851b4b863f6e889084c6479, + 0x253420007083f1aa863ad4760905c1039ed4111c9f053f27710452f83ce36a90, + 0x2276a1441971709affe6d2a99320001ec45ec72155c575ddeecac0e32759ab06, + 0x28957dd1218ea799fd3411eb19325853adf7ae8ae1281f753302fe7d31dfa7b0, + 0x2fd925726ab794c88bd75796aa3e7f1e6692f2914cf802267ddf01e37902a008, + 0x1cf8a5c9c76a84b147c8238d9253cd55b47c0c43d82966c4636a28674705fd9a, + 0x0373cbbc306e1bab9e7077368715e6230b4b2e2e4a1db9c674b8c359a41e9108, + 0x060283d2fe7f23dff513d9110b3dc62448bc48f531ce0c1eab5920bf23290a40, + 0x0dab465d6d910740f33ef6cc0eadc71bf8119bdfd5a3527dc8bbfadfaa40263c, + 0x0cba7bcbc8224b2a8e4aba17977230a686cd6421dc0ca5346f3446b62439c4c3, + 0x1e4365db0790c9c4f445b0653c466ff21db96c38b4076ba8bd68bcb4dea6911d, + 0x1bb2dba2199a9ab3bc86ef5f9de7f6c5ca13d60eab42ced68de98fc643800a8d, + 0x0ad3c1870c6d6ef40eebad52123cd1a2913d9d62e80bfbacae812e082021f9ca, + 0x01b098c91e7b0cbb5c34588077c0ddf95300ddf614935630c0ce3a2627245308, + 0x19fd5c0eac14fae7598bd4ceea3b1e2998b0c168493b6d72ae41b576e55b9c3f, + 0x0d4749d79cc163f17110a404a46fe427c6434f3fe67b7e7b4ccfa6ab95bd7e18, + 0x1ebbfe8114a41bb809e0b33399241232eb940ad8728c8a516d40ada440dbfdcf, + 0x2704e5b6133d9764d6d3f17d49d833223e3937f80eb9faeabbfba9baf4b4c1b8, + 0x2165e1c8027305b1ae0e323571635e5d540d13d710c3f9a390b6913f14d035e3, + 0x2e3497e4d35fda596c06afa63bc3a0f2e55d4eeba4aceb60e65081ad63aa8b8a, + 0x031da4345eecd6db6c0f7b07c7815d7add1fe0546d738f4d79ab5c57aa841edf, + 0x089ece54e47aa5c908e43e5f08737c1436967089006acab1c9cd19eac4a20876, + 0x2f53c15e2aded33c47f55a070483e6cc7f3821fbf8aa40677d0552ed9d10d847, + 0x142aa34f4b2e8ad0df7a21b3e39c00c8b0aa2857094801eaafd72befed077f93, + 0x17aea4da4c7bcf0d7588b014eb8b40979dd2725eda4e6ace331982467c7ff2bf, + 0x0e970c19d19748d8c465104d8f02200363f9a41786f02f1827742b20dc0d1727, + 0x04bcad9e553795642f59baf714a6bdb432fc45a0a0b77f1aba3a9823476df9b9, + 0x242c0bfbcdaa76f715dbd4ba825c71fcfed671c1b1901fa484c87f810315d0ce, + 0x25db1343c24104071023fb6ed34d9909078311e1efe85af0a11b19114fa9e790, + 0x2ffe4d9c420a59e9cdc7c31ab2bf35187ca147cb898a3942deb3677786036a80, + 0x125bb03af3e2cf18bbe6f5b590eb3bf8d0d1ba63be696483e98f283bc7cd07a3, + 0x0816be42745b7dbb4ceffe5b8e24ea60fd8b719deba50037ac7b75948745c6bc, + 0x111160f9acf6ec360d1b6a712313a0dbcbe23e64420055471d2ee4c5dedb35d4, + 0x1377978e1b1f6a8925fa8e7b7941bdf8fb59ab9542342419283d8203435c9391, + 0x0defc1d8882166ef3ccde53a4f236fba83d384621937cee57e421a513d0d3397, + 0x2f8fa5c78c706e3a5d4a03f2a7a3953046d7e94cb88a7ef350e67b5ba0f0debf, + 0x1a2a957ec0a723da61c2134bab0bf17beb00e6dcd84690c230dcb9e58da94827, + 0x1cdf8710995f5e03412b4a7f699532f9fd01f0ea167a8dfc1ddf37e2805addef, + 0x26fd31471828c36ae36c27b748054b0c0c4fe5239b301699e3765eebecc18946, + 0x0775d996cc2c4456f303a2c1f9007647e11a921d9fea3f7b926143b99d2fa0be, + 0x016fb9337708ca638cdfda91bd0daea6b97224ef7b2062672addd1bd18bb8900, + 0x2c392fbe7d3fde42fca4f9478bb439331258255356f184af6f76f119054117d7, + 0x187a2a3bf79a69fa3e5089ef9f1fd56fdb47c55eece77aa228aa3de1b486bcb1, + 0x0271a863a280a32641ffa33510b2edd278c98630359532f3e506b275fd5d20ce, + 0x1557459c9c74c94aa00e5af69a1e3112fb69537ce897ec0c718958d96516f2ab, + 0x2a8e26ca8d647d9a6388516ea9dcff89083d539e58168c2a50c6dae30f109f21, + 0x21cb752194cf43f3b51942eb0040eba9de2bcfb1c2a3fae97924b710f26832cd, + 0x2c26daf996be247acd6dd4acad60d38b5a471e6322188d02c137e7cb484377ec, + 0x0240176ee0e7982eebe92a68d3e3a38c26821acc0f5d058cf8c137bca2d26f1b, + 0x2636e0973c865c1bd974dd78daaa8d0a84cdaf6be1ad47ecf2a0d18f117318f2, + 0x19e84f4f25a799496041661dc5d975b681f6e06744cee89b7be5d9fde1744ac0, + 0x0ebf89064a3af247ca1f36f6f3570188e271e0b326c4fb26664e89e1454ca110, + 0x25c7e97b475be00e8b559a38c452364f4c9c531fecb8ac698f7fd73ce22e71ec, + 0x0444c99e592353e5aecaa302add901c14d8c55270a160afed4429ef5598ad74f, + 0x138db8887830565f2693d0e0f02e4e79e144967f0ba53b03519aba764b5c994a, + 0x24d40f462114fe9ee02aafcf74b4fca24e1ae365dc75c3b52bb13cbbb2f21edd, + 0x21e65d6d8ee43760bca40e730b5df4c4cf3a8a732db148f4b2951b4c61d68e8c, + 0x248dd79669ec09dbf0350a15d6c75c6a9bdaacefca14d51300978f13d1ab6d1c, + 0x2b8238c1548f9cbe29fd35cf91e7b48f0ebda7e639edf69fe8d5aba7924d5362, + 0x2439fd239257f38181c7be3cf513f1bf7235eba94f6b8942a94cbddecf6f62f7, + 0x200958235281a61ba2c4be0aa3282a18c74b6d262f5de7c2e33d2bb3e893dfec, + 0x0e1eca5df88ee5f60cfa7e1fe5befbb719fad8211fa9b2d02fcc233190c17f12, + 0x26b53427f9b3ea2c769d9c660fc60881a169c12732d001b7158ee4b1b842ca24, + 0x20f3b3f4acafe9f8af3e06661b3a8f778fa2812522b9d70a67402cff8db2b1b4, + 0x211e5d2b39d62520a7a627ece8cacbac9f97506def4ec286928ba6c27d463b17, + 0x0bb743ee34802129c556731aed9d302dcd085313ce572f6242d13832e536b4b4, + 0x23cb2661b488ee71e4c753ff23ae4bd25d8a44094f66b6532977e22140eba5cb, + 0x03a35aa3123911cdb4535baed3359f5f6a5205b9c93ef31d35323a47807b8bc9, + 0x27803848a0aed96a93fa943b6635e450217e137f4ade74a62d7917322714b697, + 0x0cb37839c2c9a7ff79884cbec75f41e9be5e47c76d61538231bd8162996d6f67, + 0x1f0026d0bf1f8e1dd5423cc2fec1fb5cdaa1ecdc4c3cb218dbceef77c00d2f93, + 0x02a7d7bb970b8a6ed2ee66fabbba956b6da3b100f5b5fb928eef42f9708273c9, + 0x0cfd7f4215e434c8da17ec3258b0bc605ad1ab2e90aa494351e4ee40bbc491fa, + 0x180b11b720622a156849dc6f7f6e7f571659be69682230c5ed9ac339700a7cde, + 0x04e96a965bce3d3a0a24a4a457c951582c871349ce7eee1aabfe578a94c65011, + 0x15931f782b45f7fb656f2cdbd1f7705c353a23fe1d30a5a46a1522ed160df3ad, + 0x2e296e57c97a5309acd26febf55ac963a5444c1c5f703ad88a0d7b97b9dd38b1, + 0x26157bceb78e846bbb262f9a1e06d4271bde5a5bce8f0419952f97ffd13eaca8, + 0x2194eb89847d6b0f1897f675f19c0c56b61b13248eff3ca36e34fb9d1c79ee43, + 0x2350bf35477656899151ad7dde96ea7857e15501447008dab6b3d27c8ffa274f, + 0x1a486f0ae591cacdaf09c58a49c4d1795405435340819e003f0469d110b7752b, + 0x1b56dcf76fb23cc4a834d455a4065e133571402b7df309d59bc3105d42a8c301, + 0x1a749d7964af0b7202913ef204c653f2b4bfb65ceab7b685233ab59ce3bb6925, + 0x18ae590073f969696af762ffa4e8f0ebbf97f8cc787e37cddd1f321be3beadbb, + 0x21c47b275d82dde6460d5e769a99421144b1c5a9da59294ade9cbb317103f249, + 0x0473ddbd52e737e527364e8eb63207975c38d5fd6cc32b272102b082cd1518fb, + 0x0b12fac95b6d3a881d892657c8424e645ac4e6b00515f902d594574302b26e02, + 0x08ae7616a260cf6657f8f73ac284588d2c5f07ff425d837aa7cdcef63e3e2103, + 0x039daf6876280b80e873bf2a32fd2834a83c69757badd58a888ef819e926ce28, + 0x25e7b1d7470a3c75f13f0b56546c8e09f2d8efeff06ef766f9c783ca869d130d, + 0x1e8fd3634c3ff764184d03435f98584b11b5b15aeb9c75262da3f1ea2c2a9e7a, + 0x241dcc51ac37808a415dd1e3c281f05aff11789dc0cafdd77a35484e0993f9a4, + 0x1ffc3153c56ef9755932cea2be0573749bdafe1c4fa0781a4b8b4078ce9d7547, + 0x17630d62d9a3e510c88a4d43c360f92bc0fa00b66031adec29bd9543fd3a17ee, + 0x2980400edd1d74e3d69db5458d2ccd5fabdb236ec16a82a4301a0ab59ea4a6e9, + 0x3034fb24366123ec6dcafcad35726dbfb16194c036dcd648fa69439bfcd00cd4, + 0x1aa7e8f4189ca9dff3db2ab7648be0a2392995ce46041e04680dca8ad7232df0, + 0x1fa195f834a69e62372f60eb497da167646eae14153d803b39dc5d11f5d7800b, + 0x0f23f1c74d5fbf6195ad5a6aee5e56993c5477e8453f5b93a0d7bafd333036d3, + 0x016556fac9348a735ab50aa089c97151b3caaf0a20a34fb9d9370505a1515729, + 0x23d92b793648110fc5aeef0633f0c77cacb0dbbca1879b8a6f6e5df445e5f70b, + 0x2e4c10ec5e65e2f239bbc43c13031df2686ab40fd79a304b05d611b823f23b73, + 0x12418bbfd77b63ad5e16864ad9c32ffbfc5a3dd9b78ec2b79329fe5e0a8d2953, + 0x1e4a8aace15abc1d5b76a9e848431d2c06a78f72b6bebb1293e6c58e5185696d, + 0x0f3e96107decdbd6872c20ea09acf92cdf17a3ee1d1331488092d96176deb755, + 0x012c3780207f395cc21deb0abd951681eea32498ddba6ce897a8f9f0c2357067, + 0x13eab1b4e672ba1b1c1bb901769301f1e5659d03ea10c61de2477ff0ac221421, + 0x20dc664abb20b7456c06629ce37a1ecb1a27a4e8b24e31b48b9c4635aa30323e, + 0x2c6b1e2cfea78e2c36785e76a8cfb1b057e9471f24f5b391175c3decb01e000f, + 0x188c926255f5b7af3da96355729c2a8670ab4c2c70400481b2ac903740e0c5ab, + 0x2f9913208e09e3d6e9e6fba6384fd076ab89f2662976e3e30e0870bb30eb54f2, + 0x2b33803d90889706e714f720b5628d26fb60b545a1f3e9ce49a6ae912b024086, + 0x26ccabc10eb04327cb5cc3dde2abb36f097086c97e738c133c9f57077e748b09, + 0x1b16ae0d7c54408cb75fd931f246751f2b0c3dc20d79e82a2531b76c22b4d5df, + 0x11d0bb461bd8af2844f49f0f840c94ef9518b2511344742d1f5438fe3d415ae4, + 0x233031847b476bead0118d3db338e89133ec420d673e504ad647259df655571e, + 0x1f84e97895bee438eb3c92dc9b1846c9ad29c164387b06aeb6ed1841ed8c4dca, + 0x277f7f9b542f0c2bb5f45bed054f09624536010c3cf9452d2273193327f801d6, + 0x1efc9c9069e5068baac13d2e6645641b7d27e80fc23077161535c44682ee57a9, + 0x0d6ec477761e2efbac4f14b3bf3d5257a99e64c3f25fe104faf988b20fe5ff44, + 0x0e0e7d7c5501999b7d16173b59b7cae1f203bef21aebf00251881439ccf93013, + 0x217bef2f4f12c6dcc91c2058a23391cb77de53ca6e44dcdc6ea3d36fea326ea6, + 0x05780c88adf01531b50f817e3fe44447d29b35aa8a389c71e8cf1226acef68ba, + 0x18733887a6b2b3b4c90d8e4990196e23445e47d7ea5939ebfb89a3ee3d67b4bd, + 0x20bace63acfcae0b1c9f2bee24b8e9da85ba597d37b0905720c4f15db231b07a, + 0x166ea595375a6786ac527ee9eced73ed6bf550876abcaf3ac92b42c808b00d8f, + 0x304262a9eff4040acf43e322d6f52676ae2f853ec2e7a80db00c488cf917c74e, + 0x226bac7050166e5f6db78cd0b12d36f305b6e8c9a055114ad7709e6f57245b6b, + 0x26b2f539c573829f6aca91baa954505bc5c3eb4e1df1d638582717fbdf2388cc, + 0x06a0fbf4cd52e93ba5e4c6c4af65db02ee96297f8ad200f2f1cff252e769b551, + 0x2cb9c24112d35341aceac88360fb528924e58b6ecac321b9fb29e6aa3368ff23, + 0x20e88a4d607526dd07fe08a3552a44669129eb87fcc0b13aac8fe8afd9301521, + 0x1544649a2bd73e3ba72f396df91dd65401dd8faf51de325fbaedb9d536ad94fc, + 0x1980077457995712c44da7e17713258e3f8eb354bfd80ed9eaf3ecbaf6960105, + 0x25d1d22ff13e7705d3c085f97fc4e4f6914b82ffaa5d2091ec64dac423765ef7, + 0x2fec990ef556efe1035a464ff5581e74067445cd54abcaf6b8c0399fe0d24cfc, + 0x1bd9563506d9544ef3e4830e13545012c579379c2dcc1330416c4ae49bc4ec61, + 0x00affcd17ba6003c56dfa85571fc29737b225a80d480e7dd7edec01f14f23010, + 0x23670dbaef966881f07f919a2d883128c7b23cf767a477b2b2e0762bc0dbc18b, + 0x1f93a532917394c7e22fd17abeea6389c66fd7ae2dd9f02f860f6d96947f0edd, + 0x2de42e9f537b7d61b0213771c0e74f555512be07b6a50934734e2c5beb40be37, + 0x25c557f45b99781cd37d3bb22931662a67f78b37782c885b456bb96d55e88404, + 0x2074c8b709705c9888538a7f8a3c4aff647731bd16f8e254fa74ea9f2be7662c, + 0x2738355956298138949e442171d6a4e4b74ef2065740db7cfc3a0b60fd573acb, + 0x13d36ad0a4ebeb81969778649659c65cb7d0c41cc519871fdb71a9ea6a0caa56, + 0x08a2c18ba41381348c1acfbf9617716806b462a1691bc2e343b79b8085e376b0, + 0x059092fc395aed285807bbf557ad9a1041f59c079822b1088457882fee7b612c, + 0x161924151b5a5ad2d8cac119522a991a906f15e8531dc70567f6b28371cc24e3, + 0x1c68ca8f7aa17659075405ef6341b8e69a298b9a4d72f3bb854b309e4ba87a1b, + 0x27f5d03bca1c8207f7239a4b2cf73ae559a15aa37e7bdddf3aab05eec5ce5592, + 0x0ecbff4846962a975d347ea9a8fc465fb46861557622f2c2564a7e639833c169, + 0x277c4de2363d8b5b456cfc5a7ff8e46ff2ec8daa59855f5ad64bc0521f3ac567, + 0x1b11862c52acd351b7a464793f4fbb57fec99f832b63226f95d175c8d2fc08b2, + 0x06a719c584c74ffbdd7218eb565cb4c8bd86c92e3dfb3c73e1527201aa51234e, + 0x230e4adeecb799877f7ce9a58c836b99d533584a195c1d77a313abe1c7d126bd, + 0x10b109b864809c4767a133cce6cbad6c88628173b8ea51e8cca85830ca7de522, + 0x0e21117970dcfbd4b1526b253636f377538d3b4faaeb5a8b24bf6200d14cc591, + 0x2667349978401362f6b17939eeb0e64ff55607ebdb35c7071db46bb3e7ba4778, + 0x05000fa5fda505e029a13bfe304c267b0d86c72c039babf6d3ff02ee246be02e, + 0x264d9e094aed5f41a60242220a34a284089087b2436a9bfce8174cc9be8c2e20, + 0x08076f9c4743de6130ff622cf401edd2c92f24bfe114f3c5e724891746315c47, + 0x132370abddbb0b1dd57f2a520c25336bd7cede94b95bbf5c2151d6d88e641b64, + 0x08ff1116b7a227bfdfd4465a67890882b615c8c4c17f28d8d24958edf602ddcb, + 0x2bcb0b0db8b9e3e02b7e9c1c9460fdd9c6cd98562332e648d8a3e0ab94597520, + 0x12ea68ce6881becad7f8a6b117b03ab976f7abd597f903b0bf230d20d21a943a, + 0x27439c98a76688067a097b19b6fdd7d78d5f88e274e0d8fea5ea6b7406fdda7f, + 0x02f40d0ad05f5652e31ef9440ad71ebc8419e393493937f05f00499d02a99e36, + 0x2fbf04284327ee4f680f06bd390e309d0d13acc74b9c5b14b63059b8cc7abff5, + 0x1be686d53e2a8ad57a828b0651425cfc6978c7027edbf247f6b6723c21df86e7, + 0x2683b425e85a508f96852f14b4220fcfe9f7ad8b17bfefc0e348c47ca78bb57f, + 0x16dace9b2e8012e31db1c7ebe672d86bbe61a1aa3e1693e0eddfc0de0a9dd951, + 0x27a321f8c7d3c9022e962f7fef2e3c848b4539dbb75aa139f30430fe545bcedb, + 0x06ccd7210dee1d6b0e22b79e12d19082d8078b788d71007b95e7a774ed86a651, + 0x0a41dd42221653752bef350f6d74a917b6cbb1fd76a3a12166f4d0be978e4026, + 0x220a02881e4d47ac94d950cdf8386274d1782e27cbd0d845978deec91298f165, + 0x0e2155a545fe5f3cbb6397606589eac19cd92639339c6b017298a4ad3408b4b9, + 0x0f0f19c6291e51546a267c60cc774e5fb9d088bac530782d891ec1af4b847073, + 0x0e925bcd1c6ddb4a3a1c67ec8deefbd40c53c0d33e7aeef1b46795aed5943c9d, + 0x2ad000b1748abb812cd6e5411286b9ff3ef0a5bd3d259a36e45ef05b9eb5beeb, + 0x0a65aa232d32ed6e8de63d1cdffebc2f3fa616465c27aaf97e8cd3dcff648652, + 0x0263d8470ab4b1c61d74d8e896242f4f261dcb167a3a06923893d7cb2c93d6a1, + 0x2901d946addc94b040fd58004d9a5f8cd1926540c7a8612cec1c58cb60c2b3a5, + 0x1889cfa8209f4952df9022db9dc583b5717a0696da41cee64937d0cd6321e693, + 0x236064d71cb6c64c84747ac25fcf8d881502e5f03bff87561b85a116b1f39aca, + 0x2ff7a174ffcec29862e04f5dbdc73ebf3661570033576290c0c1f6cd8ced27ae, + 0x19e724a1d742cab103455f0040edf745a2696a71084c93e322715450dd4d6f5b, + 0x03eed3892b6f0e6c5da1059c5f3793985835aa283500a8129904a94c87f161bf, + 0x08e2b8273bfa30c1ac850306d91e468a9e8d05092aee4cbc80c687248463ba30, + 0x07adcca76d8337728839a1b6ac3b3ed42afb87d72af98f52f416f2ec58b28cec, + 0x171ef37896bae2b1020a0a5839bd51784ce11bb4237d548c171169d32fa19b40, + 0x20ffdfcb86f4d005064edbc296918c332d32fbeff1729de5056a26abbc3a35fa, + 0x08ecd7a6f1735eed86baa094e608f488f38dbb398fcfed4b994383a0ca8e4647, + 0x1c3f5d86e5921fde9890189f1d8c618754288600e6928bc182ac4d5e4c9f0ccb, + 0x29c61184ed9d460f337558a1af639aa7e3c0975e4014ed8ebcad4a25d51eabf3, + 0x0defd45b28958728228adbb2dbdaef6a5e9b1a64902a734f402b8cefb8ab3b56, + 0x0a74ea22d8a09336060610179ac1d82fffa9492df76deed4ea60e0133b0811a8, + 0x03a37bf12daf1400d297ac4ac13ba24c17dc262db16c8523deee4e0ccde9a680, + 0x11fe1790d5abbf5935ff22318e4f7ffe69966ada2f9136b54f830eacb0a65368, + 0x018165842f406375f2346686915afb14bf1fe0564c8858ee3bde0aba3de5f68f, + 0x261db25e7cff5a9fb72f276b1f9260b667300fb7d361b50fd5c0e8b6995b05f9, + 0x2a3ac3314b2b66e796fbe36df778c5e46972320cc43ec807048826b6704ba7c4, + 0x23caa4b80ecfa99e9d3fea2bbc1dbbf369d1bfc8937d03d074061c30fd8cd76b, + 0x27db260085e224898df145f23f635f2066d8e4e124e581e8c6261929b1dfe107, + 0x274f6c5fd34a784d6b915ef05d424ee6c0babbf369e79ab138b8167b5618ec7f, + 0x2c3a29e13a84d26a0911c9289daf1aa4cf5840aada0701d57e23dfc796da6da1, + 0x1ea210f2001a334d3e801f4e53270d42da7aaf317a553b4282aa78eaa2282e6d, + 0x254dbeb52884b699c1ba7fa0d6e80d610903b18a3e509c36351ccc3b024946e3, + 0x059e781d65896ebe0e4ba26dc2f29907f47bcdeda4a2ca2c713d8505ea31fd5d, + 0x0b5b1cec63d42d5e615dc269b885a24cef303ec78c972dd17cdbb3e915cc4ffb, + 0x2a7c015e9c3b2c57ca8b7d26d39a1bcc85d6ffacb7d9fbd66d2a8f1d64ed0c92, + 0x29b736b911d71a79cf63d8a6f786f11bd5abee24161dc567a7c851eae1e43b51, + 0x285745a90a7fe3d09af5a808704bc69c6f1701e573912df5cc1e265d596c4141, + 0x2d901b8195c3c96c8c36eb99fec0134ec2b8304ae810bd30da554e3080826715, + 0x1905d3518355eaba7859b591ed7b8c9c253980f0450dbdf54d7a7782ba058392, + 0x23e813026fc0b80064d19b5c5428942fdf7efea80bfa8ec4095272bfdb7b4c9f, + 0x23c0a19a252c87e6b1c1c21b1a79800200c3fbff3e3300e7e5568071de9efb81, + 0x11c4ae607bae492413bf62cdaa2c2868ed1fec6dc0631b067ca60fab125b9e2a, + 0x2cd055ebb7ee4686365dea450f046ff62405fae1b1afc9fb01707cf81da0e3b9, + 0x053c9fef2e021fa9a20fada22fdea1505b58a3159bbb47337dbf791b215b1452, + 0x0a35bd74e87cbabaabe89ad1319d2c9e863b4c631c21938c9a5395bf97872a9f, + 0x1c115056539ce20cd5a04d1a5c43e2b00fbe83b25901be36f5ddc4666fc383fe, + 0x242954047e5772fd3bded590ec8beb4c542f2e264c8c3e284cdc473505c51a90, + 0x0e2abd315b47c0dc93849c0cdf267e811cbdbdb200a6e7c2b67edf7cb0174214, + 0x282b37020c0890d751c3fd76950d8068668e1dfeae621dd552d2de887da2ea75, + 0x28933852266b52d9ea6b5bb923d9d94f2e5a5be5c778e75e07942c234b643bd9, + 0x099ab6765505ba1198ef140e77b7954d4fbe79a056ce72bace39c048c00da3cf, + 0x2af211d8e0ac2d8fda7f849b8f229a225c6186b55762c7a7b2ae2d1dd85c57cb, + 0x0cd070f234014a2809ab90c71c1da61e98a96322fedd99b6aaae1ca104f3facf, + 0x26793e2abc8d3c30c60626fbaa158f263587d6bd15833d448b116264b930256a, + 0x225be36ed0ee85e1f845ada84e5748a56699152113ff61b5056b6d8bde60c19d, + 0x02174f49edb02d5154d2beca2dc92b9cc595383da1fde8f09e4b5ee3ea5a065e, + 0x0f64891c2c8b020e46c3594cb758f0bddcdbd09bd0308816fb41734a869872c3, + 0x192a84ca2f99d36991e2d2b1deff3989d1c156c239e10e9f56140e1854576067, + 0x29dfcd7b63f05abf2753a8c341d6b7a60c6243b04c9a1b8b3320bba04a4d4787, + 0x1ee27ad6b9b5a867733afc61a2b3e76a52ba3e4bd5e657ade91fc038819dba5b, + 0x0ab4773f150c3f8ad3bc9538f43cec395a7e3731ae973fefeb623a09217e64c7, + 0x13c352a02f595186202cb0b99fa58c5542ab67f9b6d3a0afd103deeff6d80f41, + 0x2a97cf2c10c4bfbfd299f67c52a169f92c05b7dac56a41c4dd4fe87c8246ce14, + 0x00becbb47042bd7f8c9f6bb422162d1aed089a28482f7fd16ab06a13285fe702, + 0x008e44da21d738691b881757ef37ed29c5bd9f7a4450fcf53290a92cc2ca2176, + 0x2b205a8b6d4b7063d931f3bb5d3464053843fe7fbe4b83c17883f86527882a18, + 0x2d9e32a7c90556fe108d255ac01e75df338fcd63b2bf84c19280d427298863fc, + 0x29a322a84c25bd2ddf6e2e4200228d95abd6349a02266ac1dbba520738ceca97, + 0x0678c9bfc6f2df012f4fe55e33bb68ac14ced1df0d02152792089d046d828c43, + 0x0faff3a5e7425794fe20a7e0eb615b8b1760394b7f2304286a3ae4009124db23, + 0x1f8f5b611af9feb9cea86c084058120553e404103aee213f5a41d1d02541c0d3, + 0x160875d8479602f96f40acc2d042ee52c1588b6a29de4284965a6dc6c930ea07, + 0x16d87a5183a316a1d70afc951efe2cd667c77328fcfda458cbf5fe3045f46d9e + ], + [ + 0x2197703fceb4cbf07c6dbf46c4ad93e7d14e554db66d09102ff84824743fe4e7, + 0x1322f0fffc7e4854bd8b5fc23e7106b51f59bd5061d8b565aca2fd3efe512f79, + 0x19e414f80380aa2d222133118c337d82a8c5894c2f88861ee46f448fa9d61359, + 0x22241199a4df9cb7d65249d9562cad6c65f16460e79a7939cbfdd6d7b9209d9a, + 0x0301061735384dfcecf9a311c22ade327b51c78b211615f41c77f6d85e8a41b6, + 0x229e1d86c1f2810f4a2633b7b4b5bb61b7dc5d19ac95fd8d379548ff2b6850ee, + 0x0e31dcf9c53209a817eeb292e989727c3f56bff65883afe5fdc28ac3dfbea675, + 0x222c7318ebe96306c9d79ac11237263c6b8eb25272eb88407e8c29a358b40f2a, + 0x0cb416b42c53a829cf4fc823be8f4fedd12593394cd529053ff4e3604974a2c6, + 0x0892729d09594a8d8b1adfbf2e2ed75399dee612842b6db3d2d2c2aaddb6c0aa, + 0x18e39e9ae45f14ba97a15bd672711ae124375d9f482a4487a0e334dee2d27c71, + 0x2560c9ff672e6ea69dbb33844d0d22870461d18eaf0f8992d4d7ac649edd6610, + 0x21bee2b8ed54b726ef17f77366b1dcfbda7ccf1e487f9916e5f963e814c57312, + 0x300e1b28dabebdc0d4bdbc19be29a3dee4eda8425dd0c7c6e82fec147cb070ba, + 0x2c44a5ff45deea69dd2961d67011af4982b9405f9fe38de4a732d2aeae88cc23, + 0x0c8d59fe1b7f55095e6aaad9e3b4e7b1c93d876ba3234dd1ac5ec64108291bfd, + 0x06cf82bc5fd115d348a30b0c45378d90cca1660446ba049759fa53103fcd78b5, + 0x2f80ed01a2118d02e2145111c3fe6ca70efdf95d8abeaee8829293347dc9061c, + 0x0bdfe7f6803e4dee7b026e079075908cb8414e3d651dd12fda67df08dded9e42, + 0x06cc48ed882405595b34d39138f50bb5b31a963a0dba66aef17c19ad622e29b1, + 0x2a67f3ba6d15949932ac5622cf9e2b493801bf16a50336a4518258bcc6867c95, + 0x2572725a67c60718df656934aa78fbeb80c8f395aeb6a20cd833c4b14fef412a, + 0x03bb7f6ca43545b11f19721265b416166579cb753330b1879b79685d1df0bfa7, + 0x2412815e863f8f3bc28bfcbb957faa5f393300b25133e9221b8eb3156ed5c12b, + 0x0dbf64d58df212e4307871966de097a5db09a93e5bc305cebdcd0630f433af45, + 0x274c06c01158e047ff4a791e25b7bb3db190529df8f50b6386273f810f15c6ab, + 0x23cf40693f52abf0ed3d842f7bc85d1a2111d0abecfc18acd0fe3991ee5fd33d, + 0x1daaa926528f3368f4e4cf924166b8bd3ff8daefbcf900e6dcc4ee63c4099698, + 0x10103789dc9471ad718657bebb6781e39bd92fd20ee1a32d0de3ea2817a01555, + 0x0009bc25065080e6c6e9932e34bfde78d1085f19e9ffc8965a4660a4d9b6d607, + 0x1312c727cb5489bb174e1dcb82588edfab31a2999b377dabece466e9dcd6afee, + 0x20294a462c7d0c25aeb5374618e5e77316682ae3d726824f15f00f7cb9a7009f, + 0x25e0c6be89bbb04bd8391c90cf35588f0e9d73fdb06259f47a05513ad7a23e91, + 0x0084a0b87e0b336c9a911069f89d875a38be313efc420d28b9ec287f28810fd3, + 0x28a03ee29f612aab268f76241d54d477a1d97f5807ba2e1812f4d350d7c6f7da, + 0x0b6794182b723a12e0b35f76bd55a7d106ee6a4035527c4d329a6f33068d7eda, + 0x015b9a698465428fc686b79db4959c8495b92b85122f6a6932940836facea86d, + 0x1bfe52289f811f5c3619f14866138ae9a1279bb76e8cec9a8936fdc36f59df7b, + 0x1cd574fe8d5e4c428b92b23a9717342176e1d309a7e259052c31bdc9af091fa3, + 0x212d1bbdfaaf0200735bc5851a156adcbfa4f607f5da122e1f63afaecd38cab7, + 0x0b0479e28820e883d903a951f95b13093788e9e1ca64ddf2abb94b13fee9edbc, + 0x0110f5257c21c9379d73b76e9ca95c513c77a15cc8ee0ef726d8460d4fbbdaaa, + 0x08c52e9401a9764f0c2487dfed34e215c186b6c2838e38eb5a50cca4f0bc6994, + 0x2e422b4323cb4c0af46f4b0e5052f75744c538abccc7643f339440dc3aaeeca3, + 0x2e12482ba160472d45549ff79cd04aebc4a327c4bb9d78c2573b835b05c55fe6, + 0x124fa5f9c5a96d6cce92cfc73ea2446202f09100eed203ae4267aa637a032d36, + 0x0bf651f82f83ca1fa037a941d4e2a4b3e08f5e1603f933a1723adf4135796de7, + 0x21c674ea7b834741cbad39b21b242ab9a5554c6c9f92e801cb1fe4382b619463, + 0x214f91d6c4aef57e83186b57fd9fa48a193e1caf16d7f6dc1559d144a271b341, + 0x203e2218389729c26c6f66213f2269c262785ec68c759599c2d8e3f68035055b, + 0x1aa934198713ce17658f51293fad44b1c22fc80391405ce76c92b2349b7eb3a2, + 0x1014d4e5ddd9c17b3c2b29684476afdbaf7fc56e8b799616a67bbc6678e45351, + 0x033c13ed45b4762a47e1d2d45d7fc8fbf9d4e24546e20dc596911fb991710358, + 0x09bc1c3274c569e7e5c5d77c51fe69b23b7e435138f4f3217016a2d70ce71d5e, + 0x1803171c9dbc0610e38d8308db101d6a99ca90137f6ab8cdab2a91b36b63322a, + 0x0ba6071aa98afec3fbdeb46a88e4a5d17bd4454c0e7da8c74b15b084488cfdcf, + 0x179e90ab4b08a4ead281a8709057487e077b710879911f215fbd6e8ebf838e97, + 0x1cbca88b8ab3f0588ff87deea978d00008adbad808e6510897238ea007f491a4, + 0x2f50b20b33692bb0f62777de5e3198377d7923ef2fa8ede08831e10f7e9b9f5a, + 0x15ba030e8f1ef6f260566fd6fcfffcd21a1cfc1232f7ec7148ff076d1ba68707, + 0x0dbe053da01aa4b7c0fad83a3cc966f0b8281bb4940f97a5516cfb9dcd543a6f, + 0x222eca5d754afeca8997f31d6fcb94a5d799afb795e68d4d8b0ce6d839f6dd7e, + 0x2abffa43d756ef242db7f584bd62405991112618362f1b29a33ee2131b46a446, + 0x03c92524ebe67300d0dd0aac464f0e6ecf962d6ad41bf2685f077bfd788eb3fd, + 0x282241758ade4ef8ff3858305288d3b4a52209295d1a4bc89d885b2f5dc3341a, + 0x02635cb973d71bb3d2137bd81680dd3bc607fc5487e898c4c2d83c1dc2817687, + 0x13c866aa66e8d506079dc24c2df7b1e691994887d35622f4cfcf014bbea223e9, + 0x151f0007ccf42a7ef969f1b6f6315992e6594bb5344d2839fee6620b60e2c023, + 0x1c1c6a5ebccee8caa4dc7ef18e194274f6e198d2b140ddcc97cb15c92ba1409c, + 0x18330c9e67d62f7861a996d7ed69bba904b0dd459f2b254fc7cc53dd28e45a65, + 0x26b747740c95bf139cb11bdf02fa63a4bdb29a90f158933a1822cdde5387290d, + 0x1475676fb205084246ef9bc7234f312c214f426852dcb2ec7dc3772f579af8b1, + 0x1b03ad9080d29b70aaf30bbc3200efffe73ee269dc032d2e32bd190767bc380d, + 0x21c175f937c2f82e99735bc7c201284f89577b27a1f84fa24642eceb552f4455, + 0x1192e0269a6b66a8c5887527aa4474c2de91cf8c71ebda835df2cdccdd4a4e4b, + 0x0f3a12c0ee52f0d34f2b4a0dcd13541b48aeb3d5121d311113bba9792a45a58d, + 0x07fb521883bdf78b33689205b45e52269458a061bcb87eeb3b1e183c6d7eb5b7, + 0x248d0e8051c1a965640c96c6f010c4931fe648b96f95ef6f5b8e474f64cf3169, + 0x2ab553db9ead2c82ce91febe180529eff3521875f7e90a9b8b7a3c4de4877cd6, + 0x211ee3bda3c95f1954eef22a0a82c2ede8444e42a72a8200bab6a133846d5b5c, + 0x111db3b5184ff7412f79c129904a9cac4ee65a51c2062d66732f54bcdf767be4, + 0x1a73843264cf9a3a1bb6fb68ef76037c4fa98337e5c10096c630b449ec4a5f67, + 0x1c2e5a2d9332f65128c85358662d6a7c44353add09c27cd07da02f9144da855e, + 0x0e2b35fe1021b879de5b67a7458fa6188bbdea39e2bf468a1a24e3625cafff98, + 0x2e568594e5dfbfadf272b8d6e8c99bd785c4fa94ce9e87fa8a9a37e32c7a28de, + 0x07043c7571cb7dc5205bfda42d693527a4bcb58238ed6a6a248e7917ddaf0c3a, + 0x239e18a0c85b845ffd6b85e96343f1a8378f3c691dadfb228da6ff7aa79efe1f, + 0x25e247af250c564c00f5ff1cf1f2bc8606600f173cb65ef0780af9f5a1b676c8, + 0x031ba3385664544e3e0801f1698b15033a6049b2504e9cdc2c6e3eb2fd12100d, + 0x2a33777739e2ab0adfb1ca5687db1e059b20370cbeeccad32da5c3609431ff65, + 0x2bfd6f0e9e996ba13749327b9c5cec69903d413b2df29b777d05384b3e7af952, + 0x2d453d93fb36fbf8e36747ee92d90cad9e02e692d0748c07fd43eafc2cc5e823, + 0x187bd8043f8642cda2b6bad82958d115818880eb80f6b730381d974ac5d5037e, + 0x21aca605f92a48ac35708fe5140729fb35c3e48ccec441217713b08649443930, + 0x173fd164f5224ac06c2e99f3e2eaa6379df113de30aa485e8bbcc7f0fd2d1e03, + 0x071c66a6463c3fd4292bf1e5acb6de611142d73cd1db590e89b61b57d44d69bd, + 0x044a40e396855be550d8ccce7b82ee2caaef6675bebe92266c666982ff72bbf8, + 0x1176d9f52e12df67f087110a15aaf98d1ded293ffdf99599fedef2e51569e4f6, + 0x06e8eb7dd026d257b15c6624bee2f37d5b67b4a671cfcdfee5797e8457b63916, + 0x0696aa48c1d5fe84ca5cf59009ab0baaefbb612e32c91d5ef306def38dc5673a, + 0x0853c33a9c7a7c3b355c92c75de444365db82d241eef9f3fac417004a3a1accc, + 0x3016c0ba34678e0a67f59cf96ce16e908154f5f9802591717e66e95ba25ab77f, + 0x0af008601dc9552517f303ff9e22c793a682caa93256f2f09a4f746542603b0e, + 0x04cb6d76b5a27a5aae387cb647790318c25fc16f8d7d1855a38765f847f731b0, + 0x2ecf70c372d8e5edcad49e58d47875f26933d62614f266e6b4f586177148565f, + 0x01f393a6ee74dd6c4d52b0e7820a7132f8c4889742313c06caa6ecc55f3dd413, + 0x2e4d4ce3f97bf96ff86b88e969d13e415e14721282769f7cf8c3a73723f094db, + 0x306000ef24a7f5a9c652e3a9367578554ea59bf8efa0bd8bc5776460c18c1add, + 0x26e58d6287678f3db9c225c1d3b93ae7c43a69024ebf249c8bde40617c2b3d49, + 0x09eee09f873d1bf683971df4d7ce56c8f0b8b98ddc05b9612c0a0d317310655a, + 0x0f08879dfd4fa0dc11ded556ef01c6f94cc6f4d18553b08bcb1dd604392ec00c, + 0x11459f7e9f0e3c727777e34d6d93ec28a25bd867171523bad5be0d5a20029eb7, + 0x04e9cbb6f6e8e805a20fbd801a53b723f78c1f5acd227880f7f37f4e5b0528ad, + 0x2d2ff32eb7a0c0266dd46bd5939c9a9aae88b3e9af5dad01a7304f9868f7c7c6, + 0x23b77eb0f27e950200a590447d645a723d9b405fa2538a5cb76fc5fdae16d839, + 0x2cd6d2c5658ec0792daee2067e2f958d6849886318a6c1c27233a469e9998c2f, + 0x0ae1daa420bac90780d0c83026bfcc84af83953e26eca839da76861e739855e7, + 0x2b495b854553d02a75b68763bda6dd8ef0e81fe32b5cb072d3f580a914967bf0, + 0x056fa5d7ce2c32bc5735351d2d48af5d6c9256a4b72e12a35640b53ea959e296, + 0x2ecbe1a06b28ec78ea7d22df11cd224a0e1a0ac7a3476c5cc3c4e50da961a87b, + 0x143053c1c387f9353bd677e5db6e9975792bffeecf02d6aa0fe8f627579fe6cf, + 0x04064b25584499a011ea74ac047a8b37494189bc63342bb1182e234212d42bdb, + 0x100f61f6b81542156760a6d29af5dd8644c82deab5b90e6ac66de8b4a069564a, + 0x18d331b2e8180b7aa7055c029fa77aff4f02b0e2a2078bff67688ed65b51d6dd, + 0x0fcf9b89e19b1a55f9b03255cf80ccb9fb6aafde2b46207d873fac80ccef085c, + 0x254f801f3c89c62436ef63df67d912c1f231bb1f76c6c7b497f7708dbcfdc17b, + 0x16d8e85e57819a10a61461bcd8d3d3c963c4f95afba3e4d8fd0d6ec882b9d161, + 0x29c9565aa702088bd443e4620d84bb2bfb93253a8f0f04e5cf408c92820ada84, + 0x294fb68064643d8beb237bd705a557871b5f1408624eda46d47b583a60d29cf9, + 0x2c26f3083140c104baf24c3df922317584aa11770451e6a846de7dc795197313, + 0x231811279854707dbaa537cb27241e7021a949a1d9671380a7d6944c838904cb, + 0x1419365adbb91f1f7d1bb0aa8a4b5d11c7ad0570cc6cf3638be9c5a2a275b495, + 0x1674425f2e9fcaa66eb001feca48ddd4b2a29e86d451f00d176ea35b4e02fb84, + 0x291f956def59b878028000cef03d7b54dcc2fe1dd5a75dc180d6d5bed898cd30, + 0x2f1302894fe6a26b5bc03fbaa69c4d95012394d78de494549c7057b7ef965bcc, + 0x0627d6d6d94d0a19a17db45c0796f7db8de13d278a2b24c99ac5d92d0a1a1ce2, + 0x2ee297662bafebcb01df8e62bd5f50f03025515b10465d59f3a294f0bfbb2fc5, + 0x118029945df773f52fef5429da766b902eeae7d967062fdd879c60a1bfaba75b, + 0x306042d262f6268ba789eb4323c2169279752ffec6b8536cc68b53bd4df0e858, + 0x0472a13ac7da9ebe1132e05f9ef609135c82a0ebd9278def2b34f8ce709aee4a, + 0x2e8f76b27b474180f00c5a6c2d65850bbf96019bf0d76dbb4743a970f42a130f, + 0x1e33984165f47c204a33fee31f613544b7d846a7d5ea45280ede4b362c32aaa4, + 0x17f22e27252bdcf91a72b59eb276a666ce4fea7adfbacb2ea9fdf28524b7b43d, + 0x00547e7c70ee4e3fb4a4d386c8baa55d823a0f02bc963b43039b8847cff6e6c9, + 0x08ea4ccbf815be325ccd15494f38f3f97153ab09c54a87a852b2a99480724e25, + 0x277cb45f3e632718673ba05d48c712fe7404df9eff5401cebe45d194c67fa8db, + 0x0159ec7ea49aadb3a8b0a23c1dba0023807b0d099d3c40b69df866a92dc87b37, + 0x0c33489297e244956de579c5c112ab40c7fb2d89866a28418f660a86ee18524e, + 0x01bb4fcbae28a2f3399568c6b3849da27d6ddf4fe6adabb591151679ed37d21f, + 0x2a23343d24a9cfa3b8f413f52ee1b233ce4c1d5b9bf34b03dbc6d733d52305c9, + 0x0707a6d515b3bad03a9b06d6be048defa850134aacd120f38fa93264016b7786, + 0x1837db5401dd6ec30ba6b866184da56e8db439ffd04154ec469b62120ce35cb4, + 0x244872a0d2766b8547e6b6a5afeabf198e1409a0f0026de36c101793952f6cfb, + 0x204fb17927ce873c761196395f7da46f679ca331832a59fddd2ae31e84eba1f5, + 0x056f53037d5d8efc7cf6a6feba18d102bf818bbba70b86dd9b763a12072f4c2e, + 0x1df4bc5d73239f5ec3b89efad53df9cd8ad8fca543be01f5f40fea2952071bd6, + 0x1ffb6ccbba001155d46e167d1fad1c13bf2892ac87cd9c347c734ab5ef658367, + 0x08ee36e881496539b0abd647d353e51b63fef91fc944880006f2c26c2ecf2a24, + 0x1c3080c254443332a3e6283d5bab6f7fce8aaa68487b9ee4e372cbc6cc172665, + 0x2dc6040500e7329f75a3cefa4db49f9b47085b1660f8873b3e81b7b1af82af53, + 0x2c8bca9dd293bb67db1f66ff2e82047ae9385ce67d7f33568cd4c216a89994b7, + 0x2a157b9786f9224cf63648aaec1b9f61c7a7087ed6eb8ab20c6c5469d401b7df, + 0x1e0fb0cdd8a54591c42e7c26b9027b77417e4e6522b472bfe61ff89c39bc40e9, + 0x250144d1cea033fd78bd73ee4ea4cfdcd6a42f7c00e2d7ee6794d464207d2b3d, + 0x0b6b3fe9a7a525ca60443c4b78a8e830957aae0403116d22983a2e680eedff65, + 0x2fdf613e67d176569f4743b4963f8c53e52482fa32e705247eb650bc7bd616e9, + 0x048f64b14275fb86fc55b3c0469cd89306752827c3c04463be5bea66fbd7b38c, + 0x0f2027b781c2c52490e11ed4b7b494d66cdc16e690b6a4b3c924dc9d6e854832, + 0x29652785160b261c1c20c741524a26147cc3191f33b74ebf17d44ce2f88b0f91, + 0x1176909e02a5b37bfd47810fcbe73af87fea130470aa44bdf6b058c4d359e179, + 0x180f26c6ce2a3a477baf0da58d069769c2bf0156d636f2255e1bc35c01e98993, + 0x2afeedcc2cec57285ad22e734fb7fe3dd65f62601c1ca4884a86c7a6a05f083d, + 0x0dd21a87ee22626998dbcd73dd751affb49d47a02e995a41bca26399103087d2, + 0x1d21baa09d7f50f0159fa8a0b6e0d61446d1c7db5d1566469da6a85aa7224962, + 0x2dc59c4c9e275cd8c2506282cc5bb842c014bea4236b1bc27a856351b48af802, + 0x2cf62d08541dff0919ba68a697f44f4791c42d1447a41513ab9d5f755eb1f38a, + 0x2f5b8853e2cd2e47a9fedeea4047e46083c97acd4b687aebd2264e7a0eb354b1, + 0x05865328a9b2fd469170c391c5ba8db5c66eef9938e4da5bae33f2703c470730, + 0x29761c9fc3d2c4cc1b126be1dc0470a97b8f2725d327c6d1ca923c2aa8092b1e, + 0x1d3fb1f8dc3c77cb515c37bc810d3a5e3b96552d4bbb57fdb01c2aeeb1d9a048, + 0x05f2fbeb7cae0a35ee2f3a4d2964d241a0ceeb47b3f7c4c87bb3b052c8705d90, + 0x1f445014a0f266082a50257152609cc219062154f4d7c13288746954b97998f8, + 0x2d35917cb1d0ca611ee37cfd9078c924fc84bd1a4bfd7db3ce39e05b38f698b1, + 0x05a89a4eb40387b8512f2f398b6526efe76716951c500fc8dabc835775335ced, + 0x04e26aa3f02601174f46ced15594329e4f4e5bd5d7d53d5df6c8633a94dd01de, + 0x204d587d61526c1e047e1dc6b6d403b9eb8730f2e2dfb7bc7350d939bac5b90f, + 0x21c8ca213d2f44446ae90a6bdae5843b7c2cb53ed699f36675ea8280a2a420e5, + 0x1303bd921f32fa4c4e73af21457c46b6d69e2e6a2c396716217787b46e822ebf, + 0x0613823c5b6abeef14387465317e713b45ace79c0e4433d7c4d352097e5c8399, + 0x0f27c5305ee978f4f775e213e3ba12a901f51144ce1ea89bb5046930f5ec55d1, + 0x2cad11c693c6a627531950a307e07b30ea8a495115f5a5388827792120c7bdb0, + 0x16bb256883c44cf37366618e46c6db4e3da97a9d4ae7d5c585959de3272f82b1, + 0x29afe50bd78f72cc763695976410324bfd67157a5ccdb7ae45b00032e1d57a51, + 0x09329902e59e5243a726ae5ca35408a207148609ab3698139725aefe29aeb167, + 0x04b1800e600c90ec4776bc6af1764ccbdc10bf55c3314f42acd0531ad53420fd, + 0x298d0110bb90e4c35e293c7a7dacedef7ee9342a591b4330e27276aa13b67ad1, + 0x024ea6e68cb1aa6b407e022649aa32d1b7ea4a350e510c07eee43929395e4f82, + 0x22ae3a1a81c4550f5fa0116e135d2df2bd9f6835a0f0d03f4dd934e1320a3d8d, + 0x1f0f5eee9e9abb2a2f4ae04d6fe09311fe0115c1e199c28e22705e681442ed37, + 0x023c86606616f317af022464f350b4bee80c2fca32064bcbf83e8cd35dac06c7, + 0x2a89c4e5b074fbe67d04cb03efe18c4bf904bec4759b33dad6b2c86ebfd2b9d5, + 0x04b0f48c4f2e05bda4b9cf806075f9c275df2cf60b5fd11470eaa7394a82727e, + 0x0edde5a2c01327ad042a686f443417bd8f107c99eb7c02900c931a7bd8cb349e, + 0x2cacacc9c9d8b0004d8932080f9378b60675a8bd853aad1dc50672f137212cc1, + 0x0816f33508621f2d56371156b0a3f7731030e4b218e44c90a88cecaf07170dec, + 0x2ef8e0a455d472b49bffda935c8d3bee1ae9248608e2a52d53f4b76313c97920, + 0x17184a8af9199aba605dd1f2dd18ebc02e3055ce408068eccaaf3ea7c0a334af, + 0x16395e153937a83660db6f78446cb995836436602777d81f0607130b44881448, + 0x0e174088223c38e9440fc77307d6720ac32784c9d2f591e2437eaea9b8f5e2bb, + 0x19e70fa937788f7a2127573d56c8197bd0dd096140f39064865c65c31b47d402, + 0x0e434c329d5242adbdab24780495ff97230beb344b918f6f8d6bd7d21b03692e, + 0x2c88a82eb87c81ba42a211bf2ef3c15875ac157c7f3868fff35af9f55a8c22bc, + 0x111dc223e3c9fc7452a9c2de469383915f33adf4cf5b49fd2e01c51d09ccf436, + 0x10647353de3197b9cb48f4539b507e45393b000842e8baa1218af097f871baea, + 0x0e53d64121c0a851c1b3f07423582034abce698525d0a47724354c07152f703b, + 0x2891938acb83ee193754969f4aa5a62a531081dbca4dec226258ea92984b4348, + 0x04106f95e4ba3fb74dbe4bc53abc170262ba00c7c63ed8c457c3227532c12ce3, + 0x2a73e61b8f1babfbb38b186f401eed0d92c5613ba25dd2ff4d099f7dd3c19fe5, + 0x18e16b24642f19193b798b923b8dd25f6e4856d6b21b729aed2281ab154f7c5f, + 0x0d5f849b166ab9f6fc1a64467c5557029f359a2d0f194030c4dd875e12ae3485, + 0x0e25250c57365a29c63a4f1531b8b0ef523eaa93c1d70acd0aa7cd7844dd0442, + 0x0f813d14af0c85bcedfbf480b3d80b9f335853c60188526d80761274074a599a, + 0x0d2356a92dbaae8c24a8cebed6428083ef2f469460f166a6e774377e78055435, + 0x1fb6dceb495bf90fff56c8aad70b40bf773ea1003cdd092fd77a43961e9d7dc7, + 0x2c0a70ced79951a75e23c5a323fd706c2ab87c381cfc3c269081627741c2bbe8, + 0x13dc6b3bdb05167dceb4b11037064ac5fd22db5e229e4c6ba55e8382321dc5ee, + 0x210fa8b777907ec30bb88dbd7c0e6ca9004eb3425d498025da6c90a47c35025c, + 0x0c5cfa957139b45a72fbbf80a410aab5454a982668baf24b0dd3c04e4d599cd9, + 0x1f1f3bc4c21d633400fcf8bdb7be59b7f65cedc06bb2fc93a873b6ef12e0f52b, + 0x188f0ee95a9dfb03cd5e3fb30827057e933711644ee7bd57490374c0d67532e1, + 0x0823877ebf8a842b77e8e0f3b44873e9409727101b186cae2b80d0cfa726ec8c, + 0x0fe81603de39ccf148ca6390d6f8bdc9395ca2f3f50878283d98f1f0e61b1aff, + 0x2ef61fe192f52a9d7cebf41c134098f2ccae35cabcaa12963566768ff1b83706, + 0x0db6d076b2dd1b9f4d56d2f66fab4d7bfc6a38fef7f9ae1d4c2f8c44b1510f51, + 0x2a194a4ae8583f28189f9c011d107b82f279e6a0f8ca8bc9cb0aa581831c7d06, + 0x0ae539fa9ca67d4af48fb292f9188c9e72f2eeaae2e500b7e7201718c8da8de9, + 0x23f66a894b1df4d26a8baa6d05b1ace511faffd4605b36cfd12bb4c6dc2bb4d7, + 0x137cef522af2942aee9a4fb8017bf330e64601f466b56d32245669d9fe5ba707, + 0x187aafcb87841b2df9d64c1767789a6b221767e4634f0d550063a0bf92788c32, + 0x23212e75f4b89992a3647036ee36d74938bb9a9851e13d7b6e52daf66c4cbd25, + 0x0f54cbe967770dfa9d068b2fc53abc96489bb7d266212654d326de6b9af16d63, + 0x23d83a60b9887ab4359b8569ff3a219bb81367955fde72a62002d3cd51101fcc, + 0x2ea676fe7f21fc583ab0b0e189020d42cb22f044607ee15bfac7dd66da5ebe76, + 0x16f37f357a0c584821a356ab56a16d41f045029cb515f58ede001f05a807890b, + 0x139093b78fc9603a4288ae5811ed1311be916e4c97d35a5cf18e4b7e47d13b03, + 0x0aaba5fcad1c047030c8bf246f41610b68d60bad285cc15f55900f52778a11ba, + 0x1611827956f3435c1fc67dd3d37954a255eaa0196cddc5d5a6187fa0a2839efb, + 0x23db56362f248912421e5f087ad16e0c9e6d2bb59db30a52818e41964b7d8126, + 0x2f215e640207a88b02999c98f1af8fa17331d19ea3de1decfe8f2e478224209c, + 0x2b2a261917c0fecf2bce19021f8506e378e9d3e1afb451e9d162b3d93eed8612, + 0x2f662e4cdfef5f822cb956df75b17b46f17b08f930f54bab4324a0363e23384b, + 0x0870eeab2e7bb1e82c426c2ab1d65fda25d426749a538b4ea669eaa31f661a00, + 0x169418dffc99f2ef5dc6b1013717c134409349d846457985725b15ac6a152fac, + 0x021d3cb240d6400339ad5bc535b4fbb40919ce6b90162e51ec6895a7cabb4375, + 0x12e45c46c45b660b6addc149e4216eeb6fb19474c8cce4d78e34c3cc18024afb, + 0x0c7c86394b7ad61d8c348d185403dc77152fd310b5d05970375a11b5abd03548, + 0x3024e78b217f85d8efeb60008ff70d33c3e84c238d9c21a04121b498a2fbb131, + 0x235977101b56071ced3163c1ec7187909a3ed7679bb54ad40811ba318e1afc81, + 0x14bf885e66f7c01fd974efdc0bc2d628ed79ad6fc6ba511c5a8ec383e1a73a70, + 0x223325ae7e73cf093e1d5891aa92ed43f82610f1283f265f56548b38072f38d3, + 0x239a5ae138dce6a019f44560ef7c19d2b8025dadf040559226f54870d318a57e, + 0x01dcc35115d9057efaf468d7c8a7d46048e01359c974855bc99738f0b247672e, + 0x1359a40012c5332587a4deb5604a436e269c282ba240cca0a6d77b343e76bbf3, + 0x0a9ee39712223d4c0c37c26a96f267c85fc8e31acaee0c07354d3798dc5003e7, + 0x11812d1ca3671ae688a9877233eeb5ec29868f7cd7c5e13275391a84167e0231, + 0x2435cd699bc94985945d878960770f9298d40c0e28b6b5979069e0590952f0b8, + 0x2bf020785e4117a1ea5930cd5355303bf9aab2a1ea0d6685391f40eeab2af0a0, + 0x2cef6c78577c9e97a76855292ca92e4269ac53e9b7439dffbac2eda5c6758024, + 0x09a30e00c9f0f6f260f05f029cdaa7c7afca506a5ce562c877b3b8d543135429, + 0x1fd85928f8c8053c9b264a74f121b90bbf9ae8063e0e89670165b9ba66a3e7cd, + 0x24482279d9efa57862a6cd4524aa289e6950606df8cdf8fbcaed4b674fdade91, + 0x10260a39cfb0d82ad8182a6951f9c780a455fc1de48c417d6ce6b27f36462185, + 0x25207827a76052d489bb2698730d5c3fc97192a4420578d2474a37ae7d7e3148, + 0x28e36b634ecbdf7b8e4f9e1a347df95d771f15d97f2d5c401edf6a6e375874bd, + 0x073f0dea6f83d443ee3ba27c5b7f0064ab7cc0d34babae859f6bf66d46a1e165, + 0x14c6618569f748ff65514437adbcfa97f87b9b0d169048e84c553ba9888c451e, + 0x0c7675a042ba6cc74fa588a0b26fdc4f2d1f119a0fe6ef111be6a2d45b4bbcad, + 0x03dfad7db3f32c6ed8130c43cff604dbe1c29dbff250c684c955f09e495fb34c, + 0x20114281fbe35c188164fc6d4144200fc1d9ec433efc677480bd2cdcb35b64e6, + 0x29e42f5218b1ea3fad06a48e2292c0fe3df08a2c4a823a3be4b998955da8a21d, + 0x13bf4039488d94b1b6a67f256296daeb6c7c80fad2726d6e9be11e17c2352816, + 0x1847a4e36b3eace13de58fa4662a9f88c9c17a464e6dbd2083c2938c227ee3fa, + 0x0a7a2056c7b79384af9fe3c6826830145f51f6f8ca5d1a344e295ca7663ada27, + 0x181278caa15bdfb5940cff2bc3216ff06a45962d4979dfc0d6c94993bb7de86d, + 0x0a8a6f4fbba2ee09a36d390fbb1485fb789cf3f9f641dae011520c8f10e57a43, + 0x08f6b4c0d7bd5e4c87fbc6874520e3329c067b6841fc833aa37514435e987cea, + 0x2206b2c18f3292e7a9a91039683a55d813dd914b0c7d523210424ff0f2817df7, + 0x0186cef5c04b3a6c32da26405a16cdd359df57be8e93291acbeba3f487329cfc, + 0x075aff67570ea17c7c79c9114c7a10d533c6080b6d15a5bebd1204fdcde772f0, + 0x2b06d8389ba9621c3869d2e8b25ac15e2c97389caaf7f97a35700be66c1655a8, + 0x04fc6d0a6b67744428161cb5228a94e7c0e95dede804b2b47a18055acd737aeb, + 0x25e4a295b4e7a2dc71394d41ec2a8f4b124e58c234448a028a2c3bc6ad25e69b, + 0x0094c24ab01c6db594fda907b639a7b3a54301439340e889b6ca9cb6cba067b0, + 0x2751821a6e3b2206cd6bc3cd5d98cbae8850745ec6cbbea413e7254d2a514549, + 0x145aaecc24e3878db9a8d77149b2419ed5b42df025ecbd1a8e97d8b817904bb9, + 0x0d2aa00cc6e5167d845ee1877b7aa059b5e5151c57e4c163da3403f9a95755f2, + 0x24233b69861c70c449ebd36e4420ddfc3c242b69ff6e3d4c6090c2bd08a764c2, + 0x2c55fe1a75147c9c826f762f836d5645ac4184ba1927dd56a76dc056a9895667, + 0x19779b1cb16a9c79654016674978b8b6ee1a78b64579de93ed2d67b9e49f098e, + 0x1807721ba60fbae476ff60120c1f47ec0bce692cfc00102ae50bd9376c5a22a1, + 0x1c0208f5aba12750802fbdc3bf12eac9e00ada708f167d4b167bd7d4b03d76f1, + 0x090b6e28ff541cc38869abe2f5dbfb9fbe888d21021f29d2bddb9127d3c273be, + 0x193d6c7e76ad94eb59a20010a799c7bf96a8dda8c90887d65214c8665ecda01b, + 0x09ddd5bc0b1f8d4c4f1a7a102c1ba12ec7e7540cda285a564ea7c4753af8a8d1, + 0x300a1dd5fda15d1a9cfe2a287801817168721da2f970139549e16811f555be1f, + 0x1520908df2eefba075bb41cfe0740e1e5a1ee181ce492016e152706e493cf470, + 0x0b3f215d52e85ec3c682698ebcb6228233ae9518f9450f480689e7cf30137846, + 0x050996a07af6765c56a8ee2f736650deb4972bfcddb194a0efeb1954daa8a4d7, + 0x23a59326daf5f94f3b5192c18ed06cc58cd9608e44138686399dc4f1ee807add, + 0x1d220b9add0592866898ce834b1bdc2003976e815c0cf7d3f6b8bf967ad56496, + 0x19b49c4da3d9e3a26d36566738658923477c504e76a38a82b1b1247104f681e1, + 0x139decc567b06b495bd6f3cf006c05b7e1f25d5b7ac554445c37dd285beaae7a, + 0x1a5a7d8bca8d4f07d4cd6e9bcd00c009e3099e99af3080debbb21f90f8e5b425, + 0x0621e3811d3dcb9584d0a8be41e431d588c93274c8549e625f98fd15983a809e, + 0x02a41c2d2bcf14664a0130a021daa6efd4a3b0c3aded38635bff97e3785ed6bd, + 0x21cfb54ba72fc06794947cc3bda33d815355416e2aae19084d84471eedca399d, + 0x05115093894089a202a4cf8d0aea329d83cbe0ece741160f9975cf01b7c85dc6, + 0x2e40541caca7653212827129559ab422a1c06a6f48c974291470c65fc070dfb6, + 0x07eeadd730284f5ab60778900b60300d27970001aa63e46ebb7f9cda1157600e, + 0x0cf33e4964d350adf2051f8e2e8448d3324d24d3f4858407f4fd60d3333bd98d, + 0x287c60483e2db313f1a2bda92c1e1c28b65ef0b99df4acfb75709edf6a3bfcb9, + 0x289440f4b7fdb8b2b22661d0742e9695139c1a1ecef53c3febde0b5f6d9bb4a5, + 0x291bda2c37fac962a24555a7abeb36d8e8b9eb25222f97f4817ef2e5b0bc7208, + 0x0e105449589412404cda7b82f14d527594ff99d04cea894d6ecc315119f42b73, + 0x0e6097f0ad418ac7123ae7eba6cd4522b7ffa8dc8cf60a1f836be23e41ec25e5, + 0x22fdb676724017afa8a8069c62d307aa4ff52c1445ad41b94c3e406e33e0def1, + 0x0204d594ad7855ad0f6950742b19e60c2c5338817aab7ee7bf631c3aa92160f1, + 0x0b6a643dad3f953877110517f7b336518c8fc11d868bc72e76cd76c3b2f7dc1b, + 0x04189ea6c2bd4b00fa6349adde17027eb7d76353a10bd07d0942639447cb43d3, + 0x23bc8449d898a7524b2dfde263036cac2e14935134f8c3baf7f1e13ea2deec3c, + 0x0017efa608d9941bc64d39e0b2593b742576dba257fab323d4c99c7a42107a16, + 0x02f061475e9d8888b3877f9308e7758a16f91e3a34a5856f15ad0b9f2f92e2b4, + 0x1f257d4d6f3277674a061330d73d6ba135da7cb0cba318686872fe1ef6d52e25, + 0x195340f6c1f7b5f6158884bd237715149cea488edbfd80fc9b9cc61c384853ab, + 0x273e200179c5c45d860b26a20b2c0853c1008f942459d5cdbed633ede031aa1d, + 0x24bd0ecea1e1df97af0f296c0e792d676e2c8e02e808a158bdbe01431c5e4a48, + 0x0c6e6f0f7c20811f404599d458af5c6cb41ab671599d6350df38e82104bc6835, + 0x1dee1352470235cd8e129b5611fa953706bc08d58f6a3ef3d80370d8d19683a2, + 0x1be0cc30343a168fda7c757ac0c7e5e16afddbfb7265878080725a12fa12ad4c, + 0x1a449abf644f68a64c217c6a042a231107ca8d9c619208580eb76bbd9215d984, + 0x080117dde58f228a459f59d90e64babe2daf476a9a2ca018faa3c5fecaac1789, + 0x24ab9a167b61855e0f2c60bff098d5eb7d15166fab51f2b62c809de318d6d176, + 0x2b56aca9d595460503363292bccdc80e823201f71b54bda684c93eb0893784f6, + 0x057361ec23c87b30080ff1cdf3467d57c95a12afbfc48ab5e1e4de0162a41b5a, + 0x1baed177177a25ecbbfaf4f204d9921eade3689ba1378cd9362cc14145089f95, + 0x00ccdb6d5f4913d7656889c312975fdbe0e0309a841849fd808d75f593a71481, + 0x2c52f5e1ef57de5dde528471cc1f0ee7839929df98ee743d9eff962515561910, + 0x0234a4a32f767f2e1ca48dad3a2fdd3ff54b2ca3d53ce13fc9052414ad7f7555, + 0x182b4c0c551ab0ce1990b472278f794ba9cc62abcc90a89efdd80776558e3433, + 0x001ab2bbdbd043d2d7d1a4eb76db4de71fddf19edf10d7cdb9550e1846e53fd5, + 0x206e6cd1e3154c113a762a628e24940907b41e90e7c2d43aa256ea5249978358, + 0x27816cab4bec18577bd335bdaf8298798a261bb175137177d46ba95dd03dc8bb, + 0x1680b632a04be3eb1ed64ef589440b3f9526b2ad82cf0b8839d3e7b0f585bc8c, + 0x196b2cc0e6e07628df8234f58c027c190c75b0342511efea4c3724c4fedd6e75, + 0x29ab0b6065ebbefc684608acc6bf3b5fc693770c38bf91b4be38fe6f72647486, + 0x224ce814d39c382da2d65eccd9deb48056ede18c5efcb8e25515b727e540a859, + 0x195e1cb28f38a9cb57b2c719b504f5fdd1d42559b6a368264fd0fbfefa66559f, + 0x0e9e5eb70f4490ba6dbd1c0ee1d6724ccdd58acdf138785ce98ee3848ffb7840, + 0x1995c9c8e520014e4412ec653839d781548cf71f46fbeb51919582226cbd5b21, + 0x0886095cc376c87fa653000283a6eae11008982f27104afee198fc377f26e324, + 0x13761e206b3e89b23de2342bfca860f9b0d9a36d486aa115565f9f52369c124d, + 0x22a8c6cfc0e38a500a47515c519ad6a72506ec0d508de25942c10f51f0dfab81, + 0x18985e9c7ea6f1a16962e4e27cf1aa4aa3086938b13f8ee9465a5ec7bebdee03, + 0x215b523ce3f055c92eb148c00027d1ad406a2abd64081043e0d15492845b31a4, + 0x0102f78c7513b093b885726b7df2e70298801b3e4019cdd42239d76448588c31, + 0x0bce88602fd3a0f0ab8885891ad44045058f9ace11fdabd24e8dfa1b0a4ae727, + 0x0745f760f8d466fc21043e2292e6cbb20b6227517f5200251129c5481f52fa4b, + 0x0406de3807445c6d3cbdf7b174c410a998a1530fcca991535a2a262de4e2ee56, + 0x26779e7346349068dbba66f784f87e243cc27cab59e887f7ed7a0117887d1acd, + 0x25150652a08af8ca574c7c5c77ffd98b17259a1d914a6ea41db75014267949d8, + 0x00bb8d13438040f674a79ed42202c5bf6e67de6fc3f6b65ca837ceab795fcc6f, + 0x0c1ebf40eeaac3d4a192dd50ee25c0067f66eff6229d045d5a801067639ccf2c, + 0x1a39731eb32fdb51dd793754f76103b5cab86947aad12d490d4951932ff20727, + 0x2baad3d41b18ae10c463af1662ecb28c6988524edded36943672a0e857b960f8, + 0x2e778da1518b6a4fad2e833e41466fb2fe82f4f8df1b5c218cdd3b7e49af67e1, + 0x156dc717930d6490167743911e9bf4d4634ae049b53adab281698645f8b16dc6, + 0x117f2ef1712692ab9dbdc51db4968b45f5e0104f9e5281329349d908b23e231c, + 0x0b281b5d9dd2ca1a92e2d83b5087b6a08d6ab08330f47512aa047b2f88ba68cc, + 0x1c2803766dd9096567a3366061764f8c916f2a2dd640b6eec0942ccb75d40767, + 0x120174d53ba57d1a141bf40e4c705683668bd55800000aab6f34766b7b6575a2, + 0x0c37b25020f8c76ea5536de54c722e47d01795d31b5ed73466e7d8b8ad376d46, + 0x0a508f345cc9a8b0c30ba27651ba1c3ad8398025a4000a5c2500228c44fa91b8, + 0x12afa49ff4d8b4c6c372f7e065840783cb9497eeacc847a340f61f1823cb2a8d, + 0x29fc37eb5ec7cd004809516b7aa3c716f4f7f6e7772f443e0730b01dd5071a55, + 0x2048fb9c1fdaced0fdc5159490db2977e57dbcbff7514ad1e52a271bf84dd1a8, + 0x00a6c4223aabe583e899bbcd0314a4743181f1d5e03dbc11c8a4d02550fab64f, + 0x15f462ab5b21c31557e25d9c22d8dc6a0cca93c8ed68a35655cff745686764d0, + 0x27bc1c9af68edf8e3730197124be559f1472e7e3bba0d35e079b2d1b9e4271ef, + 0x1a2ec148f900eeae38c0d3d6efda64e146929c71eb82da3139a3a85968ec6ebc, + 0x04ff41cb553ca616d0616545922f2030b71b2354bcd1c55d7eabcaea8904c22e, + 0x2f2c4e7b18a845fcd6add67009fc237b14a984619260a7b3d38712e03a0849b7, + 0x22925c606a1f091c1d5c7122f8e1a8ffea6a140031106826ac53a9c69d84c0ab, + 0x10e2a8c7b12bf70266c257573ca2594d8811633f77822d7c232b329c5b4e7279, + 0x1712319595ae464992524bf8e488b783fa45b3548cd3f162d586bce31ec7184c, + 0x2e9616987d3333388ea5a1cb56b4c161f279ff19454a64ade43daed4dcda5c0b, + 0x2c68210d75660df5d9a8392a2805ea1612fc6137cf5b35a68fc1f03acfbfe4ca, + 0x053cf3707283df8730b6e1f637d23c67b0b3533061a35bcb0cb0f9bbe4e8adc2, + 0x07577491483d03d7769dacc79607b9897081c0095decdce3d227c059ddeddb66, + 0x05639b2324c0b0af81c5b256ca6b2d46b95eaf855fc26cedbf90411312de4a12, + 0x0ec90944eb8fc36c52f3fd13763714f41cea1ff487ea39d70bd94e9b7f8f16d5, + 0x1e96cd3ac345bb2e5bd3e755922f84afaf303d6fb227fc68f703b93665f5ea96, + 0x0408425405c66baa7d49858e6d5871e5b42ffebb0df885a824942da1e2e36d58, + 0x284d77566b42f3913d41ebb0528b899426e0805aadb9957a534b022b081aa977, + 0x0b044e5984887cda337f58c7ca50a78126deb5624f644516239427948d7d06bc, + 0x0486972179ee3496795bded1c2fc9674c0c3f71b58150c9c525063a6f2b340d8, + 0x25b7568316c4b2fef9b72543b6033b317a7bfe406623e47cb68e5c79296e6bee, + 0x0cec9e74c344198703ceff28a4d11275f6c5c15738aa5a54a19269261ec6a8a8, + 0x2bcc34a99345174c97a65e8978194486a9957c9d736f0ca39b98130801d1a114, + 0x2ddb2ebc0ac98f6498c0f2be2d73e86a786940a1e8c558d8dbed8d6f44b02551, + 0x2642b4a208e503e3480718d4d205351f43da183ed284ed7a385ef7cdca80bea8, + 0x23fabdb09b481bc764102ae85ccf1e6ff71c7762f8bad04a2de3f7a025cb5087, + 0x0ae4ed0ea6adb74b9d327fbcd01dbf37f5f6c467480c8aa5f495124cf70b823e, + 0x09034e1a646d6674bef041afa774e3634faf8adcc7c71bc2ed6e03b0b4492016, + 0x2817ea20b471a4bf138dec79d84f9f6c0015e0ca147b650683df4b3372b55ef2, + 0x2dfb7f81425c2def6bfa4e833e51e912298397de78fd2aa17f6d1dd2f1379ca9, + 0x137b5bdb746523c051d680be08daa6b0d54c9ff7099f2bf5ce894c24a8ef1f37, + 0x03900ec7adc8e28af7046833dbad3fa1024e382aebe02bcb535243ddca21aa85, + 0x2b285b6c23b25c52f2079863c759e6a10c33df8f191551ead53ea508511cb555, + 0x1242067be2202d1b2c32b79c464e2d6c977e6fd12d8b35281e84c375864613d8, + 0x1e8690f5b0a8729b9536ef2920abe7e6f3eee805237b158d997db63b17525eef, + 0x047f5113e1287b5572c82edb369fb0f717a91f261ef9d81764a5b279ad9c13ba, + 0x2d8800f21cd6774d5a6aa58ae2cd32593593d173b687122a4d61c44743902105, + 0x274ba1521d5bc5c580647f10d1a4c4cadeef088685d1976979bad813756f84b0, + 0x17895b7c10d6a475310d34a0737efaedddca8f1eee9d8d56e7fe4934c8b56441, + 0x06eed11ae9f70df5ced09b1a6db258978cf5becad2f66d15761bf61e7dc13440, + 0x3036b521c631ce5d3599e37f6a5daf928842cefcbcd2c6bf84e2db5ded748f09, + 0x1f52d6e9ac28976c5a6fbf168c818478645c90d72e367609d7d7805a6367482d, + 0x2a0e60356875d6ace1055932b3dd9ef39c3dd871091e96a323c1596cedb35e6b, + 0x02089633a6194f3ed38eeec2c8f54d0c7f434938fdebb9c0e1830dbe5311c38f, + 0x178c73d2769765d85383283fdb0d769457cfef0612baa963336bac1240b604c2, + 0x2fc20bcaba9e3d96ebcdd710e3b341837d5d0db849e789f28c4be5004afa19a0, + 0x151a423bee67fb14d5ad279f425213db7e0f21494982df872354c01f0f4a722c, + 0x25d61619e135690c4e10e4afeb4f5578ad0f8e25c20735366895b31eebcdf47e, + 0x15dd579bbd075429301d7295d3e685d832bf9f36c51277d09f2c3a664b045cd7, + 0x236fa29b81678c8a109fd361c1ca90adf4423c13cf5b8cc1032b7283bcc959b1, + 0x2a80cbac9b884e20368691bf1567cb7320537a977da10e53c5baea3446c01d1d, + 0x11d4cb8957937b3628a3b3f4d27f276cc0c179b0c22b2c13fffbde85fd912378, + 0x1289bf8ec507bf752a07c9b71efc0f800a52fbeb1637c5010fa54eadab402946, + 0x26f842b1a99394297d25799f2f03dc9e4903e77d2ddc03ec2fb155466da6f303, + 0x15944b9954b6182314e878fa2f9e091dcc40eadc48d37d39bdd5f09905c3a369, + 0x0742166dcd8ebd8576a6bfe0f1fed13793928f84442c7465a0012f584426fadf, + 0x08603d5a0e937b5353b56b05768fd50bde792e72fd61c06344cbd735707b68ff, + 0x0caa1711c66e9301b6f25e21a31683d80bf58d86032d03bfd25b9777edb74a75, + 0x2d6506da695d2087dff87b5f636ee676fab00c32ae45c75b3db345f3fe74a311, + 0x0d9244b07af9b6eaeff6f84049cb2e01d75dc4cb68533606e976b8b300758c84, + 0x243abc3c3382faa5dde3f1c3b432042d3f030ef6a1f5401aa37acd15cb1c8c46, + 0x168416e0a6d275d30eda3989242e0723024727d3b0791b06f8e1bfe8efe40198, + 0x1bcdeef03693d1ad0ea80c65688654affe634aa14cb11ae3a491681d9c5f8eeb, + 0x02f66bfda3d2a1bdedb0ab8bf7eb1c4e551bef58d94fad7f7c231107e5653909, + 0x019f6802171ab82a5922f023fdecc097eb8ac1fd0a1ed349afe9a7b94298975a, + 0x195a1c738398feed8c760468a0556c232645a1dd862d87c1f508c949ad52c3ae, + 0x0a36a3a46e6ec16567dfae1f853f360e6f24924810e838cb24ed1b0fce37f1e3, + 0x002123c29ea87f7ea7b35c25f9e8dd3e81bbc3974c3c17c607cd840c09f374ae, + 0x02a717499cb6c31f71f0f0352b0f5bfef3005b80e93a520b6e42b3985789e2d3, + 0x0fc053584b0a4607a2293e18baa309c52fdc933e9ba90fd327aaa8c8cfc4daa1, + 0x1310d1942129737b32e87a86f4573032b1b99ae3c6d71bafef7b494794855541, + 0x1bfadae53fc82900f5761c558fee5e1218e6b2a6657e74b540969eeb49e0b8de, + 0x28c08a69e5f3641460ff2c60b7579395650c5b6afb392da142d32de8677556ea, + 0x223222ee42b6ca997f44d643ed6a3f2b040f47fe8cd922163d9d9d8b2622d909, + 0x064dad4752e708ff29bb0842d2c452a71448b43949345690031cb125588876a0, + 0x2d5ddc21797043996b22dcabb9a1ba6c82b71e9a1bc5919db8befd35411056a5, + 0x26315fcd9b5e1a266ec8e9f6600f5a6e0bcdb22f926d61591e83fa21069c0e0b, + 0x0759273a4177fcdeab23da38b478faf2d4f22e82f346aa754b0a1331bc8371ee, + 0x09e13300eade70568fa0a840ea9729896ddd84c364d6279d34a0b9d1478fcf2a, + 0x13e97ed3c16fad6cb5b7bb954f278f2434b22f8cc054463a145cbe0240d4f8bc, + 0x05cd3486dca58f4eb221bc2cbedb8aa3027cde5765971bb1f61c272c5aa51ad0, + 0x005ce523f6bc21daf1df468b12fd3e8665e1c1697816a9a671a3b2b6149c7de4, + 0x2103066cc5df55e67cd7914028145fb71f089d671c83c5b537abea482b2d8cbb, + 0x039f8077bd9b71f91ca0502eaccc1672c539f72329317aaf8173d2edd7636928, + 0x2247bc0cc4373705b89672a2205346e6af3a6422e81b4f4885dc3af7cadcc5c5, + 0x27bcc768bd31b9d00687a7e53c3ce53c426762706188790ea20b2e819638df80, + 0x0d91cef51a76f7a62c51c73a2809732d79ac350159814ea536487368cfdfd708, + 0x20a9ecdc649a26388dc68dc02343a0f167bad46d6aa1cd008537f627ba140730, + 0x23134149a0d4567c6dfc911d5cb80c1a1016220d39e0c230325dae2941f528bb, + 0x2a07507e9f030a42c6f29ccf1c9cc4f3e5a5b0dbf05874d5edadc03fe74b9474, + 0x1bdf66bb1d57fd788e54ef29f06f35fdb2729b718ce81152cf3aafc64966110b, + 0x275c33d07f9e7338ddf50783bf158d51be619bf77a12020cf5630b78e7e0d0b9, + 0x16411554e55fe604a1ff1b3b5b7afb6a2bfd0f32c4070b55bf1ad234e8b28116, + 0x073e6ac7e6af227557249ca1a5c55222a36c641bc2851a0dfcfb60831f6759a8, + 0x10a6fde88c5f621d748543c76a218f95c202bbc3baca06838f31331b0556e12f, + 0x29c5865a26588ca8a88128a072c8434cc97a1bcec23e136f038d29dcf96b0eb6, + 0x233e0ef6ad132ed211b1911cdd569576fea8c17ca64e4d5dd516fcca07212c1a, + 0x096f9b92b9cf2c7d664408a29860365f5b6adc238d878a476bded3e4d2e0b840, + 0x2fc788fe8aad4c28b943bb57cb90edf6d7b1f1e835de1fbf3192e395db785554, + 0x1bac0ed609233148503795fc5e114076ef7c9d722bc648dd0338d9689f6e023a, + 0x001c35268aa030d6cd148e106e3fc23094e561573d8c72a69fc383643e2adc82, + 0x2bb1f8fe5d998d0b8b92837ffb27bfe7a39ce39ff94fc167ddcc95a7202e34b2, + 0x1a98576450a43e5e705b9af68cd0c145422da23945630b10b8e821dd61f9a2b2, + 0x2714d37ee506efbc2ba9941043fb23f16af966f123d653f38388bcbdd50e6037, + 0x175d0480ba14abf0bcb8075a03f4a2a01ff7ed75413917b53e50ea00cc2a4ad0, + 0x203de45a037b75ef63761750dce08da2be7709701ec8158c17fc026fd084d541, + 0x265aabfc78b70ca985c329080d6329a12560f76b01cc3d431a7283022193abf8, + 0x135468dfbeb70e8c2edaffac8658a6c22b2ad1520ac0819c127af2ea5f3a87a8, + 0x216a41e24329deda65a8a82001c84ce8286c61758447ff1bfa9d9293b6711fdd, + 0x2887ed49797bd6652bed8bb99ae345ad70d1a27cdb21b9460bb6fd0d4fe482e6, + 0x03e2bf82690c804bb6ee3c79dabd1892ea53a9811e2424a19fae446b8ae49cad, + 0x0e6dce1bbe6e9e465cbe14dcc615611867414676dd8a8ce9946649b1c4e81116 + ], + [ + 0x123992df3b9daa65139ec13fbb52f7d348e134333684c1596feb0e8d8c3ad596, + 0x2fa46f5dba9909ce9984a01e2af30b550dfec978be92b49119a3959c7f623703, + 0x21d8f94d3bd98f0b63a7aacb175b2cca13b2dd8a8cf68fc36d94ae29401b2d2c, + 0x1a8c06c61046e0f8dc6a39bc57aea0d07fd7db34e68f73579da89e116af87eb8, + 0x298cd7046f58c0cab77523a58a6fdfd1401b89e7ae5eef4994442d167f7ad1d3, + 0x0eac737966715df4a20b31ab693eda86a07f3e830fca475a6574d67fc5f19f63, + 0x06b9b718bb3b6d45e0cbe6d5d9a2f096a77beb056821750d072262af2a70a33e, + 0x0bccdad6e8b1fdfba846a9553fc7905b3f96e435d653eec3972565e1fbbc302a, + 0x1b3ff4a6bc8490993abb7a002393cd1c1c007f49240ffc2ae1f1057cfcd8c7ad, + 0x017f0c9452d70eecdf5cc8b6b0b205ec2da1de59750d6d1709751831b7e4ce26, + 0x0cf1ab805bc47a10349ae77135ea95a4144a6ed0718fdeed42971c160791b269, + 0x18dcacac61318af644ab0f2e61ef48c29a8aecfa0282e9fc325b5c0287103ce0, + 0x16fbb3bdf4066e2b2f050b89b685d408711685db7e4638dec90ab1cc794350fe, + 0x0eefd0b8617a1ecd7711ffd5f6c4cd0496487a1b1146e9f3d53275af18fc6c6f, + 0x03c707d1835066fa30e7295a097a6ff463b85b778ca11d9bd2988d41b600aae2, + 0x063ad3f6e3f8443e0908af99ce32d2c09606e84aae5e3ad30ed60d7a660738cb, + 0x2cf67cc9cd3a5313d992e315010d90cb501f790bbe35a166392a51d90d117353, + 0x2a6e7a7bf7c190d4e4f7f258d890dd41780e28f6b71e893716f70140f4406b34, + 0x26140420009b6d8c7314723e66925badcf98440da6c2b97b66a52b98cbdf1d41, + 0x212c611149d057b2ffefc9938ab1498d3b265392c73480b9cb02276906e445ba, + 0x08918ab686c1a160a55db12010b20150f82632dd5933e27cd01129518cd9e952, + 0x173ef7767749a3249b004eac7aa7e94dab20d465c65ebf4bab422f743f17d8b0, + 0x049d90fb549e0e25790f5a6570755c68c13c97b18d67bb9199dc765355fcb1fe, + 0x0d1aa7cfe6ca9e048ac6ce2cda40c6d64afbb8c15a7cd9e0222566f9922a1547, + 0x2d82e2ccd8bd63b2ba44bc0f4cb5ec88142a4408acf1dad452a66e8219f667c9, + 0x2ab73a842e0bbfe229ea1154bf8aeb48cf2fc289b939471d6b465b7202eb2354, + 0x233f36bb205dd59d045310064408c6eaf710173a118f9ed21153c99a6b0783fc, + 0x18c14a50595b8df32124bf57f8b8df430449f35986242a2ff79a644f510cef27, + 0x186508d6b75c7902ed6a1948f91088c7cddf973d8cfcdb4e5a5b0cac6b5b22d0, + 0x10bf42990104c39b27ef0ba451b510cbb001f8ec39a313d259be4309d6429bd2, + 0x163e875fd9e04b255971072c0d2e7614ee1f3c7d2b93799aa1570bf73153f3ac, + 0x2925a59f82c1472b8120988e3af6cf24c2ebec9a9f0f830bb5c826061c65eb8c, + 0x25caf9ff6543dcc34e2d0b8c2af3b36ebef3d4c3fe62e2937ce590a38df2da1b, + 0x14cc417fd674083090f4463f66180e4a3f38ca5ba87f4889e510ada924f6b799, + 0x182550aed7fb3b7d92ef0b91f4916ac7f7db3b943103ae7ba2e09ec0f4a08517, + 0x216305852467475a9f934d3b1132a99642fb79fb6bb91d948f391ac9e1c3f1c8, + 0x0423b771f7215716cf97b3a72ccffe156bb9f8097c77a2b6dc67bb5848689b8d, + 0x2247cd5af8b5ce0a983aede949f81dc7d3fc5a2cbbeb8d16ad43fa2c3a882537, + 0x04990ce49123ed1eca92df7bca2b271d07ba4ae5a30c6a0119f77b51c3643d2f, + 0x064e8bb29cc072af727af1b79af50896a6548dec41bac10f0319fbefc1bfef9d, + 0x05f9be83351a037f574fd0f54d4e9ae5cadb930ceb51c91b07894f0160f8fa42, + 0x202ce17e96cb24e8986cd09351ab9576d5a5167168f9d5f3877c4c5ce03629b6, + 0x098a2fb5cb01868cde6424c4211b9549b8f550a7f03e7fcd8b5121516b3f452d, + 0x2cbd947e532cda0f8f1b899ffbcdd5e0b6b08451e637fe53f3b4a8ea7832aa27, + 0x0e0fa4620cfc943da81b40b6b42f86fe74e55900f800645ba66137b6b7c728a0, + 0x2e1ca081c96d5abf2cc40b3797c38b0ae8a8ef5d76e6d03e9bb06741c2184123, + 0x271cf3ea7b06b4e743585ae68997c0143542e405c70855787181163e4ac20b45, + 0x09dea127972d2109cadb7e96abba7577c0ac0077312b9550f81b7716a92f5eab, + 0x1982cc716da20b119525c64a3fe85f5e31baa97c76c82376999637d8ef1c8a07, + 0x226600de8bb65b38ecf996e5bb26fd6288c690f16a5eedb730d939311d0c3ff1, + 0x020f7b77fbbcad998e7744ca27c0f7c0c2550a3db90fe28944e73d01d24ae6cb, + 0x1c2e445cfc98637aaebc2c1ab7b6d790ebac5027071d1057a945bc90437c49c2, + 0x244b349502df4a33563b30237ee750e79bde135f0b0896f0d9cde04f1004171e, + 0x10860a875d80bd71c6267c1d54b02fb58c890b1cffc35fa707fe6a94941281cd, + 0x2eec5addecc4e24650dbbea531a0fef0dc327dc694f229b2526d2f30b2c499c1, + 0x188bb7150b6e40624b02ea2821aeb6b52b1e85b5b724bc0ec512f8fa641182ca, + 0x05e56007dabde2cc83d498371e99ada953ecd69e135ef0204d2d3b6cc1f49aa1, + 0x2553755b36de611ed557768bb5513731474a0a8cdc6dba8f04f3031b07687b16, + 0x1cf267dd9bfb6e678a82c7745857a63e2b57066a8626b52c0fd5ff42418aa65d, + 0x106b2a40087375ea2988b8e0700fdd71d3716af2bfd0b6b0ca6e24ab4b4c25e1, + 0x0b978e4a10dbcdcbc7e90aae2ca19615df674819cb611d93b4cbf5f2ff9a0a16, + 0x2ed68ffba6a646e5047666b8ad69f6cb35ad096d6d34fe1ca67e532b5186bbf4, + 0x23c632c2fe68d4f0a71b1ee63951c72b7d349797f07053df2ed33520ea3e94cd, + 0x27fda5f826ce6a8340d12a584d4b9c84f0a4ea3c9d33eae8d6c0e23a5a9897e3, + 0x2d24aa4c0772256e90344d20d46dfbdbb5e9dc132a4fb07faf8eddaa30da7674, + 0x048d52c4e3d71485ce6af122ea136e60053e387d77369eedf8d9bbc663fb98f7, + 0x0e0c1f005a1759dd161302fdb233cbac5fe151b5c2192255bd757b3ced899f92, + 0x230d641c4552e5e55416e360eaa32900751de5ca53e8654af8d422eec627efb2, + 0x02ff6fa8364a8cfb19e30be87d4cdeed9f957dd024f8138d535c6380a8b5d38a, + 0x1689a04762a5ab1388f6a7257e7c72838513c57da7f546a2017ff128afe16171, + 0x288d8c7325204250e8632f42debee8a31a470312ab2fd00afbc7694f95b827cd, + 0x23996135af9f3a42a6db33fd55319a7caed8da2e6e338068d78f5408552c83c1, + 0x15d052dadce14506fccd2690c333f8ecac382d2b6734726236cf9c7be278bbe4, + 0x1494fb65e5993d96c30bf0bce3f56dce68a2de52299b4809cc119e37d8e042e6, + 0x0b800ef8749f91b307947c581095ec9283c3b131be5ad5bda4200992fbff053c, + 0x0bac1f53d5a7d39811bae7c1a79dc997fdd5f1270f72805fb05f5c52d77c1cb0, + 0x179249893fa86ee067b47bbe8335b8942bc921ae0e082c303e32b809d939786e, + 0x0985a7c9b42805d910a89e2dc9563e7e3449fd5b401ff4d5eac75dce7fcb420d, + 0x2c1905b5f00c927a57a154c474427e31f3caab81981d621fb7fea525ccda9bfe, + 0x0b23502ce04c0f4cb30c0bdb6c4f2a4f81c2ef223936f07ef57856f0a9bb4f70, + 0x2dc051c1bcf637233ea7c5e086aed7dcdeb51b7a3525820bdd6eb65e578519ba, + 0x273d8a4166dc3f53b1ff24c61f1a3b3007a282b526c7239eec81e92f51c741ae, + 0x257988be7dc257a0c5dd7078b72f692c755f01ba3c8e57d82d9b969565dbf0fa, + 0x213d0fe5a3e7608fa602f5b5ad5b8260654445ebd72492a32ad3991f3a5a6218, + 0x07a383e7a221bc76fb14370d4b3eee8de502601a5e4d54b3370c4c502b097a8a, + 0x18ce7b3e647ce9a3a90d0ed9aa57eb9a895d596a54958cc9702d8da219623e81, + 0x12320ee10efc1f8118d3ea697574eae2dfaf8f29c183abd123392e3c2829900a, + 0x093d0e1304c660fddafdb48295928fb6a83114827566cbcde26ef4c87c9fa89e, + 0x2931b9295d96e5b97364b37daefda7dcbf3dc9f48ab3364da9dc6a7234d714c6, + 0x1f533a1e4b4878c2fc2e9706e541d28481ce43b1627d0ba46596906cf3281624, + 0x2517cb724d12ee6ebfa7b4b0d25cf0315466e98d8cac3ffbfb1a1bcdee0cf064, + 0x00e43dc983bc8febeaad40130444ab7f9187185624149a7f274492d9bd8389ea, + 0x186bc09a7ffc4edd291579876b77c2fd3eed0b1b83f21ddfb899039ceb77f379, + 0x05d22a2f48f64658e181b8ae5e72e1a942796af2bfe6ef74ac9abf53ac65eeb4, + 0x1f006e8d2463636bca787f765fd6ac723ad2c2e466ae6324f5d39f3eee58f0cd, + 0x28913d42bdf680478ffd17374e895fe7799d9d100196f6ccc30dc08f39a479f7, + 0x11b557c8d7e97bd99ae5f49e823308bd6e22694225d4029dfdcd836cb7c0ad7b, + 0x0744b53926e1a0ef395bb04908b13326ae1866a68983c41de56fb7cc7dcce297, + 0x2bfb2f2456a70989b165fb6a3ee6f944d28362935cabe516114980f141422a03, + 0x3027047944ec82cef6240d1637070c622c5d28a74302de0efd6d4addd4dc2db2, + 0x1ed0b5e4b29aeb0b5b3eb128cf031759cb3bc47cc1286657cdfe88c5c411d4a2, + 0x263479ee77e44e8b2ab953e82ef63a7e4aff48f0e730f4782b225cb22777104f, + 0x19904c84e55e1af3147cdb7f3a428265e20c1bbccbec2a5c8b950417ca2ee471, + 0x2fa8468fea3204ed2a934a1eef7c78580a8da30c5ec5922fac89ab92ad81a3a4, + 0x267c0b4b19662cf09b870e05f7441e042e5b962f73dfd78d23384dc7ea71afa5, + 0x2f1504675041755409946e8c5f5432d35849ba7bea0d12512547ae684b83ac2d, + 0x204199d64982f574327ff3f400705e0a53b25d59ae91ce0b9d31fdbba1ee2b0c, + 0x0a087554e5511426780e457757c175cf6187a2efb9568a3d390d3a51c2297ccf, + 0x2ef9b88428465f535cb04119f518d1c2052268455f1ab145ccf1693be92416ab, + 0x2a96c9f200b477eba78316fc4497e08b2a4384b26c97c7b4ce877cb65ff5634f, + 0x043293e61ef1b614850bc015dd316e2c7c54f12d2db746f7c0cdcb0ec551cfc2, + 0x1d81e0e280611bf30989c1a74088493504b818b385d04d96ad298dbed9a7bdfb, + 0x1ad9cf17b8368d98002ced2cf6ef9385a074c5e3aa0b2e12f4b768cc4804bde3, + 0x19b30a27119ff50da2734b127ab83299a4b099694c31acc182ab453fc000ef95, + 0x132d81f00bbef2804901c4073fcd9c817a63832c30d653063f67fd86482e1998, + 0x292ea3ef2313863a1276b1f0e4973fa784dea78a1ec98f4d593947f6a4e73924, + 0x028cfb5e0c41b0c77d987e737a5018787079f2ffa650102f2feb735c7d9bce84, + 0x11afd75dc84353e2f9c2f05d1f3ca734eb45546b92396233a3f29f4e8f6791b3, + 0x1aaf43ed6da39b453120bd0312f259294ea101b678dff427843c0fc816409ed6, + 0x19db09df83387b1e4185cd79400609e79f37e5a4658dbee0785dab5dcce32868, + 0x029cb3dcaf2ebb0f5b0b949e84278fed2d11db8c1fcf35e38189afca16c0cbfd, + 0x2881df9352d274f0cfeb55df8ffeb1d0d81fcdab794082e2107e1b0426a730a2, + 0x0628a0f9594c159206c7627a8f10748a1df2ce582b7604a8e64a7015ebddb65b, + 0x22657393eb7ed9f4572c22cd7b9d5134d1fbce295c2a95f1afc6441de60d7fb8, + 0x006325f509f0362714c4850daed8744062fcf8098608005e7d08b509bba33624, + 0x171d6498b42b39345d56e8661ccc2b576ef449b1f8e5bdc5ac72d9f93dc3dd9a, + 0x1be82f3b1cc9d849595d85e3398331186b6e4b4cbdf43ceeedbf04735315a8d2, + 0x154711be62f23cd46086b9311b28eeada8d26323f8864de7e36e5543bcd7a38f, + 0x19ece5d8c0b6cc07fa0119746e7f36c9c8d496ac1e1d95cd5bb8d769a6745cd8, + 0x26d6162d8d9c9c60244cbcc1bb78814265fef97a53a168c62a43b9e6f4cb2d16, + 0x28bb85fef9f65884e4a99a63a59a906d586cdd88bba7c51259b1fe6a375fe4af, + 0x267ccac1e34271971e474179c5800526ceef2f1a6fddaac1de2299e92d9d8ce0, + 0x2e6b4868d15390d8014248eec0c7f10d8ee9eebfa64025f961ece49a9ffad985, + 0x17039023ba24e37bc4cde497e95d134ff35dde6fe093ed788e4839d2bcecf840, + 0x214455d91fc747c6aa9908ad92d19b2dc75a84651183dcf43b9a256320c33e57, + 0x0a07405f036d30ec77ec64b034b9fc5df2cff5877c3c67b7ab23b9f2d8dad2a4, + 0x29f6807284b6e435ccc2fc14579baed0a60617e0ee33a358cb316811b3d8864a, + 0x246894f6071fc9630f69187cb5ab506c05084114d2efcf231780b5d4b5c4a0c6, + 0x04224081b90a67774d15ff98e6134493c01926f7ec25053de56215c145e5da67, + 0x0d99cfe7649d1dfd292f11773bfff1ce3645ce4212787ed369c0a06b602bab21, + 0x1fc76023333ba4dc0f2a8dbafbba1bff33b753fd77e6b1bdc4c796a031b7815a, + 0x2f60e05fa1f7446735a3717a9d73728a5b20166537ffeb65707e5f7503e8acf3, + 0x1a2b7508921fa054f58ca4d6eeb133453663c8979d6216ec9ee1240b8c894e80, + 0x0a0aca4924bea6979a56e47af0bfa19c1db7d756bb4aade0a58e5bddd7ddcb4d, + 0x262a2365cc780f62557c854566fa2c8822e6fdff8eadb90949faa5abd63a7f82, + 0x19ad5a882f1dc4971429545dda3db1857b1ca0a246768b3a2b0014ba5a302439, + 0x261e3360fb23c08e87b8f588bd59f08cef07bb48a6f1226a64cdc7d4de7e95ca, + 0x069cc67cae46ded18fdc725c9cad9dd64e445c990271b0e2d2ccc42fdce0bf59, + 0x162e21896c8d1f6c2b7ec16fb7ae7ef8c8ee19216ae189a6ef2d7ebdb1ce62c8, + 0x128d42c08444d8956879995a105a336c4248ff9581139122ed9c9d55464ee9b3, + 0x12e9391f7f131f13c39725c4414669bcc64c7a41b6764e687cee8e507433e3e9, + 0x1de988e46c2c9a1c00d85dfafb1da7509bcb36422aab6052fd1f927df741c170, + 0x2002cb8a779f93de8b44d7fb08cff50828e0771d65011f9954b424e67802cf0d, + 0x28f6e5af2752c79d01a3c6c7d2930fdfb164989c20f905ccfc0982c29365d631, + 0x19ebacb5354f7f272f5c12d6c71b39d89e14aaa4efbf987377337ffa3c026b2b, + 0x05dd47c695cc6c95e2acd1bfc0ce335cb304a3c3380a94e8b7c070682ca869a1, + 0x246bc3c037a3c9ae2bba7e73578b1a825e1672a7418801cc0743954534d9c0c7, + 0x1b7ee255815ba7020f0cf78ceb9860815c0eeba268a72cecf9e3fd1a6870b3ae, + 0x1ce04f643bc9513316211fdc0bc23c9a52bdaf4bccd9ca18590c1703a2d120e1, + 0x2e3a6532afa95388b41ad59d7c2705445d7ce10c88d73411b7271f52ed4c44cb, + 0x1f91121f2cbd1ead2f70f4f74729a25723721a895a87d73394cc9c1809fccfbb, + 0x11082403388a99da0de3ed7d3b873f5abcf71f8bea6e358f5b0f17ca5276d926, + 0x03962a691eb42cf5ef779bee82508641329ed9eeb7857f1cecc46dc93046e1f6, + 0x0a67910e294583739c2b6d18ea5ad74e141bb2a353fcdd93fc3ef83f4fd7863a, + 0x1c20f9bd1323709fda124f71e88901235f44c5e48287bf0f43b45443ddcbae5c, + 0x111ab56e19274efd47392b70171dfdab0c8cef5b6de579de67f579e86b506fbd, + 0x006e6b88e6f0cdf982de483aa04bb9d0fe288ee5863a6892915d125eaed786b4, + 0x29bc59d6fba6d692e2a5e85ba50d6fd9bcfccc57e2bcbdddd65881af445fff84, + 0x261d13ac441b2f30096c1f7f66a6d973244c2c070211275a37d49b1d70340edd, + 0x077f8d9273ffda37ed1ea683f69349715f95986d26163f00d41c9e3c366ccbfc, + 0x1678f9fc6c4502c235267f4b841d9543208542355ed7db420a609acb8e8ebdce, + 0x1a65b41dc302b906fd144a594bea6d909f72fb707500b270837c9a249590075b, + 0x265359bf0ead777264d18dbb4c4664301a23b10579368f40b433710b97f807a9, + 0x2e944ce0eb653745a45632c070b931d08ecc4973ea091e5dc67125cc9045e41e, + 0x27e3025a2d3e82614a4dd0550f59359f5643b86835926aed2eb0a7aa4f06219a, + 0x0d9848e0d3b8bc8d43e5e6954e6f0181986e575054840f238cab4cb5b03fffc2, + 0x1ac3aad815d8ec13b035decf67a685496a87b104bf57ef38cda855877fca7c75, + 0x0c910186f912eef95fd673ead2281ffd0d5ce9c80cc51f6f931d0c75b9c0a3af, + 0x248b63a76a024d5cf2e42a1bf70a954f01b1849dac31fd545a7cd74c5c3a1e54, + 0x1a71fba60cd363b0be3ea3604a386cd1df466b5e69f93503858c69f5a868695e, + 0x15a2869b6363cd02a472cbcec5c91bfa17242cedeab83084f0eedf28343178b1, + 0x2813c10731f7694540eacde857786ab2443fb1891619243b8d4d9a529a733548, + 0x2aa96905ef42bc1e8452087fe13dc3d55ce94062936fde48fc29f8698ed5ec50, + 0x0f093d369fad0a0d255bfc311c4a58dc98a1900cf359b3e7d9688f6591b8d384, + 0x068dbbc530967765cf7c7e69b8bee4ee08d486b420d5339626c8411ca984027d, + 0x1dd0cab71570941ee962bd61dad1cb68a8ed8022adff356a67fcab3a6eaf5aee, + 0x29a857f084ae7f2b506efd6cfb0672d63ae960cd1979f78d7f55d78259553777, + 0x2081f7713f51b3930dfa0a6df8e83611bc8829cd1f8471b7e2e17f480d853c33, + 0x2eea374a60ab1a20648cb908e605c6d8599ba601538635c8ccee00cabc85727b, + 0x1a1b68bd2951131e6d71952233647e4165bc412da6d99c2197aa397d8d3ee5ba, + 0x1defdf14415a78d5e6f287ae6e49ebb11822b8734c9df91c80e08de57b2d4f2b, + 0x10040cc4fd20bacca69e26287138be4dac94040cc6224e2bfdc76661106a7249, + 0x20ce67f32e823b988011d0c33abb0f725be96fc9ab5b2eb71012f5f80a55ff40, + 0x202ecd50c82c9e1c79f0fe136518b22551c058c21b6eece43585bcd28cc4ea87, + 0x10fba50c060fceb989d7536c3692f0c3243338210d145d6187926798b747087d, + 0x02680936e402765dd6ccfdfe2dea719d3c507a7c551123c0f9dd59a58bf8dcb5, + 0x102beb4a5c4c903eaef9ecb0d5794154620d7e9de84364fe0583be79b4de7cfb, + 0x08d01db18faecd1a26c285be65414bf18ab012d7efb2675f4ae1d6f5e1370622, + 0x112fe5d217f33c2d2d19762d286841366ba782b4bddfa33bda836fa2de419010, + 0x064885f457cfafe6ece2944a9a935efdc717affcb4449ceb31a2792d5eea6765, + 0x0bbdc371ab6d4296e73ed2078b99fa47d00c44cf51eec0ad4ad0aab9c09cd886, + 0x0b9e59b699aa688dd12143e890b6fd0e34800d6b440f5f6b6c426b30ad078887, + 0x0a5aa31d4fab8e109b0fdfc55eb14a5c2d9267d7f986b610170ce5543bfb30b7, + 0x03239d50b4a0128e39c7673f2f99d88b5903eb1bb7704c6c0cdd4c31408a7a6b, + 0x11a6945949a182759b6f1da60eadaf2c730cce66ea046f8f5eb781e7c45f8c9d, + 0x0c502ff1bed8a68726803e222b87d59074956d834f2d63817f2a9efed3dc931e, + 0x222d9daa384ae2b40e43e274cc07d2dbb9eb6988d03894b6fbf51336634c917e, + 0x1df8fe0dda8e51971b917b0ff0f3e05ed4b00c09545351a1177805c50f6bc009, + 0x222bb8290405c5b3373f1b199969c6d0f9ba8eb772f2497c55c0f551775b2635, + 0x07902bec23d9f91a003a928eaaff9647ac030289dd5eacd8cafdd31b93264d10, + 0x2c706f059d6a86ea496c2e4693d1717e4098ff87d05a82d738fd8883a82b9d5e, + 0x05ae261694bee2446a1813608edec696f252922d33e94280aa805bfd843786f5, + 0x186ee2ca779c5c26a193adf0ff47d9f333b750f99b77655011c64b3e8ccdf93d, + 0x1c2ab6e96f68e3b2cce6da3465b19e3e4a437b1f209c55e6ef99a1ac0736bd11, + 0x2fd17db7e1827169c32ccfc0ad14d9f97c7507f8ef88dc5d6f04b02203c37e55, + 0x241fad7570628418ab9748ced53646c2e100aeebd62a6c73804f080de66d9720, + 0x0016b5b53403ee6f47e6100c2778ca970b40af6be277e98b71032f894e6f6a2f, + 0x000a095842f718e71645b2e81c90b3f0857c8c935b135b0cb25df1541d38c7ff, + 0x303f2ba04eedf1425b5d7cc4be2c5088b9d2ef2bf478b9e9b8ce6ff1668909bd, + 0x1494435142c96fc94e8d66d9b643e019163c6ac2e4e162056fa8feee51956667, + 0x031cdbb9ad28ec57c4e1ac8ff66c791d04b25a28abcadae83a5573e3f3d4bfea, + 0x0c787dff012f136b89ce3516c1cf867928d7107d218d62d51b0b2d8cc9850498, + 0x0b20b314907f522e17a9d5da8c10fcf88cb956556cf077457c1e4a9ad5dc0b0d, + 0x11d5cadfd04189c6c14a49e8ba6783540adc7ed70bf25afe25df9e2ffd9bc35f, + 0x0852309d50f14538c8b7d35658d89ba30e29aab6626531aaa1185ff0cab8a1ff, + 0x257395e7c190b3cdce5f934dbea907705008a30593c69293fd7105622602604a, + 0x0aae37af5c3a542202935f590b667f979fb414273cc87931610a4b3144aebfb7, + 0x1c1654a77feafcd7feeba94c32605f95ded03e13c08a6274c47edb41134e2444, + 0x1480cc4cb3b9d9fc97b99e340fec19823dcd2edf198f7095ee5c70a9200995e0, + 0x18711057869189126f88536accea4882a34797a9dd96a94cc87b8ea462417655, + 0x0e9c4735ee797b9c70833a7a6be7c2cfcb962f070caaa649466fdf9bbe5828cd, + 0x2e2e38ccea7ef6c29a922b027d31d9870ac0f9d27de19d70039bbd1f90ff74fc, + 0x1d66369e95c2e76030e380d6538a93278f91ea5dd60e5a316b3dced27fc137a3, + 0x29ef9102b5e671edc05f87bcceb6d900484e7ee7402a32ccc77fde2e7866a083, + 0x2103b04c1735f7511eb775c7334a0bb6d626fb60937ba3761dad73a84478e3dd, + 0x0dd1b6ba84a3c29b62923765068cf63c711bc1d6bb28eefe38a0e4861ad13963, + 0x1eab4c7faabec58ab9b73b2baaf21e42880b77b0f0dfd30d38e1c955e9dd721b, + 0x002e1a3f669dfc929b9cc84d96d489ece114d5be5db8571469f774cf6f6c8022, + 0x1214ca424ea151785150d7db57b93cc6bbc8d75d1929938460a7c67f0c791f11, + 0x2e174dd4aafff6103164d9165ff8319d9260c86218510a4d910341f0b4e01d38, + 0x20b32f4a423617fef146da5f1a2695fcff6497ffaba30decf6ffe62ae952c435, + 0x29f4dd468db0873491468b7009dbafc79951f3b83ab64efb8dd2e56cc9b31a8e, + 0x2519801de4e58e4164f7f0d86994311c87f279a38afc4cb3c4d26cf41c642af0, + 0x2ca123faf875de4eaad80eba73cb2a00f22eaf5b6109ef41a65d2d286f602cc1, + 0x0efed651a61fa30b70937bde9d02b9b6a302a1aab706687b2233ae9b20331267, + 0x13e21dbbfd7e5526bdc5075e73dee0aef45a0ed2c880b29b7dbd5c9e6439ee3f, + 0x2c2486d85aadbc358b1065dd7b14957e8cf5bf7451afcb394659741cf6be5821, + 0x2c97a5d5b9751943bc11e04c2d60a56c43d945b96b0982c8a3f5e63b73550d6b, + 0x0d3876b0553694380adc086cc9272e1770e2f86b336ff78040419e5edccd8cf5, + 0x12365c7cdd616d258f9ae3504b37d44e958c816a0bba374278e8b7ad79ab9679, + 0x1b60354d16b01843540b8fc6961ff84a58ebe5e42b46d22aeb618e2db4ade65f, + 0x03778fc723ccd03ad8c90c311c141963dea639d2524ad972d8496d129e1c2434, + 0x2ee721dde852879e1238cb7a79207147b3d864e6c8a14a327e2e558b9df57662, + 0x11020d0581ff8e79c8f5aa4d50be2dc792a038bcb61aec4ccea2ec4df2d0af4c, + 0x1e0e921193e35b3c42ded003dcbbed8eae46712e15e63aec715f3f7031cf4f8f, + 0x2a6c13d7afd6636c2d4d5d36f42c09ac3286b67703ac4d2c24dcf5a3add9020d, + 0x27bddedea7d8d398b4b6e9152e17c2d092217609b109c14574f932bb02c88440, + 0x2e13f9cbc356728e6d2b7a5c593aa9ecc9b900bb98901593d021d61eba6555a3, + 0x109af33773e416156885bab0513dc199a0045d405d81bd2a151690bdafba3b66, + 0x0bf7a121a985d20eebebf624f3837307415ae480954bf49552dd8c5f3e50301a, + 0x0f78ba7c3e6d15d11292dd121aad459483271b5fe2ee56a63814d5db19290567, + 0x1625df035eaa992f424ddc6dc88c1b700ac5e6d5981e2ad0df9b290a56bd5001, + 0x1ac7d1f33bb598fe9581ac73b0aad4e9ace99ead01981fcf2c502a71afd56762, + 0x2d37296ef0cd5676d0809608ba340cd7b202e2e1c2546d989417d303ec319337, + 0x019caa62c5238e03ecdf75bb2c276be1805be3fe44a957d8aa3bf07cacf1c114, + 0x0f32dea104320ce0f00919d90f9c6c76d496882791146c522a8acaceae3e4a48, + 0x2ce5d2452c0a5a9fb65a4a6482f34998865be9a29f266f88a8affa850f5ec6e5, + 0x135d590de80a0e717da7325c781aa167a25e5c310d92df83120e891cced24a8b, + 0x1d3ce96a7cd79e94492e32b8983d62fac736499850722f7fe7dd1589706ab693, + 0x0ea3a1e1f5dca3ff7d8671f2fecfb467f6a4e6516c8038a9306b36dc818321b2, + 0x1ed08c4f0e16d144059100f05fb463098e3d869f342e0ef8b4a47afe74a83a25, + 0x0adf612bc0c24e826135c7de0dba90fbe1bd249f7424f1970b52e8bb24d986ed, + 0x240c424a024e59bea3a14fca73d7b63869eb9b68746ad9c356b93fb6eaa3e22b, + 0x24dfab7238b05bf08f66fbe599763f63d5c70a181a7e9fe35daf0479e2b1cbd4, + 0x160d79a03959c968dafb76ea3e08ffd2ce117d094e820d5e9f7ce1debd3bb08c, + 0x1b65216187a1ca1679642d4c40aa05bff725bfa50248aa89d57f570c2fe9345a, + 0x243503bad8adaf14a8e565013863c13a77f6f7a0fff571c1275b18f54bd77351, + 0x06c2ad47bf4de574cacfba515d18ddaf782a8addfad1c18ee4391163c541a62c, + 0x214366673d387148578fef89434bcfc7e0ce4eb08661904026b30ba10f3a1341, + 0x1db81d98b4d4d83226ae4131301c8e3622a32e2b7884860e85257f5f7b7e6de4, + 0x29d2bdbc19896e8faf0ce15d7c883bcbfaa38861d7c92299a6bef42f7c443f0f, + 0x19295f72c5907e8d9f8d8cdecf7d193fa86404cbb7a85522f7fc33857b7a9c88, + 0x0bf015760770cbe8e6f69080f3aca18258f2cd092e33d3ed62d8d19d144baca8, + 0x06cb21aac0be8dc2528c3974724b38d73a918530976ff118d08764cd42e0b240, + 0x1276fe2c751ba49fd5b75cab5b71f64aa0588ede807db1bd583c3d6ae6941356, + 0x2a17fd8041ecd762f528d12067a09204f9296ea57374806c39896fe9499b98cf, + 0x1904e2bf9c0512c72559e71e3f132f65259058f7d68b9d7d6da1a8f9f5caf674, + 0x115b5eb99233a8a2200170733c4743b804c601b5d8d4656a138212d66eb89d38, + 0x006b58885f0e09be6ba91176fc8a6172bc16d680f888a3d92f31a3bf213e7ef8, + 0x13c6704e90535352934dcdc0483b4bb974d50beb7a5b6be30af0e46fbd7325ce, + 0x0fbbcb96ccaf43c773ba1ce70613892543732feccc872975b8eb73e3fb4d54a5, + 0x059b4df63dbd2bb66e0b2a826c5cbda96c338fcc38dbf9e9c46041918bdd8bfc, + 0x27d859e7868c99d80f99d181e6ef7ea93a694623a89bbe57a6c8e7ee54be21fe, + 0x21eaced08f9d0b42c6fa51f59d65f96598e9ca50d6cd1dd49b84fdc0646ed68f, + 0x06815b7a3b80971d05fde6d7dc5cd2823363f38d0af5c0ff8abeaa71a323a2a7, + 0x06a778d29aabebb5a3cd940b1c33f05551217b6005248e0e716bd5a10d558c6f, + 0x14fe9fb1f167c6257ea010088115769e62b60ef3add0f3a22c9fe7a4918e94c7, + 0x090305dff314174e27edebe574bd8f0c8fd85843e7d2627db607b2816e357dc1, + 0x2ce23dfbeb8e1874b9ba894cb85f068bfb0497555cfd3dfaf3888aa492d20445, + 0x1b0fd94dd9cfe774d9146be584ed0b25cb2c7495a708247f5763c2380e5c1cd5, + 0x060bb716ba723a4e5f5faa179363a36774619d1e0cd91bf4789a1aadb3e612aa, + 0x043b10c508e8681843eddc05e73b95b7f54da5a93b701cba4d6822f9c9dcf436, + 0x126734e9502ba9fae4a314b67ade6ce8890e304a430e6c9f4fd60cb8ad69950d, + 0x26edd35db97c2ab2ce27b503592859b4317a25a688f9743ef0dd9cc2619db7e7, + 0x27b225e4a981af36cea863f591c8bc5aa95a4beb6d5c9abc5e03ba906ed72062, + 0x1102728832f751c313ac6610fae58b9cbd511b51d6121b3bfa60f47db12518da, + 0x18276cb011bdc6d75eb1c7d5d06cce10c7c9079c8c9920fa389b116620ee4141, + 0x2502d7dece8cd7d7a04a1730bfd2868fc64f835dfe143cee18480c7c3fcada76, + 0x06b20beaa575dd846254695068484611bbee1ae48285ba2c3d99c14e62581a2c, + 0x063ab4a078fcb212275ff5fd06042bdbd17aceae994e2c27a1ba876139f8ec1a, + 0x06372d5952bb69a460bf1333ef4ac6b20b07ad4ab4124dd4066a6cf66f406993, + 0x0f41d4e3ef55da71cf4037c49d44c0a641f52a5a174f7abec522476e3c623ce0, + 0x0f0ee9841b21b9b223c1d1a906993bd66b0ebcb7dafbe2b802bb8165c6011773, + 0x01df2eb2fa423f01396e073390104cad8004a6a5f140a2b18ed658068167521a, + 0x1ce05bc55407c883a5a41792ef3486ff22e403d38474cfa90f5ed30c8d30198c, + 0x037f1fc7934bbd5fdc34388bfbd0f95467254e5df2b5b62caed0500a2594ddad, + 0x1bd6a614004398f329b7080ffe69d3dff6de06c819fedea24aed16e4c47164e7, + 0x0fc2e5cff7e9efd46fee62aa3b3f22bcc9f1a3bd8917e2e1cf5aa334d29d2a06, + 0x274fa4e3d86e7ef8b0fdf1a81acce8f9ed2f2eb4627de75781a813f106a377e7, + 0x193af1c5fa057ce682ec728cea90735935a22b5aff46ea2f803a29421aa950d6, + 0x0e72c33ed6055471adad61d027c5ac1bf75444fc4e14988b42268f0787e29875, + 0x1c75804a4ef1c81c83684d688c4429ab1a7e517dfc602c9a2443c59f32ee9614, + 0x08803f69d83e0c3397e09dd47a80cf9f4e423437008cabad2e50110456c8c60d, + 0x2d1214ed17bf81162a5dd43a3fdcf195fbf47426044cb22db538478e942b07e6, + 0x0c85b24b79ab57504422135fb1cb0c5e1e3a5f0a06103c2486ee6a3eefac7288, + 0x2e29f517dd1b30b791bfab03ce747f950202f0eb8267ef3f71ccec40e91d95e6, + 0x13281c94a670fe5ab09773af42606740503509efd74c1ed993bc6afaf3d64174, + 0x21a211407cef7b0442160acc9dbfce1a1e1d58c9e98f381a7eb48f7bda0f1e05, + 0x085ef1e77f929bcffad1a93f920c1d8c8b3632e1e1a1ccd4ecb01602759e087e, + 0x2b6f796de3509ea703c8da6276e3ea154b504170c59a8ec4581e9757d74ba759, + 0x1fda5074fa5bae5e16fb4f2d18d589a7230b9a1c1e4d08a8069fc8d45b1de3cd, + 0x02d22a3c0d324750d3be31219af32a8282c372dfde4861ef86ef15c3155dcf14, + 0x0c21f4f4bdae07a79bb3a98cfb351aa629f3239c4d24aef92ea79bfac9c2fa25, + 0x1b721ec1c1df81c83acd7a95ace16b3e2ff4297aabb6f58100b5dab06d3dc404, + 0x27ec9e9e923edee58189d6c7f303ee3e5249c5aef78758c7f511cf87b953561f, + 0x1ecf1060366dea9506fda0d01cba016db9620090a160d5a760a75d12d5d72e78, + 0x25d432df312e005c69a06a1f004ec899575034da26392760d17acc80c39506cd, + 0x17a0ea51f9a201ba2a0f857c9969a7f6bc6f5d5bc0e4957e1c0dfe4b202e4a24, + 0x02d34c47b847d67c9b4dc313bc714ff223ab01127806ff6c922d8763f142024b, + 0x020e59e5e5bb0951a660122fc1aefea294e7ccd5f9c79839282ebd9e119f96ca, + 0x249c9c850173dba0ffea3568c28416020121c3d9990dfe2e917377467759267b, + 0x01e8ec57b7681d631a02d530c9aeef93775869ef093de92014cdf85ee2d459da, + 0x00f739dcb9f3ee6e7b5519774b540b2898bb6cba3629bb6c60e423b7eb6b5ffc, + 0x0e016f0724fff85d781aeb1548d76c566e5c26aa7996edf504e4167285fda66e, + 0x275270828b9ddc964bb8d68a6258543568c844947ed5ed94b3180cb874c68325, + 0x00f1ca3fc28aacb8ac21a5b44bbeb0ae64cc339de13e04c74fce820f4f93e48d, + 0x216b2f89c90105f570e0911bd1ce20e0664ffe01811cb777f90376719c0e20f3, + 0x1a91edf90950cb2689d2c29cb22f8dea61ec41fb061f1b6002f72265694c784e, + 0x2da3342eaf39a2b242713484462971afe53df55bed5f5d50d67d9138cd78fe84, + 0x29f79c86f5a9c96fcaf2296be36425b72afaad4865cb9090848249158e2ea4b1, + 0x0519426a15a599f20d2979302067dbd1454b46539c9499c65f6195b55c760337, + 0x0f9c475cd72b7e2e3865e96baef89a149eacd3ab340210a9c5e0de6fc082e89d, + 0x15f1d711979dfe13e45eeb9759a89f51db3d27594985890b88c9bf276922173a, + 0x1f083ac0549a1ab00d4bc9066f05494148f60c9569e7989941c3f50fd6acf760, + 0x1505ee4f79bc8187856d5f3f5a24de97aa082b8d452c63b17ac3a591451b747e, + 0x0f20876d712f147e2fb9f7be6a51f346ea28447df529eb41342948fc2d8f096b, + 0x1696d12d9ae779c92120ee715f6b8da11ea93af2673715a2df7731db91e360dc, + 0x28485f438eec133b0be36b32fae82da57fb4006bd7f5bb15a267e7746b37bad1, + 0x2780436f9da12461fbe31d979656e6d1a13386e0e6a5309b050ca819e10ad945, + 0x271ea863673332df2bf2471e6c8935b037ea8318ea5b32379583f611e06b3da6, + 0x29f1ba4b29c1daecb9839bdc08431bcabe68391ca540f68b484a4f8e96a9dc61, + 0x294f4cc728dd423fdaf37377e069aba66f4d3000f1a559bf4c449103306031e3, + 0x146b521b1c08c9181213ebdbc2a34fc3efd87ddeb1bfc5e5d17ca951f55abd17, + 0x0dae0af973ea0b0fcdd8158ea51b9efdeed5eb664b84ef67eaa255fe4e55f3e2, + 0x2604cccc370f0a50f3f726edf1242bcc131dddf2697853276c079ebfb883d8c2, + 0x2873b19db1d03896d3d52d6f9361e3fdade5e7b2e6833e4d5ce4661186bbbb9f, + 0x0b04d090bcc4cfabfa47f60043859aeb5f33a6de205dfdf0e3d099d4a8394e08, + 0x0508a195c0ca583ec10156f205ca1bb6f6917318b8ed6ebb7347b77d72dcf748, + 0x09262dfa80aaa0bc61c5891c237a519d3808c53fc05dce3d71f17c0e3f2a5eeb, + 0x0ce6d25b1c6c1b89fa005c23619d877f2ab2fde708d30923669a49fe25b3c7dc, + 0x2e69685b46c8050268dbc1040e23c739d7216b2c5e76108136d6895ded3ddc44, + 0x0278fb3df3fe913657bccceb553138fa7b8ab6e062a5ddeadfdddd5b305ff822, + 0x16da892ade35754e57d8f03f3e6f4110a9dc1639d9b6de65e479165ca49f7a4e, + 0x159754924e7334854ff803a1782ffc059927a3c26dc43e661e09a1261bd7c94a, + 0x2212ca6487b845ba4d16c09e224297d4b1a16e341e6c593d7fabadada3929d7a, + 0x2dd088de831852d169aee1d6be69b52c5dee0b73e18fca91cdcef9b90396a047, + 0x24ab42ad6749a14fe2f707ec53ac3b0315deecf421b9753032533e28491db30f, + 0x2f6466e50ef3c61a0e6493b18d34911406e2e97d3551887af808d67e1ce9ae27, + 0x1f5886fb8618c8711ec08de9477571f0eb6e462b8f5e5349f85631f059594480, + 0x05ba34953959784a57c0019e916e2ade5d6a523110437cea9c2b94453dcdf2a0, + 0x27aee67a3c6ef783cb55915165a5bbfdd86bc06c776f145048bb2401dcf17341, + 0x0f57efc05e9f97e7f68c694ba2b3bf216eefbd5c71710a56f460682a6ba5d5ef, + 0x1d35eb4a40a41dd77506d872a458ac93d7336dcb72f15b182a6702ca53b94eef, + 0x18a33064586d5a702bc4bf64f70b44b5a77918255c2dffbefc537e40bd5951ff, + 0x0b0ae5716e42b440b7423bd899319c880a4a674550b7bd036207e006ac7a2d21, + 0x1136a0f6c004a2c57d21a00c40dec6f027b140b36d3594c1cdc1b0e8707b62f1, + 0x21cec52ac4b2aa7f80f98eb75b4e0280591977d50b677b8ff10b0a3d028532ac, + 0x284a636786fa63579b1541746901d48e440cf0c586f1b089cc45e8b830fad22e, + 0x1d4a0aba0cac51c3261f7c483d89628d76748b0833cba6bbfcac5243e4bcb4da, + 0x0410a065925e90fc70ed1aaa46477a8ac8193a10c48b5d84fb5e9cf2123ae24f, + 0x301453b23d055c184a65ad6a6acffd9f520637fe751ff7b769409d512fc92f0f, + 0x037827104287d94bbdc06584d36d4d5e2c46c4ea224f4e0dc0c3bb541f053b79, + 0x294641ba8a02768c5e3b7f542d281c69dc2c3f2e8032f864295a64b08a93d993, + 0x1c12f993f0f1edd809eeefae6932e5b88738b336bbe6f976f5f7a0a178ffeab0, + 0x0cb2d948d38fb8e17c60ba6c67608c9ffd912e0a627eee756b8d22af8b9e5e43, + 0x26f1ff731268d9bbd26ab33e588acec09fd5a4b70d60b553904f5e2d05e894c5, + 0x09aef8a2029f82b76d80ad8a3926cb6e1174d8b8b89c59707c123473120b4c7d, + 0x1be80cab12f4bd1737796bc770f17073c6b0046c327bcbf3a36e26406c775c74, + 0x2476e7bc637f243d23d762cb3e2cd8430dad89762576cbdd918428a75828836a, + 0x196d707ca5a9edcc0e3103aedfc60abdd1c9e577354d930be0d5b6d03617c209, + 0x1d262487237e8503908d5375a1a798a9b8c0faccc056eddd8aa87d0a66b07d24, + 0x2a21e03d41154bf3191f1a834b9af6b23d40bc01d027c2b4841fb23dc9ff715b, + 0x029c647822a1ae565b2bf1249edaeba0cbb3ad730deb6d2e6618fbf9e74daad9, + 0x23e1971175b8fbb26c0989dea82d8f4a3f708774c286e4ed2f8dfaedaf3db5e3, + 0x1306188b792368ebda1f2e31e846854cbb34f175e01c92457959ee1c6da0ff3d, + 0x127d0f7eb9804fc20ab4f8b9409834ae521645fffa86b0c221d9223fa0e9d2b2, + 0x2441985bcace35a81b1f81fc6621215df0ba42441e450fc65e3519a0393b1196, + 0x2df7d4eb115114544ac4f52fca36d6b33f09f639253e9e3549d5987b0e097136, + 0x0f6c5518f92ee2e549d31adbb4e78036ef9aa3c2164c317aca92203e3b99f940, + 0x26e2cc9dea47dc6807f87cd87c531b17a7f2f5ea86ac094e5d5a22fc3433dcdc, + 0x1c71e33c864b0a8de4d10dc26f76bed55771d1601a0e04d399cb2397064c5cf8, + 0x2a2f0b563b4083766c8b6c60872c32eeff2b207a1981c05b1f396178f01207af, + 0x0c1af0bc5546250a7fddf1cbd3e7bcdbaf74ebb979535e0b343676dc9f9433ca, + 0x018bdf2e7078dc40af1cbe488cb562fd32120499c4c972a6d43b92ce167ddfe5, + 0x22b36859a16a8cdc3df10af2820715891f779660a1f9a25ef652019f640bef06, + 0x10e697dbbc43c7ae2030f5d49974f8344d5e48ab66d635b41e7b96fbc7c6289e, + 0x057deb4fe56390abbbdcd8822cab5da1207a0ad79423920622b0c4a12fef3552, + 0x12b27c1639f162f846fb37ae7144f29137682ee7eb1632e791b4628aff4aac23, + 0x0b2c7c76d01843a2d14655c23e8091afb6f3559d66c3bbf3d115dc9d70db5af2, + 0x0b7d9684c0c8eca0e8c31634c9fb68b2e83abe72a3679b3678a8c9b1a13a4895, + 0x13ab0a7fea9b2c828766d2fabf574248d2d7f7b2f8e60e261cef29cd916e9a2b, + 0x2de3579d790ac367f66d90557b54668153a5c37d5391e92a6a5615c9d60be979, + 0x1ba010b6d63b9538b281be3764e8e6231642c6a6735d89c9808fab7bada21f6e, + 0x26ffdea8a8d9894ebbe02a705fb7506e12b1a7f100c5902584e4dcbe1f2119ac, + 0x11ff1619a49d6abbb56390e3dbaaf0c1cb01b951a734218b3cbda4e8052ccba2, + 0x260c36b80890befae89cbb3478b9f7b5b3f6b11ded47aae2c0d5e0c48d8e5174, + 0x05ca88857cb0dd5f380e592aa37f6f94f7f0c3262131cef29948a1a49fd184fb, + 0x18b3832a19eb7ee1a9dcf574302ee063ec19046b3b9eb7fb277a48ee8390e485, + 0x2535291f03dad1e3c540e7f26201c2e330188fda58be783067698a1739f79369, + 0x014f832b38a9f43af26e5ec2fabf6c4250083cf87f0ba86b95053e9182d1373e, + 0x2548e6c4767c67691af55162d9ce0e45e89ea08a4232fa0a223fde869bfd3ea4, + 0x023ecdaa3f942bd45ba46f528cbc81a51ce1425039f44781a7696f48d29dfbd1, + 0x1611bb59a3b28756b840db3189a3a5ea22ec16845472abd68570ac771c8f15ee, + 0x0bf7618845013330ff465f12ca95079ab72d0ca9d8a7e633048c11bf2c46c7ad, + 0x15c88fa2eba3d087fd29f6de6fd864b875662ffa438144352d684717cdcd3ccd, + 0x0d58d12798ab552f96f0d951e97cbeef887d858656b1f6af4010c80091b0c662, + 0x0406eecd7bbc21eb04fa1e565745cc65445e4f82f4a241efb8bab06eaf9c7cbc, + 0x2fa88eda065714b9ae5e18456130e31bd6f48d02b2415ec61ed209ad8ddc3164, + 0x01749863aeab13ca512261103eab93b43fac53df6b04022c7cb7f17638f51c29, + 0x01553263a318edf34429d901f3879932b72f5c32ad56e900abf47672f86f9a62, + 0x028b7a8be47c2239079a01dd6d0e57ddc03fca9c6a58d3df6f234dfe82f96aca, + 0x2c489bef0fac19bb187e5f8a064e67636f34b289c2e8adc76ecbdbb5105fc1c9, + 0x1ff548c6690f5227d576668fef6741f999c9914cf4842e793fd5b5194bd0c3dd, + 0x03c1b551c84903040faf3d6db934e83dafc5f0efdeb7a8feb27547724727a344, + 0x1ee3620e8f0dda8c6f155ce81a9376009bcef2c8d8f6f266e04b7b80ac8cf867, + 0x18e45fe7ea171fb11d0c4af5338568990f22147e14421f336fe6e0bcbb8a0014, + 0x27393404521a55e0e1a4e58c561180040c18682814882f45aadd131b9f08753d, + 0x07ff6857011a24b20d698ad43a5f959acefff729940e346ab18f9d2600f83d05, + 0x2981b3a288b4327839542c5796ce2f09af9d022a604ffad61fe0077d76748bfe, + 0x00dd5b0b8158e8a73995efd0b9d898d4fd3587011fa586cfe02ce800f3064033, + 0x084c05fae73cbd6432e622cf9880f0d28337c6874b87b88ec0b45a55d393623d, + 0x1e2ee2fee9b9bf8d3f3722e7028ff3af8e5ec6319fa6d8997dc115e5de2ea8b1, + 0x0003418fc5909b62b0296e6eb42aa07a971050939e99ee371f6412e44e0ef577, + 0x1c4994a2d41258064376be5cf3c99887aab74803f67c12c64e65aaf7f1ef56b2, + 0x0413c2b38733961feda0a68493d3cf44febcd77952b8806ff583e8c40b31032e, + 0x01c46ad39455255525b267b8a0533c5c66504f81ae9534bdd091ea98994997f1, + 0x232fa2c090ff3ddea83adca0b9cd0e0918c9458b75b0ba3b7d677add820be289, + 0x1cd5701c80a10f420eb34f534738c0dccfccb6c87ccf9aece35abab37cf05fba, + 0x03b981fe0c71882c6194465537d5e402b816118aae94bf8518eb07a529e4ea54, + 0x168a588900100006443658a61ca9d659f0ac451d1e0bfd5a6c6a3aee85723bea, + 0x1e51f558bced240c65b7cebcdcbbdb7a9ab06e3580d46f318de84edc795e6f88, + 0x1afa5a8c5fce396de56ec97dcf0317a6b7cbc3ee1f8e9a3bccd6d870022b750c, + 0x1135efd63e8f8cc9cc0661dd49d36ac8ebf7900d90d66dd5fa816054d4017dca, + 0x2914d21c2d2845ce2b14e951f42103599c8755015641db03c54df337103440ad, + 0x20c87a2d759749aea9b2f0f8cc01452452e711e39eaf5a8b07100a197127eff6, + 0x0db07920dd779c19fc1ea8ec5323d5af0d511b869db67dee0408785ed922905d, + 0x0d631f18fadaccbfdd3b3be46772a3bcee276378cd2e46baba90d56468cc50b6, + 0x2c500f790d463fb136f2d8d4cade62296e7d7c49bce18395b3014c9fc72d005a, + 0x176a9eba97635d1e59b19faa2b3325a5b1a27376a16dec7317aae4afee02bfb4, + 0x1202fce1a501b88b455ca44788d55214baeb3b54e37d1cc80f3d6ec0e09d4747, + 0x222948377ee9d27fc6406007e1727b566b825decb95096c9aedfa8e6453a5cbc, + 0x2ec66fc27d82aab2c98eb50e67a0932210f3c6e12456269d57ea9095f41166eb, + 0x2f5c233dbe3571836fdac0915ce6596fc0844fec3d0bf5a9b968ca58c45846a3, + 0x13889bb59b9c07953b52f66123c8c1380e6f272426103adcefdef4dbd2865da2, + 0x1cf78f25faa52c747312d09fb4e9abb4f1e55a3da349cc8dcc6dca81cf99ac3a, + 0x2c0eae2866d65c97077047d0f4c43c28c8d7f36af6a9c6fe07ec89219f1cc735, + 0x28b816cd8b8c98163380066d0a50d8b0e06ff1c690b81b918c7ddd08a6b7066a, + 0x1d46d91669ce5be6554fc3ecee895d41fdaeee189adee381abfb75ede1488cfa, + 0x1841e03b9fc527450e4470aa8f0888d9ec8599db6b0f7222dca26cd43d22bb05, + 0x2d2ead7b2078b09085805c2777c90f6c55744b49a73bbef04c899313bafa0f57, + 0x01830a8db342676cf7492281b4cfc7b138c55d44daae47b14fc888e5bf745095, + 0x074e4ce32bd14b01fe9f6729de2a12f218fe443fb708738a860f1910bdfa4678, + 0x1fad4cb140fa4d559cf9525fb24e7f17494d239af679a030e7d1b7c9cffa949d, + 0x1e50c6526c7324b97b7f338752bd700ca5bd6c0efcb225260224556d76a28331, + 0x02cf0359b8da1abffffd73f90758645793f5d1112fe898e8af0c61e79e673e5b, + 0x0a14ae497b49785ae7771f0dfef4bf41857bb2fd1f27d15c3cbc8ce3df9895cd, + 0x16bfa02f57735662eac1c1f520b4b3f9c4bd26cd2792177b276068916954cd41, + 0x0f6fa95e0117b734579f68dc59736c7f9afd9cdd4a90e13629eeabfd84525e9b, + 0x1d59cafe27bdfd78f564894300763436daf93f863c3213c1a849d1c3169ba771, + 0x289e39d6a2d4bc817ab104443b89b8a608b13bbb93b3ade772a63bee300bbc3a, + 0x0d47edafd6a8d4651c27f6bee48e9756f5d6515af1a3a3512f59e9e3ebdcc331, + 0x198d6aa9072a06de13128d7b17157f85994a10c4957262770cc4f59e6c6d332f, + 0x174b80e4210f9d81be7bf70e3ab0b21de8065f7222e80cbbd3cf985d6aab0f05, + 0x2d78036ba0948752ae78b1138b4b9c4b67f0d78a9c8965e1bbbfa356158532bf, + 0x0c1ff404599af823908f32e607564f521b75812c670543e390cb02e3087ce924, + 0x0a561b578f4be4c533151da1a529bc98f4940aa5b48f8c012a9c181d811b8f34, + 0x2012a6ed245e48cf65030289a1cd01d26d3eb2e439bbc4f16f256adceb40bdec, + 0x0824422abb64b758f600c18e6b998c19d82a9ffacb95f9eff9e018d5afb30baf, + 0x250a091bc91301bb1393782a7e21eea81c0bc8e68161a3a4e5e4a8a7e30964ad, + 0x1a4adbc8530eace4e19696d77a06e1eedeba3dec2e44accd3acfd7fae6d076b3, + 0x25a511f7b8595b12278f2b05b4ed6684ee12b1d298fce27ccd6787b5a86e26bb, + 0x07df25e8f76f32d99b99dd04d927c1b2fa1903776636e38f7188d8c2b73c3a54, + 0x059421ced9bb92262f97e7c7beb8135539dd66bcd6f0bd41bd124a929823f75c, + 0x26e1cdacde91e112796df70dd3a479b595b8cfe7c4c95b5956ed477a07813842, + 0x298083deae9e0cc40a9b60e494e44e6efe93a8e0fe21181cb1351d97fc0d954b, + 0x0f01fc7bf4d2f1ec8cb1af8ff17715316fc44387d515185f49a2443ad2a14ede, + 0x186049573b3286b17003f9e5b27b8a36a78b8f32efbf0510d9fcc8fa7e73c5f0, + 0x07335829d8e3758cbbfc4cc49b655ec758086676b4d3912da39f2ccdc4a28d14, + 0x019d072d6e66aa6e034843cc3d7ca51c47df51f35dbbf4a99d34293fc3d59624, + 0x2bea340a223b6665f5be6dde2eb55b40a05aae26d349a6c4af07e3458ab9be5d, + 0x1b90f5c0e53409f8b573056438bd9e6395f5256fabb16006c009bcade1eecda7, + 0x01932c3f3e1c4481420c603e23f16029d8b97603565f6314184776d865ba2e7e, + 0x12e4e9f31be336777527af3ad443884e353552da362921074e023f14580b5e73, + 0x25e7a09a55698b0c7323472b2409654ef12f2959a7656c0dcf35ad9a7926f3f1, + 0x178c9238fb91fe512f6885e512e2a59b7686a34aed0fde1ddece6b1d08d422d4, + 0x2b568832e6262628c31e405305f88402948b515d28861f0dfaef24921e7e352c, + 0x146ca0dbfb0fbb98c162eb84b37228cfd7311e0d15d2e48def85f9d207bd175b, + 0x0095371673ed3ee55892e373d5ad5c760268c83df7f50d44d29d366e1d7a9373, + 0x051c57cc37343989744272869cdc94c0660bfcf6ea1c1c7ae51427fb298c9db4, + 0x1c8bd96ca390714a2b0079ec38e25af0fe7a69fce1620f376f770e1325aa65df, + 0x1712f67e82f90446550d51c1d2e4ebb1475d6e6043a5c46eda3170839785072a, + 0x1c3363715dfea957de9614b6cdea17066c385a8864dad5b43aff09c963573925, + 0x2672b8adef74adb0b71c0166de766a39e5e1cae03719aed0fccfb7ff432fe916, + 0x10635771a37850c2417c96b7f5fa48a98734ffa59038d8b7136cb5d0c646e1aa, + 0x0b16fd5ba97f28f5619f6989cf0d665e908cfe8a1fc24e5326461973d09bf0e7, + 0x0027df27e1618278ed22497590175692d262d4aafddfe34bf8db619c37a66068, + 0x036ab8de1d7df77301d16cb576a1346fd196d25534b22667f50628769ae136ec, + 0x049ab0f37ec5bcc724a3ea321a91951f90cc00afdad5ba3d5081706df5e75e6c, + 0x112fe3f664849af9f494ccf3ccf0d4b8f1e4a600c29631d059bc6ec343450c49, + 0x232b3e1d4715272d5f18a036c137f0c6fa56878c9aa054cc33064e2a5d30f567, + 0x056c91dceace41ab131a1c59ce4a320857224a09657ed82f7141e7619a5db545, + 0x144cd983cfa259516382148e290dab14ba9b5d8e6e76b84ddae2ab086e7a7952, + 0x1d21aad5c6b407e6eee7d0b55aa92ce0a32a39e918bb32bc8d45c28094a634af, + 0x176f60be5a21b98d3469e1339bd5c7a0a8ee84a0d34339bef675d064e6e0a466, + 0x0329d048658d0eefed7f3aaa9bc143b0c26636f13262176d650a1a7a2044d34b, + 0x0fef28f114d6420d1a288f960fd9dd40bd4a5a02d58081621711ddd2887c757b, + 0x08818813ba3e9a9329254e78e00a83b360c905c7202459cfad0ab47658276a81, + 0x020a128b7112994e52c4849bba8d1217f13a957bb4d0ba6a0d97cf1914b65b07, + 0x0980db3c7d2c8866e9ca0902c3b8e0a078585951ea4acbac245b61cf55a703af, + 0x14f2bd6dc317fe19126b583da18e2d7175cfa704c5267b848a2ff9a12bb188c4, + 0x11226fe9d81faa6c6a35d3a12230d63245061f2045361e757aa0c5ba7c5b3152, + 0x1fc144aa275cad950ee4e3182bb87783dc45906b2e846e2703228e5d5328c1fb, + 0x07858a3e15adfc14141090d972cdda3461908dbfd1c91b7e9b991760c1d47749, + 0x19284489d7b53ed2549c5fc66331c71b9b31446eb3668c65d85ad094727d45e0, + 0x0587702c19b9737857f99cfd021f8fc6af71b428e3ae90f9f5d2ec8e7140f5d8, + 0x30602b296ce2450d72b00ee8cece9f896842ff3470b98e1cba2a1b3ad87539eb, + 0x2776dbec079a5034700cd9c6e21404eabf7c13fa17d065a2d69d2987a718e78e, + 0x28bdd009549a97fd0c29e9c30f7af9555d864aee05ad1886fb918d371ad29e90, + 0x29791a2e17dc204afe645306f584ad767f2be949aa6d061f886f21d0401aad14, + 0x22a667b65908699a22edc1697324bd37ffb0f18f00c0ba7292ec8e05470fbd76, + 0x200d4863b2f35a853b7d5dcdc22bcffd8f45b60bd036c2f94907d873e5d95ca2, + 0x18bdccaca11c8a10a12be6f7cc96d4557dd9cdbecd5f841e87303e3a312e9e23, + 0x126ff502714b58c3a40ffa3d96df0de4e8aff3543975235bf3510c7ab22d897c, + 0x0570fa4d1c92cf2917036fb2d477727e55b569b4a58891a07f96c500c28bbce2, + 0x08c84000db8f725655f47432db3a4dde514dcf49b40fc4d301a17ce5d7228feb, + 0x07212da8afb35376a4b9f93c20f7419ec704b22c898b20ebbf3ac9f1bf513038, + 0x28c6bd8667a7e5336ebb7e53c724990fc8af6a059390353bee16d8c8dba971e0, + 0x01790e7a8c59ebbdce18ea7b9be261b8848a8f5c69b3cd7a7b63a1b1e6d4c926, + 0x09ce10751c2b7b90bce0d62e8fcb29fd3c8a0d286e93411fc66588a70a14a4fe, + 0x203ec579417ebd5f056e1346a8c5be34cda66c9901fbb0bc27b8d773de7f665f, + 0x2297981100bfd0bdbc495572aae5ed5676ecf2b693e33913b8fcffe65f57f4cf, + 0x00e3fff36bb554a017f94e88130957a975d343d15c0772a67ce88bb1736db3e5, + 0x22214f9dc31c1766784846260971d051aeee92226b6f13e2c4678689ee1304ba, + 0x1eeccaaca23a1446309ca4c3d9b7d07962dbf8bcd8b3b37218f4199281263327, + 0x1bd52cf0abbd32e888d402aac0a358309bc83eb74256efa17edc1abad196bf63, + 0x26cd8ce2ace79114e2ee96fc1ca3801d012345c68750009745735edfc4e29d71, + 0x1dd921013e6519e29b9aa0f52cc8c02fff3ad7af6a187ef0e90635008406dd02, + 0x10358e1cb8ac12e54988a64bee4f1e94921f030a6926a00d57236283ea0c0ac2, + 0x1ca1168b167aa5298bff96d82356b7387ebd1d70431c30b1c0c0df81fc0408c3, + 0x08d1ab2692d291aaef2e50985c869485061578a2dfc37997222c81ef301fa942, + 0x2d59780dd0a00a869516c6a0b300ed06f6fc39e0f9ead60507cb24c14444899c, + 0x19b30f06355690afa779693f7f99c4a470f8ab8abd6989993d489a9b17180cb2, + 0x1b93c9367d56b207bb1a2f171b56208c6aa1279be2572c1a59e65345d873768d, + 0x2f8b45e1e079448ade818bcb785b0c8bcaeef004d956142347a08467e1961809, + 0x239af691b7d6edf2761f88deeaec665169de99399cef819dcc37b4609b6cb4e0, + 0x1260bd299d9e99321561090559b3f90afed3a36f36c4d397072de293d34cf8b3 + ], + [ + 0x2088ce9534577bf38be7bc457f2756d558d66e0c07b9cc001a580bd42cda0e77, + 0x1b86e63908c4b12af43cec6810356c94d21c9e37d73dfff9742a58e0ec356be1, + 0x09ca022ba1142d170f755212e2edc9d0a4ace33e16825f540d5d50d5a021a169, + 0x277e69d47a133804241f6aebe9449be6e22c849c6d8ad8c938eaf613bc1aecd4, + 0x17b57ea03754e24ae0ef425aa2ad931aac9ba5457a18cec594545a235db6b269, + 0x11c740983395e0f4a026e2c7c939236375c9077755eb1a37a77d5a1fd74abac6, + 0x1cd85529010dd7e2fb7ea403515bab5727556a479c59b822efc5a81eb37bc5bd, + 0x2cb9354002cec4bcbfa985de34f43d702ced83d197aa374b5a1f96f87b12f292, + 0x1f7af98e08f6877923f27a3dad40c525ac52f56fbbd878506544f9acd61aa32d, + 0x2b15176925df33a45c9e99a7c4f26ad946b1075de58c7064c0ff92c431d31dd5, + 0x22c89859b4d399d3a60a322d6b399b88061358493f3cb3653fda940e988c1ca3, + 0x1a9f2730c80854d8f6dd98109363d405597039373af5055aa67fc18e5b1938fe, + 0x040bae2c57fc68e3ce5e294998ea060e2563ebbac58ff8fc4a1a0a40575f0ed3, + 0x16bf4f5622729467ee9749cc380605d2bc4d885cb99699aa2dd8565c4faf8b7e, + 0x1045ecea044ba1cb1c3bf07ff4968390a3ea075001b21637ec7fcef61b11329a, + 0x26a319fe6b7d6e08dd6cea9587cfe3f523492ece769f70f66d3b6197a262fd09, + 0x28a5629b4c2083387eacb09c1571256d172ef1ed9c0738686da84216ba81bd6e, + 0x186be22b6a063d18cc8760dba63b119cfc6d8897e32d6a0b19de280532fa9726, + 0x2c41eaf9c0128c486c5595a1ced6b3dd15bd9b73218c6af88137cb8aa5c574e7, + 0x11864265d76e8873b4d2ceccd18dada46ab7213321dbe0683727fa2df7e3cd7a, + 0x1383e7371d7f3eb75f97461ff79565538166ede6fb6ac68b02cb60d8322467e4, + 0x1a005346e9edc59573e3989f34c304ff1351de9642f398163602e138c59c7469, + 0x2b541345bc4fe1589d649270ceed4b2dc6299c69a5d24b460e36f3b4eb486052, + 0x213e74e3b88692068b420fdac7a62f3e90f87e8bd993310b982881b4ea7eb58d, + 0x0254370fdf60e319df5d27b984e21d8979c86cc6c9db77b47e9e037d41ae2b84, + 0x083b7377987bed3fbd0c5ee3279cccb319adaa660bb6a79ceee627f5a6369ecb, + 0x0a2b26bbf2b84a55bc4c5b09b209d4a77bade4ecb0999e2a70021cccd4fbce1c, + 0x287090d407c4c5293cd72bdd881ace1a4785c51889ac9ca053faef068533eb09, + 0x00a9fcc21a234bc22a473c04931dde66476001ea6e32931277ca4cdab62a8587, + 0x1d79fcc5066ff2a62d6ec0c096f3c0623f9722c5d10d6411386b8cf06606d116, + 0x1d2da676081b7b0a7d87a57c6a6f2c91022a82291934ae8d646814f38b7c9cc3, + 0x0121189d7362dba92f3bba28737ea247e85ff4b3ceabb4eadac26f7a79d371ad, + 0x03ba01bdc7f31b4b3626831d5e82852a5da5a7f472f497564362ee63bd6d6102, + 0x216487ac4eea81e4d835b220c7f1e7b7a3312df5ed0b6e606a169bdec89a35cb, + 0x0eb5eb424bc72e5b20779d6138a7296dc333b4d98e4cede698c1d8f3069fc804, + 0x1476087ee68863fe69d538de90f90bf271875fafec3aac6831fa17811afc45f6, + 0x25995ecf079f4f81925ce8050e6bdd0b440e7adfb00da7e4dfd8a5aaec009f32, + 0x01b590ea145df6152ff0e8eccb97f057eb378d3dc8585a8195a8fc6b03dddb21, + 0x0ebfed12777ad9747734d82fb7ab59ebc85f07c3d055eb987dd42470e016bd52, + 0x2e03b519ff070e31bad1ced25d02de18c5c073355890f26d6437c9990a3e232c, + 0x028ed48befb70534a157c0bc8037347830ff6f7bffeda93a22663117c3038109, + 0x21d5480ef2288cf37627083f5c6ff5806645d7878339792169d109945aa879cc, + 0x2a017f4ca62717fe9d616fc3b74f426a22666a268eed190c92513679ff531866, + 0x085cf123084d6b4b0b2b34cf06cf6f893e0a9db664958560e13102dca258a182, + 0x01cab1eb61ae5a9c4f1b1f0f4cf71073d063cf8ea6ecb3a326bc3f2f24fc30ab, + 0x08b659a737c0a7e198c51de07438e7faee94369715042367495f0305e89bb96f, + 0x02b3adfef956007ba949e044a68115b0a9c895a81386e769744e7b5b2c307df6, + 0x1a502a7b0883deaf9b24a7b451cf439d9b04c40af2fecc172b057b4fc00cafa6, + 0x3048a536a2a75af41a0fa596752c83edb19c46c00e4072516a2cce33a42ce949, + 0x01d008216832f77736b9f2c8eaf18d2ae69a7595a3d2e8725e75b3e9c66ab22c, + 0x067389fa6719bb9e493424576d30d6254f1b7d54e69e1d1896c1b15ee85c0c20, + 0x17da04cb5060861588a4dee60dacec407e08d6b19650359452705699bcdcabf4, + 0x1e110b24526cf19448a04b71f91f834d903a08d3a7658e05ff0104ce6de14af0, + 0x0b0a28b67269dcfb242231c7384d9b96c4406708f1a7bec26160e2352a820e34, + 0x0226ba223bf5cc831bca604a2f55b324ad1d4b29b81ae33cbd7391ad0dca0c61, + 0x1fa506fae71f617db6a04dba21eb6224accac5f7cff145947093bfce2f3f5cfc, + 0x29724cc2973b5b34c4e53fb981f273589e7e0467a5b4b5a16d596f48844f0394, + 0x20185815e6d5bd43d769b1e7b3a42369db44fada44534a9e41a181a7cd90cac4, + 0x2cb5ecab94a2faf89986b565545493d5d8649d73a9f53133b614af6d89376612, + 0x06772704a6a6c396f2f186272db825135c5986fbdbce0a3fd879bc27ee2134bf, + 0x0112bff4736679a477440e744d7fc6191e168efe6c37fd0beeb6e64d30591851, + 0x2faacc248d2f742b7dc50b013be9c4b2ea8d00be172832ad07ac0e268e391a57, + 0x115ea053915c9231d6b9a71b4f3437e76d08af6e8fe7e42a3800136498df40aa, + 0x0353e2c2845c0fdfc53f58394e2dbaca06164d10dbaf756127621b5a22181235, + 0x29b3685900bbaca910363ae0cdec5f61cae2c52c7ede3ec010e2afeac748710e, + 0x1a73ba985b824209d0a9f310920791fad9227b21bfd8e8a3a9f1c2fa89fac1a4, + 0x274682d63a1d6a9eb5ea22e0558b145f5b9b5e845c8c9dceb83be943309a305f, + 0x249de663dfdf6682ddc122e02aac0d79398f38e6089d92e2c892ccf949fcafcd, + 0x076346a494ca499918229d2faf87b6b5afd4992f0d7d4023cbb677ea4376d4e2, + 0x0712154eb43b0a3e8bdd94e29ad85939e220daf6931b84464741e64e9926b50e, + 0x15bb7e127b9fc937642692a92d864960e249ddf327fc6c92afdedd89befc6c32, + 0x0d438d885c3fce5b06a80584015eaf7a8ae05c60052c10ab80d80076800d8e11, + 0x2bffb873c9b04762b2e362d6195c8013dcf7a5fd881894b7dc383c8aa34a9e0c, + 0x24ea42c76f7350d08e8b1016663fdaa3f8552b9564e5ba2da45b76652707d6c0, + 0x2a62ea21a0ade4740b808b9d838b4ef205b1193b579ecece0da34523c481dfbc, + 0x0c49774a68f5274b468cea0f32211cc9a8ca864c6d32f2c644b1ab89edf475e9, + 0x0a9b4d3d32564d83c24d4e052dc3072cffd61cbffaec957151fead13246073cc, + 0x221179d848ae3c29baa0de8e19ad399cf000dcfce572ac310fc64bd4d201c3a1, + 0x1702294352579a43d19da15dee1fdcb2a70a45de25203435e2340692f7f5e0a0, + 0x059ab788273600685cf6de04f87ca9dbbceb1aefe37f779663a7ef5019d4d8e0, + 0x23af64b1622be07735af1999691398ad6a034029a109ce435f12c1b21b41f599, + 0x109ed21e2456ad7f94a0c6ca6ed942ef5e8132433e5fba6ed8f49b2038594516, + 0x26d9ccfa5379d3fd6927a58958338d6037872271d891f19f67f70c39e0893326, + 0x24ea9e2db358c1becf7dcd7d0e46979a647207816ae5a901fb00a6ccd991d0fe, + 0x0015a9b8c33fce93ae3971d193a430be98eeca1d27735974cf502bfb20c71bbc, + 0x2bbb366f79bc3baa138d79a96ab5cd14826bd3a85347e559550bf351f296dc1c, + 0x0a1c76641eded157eaa1bf4aadc956791d9e7b29eb14d07654af052686b70e29, + 0x0a8a9f9ee8ecf8ad0b5cd84217af26fdce2ca16c07bc747d103abcb48ab21fc2, + 0x26d6852b5917f4e229c46824d00b44442b77d8e566fe3b3901ba6de2011dead6, + 0x19601734c30cb2a44ee4a323b35f2c171ed67e0f3c1fcec7096e5f01fbae6885, + 0x07895f7f029f84c3f17e359b0ee926d402505587f386cbb71070bc17cc87d044, + 0x05807e0a2b2473f3b87130586c7868228eb4d9503bf25cc2b0f35a939e0ef483, + 0x1ac9ba8eb9e2fde0a79886aa8c7dbd362aa490a355e07982828be3e5099d2fde, + 0x231c7595f76fea5828672afc5bbb6463cd00e7a07346e2588af5638e3b321b40, + 0x2e3d1677310217ce5fcc58f4039532ff946e2eff2b80d17f581ca78f0068672d, + 0x0974163441712975a33b4093f922d7df17b2bdce7b7eb02c7830c5980464000e, + 0x1cf5c1a4280822a59deecb82a64baab4edb87977e98ee29139bb51671b9919b2, + 0x11ad46e13792150cf57933aa9476ec9184bfd5f23de46f1df78ed7e94cc81289, + 0x0828fbfc0951c1ea0c0f3d5af2fe5796ed792a9c3cc4002b41e7a1bb8e63dae7, + 0x02c720a8486e7122305304ecf3a00f99854535c4ff404fe82e30e99e8500fcf6, + 0x09bdfc942fba8824c0a38d6f525f9176360d2881aa425028f1cd3a7fc3ef72c2, + 0x1d954a0f93250e5581c6b897fbd72f4f2a943dde51e262e7dcc4a1b2ca82e2bb, + 0x2b829352e297ab2106e74f9fe702f69635edf37e7ab0e1a7f92f14c98aed56eb, + 0x12d3b917e58f1f44e1babaa341d1dac923dfac75482e108af1c33368734a904e, + 0x28a9e6c65d06ed6ea47795bde9b177b5509305f85326062ad5015077afe4bbfb, + 0x2bd3c33ae311c2f8d4ad82508b76df890c311fc8d232fbc2dc535fa593221ca8, + 0x272d00d7a8fb1463bb624f1dd774edc8f3a0923bf9059bae3d84da23767d6873, + 0x1355a796abdfaa903b81dfae32101a13068f5070440552eee0acf2a4d07d03bd, + 0x0734bcbce4180ae16d4a6689b9b94f2b02cc7d74ca8ef1592cd16afe2a033728, + 0x0778d4a614c2f76e28199d989a9052e2627464b620d91e7b6d3d15dbd4799d54, + 0x16bbc980a67b2a65434d087c501859d127db377ae144ff634cb8574fe8bf869c, + 0x12a3e7e197b0504c6894366245bed65e326db7c7aaf2c1c0d59e4bac10d633cf, + 0x1f35f8c4431fb0dbf42d9d07334fd67f99160fa9f7e20d811f4b8fea7dd5d33f, + 0x25d5bf1a863a0a6441cf55e7c85b8f232ff1556e77fbcc6d71e8bdf349bfdfbc, + 0x15e6b8d9ab7e063a3638216ae471176e87ee4ce30cc24cad19587a23332320aa, + 0x01929ef47c7322b77ebd0d1a40f9ec4d41eb2641bfba35a9cba7b708a534c9ca, + 0x184f51e791edaa2dea7911151247bad4b0e864d7a8f678c7708ac65c51e3bb79, + 0x2605adf5562d5055ffb284df1ec0d4e371eee0595ce1422ac535a410597cd866, + 0x06e6d41feb832c2fe007e1bccc81442585bc9eae1612b8bc3d2a4925c239ad51, + 0x137eb7da068955cde28db6ae5e780b7ae1c0d633cdd113bf0fde4345ac9c954d, + 0x2e97930eb419f7353ba27b25879753fe64d7d187023ce2de4bf9e70eba6e9bb6, + 0x13af409362087866e62d6860fdab159207405bf9c75a9efd9321736a1d812413, + 0x0fd2f95404a9e92f46d57c80507375724966264560ebafb3ff2fd19259d47d62, + 0x0bdd93ac21aedf31826fc3012fc8fff14384add521d98135df3ce70e47d38116, + 0x083ea678d5a53e8a9b601906befbef23811a6137788bb873fefd5521f7d99f03, + 0x08a9906be6e9ab93cbf1b94f090df2d02df6c6ccff6364c2ed6986d61f16af29, + 0x187b1c82cfaf880449337cfa77f618e3ed19c604e65fb768b0333d8d535eaa47, + 0x245005f814e38250751143117f5e27d5c173f0ca4ea2a81b1b8f3e90d7fec4f3, + 0x25aa5a53ec5e71f3f47fb1cf8ea8c757fab69a61274fb36eada71deaf1614db2, + 0x01c244a2ed1922753b39ec6b775f07cad91b14cd9b6578b64492c2cc4b0c8bb9, + 0x01664e5c861216c4cb10cf3a3bd51afa0f3e59eae24fcd7e7daaa853d46c382e, + 0x2af001a296c111e41e327ad212ed30234da2beada0449ea1d2e0f0a00e424074, + 0x16022bdd67d2ade15f661a287dfe23915433b270f28c24e6066e45039aed813b, + 0x132d7ca5f935f3e8864268ad723e8780df36916384a54b812c74a749a26826f6, + 0x20bdab9829e48c89a99d0e8b0d69b79a4a273808807ade4ec5db95fd184c4f37, + 0x28db494350ae9c81ab52d719ea05f98dc2afe87bc1afe556161e61772258a951, + 0x19fc92f1d2c1dc043af3427b77ea74e80ab9f6041e0e51d1b24d9cb9f3fb3ed0, + 0x16bea7126b8f072ab6c86afca80b606cb90c7e5fd02bbdba1dd733c3cb884705, + 0x1fc57b168a5badca15a417ebb4bf5beb28fd09e0dff889550a126f5833f1fd5d, + 0x1ad20d1a3ee559b6334be4ba911dec957d56699cf37dd7b97d23dcbc65bd9afd, + 0x2173430a6842061f027393a443b6e25e59a3e5bcd20895ade0fcd7bebcd88885, + 0x11673173043e15137361db05a0b067147a23d7f3003680f3e1534b183fe27cd8, + 0x037c80af5ed51c1c22181f3e7738806984493eb998add05556eff65129259ff2, + 0x1d70b961246d2262cacd8c0954040548b63fbd25f3038285c36f6b44e9b9ff5f, + 0x2184448a7bb80d176dbe3de73f383a909635e4610c25864b2c63252186b6c44b, + 0x03bdca6b22fb80cf9e7b317190ebbb9f6c7d3c96c1bf7d5013f36521a5dba7d0, + 0x2b65873313d5bffa44d510dcb3f55048436f4eea91a100ec0d1af952eb64b247, + 0x2a7fd02ef10db1c9dc03c9cbe82e857cf06f37ea10e7e3f539b53778ca274616, + 0x1cb880cea192153865713565ee4255ce72da23b3d2142d265fbc2196fb8b569f, + 0x16628b6f83fc36bbc1d60029a69c843d27484f594a7e3ba8d47cdfa548a91a56, + 0x26fa9b84e855f1069e76e037104f8886b760d4919bed798e2e4b8dbe0080f16e, + 0x0ee86c87bdf0ecd526e36a6c4ac9fc9bf05b9161856d658c1b9ecd80da9e9687, + 0x08a5179993a8056405527cb82b6f619984c63cd115ffed3a6734ffa85267191f, + 0x047aa61e4bf0721ac4e0a2f291e62124bcc2ad3949dcf96e875f45df7eeb5437, + 0x263a511f033e1fbdc6d282b52712a09bf5d1fec21ea8bbfe2eb1ef5bc4f21148, + 0x226520bf730486e2d8c859b449bbda7631b86432a2c100dd7386c9b1f993f34e, + 0x2baef27107a52854788f0c5a940f5a4df0d18d38b893cbb1157b386a7d356357, + 0x18022cca17f26818d54e60e300b5c949d9c92122f7de5651a60cf70c8da5fc52, + 0x07baad301d58460d1e6ed10f52abf1bd785caef8565777fed94dd67de6717d25, + 0x1e476106c4bce3903a5aac6e110df2cc1a7f71b4135be3662f4b01047e248a6a, + 0x1e019dea5028d23b2df063c210466a88c3fc1ebdedccb8045c7e9d1bb6e77a98, + 0x0dd55f006559bb6747b254d29a73f5ea7174c6b6067e730a5f9a9908186308e2, + 0x0993085a8024a598e0c9059d3b919fb2ebc81be408cb96fe38a48a952c029189, + 0x143f3cbf98e40971b2115493ee06e26c7893787bfcfb13b39f165869ec7fb9b7, + 0x0525ff28fa24291b8d033b021395754fa030d497312cc17caafd008524eda07d, + 0x2d9fdc18cd2586b9f449142017909392025095182d5f40d5911f708eb05cd852, + 0x230997202fcd6f051e1bf1e59a9d01188e3621d613fe0e78e6dfb400efb43f45, + 0x044b56469ffbbc9d0c0f075e20f390d30d11981a767e507b80aef7ed69e7171f, + 0x1507d88bbe10b21c23a94555d1e4d379aa71672e002450393eaf7a23736150b7, + 0x104d6752a761b50026377ec798404f71151b3cf6a9ea1be93c6840594824e9b6, + 0x25276305cdeae4c16558de60da72941446a9fd2226aa604d44bbff12b1e0ec23, + 0x10f3cefb054d630bd7dc4c7cabd97940dca683dad8cc35a6d0c30cbd9812051c, + 0x0e406cbfa384c6b24ed043ff3cb1d6891baff0585afc4fcecc7cccec809df03d, + 0x18f36033fcf64f1bda0c12616b00b611863efdb8966db7ed3534cfda40aeaf0d, + 0x165d022a34cf10ad3255723635a51a35ba2a6db07572dba106dc56ca6c937c52, + 0x223c8c9aed305b3d18265b56ecb7a4cfc4b10e58baa1365827a539c47819424f, + 0x2103fee94674840b1aa185a1f8221ee4511a2b5268f1ac96d7b28c8984fde6d6, + 0x1c1396433bb9eac9a02abf2390973c1723ec5cd55297a387a92806f78ef9d384, + 0x1befee24005a88d2c9ae9226169e898106996fd32fecb72b0cb4decf109f1b92, + 0x1adc49f1f1b405df727a64e98675ea0ac2fc742c806f0d5950c8ac41350f5184, + 0x10a0e0cab76db0b6a00799dab1f2e4a74ef739173cfaab2d03eae240c9c847cb, + 0x1a9aff62d6c66fdfed0eb91b6c4f974c1e047c0b27ef49b10d2933af1af3f997, + 0x261967f6840995daf7411034526eb5ac725f95e21fc36c8ed191873985f95cb4, + 0x1338030f85fcd2fae09eb016f4254086e1af2f88fe7dbe29d183c89ed5286098, + 0x02c53745d1f0e66499ff109e777727e750c1134914cbb4d52bdf1649c7911ada, + 0x2740100354406de4d94eb857a1c5df1c0e88d8b0b82d10c1276ea7d9f62a05d0, + 0x0b8a9153d3d643f0a9f7dc08f24d70863e4f150d1c32ac8905a6226887c9bcef, + 0x25dd73d81ea8918c9c1ff69b0b86a0ed3801ed1aa4059d94eb72cf548b2eea1d, + 0x253d813cf05f2ff1c7d6622bdb9faaff277b4d0312a5888a9dcd12891ad1526f, + 0x2523322d2d2a78cc54c944b57752bdd8d2c8e62e3af51e020eb2c15ed830f5f6, + 0x2ac9c2d60d456848e8dfd47499cdbd4f2377f3b4ac98e10e2ae3e4f83b0071b4, + 0x2a4e35f1df833442f9ccb8c75523b1ac8a9716174f47fb0830d94f9bc4386bcf, + 0x270e7f6b15f2c0e0926147cbf79a7330b676d174acb65b730522dccb096f9fdb, + 0x1933ef75d4b862f2274634e1f5a4e50ce899f15214f0b8feaebb2ca2ef52ced2, + 0x165130ddf77a82db84278a31841109da4108d364bbdc6acbb1b0fa7aa5175dc5, + 0x2fc1fe031dcd4538d5d8b1340d0d37df5505e965b7e7dc4c19895b9f6fceda6c, + 0x0e1ead2be6f64559d903eaeb6e02a7c85d546422e7730e360a1e4bcc0f62f16f, + 0x0a983360bf32392d5df30a2e4b22535a4f161fda3d05b1a5067d278e21c8e54c, + 0x2e27e61828693607c17eff9bb1e5ed0baeef782e879c5230b86d6a79d729f4ce, + 0x0d1cea26a08207e522ace505e837caa2ce7b105cbd04e7c838c1acd006ffa53f, + 0x0b958dabc9a8066de9e4cef89abc82e3396a03568376fb44ccde4c38cb2a1944, + 0x16f5b42d88f8d4f787ffff796bcf8175b1cdce307261dec86cf2034a9b88bbe8, + 0x12b68aec2db262e0a61f0fd4b976b00ddbcf7546ef27f47d7435a288c2b6c63a, + 0x1d2238d8d9768dc639d06ca5870e3503f3f81ef863300944c87b77628ab6d84d, + 0x0d164e32fca3c3c8da3ae332a831cc9a95e75d4833ae232ae382bdc6b790d91a, + 0x02fcdde6d6eabd7f2fa19234fb157661b762a5c47b57739a62000d7f6ca8ef3b, + 0x0f133b8b1e54f43484574647812ca377c802a1590df5e5b8f9c8c21908efbe37, + 0x03057ea8932e9bf7d1a4bad8241e14f1e60afd13ba4e90afb472d9dd29c42bde, + 0x23dbcb6ecb4807740debdc825f7764571bc93f33645825d0e45c88b0088a9f18, + 0x01b90754a2058217cdb64ab45e24c2e29423bc3a76f8289579927ecdf63edac9, + 0x28db800ae16d7033c8e107e198aeaabbf9d0271c74d957c6bb9514a0f038fa91, + 0x02f97a36ef93a7904cbdbdc36e5ef374e58eaf37b5b9439473cbe477c3fab178, + 0x1bad1d9637a6ad6db5cbd19ba7b955a45b9e8089d1697445a130743e03ed3caf, + 0x2b96f520dda8251a878b28bf96d281855b9c43220b0a3279179753f740edae80, + 0x041f97f76c60b28e0fdf7974bf922b7a0999e0e0e40c654378ae12843212909d, + 0x13b5cf57475057a2f5fb6d08093123973aef9726cbd9835b95616c2aed5588e0, + 0x2ca43aed5aea162e8c9be92a15e7ad0af84d44f3d2e398b5f7491fa2df12deee, + 0x089f6b1ec8b51cd1e6ea69b9649520a6f0f2f96ea11df270ab0c5d9adb5c3df0, + 0x04f510cfc7e528370babb8ed7c50c34c6041772627793a0f3711d1300b4d1275, + 0x260e12c47d0ab52563affcdd5c2862f4bad5b7af4ee037ea5f8164d0f13d1059, + 0x1a656424760e75468aedd8515b3111e16cc0d60f8dce451f7bb35b12dec772b7, + 0x00cc850e959c567bed20058b6769fc27a6c70cf72f222b80879e9bdfbc6711a9, + 0x088947910eb3b43ebd8688695c64ac020e19d0bbe875a7f3a0b699bc60f18cac, + 0x2c25c236bb48035f45fde5b178105655ace9f3f9afb09071e790dc4babdc86be, + 0x12dfe1bc28654f5c9ba65865769c9e47f2bde0d79ddbdda21704904b2905da68, + 0x05645b68f99a564ff08f745e1413bd83ab5b0442f0b8efaa2a986a6cfb2fd8fb, + 0x17cf3ec9831b4d6ead640d912e41b4c72e9c259126bf6310fa4b110e43864c75, + 0x12b15f28fefe5d6fa519ab9cc67a78c57dd721ab44af286e72fbbd5689a66f61, + 0x2da44f7210520779cbdacfaab2e1ef01edda8eedb6fe6d037ffaf8e59842a00b, + 0x137ff7323fe757f32afa165f11588b403bd393d5c9a961cd2f7da2e5d9a894cc, + 0x1318105fa9fe1549f04ef48679c73d46b91ee0bf27b4451195de945c8cf78aff, + 0x1408a4259df52a491775936b2c2d476a121708c312e635ef8d1f843c3ba3438d, + 0x10cf20dd5734c18880dec5be44ae2ddcc4f447f20cac98c95193eb7571585d07, + 0x2787fe4623bd3264e0c8b5a471974ac1feb1e37fbc3a9c8a4ea74d6010b7d08e, + 0x1b90e21074907545c1dec3c59dbf2a6b1f703258bc03707e33db582d45ab172e, + 0x0b8e912a5ec5a0bfb779a0801b90863edfd9429a7b3632bb5022fdbc40636cfb, + 0x0d9982378cd9a8370bb7a555c34df3183ee6b0d8abf31f1f547a3993044188db, + 0x1e497bcfd5c95cdfd630b0afbf6d376f29a468d1cd3ecde56f6940221d248af4, + 0x2d602401cabbc69dff3dd552e271eec29a5a4acbc935686ccff9a15076585b7a, + 0x170a5f4518f58544330671ad2a361f2c803c0d355f3e10a5784951f2abefa707, + 0x21b3a23c3a553d401c08502eca497be938776af671edfe44c784956acf98865e, + 0x224dd497bf3a4247b9c48c9ac3cee5307490e824a14204ed88c2b1166e8e479a, + 0x2654965a3bf3c92422fb54e676ac8401baaf0f68d42664e300624a375302e0ef, + 0x1d525f4105f51b69c006828670e7785b726e95be160ee1a3e299677820839f32, + 0x28f88d089f421ca2bfe697270fc0f34f50ec41a1ede53612c52db74479b4b323, + 0x082e621153ee34324e9fb7ff3d123fc9560ef9af0fa0f948db24d1c8e6f07a9c, + 0x07f8578337523867b1d9403e9ca61ad99c0d7d5bcde4f19d8752e12a4d5805f7, + 0x2e52f30dd05931adb7d7e85255849b062ba1cf2eb8d59208b5bda8e35d69819a, + 0x14cb3e56b2b8c6605ba04261a8b117791caf26f7c233bb183f83f72ef4c8f345, + 0x2fd6b4e6c892609fda21414dd8712de845eab305be627df4d36c8d325c9bd7ac, + 0x0325898c8434f7ca32ebd73f53df3b1adb0c9940a69e9191fd996a4a96157bf8, + 0x08f50a7b584dc022b85d6a16a0d3dff6b8a7ec4dcf5ec066f99fc4644d6d5d48, + 0x29c5bbb8eb214fb285ca30a43cfd7141d9ceb8a19ff3c970f2bbf4c9bae9e11f, + 0x1264cbd9ec001175211e2856a78901e4088f1eb7eaf5934999e1997307e7432c, + 0x28a0e7819aa0251e9cf2bdabf64fadbd51dc9416533ae33f7cb97fd177688504, + 0x1a9be651c412fee6c800848477cbb67e4c52fc23e51ade9c48f6af307ec621d6, + 0x1bf70a24fe7fc8946fdde6f556b3ed4b03c33005cbe7f34ac11296e5b0c75f6d, + 0x2f56c8c0387e5e44cf4921abd33b1590cad0719e932a36195c5138e0c6ac83c2, + 0x1109db87b7684f4927b2afeeff00608af5f211920eb8d638e3a7c943b293fede, + 0x1851c29804025b6f9c69c80891035590a51d13032cd576d332ca89222bc75787, + 0x0909e4cdc0bc47f2df4898106b5c40f25c7137e1d5ac9a986c9f66fd5dfadfba, + 0x2ae3e90e2650e286d5913d4dd1e71d4f233659701b319aa228e16af9f010e07e, + 0x06a6c015f95173441f7a40d4f1bde04eb60fbc4dc72fdab7dd81ec557235d530, + 0x2f6ab5d35ccfe9ea366da257c8596fa6ff30d6c46816a3bd3d484c97f8d2446c, + 0x01f9c60308182eb6d4a83f9272bc220a8745d9c9127050899bf6426f7ab57cdd, + 0x2f514c412bfd9754e6798e4c3cb13d5e4c4b29609d3ea5617ded35bc01d799d8, + 0x14c4162b9c9eefb97941b1f133bb18225d28294d092cb8917afcb3e08abcd9cc, + 0x19921fd625c66ec67ecd8af3d6ff0e0a3cb650e1e72b3fc98884b00354085b32, + 0x1c852aefc9296753e1268739ac15d2c6d21de3436c816f75f93b8debf37eb6ca, + 0x04bf4a69b1aa4f304afaa1dd1bf60de1f559e8167edddac1eb88ad9d02745fb8, + 0x240a791f3b8bb62d5d9aae80f341cb569fe3fe72e7183d8e5830165e4d123753, + 0x151b295b4242e0c09fef7bc5ef40f1e3c8551654186d62cc663ee4f28ff5e764, + 0x086eb3d30bc4d80664a074a09739dc8c497c93cf7e657954b0cbf7676165f23d, + 0x17aa8992d7b901eade7eacd95a8e89382a292a7121ab0ebbebe0dd62622c21c4, + 0x1a5b3345a4c0d875663657607b5c7ff832f489b23a3c43962008570f96eb8de8, + 0x2f03b46d9eeedcd7f8f4cf2cf710e48ce3f31d1364f03345b2a7964b01e6347c, + 0x0fef583e7e8e102feba879f7bd60241870a0291723aa354a35259e0a40050d45, + 0x2e07b5d70ca583cf4d9baffacd02d7d80fa5e523abbd895086a36288b969fa6a, + 0x24599dbfa1dd1f4714d585248cf23ca1394b858af8e904c0517baedbf2f176df, + 0x00a826afd370bcb65b66189e8d986777e61377388d8727e407b500fb5291f8ee, + 0x28745950870bc1848adbc5f4bc03415f0a2bf23e905e7d33cad03de907081e3b, + 0x219e6dcda590fc88d405673d2cb4710f8b5747b46dd9914d1be4081714cace58, + 0x296692077b42e972399f17ba71ffededd95185ff7253d9d1f41747c6f27dbe6a, + 0x2ccc5f0e2049d426841862f32f8062829fb5d826a6a483dd5078de859f9cbceb, + 0x04f915a4fabc8ab208a615dd89fa207d367700bbb9bc061d07fa90a70feffda2, + 0x2e04b7c1aa853f9ee5e4fbb5cd7b6e60ccea4ed5928a34f4e59ea9eba8794708, + 0x08700df51138b36c0ef2bed12bd78340ec69b04a2e1b865108036391b4b6db3a, + 0x2503336398f165bdea8d4929db1dd0b3710416fd63d7aadcec41bb7062c24782, + 0x05633785a50a9c77573ab10d893341a0cc2df072ed8eab9a2996a47a527bdaed, + 0x0ba4084e44c50e1412a4c982dc0d8a0d4622513b7c96e9fccb2c3be2d3901e1c, + 0x2d6f32cb761406dfa9e03d7ff8a43bae106dc4519c61c3996cc9cccd8f307c86, + 0x2f959c830737e631395846373b1f7d003c8e6bae3aea2edb73491244f8373687, + 0x14863af59792adb1bb40901664349217498d999250cc0a858db27aed54fbaa38, + 0x27623d101b1f922899f9c5783e1fdbb1e7552826e4d6b58d6df8d986937cdc82, + 0x247328a4d9ce81603e37ea72cc5d1c895c21f09305301bf1411c0798602a6268, + 0x1921909aaad03cc78a6cfbed6c1056e3d93a25a5496cafaca12af4ce324c6081, + 0x0a85c0358cf388b47d14d42feafbdd4392df154f649b7213e29cf101aed00d80, + 0x01bac04734a5920d65d67aaee04165de621beb56f902ca483860f7077537512e, + 0x1dd1720966b3231bb00b08d6b8bac6c76dee5454f784134b93d8c70ab3eed999, + 0x22897debc6eb2a7f36bee1e7f42ed4b0d37ad696535d82d39ccfbbe92e86c08e, + 0x2ad01bb42b95d113b3b91ad88c69a33c1e94dc85512bc5168ee73065b387e175, + 0x2e82bd0a053ce03af9aa947df5f131791529a57f8360a2cd697eaa177c6000b0, + 0x2d2daeaeaa93a5f9d8b6529f00c4c6d691c3bc4efbfc8e7c2f08ae3e44e1f4bb, + 0x0ab08914b2de57397983bace0b327f98c1a9c1e58c76ef2e716cc305727a0f72, + 0x2758796cd1c178ed0c433c4f1b6b19d42ffa1bc884c3cd1ccca107cb2bc91998, + 0x063df5b0349016e7bda4741ec898c74e4a30fc4f1b59fb713a824992311e30f4, + 0x23713016555546753d41abd69e6fb91e4344b7c05838048ed0641cedc5fc6728, + 0x26bdfc0a894998e693b7e2059d6a528aa86ab57eb031b96b53fe8b5adb74c075, + 0x08897118f75cc8e9115dac581b9553cb407a1de135b632541bb734f53985286a, + 0x02ef8eb2c7b26f7a57691ecb1e15a40afa9b3a5557abe81146ea6f6d4960c346, + 0x254e8e5fc11b992348fd7a2c9f4a5a0b586bcaaf12603658b25910f63cf08b01, + 0x02f41c21b73dd4e7b510dca16e7b4b4277301da5fbbd59db03d3a32b89c57b7c, + 0x253f09ce9ecfd2aeeae98ba1b29806bc2871e5fc67bff13e303db99618e1d0a0, + 0x04395eb655582d03f25775e66ae67be0aaf7c63ceffbbea9226b04b0e795bfc9, + 0x13711235c3d21dd749e3e41bd048a32bfa2e796e26b72e05c999e6e6126e402c, + 0x083c75117510a37d43b5513963fbd0f9f33590ddcc297e3cdd9ea42add7a175b, + 0x26cc9b5718d84e606582d35d8fdbda944c6525ddcd7488cff21d4d0d823dcea9, + 0x0e8978f047929b1a94601499634a8da020b9a46d0b1187d54504ed8a344d56e4, + 0x2b11423af39a5d15be397439b5ca50aa9a6d41234acabed2006247688f6fa805, + 0x21a56381040c702dda5a31a5aa275ce692685625e5aa77bbc430382573b402b6, + 0x19a869e15b3f9b965016feca2cb82a2f14c800945ba49db74aad8e9346af07f6, + 0x2b01c5a2baa16f9569d4670098466f05bf3ae097aa930771b76f24afa6be50d5, + 0x0586148573b6b56617f94602fd6c86ad4a71b3fc67a35448d64eaea532582124, + 0x040352e19809dd93bc7a2c549bc19cb007872e0599a3127a3e7704411894f98a, + 0x2d6486b8e7b9549ea86cf044e8950ffa36974e842e1fef876561e1346c5a893a, + 0x2ea9d2e1b7d07c9a3895565840e25843c9debe589044f305c1b5872c74e5a49f, + 0x12e0dc4105acd8692b7cea0bd76da34aaeb8f6d00ecf84b4f062270413a8087a, + 0x0da9c10656e6f42c3ce7c980a70c9d793db4df8307599a33a491f24b6368290f, + 0x02f3551c6a648387da629c96633d5cc99360d9b89aec23c18ac76af21b11a850, + 0x202de33a6fce9dfe8aeea34af1ed5c74093386c8a553d3a3da46e134731dde14, + 0x07372d41054dbc009e3e91f902d57a213f043575f3427e35768a5a52482b1b7c, + 0x02f7e35a4bbe9699949a819262943c97e8e938cd999cd911a9edbc716e2454fa, + 0x2a27b84a7422e29b8cc73bf54bf535b011606c819b4baa6824b6123036d73ff1, + 0x19527e9093b313d5d2638c863499839ff5d8e5f98e74b312fa0c63aff7161a3e, + 0x08571a6b8b730363299666231e3c49ed231d1e355d93894c8562ba033147f025, + 0x2c0f32778edfe932d912961c81d88e98d4fb64caea2cc2d4e3f213a5d2a1b9ed, + 0x2710a63e84f8bf3b15da09e69bc24c567f84a4577610b19cc58191b2b1453ea0, + 0x2d4b8440f168745ed84c3e393f75bdc0b0fb3f148e4ee77b525ebc258a953dd7, + 0x234901ff3ec65e0a4f629bf6e96eaf379aea7c808ca9ee79b6b796895917684f, + 0x28a529a627cfc689ba1bb3372072518c7720b450975339e87865c36be526e5e6, + 0x1a1af260473d83489a6a466ddc1855fdc6e83d73b5c5c0fed554af11c6cef5eb, + 0x2fd594dc14997e8e0123f3af16c9289d088264cc16a8119e8f02ab7270952924, + 0x0d3564e44716de8c02d8f8278b0d2f819658234bc4db59147fa3a5dc23eec833, + 0x293e9ac448bada42377dd8b02d5ae5695e886e0f8e43f01b38266aada3cfaa0d, + 0x2186e961df0728bcd7b667d35e95f354cfb1ee1288aefb7e0b2381296daecdb8, + 0x1b4972ee03b2787a27219cdeab7acdb5dce44bf8368a0c43e1e3b8c8a7f49e74, + 0x01105ad26651d5ac52e817c32d86a3b10f05738fce996b2fa905ce1c3279522a, + 0x072b770a70dab242ac30d03f5d2477595cf521ba7c91478d72e45358569ef30c, + 0x1e399a42196a8061079e9d61ec97ff8c837195bb936206997f5a93021b70d275, + 0x24f50ccc3a68ab3e2cba453ec40a8796a3c59735dd3303bcfadb6218aefb7d6a, + 0x14fe92dc9227b42df23f8a5a0a7a2f50bc119f01dfe708b9118f75616714bd3c, + 0x24713d85951736c77b66941c007d170282271958c98fd42d6b12696a7065916f, + 0x05cf2ad05c75de38238f63258c8dfce0d1b698dede7feea9a97b263cce815ceb, + 0x2d62695c7008a11d0c874b40395a695fffaaea6e6bfce85ae1580dc48218aa26, + 0x19e47227e74d5563126770fa5ba61405ea6f348565c3aadad0830b3ef5d775a0, + 0x20e43ff580378bafe2074a6b2fd50c74594537f98565f2d65ed8c15e5ca1084a, + 0x264e4841309ac1aae92ddd9cb4d973e237406d50d2849c7091bf1c1bf5c1273e, + 0x1238beacedd4f53b35b578af1c30c077f4289680658fb26ae1b4c0b2f710e604, + 0x0d90474c262aac1913f37459d4f2055dade903de9bc02fa5fc7c137cce05fe35, + 0x0f5aaf4827d5f40e00235ebd1cd1b9f6ebf3388383e692573b95cae4f653ad82, + 0x2cdda4350f35334773cd823df37097ee967c28d62d0c45c34d0cee4008834893, + 0x1c0c8c2ebb6860e64dc46755a7e072795bc2c78832a618bb6a2d5d0911b7d768, + 0x269fa26069db1cf0cb705bc3584c0150b85642d4f243d5e68d7240b8e8c03276, + 0x09b443b0a7676575b9a6d3f003609fa7c7b6226341ac8389258881d994fa91c8, + 0x191b4697a8e295ab80f81b25743fe13f3fb6998e9131e99a86f22bd33e7bddbc, + 0x0b488b6a875f238bc324f04288ad865c8577e8f906a971ad4bb9d91775645730, + 0x275928b25e503c9c95c01b18a5d30081bb0cd31c36cd172bde1db83287f5f5e6, + 0x1fde053dd87291d7e14f0f2e7b7461b49f60e4afc39cfdcde65d70f65c3b026f, + 0x29b2c386816e9d3f76100e8fb9543329ff88ac29199a181358dc231aa1dd3e0b, + 0x04987de3e3121811ec3c10421005e133fe1ce9c2aa7d7c54a26f425cd19767c5, + 0x19a23ba97426bfa81b757e35aa3559050628665eb496ed8732d409942fb6e16b, + 0x12333e97d1f0e3280b5e2f9d96561b2c04d001d2b393791a861fdc26c1b7f767, + 0x23e48a5b646d353895d06928a181d75ad25c95a7672f3a1f4917ca03baff3227, + 0x1b6bff423317d2c2721965972823ca2e93b8f2bb0a52245cedcd94587d596382, + 0x16af0f387b9ba94c0ba6d176df30701ff378b3524680aafda4f7c4df4b088b07, + 0x1bfad9c1a92234ed97c51ac7dc2d80f2e908c098b28bbe712cb75b92797a2103, + 0x29bb5064073e9a6aaec7bfd94d48fe2207d90ea8962530f388442ca4d95e6256, + 0x1cbe456ec3f8d8849e10fea36509acc3647edc3e765f4de7489264f5e34033e5, + 0x0087a35062dbd735636f76cef6fab3b412749781f03b39b181495a62aae42424, + 0x1f1219145ff0bf15d9645e347879a7347f9a6a5f3dea9a9bf9495174d228bcc3, + 0x07f93fb41605d3cae1b42b92d527b2ce7cef14ad2b907702afa13d76ce02f88c, + 0x0ae3de8a6edd589ab62767e92f3c19efbf32115679d2629a5ebd26c1c7d34299, + 0x15b6688e877724b41ce08fb17695347b5eb8844423c71a98ebcc188c23888dcb, + 0x131cdc252f00cfe48cd6cb1b15344b6fec8b176c1ca5584d76d6f9f6ad26bb13, + 0x1bd570cf878b3dc1616ca32bf55e0b3fd898444d0e70d64909ec789ff11e8eed, + 0x1e5a54e71ef7b9eabf717c01dd99b7262c3b43d1d6960094b8e508d1e11f03cb, + 0x21c88de360b36a24fb641014feceacee94856233dfbccbdd1e9f0f35c9e7fccd, + 0x2ef387dc1012ae94898b8afc9aa54a3be1f91820b61ab86f45ecb3ae21e23ac3, + 0x283914da97f036349936af1157c536d9c2873fc3c1543afdbfc1c0c55cc6d5f4, + 0x276ad4f7ba33971e4db2292c7ff704d15a14246a6e7d76ea79f1189066dd42c0, + 0x24ca7fd6a2014d9821a624bf07950e8f64f5e6892d48e4a71cd4f63e9e2c63d8, + 0x0fe8f370d24968de4dec0fae5919d8f4f666673ecae78bd7e22dc2276364afd5, + 0x2f0bbec7f6a255512df348122df4b91778775ace589d4657dcc1223aafbf2586, + 0x180732ee6d3ae2aa4866158f54f4d8b980013cc671d68c69a72d5955678703d1, + 0x05a0b0ba16b7b0631dbe2c92f9121284974a7033a69be30407bec6b153590703, + 0x2908a5a3204a9a144f6565e561bbfe9a4b664edaeba4106e1a57ac77290193db, + 0x18c860a5d2537a84944a1075e804c32ec66cb5979908a8ca8cd7f2d8a7029c0f, + 0x1ef80617b025bd54de5361dc2fb16cfb90c364e37f7a1f07ddb9ab292afc0e91, + 0x2ab495215ccdfda498510f6d5dbfdac1429464e7788a229feae561be3d62c2c5, + 0x251dc073bf23010a06bea25560e1be3ccb2c38e67d64eac680aea6c19952a7ec, + 0x02201c3662a59685a511e2555643567df50772e8c150bcec0943a8af3f106847, + 0x2bb9277b8021c5d354300da09101d24c72a842f97627a82065e5e67a22f465f9, + 0x14f5ee46878e605585b3ded3fa8b9b7fd62a2017b6d2f30ed61339cca435e348, + 0x114578668b59522fc7d794abcd2497baabd855f3fba503d5f5e0486047bf3fc4, + 0x20bc06a35fe07cd507d0dd0a9da6987f228017055096ee68cd33eab3773a1146, + 0x184801f655e82f8d32b94fb0612baa4ec983d1cd94cada67237670051d5fac5f, + 0x1404d5fc7a2e8940778158fb2d303364892147a64bfee54b25d3906ab5b3490f, + 0x251df4335e5164fcbbae73beb8cb57b809d71cb59d6e303db0560b0c1ee79e0f, + 0x09a45be49f35c4f987b58d749c78c69082486d3f8777eba4103eac7190faad57, + 0x2ede228b9b96b21dd5e1e6ea260a87f902c0051f1f203c788fb907df00e51177, + 0x100a3118e3248ac400e6aab0e4e6b10f07e96de582c2c923a99cd14e45d6f209, + 0x15872dba1f1047ac1faeac076b57513ad92ff71b6a6a2b32f27adce084894e10, + 0x1f68a35d81c05733a573076ccd7946a4039da22e42959520737e4a6843283fa9, + 0x2a165a1a2b018ab2fa4e581d7cb567d9b1515db27ea710af3683a8919e99a282, + 0x064ff94b98a0588aa924e943ca627fcbd2ef854c66f917ae526f719fb40c6759, + 0x1c8349f898cbf2d1fe6db936c53bd3564b673b72d673aaa39f9691e08283d5ef, + 0x2e4628a8655d2fc84a32f10e0a95e92d0576739c07050bcb0158f156db6e7c5a, + 0x0068316de71fed80213380a8757b3a9d517e7ea1e4800a22c510755a4a1ec152, + 0x229e32cdf952fd49ddac8bacca9ec0a85b9f5f1e8b4ebbd995ec5b8289a54289, + 0x26c9af69ab4a7e08335cdfdf33ce102a14cfafb05ad000afa7383f01b9b5b892, + 0x14bc5140566915518f20d51498ca60f6e5e48678f97c1bb58e17af4db8f232d4, + 0x22fe06bbaccc5b18b4a8bf2cc8c47e351291bacee5c5226fbd0cdb308734339c, + 0x1dca1403773581144b083aa9b9768db5a81902626de0d81d80f53d75d247af04, + 0x04152e8ca329e892a4503613f3472ee94b7e3025a592d4625f420c45c56a1f52, + 0x13ce7edc9f1c7d2ed533026150f2bb6d261f379f1fbb48a8d556cc5ad7914e36, + 0x24f4fa36a48be01d0bbe57854d48399d81ec03c394fb2eec544a631f4e1cb1de, + 0x26e0659af8c838aacc352710f1433d9df9ccefc47bd5c487a0b3c29a01e559ec, + 0x222f80f3327ff730c8ca585c067b5ce946724707601b7a4a72476c4f73e7818d, + 0x19cd3a66216e859e433f64e4f9f3e2ad9c58d993ee168ceae5ebed3049ab2f87, + 0x0d01aa823ee846c2cb695543c8499803101fc0ef222e3c2b44d8680e8a76188e, + 0x2e17901918cb6f4fad9ac0d387757aa77c7207924e177d0826ebcc45c76488b3, + 0x2e30cc49639069e2101cb479c7281e8715ce5f34d17c016430a9fa75bf484ad4, + 0x18694d18fe6758b36c38ac70d1344c6d2b70249db92a74e1404683b2f00dee5c, + 0x2597efc11329ee3e0c8bd40b4a78681738b4c52af4e55fb5be529996b56bffbc, + 0x003ead8cba0d24715aea9ff5443d25ee640893186e6ff6c045dfc91edbbd1c94, + 0x1e17e4583d68f0e1e7234d41915f2fa3c7b7c04cc2afaabd7f3bbe071cf1ca2c, + 0x2d05098ef2828d71e8758837f5c973ec97b7547bdfa1433a5527168ee9f9d5c0, + 0x09220ca57e2ddf5a1b2f2971627d1a74b7c1b837ade64a37e8e1f0d436051a7e, + 0x22ee5c6d36a980b7a428f8afc999eb09868adc52b4fccfdb68b3f5fba518e03f, + 0x1b70154b6e76cf9bcf4411203db1c19c77bc0ca8bef907ae8a4b4aac270842c1, + 0x1a2ad9a834a4d41bc0d5bac3b7e9453100f58c8605fd112ef6b7a25baa7dfb88, + 0x075aa06f43a273433cf8ee196e8577e5fa28844595b1f2b36f6473ffda38380d, + 0x070f884d5d0093ff75fb09ce934c8733008f994efa4f556520f11ee8bcedf82a, + 0x07d5a9301209de0fa56d9dee45f8480b12d33a73be02f078f7b9df6f9225ddf9, + 0x0100dd4a2833b127fd800d28af04254a018853218ce565a8f615995a0f2466ea, + 0x164c79e2906202e73bcfb8105c5c10829397bcb0089ce03bafc5f0e627e0d836, + 0x29dec9bfa2a12f2fa1bc9158dc1d3d1ebad1d849fad58d34163d741923f8fdac, + 0x27d590c95d3dddcdd43e3c40f7579dde645f33c7b0ce03d55e07978096257f88, + 0x0c32e71be02fa8302d8abcb8ab2c6a3dc4e962e75955401c1e6a66157dfb965c, + 0x0cecd591ea4f3cfe0c7d3edf52f4f93d60a3126433bf9b9e47710d298c31e9d3, + 0x070627a0421fde844216f5f24789b3f54d44f1a06184aa81f75aa227335f264e, + 0x116f5232abcabac8a8b9f1a3ac86bfa97fe285811ec2cfd733f1206f449d1de6, + 0x2a8ecaecf1355850d03fa2f1a7904cf3a2ba7d3bae30aad7a35cfb4a6d7dbec1, + 0x252ee8a2dfbaab265c060600b3f6e19f24e491ddd37195211f95918d3d39b911, + 0x23ed5e73a4223df85afe948fdef2b6e0d3c120aa31e2f1b4c89054d5218258e8, + 0x0ddef510d2c7ba32e4331ddba93aa688bb9fb86173625037b86ba4c62a0600fe, + 0x2339cd5cb769acf2dafb5073bd988be15a65bf8ad06c38a82d38d317f0febe8d, + 0x26fb4a101c97c06acc999150483d44aa762b585c422bf8dcb37afbfdf076ab49, + 0x077d5874dba21d260cb02f280c5fdf78fb8ed9e0acada998ab5cb833b09d1858, + 0x22ddb2bebc8cd1c946f8522d7326702328511313b40b4a9e812b69aeb6113220, + 0x2e7c43c6222e6323f682c05c571f6aa62a3da64be2c3f381698e2c0ddadc93b5, + 0x19ee0e60fc2da7a295371c667ce850772acdbbfa0a9eab7a7c94a50c9c682de5, + 0x04d46d32c131ca79258ef2c525659b8138c0e199ce5968e57a82e780f1fa79b9, + 0x2ddd25bd37dea23386a030f4bcc1d4382635a6dc7ea3cf3889a5e8faca46bd82, + 0x0be3e9d472b8118ce3d01a92fc168de78549347b44526893312fd5ec3d2726ad, + 0x27fa8f235db616a5909a2f31896dc8de9594798707b477f343b48ff528e49b8e, + 0x17226412ab2fab6223eeda0b848333816a4dd6495e29ca47ce8b96f8c87aea21, + 0x008a2aca609e6344086eed8a710a35469bdce68646a435a6918277a21d03d4a8, + 0x27a10619eec3b5211b7ce9c318df7edfaecf7bc84098dc1c58232ac25093e35a, + 0x06def2df638eab9899865393563ec8bc81897fe0f1adc5c0499755f25497fc46, + 0x0c86bd5b00467b98563b7ad1b362a058538a7faa110a438b9d0ec7be8c50c098, + 0x02237c3870ca51c0c9daf086524707a78be8845df471e4d4fb3f2e7f30d90214, + 0x2aef4c14a514a36ce1afa9f2c5f1ede8d00530e01e2a704d70494cfd3c2982cf, + 0x0f425f81861ada856f01fcf0d5ef108acea281735a913d24eea75b55833b328f, + 0x1e562f2a3a83be1321eeaf564fb19f57aec9c66e6cc8fda18999d5baa0b4630f, + 0x0627d8f4c1a8c8f8c5e1eb617598954aa814a756782e2cd85b79e8e1e748c705, + 0x15e5ad36f719cca83a41f67782388cca380c25992e5cd14c670fd3c317b0ea5b, + 0x0cc8d138d0854f9b62697b7791da960be500e3529cdefd4f0b18d16c5e757ce2, + 0x17ff555b52d28be1b3c46c80946df519e9de247d2cf8d8175086f975d24c1e8b, + 0x0fd5dd57c2cede876671978d2fd289aa0a02693252b74f7fdee8bd404e6c79e6, + 0x203144a77c72ea89fcaff39b141def7e93a1da1fb9e22b7d0c6733bd72f06f69, + 0x1979320524dfa45aa8ef35eebbcf6f621e1c855b5704d8bf755bed7daaf721d4, + 0x089b6683b1f849dbbab0f1092ca04880f8b894d7f8bbcb95cade4e736ea28998, + 0x2c2dd8e6610a0495784aa08bb9661fbe25c908396b5c3f2bd51109517fa28162, + 0x2b9627b579ec4019306886e1ff4003aeb3a33249be5cc6b56dc3607b17e42477, + 0x178f70a99501a6e05bf4ca79b2d6da47049f8c988936696519344ddd931174f5, + 0x224ffa0f9d0d57eb0c7d718e99cf3b6ba01b523548ea0ca23a3f156c04083abe, + 0x00f2ee1e2be1ece2cd8aef1dbfc826997d304d88cdee555ef67a799759c39ed4, + 0x25757740ab14ca93745a76000e24328eb1a3d21d3cbed1930dd1ba2cbf7de236, + 0x0fa6b963bc65bd930510b3ca6e1ae62c1b4675edf79ee79a7f280eae6496f16f, + 0x0ccb794ddf870bb92a9cba5f859fb3cc3f4eb1f1117d14c1caef37beced0e32d, + 0x123fc6d306f17fcd5a4309d4fe6e0cc1ca00fc23ea9447a7c6b68c7f6ba50005, + 0x22162170a1f845eb0aa1ee7baea486212a09814a9557bcb9fc72cf90f0a29961, + 0x13e385a5cd2fbda978dc7740e927ce8d422c9ee861c43036257242484e497e3a, + 0x13bebd80c2022724017d8e3eb84c269810cecf47f9f57e237bb4be69410a7803, + 0x13ed291502566a7033b4c4607245156a158a6fc84f4ba6f0246c1de057d8ff1c, + 0x2ffa06928536af91c7ac3b7714f204e26c541142742179217095a6e54f743247, + 0x2a6df655e926c4aa029749aaa7c9a40a10fd55a368624c148b5e528d4313183e, + 0x27d8531ec6121a3eca74db524323fc100db502a580b8a4cf8651f1bf6b9b0238, + 0x1ea104a44d82fbe1bc1ccfd4626cea0c06693422b3846b3a2b4aa12a3b0e747d, + 0x1d69a3852720a88758034d954dea602e5989114a4667251b0da5915412ac5ff4, + 0x1b8e232710f6c1ceeff9c1086d49cd8d2e647f6926da913cb5e10337d7f3d7e5, + 0x2d40d3f8e6f9e3aa6014c69630dbfdf3169f88067574ffc9210f7da599c4fb3d, + 0x24e1c2f60b1cd36101770cefc4334a8c02f00cc696df64f76df54a6fb6f0508b, + 0x2408f2eb6b1e958ccadbff81c9a44913ac0c9cb5cbcb4b4054017abb3db8c04d, + 0x0e3c6ecd281ba2e16aa37dacd2abc38eb07c1353dad96e87d14e5ea33ff8ecde, + 0x248c7cfb7ba2e71819bfc755eb9e9a306cd0f6e3212e254090f0006d9ec543e8, + 0x267fdcdeecf69d799e79f68632217df51226d8ce39574d72b4ae4f39d21721ed, + 0x2bd9173ef276b7d4911ebf78dd15342eb261603c2c9afcf4ad831de9fa34bab9, + 0x1cc0af33d07e50b2adda3346723006250fabad8fa3ddb365c1d8582f4dc65f14, + 0x221f2bc4b7dce9195f9ca9ce8fdeaefcb05440c20dd9754bc59c11447caecebc, + 0x18ebd5c63b0bf20f45d238fd0cab5dec8dbf1996bcd1b3489f3c2499ecf92b07, + 0x2f338bc5a586f2774af3beb92aa92ce8e58a5efa19ddc891be47a5e77e9f5a4b, + 0x0556b9c3784145eb4f2ff6e0c88f41989da5907f8c7118ae492939bfe4e9fb1e, + 0x1ec100367f65684538bc6956805ed37051238a3637e47022a3294cbde38b2284, + 0x1645a29dd4527ab91a4b798c7096e832073c8baac6e5db87e26c215bf448f84f, + 0x22a78abf7d5b362a743ed52ef2737bbbddd375e9b3bfb42409a95ad105ac9350, + 0x1a9921dead26c55aafb3ac9f3f35acb61a49d5f181e8036540830bb18686eb37, + 0x0eb8645b0d2b8f0c3927d4643574c0b1a588272465d319e15fcc6c3262191aa9, + 0x0e48af0cb275af55deb825a34ca48904a47c31b5592c4afa9077d60e5e7ea655, + 0x17dfbac5a26f06fff967cfef597a6da11b5bc894ee6b62e626a62e85a3ea4b66, + 0x0dffbd016ffd2b795226a83edbdb3c5a6f78917d7fbdbbc1b3631027c866aaa1, + 0x2f948d5f70856b5f23a4338d244f6ba7e7ebfc750e16ebd1e2c2d13825094310, + 0x194c9f7615cbe3eaa0f885c59e420bb89dca60fe174ea321d80435301511713c, + 0x16e81a0540143cbbe662c7ae726051ec663d621562fb3701240cbfbb4b17b3cf, + 0x11ef0c2d88131f715e47e9a4953f789fec78decdbeed34bc8eaa42927ea6eee2, + 0x0876e45a4f862901bfc620a55951802a1d1d5c3e1414308db7d548400f668535, + 0x2e78d35e1dd86776a4ddaee1192c055aa8676363bfcf3165317dcc98017e6c75, + 0x19f6e589ba384db3c36adae4bc034fb9a444da42164b6ef289009a2cd7d15a6e, + 0x09fed90b1f10f84f6739bdb1b4b508957acceadace687aa735dc9f6ab14404fe, + 0x055e35bbef7ce5ee7a3603222e09005dd5192adcd70dc33721714137221f4831, + 0x05e8dc359ee98d3bb6990fd928ecf056f9bb736e0d47cec22a96e7cac65a9828, + 0x0c732297f8b0c272fac76944ee969930752a7bd3943c7b97e038bcd2315d290f, + 0x16703fb8b02c94ade315d5b62aa1bf7834de248310887dc13cfd13fb6c2a10ba, + 0x28715ac5265d7a812af4e39e43bf9ac80059635d01fd6fe40f3f1e059d7f7f4e, + 0x2f683b0027994e095e71eec8475730fe227b480a6aca67ab1593ce6f837bcaf8, + 0x0854d9c3be72187a2f198590decd43943c5aa6140a858f21595b9a08da85b323, + 0x1e3d592b71a473c85b2104acc1d8db8cb9101a3cce55c66801a0d379497deadd, + 0x1eb27377cfa38a3967a71e697725c195bc1d7ce047e83d0e069dee8b95a9a70a, + 0x0045b9fd1e0f115801232c7aaafb5e73bc2d657c47b122f4e3ea30a659bdd9be, + 0x027aefe3d1130e9394b61a804dfe2231d68295910dd39245f1e1de65a87dba6a, + 0x2e4c5fa1a42064e556fc50dd7fca7b48625e4c169415487d4df0482a9b1df4eb, + 0x05767cb28f1019a39627a19196a7e4672e82441be0b90523c7b9b9f74dd3315d, + 0x17e443e32ab352d209d3e038d1364b24eb3f945e99a6809502c5439c807fb4dd, + 0x017a0c0d83cead8ffb70978edec1bf3c4acef4a2cdcfd8c335bce42793513e43, + 0x28b749b2a9becb34665e38f3c49b767f20738a481a7a76a19bf1030008a252b3, + 0x1f5252eb629922c70f2fc1b5ec5ea0a0e0acee47da26c40436c3f1ffca690356, + 0x29324c40ee7bc85d33a056c3fa8f44d6a7724da53ccedb3e56cc26b73358aa0e, + 0x00567e9bd8a2b947d75b376a9a1af17bf8bec6c9abede582054fb3ecf7860cde, + 0x1e96bab6ed6f45550f2621c0adad747c2fc9988485f6184355c3176d5c11e8d6, + 0x08d47dc23b1ff527992c9eddc91259a748f6cd7c1f61874a0836f599e995a399, + 0x22733cdd318150f40d89d1ac142f26750809a0b888c85743af671050cf6736a2, + 0x2168174bb9c45be2ee87441174a24fd41de6bff4a377803025864c5ca1927347, + 0x0b48fdaba88524ef8d0495ba63e8713b65af4a9267b5d62083e7b8726043a1e0, + 0x18658643fcb63644520c0fa02dce232935a4ce8d7b733a9b17a866e50b3ec8a9, + 0x2fc94cda5238fc785871bca97960b299ed0df05f6c6b28a3834865fd4974bc21, + 0x1a54a91a89dd7e0ce87530303c12ef76244fcf42c38db35513d65c6d5994ab6f, + 0x15610d8d64ba02952f4170eaf42a27cfb2d13f04d4673537b72510c5c4c3da22, + 0x13597b4707657f437ee42087cf8b589042b277467d8a0436cf66ea44a6661212, + 0x2dbb95e5114e740028bc5edf58b2e9fc7e3871d3f16ad0c3845d5e961a87837f, + 0x2cb3a3e7ce16cad9596eab92d772f6b8afb43cb6492b2c363ec71e11f86c52f9, + 0x286e8b9468bd2d392dad5d90ef65d28dec27de7147ce50b8edffeca5d70020a4, + 0x166e762a73b519001d753737d7d908ef226237b077cb76ed9f6bbfcce9989317, + 0x1dc5bee6477d7e7879fa2f33ba9adce878a57fad3845e7c9eaf4be54ab844f61, + 0x1f16f7f1cd61d9563e064c86b508afec41d614abc7b34bb45174b40d3877155c, + 0x28df04cdd7f79cb06fbf044e631ab11fadf9691e4ea5f6209f8751af58c8eb15, + 0x18aa6490047ab52105dc1e60f448762461b7075d38a7c0b2ba95646526588fb6, + 0x0076ab8143a290792147c6a6465c9a83bddf4f65388cae8357bc6bd9400ab99b, + 0x2616217a94f407053cef3b234cc11acbbd2e344b403bbd8a26f821bcb6f1f8de, + 0x2296862cb9a14424a34d3a11080d6ed5bfe1bc4e0301ec1cbd4e260d81675684, + 0x0828428022a299903406314c159732bc0fda227a3e7a40a4834e513f3ef97c53, + 0x0771ff9f397469dda6f20cf1841e702c1780a0719b3f590175b394f38279c77b, + 0x0dc489dcf61aba1104925eb9439a4f44228d06dd4567fce1444965a749567975, + 0x104470f92923d3b9dafa39eabdf7eaa23b6ff11b2ebb64a63bdb912d43865fa1, + 0x14a490ce09c929505ad223e2f397186135aa6586b27cc9ccd4f78efbec993a6d, + 0x206893bb747ca2504461fb24a2f72eae4cf330835825fb8ac9563fed9a7853ea, + 0x03c2a738e753f35b068c6ac8171244c23fbd4f37c80ba508618c800acf626546, + 0x129edb7a013029be80efc7400212cd7af1308100d34a569ef3646b52cfb06e16, + 0x0874b0edfee05d8cddac89e7b562f917c7ece1ec2e262f226f4d1524a1ddc158, + 0x10a0bab2786cda30537c696bb1ffaf898078841896f7be41cdf30ad2517b2aae, + 0x0bab661c2a17fbe0221f435ba90520bced928364cac984e17a6c72a47e13fc2b, + 0x2042016e686c984057a28aa2ae13c981ad8dd02ac7d4663005e1380c54f843b2, + 0x1fc295ac71911a59a81d087f967f16a3a887739d7cee663fff5d6e0710cf4a42, + 0x05922697b04ae608cc3bb0d9d345cadeaf4fa291de888e9b1dd32c19cb1a8777, + 0x271b87d8b895c6e1d864b9cd030729e523bc90b469cee37b51144bb3b0e4b9db, + 0x24aa401343e4705f22900fee892cca269d0c0ffab8f55c21c674edb9d7bba552, + 0x1b07068cafe17b55b5e00f7037c9ac37ef0268d5d2b76d7271c617004f05922d, + 0x1e35bad319a036cc6a2094f2a1bf2d1984a2b74aaf3e5b13a6ee30c90097cb33, + 0x2ab91b9a85ce69e7bea68f4fb5b1fa0903945e039c4ddbe05eff2d5e754fc219, + 0x21e979fa3a2594d2365ec70b5b3e0ddc5edb8e28fa7ec307aab14b547858f666, + 0x187cffd76c5fb29795523ebe065c9c2115e73784ac6b15c596fdd68469d1ad0e, + 0x18d2ff882c52b396a8c068f88c3d23f9d11d9f91c0f7fde9ef6af2180a007392, + 0x0a878a77de615e83c3d430f11f326b785c1ac114e599c24e5adc1d9fb91b31f3, + 0x286b9c6381700288bcc75d020ea09c45957a615576d7620a0b9af2609d39afcc, + 0x1c4e5ed7db96db52059ae2da709879d489a1ac5031c35ee1b6c422d9080c3f12, + 0x27141679bb9260a693b880784ff5fbc5d59457b96630e0a5c04912092a4d2abd, + 0x15e337c65fa58edb6a74fdbe7cdd1901b5d019ce7dd4144a8b49eba02bf085fe, + 0x08256792218c8227eca89f5114f1e7f091d88a557c69b2a956fd2dc90cae3631, + 0x0c08d19af9c30a31acd3928ffb5a57de5e83367204ee67209ee7ed1bca5185da, + 0x1919839ad91604c370f237d2a0aa98efac29246f93c24a1bd0f9d2b60709b6fa, + 0x15bf65b02b92f40b9f0ea893ddbb0572f49375acb5958bf944c77ff6c3561a41, + 0x122e02f2e0169809b22def001acc797b202d335af7bd2cf032e3a7c75ef033b5, + 0x12075100dddb8098654e718605211f7f6a21f5176d380141fb39977305182469, + 0x2dadbbb8fecf5ccdf01f73d0cc60b15f1bbef018a63f50f68d00b72d8adf0878, + 0x14334ece05a631ab375e7cfe7b89fa0d8092ec0cee24c9fa3009edcd62ea8b71, + 0x09a51856d49ec654f7d44aca57b174365ba5479d8714a09f0f6de08b34e3942c, + 0x048e8feea9b828528dbc63cd3d811ed05ce9de018f4a4647ac1f685bb8f6715b, + 0x204ba6f18193f747ff10980957022ecaa8fa4c13e7fa4e89730a76253c9b07f6, + 0x0079e1be1622edc5742e4f811ea2c0379bff4fa82b79fde5d0c9a0d174df130e, + 0x27e48eabb0ef3b22305ab720ee4c7f414e8d4dbf4360c81d1ffae4d7683f637a, + 0x15571becc7f5454e45ae416a6b3576274767215f659c91ba354372d999881d5a, + 0x2e6a4545ebf7c2e44af91ca7192eec4aedddbd2ac1df4f5101f7f8cdd316655e, + 0x2de19fcc78800027b1932cdf6f9e959208606cbf8a07524457492867f8f6bca5, + 0x2e1ca8efd1876e209fc2d62cb14446e8f3c4bdd53d6382ca86b113f3209d55f2, + 0x154b3f85eaed8b65718e733ca2ca7c8af03cf8f23befc4d7c6177ac00ebad368, + 0x29e58f39555d9dde7bac3df18d8eaeb2a5a50503860d20c5cd0ba2a2cf6373bd, + 0x032d32032e52103ad798fb36ef7c0681504cd2d86a12c7d937ff518e57b4c3f0, + 0x281de0191d30af73105e39dc174015d65dc7ff12d20888d02cec650e1a245a3a, + 0x0f7e76af800ebab14281645d290607eabb062bf0afe1419133e1ffdcf70c808f, + 0x27ea405bdfc6557a4dd338a2bca9819547501f6f77a588a75c014d46283f75b3, + 0x0570af543efefdfddab63fb05d31edcad395ac82381491a80c825c621c7ac22b, + 0x027a797e0014302478a413cede7a45cd894b0a229c8e89f56ebaec4c46692bfe, + 0x1dd0e283a8ef7d0f4966a517687fc53243554a8d3c7e41d91719b36bace81516, + 0x2006444695987560869df6dcde2673e5b73ee5bccbb43a05c2d8be6c59979242, + 0x271926392e5f1c94437afe2c2969bea4ff3f6d83ee71394008831d24bb1b6cb6, + 0x1b607ed2f130580d9a8c20ea26b33b478d6e1f00cc82f00176935a8b54cabf8e, + 0x0b7a6e33808d217a9e55c23871cfdfe495c10d62b8b981784b0487e63df03e0a, + 0x28ac790d462bb345ab80cd1670403943599b79edef17cf70236ecb1ef872cbc9, + 0x2f8d745b1b4750fd2f932f7913095515c498be314210180c6c3077231226bb94, + 0x2a3ef20e60142f17d2f3b82eef6135079523956d8bc684092eecb7a7d56d71be, + 0x08119b14b83922e4b224697c2c6536cf772d067489d42672b988cb638c71a0f0, + 0x1a4bae6c9cf73ea22739a275bc722c8cc83d91e7ddfd5110614a52d84ce73205, + 0x1d659aebe4b37b888be3a7d7f23e362c250046c09d5326312d8d94cdb384d1be, + 0x28e2fb92bf6da4e6b96730479f170760564458d95f732aae2406af4c03969f8f, + 0x10f4ec3ad6f3ed3387729990456c9685786ede8e6e14b7c66311d47b8778aa68, + 0x2ad366d90419107866504d4d34346e0a3c595de6e0aa51c805272ae1bcddc2d8, + 0x02f1dc29a06c64c9e43d3379db0f2e8f0cd8f80351724d313ca02ad24c6dac81, + 0x20086a672c397e65cb37cfb64ddab08074f173f37d0e4a1747b7f020652da64e, + 0x0ef2861f4ec9ba5fec74ba22c0b7af9d458c3cd8f90c825c1f36110ca2ee9076 + ] + ] diff --git a/crypto/Pact/Core/Crypto/Pairing.hs b/crypto/Pact/Core/Crypto/Pairing.hs new file mode 100644 index 000000000..a9b16f937 --- /dev/null +++ b/crypto/Pact/Core/Crypto/Pairing.hs @@ -0,0 +1,743 @@ +{-# LANGUAGE BangPatterns #-} +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE DerivingStrategies #-} +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE FunctionalDependencies #-} +{-# LANGUAGE GeneralizedNewtypeDeriving #-} +{-# LANGUAGE LambdaCase #-} +{-# LANGUAGE MultiParamTypeClasses #-} +{-# LANGUAGE OverloadedLists #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE PatternSynonyms #-} +{-# LANGUAGE RankNTypes #-} +{-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE TemplateHaskell #-} +{-# LANGUAGE TupleSections #-} +{-# LANGUAGE TypeApplications #-} +{-# LANGUAGE TypeFamilies #-} +{-# LANGUAGE TypeSynonymInstances #-} +{-# LANGUAGE ViewPatterns #-} + +{-# OPTIONS_GHC -Wno-unused-top-binds #-} + +module Pact.Core.Crypto.Pairing + ( pairing + , CurvePoint(..) + , Fq(..) + , Fq2 + , Fq6 + , Fq12 + , g1 + , g2 + , multiply + , add + , double + , negatePt + , b1 + , b2 + , b12 + , G1 + , G2 + , pairingCheck + , isOnCurve + , Extension(..) + -- , toG1 + -- , fromG1 + -- , toG2 + -- , fromG2 + ) + where + +import Prelude +import qualified Prelude as P + +-- import Control.Lens +import Control.Monad(join) +import Data.Bits(shiftR) +import Data.Group(Group(..)) +import Data.Euclidean (Euclidean, GcdDomain) +import Data.Semiring (Semiring, Ring) +import Data.Field (Field) +import Data.Foldable (forM_, foldl') +import qualified Data.Vector as G +import qualified Data.Vector.Mutable as MG +import qualified Data.Semiring as SR +import qualified Data.Euclidean as E +-- import qualified Data.Map.Strict as M +import Control.Monad.ST +import Data.Poly +import Data.Vector(Vector) +import Data.Int(Int8) +import GHC.Real(Ratio(..)) +import GHC.Exts(IsList(..)) + +import Control.DeepSeq (NFData) + +-- import Pact.Core.Literal +-- import Pact.Core.PactValue +import Pact.Core.Crypto.Pairing.Fields + +-- import qualified Pact.Core.Names as Name + +class GaloisField k => ExtensionField p k | p -> k, k -> p where + -- | The degree of the + -- fieldDegree :: Extension p k -> Word + fieldPoly :: VPoly k + +newtype Extension p k + = Extension (VPoly k) + deriving (Show, Eq, Ord, NFData) + +-- | Frobenius endomorphism precomputation. +frobenius' :: GaloisField k => Vector k -> Vector k -> Maybe (Vector k) +frobenius' [] _ = Just [] +frobenius' [a] _ = Just [frobenius a] +frobenius' [a, b] [x, 0, 1] + | degree x == 2 = Just [a, negate b] + | characteristic x == 2 = Just [frobenius a - frobenius b * x] + | otherwise = Just [frobenius a, frobenius b * nxq] + where + nxq = negate x ^ shiftR (characteristic x) 1 +frobenius' [a, b] [x, 0, 0, 1] + | characteristic x == 3 = Just [frobenius a - frobenius b * x] + | r == 1 = Just [frobenius a, frobenius b * nxq] + | otherwise = Just [frobenius a, 0, frobenius b * nxq] + where + (q, r) = quotRem (characteristic x) 3 + nxq = negate x ^ q +frobenius' [a, b, c] [x, 0, 0, 1] + | characteristic x == 3 = Just [frobenius a - (frobenius b - frobenius c * x) * x] + | r == 1 = Just [frobenius a, frobenius b * nxq, frobenius c * nxq * nxq] + | otherwise = Just [frobenius a, frobenius c * nx * nxq * nxq, frobenius b * nxq] + where + (q, r) = quotRem (characteristic x) 3 + nx = negate x + nxq = nx ^ q +frobenius' _ _ = Nothing +{-# INLINABLE frobenius' #-} +{-# SPECIALIZE frobenius' :: Vector Fq -> Vector Fq -> Maybe (Vector Fq) #-} +{-# SPECIALIZE frobenius' :: Vector Fq2 -> Vector Fq2 -> Maybe (Vector Fq2) #-} +{-# SPECIALIZE frobenius' :: Vector Fq6 -> Vector Fq6 -> Maybe (Vector Fq6) #-} +{-# SPECIALIZE frobenius' :: Vector Fq12 -> Vector Fq12 -> Maybe (Vector Fq12) #-} + +----------------------------------------------------------------- +-- Num instances +----------------------------------------------------------------- +instance ExtensionField p k => Num (Extension p k) where + (Extension x) + (Extension y) = Extension (x + y) + {-# INLINABLE (+) #-} + (Extension x) * (Extension y) = + Extension (E.rem (toPoly (karatsuba (unPoly x) (unPoly y))) fieldPoly) + {-# INLINABLE (*) #-} + (Extension x) - (Extension y) = Extension (x - y) + {-# INLINABLE (-) #-} + negate (Extension x) = Extension (P.negate x) + {-# INLINABLE negate #-} + fromInteger = Extension . fromInteger + {-# INLINABLE fromInteger #-} + abs = error "abs not implemented for Field Extensions" + signum = error "signum not implemented for Field Extensions" + +karatsubaThreshold :: Int +karatsubaThreshold = 32 + +plusPoly + :: Num a + => Vector a + -> Vector a + -> Vector a +plusPoly xs ys = runST $ do + zs <- MG.unsafeNew lenMx + forM_ ([0 .. lenMn - 1] :: [Int]) $ \i -> + MG.unsafeWrite zs i (G.unsafeIndex xs i + G.unsafeIndex ys i) + G.unsafeCopy + (MG.unsafeSlice lenMn (lenMx - lenMn) zs) + (G.unsafeSlice lenMn (lenMx - lenMn) (if lenXs <= lenYs then ys else xs)) + G.unsafeFreeze zs + where + lenXs = G.length xs + lenYs = G.length ys + lenMn = lenXs `min` lenYs + lenMx = lenXs `max` lenYs +{-# INLINABLE plusPoly #-} +{-# SPECIALIZE plusPoly :: Vector Fq -> Vector Fq -> Vector Fq #-} +{-# SPECIALIZE plusPoly :: Vector Fq2 -> Vector Fq2 -> Vector Fq2 #-} +{-# SPECIALIZE plusPoly :: Vector Fq6 -> Vector Fq6 -> Vector Fq6 #-} +{-# SPECIALIZE plusPoly :: Vector Fq12 -> Vector Fq12 -> Vector Fq12 #-} + +karatsuba + :: (Eq a, Num a) + => Vector a + -> Vector a + -> Vector a +karatsuba xs ys + | lenXs <= karatsubaThreshold || lenYs <= karatsubaThreshold + = convolution xs ys + | otherwise = runST $ do + zs <- MG.unsafeNew lenZs + let lzs0 = G.length zs0 + lzs11 = G.length zs11 + lzs2 = G.length zs2 + forM_ ([0 .. lenZs - 1] :: [Int]) $ \k -> do + let z0 = if k < lzs0 + then G.unsafeIndex zs0 k + else 0 + z11 = if k - m >= 0 && k - m < lzs11 + then G.unsafeIndex zs11 (k - m) + else 0 + z10 = if k - m >= 0 && k - m < lzs0 + then G.unsafeIndex zs0 (k - m) + else 0 + z12 = if k - m >= 0 && k - m < lzs2 + then G.unsafeIndex zs2 (k - m) + else 0 + z2 = if k - 2 * m >= 0 && k - 2 * m < lzs2 + then G.unsafeIndex zs2 (k - 2 * m) + else 0 + MG.unsafeWrite zs k (z0 + (z11 - z10 - z12) + z2) + G.unsafeFreeze zs + where + lenXs = G.length xs + lenYs = G.length ys + lenZs = lenXs + lenYs - 1 + + m = ((lenXs `min` lenYs) + 1) `shiftR` 1 + + xs0 = G.unsafeSlice 0 m xs + xs1 = G.unsafeSlice m (lenXs - m) xs + ys0 = G.unsafeSlice 0 m ys + ys1 = G.unsafeSlice m (lenYs - m) ys + + xs01 = plusPoly xs0 xs1 + ys01 = plusPoly ys0 ys1 + zs0 = karatsuba xs0 ys0 + zs2 = karatsuba xs1 ys1 + zs11 = karatsuba xs01 ys01 +{-# INLINABLE karatsuba #-} +{-# SPECIALIZE karatsuba :: Vector Fq -> Vector Fq -> Vector Fq #-} +{-# SPECIALIZE karatsuba :: Vector Fq2 -> Vector Fq2 -> Vector Fq2 #-} +{-# SPECIALIZE karatsuba :: Vector Fq6 -> Vector Fq6 -> Vector Fq6 #-} +{-# SPECIALIZE karatsuba :: Vector Fq12 -> Vector Fq12 -> Vector Fq12 #-} + +convolution + :: Num a + => Vector a + -> Vector a + -> Vector a +convolution xs ys + | lenXs == 0 || lenYs == 0 = G.empty + | otherwise = G.generate lenZs $ \k -> foldl' + (\acc i -> acc + (G.unsafeIndex xs i * G.unsafeIndex ys (k - i))) + 0 + ([max (k - lenYs + 1) 0 .. min k (lenXs - 1)] :: [Int]) +{- + | otherwise = + G.generate lenZs $ \k -> + let !b = max (k - lenYs + 1) 0 + !e = min k (lenXs - 1) + !l = (e - b) + 1 in + sum (zipWith (*) (G.toList (G.unsafeSlice b l xs)) + (G.toList (G.reverse (G.unsafeSlice (k - e) l ys)))) +-} + where + !lenXs = G.length xs + !lenYs = G.length ys + lenZs = lenXs + lenYs - 1 +{-# INLINABLE convolution #-} +{-# SPECIALIZE convolution :: Vector Fq -> Vector Fq -> Vector Fq #-} +{-# SPECIALIZE convolution :: Vector Fq2 -> Vector Fq2 -> Vector Fq2 #-} +{-# SPECIALIZE convolution :: Vector Fq6 -> Vector Fq6 -> Vector Fq6 #-} +{-# SPECIALIZE convolution :: Vector Fq12 -> Vector Fq12 -> Vector Fq12 #-} + +instance ExtensionField p k => Fractional (Extension p k) where + recip (Extension vp) = case leading g of + Just (0, vp') -> Extension $ scale 0 (recip vp') y + _ -> error "Division by zero: Extension" + where + (g, y) = E.gcdExt vp fieldPoly + {-# INLINABLE recip #-} + fromRational (x :% y) = fromInteger x / fromInteger y + {-# INLINABLE fromRational #-} + + +----------------------------------------------------------------- +-- Group instances +----------------------------------------------------------------- +instance ExtensionField p k => Semigroup (Extension p k) where + (<>) = (*) + {-# INLINABLE (<>) #-} + +instance ExtensionField p k => Monoid (Extension p k) where + mempty = Extension 1 + {-# INLINABLE mempty #-} + +instance ExtensionField p k => Group (Extension p k) where + invert = recip + {-# INLINABLE invert #-} + pow x n + | n >= 0 = x ^ n + | otherwise = recip x ^ P.negate n + {-# INLINABLE pow #-} + +instance ExtensionField p k => Euclidean (Extension p k) where + degree = error "Not Defined: Euclidean degree for Extension" + quotRem l r = (l / r, 0) + {-# INLINABLE quotRem #-} + +instance ExtensionField p k => Field (Extension p k) + +instance ExtensionField p k => GaloisField (Extension p k) where + characteristic _ = characteristic (undefined :: k) + degree _ = degree (undefined :: k) * deg' + where + deg' = fromIntegral (E.degree (fieldPoly :: VPoly k)) + frobenius y@(Extension x) = case frobenius' (unPoly x) (unPoly (fieldPoly :: VPoly k)) of + Just f -> Extension (toPoly f) + Nothing -> pow y (characteristic y) + +{-# RULES "Extension.pow" + forall (k :: ExtensionField p k => Extension p k) n . (^) k n = pow k n + #-} + + +instance ExtensionField p k => GcdDomain (Extension p k) + +instance ExtensionField p k => Ring (Extension p k) where + negate = P.negate + {-# INLINABLE negate #-} + +instance ExtensionField p k => Semiring (Extension p k) where + fromNatural = fromIntegral + {-# INLINABLE fromNatural #-} + one = Extension 1 + {-# INLINABLE one #-} + plus = (+) + {-# INLINABLE plus #-} + times = (*) + {-# INLINABLE times #-} + zero = Extension 0 + {-# INLINABLE zero #-} + +instance ExtensionField p k => IsList (Extension p k) where + type instance Item (Extension p k) = k + fromList = Extension . fromList + {-# INLINABLE fromList #-} + toList (Extension x) = toList $ unPoly x + {-# INLINABLE toList #-} + +-------------------------------------------------------------------------------------- +-- Curve implementation +-------------------------------------------------------------------------------------- + +data F1 + +data F2 + +data F3 + +type Fq2 = Extension F1 Fq + +instance ExtensionField F1 Fq where + fieldPoly = fromList [1, 0, 1] + +xiFq2 :: Fq2 +xiFq2 = fromList [9, 1] +{-# INLINABLE xiFq2 #-} + +type Fq6 = Extension F2 Fq2 + +instance ExtensionField F2 Fq2 where + fieldPoly = fromList [-xiFq2, 0, 0, 1] + {-# INLINABLE fieldPoly #-} + +type Fq12 = Extension F3 Fq6 + +instance ExtensionField F3 Fq6 where + fieldPoly = fromList [[0, -1], 0, 1] + {-# INLINABLE fieldPoly #-} + +type G1 = CurvePoint Fq +type G2 = CurvePoint Fq2 + +----------------------------------------------------------------------------------- +-- Curve implementation +----------------------------------------------------------------------------------- + +-- y^2 = x^3 + b +isOnCurve :: (Num a, Eq a) => CurvePoint a -> a -> Bool +isOnCurve CurveInf _ = True +isOnCurve (Point x y) b = + ((y ^ (2 :: Int)) - (x ^ (3 :: Int))) == b + +-- Curve is y**2 = x**3 + 3 +b1 :: Fq +b1 = 3 + +-- Twisted curve over FQ**2 +b2 :: Fq2 +b2 = let + v1 = fromList [3, 0] + v2 = fromList [9, 1] + in v1 / v2 + +b12 :: Fq12 +b12 = [3] + +g1 :: CurvePoint Fq +g1 = Point 1 2 +{-# INLINABLE g1 #-} + +g2 :: CurvePoint Fq2 +g2 = Point + [10857046999023057135944570762232829481370756359578518086990519993285655852781, 11559732032986387107991004021392285783925812861821192530917403151452391805634] + [8495653923123431417604973247489272438418190587263600148770280649306958101930, 4082367875863433681332203403145435568316851327593401208105741076214120093531] + +data CurvePoint a + = Point !a !a + | CurveInf + deriving (Eq, Show) + +-- todo: sort of scuffed, num instance? +double :: (Field a, Num a, Eq a) => CurvePoint a -> CurvePoint a +double CurveInf = CurveInf +double (Point x y) + | y == 0 = CurveInf + | otherwise = let + y1 = y + y + x1 = x * x + l = (x1 + x1 + x1) `E.quot` y1 + newx = (l * l) - (x + x) + newy = l * (x - newx) - y + in Point newx newy +{-# SPECIALIZE double :: CurvePoint Fq -> CurvePoint Fq #-} +{-# SPECIALIZE double :: CurvePoint Fq2 -> CurvePoint Fq2 #-} +{-# SPECIALIZE double :: CurvePoint Fq6 -> CurvePoint Fq6 #-} +{-# SPECIALIZE double :: CurvePoint Fq12 -> CurvePoint Fq12 #-} + +add :: (Field a, Eq a, Num a) => CurvePoint a -> CurvePoint a -> CurvePoint a +add CurveInf r = r +add l CurveInf = l +add p1@(Point x1 y1) (Point x2 y2) + | x2 == x1 && y2 == y1 = double p1 + | x2 == x1 = CurveInf + | otherwise = let + l = (y2 - y1) `E.quot` (x2 - x1) + newx = (l * l) - x1 - x2 + newy = l * (x1 - newx) - y1 + in Point newx newy +{-# SPECIALIZE add :: CurvePoint Fq -> CurvePoint Fq -> CurvePoint Fq #-} +{-# SPECIALIZE add :: CurvePoint Fq2 -> CurvePoint Fq2 -> CurvePoint Fq2 #-} +{-# SPECIALIZE add :: CurvePoint Fq6 -> CurvePoint Fq6 -> CurvePoint Fq6 #-} +{-# SPECIALIZE add :: CurvePoint Fq12 -> CurvePoint Fq12 -> CurvePoint Fq12 #-} + +multiply :: (Field a, Eq a, Num a) => CurvePoint a -> Integer -> CurvePoint a +multiply pt n + | n < 0 = multiply (negatePt pt) (-n) + | n == 0 = CurveInf + | n == 1 = pt + | even n = multiply (double pt) (n `div` 2) + | otherwise = + add (multiply (double pt) (n `div` 2)) pt +{-# SPECIALIZE multiply :: CurvePoint Fq -> Integer -> CurvePoint Fq #-} +{-# SPECIALIZE multiply :: CurvePoint Fq2 -> Integer -> CurvePoint Fq2 #-} +{-# SPECIALIZE multiply :: CurvePoint Fq6 -> Integer -> CurvePoint Fq6 #-} +{-# SPECIALIZE multiply :: CurvePoint Fq12 -> Integer -> CurvePoint Fq12 #-} + +negatePt :: Num a => CurvePoint a -> CurvePoint a +negatePt (Point x y) = + Point x (negate y) +negatePt CurveInf = CurveInf +{-# SPECIALIZE negatePt :: CurvePoint Fq -> CurvePoint Fq #-} +{-# SPECIALIZE negatePt :: CurvePoint Fq2 -> CurvePoint Fq2 #-} +{-# SPECIALIZE negatePt :: CurvePoint Fq6 -> CurvePoint Fq6 #-} +{-# SPECIALIZE negatePt :: CurvePoint Fq12 -> CurvePoint Fq12 #-} + +frobTwisted + :: Fq2 + -> CurvePoint Fq2 + -> CurvePoint Fq2 +frobTwisted xi (Point x y) = Point (frobenius x * pow xi tx) (frobenius y * pow xi ty) + where + tx = quot (characteristic (undefined :: Fq) - 1) 3 + ty = shiftR (characteristic (undefined :: Fq)) 1 +frobTwisted _ _ = CurveInf + +lineFunction + :: CurvePoint Fq -- ^ Point @P@. + -> CurvePoint Fq2 -- ^ Point @T@. + -> CurvePoint Fq2 -- ^ Point @Q@. + -> (CurvePoint Fq2, Fq12) -- ^ Points @T + Q@ and @Line(T, Q, P)@. +lineFunction (Point x y) (Point x1 y1) (Point x2 y2) + | x1 /= x2 = (Point x3 y3 , [embedFqToFq6 (-y), [scalarEmbed x l , y1 - l * x1]]) + | y1 + y2 == 0 = (CurveInf , [embedFqToFq6 x, embedFq2ToFq6 (-x1)]) + | otherwise = (Point x3' y3', [embedFqToFq6 (-y), [scalarEmbed x l', y1 - l' * x1]]) + where + scalarEmbed e1 e2 = embedFqToFq2 e1 * e2 + embedFqToFq2 q = Extension (monomial 0 q) + embedFqToFq6 q = embedFq2ToFq6 (Extension (monomial 0 q)) + embedFq2ToFq6 q = Extension (monomial 0 q) :: Fq6 + l = (y2 - y1) / (x2 - x1) + x3 = l * l - x1 - x2 + y3 = l * (x1 - x3) - y1 + x12 = x1 * x1 + l' = (x12 + x12 + x12) / (y1 + y1) + x3' = l' * l' - x1 - x2 + y3' = l' * (x1 - x3') - y1 +lineFunction _ _ _ = (CurveInf, mempty) +{-# INLINABLE lineFunction #-} + +powUnitary :: ExtensionField p k + => Extension p k -- ^ Element @x@ in cyclotomic subgroup. + -> Integer -- ^ Integer @n@. + -> Extension p k -- ^ Element @x ^ n@. +powUnitary x n + | n < 0 = pow (conj x) (negate n) + | otherwise = pow x n +{-# INLINABLE powUnitary #-} +{-# SPECIALIZE powUnitary :: Extension F1 Fq -> Integer -> Extension F1 Fq #-} +{-# SPECIALIZE powUnitary :: Extension F2 Fq2 -> Integer -> Extension F2 Fq2 #-} +{-# SPECIALIZE powUnitary :: Extension F3 Fq6 -> Integer -> Extension F3 Fq6 #-} + +-- | Complex conjugation @a+bi -> a-bi@ of quadratic extension field. +conj :: forall p k. ExtensionField p k => Extension p k -> Extension p k +conj (Extension x) = case unPoly (fieldPoly @p @k) of + [_, 0, 1] -> case x of + [a, b] -> [a, negate b] + [a] -> [a] + _ -> [] + _ -> error "conj: extension degree is not two." +{-# INLINABLE conj #-} +{-# SPECIALIZE conj :: Extension F1 Fq -> Extension F1 Fq #-} +{-# SPECIALIZE conj :: Extension F2 Fq2 -> Extension F2 Fq2 #-} +{-# SPECIALIZE conj :: Extension F3 Fq6 -> Extension F3 Fq6 #-} + +additionStep + :: CurvePoint Fq + -> CurvePoint Fq2 + -> (CurvePoint Fq2, Fq12) + -> (CurvePoint Fq2, Fq12) +additionStep p q (t, f) = (<>) f <$> lineFunction p q t +{-# INLINABLE additionStep #-} + +-- Doubling step, line 4. +doublingStep + :: CurvePoint Fq + -> (CurvePoint Fq2, Fq12) + -> (CurvePoint Fq2, Fq12) +doublingStep p (t, f) = (<>) f . (<>) f <$> lineFunction p t t +{-# INLINABLE doublingStep #-} + +parameterHex :: Integer +parameterHex = 0x44e992b44a6909f1 + +-- | [Final exponentiation for Barreto-Lynn-Scott degree 12 curves] +-- (https://eprint.iacr.org/2016/130.pdf). +finalExponentiate :: Integer -> Fq12 -> Fq12 +finalExponentiate u = hardPart . easyPart + where + easyPart = p2 . p6 + where + p6 = (*) <$> conj <*> recip -- f^(p^6 - 1) + p2 = (*) <$> id <*> frobenius . frobenius -- f^(p^2 + 1) + hardPart !f = p4 + where + !fu = powUnitary f u -- f^u + !fu2 = powUnitary fu u -- f^(u^2) + !fu3 = powUnitary fu2 u -- f^(u^3) + !fpu = frobenius fu2 -- f^(pu^2) + !y0 = frobenius (f * frobenius (f * frobenius f)) -- f^(p + p^2 + p^3) + !y1 = conj f -- f^(-1) + !y2 = frobenius fpu -- f^(p^2u^2) + !y3 = conj $ frobenius fu -- f^(-pu) + !y4 = conj $ fu * fpu -- f^(-u - pu^2) + !y5 = conj fu2 -- f^(-u^2) + !y6 = conj $ fu3 * frobenius fu3 -- f^(-u^3 - pu^3) + !p4 = p4' * y0 * join (*) (p4' * y1) -- f^((p^4 - p^2 + 1) / r) + where + p4' = join (*) $ p4'' * y2 * join (*) (p4'' * y3 * y5) + p4'' = y4 * y5 * join (*) y6 +{-# INLINABLE finalExponentiate #-} + +pairing :: G1 -> G2 -> Fq12 +pairing p1 p2 = + finalExponentiate parameterHex (millerLoop p1 p2) + +-- | [Miller algorithm for Barreto-Naehrig curves] +-- (https://eprint.iacr.org/2010/354.pdf). +millerLoop + :: G1 + -> G2 + -> Fq12 +millerLoop p q = + finalStepBN $ + millerLoop' parameterBin (q, mempty) + where + millerLoop' [] tf = tf + millerLoop' (x:xs) tf = case doublingStep p tf of + tf2 + | x == 0 -> millerLoop' xs tf2 + | x == 1 -> millerLoop' xs $ additionStep p q tf2 + | otherwise -> millerLoop' xs $ additionStep p (negatePt q) tf2 + finalStepBN (t, f) = case lineFunction p t q1 of + (t', f') -> case lineFunction p t' q2 of + (_, f'') -> f <> f' <> f'' + where + q1 = frobTwisted xiFq2 q + q2 = negatePt $ frobTwisted xiFq2 q1 + + parameterBin :: [Int8] + parameterBin = [ 1, 0, 1, 0, 0,-1, 0, 1, 1, 0, 0, 0,-1, 0, 0, 1 + , 1, 0, 0,-1, 0, 0, 0, 0, 0, 1, 0, 0,-1, 0, 0, 1 + , 1, 1, 0, 0, 0, 0,-1, 0, 1, 0, 0,-1, 0, 1, 1, 0 + , 0, 1, 0, 0,-1, 1, 0, 0,-1, 0, 1, 0, 1, 0, 0, 0 ] +{-# INLINABLE pairing #-} + +pairingCheck :: [(G1, G2)] -> Bool +pairingCheck = go 1 + where + go acc ((p1, p2):rest) + | p1 == CurveInf || p2 == CurveInf = go acc rest + | otherwise = go (acc * millerLoop p1 p2) rest + go acc [] = finalExponentiate parameterHex acc == 1 + +-- zkDefs :: NativeModule +-- zkDefs = ("Zk", +-- [ pointAdditionDef +-- , scalarMultDef +-- , pairingCheckDef +-- ]) + +-- | Pointwise addition on two points on the curve BN254, +-- either from G1 or G2. +-- pointAdditionDef :: NativeDef +-- pointAdditionDef = +-- defRNative "point-add" pactPointAdd (funType a [("type", tTyString), ("point1", a), ("point2", a)]) +-- [ "(point-add 'g1 {'x: 1, 'y: 2} {'x: 1, 'y: 2})" +-- ] "Add two points together that lie on the curve BN254. Point addition either in Fq or in Fq2" +-- where +-- a = mkTyVar "a" [] +-- pactPointAdd :: RNativeFun e +-- pactPointAdd i as@[TLiteral (LString ptTy) _ , TObject p1 _, (TObject p2 _) :: Term Name] = +-- case T.toLower ptTy of +-- "g1" -> do +-- p1' <- toG1 i p1 +-- p2' <- toG1 i p2 +-- unless (isOnCurve p1' b1 && isOnCurve p2' b1) $ evalError' i "Point not on curve" +-- _ <- computeGas (Right i) (GZKArgs (PointAdd ZKG1)) +-- let p3' = add p1' p2' +-- pure $ TObject (fromG1 p3') def +-- "g2" -> do +-- p1' <- toG2 i p1 +-- p2' <- toG2 i p2 +-- unless (isOnCurve p1' b2 && isOnCurve p2' b2) $ evalError' i "Point not on curve" +-- _ <- computeGas (Right i) (GZKArgs (PointAdd ZKG2)) +-- let p3' = add p1' p2' +-- pure $ TObject (fromG2 p3') def +-- _ -> argsError i as +-- pactPointAdd i as = argsError i as + +-- -- | Scalar multiplication of two points. +-- scalarMultDef :: NativeDef +-- scalarMultDef = +-- defRNative "scalar-mult" scalarMul (funType a [("type", tTyString), ("point1", a), ("scalar", tTyInteger)]) +-- [ "(scalar-mult 'g1 {'x: 1, 'y: 2} 2)" ] +-- "Multiply a point that lies on the curve BN254 by an integer value" +-- where +-- a = mkTyVar "a" [] +-- curveOrder :: Integer +-- curveOrder = 21888242871839275222246405745257275088548364400416034343698204186575808495617 +-- scalarMul :: RNativeFun e +-- scalarMul i as@[TLiteral (LString ptTy) _ , TObject p1 _, (TLiteral (LInteger scalar) _) :: Term Name] = do +-- let scalar' = scalar `mod` curveOrder +-- case T.toLower ptTy of +-- "g1" -> do +-- p1' <- toG1 i p1 +-- unless (isOnCurve p1' b1) $ evalError' i "Point not on curve" +-- _ <- computeGas (Right i) (GZKArgs (ScalarMult ZKG1)) +-- let p2' = multiply p1' scalar' +-- pure $ TObject (fromG1 p2') def +-- "g2" -> do +-- p1' <- toG2 i p1 +-- unless (isOnCurve p1' b2) $ evalError' i "Point not on curve" +-- _ <- computeGas (Right i) (GZKArgs (ScalarMult ZKG2)) +-- let p2' = multiply p1' scalar' +-- pure $ TObject (fromG2 p2') def +-- _ -> argsError i as +-- scalarMul i as = argsError i as + +-- pairingCheckDef :: NativeDef +-- pairingCheckDef = +-- defRNative "pairing-check" pairingCheck' (funType tTyBool [("points-g1", TyList a), ("points-g2", TyList b)]) +-- [] +-- "Perform pairing and final exponentiation points in G1 and G2 in BN254, check if the result is 1" +-- where +-- a = mkTyVar "a" [] +-- b = mkTyVar "b" [] +-- pairingCheck':: RNativeFun e +-- pairingCheck' i [TList p1s _ _, TList p2s _ _] = do +-- g1s <- traverse termToG1 $ G.toList p1s +-- g2s <- traverse termToG2 $ G.toList p2s +-- traverse_ (`ensureOnCurve` b1) g1s +-- traverse_ (`ensureOnCurve` b2) g2s +-- let pairs = zip g1s g2s +-- _ <- computeGas (Right i) (GZKArgs (Pairing (length pairs))) +-- pure $ toTerm $ pairingCheck pairs +-- where +-- ensureOnCurve :: (Num p, Eq p) => CurvePoint p -> p -> Eval e () +-- ensureOnCurve p bp = unless (isOnCurve p bp) $ evalError' i "Point not on curve" +-- termToG1 (TObject o _) = toG1 i o +-- termToG1 _ = evalError' i "not a point" +-- termToG2 (TObject o _) = toG2 i o +-- termToG2 _ = evalError' i "not a point" +-- pairingCheck' i as = argsError i as + +-- toG1 :: ObjectData PactValue -> Maybe G1 +-- toG1 (ObjectData obj) = do +-- px <- fromIntegral <$> preview (ix (Name.Field "x") . _PLiteral . _LInteger) obj +-- py <- fromIntegral <$> preview (ix (Name.Field "y") . _PLiteral . _LInteger) obj +-- if px == 0 && py == 0 then pure CurveInf +-- else pure (Point px py) + +-- fromG1 :: G1 -> ObjectData PactValue +-- fromG1 CurveInf = ObjectData pts +-- where +-- pts = M.fromList +-- [ (Name.Field "x", PLiteral (LInteger 0)) +-- , (Name.Field "y", PLiteral (LInteger 0))] +-- fromG1 (Point x y) = ObjectData pts +-- where +-- pts = +-- M.fromList +-- [ (Name.Field "x", PLiteral (LInteger (fromIntegral x))) +-- , (Name.Field "y", PLiteral (LInteger (fromIntegral y)))] + +-- toG2 :: ObjectData PactValue -> Maybe G2 +-- toG2 (ObjectData om) = do +-- pxl <- preview (ix (Name.Field "x") . _PList) om +-- px <- traverse (preview (_PLiteral . _LInteger . to fromIntegral)) pxl +-- pyl <- preview (ix (Name.Field "y") . _PList) om +-- py <- traverse (preview (_PLiteral . _LInteger . to fromIntegral)) pyl +-- let px' = fromList (G.toList px) +-- py' = fromList (G.toList py) +-- if px' == 0 && py' == 0 then pure CurveInf +-- else pure (Point px' py') + +-- fromG2 :: G2 -> ObjectData PactValue +-- fromG2 CurveInf = ObjectData pts +-- where +-- pts = +-- M.fromList +-- [ (Name.Field "x", PList (G.fromList [PLiteral (LInteger 0)])) +-- , (Name.Field "y", PList (G.fromList [PLiteral (LInteger 0)]))] +-- fromG2 (Point x y) = ObjectData pts +-- where +-- toPactPt (Extension e) = let +-- elems' = fmap (PInteger . fromIntegral) (unPoly e) +-- in PList elems' +-- x' = toPactPt x +-- y' = toPactPt y +-- pts = +-- M.fromList +-- [ (Name.Field "x", x') +-- , (Name.Field "y", y')] diff --git a/crypto/Pact/Core/Crypto/Pairing/Fields.hs b/crypto/Pact/Core/Crypto/Pairing/Fields.hs new file mode 100644 index 000000000..ff3965297 --- /dev/null +++ b/crypto/Pact/Core/Crypto/Pairing/Fields.hs @@ -0,0 +1,81 @@ +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE GeneralizedNewtypeDeriving #-} +{-# LANGUAGE FunctionalDependencies #-} +{-# LANGUAGE ScopedTypeVariables #-} + +-- | +-- Module: Pact.Core.Pairing.Fields +-- Copyright: Copyright © 2023 Kadena LLC. +-- License: MIT +-- Maintainer: Lars Kuhtz +-- Stability: experimental +-- +module Pact.Core.Crypto.Pairing.Fields +( GaloisField(..) +, Fq(..) +) where + +import Data.Euclidean (Euclidean, GcdDomain) +import Data.Semiring (Semiring, Ring) +import Data.Field (Field) +import qualified Data.Euclidean as E +import Data.Mod +import GHC.Natural(naturalToInteger) + +import Control.DeepSeq (NFData) +import Numeric.Natural(Natural) + +----------------------------------------------------- +-- Galois fields and field extensions +------------------------------------------------------ +class (Field k, Fractional k, Ord k, Show k) => GaloisField k where + -- | The characteristic of the field + characteristic :: k -> Natural + + -- | The degree of the finite field + degree :: k -> Word + + frobenius :: k -> k + + -- | order of a field p^k + order :: k -> Natural + order k = characteristic k ^ degree k + {-# INLINABLE order #-} + +----------------------------------------------------------------- +-- ExtensionField +----------------------------------------------------------------- + +type Q = 21888242871839275222246405745257275088696311157297823662689037894645226208583 + +newtype Fq = Fq (Mod Q) + deriving + ( Eq + , Show + , Ord + , Num + , Fractional + , Euclidean + , Field + , GcdDomain + , Ring + , Semiring + , Bounded + , Enum + , NFData + ) + +instance Real Fq where + toRational = fromIntegral + +instance Integral Fq where + quotRem = E.quotRem + toInteger (Fq m) = naturalToInteger (unMod m) + +instance GaloisField Fq where + characteristic _ = 21888242871839275222246405745257275088696311157297823662689037894645226208583 + + degree _ = 1 + + frobenius = id + diff --git a/pact-core-tests/Pact/Core/Test/ZkTests.hs b/pact-core-tests/Pact/Core/Test/ZkTests.hs new file mode 100644 index 000000000..6dc89008d --- /dev/null +++ b/pact-core-tests/Pact/Core/Test/ZkTests.hs @@ -0,0 +1,325 @@ +{-# LANGUAGE OverloadedLists #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE ScopedTypeVariables #-} + +module Pact.Core.Test.ZkTests (spec) where + +import Data.Group (pow) +import Data.Field(Field) +import Data.Foldable(foldl') +import Hedgehog +import qualified Hedgehog.Gen as Gen +import qualified Hedgehog.Range as Range +import Pact.Native.Pairing +import Test.Tasty +import Test.Tasty.Hedgehog + +p1 :: CurvePoint Fq +p1 = multiply g1 2 + +p2 :: CurvePoint Fq2 +p2 = multiply g2 3 + +pt' :: Fq12 +pt' = + [ [ [ 0x10227b2606c11f22f4b2dec3f69cee4332ebe2e8f869ea8ca9e6d45ce15bd110, + 0x27d1c9dae835182b272bb25b47b0d871382c9c2765fd1f42e07edbe852830157 + ], + [ 0x1f5919cf59b218135aaeb137ac84c6ecf282feda6a8752ca291b7ec1d2f8bab4, + 0x2b7e44680d35a6676223538d54abcd7bc2c54281bf0f5277c81cf5b114d3a345 + ], + [ 0x17e6d213292c2aa12ef3cc75aca8cb9cbd47d05086227db2dbd1262d3e89dbf0, + 0x291a53fea204b470bb901fb184155facd6e3b44fad848d536386b73d6c31fd52 + ] + ], + [ [ 0x2844ed362ecf2c491a471a18c2875fd727126a62c8151c356f81e02cff52f045, + 0x2a8245d55a3b3f9deae9cca372912a31b88dc77cee06dfa10a717acbf758cbd5 + ], + [ 0x222ff2e20c4578e886027953a035cbd8784a9764bbcd353051ba9f02c4dce8ad, + 0x8532a0a75fb0acdf508c3bdd4c7700efb3a9ae403818daad5937d9ffffaca45 + ], + [ 0x2e7e3a4aaef17a53de3c528319b426e35f53455107f49d7fe52de95849e7dcf6, + 0x2ba2bc83434031012424aad830a35c459c40a0b7ce87735010db68c10b61ddcb + ] + ] + ] + +fieldModulus :: Integer +fieldModulus = 21888242871839275222246405745257275088696311157297823662689037894645226208583 + +curveOrder :: Integer +curveOrder = 21888242871839275222246405745257275088548364400416034343698204186575808495617 + + +genCurvePoint + :: (Field a, Eq a, Num a) + => CurvePoint a -- Generator + -> Gen (CurvePoint a) +genCurvePoint gen' = do + r <- Gen.integral $ Range.constant 0 (curveOrder - 1) + pure (multiply gen' r) + +genG1 :: Gen G1 +genG1 = genCurvePoint g1 + +genG2 :: Gen G2 +genG2 = genCurvePoint g2 + +pairingGenTest :: TestTree +pairingGenTest = modifyMaxSuccess (const 20) $ + describe "Curve generated tests" $ do + it "Generates a point on the curve, and obeys the pairing function" $ hedgehog $ do + p1' <- forAll genG1 + assert (isOnCurve g1 b1) + addDoubling p1' + + p2' <- forAll genG2 + assert (isOnCurve g2 b2) + addDoubling p2' + + r1 <- forAll $ Gen.integral (Range.constant 0 1000) + r2 <- forAll $ Gen.integral (Range.constant 0 1000) + pairing (multiply p1' r1) (multiply p2' r2) === pow (pairing p1' p2') (r1 * r2) + where + addDoubling pt = + add (add (double pt) pt) pt === double (double pt) + +pairingProofTest :: TestTree +pairingProofTest = + describe "Proof system check" $ + it "Should verify the test proof" $ do + let pp1 = Point 17899149025429256540670503450603840524526341770363252849540840688855727610005 6794888886586012478899094699714874747255503821264355877996121220781692052981 + let pp2 = Point + [4555160965165375385578562333880156835913586562443164694386914449127412126755, 16845220796436439159658389520454136502557317448502144055381480626643346396453] + [15740922883530394503972296892303076718862447518810507376564218784428077030254, 9794083499477745551885635852864140214811154513402172713835626845455029169909] + let pp3 = Point 2188339130061078784977610313576641337709587353412678866175084864819379744795 7363399164077520072321162032202323356331016580445157674442815097597932017402 + let inp = [293440811465879871736579011234159205259, 82735329187654304797954025540247337640, 1125899906842623, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1] + pp1 `shouldSatisfy` (`isOnCurve` b1) + pp2 `shouldSatisfy` (`isOnCurve` b2) + pp3 `shouldSatisfy` (`isOnCurve` b1) + verifyProof pp1 pp2 pp3 inp `shouldBe` True + + +-- Tests from: +-- https://github.com/ethereum/py_pairing/blob/master/tests/test_bn128.py +pairingLibTest :: TestTree +pairingLibTest = + testGroup "pairing lib tests" $ + it "passes basic field arithmetic for Fq" $ do + Fq 2 * Fq 2 `shouldBe` Fq 4 + Fq 2 / Fq 7 + Fq 9 / Fq 7 `shouldBe` Fq 11 / Fq 7 + Fq 2 * Fq 7 + Fq 9 * Fq 7 `shouldBe` Fq 11 * Fq 7 + Fq 9 ^ fieldModulus `shouldBe` Fq 9 + it "passes basic field arithmetic for Fq2" $ do + let x :: Fq2 = [1, 0] + let f :: Fq2 = [1, 2] + let fpx :: Fq2 = [2, 2] + x + f `shouldBe` fpx + f / f `shouldBe` 1 + 1 / f + x / f `shouldBe` (1 + x) / f + 1 * f + x * f `shouldBe` (1 + x) * f + x ^ (fieldModulus ^ (2 :: Int) - 1) `shouldBe` 1 + it "passes basic field arithmetic for FQ12" $ do + let x :: Fq12 = [1] + f :: Fq12 = [[[1, 2], [3, 4], [5, 6]], [[7, 8], [9, 10], [11, 12]]] + fpx :: Fq12 = [[[2, 2], [3, 4], [5, 6]], [[7, 8], [9, 10], [11, 12]]] + x + f `shouldBe` fpx + f / f `shouldBe` 1 + 1 / f + x / f `shouldBe` (1 + x) / f + 1 * f + x * f `shouldBe` (1 + x) * f + x ^ (fieldModulus ^ (2 :: Int) - 1) `shouldBe` 1 + it "passes basic elliptic curve operations for G1" $ do + add (add (double g1) g1) g1 `shouldBe` double (double g1) + double g1 `shouldNotBe` g1 + add (multiply g1 9) (multiply g1 5) `shouldBe` add (multiply g1 12) (multiply g1 2) + multiply g1 curveOrder `shouldBe` CurveInf + it "passes basic elliptic curve operations for G2" $ do + add (add (double g2) g2) g2 `shouldBe` double (double g2) + double g2 `shouldNotBe` g2 + add (multiply g2 9) (multiply g2 5) `shouldBe` add (multiply g2 12) (multiply g2 2) + multiply g2 curveOrder `shouldBe` CurveInf + multiply g2 (2 * fieldModulus - curveOrder) `shouldNotBe` CurveInf + isOnCurve (multiply g2 9) b2 `shouldBe` True + it "passes basic pairing tests" $ do + -- Pairing operation on negated g1 + let pp1 = pairing g1 g2 + let pn1 = pairing (negatePt g1) g2 + pp1 * pn1 `shouldBe` 1 + + -- Pairing op negated in g2 + let np1 = pairing g1 (negatePt g2) + pp1 * np1 `shouldBe` 1 + np1 `shouldBe` pn1 + + -- Pairing output has correct order + pp1 ^ curveOrder `shouldBe` 1 + + -- Pairing bilinearity in g1 + let pp2 = pairing (multiply g1 2) g2 + pp1 * pp1 `shouldBe` pp2 + + -- Pairing is non-degenerate + (pp1 /= pp2) && (pp1 /= np1) && (pp2 /= np1) `shouldBe` True + + -- Pairing bilinearity in G2 + let po2 = pairing g1 (multiply g2 2) + pp1 * pp1 `shouldBe` po2 + + -- Composite check + let p3 = pairing (multiply g1 37) (multiply g2 27) + let po3 = pairing (multiply g1 999) g2 + p3 `shouldBe` po3 + + + + +spec :: TestTree +spec = do + pairingLibTest + pairingGenTest + pairingProofTest + describe "pairing tests" $ do + it "pairing smoke test" $ do + let a :: Integer = 2 + let b :: Integer = 3 + + pairing p1 p2 `shouldBe` pt' + + pairing (multiply p1 a) (multiply p2 b) + `shouldBe` pow (pairing p1 p2) (a * b) + + +-- Verifying proof contract tests + +data VerifyingKey + = VerifyingKey + { _alfa1 :: G1 + , _beta2 :: G2 + , _gamma2 :: G2 + , _delta2 :: G2 + , _ic :: [G1] + } deriving (Show, Eq) + +data Proof + = Proof + { _proofA :: G1 + , _proofB :: G2 + , _proofC :: G1 } + deriving (Show, Eq) + +-- Verifying key from Solidity code +-- NOTE: When porting over solidity code, +-- their representation of points in Fq2 are backwards (that is, 5+2x is represented as [2, 5] and not [5, 2]). +-- +solVerifyingKey :: VerifyingKey +solVerifyingKey = + VerifyingKey alfa1 beta2 gamma2 delta2 ic + where + alfa1 = Point + 20491192805390485299153009773594534940189261866228447918068658471970481763042 + 9383485363053290200918347156157836566562967994039712273449902621266178545958 + beta2 = Point + [ 6375614351688725206403948262868962793625744043794305715222011528459656738731 + , 4252822878758300859123897981450591353533073413197771768651442665752259397132] + [ 10505242626370262277552901082094356697409835680220590971873171140371331206856 + , 21847035105528745403288232691147584728191162732299865338377159692350059136679 + ] + gamma2 = Point + [ 10857046999023057135944570762232829481370756359578518086990519993285655852781 + , 11559732032986387107991004021392285783925812861821192530917403151452391805634 + ] + [ 8495653923123431417604973247489272438418190587263600148770280649306958101930 + , 4082367875863433681332203403145435568316851327593401208105741076214120093531 + ] + delta2 = Point + [ 16809031008450260338666218659281275370828342486329981864349494337906939571887 + , 14264224196899353800543367999525075765943744025449601386425105981609273614701] + [ 11890256881228627469373664690032300678627026600164400771388911741873652827176 + , 19575774426779481952987745556743272872528397589822551825491193352706249147828] + ic = + [ Point 703628372913608924678229163876049246019207425954662225921071872483627421722 12211995813319149655177018938770234811518560618061207904053494967754185713570 + , Point 245257359888022973124621370122921842349425470670527924595405093609495308747 16424211039905278739428973076501641419102983596574674938829868639077765818142 + , Point 11110164462478062380497336442107420783806541677398299686522715666379498138472 11772875621558518653532220728777759671658134704623077088185806874340215959359 + , Point 18074393405015025057791386123633410704735277649988577562824116025859630543119 6512362579817099053449579131846840340322546772440905776424666285439665971742 + , Point 16324035526312367325456640773935782752062271159753322602146362004262088969135 1959877669644004327327941905732419844609901799055849407390385762919820073782 + , Point 7958732978061398276873406529212832852529841068044035448997300713023105585033 17143584956740843297694279539007817220119917091654840292522900244927912727369 + , Point 19790616331302654635046558077934057923437716290995001520546062733967158884432 3876239317603061711287361903875372717184929107501147494633374979429019396018 + , Point 14590717951490734152256639590507997933809755442616725401381713035954026634761 3225155507246149008951243692824143870155533409045696678069139586430835695226 + , Point 8650680088861200059927247719422818384661114515347998151694550511594524540419 9638849577460518420520485529873913372767621068985215869067476349645606505077 + , Point 17562317824746836410714834945198951796768727084595092618069846988441315688042 19452027031432595136507137552742780122072574021124781097949079775870562190348 + , Point 13182231104070542193327121010898638946743037034726286337778578885258172200370 757187892995880849330492963674577612574015215504544964795700288326850257327 + , Point 14409932519884296032513716882778643894210345146972579810764887578771580357222 814882272533738805340475214361663264998713952212684412413716253117631329790 + , Point 12509202143372575765947197406153125630356821791569394199509048702081149394252 7737627039987972603153686057063377754848525136672116479087023797531609007397 + , Point 8407744049840718757455802166031970590203865445336729285031156887247294225651 188049909694651097938181392474312752814356026969638293041076738773396096245 + , Point 334110586971536499255771782557320020258112908015957001506636732710862874984 16580656581000952485971124280378233725304032835996723142898957560222784358519 + , Point 7727226277603419079704813924510379012883865378360151539308685989224075286070 12912566309035429310049884735227185094569540217854933912859497659097301533657 + , Point 7681998061757907807252614087798324369243677279399770153101699113400315047554 17481742211680301513436042099326808806059638013948490790089189392596297352637 + , Point 12569417065062182916398142101141299032330235062582799620914438471333638326044 17523163572024314338870129158401181066960544407476643264775649919375538750903 + , Point 20366720006081427400904331708710783224493502999618856932501475384256136971442 12984908039677137046692512896720328898650869058550411984382690230037651160819 + , Point 8428544296631560843765157901673529267885840366893744558046063361202851291828 16289478447662297604149997612134385555472387391722487532370257859531844209269 ] + +-- Proof code ported over from the solidity contract (without the weird boolean misdirection) +-- function verifyProof( +-- uint[2] memory a, +-- uint[2][2] memory b, +-- uint[2] memory c, +-- uint[19] memory input +-- ) public view returns (bool r) { +-- Proof memory proof; +-- proof.A = Pairing.G1Point(a[0], a[1]); +-- proof.B = Pairing.G2Point([b[0][0], b[0][1]], [b[1][0], b[1][1]]); +-- proof.C = Pairing.G1Point(c[0], c[1]); +-- uint[] memory inputValues = new uint[](input.length); +-- for(uint i = 0; i < input.length; i++){ +-- inputValues[i] = input[i]; +-- } +-- if (verify(inputValues, proof) == 0) { +-- return true; +-- } else { +-- return false; +-- } +-- } +verifyProof + :: G1 -- Proof A + -> G2 -- Proof B + -> G1 -- Proof C + -> [Integer] + -> Bool +verifyProof pp1 pp2 pp3 inp = let + p = Proof pp1 pp2 pp3 + in verify inp p + +{- +Verify function ported over from Solidity + +function verify(uint[] memory input, Proof memory proof) internal view returns (uint) { + uint256 snark_scalar_field = 21888242871839275222246405745257275088548364400416034343698204186575808495617; + VerifyingKey memory vk = verifyingKey(); + require(input.length + 1 == vk.IC.length,"verifier-bad-input"); + // Compute the linear combination vk_x + Pairing.G1Point memory vk_x = Pairing.G1Point(0, 0); + for (uint i = 0; i < input.length; i++) { + require(input[i] < snark_scalar_field,"verifier-gte-snark-scalar-field"); + vk_x = Pairing.addition(vk_x, Pairing.scalar_mul(vk.IC[i + 1], input[i])); + } + vk_x = Pairing.addition(vk_x, vk.IC[0]); + if (!Pairing.pairingProd4( + Pairing.negate(proof.A), proof.B, + vk.alfa1, vk.beta2, + vk_x, vk.gamma2, + proof.C, vk.delta2 + )) return 1; + return 0; + } +-} +verify :: [Integer] -> Proof -> Bool +verify inp p = let + initial = CurveInf + vk_x = foldl' (\pt (i, kpt) -> add pt (multiply kpt i)) initial (zip inp (drop 1 (_ic solVerifyingKey))) + vk_x' = add vk_x (head (_ic solVerifyingKey)) + in pairingCheck + [ (negatePt (_proofA p), _proofB p) + , (_alfa1 solVerifyingKey, _beta2 solVerifyingKey) + , (vk_x', _gamma2 solVerifyingKey) + , (_proofC p, _delta2 solVerifyingKey)] + diff --git a/pact-core.cabal b/pact-core.cabal index 873e663fd..ad81c96de 100644 --- a/pact-core.cabal +++ b/pact-core.cabal @@ -84,9 +84,23 @@ common pact-core-common NumericUnderscores TypeOperators +-- internal crypto lirbary +library pact-core-crypto + import: pact-core-common + hs-source-dirs: crypto + + exposed-modules: + Pact.Core.Crypto.Hash.Poseidon + Pact.Core.Crypto.Pairing + Pact.Core.Crypto.Pairing.Fields + library import: pact-core-common hs-source-dirs: pact-core + + build-depends: + pact-core:pact-core-crypto + build-tool-depends: , alex:alex , happy:happy @@ -134,7 +148,6 @@ library Pact.Core.Principal Pact.Core.Namespace Pact.Core.RuntimeParsers - Pact.Core.Pairing -- Syntax modules Pact.Core.Syntax.ParseTree @@ -162,6 +175,10 @@ library Pact.Core.Repl.Runtime.ReplBuiltin Pact.Core.Repl.Compile + -- Crypto + + + library typed-core import: pact-core-common hs-source-dirs: typed-core @@ -268,8 +285,12 @@ test-suite core-tests , tasty , tasty-hunit , tasty-hedgehog + , groups + , semirings + , pact-core:pact-core-crypto other-modules: , Pact.Core.Test.ReplTests , Pact.Core.Test.LexerParserTests , Pact.Core.Test.LexerTests + , Pact.Core.Test.ZkTests diff --git a/pact-core/Pact/Core/Builtin.hs b/pact-core/Pact/Core/Builtin.hs index ca8daa2ac..1b1c5e032 100644 --- a/pact-core/Pact/Core/Builtin.hs +++ b/pact-core/Pact/Core/Builtin.hs @@ -199,6 +199,12 @@ data RawBuiltin | RawNamespace | RawDefineNamespace | RawDescribeNamespace + -- ZK + | RawZkPairingCheck + | RawZKScalarMult + | RawZkPointAdd + -- Poseidon Hackachain + | RawPoseidonHashHackachain deriving (Eq, Show, Ord, Bounded, Enum) instance HasObjectOps RawBuiltin where @@ -332,6 +338,10 @@ rawBuiltinToText = \case RawNamespace -> "namespace" RawDefineNamespace -> "define-namespace" RawDescribeNamespace -> "describe-namespace" + RawZkPairingCheck -> "pairing-check" + RawZKScalarMult -> "scalar-mult" + RawZkPointAdd -> "point-add" + RawPoseidonHashHackachain -> "poseidon-hash-hack-a-chain" instance IsBuiltin RawBuiltin where builtinName = NativeName . rawBuiltinToText @@ -466,6 +476,10 @@ instance IsBuiltin RawBuiltin where RawNamespace -> 1 RawDefineNamespace -> 3 RawDescribeNamespace -> 1 + RawZkPairingCheck -> 2 + RawZKScalarMult -> 3 + RawZkPointAdd -> 3 + RawPoseidonHashHackachain -> 1 rawBuiltinNames :: [Text] diff --git a/pact-core/Pact/Core/Environment/Types.hs b/pact-core/Pact/Core/Environment/Types.hs index f55d8bd22..5a06de041 100644 --- a/pact-core/Pact/Core/Environment/Types.hs +++ b/pact-core/Pact/Core/Environment/Types.hs @@ -107,7 +107,7 @@ data EvalEnv b i -- ^ The list of provided keys and scoped capabilities , _eePactDb :: PactDb b i -- ^ The Pact database store - , _eeMsgBody :: EnvData PactValue + , _eeMsgBody :: ObjectData PactValue -- ^ Transaction-provided data , _eeHash :: Hash -- ^ The transaction hash @@ -190,7 +190,7 @@ defaultEvalEnv pdb m = EvalEnv { _eeMsgSigs = mempty , _eePactDb = pdb - , _eeMsgBody = EnvData mempty + , _eeMsgBody = ObjectData mempty , _eeHash = defaultPactHash , _eePublicData = def , _eeDefPactStep = Nothing diff --git a/pact-core/Pact/Core/IR/Desugar.hs b/pact-core/Pact/Core/IR/Desugar.hs index f8b5e526e..23cbc356c 100644 --- a/pact-core/Pact/Core/IR/Desugar.hs +++ b/pact-core/Pact/Core/IR/Desugar.hs @@ -177,6 +177,8 @@ desugarAppArityRaw f i RawReadMsg [] = App (Builtin (f RawReadMsgDefault) i) [] i desugarAppArityRaw f i RawDefineKeySet [e1] = App (Builtin (f RawDefineKeysetData) i) [e1] i +desugarAppArityRaw f i RawPoseidonHashHackachain li = + App (Builtin (f RawPoseidonHashHackachain) i )[(ListLit li i)] i desugarAppArityRaw f i b args = App (Builtin (f b) i) args i diff --git a/pact-core/Pact/Core/IR/Eval/RawBuiltin.hs b/pact-core/Pact/Core/IR/Eval/RawBuiltin.hs index a2d125b4d..f9bcf05ea 100644 --- a/pact-core/Pact/Core/IR/Eval/RawBuiltin.hs +++ b/pact-core/Pact/Core/IR/Eval/RawBuiltin.hs @@ -24,7 +24,7 @@ module Pact.Core.IR.Eval.RawBuiltin -- import Control.Lens hiding (from, to, op, parts) -import Control.Monad(when, unless, foldM) +import Control.Monad import Control.Monad.IO.Class import Data.Attoparsec.Text(parseOnly) import Data.Containers.ListUtils(nubOrd) @@ -35,6 +35,7 @@ import Data.Decimal(roundTo', Decimal) import Data.Vector(Vector) import Data.Maybe(isJust, maybeToList) import Numeric(showIntAtBase) +import qualified Control.Lens as Lens import qualified Data.Vector as V import qualified Data.Vector.Algorithms.Intro as V import qualified Data.Text as T @@ -43,8 +44,9 @@ import qualified Data.Map.Strict as M import qualified Data.Set as S import qualified Data.Char as Char import qualified Data.ByteString as BS +import qualified GHC.Exts as Exts import qualified Pact.Time as PactTime -import qualified Pact.Core.Trans.TOps as Musl +import qualified Data.Poly as Poly import Pact.Core.Builtin import Pact.Core.Literal @@ -59,7 +61,8 @@ import Pact.Core.DefPacts.Types import Pact.Core.Environment import Pact.Core.Capabilities import Pact.Core.Namespace -import qualified Pact.Core.Principal as Pr +import Pact.Core.Crypto.Pairing +import Pact.Core.Crypto.Hash.Poseidon import Pact.Core.IR.Term import Pact.Core.IR.Eval.Runtime @@ -67,13 +70,14 @@ import Pact.Core.StableEncoding import Pact.Core.IR.Eval.CEK import qualified Pact.Core.Pretty as Pretty +import qualified Pact.Core.Principal as Pr +import qualified Pact.Core.Trans.TOps as Musl ---------------------------------------------------------------------- -- Our builtin definitions start here ---------------------------------------------------------------------- --- -- Todo: runtime error unaryIntFn :: (IsBuiltin b, MonadEval b i m) => (Integer -> Integer) -> NativeFunction b i m unaryIntFn op info b cont handler _env = \case [VLiteral (LInteger i)] -> returnCEKValue cont handler (VLiteral (LInteger (op i))) @@ -697,7 +701,7 @@ keysetRefGuard info b cont handler env = \case coreReadInteger :: (IsBuiltin b, MonadEval b i m) => NativeFunction b i m coreReadInteger info b cont handler _env = \case [VString s] -> do - EnvData envData <- viewEvalEnv eeMsgBody + ObjectData envData <- viewEvalEnv eeMsgBody case M.lookup (Field s) envData of Just (PInteger p) -> returnCEKValue cont handler (VInteger p) _ -> returnCEK cont handler (VError "read-integer failure" info) @@ -706,19 +710,19 @@ coreReadInteger info b cont handler _env = \case readMsg :: (IsBuiltin b, MonadEval b i m) => NativeFunction b i m readMsg info b cont handler _env = \case [VString s] -> do - EnvData envData <- viewEvalEnv eeMsgBody + ObjectData envData <- viewEvalEnv eeMsgBody case M.lookup (Field s) envData of Just pv -> returnCEKValue cont handler (VPactValue pv) _ -> returnCEK cont handler (VError "read-integer failure" info) [] -> do - EnvData envData <- viewEvalEnv eeMsgBody + ObjectData envData <- viewEvalEnv eeMsgBody returnCEKValue cont handler (VObject envData) args -> argsError info b args coreReadDecimal :: (IsBuiltin b, MonadEval b i m) => NativeFunction b i m coreReadDecimal info b cont handler _env = \case [VString s] -> do - EnvData envData <- viewEvalEnv eeMsgBody + ObjectData envData <- viewEvalEnv eeMsgBody case M.lookup (Field s) envData of Just (PDecimal p) -> returnCEKValue cont handler (VDecimal p) _ -> returnCEK cont handler (VError "read-integer failure" info) @@ -727,7 +731,7 @@ coreReadDecimal info b cont handler _env = \case coreReadString :: (IsBuiltin b, MonadEval b i m) => NativeFunction b i m coreReadString info b cont handler _env = \case [VString s] -> do - EnvData envData <- viewEvalEnv eeMsgBody + ObjectData envData <- viewEvalEnv eeMsgBody case M.lookup (Field s) envData of Just (PString p) -> returnCEKValue cont handler (VString p) _ -> returnCEK cont handler (VError "read-integer failure" info) @@ -735,7 +739,7 @@ coreReadString info b cont handler _env = \case readKeyset' :: (MonadEval b i m) => T.Text -> m (Maybe (KeySet FullyQualifiedName)) readKeyset' ksn = do - EnvData envData <- viewEvalEnv eeMsgBody + ObjectData envData <- viewEvalEnv eeMsgBody case M.lookup (Field ksn) envData of Just (PObject dat) -> parseObj dat where @@ -1610,6 +1614,207 @@ coreDescribeNamespace info b cont handler _env = \case -- ZK defns -- ------------------------- +ensureOnCurve :: (Num p, Eq p, MonadEval b i m) => i -> CurvePoint p -> p -> m () +ensureOnCurve info p bp = unless (isOnCurve p bp) $ failInvariant info "Point not on curve" + +toG1 :: ObjectData PactValue -> Maybe G1 +toG1 (ObjectData obj) = do + px <- fromIntegral <$> preview (ix (Field "x") . _PLiteral . _LInteger) obj + py <- fromIntegral <$> preview (ix (Field "y") . _PLiteral . _LInteger) obj + if px == 0 && py == 0 then pure CurveInf + else pure (Point px py) + +fromG1 :: G1 -> ObjectData PactValue +fromG1 CurveInf = ObjectData pts + where + pts = M.fromList + [ (Field "x", PLiteral (LInteger 0)) + , (Field "y", PLiteral (LInteger 0))] +fromG1 (Point x y) = ObjectData pts + where + pts = + M.fromList + [ (Field "x", PLiteral (LInteger (fromIntegral x))) + , (Field "y", PLiteral (LInteger (fromIntegral y)))] + +toG2 :: ObjectData PactValue -> Maybe G2 +toG2 (ObjectData om) = do + pxl <- preview (ix (Field "x") . _PList) om + px <- traverse (preview (_PLiteral . _LInteger . Lens.to fromIntegral)) pxl + pyl <- preview (ix (Field "y") . _PList) om + py <- traverse (preview (_PLiteral . _LInteger . Lens.to fromIntegral)) pyl + let px' = Exts.fromList (V.toList px) + py' = Exts.fromList (V.toList py) + if px' == 0 && py' == 0 then pure CurveInf + else pure (Point px' py') + +fromG2 :: G2 -> ObjectData PactValue +fromG2 CurveInf = ObjectData pts + where + pts = + M.fromList + [ (Field "x", PList (V.fromList [PLiteral (LInteger 0)])) + , (Field "y", PList (V.fromList [PLiteral (LInteger 0)]))] +fromG2 (Point x y) = ObjectData pts + where + toPactPt (Extension e) = let + elems' = fmap (PInteger . fromIntegral) (Poly.unPoly e) + in PList elems' + x' = toPactPt x + y' = toPactPt y + pts = + M.fromList + [ (Field "x", x') + , (Field "y", y')] + + +-- pairingCheckDef :: NativeDef +-- pairingCheckDef = +-- defRNative "pairing-check" pairingCheck' (funType tTyBool [("points-g1", TyList a), ("points-g2", TyList b)]) +-- [] +-- "Perform pairing and final exponentiation points in G1 and G2 in BN254, check if the result is 1" +-- where +-- a = mkTyVar "a" [] +-- b = mkTyVar "b" [] +-- pairingCheck':: RNativeFun e +-- pairingCheck' i [TList p1s _ _, TList p2s _ _] = do +-- g1s <- traverse termToG1 $ G.toList p1s +-- g2s <- traverse termToG2 $ G.toList p2s +-- traverse_ (`ensureOnCurve` b1) g1s +-- traverse_ (`ensureOnCurve` b2) g2s +-- let pairs = zip g1s g2s +-- _ <- computeGas (Right i) (GZKArgs (Pairing (length pairs))) +-- pure $ toTerm $ pairingCheck pairs +-- where +-- ensureOnCurve :: (Num p, Eq p) => CurvePoint p -> p -> Eval e () +-- ensureOnCurve p bp = unless (isOnCurve p bp) $ evalError' i "Point not on curve" +-- termToG1 (TObject o _) = toG1 i o +-- termToG1 _ = evalError' i "not a point" +-- termToG2 (TObject o _) = toG2 i o +-- termToG2 _ = evalError' i "not a point" +-- pairingCheck' i as = argsError i as + +zkPairingCheck :: (IsBuiltin b, MonadEval b i m) => NativeFunction b i m +zkPairingCheck info b cont handler _env = \case + args@[VList p1s, VList p2s] -> do + g1s <- maybe (argsError info b args) pure (traverse (preview _PObject >=> (toG1 . ObjectData)) p1s) + g2s <- maybe (argsError info b args) pure (traverse (preview _PObject >=> (toG2 . ObjectData)) p2s) + traverse_ (\p -> ensureOnCurve info p b1) g1s + traverse_ (\p -> ensureOnCurve info p b2) g2s + let pairs = zip (V.toList g1s) (V.toList g2s) + returnCEKValue cont handler $ VBool $ pairingCheck pairs + args -> argsError info b args + +-- curveOrder :: Integer +-- curveOrder = 21888242871839275222246405745257275088548364400416034343698204186575808495617 +-- scalarMul :: RNativeFun e +-- scalarMul i as@[TLiteral (LString ptTy) _ , TObject p1 _, (TLiteral (LInteger scalar) _) :: Term Name] = do +-- let scalar' = scalar `mod` curveOrder +-- case T.toLower ptTy of +-- "g1" -> do +-- p1' <- toG1 i p1 +-- unless (isOnCurve p1' b1) $ evalError' i "Point not on curve" +-- _ <- computeGas (Right i) (GZKArgs (ScalarMult ZKG1)) +-- let p2' = multiply p1' scalar' +-- pure $ TObject (fromG1 p2') def +-- "g2" -> do +-- p1' <- toG2 i p1 +-- unless (isOnCurve p1' b2) $ evalError' i "Point not on curve" +-- _ <- computeGas (Right i) (GZKArgs (ScalarMult ZKG2)) +-- let p2' = multiply p1' scalar' +-- pure $ TObject (fromG2 p2') def +-- _ -> argsError i as + +zkScalaMult :: (IsBuiltin b, MonadEval b i m) => NativeFunction b i m +zkScalaMult info b cont handler _env = \case + args@[VString ptTy, VObject p1, VInteger scalar] -> do + let scalar' = scalar `mod` curveOrder + case T.toLower ptTy of + "g1" -> do + p1' <- maybe (argsError info b args) pure $ toG1 (ObjectData p1) + unless (isOnCurve p1' b1) $ failInvariant info "Point not on curve" + let p2' = multiply p1' scalar' + ObjectData o = fromG1 p2' + returnCEKValue cont handler (VObject o) + "g2" -> do + p1' <- maybe (argsError info b args) pure $ toG2 (ObjectData p1) + unless (isOnCurve p1' b2) $ failInvariant info "Point not on curve" + let p2' = multiply p1' scalar' + ObjectData o = fromG2 p2' + returnCEKValue cont handler (VObject o) + _ -> argsError info b args + args -> argsError info b args + where + curveOrder :: Integer + curveOrder = 21888242871839275222246405745257275088548364400416034343698204186575808495617 + +zkPointAddition :: (IsBuiltin b, MonadEval b i m) => NativeFunction b i m +zkPointAddition info b cont handler _env = \case + args@[VString ptTy, VObject p1, VObject p2] -> do + case T.toLower ptTy of + "g1" -> do + p1' <- maybe (argsError info b args) pure $ toG1 (ObjectData p1) + p2' <- maybe (argsError info b args) pure $ toG1 (ObjectData p2) + unless (isOnCurve p1' b1 && isOnCurve p2' b1) $ failInvariant info "Point not on curve" + let p3' = add p1' p2' + ObjectData o = fromG1 p3' + returnCEKValue cont handler (VObject o) + "g2" -> do + p1' <- maybe (argsError info b args) pure $ toG2 (ObjectData p1) + p2' <- maybe (argsError info b args) pure $ toG2 (ObjectData p2) + unless (isOnCurve p1' b2 && isOnCurve p2' b2) $ failInvariant info "Point not on curve" + let p3' = add p1' p2' + ObjectData o = fromG2 p3' + returnCEKValue cont handler (VObject o) + _ -> argsError info b args + args -> argsError info b args + +-- pointAdditionDef :: NativeDef +-- pointAdditionDef = +-- defRNative "point-add" pactPointAdd (funType a [("type", tTyString), ("point1", a), ("point2", a)]) +-- [ "(point-add 'g1 {'x: 1, 'y: 2} {'x: 1, 'y: 2})" +-- ] "Add two points together that lie on the curve BN254. Point addition either in Fq or in Fq2" +-- where +-- a = mkTyVar "a" [] +-- pactPointAdd :: RNativeFun e +-- pactPointAdd i as@[TLiteral (LString ptTy) _ , TObject p1 _, (TObject p2 _) :: Term Name] = +-- case T.toLower ptTy of +-- "g1" -> do +-- p1' <- toG1 i p1 +-- p2' <- toG1 i p2 +-- unless (isOnCurve p1' b1 && isOnCurve p2' b1) $ evalError' i "Point not on curve" +-- _ <- computeGas (Right i) (GZKArgs (PointAdd ZKG1)) +-- let p3' = add p1' p2' +-- pure $ TObject (fromG1 p3') def +-- "g2" -> do +-- p1' <- toG2 i p1 +-- p2' <- toG2 i p2 +-- unless (isOnCurve p1' b2 && isOnCurve p2' b2) $ evalError' i "Point not on curve" +-- _ <- computeGas (Right i) (GZKArgs (PointAdd ZKG2)) +-- let p3' = add p1' p2' +-- pure $ TObject (fromG2 p3') def +-- _ -> argsError i as +-- pactPointAdd i as = argsError i as + +------ +-- Poseidon +-- + +poseidonHash :: (IsBuiltin b, MonadEval b i m) => NativeFunction b i m +poseidonHash info b cont handler _env = \case + [VList as] + | not (V.null as) && length as <= 8, + Just intArgs <- traverse (preview (_PLiteral . _LInteger)) as -> + returnCEKValue cont handler $ VInteger (poseidon (V.toList intArgs)) + args -> argsError info b args + -- poseidon' :: RNativeFun e + -- poseidon' i as + -- | not (null as) && length as <= 8, + -- Just intArgs <- traverse (preview _TLitInteger) as + -- = computeGas' i (GPoseidonHashHackAChain $ length as) $ + -- return $ toTerm $ poseidon intArgs + -- | otherwise = argsError i as + ----------------------------------- -- Builtin exports ----------------------------------- @@ -1741,3 +1946,7 @@ rawBuiltinRuntime = \case RawNamespace -> coreNamespace RawDefineNamespace -> coreDefineNamespace RawDescribeNamespace -> coreDescribeNamespace + RawZkPairingCheck -> zkPairingCheck + RawZKScalarMult -> zkScalaMult + RawZkPointAdd -> zkPointAddition + RawPoseidonHashHackachain -> poseidonHash diff --git a/pact-core/Pact/Core/PactValue.hs b/pact-core/Pact/Core/PactValue.hs index dd589f38e..d80482b35 100644 --- a/pact-core/Pact/Core/PactValue.hs +++ b/pact-core/Pact/Core/PactValue.hs @@ -9,8 +9,9 @@ module Pact.Core.PactValue , _PList , _PGuard , _PCapToken + , _PObject , checkPvType - , EnvData(..) + , ObjectData(..) , envMap , FQCapToken , pattern PInteger @@ -125,13 +126,13 @@ checkPvType ty = \case -newtype EnvData term - = EnvData { _envMap :: Map Field term } +newtype ObjectData term + = ObjectData { _envMap :: Map Field term } deriving (Eq, Show) envMap - :: Lens (EnvData term) - (EnvData term') + :: Lens (ObjectData term) + (ObjectData term') (Map Field term) (Map Field term') -envMap f (EnvData m) = fmap EnvData (f m) +envMap f (ObjectData m) = fmap ObjectData (f m) diff --git a/pact-core/Pact/Core/Repl/Runtime/ReplBuiltin.hs b/pact-core/Pact/Core/Repl/Runtime/ReplBuiltin.hs index 1e4707ffa..214f05430 100644 --- a/pact-core/Pact/Core/Repl/Runtime/ReplBuiltin.hs +++ b/pact-core/Pact/Core/Repl/Runtime/ReplBuiltin.hs @@ -189,7 +189,7 @@ envHash info b cont handler _env = \case envData :: (IsBuiltin b) => NativeFunction b SpanInfo (ReplM b) envData info b cont handler _env = \case [VObject o] -> do - let ed = EnvData o + let ed = ObjectData o (replEvalEnv . eeMsgBody) .= ed returnCEKValue cont handler VUnit args -> argsError info b args From 6c305f54fb6dafc64d089ca1525531d7f7b0c4bf Mon Sep 17 00:00:00 2001 From: jmcardon Date: Fri, 8 Dec 2023 12:13:40 -0500 Subject: [PATCH 08/20] Tops --- pact-core/Pact/Core/Trans/TOps.hs | 45 +++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 pact-core/Pact/Core/Trans/TOps.hs diff --git a/pact-core/Pact/Core/Trans/TOps.hs b/pact-core/Pact/Core/Trans/TOps.hs new file mode 100644 index 000000000..2a9a573af --- /dev/null +++ b/pact-core/Pact/Core/Trans/TOps.hs @@ -0,0 +1,45 @@ +{-# OPTIONS_GHC -Wno-unrecognised-pragmas #-} +{-# HLINT ignore "Use camelCase" #-} +-- | +-- Module : Pact.Native.Trans.TOps +-- Copyright : (C) 2022 John Wiegley +-- License : BSD-style (see the file LICENSE) +-- Maintainer : John Wiegley +-- +-- Operators and math built-ins. +-- + +module Pact.Core.Trans.TOps + ( trans_pow + , trans_exp + , trans_logBase + , trans_ln + , trans_sqrt + ) where + +foreign import ccall unsafe "musl_pow" + musl_pow :: Double -> Double -> Double + +foreign import ccall unsafe "musl_exp" + musl_exp :: Double -> Double + +foreign import ccall unsafe "musl_log" + musl_log :: Double -> Double + +foreign import ccall unsafe "musl_sqrt" + musl_sqrt :: Double -> Double + +trans_pow :: Double -> Double -> Double +trans_pow = musl_pow + +trans_exp :: Double -> Double +trans_exp = musl_exp + +trans_logBase :: Double -> Double -> Double +trans_logBase b x = musl_log x / musl_log b + +trans_ln :: Double -> Double +trans_ln = musl_log + +trans_sqrt :: Double -> Double +trans_sqrt = musl_sqrt From df1d84c6d4242286fe111c6a4c96a2f5d6449bb9 Mon Sep 17 00:00:00 2001 From: jmcardon Date: Fri, 8 Dec 2023 17:55:54 -0500 Subject: [PATCH 09/20] chain data tests --- pact-core-tests/Pact/Core/Test/ReplTests.hs | 2 +- pact-core-tests/Pact/Core/Test/ZkTests.hs | 159 +++++++++--------- pact-core-tests/PactCoreTests.hs | 4 + pact-core/Pact/Core/Builtin.hs | 5 +- pact-core/Pact/Core/Errors.hs | 2 - pact-core/Pact/Core/Gas.hs | 3 +- pact-core/Pact/Core/IR/Desugar.hs | 59 ++++++- pact-core/Pact/Core/IR/Eval/CEK.hs | 28 +-- pact-core/Pact/Core/IR/Eval/RawBuiltin.hs | 128 +++++--------- pact-core/Pact/Core/IR/Eval/Runtime/Types.hs | 4 +- pact-core/Pact/Core/Repl.hs | 11 +- .../Pact/Core/Repl/Runtime/ReplBuiltin.hs | 8 +- pact-core/Pact/Core/Semantics.md | 18 ++ 13 files changed, 234 insertions(+), 197 deletions(-) diff --git a/pact-core-tests/Pact/Core/Test/ReplTests.hs b/pact-core-tests/Pact/Core/Test/ReplTests.hs index bb719c723..b81a11e06 100644 --- a/pact-core-tests/Pact/Core/Test/ReplTests.hs +++ b/pact-core-tests/Pact/Core/Test/ReplTests.hs @@ -30,7 +30,7 @@ import Pact.Core.Errors tests :: IO TestTree tests = do files <- replTestFiles - pure $ testGroup "Core repl tests" (runFileReplTest <$> files) + pure $ testGroup "CoreReplTests" (runFileReplTest <$> files) replTestDir :: [Char] diff --git a/pact-core-tests/Pact/Core/Test/ZkTests.hs b/pact-core-tests/Pact/Core/Test/ZkTests.hs index 6dc89008d..4a33cbec7 100644 --- a/pact-core-tests/Pact/Core/Test/ZkTests.hs +++ b/pact-core-tests/Pact/Core/Test/ZkTests.hs @@ -2,7 +2,7 @@ {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ScopedTypeVariables #-} -module Pact.Core.Test.ZkTests (spec) where +module Pact.Core.Test.ZkTests (tests) where import Data.Group (pow) import Data.Field(Field) @@ -10,8 +10,10 @@ import Data.Foldable(foldl') import Hedgehog import qualified Hedgehog.Gen as Gen import qualified Hedgehog.Range as Range -import Pact.Native.Pairing +import Pact.Core.Crypto.Pairing.Fields +import Pact.Core.Crypto.Pairing import Test.Tasty +import Test.Tasty.HUnit import Test.Tasty.Hedgehog p1 :: CurvePoint Fq @@ -66,127 +68,130 @@ genG2 :: Gen G2 genG2 = genCurvePoint g2 pairingGenTest :: TestTree -pairingGenTest = modifyMaxSuccess (const 20) $ - describe "Curve generated tests" $ do - it "Generates a point on the curve, and obeys the pairing function" $ hedgehog $ do - p1' <- forAll genG1 - assert (isOnCurve g1 b1) - addDoubling p1' - - p2' <- forAll genG2 - assert (isOnCurve g2 b2) - addDoubling p2' - - r1 <- forAll $ Gen.integral (Range.constant 0 1000) - r2 <- forAll $ Gen.integral (Range.constant 0 1000) - pairing (multiply p1' r1) (multiply p2' r2) === pow (pairing p1' p2') (r1 * r2) - where - addDoubling pt = - add (add (double pt) pt) pt === double (double pt) +pairingGenTest = testProperty "Generates a point on the curve, and obeys the pairing function" $ withTests 20 $ property $ do + p1' <- forAll genG1 + Hedgehog.assert (isOnCurve g1 b1) + addDoubling p1' + + p2' <- forAll genG2 + Hedgehog.assert (isOnCurve g2 b2) + addDoubling p2' + + r1 <- forAll $ Gen.integral (Range.constant 0 1000) + r2 <- forAll $ Gen.integral (Range.constant 0 1000) + pairing (multiply p1' r1) (multiply p2' r2) === pow (pairing p1' p2') (r1 * r2) + where + addDoubling pt = + add (add (double pt) pt) pt === double (double pt) pairingProofTest :: TestTree -pairingProofTest = - describe "Proof system check" $ - it "Should verify the test proof" $ do +pairingProofTest = testGroup "Proof system check" $ pure $ + testCase "Should verify the test proof" $ do let pp1 = Point 17899149025429256540670503450603840524526341770363252849540840688855727610005 6794888886586012478899094699714874747255503821264355877996121220781692052981 let pp2 = Point [4555160965165375385578562333880156835913586562443164694386914449127412126755, 16845220796436439159658389520454136502557317448502144055381480626643346396453] [15740922883530394503972296892303076718862447518810507376564218784428077030254, 9794083499477745551885635852864140214811154513402172713835626845455029169909] let pp3 = Point 2188339130061078784977610313576641337709587353412678866175084864819379744795 7363399164077520072321162032202323356331016580445157674442815097597932017402 let inp = [293440811465879871736579011234159205259, 82735329187654304797954025540247337640, 1125899906842623, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1] - pp1 `shouldSatisfy` (`isOnCurve` b1) - pp2 `shouldSatisfy` (`isOnCurve` b2) - pp3 `shouldSatisfy` (`isOnCurve` b1) - verifyProof pp1 pp2 pp3 inp `shouldBe` True + assertBool "pp1 on curve" (isOnCurve pp1 b1) + assertBool "pp2 on curve" (isOnCurve pp2 b2) + assertBool "pp3 on curve" (isOnCurve pp3 b1) + verifyProof pp1 pp2 pp3 inp @=? True -- Tests from: -- https://github.com/ethereum/py_pairing/blob/master/tests/test_bn128.py pairingLibTest :: TestTree pairingLibTest = - testGroup "pairing lib tests" $ - it "passes basic field arithmetic for Fq" $ do - Fq 2 * Fq 2 `shouldBe` Fq 4 - Fq 2 / Fq 7 + Fq 9 / Fq 7 `shouldBe` Fq 11 / Fq 7 - Fq 2 * Fq 7 + Fq 9 * Fq 7 `shouldBe` Fq 11 * Fq 7 - Fq 9 ^ fieldModulus `shouldBe` Fq 9 - it "passes basic field arithmetic for Fq2" $ do + testGroup "pairing lib tests" + [ basicArith + , basicFieldArith + , basicFieldArithFq12 + , curveOpG1 + , curveOpG2 + , basicPairing] + where + basicArith = testCase "passes basic field arithmetic for Fq" $ do + Fq 2 * Fq 2 @=? Fq 4 + Fq 2 / Fq 7 + Fq 9 / Fq 7 @=? Fq 11 / Fq 7 + Fq 2 * Fq 7 + Fq 9 * Fq 7 @=? Fq 11 * Fq 7 + Fq 9 ^ fieldModulus @=? Fq 9 + basicFieldArith = testCase "passes basic field arithmetic for Fq2" $ do let x :: Fq2 = [1, 0] let f :: Fq2 = [1, 2] let fpx :: Fq2 = [2, 2] - x + f `shouldBe` fpx - f / f `shouldBe` 1 - 1 / f + x / f `shouldBe` (1 + x) / f - 1 * f + x * f `shouldBe` (1 + x) * f - x ^ (fieldModulus ^ (2 :: Int) - 1) `shouldBe` 1 - it "passes basic field arithmetic for FQ12" $ do + x + f @=? fpx + f / f @=? 1 + 1 / f + x / f @=? (1 + x) / f + 1 * f + x * f @=? (1 + x) * f + x ^ (fieldModulus ^ (2 :: Int) - 1) @=? 1 + basicFieldArithFq12 = testCase "passes basic field arithmetic for FQ12" $ do let x :: Fq12 = [1] f :: Fq12 = [[[1, 2], [3, 4], [5, 6]], [[7, 8], [9, 10], [11, 12]]] fpx :: Fq12 = [[[2, 2], [3, 4], [5, 6]], [[7, 8], [9, 10], [11, 12]]] - x + f `shouldBe` fpx - f / f `shouldBe` 1 - 1 / f + x / f `shouldBe` (1 + x) / f - 1 * f + x * f `shouldBe` (1 + x) * f - x ^ (fieldModulus ^ (2 :: Int) - 1) `shouldBe` 1 - it "passes basic elliptic curve operations for G1" $ do - add (add (double g1) g1) g1 `shouldBe` double (double g1) - double g1 `shouldNotBe` g1 - add (multiply g1 9) (multiply g1 5) `shouldBe` add (multiply g1 12) (multiply g1 2) - multiply g1 curveOrder `shouldBe` CurveInf - it "passes basic elliptic curve operations for G2" $ do - add (add (double g2) g2) g2 `shouldBe` double (double g2) - double g2 `shouldNotBe` g2 - add (multiply g2 9) (multiply g2 5) `shouldBe` add (multiply g2 12) (multiply g2 2) - multiply g2 curveOrder `shouldBe` CurveInf - multiply g2 (2 * fieldModulus - curveOrder) `shouldNotBe` CurveInf - isOnCurve (multiply g2 9) b2 `shouldBe` True - it "passes basic pairing tests" $ do + x + f @=? fpx + f / f @=? 1 + 1 / f + x / f @=? (1 + x) / f + 1 * f + x * f @=? (1 + x) * f + x ^ (fieldModulus ^ (2 :: Int) - 1) @=? 1 + curveOpG1 = testCase "passes basic elliptic curve operations for G1" $ do + add (add (double g1) g1) g1 @=? double (double g1) + assertBool "double g1 /= g1" $ (double g1 /= g1) + add (multiply g1 9) (multiply g1 5) @=? add (multiply g1 12) (multiply g1 2) + multiply g1 curveOrder @=? CurveInf + curveOpG2 = testCase "passes basic elliptic curve operations for G2" $ do + add (add (double g2) g2) g2 @=? double (double g2) + assertBool "double g2 /= g2" $ (double g2 /= g2) + add (multiply g2 9) (multiply g2 5) @=? add (multiply g2 12) (multiply g2 2) + multiply g2 curveOrder @=? CurveInf + assertBool "g2 field mod test" $ multiply g2 (2 * fieldModulus - curveOrder) /= CurveInf + isOnCurve (multiply g2 9) b2 @=? True + basicPairing = testCase "passes basic pairing tests" $ do -- Pairing operation on negated g1 let pp1 = pairing g1 g2 let pn1 = pairing (negatePt g1) g2 - pp1 * pn1 `shouldBe` 1 + pp1 * pn1 @=? 1 -- Pairing op negated in g2 let np1 = pairing g1 (negatePt g2) - pp1 * np1 `shouldBe` 1 - np1 `shouldBe` pn1 + pp1 * np1 @=? 1 + np1 @=? pn1 -- Pairing output has correct order - pp1 ^ curveOrder `shouldBe` 1 + pp1 ^ curveOrder @=? 1 -- Pairing bilinearity in g1 let pp2 = pairing (multiply g1 2) g2 - pp1 * pp1 `shouldBe` pp2 + pp1 * pp1 @=? pp2 -- Pairing is non-degenerate - (pp1 /= pp2) && (pp1 /= np1) && (pp2 /= np1) `shouldBe` True + (pp1 /= pp2) && (pp1 /= np1) && (pp2 /= np1) @=? True -- Pairing bilinearity in G2 let po2 = pairing g1 (multiply g2 2) - pp1 * pp1 `shouldBe` po2 + pp1 * pp1 @=? po2 -- Composite check let p3 = pairing (multiply g1 37) (multiply g2 27) let po3 = pairing (multiply g1 999) g2 - p3 `shouldBe` po3 - - + p3 @=? po3 -spec :: TestTree -spec = do - pairingLibTest - pairingGenTest - pairingProofTest - describe "pairing tests" $ do - it "pairing smoke test" $ do +pairingSmokeTest :: TestTree +pairingSmokeTest = testCase "pairing smoke test" $ do let a :: Integer = 2 let b :: Integer = 3 + pairing p1 p2 @=? pt' + pairing (multiply p1 a) (multiply p2 b) + @=? pow (pairing p1 p2) (a * b) - pairing p1 p2 `shouldBe` pt' +tests :: TestTree +tests = testGroup "ZKPairingTests" $ + [ pairingLibTest + , pairingGenTest + , pairingProofTest + , pairingSmokeTest] - pairing (multiply p1 a) (multiply p2 b) - `shouldBe` pow (pairing p1 p2) (a * b) -- Verifying proof contract tests diff --git a/pact-core-tests/PactCoreTests.hs b/pact-core-tests/PactCoreTests.hs index 931a11dc0..ecd780781 100644 --- a/pact-core-tests/PactCoreTests.hs +++ b/pact-core-tests/PactCoreTests.hs @@ -5,6 +5,8 @@ import Test.Tasty import qualified Pact.Core.Test.ReplTests as ReplTests import qualified Pact.Core.Test.LexerParserTests as LexerParserTests import qualified Pact.Core.Test.LexerTests as LexerTests +import qualified Pact.Core.Test.ZkTests as ZkTests +import qualified Pact.Core.Test.PoseidonTests as PoseidonTests main :: IO () main = do @@ -13,4 +15,6 @@ main = do [ replTests , LexerTests.tests , LexerParserTests.tests + , ZkTests.tests + , PoseidonTests.tests ] diff --git a/pact-core/Pact/Core/Builtin.hs b/pact-core/Pact/Core/Builtin.hs index 1b1c5e032..74ae15154 100644 --- a/pact-core/Pact/Core/Builtin.hs +++ b/pact-core/Pact/Core/Builtin.hs @@ -75,8 +75,6 @@ data RawBuiltin | RawAbs | RawPow -- Boolean Ops - -- | RawAnd - -- | RawOr | RawNot -- Equality and Comparisons | RawEq @@ -199,6 +197,7 @@ data RawBuiltin | RawNamespace | RawDefineNamespace | RawDescribeNamespace + | RawChainData -- ZK | RawZkPairingCheck | RawZKScalarMult @@ -342,6 +341,7 @@ rawBuiltinToText = \case RawZKScalarMult -> "scalar-mult" RawZkPointAdd -> "point-add" RawPoseidonHashHackachain -> "poseidon-hash-hack-a-chain" + RawChainData -> "chain-data" instance IsBuiltin RawBuiltin where builtinName = NativeName . rawBuiltinToText @@ -480,6 +480,7 @@ instance IsBuiltin RawBuiltin where RawZKScalarMult -> 3 RawZkPointAdd -> 3 RawPoseidonHashHackachain -> 1 + RawChainData -> 0 rawBuiltinNames :: [Text] diff --git a/pact-core/Pact/Core/Errors.hs b/pact-core/Pact/Core/Errors.hs index 41439f687..c2dc6681d 100644 --- a/pact-core/Pact/Core/Errors.hs +++ b/pact-core/Pact/Core/Errors.hs @@ -50,8 +50,6 @@ data LexerError instance Exception LexerError - - instance Pretty LexerError where pretty = ("Lexical Error: " <>) . \case LexicalError c1 c2 -> diff --git a/pact-core/Pact/Core/Gas.hs b/pact-core/Pact/Core/Gas.hs index 45faec3fa..f923479ee 100644 --- a/pact-core/Pact/Core/Gas.hs +++ b/pact-core/Pact/Core/Gas.hs @@ -24,6 +24,7 @@ module Pact.Core.Gas ) where import Control.Lens +import Data.Decimal(Decimal) import Data.Word(Word64) import Data.Monoid(Sum(..)) import Data.Text(Text) @@ -39,7 +40,7 @@ newtype Gas deriving (Semiring, Enum) via Word64 type GasLimit = Gas -type GasPrice = Rational +type GasPrice = Decimal data NodeType = VarNode diff --git a/pact-core/Pact/Core/IR/Desugar.hs b/pact-core/Pact/Core/IR/Desugar.hs index 23cbc356c..d6a57587a 100644 --- a/pact-core/Pact/Core/IR/Desugar.hs +++ b/pact-core/Pact/Core/IR/Desugar.hs @@ -167,6 +167,25 @@ desugarAppArityRaw -> RawBuiltin -> [Term name Lisp.Type builtin info] -> Term name Lisp.Type builtin info +-- Todo: this presents a really, _really_ annoying case for the map overload :( +-- Jose: I am unsure how to fix this so far, but it does not break any tests. +-- that is: +-- prod: +-- pact> (map (- 1) [1, 2, 3]) +-- [0 -1 -2] +-- core: +-- pact>(map (- 1) [1 2 3]) +-- (interactive):1:0: Native evaluation error for native map, received incorrect argument(s) of type(s) [integer] , [list] +-- 1 | (map (- 1) [1 2 3]) +-- | ^^^^^^^^^^^^^^^^^^^ + +-- pact>(map (lambda (x) (- 1 x)) [1 2 3]) +-- [0, -1, -2] +-- this is because prod simply suspends the static term without figuring out the arity which is being used +-- to apply, vs core which does not attempt to do this, and picks an overload eagerly and statically. +-- in 99% of cases this is fine, but we overloaded `-` to be completely different functions. +desugarAppArityRaw f i RawSub [e1] = + App (Builtin (f RawNegate) i) ([e1]) i desugarAppArityRaw f i RawEnumerate [e1, e2, e3] = App (Builtin (f RawEnumerateStepN) i) ([e1, e2, e3]) i desugarAppArityRaw f i RawSelect [e1, e2, e3] = @@ -528,10 +547,12 @@ termSCC currM currDefns = \case DN _ -> mempty Lam _ args e _ -> let currDefns' = foldl' (\s t -> S.delete (_argName t) s) currDefns args - in termSCC currM currDefns' e + tySCC = foldMap (argSCC currM currDefns) args + in tySCC <> termSCC currM currDefns' e Let arg e1 e2 _ -> let currDefns' = S.delete (_argName arg) currDefns - in S.union (termSCC currM currDefns e1) (termSCC currM currDefns' e2) + tySCC = argSCC currM currDefns arg + in tySCC <> termSCC currM currDefns e1 <> termSCC currM currDefns' e2 App fn apps _ -> S.union (termSCC currM currDefns fn) (foldMap (termSCC currM currDefns) apps) Sequence e1 e2 _ -> S.union (termSCC currM currDefns e1) (termSCC currM currDefns e2) @@ -589,19 +610,30 @@ typeSCC currM currDefs = \case | S.member n' currDefs && mn' == currM -> S.singleton n' | otherwise -> mempty +argSCC :: ModuleName -> Set Text -> Arg DesugarType -> Set Text +argSCC currM currDefs (Arg _ ty) = case ty of + Just t -> typeSCC currM currDefs t + Nothing -> mempty + defunSCC :: ModuleName -> Set Text -> Defun ParsedName DesugarType b i -> Set Text -defunSCC mn cd = termSCC mn cd . _dfunTerm +defunSCC mn cd df = + let tscc = termSCC mn cd (_dfunTerm df) + argScc = foldMap (argSCC mn cd) (_dfunArgs df) + in tscc <> argScc <> maybe mempty (typeSCC mn cd) (_dfunRType df) defConstSCC :: ModuleName -> Set Text -> DefConst ParsedName DesugarType b i -> Set Text -defConstSCC mn cd = foldMap (termSCC mn cd) . _dcTerm +defConstSCC mn cd dc = + let tscc = foldMap (termSCC mn cd) (_dcTerm dc) + tyscc = maybe mempty (typeSCC mn cd) (_dcType dc) + in tscc <> tyscc defTableSCC :: ModuleName @@ -618,18 +650,31 @@ defCapSCC -> DefCap ParsedName DesugarType b i1 -> Set Text defCapSCC mn cd dc = - case _dcapMeta dc of + let argsScc = foldMap (argSCC mn cd) (_dcapArgs dc) + rtypeScc = maybe mempty (typeSCC mn cd) (_dcapRType dc) + in argsScc <> rtypeScc <> case _dcapMeta dc of DefManaged (DefManagedMeta _ (FQParsed pn)) -> termSCC mn cd (_dcapTerm dc) <> parsedNameSCC mn cd pn _ -> termSCC mn cd (_dcapTerm dc) defPactSCC + :: ModuleName + -> Set Text + -> DefPact ParsedName DesugarType b i + -> Set Text +defPactSCC mn cd dp = + let argsScc = foldMap (argSCC mn cd) (_dpArgs dp) + rtScc = maybe mempty (typeSCC mn cd) (_dpRetType dp) + stepsScc = foldMap (defPactStepSCC mn cd) (_dpSteps dp) + in argsScc <> rtScc <> stepsScc + +defPactStepSCC :: ModuleName -> Set Text -> Step ParsedName DesugarType b i -> Set Text -defPactSCC mn cd = \case +defPactStepSCC mn cd = \case Step step mSteps -> S.union (termSCC mn cd step) (stepsSCC mSteps) StepWithRollback step rollback mSteps -> S.unions $ stepsSCC mSteps : [termSCC mn cd step, termSCC mn cd rollback] @@ -647,7 +692,7 @@ defSCC mn cd = \case DConst d -> defConstSCC mn cd d DCap dc -> defCapSCC mn cd dc DSchema ds -> foldMap (typeSCC mn cd) ( _dsSchema ds) - DPact dp -> foldMap (defPactSCC mn cd) (_dpSteps dp) + DPact dp -> defPactSCC mn cd dp DTable dt -> defTableSCC mn cd dt ifDefSCC diff --git a/pact-core/Pact/Core/IR/Eval/CEK.hs b/pact-core/Pact/Core/IR/Eval/CEK.hs index 582ac3929..5c0016ea7 100644 --- a/pact-core/Pact/Core/IR/Eval/CEK.hs +++ b/pact-core/Pact/Core/IR/Eval/CEK.hs @@ -192,20 +192,20 @@ evalCEK cont handler env (CapabilityForm cf info) = do capFrame = CreateUserGuardFrame fqn cont' = CapInvokeC env info xs [] capFrame cont in evalCEK cont' handler env x -evalCEK cont handler env (ListLit ts _) = do +evalCEK cont handler env (ListLit ts info) = do chargeNodeGas ListNode case ts of [] -> returnCEKValue cont handler (VList mempty) - x:xs -> evalCEK (ListC env xs [] cont) handler env x + x:xs -> evalCEK (ListC env info xs [] cont) handler env x evalCEK cont handler env (Try catchExpr rest _) = do errState <- evalStateToErrorState <$> getEvalState let handler' = CEKHandler env catchExpr cont errState handler let env' = readOnlyEnv env evalCEK Mt handler' env' rest -evalCEK cont handler env (ObjectLit o _) = +evalCEK cont handler env (ObjectLit o info) = case o of (f, term):rest -> do - let cont' = ObjC env f rest [] cont + let cont' = ObjC env info f rest [] cont evalCEK cont' handler env term [] -> returnCEKValue cont handler (VObject mempty) -- Error terms ignore the current cont @@ -625,7 +625,7 @@ evalCap info currCont handler env origToken@(CapToken fqn args) modCont contbody lookupFqName mpfqn >>= \case -- We found the manager function, evaluate it and commit the argument. Just (Dfun dfun) -> do - mparam <- maybe (failInvariant def "Managed param does not exist at index") pure (args ^? ix managedIx) + mparam <- maybe (failInvariant info "Managed param does not exist at index") pure (args ^? ix managedIx) evaluate mpfqn (_dfunTerm dfun) pv mparam >>= \case EvalValue res -> do result <- enforcePactValue info res @@ -659,7 +659,7 @@ evalCap info currCont handler env origToken@(CapToken fqn args) modCont contbody -- emitCapability info origToken evalCEK sfCont handler inCapEnv capBody -- evalWithStackFrame info cont' handler inCapEnv capStackFrame Nothing capBody - _ -> failInvariant def "Invalid managed cap type" + _ -> failInvariant info "Invalid managed cap type" evaluate fqn' term managed value = case term of Lam _ lamargs body i -> do -- Todo: `applyLam` here gives suboptimal errors @@ -816,7 +816,7 @@ createUserGuard info cont handler fqn args = Just _ -> returnCEK cont handler (VError "create-user-guard pointing to non-guard" info) Nothing -> - failInvariant def "User guard pointing to no defn" + failInvariant info "User guard pointing to no defn" returnCEK @@ -988,25 +988,25 @@ returnCEKValue (CapPopC st cont) handler v = case st of caps' = over (_head . csComposed) (++ csList) (tail caps) setEvalState (esCaps . csSlots) caps' returnCEKValue cont handler VUnit -returnCEKValue (ListC env args vals cont) handler v = do - pv <- enforcePactValue def v +returnCEKValue (ListC env info args vals cont) handler v = do + pv <- enforcePactValue info v case args of [] -> returnCEKValue cont handler (VList (V.fromList (reverse (pv:vals)))) e:es -> - evalCEK (ListC env es (pv:vals) cont) handler env e -returnCEKValue (ObjC env currfield fs vs cont) handler v = do - v' <- enforcePactValue def v + evalCEK (ListC env info es (pv:vals) cont) handler env e +returnCEKValue (ObjC env info currfield fs vs cont) handler v = do + v' <- enforcePactValue info v let fields = (currfield,v'):vs case fs of (f', term):fs' -> - let cont' = ObjC env f' fs' fields cont + let cont' = ObjC env info f' fs' fields cont in evalCEK cont' handler env term [] -> returnCEKValue cont handler (VObject (M.fromList (reverse fields))) returnCEKValue (EnforceErrorC info _) handler v = case v of VString err -> returnCEK Mt handler (VError err info) - _ -> failInvariant def "enforce function did not return a string" + _ -> failInvariant info "enforce function did not return a string" -- Discard the value of running a user guard, no error occured, so -- return true returnCEKValue (UserGuardC cont) handler _v = diff --git a/pact-core/Pact/Core/IR/Eval/RawBuiltin.hs b/pact-core/Pact/Core/IR/Eval/RawBuiltin.hs index f9bcf05ea..a32422d95 100644 --- a/pact-core/Pact/Core/IR/Eval/RawBuiltin.hs +++ b/pact-core/Pact/Core/IR/Eval/RawBuiltin.hs @@ -61,6 +61,7 @@ import Pact.Core.DefPacts.Types import Pact.Core.Environment import Pact.Core.Capabilities import Pact.Core.Namespace +import Pact.Core.Gas import Pact.Core.Crypto.Pairing import Pact.Core.Crypto.Hash.Poseidon @@ -1610,6 +1611,48 @@ coreDescribeNamespace info b cont handler _env = \case args -> argsError info b args +-- chainDataDef :: NativeDef +-- chainDataDef = defRNative "chain-data" chainData +-- (funType (tTyObject pcTy) []) +-- ["(chain-data)"] +-- "Get transaction public metadata. Returns an object with 'chain-id', 'block-height', \ +-- \'block-time', 'prev-block-hash', 'sender', 'gas-limit', 'gas-price', and 'gas-fee' fields." +-- where +-- pcTy = TyUser (snd chainDataSchema) +-- chainData :: RNativeFun e +-- chainData _ [] = do +-- PublicData{..} <- view eePublicData + +-- let PublicMeta{..} = _pdPublicMeta +-- toTime = toTerm . fromPosixTimestampMicros + +-- pure $ toTObject TyAny def +-- [ (cdChainId, toTerm _pmChainId) +-- , (cdBlockHeight, toTerm _pdBlockHeight) +-- , (cdBlockTime, toTime _pdBlockTime) +-- , (cdPrevBlockHash, toTerm _pdPrevBlockHash) +-- , (cdSender, toTerm _pmSender) +-- , (cdGasLimit, toTerm _pmGasLimit) +-- , (cdGasPrice, toTerm _pmGasPrice) +-- ] +-- chainData i as = argsError i as + +coreChainData :: (IsBuiltin b, MonadEval b i m) => NativeFunction b i m +coreChainData info b cont handler _env = \case + [] -> do + PublicData publicMeta blockHeight blockTime prevBh <- viewEvalEnv eePublicData + let (PublicMeta cid sender (Gas gasLimit) gasPrice _ttl _creationTime) = publicMeta + let fields = M.fromList [ (cdChainId, PString (_chainId cid)) + , (cdBlockHeight, PInteger (fromIntegral blockHeight)) + , (cdBlockTime, PTime (PactTime.fromPosixTimestampMicros blockTime)) + , (cdPrevBlockHash, PString prevBh) + , (cdSender, PString sender) + , (cdGasLimit, PInteger (fromIntegral gasLimit)) + , (cdGasPrice, PDecimal gasPrice)] + returnCEKValue cont handler (VObject fields) + args -> argsError info b args + + -- ------------------------- -- ZK defns -- ------------------------- @@ -1668,32 +1711,6 @@ fromG2 (Point x y) = ObjectData pts , (Field "y", y')] --- pairingCheckDef :: NativeDef --- pairingCheckDef = --- defRNative "pairing-check" pairingCheck' (funType tTyBool [("points-g1", TyList a), ("points-g2", TyList b)]) --- [] --- "Perform pairing and final exponentiation points in G1 and G2 in BN254, check if the result is 1" --- where --- a = mkTyVar "a" [] --- b = mkTyVar "b" [] --- pairingCheck':: RNativeFun e --- pairingCheck' i [TList p1s _ _, TList p2s _ _] = do --- g1s <- traverse termToG1 $ G.toList p1s --- g2s <- traverse termToG2 $ G.toList p2s --- traverse_ (`ensureOnCurve` b1) g1s --- traverse_ (`ensureOnCurve` b2) g2s --- let pairs = zip g1s g2s --- _ <- computeGas (Right i) (GZKArgs (Pairing (length pairs))) --- pure $ toTerm $ pairingCheck pairs --- where --- ensureOnCurve :: (Num p, Eq p) => CurvePoint p -> p -> Eval e () --- ensureOnCurve p bp = unless (isOnCurve p bp) $ evalError' i "Point not on curve" --- termToG1 (TObject o _) = toG1 i o --- termToG1 _ = evalError' i "not a point" --- termToG2 (TObject o _) = toG2 i o --- termToG2 _ = evalError' i "not a point" --- pairingCheck' i as = argsError i as - zkPairingCheck :: (IsBuiltin b, MonadEval b i m) => NativeFunction b i m zkPairingCheck info b cont handler _env = \case args@[VList p1s, VList p2s] -> do @@ -1705,26 +1722,6 @@ zkPairingCheck info b cont handler _env = \case returnCEKValue cont handler $ VBool $ pairingCheck pairs args -> argsError info b args --- curveOrder :: Integer --- curveOrder = 21888242871839275222246405745257275088548364400416034343698204186575808495617 --- scalarMul :: RNativeFun e --- scalarMul i as@[TLiteral (LString ptTy) _ , TObject p1 _, (TLiteral (LInteger scalar) _) :: Term Name] = do --- let scalar' = scalar `mod` curveOrder --- case T.toLower ptTy of --- "g1" -> do --- p1' <- toG1 i p1 --- unless (isOnCurve p1' b1) $ evalError' i "Point not on curve" --- _ <- computeGas (Right i) (GZKArgs (ScalarMult ZKG1)) --- let p2' = multiply p1' scalar' --- pure $ TObject (fromG1 p2') def --- "g2" -> do --- p1' <- toG2 i p1 --- unless (isOnCurve p1' b2) $ evalError' i "Point not on curve" --- _ <- computeGas (Right i) (GZKArgs (ScalarMult ZKG2)) --- let p2' = multiply p1' scalar' --- pure $ TObject (fromG2 p2') def --- _ -> argsError i as - zkScalaMult :: (IsBuiltin b, MonadEval b i m) => NativeFunction b i m zkScalaMult info b cont handler _env = \case args@[VString ptTy, VObject p1, VInteger scalar] -> do @@ -1769,36 +1766,9 @@ zkPointAddition info b cont handler _env = \case _ -> argsError info b args args -> argsError info b args --- pointAdditionDef :: NativeDef --- pointAdditionDef = --- defRNative "point-add" pactPointAdd (funType a [("type", tTyString), ("point1", a), ("point2", a)]) --- [ "(point-add 'g1 {'x: 1, 'y: 2} {'x: 1, 'y: 2})" --- ] "Add two points together that lie on the curve BN254. Point addition either in Fq or in Fq2" --- where --- a = mkTyVar "a" [] --- pactPointAdd :: RNativeFun e --- pactPointAdd i as@[TLiteral (LString ptTy) _ , TObject p1 _, (TObject p2 _) :: Term Name] = --- case T.toLower ptTy of --- "g1" -> do --- p1' <- toG1 i p1 --- p2' <- toG1 i p2 --- unless (isOnCurve p1' b1 && isOnCurve p2' b1) $ evalError' i "Point not on curve" --- _ <- computeGas (Right i) (GZKArgs (PointAdd ZKG1)) --- let p3' = add p1' p2' --- pure $ TObject (fromG1 p3') def --- "g2" -> do --- p1' <- toG2 i p1 --- p2' <- toG2 i p2 --- unless (isOnCurve p1' b2 && isOnCurve p2' b2) $ evalError' i "Point not on curve" --- _ <- computeGas (Right i) (GZKArgs (PointAdd ZKG2)) --- let p3' = add p1' p2' --- pure $ TObject (fromG2 p3') def --- _ -> argsError i as --- pactPointAdd i as = argsError i as - ------- +----------------------------------- -- Poseidon --- +----------------------------------- poseidonHash :: (IsBuiltin b, MonadEval b i m) => NativeFunction b i m poseidonHash info b cont handler _env = \case @@ -1807,13 +1777,6 @@ poseidonHash info b cont handler _env = \case Just intArgs <- traverse (preview (_PLiteral . _LInteger)) as -> returnCEKValue cont handler $ VInteger (poseidon (V.toList intArgs)) args -> argsError info b args - -- poseidon' :: RNativeFun e - -- poseidon' i as - -- | not (null as) && length as <= 8, - -- Just intArgs <- traverse (preview _TLitInteger) as - -- = computeGas' i (GPoseidonHashHackAChain $ length as) $ - -- return $ toTerm $ poseidon intArgs - -- | otherwise = argsError i as ----------------------------------- -- Builtin exports @@ -1950,3 +1913,4 @@ rawBuiltinRuntime = \case RawZKScalarMult -> zkScalaMult RawZkPointAdd -> zkPointAddition RawPoseidonHashHackachain -> poseidonHash + RawChainData -> coreChainData diff --git a/pact-core/Pact/Core/IR/Eval/Runtime/Types.hs b/pact-core/Pact/Core/IR/Eval/Runtime/Types.hs index b1a845d73..2a6da11ae 100644 --- a/pact-core/Pact/Core/IR/Eval/Runtime/Types.hs +++ b/pact-core/Pact/Core/IR/Eval/Runtime/Types.hs @@ -366,11 +366,11 @@ data Cont b i m -- Known as a single argument it will not construct a needless closure | SeqC (CEKEnv b i m) (EvalTerm b i) (Cont b i m) -- ^ Sequencing expression, holding the next term to evaluate - | ListC (CEKEnv b i m) [EvalTerm b i] [PactValue] (Cont b i m) + | ListC (CEKEnv b i m) i [EvalTerm b i] [PactValue] (Cont b i m) -- ^ Continuation for list elements | CondC (CEKEnv b i m) i (CondFrame b i) (Cont b i m) -- ^ Continuation for conditionals with lazy semantics - | ObjC (CEKEnv b i m) Field [(Field, EvalTerm b i)] [(Field, PactValue)] (Cont b i m) + | ObjC (CEKEnv b i m) i Field [(Field, EvalTerm b i)] [(Field, PactValue)] (Cont b i m) -- ^ Continuation for the current object field being evaluated, and the already evaluated pairs | CapInvokeC (CEKEnv b i m) i [EvalTerm b i] [PactValue] (CapFrame b i) (Cont b i m) -- ^ Capability special form frams that eva diff --git a/pact-core/Pact/Core/Repl.hs b/pact-core/Pact/Core/Repl.hs index 934b4fbc1..40d7aba8f 100644 --- a/pact-core/Pact/Core/Repl.hs +++ b/pact-core/Pact/Core/Repl.hs @@ -24,7 +24,6 @@ import System.Console.Haskeline import Data.Default import Data.IORef import qualified Data.Text as T -import qualified Data.Text.Encoding as T import qualified Data.Set as Set import Pact.Core.Persistence @@ -98,15 +97,13 @@ main = do loop RAExecuteExpr src -> catch' $ do let display' rcv = runInputT replSettings (displayOutput rcv) - let sourceBs = T.encodeUtf8 src - lift (replCurrSource .= defaultSrc{_scPayload=sourceBs}) - eout <- lift (tryError (interpretReplProgram (SourceCode "(interactive)" sourceBs) display')) + lift (replCurrSource .= defaultSrc{_scPayload=src}) + eout <- lift (tryError (interpretReplProgram (SourceCode "(interactive)" src) display')) case eout of Right _ -> pure () Left err -> do - SourceCode srcFile currSrc <- lift (use replCurrSource) - let srcText = T.decodeUtf8 currSrc - let rs = ReplSource (T.pack srcFile) srcText + SourceCode srcFile currSrcText <- lift (use replCurrSource) + let rs = ReplSource (T.pack srcFile) currSrcText lift (replCurrSource .= defaultSrc) outputStrLn (T.unpack (replError rs err)) loop diff --git a/pact-core/Pact/Core/Repl/Runtime/ReplBuiltin.hs b/pact-core/Pact/Core/Repl/Runtime/ReplBuiltin.hs index 214f05430..a3e822ffc 100644 --- a/pact-core/Pact/Core/Repl/Runtime/ReplBuiltin.hs +++ b/pact-core/Pact/Core/Repl/Runtime/ReplBuiltin.hs @@ -39,6 +39,8 @@ import Pact.Core.Namespace import Pact.Core.Repl.Utils +import qualified Pact.Time as PactTime + prettyShowValue :: CEKValue b i m -> Text prettyShowValue = \case VPactValue p -> renderText p @@ -202,7 +204,7 @@ envChainData info b cont handler _env = \case where go pd [] = do replEvalEnv . eePublicData .= pd - returnCEKValue cont handler VUnit + returnCEKValue cont handler (VString "Updated public metadata") go pd ((k,v):rest) = case v of PInteger i | k == cdGasLimit -> @@ -211,7 +213,7 @@ envChainData info b cont handler _env = \case go (set pdBlockHeight (fromInteger i) pd) rest PDecimal i | k == cdGasPrice -> - go (set (pdPublicMeta . pmGasPrice) (toRational i) pd) rest + go (set (pdPublicMeta . pmGasPrice) i pd) rest PString s | k == cdChainId -> go (set (pdPublicMeta . pmChainId) (ChainId s) pd) rest @@ -219,6 +221,8 @@ envChainData info b cont handler _env = \case go (set (pdPublicMeta . pmSender) s pd) rest | k == cdPrevBlockHash -> go (set pdPrevBlockHash s pd) rest + PTime time + | k == cdBlockTime -> go (set pdBlockTime (PactTime.toPosixTimestampMicros time) pd) rest _ -> returnCEK cont handler (VError ("envChainData: bad public metadata value for key: " <> _field k) info) args -> argsError info b args diff --git a/pact-core/Pact/Core/Semantics.md b/pact-core/Pact/Core/Semantics.md index 1cb7d05c7..860be9a79 100644 --- a/pact-core/Pact/Core/Semantics.md +++ b/pact-core/Pact/Core/Semantics.md @@ -70,3 +70,21 @@ Bullet points that are not filled are potential tasks - [ ] EvalResult and EvalInput-type API +## Natives + +### at +- [x] Object case implemented +- [x] List case implemented +- [ ] Gas + +### base64-decode +- [x] implemented +- [ ] Gas + +### base64-encode +- [x] implemented +- [ ] Gas + +### bind +- [x] implemented +- [ ] Gas From 4c684dee1817ced926c218a5ae7e3be745f52fa3 Mon Sep 17 00:00:00 2001 From: jmcardon Date: Sat, 9 Dec 2023 13:12:11 -0500 Subject: [PATCH 10/20] wip covering semantics --- pact-core-tests/pact-tests/lambda.repl | 41 +- pact-core/Pact/Core/Builtin.hs | 25 + pact-core/Pact/Core/Hash.hs | 2 +- pact-core/Pact/Core/IR/Desugar.hs | 10 + pact-core/Pact/Core/IR/Eval/RawBuiltin.hs | 114 +++- pact-core/Pact/Core/IR/Eval/Runtime/Types.hs | 5 + pact-core/Pact/Core/IR/ModuleHashing.hs | 1 + pact-core/Pact/Core/IR/Term.hs | 2 + pact-core/Pact/Core/Names.hs | 2 +- pact-core/Pact/Core/PactValue.hs | 12 + pact-core/Pact/Core/Semantics.md | 551 ++++++++++++++++++- pact-core/Pact/Core/Type.hs | 52 +- 12 files changed, 749 insertions(+), 68 deletions(-) diff --git a/pact-core-tests/pact-tests/lambda.repl b/pact-core-tests/pact-tests/lambda.repl index 44caf3216..30e16a8dd 100644 --- a/pact-core-tests/pact-tests/lambda.repl +++ b/pact-core-tests/pact-tests/lambda.repl @@ -75,24 +75,23 @@ (fold (lambda (x y) (+ x y)) 0 [1, 2, 3]) ) -; (expect "inline lambdas function within natives: compose" -; 2 -; (let -; ((compose (lambda (f g a) (f (g a))))) -; (compose (lambda (x) (+ x 1)) (lambda (x) (+ x 1)) 0)) -; ) - -; (expect "inline lambdas function within natives: and?" -; true -; (and? (lambda (x) (< x 20)) (lambda (x) (<= x 15)) 15) -; ) - -; (expect "inline lambdas function within natives: or?" -; true -; (or? (lambda (x) (> x 20)) (lambda (x) (<= x 15)) 15) -; ) - -; (expect "inline lambdas function within natives: not?" -; false -; (not? (lambda (x) (> x 20)) 22) -; ) +(expect "inline lambdas function within natives: compose" + 2 + (compose (lambda (x) (+ x 1)) (lambda (x) (+ x 1)) 0) +) + +(expect "inline lambdas function within natives: and?" + true + (and? (lambda (x) (< x 20)) (lambda (x) (<= x 15)) 15) +) + +(expect "inline lambdas function within natives: or?" + true + (or? (lambda (x) (> x 20)) (lambda (x) (<= x 15)) 15) +) + +(expect "inline lambdas function within natives: not?" + false + (not? (lambda (x) (> x 20)) 22) +) + diff --git a/pact-core/Pact/Core/Builtin.hs b/pact-core/Pact/Core/Builtin.hs index 74ae15154..0fe399367 100644 --- a/pact-core/Pact/Core/Builtin.hs +++ b/pact-core/Pact/Core/Builtin.hs @@ -94,6 +94,9 @@ data RawBuiltin | RawRound | RawCeiling | RawFloor + | RawRoundPrec + | RawCeilingPrec + | RawFloorPrec -- Fractional | RawExp | RawLn @@ -141,6 +144,7 @@ data RawBuiltin | RawB64Decode | RawStrToList | RawYield + | RawYieldToChain | RawResume | RawBind | RawRequireCapability @@ -198,12 +202,17 @@ data RawBuiltin | RawDefineNamespace | RawDescribeNamespace | RawChainData + | RawIsCharset + | RawPactId -- ZK | RawZkPairingCheck | RawZKScalarMult | RawZkPointAdd -- Poseidon Hackachain | RawPoseidonHashHackachain + -- Misc + | RawTypeOf + | RawDec deriving (Eq, Show, Ord, Bounded, Enum) instance HasObjectOps RawBuiltin where @@ -241,6 +250,9 @@ rawBuiltinToText = \case RawRound -> "round" RawCeiling -> "ceiling" RawFloor -> "floor" + RawRoundPrec -> "round-prec" + RawCeilingPrec -> "ceiling-prec" + RawFloorPrec -> "floor-prec" -- Fractional RawExp -> "exp" RawLn -> "ln" @@ -289,6 +301,7 @@ rawBuiltinToText = \case RawB64Decode -> "base64-decode" RawStrToList -> "str-to-list" RawYield -> "yield" + RawYieldToChain -> "yield-to-chain" RawResume -> "resume" RawBind -> "bind" RawRequireCapability -> "require-capability" @@ -342,6 +355,10 @@ rawBuiltinToText = \case RawZkPointAdd -> "point-add" RawPoseidonHashHackachain -> "poseidon-hash-hack-a-chain" RawChainData -> "chain-data" + RawIsCharset -> "is-charset" + RawPactId -> "pact-id" + RawTypeOf -> "typeof" + RawDec -> "dec" instance IsBuiltin RawBuiltin where builtinName = NativeName . rawBuiltinToText @@ -376,6 +393,9 @@ instance IsBuiltin RawBuiltin where RawRound -> 1 RawCeiling -> 1 RawFloor -> 1 + RawRoundPrec -> 2 + RawCeilingPrec -> 2 + RawFloorPrec -> 2 -- Fractional -> RawExp -> 1 RawLn -> 1 @@ -428,6 +448,7 @@ instance IsBuiltin RawBuiltin where RawB64Decode -> 1 RawStrToList -> 1 RawYield -> 1 + RawYieldToChain -> 2 RawResume -> 1 RawBind -> 2 RawRequireCapability -> 1 @@ -481,6 +502,10 @@ instance IsBuiltin RawBuiltin where RawZkPointAdd -> 3 RawPoseidonHashHackachain -> 1 RawChainData -> 0 + RawIsCharset -> 2 + RawPactId -> 0 + RawTypeOf -> 1 + RawDec -> 1 rawBuiltinNames :: [Text] diff --git a/pact-core/Pact/Core/Hash.hs b/pact-core/Pact/Core/Hash.hs index d1a876108..e36768991 100644 --- a/pact-core/Pact/Core/Hash.hs +++ b/pact-core/Pact/Core/Hash.hs @@ -114,7 +114,7 @@ fromB64UrlUnpaddedText bs = case decodeBase64UrlUnpadded bs of Right bs' -> case T.decodeUtf8' bs' of Left _ -> Left $ "Base64URL decode failed: invalid unicode" Right t -> Right t - Left e -> Left $ "Base64URL decode failed: " ++ e + Left _ -> Left $ "Base64URL decode failed" newtype ModuleHash = ModuleHash { _mhHash :: Hash } diff --git a/pact-core/Pact/Core/IR/Desugar.hs b/pact-core/Pact/Core/IR/Desugar.hs index d6a57587a..876396462 100644 --- a/pact-core/Pact/Core/IR/Desugar.hs +++ b/pact-core/Pact/Core/IR/Desugar.hs @@ -192,12 +192,16 @@ desugarAppArityRaw f i RawSelect [e1, e2, e3] = App (Builtin (f RawSelectWithFields) i) ([e1, e2, e3]) i desugarAppArityRaw f i RawSort [e1, e2] = App (Builtin (f RawSortObject) i) [e1, e2] i +desugarAppArityRaw f i RawStrToInt [e1, e2] = + App (Builtin (f RawStrToIntBase) i) [e1, e2] i desugarAppArityRaw f i RawReadMsg [] = App (Builtin (f RawReadMsgDefault) i) [] i desugarAppArityRaw f i RawDefineKeySet [e1] = App (Builtin (f RawDefineKeysetData) i) [e1] i desugarAppArityRaw f i RawPoseidonHashHackachain li = App (Builtin (f RawPoseidonHashHackachain) i )[(ListLit li i)] i +desugarAppArityRaw f i RawYield [e1, e2] = + App (Builtin (f RawYieldToChain) i) [e1, e2] i desugarAppArityRaw f i b args = App (Builtin (f b) i) args i @@ -252,11 +256,17 @@ desugarLispTerm = \case let c1 = Arg cvar1 Nothing c2 = Arg cvar2 Nothing pure $ Lam AnonLamInfo (c1 :| [c2]) (Var (BN (BareName cvar1)) i) i + | n == BareName "identity" -> do + let c1 = Arg ivar1 Nothing + pure $ Lam AnonLamInfo (c1 :| []) (Var (BN (BareName ivar1)) i) i + | n == BareName "CHARSET_ASCII" -> pure (Constant (LInteger 0) i) + | n == BareName "CHARSET_LATIN1" -> pure (Constant (LInteger 1) i) | otherwise -> pure (Var (BN n) i) where cvar1 = "#constantlyA1" cvar2 = "#constantlyA2" + ivar1 = "#identityA1" Lisp.Var n i -> pure (Var n i) Lisp.Block nel i -> do nel' <- traverse desugarLispTerm nel diff --git a/pact-core/Pact/Core/IR/Eval/RawBuiltin.hs b/pact-core/Pact/Core/IR/Eval/RawBuiltin.hs index a32422d95..2e187a353 100644 --- a/pact-core/Pact/Core/IR/Eval/RawBuiltin.hs +++ b/pact-core/Pact/Core/IR/Eval/RawBuiltin.hs @@ -31,7 +31,7 @@ import Data.Containers.ListUtils(nubOrd) import Data.Bits import Data.Either(isLeft, isRight) import Data.Foldable(foldl', traverse_, toList) -import Data.Decimal(roundTo', Decimal) +import Data.Decimal(roundTo', Decimal, DecimalRaw(..)) import Data.Vector(Vector) import Data.Maybe(isJust, maybeToList) import Numeric(showIntAtBase) @@ -96,7 +96,10 @@ binaryIntFn op info b cont handler _env = \case roundingFn :: (IsBuiltin b, MonadEval b i m) => (Rational -> Integer) -> NativeFunction b i m roundingFn op info b cont handler _env = \case - [VLiteral (LDecimal i)] -> returnCEKValue cont handler (VLiteral (LInteger (truncate (roundTo' op 0 i)))) + [VLiteral (LDecimal d)] -> + returnCEKValue cont handler (VLiteral (LInteger (truncate (roundTo' op 0 d)))) + [VDecimal d, VInteger prec] -> + returnCEKValue cont handler (VLiteral (LDecimal (roundTo' op (fromIntegral prec) d))) args -> argsError info b args {-# INLINE roundingFn #-} @@ -176,6 +179,7 @@ rawNegate info b cont handler _env = \case rawEq :: (IsBuiltin b, MonadEval b i m) => NativeFunction b i m rawEq info b cont handler _env = \case + -- Todo: rawEqGas [VPactValue pv, VPactValue pv'] -> returnCEKValue cont handler (VBool (pv == pv')) args -> argsError info b args @@ -193,6 +197,7 @@ rawGt info b cont handler _env = \case [VLiteral (LInteger i), VLiteral (LInteger i')] -> returnCEKValue cont handler (VLiteral (LBool (i > i'))) [VLiteral (LDecimal i), VLiteral (LDecimal i')] -> returnCEKValue cont handler (VLiteral (LBool (i > i'))) [VLiteral (LString i), VLiteral (LString i')] -> returnCEKValue cont handler (VLiteral (LBool (i > i'))) + [VTime i, VTime i'] -> returnCEKValue cont handler (VLiteral (LBool (i > i'))) args -> argsError info b args rawLt :: (IsBuiltin b, MonadEval b i m) => NativeFunction b i m @@ -200,6 +205,7 @@ rawLt info b cont handler _env = \case [VLiteral (LInteger i), VLiteral (LInteger i')] -> returnCEKValue cont handler (VLiteral (LBool (i < i'))) [VLiteral (LDecimal i), VLiteral (LDecimal i')] -> returnCEKValue cont handler (VLiteral (LBool (i < i'))) [VLiteral (LString i), VLiteral (LString i')] -> returnCEKValue cont handler (VLiteral (LBool (i < i'))) + [VTime i, VTime i'] -> returnCEKValue cont handler (VLiteral (LBool (i < i'))) args -> argsError info b args rawGeq :: (IsBuiltin b, MonadEval b i m) => NativeFunction b i m @@ -207,6 +213,7 @@ rawGeq info b cont handler _env = \case [VLiteral (LInteger i), VLiteral (LInteger i')] -> returnCEKValue cont handler (VLiteral (LBool (i >= i'))) [VLiteral (LDecimal i), VLiteral (LDecimal i')] -> returnCEKValue cont handler (VLiteral (LBool (i >= i'))) [VLiteral (LString i), VLiteral (LString i')] -> returnCEKValue cont handler (VLiteral (LBool (i >= i'))) + [VTime i, VTime i'] -> returnCEKValue cont handler (VLiteral (LBool (i >= i'))) args -> argsError info b args rawLeq :: (IsBuiltin b, MonadEval b i m) => NativeFunction b i m @@ -214,6 +221,7 @@ rawLeq info b cont handler _env = \case [VLiteral (LInteger i), VLiteral (LInteger i')] -> returnCEKValue cont handler (VLiteral (LBool (i <= i'))) [VLiteral (LDecimal i), VLiteral (LDecimal i')] -> returnCEKValue cont handler (VLiteral (LBool (i <= i'))) [VLiteral (LString i), VLiteral (LString i')] -> returnCEKValue cont handler (VLiteral (LBool (i <= i'))) + [VTime i, VTime i'] -> returnCEKValue cont handler (VLiteral (LBool (i <= i'))) args -> argsError info b args bitAndInt :: (IsBuiltin b, MonadEval b i m) => NativeFunction b i m @@ -292,6 +300,7 @@ rawShow info b cont handler _env = \case returnCEKValue cont handler (VLiteral (LString "()")) args -> argsError info b args +-- Todo: Gas here is complicated, greg worked on this previously rawContains :: (IsBuiltin b, MonadEval b i m) => NativeFunction b i m rawContains info b cont handler _env = \case [VString f, VObject o] -> @@ -314,8 +323,8 @@ rawSort info b cont handler _env = \case returnCEKValue cont handler (VList vli') args -> argsError info b args -rawRemove :: (IsBuiltin b, MonadEval b i m) => NativeFunction b i m -rawRemove info b cont handler _env = \case +coreRemove :: (IsBuiltin b, MonadEval b i m) => NativeFunction b i m +coreRemove info b cont handler _env = \case [VString s, VObject o] -> returnCEKValue cont handler (VObject (M.delete (Field s) o)) args -> argsError info b args @@ -426,9 +435,11 @@ rawDrop info b cont handler _env = \case rawLength :: (IsBuiltin b, MonadEval b i m) => NativeFunction b i m rawLength info b cont handler _env = \case - [VLiteral (LString t)] -> do + [VString t] -> do returnCEKValue cont handler (VLiteral (LInteger (fromIntegral (T.length t)))) [VList li] -> returnCEKValue cont handler (VLiteral (LInteger (fromIntegral (V.length li)))) + [VObject o] -> + returnCEKValue cont handler $ VInteger $ fromIntegral (M.size o) args -> argsError info b args rawReverse :: (IsBuiltin b, MonadEval b i m) => NativeFunction b i m @@ -555,6 +566,14 @@ coreAccess info b cont handler _env = \case in returnCEK cont handler (VError msg info) args -> argsError info b args +coreIsCharset :: (IsBuiltin b, MonadEval b i m) => NativeFunction b i m +coreIsCharset info b cont handler _env = \case + [VLiteral (LInteger i), VString s] -> + case i of + 0 -> returnCEKValue cont handler $ VBool $ T.all Char.isAscii s + 1 -> returnCEKValue cont handler $ VBool $ T.all Char.isLatin1 s + _ -> returnCEK cont handler (VError "Unsupported character set" info) + args -> argsError info b args coreYield :: (IsBuiltin b, MonadEval b i m) => NativeFunction b i m coreYield info b cont handler _env = \case @@ -579,6 +598,12 @@ coreYield info b cont handler _env = \case provenanceOf tid = Provenance tid . _mHash <$> getCallingModule info +corePactId :: (IsBuiltin b, MonadEval b i m) => NativeFunction b i m +corePactId info b cont handler _env = \case + [] -> useEvalState esDefPactExec >>= \case + Just dpe -> returnCEKValue cont handler (VString (_defpactId (_peDefPactId dpe))) + Nothing -> returnCEK cont handler (VError "pact-id: not in pact execution" info) + args -> argsError info b args coreResume :: (IsBuiltin b, MonadEval b i m) => NativeFunction b i m coreResume info b cont handler _env = \case @@ -699,6 +724,20 @@ keysetRefGuard info b cont handler env = \case Just _ -> returnCEKValue cont handler (VGuard (GKeySetRef ksn)) args -> argsError info b args +coreTypeOf :: (IsBuiltin b, MonadEval b i m) => NativeFunction b i m +coreTypeOf info b cont handler _env = \case + [v] -> case v of + VPactValue pv -> + returnCEKValue cont handler $ VString $ renderType $ synthesizePvType pv + VClosure _ -> returnCEKValue cont handler $ VString "<>" + VTable tv -> returnCEKValue cont handler $ VString (renderType (TyTable (_tvSchema tv))) + args -> argsError info b args + +coreDec :: (IsBuiltin b, MonadEval b i m) => NativeFunction b i m +coreDec info b cont handler _env = \case + [VInteger i] -> returnCEKValue cont handler $ VDecimal $ Decimal 0 i + args -> argsError info b args + coreReadInteger :: (IsBuiltin b, MonadEval b i m) => NativeFunction b i m coreReadInteger info b cont handler _env = \case [VString s] -> do @@ -708,8 +747,8 @@ coreReadInteger info b cont handler _env = \case _ -> returnCEK cont handler (VError "read-integer failure" info) args -> argsError info b args -readMsg :: (IsBuiltin b, MonadEval b i m) => NativeFunction b i m -readMsg info b cont handler _env = \case +coreReadMsg :: (IsBuiltin b, MonadEval b i m) => NativeFunction b i m +coreReadMsg info b cont handler _env = \case [VString s] -> do ObjectData envData <- viewEvalEnv eeMsgBody case M.lookup (Field s) envData of @@ -1180,9 +1219,19 @@ coreStrToInt info b cont handler _env = \case args -> argsError info b args coreStrToIntBase :: (IsBuiltin b, MonadEval b i m) => NativeFunction b i m -coreStrToIntBase info b _ _ _env = \case - [VInteger _base, VString _s] -> error "todo: base64" +coreStrToIntBase info b cont handler _env = \case + [VInteger base, VString s] + | base == 64 -> checkLen info s *> case decodeBase64UrlUnpadded $ T.encodeUtf8 s of + Left{} -> throwExecutionError info (DecodeError "invalid b64 encoding") + Right bs -> returnCEKValue cont handler $ VInteger (bsToInteger bs) + | base >= 2 && base <= 16 -> checkLen info s *> doBase info cont handler base s + | otherwise -> returnCEK cont handler (VError "Base value must be >= 2 and <= 16, or 64" info) args -> argsError info b args + where + -- Todo: DOS and gas analysis + bsToInteger :: BS.ByteString -> Integer + bsToInteger bs = fst $ foldl' go (0,(BS.length bs - 1) * 8) $ BS.unpack bs + go (i,p) w = (i .|. (shift (fromIntegral w) p),p - 8) coreDistinct :: (IsBuiltin b, MonadEval b i m) => NativeFunction b i m coreDistinct info b cont handler _env = \case @@ -1420,6 +1469,7 @@ describeModule :: (IsBuiltin b, MonadEval b i m) => NativeFunction b i m describeModule info b cont handler env = \case [VString s] -> case parseModuleName s of Just mname -> do + enforceTopLevelOnly info b checkNonLocalAllowed info getModuleData info (view cePactDb env) mname >>= \case ModuleData m _ -> returnCEKValue cont handler $ @@ -1447,26 +1497,24 @@ dbDescribeTable info b cont handler _env = \case dbDescribeKeySet :: (IsBuiltin b, MonadEval b i m) => NativeFunction b i m dbDescribeKeySet info b cont handler env = \case [VString s] -> do - checkNonLocalAllowed info - getModuleData info (view cePactDb env) (ModuleName s Nothing) >>= \case - ModuleData m _ -> returnCEKValue cont handler $ - VObject $ M.fromList $ fmap (over _1 Field) - [ ("name", PString (renderModuleName (_mName m))) - , ("hash", PString (hashToText (_mhHash (_mHash m)))) - , ("interfaces", PList (PString . renderModuleName <$> V.fromList (_mImplements m)))] - InterfaceData iface _ -> returnCEKValue cont handler $ - VObject $ M.fromList $ fmap (over _1 Field) - [ ("name", PString (renderModuleName (_ifName iface))) - ] + let pdb = _cePactDb env + enforceTopLevelOnly info b + case parseAnyKeysetName s of + Right ksn -> do + liftDbFunction info (_pdbRead pdb DKeySets ksn) >>= \case + Just ks -> + returnCEKValue cont handler (VGuard (GKeyset ks)) + Nothing -> + returnCEK cont handler (VError ("keyset not found" <> s) info) + Left{} -> + returnCEK cont handler (VError "invalid keyset name" info) args -> argsError info b args coreCompose :: (IsBuiltin b, MonadEval b i m) => NativeFunction b i m -coreCompose info b cont handler _env = \case - [VClosure clo1, VClosure clo2, v] -> - applyLam clo1 [v] Mt CEKNoHandler >>= \case - EvalValue v' -> - applyLam clo2 [v'] cont handler - err -> returnCEK cont handler err +coreCompose info b cont handler env = \case + [VClosure clo1, VClosure clo2, v] -> do + let cont' = Fn clo2 env [] [] cont + applyLam clo1 [v] cont' handler args -> argsError info b args createPrincipalForGuard :: Guard FullyQualifiedName PactValue -> Pr.Principal @@ -1814,6 +1862,9 @@ rawBuiltinRuntime = \case RawRound -> roundDec RawCeiling -> ceilingDec RawFloor -> floorDec + RawRoundPrec -> roundDec + RawCeilingPrec -> ceilingDec + RawFloorPrec -> floorDec RawExp -> rawExp RawLn -> rawLn RawSqrt -> rawSqrt @@ -1836,20 +1887,21 @@ rawBuiltinRuntime = \case RawContains -> rawContains RawSort -> rawSort RawSortObject -> rawSortObject - RawRemove -> rawRemove + RawRemove -> coreRemove -- RawEnforce -> coreEnforce -- RawEnforceOne -> unimplemented RawEnumerate -> coreEnumerate RawEnumerateStepN -> coreEnumerateStepN RawShow -> rawShow - RawReadMsg -> readMsg - RawReadMsgDefault -> readMsg + RawReadMsg -> coreReadMsg + RawReadMsgDefault -> coreReadMsg RawReadInteger -> coreReadInteger RawReadDecimal -> coreReadDecimal RawReadString -> coreReadString RawReadKeyset -> coreReadKeyset RawEnforceGuard -> coreEnforceGuard RawYield -> coreYield + RawYieldToChain -> coreYield RawResume -> coreResume RawEnforceKeyset -> coreEnforceGuard RawKeysetRefGuard -> keysetRefGuard @@ -1914,3 +1966,7 @@ rawBuiltinRuntime = \case RawZkPointAdd -> zkPointAddition RawPoseidonHashHackachain -> poseidonHash RawChainData -> coreChainData + RawIsCharset -> coreIsCharset + RawPactId -> corePactId + RawTypeOf -> coreTypeOf + RawDec -> coreDec diff --git a/pact-core/Pact/Core/IR/Eval/Runtime/Types.hs b/pact-core/Pact/Core/IR/Eval/Runtime/Types.hs index 2a6da11ae..d8feda6bb 100644 --- a/pact-core/Pact/Core/IR/Eval/Runtime/Types.hs +++ b/pact-core/Pact/Core/IR/Eval/Runtime/Types.hs @@ -55,6 +55,7 @@ module Pact.Core.IR.Eval.Runtime.Types , pattern VNative , pattern VPartialNative , pattern VCapToken + , pattern VTime , CapFrame(..) , CapState(..) , csSlots, csManaged @@ -87,6 +88,7 @@ import Data.Decimal(Decimal) import Data.Vector(Vector) import Data.RAList(RAList) import Data.IORef +import Pact.Time(UTCTime) import Pact.Core.Names import Pact.Core.Guards @@ -244,6 +246,9 @@ pattern VGuard g = VPactValue (PGuard g) pattern VList :: Vector PactValue -> CEKValue b i m pattern VList p = VPactValue (PList p) +pattern VTime :: UTCTime -> CEKValue b i m +pattern VTime p = VPactValue (PTime p) + pattern VObject :: Map Field PactValue -> CEKValue b i m pattern VObject o = VPactValue (PObject o) diff --git a/pact-core/Pact/Core/IR/ModuleHashing.hs b/pact-core/Pact/Core/IR/ModuleHashing.hs index b5bd191e7..2d2820706 100644 --- a/pact-core/Pact/Core/IR/ModuleHashing.hs +++ b/pact-core/Pact/Core/IR/ModuleHashing.hs @@ -267,6 +267,7 @@ encodeType = \case -- Maybe we preserve schema names instead TyObject sc -> "object" <> braces (encodeSchema sc) TyTable tbl -> "table" <> braces (encodeSchema tbl) + TyCapToken -> "captoken" encodeImport :: Import -> Builder encodeImport (Import mname mmh mimps) = parens $ diff --git a/pact-core/Pact/Core/IR/Term.hs b/pact-core/Pact/Core/IR/Term.hs index ccd0aa930..625566767 100644 --- a/pact-core/Pact/Core/IR/Term.hs +++ b/pact-core/Pact/Core/IR/Term.hs @@ -6,6 +6,7 @@ {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE UndecidableInstances #-} +{-# LANGUAGE InstanceSigs #-} -- | @@ -115,6 +116,7 @@ data TableSchema name where ResolvedTable :: Schema -> TableSchema Name instance Show (TableSchema name) where + show :: TableSchema name -> String show (DesugaredTable t) = "DesugardTable(" <> show t <> ")" show (ResolvedTable t) = "ResolvedTable(" <> show t <> ")" diff --git a/pact-core/Pact/Core/Names.hs b/pact-core/Pact/Core/Names.hs index 36d35b9ff..30a8dc2c8 100644 --- a/pact-core/Pact/Core/Names.hs +++ b/pact-core/Pact/Core/Names.hs @@ -342,7 +342,7 @@ userTable (TableName tn) = TableName ("USER_" <> tn) -- in the case of nested defpacts, the hash of the -- parent + the nested continuation newtype DefPactId - = DefPactId Text + = DefPactId { _defpactId :: Text } deriving (Eq,Ord,Show) instance Pretty DefPactId where diff --git a/pact-core/Pact/Core/PactValue.hs b/pact-core/Pact/Core/PactValue.hs index d80482b35..03d625bca 100644 --- a/pact-core/Pact/Core/PactValue.hs +++ b/pact-core/Pact/Core/PactValue.hs @@ -18,6 +18,7 @@ module Pact.Core.PactValue , pattern PDecimal , pattern PString , pattern PBool + , synthesizePvType ) where import Control.Lens @@ -81,6 +82,17 @@ instance Pretty PactValue where parens (pretty (fqnToQualName fqn) <> if null args then mempty else hsep (pretty <$> args)) PTime t -> pretty (PactTime.formatTime "%Y-%m-%d %H:%M:%S%Q %Z" t) +synthesizePvType :: PactValue -> Type +synthesizePvType = \case + PLiteral l -> typeOfLit l + PList _ -> TyList TyUnit + PGuard _ -> TyGuard + PModRef mr -> TyModRef (_mrModule mr) + PObject f -> + let tys = synthesizePvType <$> f + in TyObject (Schema tys) + PCapToken {} -> TyCapToken + PTime _ -> TyTime -- | Check that a `PactValue` has the provided `Type`, returning -- `Just ty` if so and `Nothing` otherwise. diff --git a/pact-core/Pact/Core/Semantics.md b/pact-core/Pact/Core/Semantics.md index 860be9a79..2b131995c 100644 --- a/pact-core/Pact/Core/Semantics.md +++ b/pact-core/Pact/Core/Semantics.md @@ -70,7 +70,7 @@ Bullet points that are not filled are potential tasks - [ ] EvalResult and EvalInput-type API -## Natives +## Base Builtins ### at - [x] Object case implemented @@ -88,3 +88,552 @@ Bullet points that are not filled are potential tasks ### bind - [x] implemented - [ ] Gas + +### chain-data +- [x] implemented +- [ ] Gas + +### compose +- [x] implemented +- [ ] Gas + +### concat +- [x] implemented +- [ ] Gas + +### constantly +- [x] implemented +- [ ] Gas + +### contains +- [x] String case implemented +- [x] List case implemented +- [x] Object case implemented +- [ ] Gas + +### define-namespace +- [x] implemented +- [x] repl test +- [ ] Gas + +### distinct +- [x] implemented +- [ ] Gas + +### enforce +- [x] implemented +- [ ] Gas + + +### enforce-one +- [x] implemented +- [ ] Gas + + +### enforce-pact-version +TODO: Do we want this still??? + +### enumerate +- [x] implemented 2-arg overload +- [x] implemented 3-arg overload +- [ ] Gas + +### filter +- [x] implemented +- [ ] Gas + + +### fold +- [x] implemented +- [ ] Gas + +### format +- [x] implemented +- [ ] Gas + +### hash +- [x] implemented +- [ ] Gas + +### identity +- [x] implemented +- [ ] Gas + +### if +- [x] implemented +- [ ] Gas + +### int-to-str +- [x] implemented +- [ ] Gas + + +### is-charset +- [x] implemented +- [ ] Gas + +### length +- [x] object case implemented +- [x] string case implemented +- [x] list case implemented +- [ ] Gas + +### list +DELETED FROM EXISTENCE + +### list-modules +(potentially) DELETED FROM EXISTENCE + +### make-list +- [x] implemented +- [ ] Gas + +### map +- [x] implemented +- [ ] Gas + +### pact-id +- [x] implemented +- [ ] Gas + +### pact-version +(potentially) DELETED FROM EXISTENCE + +### public-chain-data +- Todo: provide in base loaded + +### read-decimal +- [x] implemented +- [ ] Gas + +### read-integer +- [x] implemented +- [ ] Gas + +### read-msg +- [x] implemented both overloads +- [ ] Gas + +### read-string +- [x] implemented +- [ ] Gas + +### remove +- [x] implemented +- [ ] Gas + +### resume +- [x] implemented +- [ ] Gas + +### reverse +- [x] implemented +- [ ] Gas + +### reverse +- [x] list case implemented +- [x] object case implemented +- [ ] Gas + +### str-to-int +- [x] list case implemented +- [x] object case implemented +- [ ] Gas + +### str-to-list +- [x] implemented +- [ ] Gas + +### take +- [x] string case implemented +- [x] list case implemented +- [ ] Gas + +### try +- [x] implemented +- [ ] Gas + +### tx-hash +- [x] implemented +- [ ] Gas + +### typeof +- [x] implemented +- [ ] Gas + +### where +- [x] implemented +- [ ] Gas + +### yield +- [x] implemented both overloads (yield and yield to chain) +- [ ] Gas + +### zip +- [x] implemented both overloads (yield and yield to chain) +- [ ] Gas + +### create-table +- [x] Local Bypass Check (NOTBYPASSED) +- [x] Enforcing blessed hashes +- [x] Guarded db access (Module admin or calledByModule) +- [x] Mock PactDb implementation +- [ ] ChainwebPactDb implementation +- [x] implemented +- [ ] Gas + +### describe-keyset +- [x] Enforced top level only +- [x] Mock PactDb implementation +- [ ] ChainwebPactDb implementation +- [x] implemented +- [ ] Gas + +### describe-module +- [x] Local only +- [x] Enforced top level only +- [x] Mock PactDb implementation +- [ ] ChainwebPactDb implementation +- [x] implemented +- [ ] Gas + +### fold-db +- [x] Local Bypass Check (BYPASS) +- [x] Enforcing blessed hashes +- [x] Guarded db access (Module admin or calledByModule) +- [x] Mock PactDb implementation +- [ ] ChainwebPactDb implementation +- [x] implemented +- [ ] Gas + +### insert +- [x] Local Bypass Check (NOTBYPASSED) +- [x] Enforcing blessed hashes +- [x] Guarded db access (Module admin or calledByModule) +- [x] Mock PactDb implementation +- [ ] ChainwebPactDb implementation +- [x] implemented +- [ ] Gas + +### keylog +- [x] Local only +- [x] Local Bypass Check (BYPASS) +- [x] Enforcing blessed hashes +- [x] Guarded db access (Module admin or calledByModule) +- [x] Mock PactDb implementation +- [ ] ChainwebPactDb implementation +- [x] implemented +- [ ] Gas + +### keys +- [x] Local Bypass Check (BYPASS) +- [x] Enforcing blessed hashes +- [x] Guarded db access (Module admin or calledByModule) +- [x] Mock PactDb implementation +- [ ] ChainwebPactDb implementation +- [x] implemented +- [ ] Gas + +### read +- [x] Local Bypass Check (BYPASS) +- [x] Enforcing blessed hashes +- [x] Guarded db access (Module admin or calledByModule) +- [x] Mock PactDb implementation +- [ ] ChainwebPactDb implementation +- [x] implemented +- [ ] Gas + +### select +- [x] Local Bypass Check (BYPASS) +- [x] Enforcing blessed hashes +- [x] Guarded db access (Module admin or calledByModule) +- [x] Mock PactDb implementation +- [ ] ChainwebPactDb implementation +- [x] implemented +- [ ] Gas + +### txids +- [x] Local only +- [x] Local Bypass Check (BYPASS) +- [x] Enforcing blessed hashes +- [x] Guarded db access (Module admin or calledByModule) +- [x] Mock PactDb implementation +- [ ] ChainwebPactDb implementation +- [x] implemented +- [ ] Gas + +### txlog +- [x] Local only +- [x] Local Bypass Check (BYPASS) +- [x] Enforcing blessed hashes +- [x] Guarded db access (Module admin or calledByModule) +- [x] Mock PactDb implementation +- [ ] ChainwebPactDb implementation +- [x] implemented +- [ ] Gas + +### update +- [x] Local Bypass Check (NOTBYPASSED) +- [x] Enforcing blessed hashes +- [x] Guarded db access (Module admin or calledByModule) +- [x] Mock PactDb implementation +- [ ] ChainwebPactDb implementation +- [x] implemented +- [ ] Gas + +### with-default-read +- [x] Local Bypass Check (BYPASS) +- [x] Enforcing blessed hashes +- [x] Guarded db access (Module admin or calledByModule) +- [x] Mock PactDb implementation +- [ ] ChainwebPactDb implementation +- [x] implemented +- [ ] Gas + +### with-read +- [x] Local Bypass Check (BYPASS) +- [x] Enforcing blessed hashes +- [x] Guarded db access (Module admin or calledByModule) +- [x] Mock PactDb implementation +- [ ] ChainwebPactDb implementation +- [x] implemented +- [ ] Gas + +### write +- [x] Local Bypass Check (NOTBYPASSED) +- [x] Enforcing blessed hashes +- [x] Guarded db access (Module admin or calledByModule) +- [x] Mock PactDb implementation +- [ ] ChainwebPactDb implementation +- [x] implemented +- [ ] Gas + +## Time Builtins + +### add-time +- [x] implemented both overloads +- [ ] Gas + +### days +- [x] implemented both overloads +- [ ] Gas + +### diff-time +- [x] implemented both overloads +- [ ] Gas + +### format-time +- [x] implemented +- [ ] Gas + +### hours +- [x] implemented both overloads +- [ ] Gas + +### minutes +- [x] implemented both overloads +- [ ] Gas + +### parse-time +- [x] implemented +- [ ] Gas + +### time +- [x] implemented +- [ ] Gas + + +## Operator Builtins + +### != +- [x] implemented +- [ ] Gas + +### & +- [x] implemented +- [ ] Gas + +### * +- [x] implemented integer case +- [x] implemented decimal case +- [ ] Gas + +### + +- [x] implemented integer case +- [x] implemented decimal case +- [x] implemented string case (concatenation) +- [x] implemented object case (union) +- [ ] Gas + +### - +- [x] implement - as negate (1-arg) for integer +- [x] implement - as negate (1-arg) for decimal +- [x] implement - as subtract (2-arg) for integer +- [x] implement - as subtract (2-arg) for decimal +- [x] implemented object case (union) +- [ ] Gas + +### < +- [x] implemented integer case +- [x] implemented decimal case +- [x] implemented string case +- [x] implemented time case +- [ ] Gas + +### <= +- [x] implemented integer case +- [x] implemented decimal case +- [x] implemented string case +- [x] implemented time case +- [ ] Gas + +### = +- [x] implemented integer case +- [x] implemented decimal case +- [x] implemented string case +- [x] implemented bool case +- [x] implemented object case +- [x] implemented time case +- [x] implemented list case +- [x] implemented modref case +- [x] implemented guard case +- [ ] Gas + +### > +- [x] implemented integer case +- [x] implemented decimal case +- [x] implemented string case +- [x] implemented time case +- [ ] Gas + +### >= +- [x] implemented integer case +- [x] implemented decimal case +- [x] implemented string case +- [x] implemented time case +- [ ] Gas + +### ^ +- [x] implemented integer case +- [x] implemented decimal case +- [x] Musl +- [ ] Gas + +### abs +- [x] implemented integer case +- [x] implemented decimal case +- [ ] Gas + +### and +- [x] implemented with lazy eval +- [ ] Gas + +### and? +- [x] implemented with lazy eval +- [ ] Gas + +### ceiling +- [x] implemented base case +- [x] implemented specific precision case +- [ ] Gas + +### dec +- [x] implemented +- [ ] Gas + +### exp +- [x] implemented integer case +- [x] implemented decimal case +- [x] Musl +- [ ] Gas + +### floor +- [x] implemented base case +- [x] implemented specific precision case +- [ ] Gas + +### ln +- [x] implemented integer case +- [x] implemented decimal case +- [x] Musl +- [ ] Gas + +### log +- [x] implemented integer case +- [x] implemented decimal case +- [x] Musl +- [ ] Gas + +### mod +- [x] implemented integer case +- [ ] Gas + +### not +- [x] implemented +- [ ] Gas + +### not? +- [x] implemented +- [ ] Gas + +### or +- [x] implemented with lazy eval +- [ ] Gas + +### or? +- [x] implemented with lazy eval +- [ ] Gas + +### round +- [x] implemented base case +- [x] implemented specific precision case +- [ ] Gas + +### shift +- [x] implemented +- [ ] Gas + +### sqrt +- [x] implemented integer case +- [x] implemented decimal case +- [x] Musl +- [ ] Gas + +### xor +- [x] implemented +- [ ] Gas + +### | (bitwise or) +- [x] implemented +- [ ] Gas + +### | (bitwise not) +- [x] implemented +- [ ] Gas + +## Keyset builtins + +### define-keyset +- [x] Enforced top level only +- [x] implemented 2-arg case +- [x] implemented 1-arg case +- [x] namespaced +- [ ] Gas + +### enforce-keyset +- [x] implemented guard case +- [x] implemented keyset name case +- [ ] Gas + +### enforce-keyset +- [x] implemented guard case +- [x] implemented keyset name case +- [ ] Gas + +### keys-2, keys-all, keys-any +TODO: do we need this as a native? + +### read-keyset +- [x] implemented guard case +- [x] implemented keyset name case +- [ ] Gas diff --git a/pact-core/Pact/Core/Type.hs b/pact-core/Pact/Core/Type.hs index b6372ba5a..3cef5e59b 100644 --- a/pact-core/Pact/Core/Type.hs +++ b/pact-core/Pact/Core/Type.hs @@ -33,12 +33,17 @@ module Pact.Core.Type , targType , Schema(..) , DefKind(..) + , renderType ) where import Control.Lens +import Data.List import Data.Text(Text) import Data.Map.Strict(Map) +import qualified Data.Text as T +import qualified Data.Map.Strict as M + import Pact.Core.Literal import Pact.Core.Names import Pact.Core.Pretty(Pretty(..), (<+>)) @@ -56,6 +61,16 @@ data PrimType = PrimUnit deriving (Eq,Ord,Show, Enum, Bounded) +renderPrimType :: PrimType -> Text +renderPrimType = \case + PrimInt -> "integer" + PrimDecimal -> "decimal" + PrimBool -> "bool" + PrimString -> "string" + PrimGuard -> "guard" + PrimTime -> "time" + PrimUnit -> "unit" + instance Pretty PrimType where pretty = \case PrimInt -> "integer" @@ -90,6 +105,7 @@ data Type -- ^ Objects | TyTable Schema -- ^ Tables + | TyCapToken deriving (Eq, Show, Ord) newtype Schema @@ -208,21 +224,27 @@ instance Pretty Type where liParens t = Pretty.parens (pretty t) TyModRef mr -> "module" <> Pretty.braces (pretty mr) - TyObject _o -> "todo: " - TyTable _o -> "todo: table" - --- instance Pretty tv => Pretty (TypeScheme tv) where --- pretty (TypeScheme tvs preds ty) = --- quant tvs <> qual preds <> pretty ty --- where --- renderTvs xs suffix = --- Pretty.hsep $ fmap (\n -> Pretty.parens (pretty n <> ":" <+> suffix)) xs --- quant [] = mempty --- quant as = --- "∀" <> renderTvs as "*" <> ". " --- qual [] = mempty --- qual as = --- Pretty.parens (Pretty.commaSep as) <+> "=> " + TyObject (Schema sc) -> + let sc' = (\(k, v) -> pretty k <> ":" <> pretty v) <$> M.toList sc + in "object" <> Pretty.braces (Pretty.hsep (Pretty.punctuate Pretty.comma sc')) + TyTable (Schema sc) -> + let sc' = (\(k, v) -> pretty k <> ":" <> pretty v) <$> M.toList sc + in "table" <> Pretty.braces (Pretty.hsep (Pretty.punctuate Pretty.comma sc')) + TyCapToken -> "CAPTOKEN" + +renderType :: Type -> Text +renderType = \case + TyPrim p -> renderPrimType p + TyList t -> "[" <> renderType t <> "]" + TyGuard -> "guard" + TyModRef mr -> "module" <> "{" <> renderModuleName mr <> "}" + TyObject (Schema sc) -> + let sc' = (\(k, v) -> _field k <> ":" <> renderType v) <$> M.toList sc + in "object{" <> T.concat (intersperse ", " sc') <> "}" + TyTable (Schema sc) -> + let sc' = (\(k, v) -> _field k <> ":" <> renderType v) <$> M.toList sc + in "table{" <> T.concat (intersperse ", " sc') <> "}" + TyCapToken -> "CAPTOKEN" makeLenses ''Arg makeLenses ''TypedArg From 5aa5d805de8787b52e413dc7a68abd5d5389a670 Mon Sep 17 00:00:00 2001 From: jmcardon Date: Sat, 9 Dec 2023 13:41:31 -0500 Subject: [PATCH 11/20] more tests --- .../Pact/Core/Test/PoseidonTests.hs | 19 +++ pact-core-tests/pact-tests/chaindata.repl | 38 ++++++ pact-core-tests/pact-tests/modulehash.repl | 16 +-- pact-core-tests/pact-tests/pairing.repl | 112 ++++++++++++++++++ pact-core-tests/pact-tests/strtoint.repl | 21 ++++ pact-core/Pact/Core/IR/Desugar.hs | 6 +- pact-core/Pact/Core/IR/ModuleHashing.hs | 2 + pact-core/Pact/Core/PactValue.hs | 2 + pact-core/Pact/Core/Type.hs | 8 ++ 9 files changed, 212 insertions(+), 12 deletions(-) create mode 100644 pact-core-tests/Pact/Core/Test/PoseidonTests.hs create mode 100644 pact-core-tests/pact-tests/chaindata.repl create mode 100644 pact-core-tests/pact-tests/pairing.repl create mode 100644 pact-core-tests/pact-tests/strtoint.repl diff --git a/pact-core-tests/Pact/Core/Test/PoseidonTests.hs b/pact-core-tests/Pact/Core/Test/PoseidonTests.hs new file mode 100644 index 000000000..3346a1a4f --- /dev/null +++ b/pact-core-tests/Pact/Core/Test/PoseidonTests.hs @@ -0,0 +1,19 @@ + +module Pact.Core.Test.PoseidonTests(tests) where + +import Test.Tasty +import Test.Tasty.HUnit +import Pact.Core.Crypto.Hash.Poseidon + +tests :: TestTree +tests = testGroup "poseidon" $ pure $ + testGroup "poseidon-hash" $ pure $ + testCase "computes the poseidon hash for two integers" $ do + poseidon [1] @?= 18586133768512220936620570745912940619677854269274689475585506675881198879027 + poseidon [1, 2] @?= 7853200120776062878684798364095072458815029376092732009249414926327459813530 + poseidon [1, 2, 3] @?= 6542985608222806190361240322586112750744169038454362455181422643027100751666 + poseidon [1, 2, 3, 4] @?= 18821383157269793795438455681495246036402687001665670618754263018637548127333 + poseidon [1, 2, 3, 4, 5] @?= 6183221330272524995739186171720101788151706631170188140075976616310159254464 + poseidon [1, 2, 3, 4, 5, 6] @?= 20400040500897583745843009878988256314335038853985262692600694741116813247201 + poseidon [1, 2, 3, 4, 5, 6, 7] @?= 12748163991115452309045839028154629052133952896122405799815156419278439301912 + poseidon [1, 2, 3, 4, 5, 6, 7, 8] @?= 18604317144381847857886385684060986177838410221561136253933256952257712543953 diff --git a/pact-core-tests/pact-tests/chaindata.repl b/pact-core-tests/pact-tests/chaindata.repl new file mode 100644 index 000000000..d0d806b51 --- /dev/null +++ b/pact-core-tests/pact-tests/chaindata.repl @@ -0,0 +1,38 @@ +;; Chain public metadata should initialize with defaults +(expect "chain data chain id initializes with \"\"" "" (at "chain-id" (chain-data))) +(expect "chain data block height initializes with 0" 0 (at "block-height" (chain-data))) +(expect "chain data block time id initializes with time value" (time "1970-01-01T00:00:00Z") (at "block-time" (chain-data))) +(expect "chain data sender initializes with \"\"" "" (at "sender" (chain-data))) +(expect "chain data gas limit initializes with 0" 0 (at "gas-limit" (chain-data))) +(expect "chain data gas price initializes with 0.0" 0.0 (at "gas-price" (chain-data))) + +;; Chain public metadata should reflect updates +(env-chain-data { "chain-id": "Testnet00/2", "block-height": 20 }) +(expect "chain data chain id reflects updated value" "Testnet00/2" (at "chain-id" (chain-data))) +(expect "chain data block height reflects updated value" 20 (at "block-height" (chain-data))) + +;; show that updates are granular +(env-chain-data { "sender": "squawk" }) +(expect "chain data sender reflects updated value" "squawk" (at "sender" (chain-data))) + +;; show that updates are cumulative +(expect "chain data chain id reflects updated value" "Testnet00/2" (at "chain-id" (chain-data))) +(expect "chain data block height reflects updated value" 20 (at "block-height" (chain-data))) + +;; Show failure on improper keys +(expect-failure "chain data should fail to update when wrong key is specified" (env-chain-data { "foo": 8 })) + +;; Show failure on wrongly-typed keys +(expect-failure "chain data should fail for wrongly-typed keys" (env-chain-data { "chain-id": 0.0 })) + +;; Show failure on duplicate keys +(expect-failure "chain data should not accept duplicate updates" (env-chain-data { "chain-id": "Testnet00/1", "chain-id:": "Testnet00/2" })) + +;; test time +(expect "time update succeeds" + "Updated public metadata" + (env-chain-data + { "block-time": (time "2019-01-01T00:00:00Z") })) +(expect "time value correct" + (time "2019-01-01T00:00:00Z") + (at "block-time" (chain-data))) diff --git a/pact-core-tests/pact-tests/modulehash.repl b/pact-core-tests/pact-tests/modulehash.repl index 154ff9973..f0700ccb4 100644 --- a/pact-core-tests/pact-tests/modulehash.repl +++ b/pact-core-tests/pact-tests/modulehash.repl @@ -1,7 +1,7 @@ (env-data {'k:1}) -(defun check-hash-equivalent (mstring:string h:string) - (expect (concat ["Hash of module ", mstring, " matches"]) (at "hash" (describe-module mstring)) h) +(defun check-hash-equivalent (mstring:string mobj:object h:string) + (expect (concat ["Hash of module ", mstring, " matches"]) (at "hash" mobj) h) ) (module m m-gov @@ -20,7 +20,7 @@ ) ; base case -(check-hash-equivalent "m" "QCLU54Co9PbQqiqFz1F3M-pPgdn59ANGIG7bwNVFAJk") +(check-hash-equivalent "m" (describe-module "m") "QCLU54Co9PbQqiqFz1F3M-pPgdn59ANGIG7bwNVFAJk") (env-data {'k:2}) (module m m-gov @@ -40,7 +40,7 @@ ; Defconst changed, ensure hash changed -(check-hash-equivalent "m" "83c6a-9Hmv9yHOkaY1Y2LmHoHvXLWYc_lQ-Oacg8URw") +(check-hash-equivalent "m" (describe-module "m") "83c6a-9Hmv9yHOkaY1Y2LmHoHvXLWYc_lQ-Oacg8URw") (module m m-gov (defcap m-gov () true) @@ -59,7 +59,7 @@ ; Basic code changed: hash should change -(check-hash-equivalent "m" "WhYWXrM3oUwXRaiPela_j7d2nF5snW5SPjGUOuuJu7c") +(check-hash-equivalent "m" (describe-module "m") "WhYWXrM3oUwXRaiPela_j7d2nF5snW5SPjGUOuuJu7c") ; Modules, interfaces and deps (module n gg @@ -72,7 +72,7 @@ ) -(check-hash-equivalent "n" "v30ra86hQ35kT1k8pdXnGsGU434VD7Ysa7smYhHFPs0") +(check-hash-equivalent "n" (describe-module "n") "v30ra86hQ35kT1k8pdXnGsGU434VD7Ysa7smYhHFPs0") ; Update dependent module, ensure hash changes (module m m-gov @@ -102,7 +102,7 @@ ) ; m changed, hash should have changed -(check-hash-equivalent "m" "BVrxWuHbjy9heR9AhAZnbusKvSKiyzrEYt8_0LCBRqs") +(check-hash-equivalent "m" (describe-module "m") "BVrxWuHbjy9heR9AhAZnbusKvSKiyzrEYt8_0LCBRqs") ; n did not change, but the dependency hash changed, so it should also change the hash -(check-hash-equivalent "n" "ETUjfmMviiXCyZYxJLzk1uXBQFizGizyqPGz1XIt1lA") +(check-hash-equivalent "n" (describe-module "n") "ETUjfmMviiXCyZYxJLzk1uXBQFizGizyqPGz1XIt1lA") diff --git a/pact-core-tests/pact-tests/pairing.repl b/pact-core-tests/pact-tests/pairing.repl new file mode 100644 index 000000000..5650e35ff --- /dev/null +++ b/pact-core-tests/pact-tests/pairing.repl @@ -0,0 +1,112 @@ +(module verifier G + (defcap G () true) + (defschema point-g1 + x:integer + y:integer) + ; Note points in g2 should be lists of at most length 2. + ; We may want to enforce this by having this be twi + (defschema point-g2 + x:[integer] + y:[integer]) + + (defschema proof + proofA:object{point-g1} + proofB:object{point-g2} + proofC:object{point-g1}) + + (defschema vk + alfa1:object{point-g1} + beta2:object{point-g2} + gamma2:object{point-g2} + delta2:object{point-g2} + ic:[object{point-g1}]) + + (defconst g1:object{point-g1} + {'x:1, 'y:2}) + + (defconst g2:object{point-g2} + { 'x: [10857046999023057135944570762232829481370756359578518086990519993285655852781, 11559732032986387107991004021392285783925812861821192530917403151452391805634] + , 'y: [8495653923123431417604973247489272438418190587263600148770280649306958101930, 4082367875863433681332203403145435568316851327593401208105741076214120093531]} + ) + + (defconst verifying-key:object{vk} + { "alfa1": + {'x: 20491192805390485299153009773594534940189261866228447918068658471970481763042, + 'y: 9383485363053290200918347156157836566562967994039712273449902621266178545958} + , "beta2": + {'x: [ 6375614351688725206403948262868962793625744043794305715222011528459656738731 + , 4252822878758300859123897981450591353533073413197771768651442665752259397132], + 'y: [ 10505242626370262277552901082094356697409835680220590971873171140371331206856 + , 21847035105528745403288232691147584728191162732299865338377159692350059136679]} + , "gamma2": + {'x: [ 10857046999023057135944570762232829481370756359578518086990519993285655852781 + , 11559732032986387107991004021392285783925812861821192530917403151452391805634], + 'y: [ 8495653923123431417604973247489272438418190587263600148770280649306958101930 + , 4082367875863433681332203403145435568316851327593401208105741076214120093531]} + , "delta2": + {'x: [ 16809031008450260338666218659281275370828342486329981864349494337906939571887 + , 14264224196899353800543367999525075765943744025449601386425105981609273614701], + 'y: [ 11890256881228627469373664690032300678627026600164400771388911741873652827176 + , 19575774426779481952987745556743272872528397589822551825491193352706249147828]} + , "ic" : + [ {'x:703628372913608924678229163876049246019207425954662225921071872483627421722, 'y: 12211995813319149655177018938770234811518560618061207904053494967754185713570} + , {'x:245257359888022973124621370122921842349425470670527924595405093609495308747, 'y: 16424211039905278739428973076501641419102983596574674938829868639077765818142} + , {'x:11110164462478062380497336442107420783806541677398299686522715666379498138472, 'y: 11772875621558518653532220728777759671658134704623077088185806874340215959359} + , {'x:18074393405015025057791386123633410704735277649988577562824116025859630543119, 'y: 6512362579817099053449579131846840340322546772440905776424666285439665971742} + , {'x:16324035526312367325456640773935782752062271159753322602146362004262088969135, 'y: 1959877669644004327327941905732419844609901799055849407390385762919820073782} + , {'x:7958732978061398276873406529212832852529841068044035448997300713023105585033, 'y: 17143584956740843297694279539007817220119917091654840292522900244927912727369} + , {'x:19790616331302654635046558077934057923437716290995001520546062733967158884432, 'y: 3876239317603061711287361903875372717184929107501147494633374979429019396018} + , {'x:14590717951490734152256639590507997933809755442616725401381713035954026634761, 'y: 3225155507246149008951243692824143870155533409045696678069139586430835695226} + , {'x:8650680088861200059927247719422818384661114515347998151694550511594524540419, 'y: 9638849577460518420520485529873913372767621068985215869067476349645606505077} + , {'x:17562317824746836410714834945198951796768727084595092618069846988441315688042, 'y: 19452027031432595136507137552742780122072574021124781097949079775870562190348} + , {'x:13182231104070542193327121010898638946743037034726286337778578885258172200370, 'y: 757187892995880849330492963674577612574015215504544964795700288326850257327} + , {'x:14409932519884296032513716882778643894210345146972579810764887578771580357222, 'y: 814882272533738805340475214361663264998713952212684412413716253117631329790} + , {'x:12509202143372575765947197406153125630356821791569394199509048702081149394252, 'y: 7737627039987972603153686057063377754848525136672116479087023797531609007397} + , {'x:8407744049840718757455802166031970590203865445336729285031156887247294225651, 'y: 188049909694651097938181392474312752814356026969638293041076738773396096245} + , {'x:334110586971536499255771782557320020258112908015957001506636732710862874984, 'y: 16580656581000952485971124280378233725304032835996723142898957560222784358519} + , {'x:7727226277603419079704813924510379012883865378360151539308685989224075286070, 'y: 12912566309035429310049884735227185094569540217854933912859497659097301533657} + , {'x:7681998061757907807252614087798324369243677279399770153101699113400315047554, 'y: 17481742211680301513436042099326808806059638013948490790089189392596297352637} + , {'x:12569417065062182916398142101141299032330235062582799620914438471333638326044, 'y: 17523163572024314338870129158401181066960544407476643264775649919375538750903} + , {'x:20366720006081427400904331708710783224493502999618856932501475384256136971442, 'y: 12984908039677137046692512896720328898650869058550411984382690230037651160819} + , {'x:8428544296631560843765157901673529267885840366893744558046063361202851291828, 'y: 16289478447662297604149997612134385555472387391722487532370257859531844209269} ] + }) + + (defun negate-point-g1:object{point-g1} (point:object{point-g1}) + (bind point {"x" := x, "y" := y} {'x:x, 'y: (- y)}) ) + + (defun verify-proof:bool + (proof:object{proof} + input:[integer]) + + (enforce (= (+ 1 (length input)) (length (at 'ic verifying-key))) "input must be 1 below ic") + + (let* + ((curve-inf {'x:0, 'y:0}) + (vk_x (fold (point-add "g1") curve-inf (zip (scalar-mult 'g1) (drop 1 (at 'ic verifying-key)) input))) + (vk_x1 (point-add 'g1 vk_x (at 0 (at 'ic verifying-key)))) + ) + (pairing-check + [(negate-point-g1 (at 'proofA proof)) (at 'alfa1 verifying-key) vk_x1 (at 'proofC proof)] + [(at 'proofB proof) (at 'beta2 verifying-key) (at 'gamma2 verifying-key) (at 'delta2 verifying-key)] + ) + ) + ) +) + + +(expect "Pairing function check on test proof" + true + (let* + ((p1 { 'x:17899149025429256540670503450603840524526341770363252849540840688855727610005 + , 'y:6794888886586012478899094699714874747255503821264355877996121220781692052981}) + (p2 { 'x:[4555160965165375385578562333880156835913586562443164694386914449127412126755, 16845220796436439159658389520454136502557317448502144055381480626643346396453] + , 'y:[15740922883530394503972296892303076718862447518810507376564218784428077030254, 9794083499477745551885635852864140214811154513402172713835626845455029169909]}) + (p3 { 'x:2188339130061078784977610313576641337709587353412678866175084864819379744795 + , 'y:7363399164077520072321162032202323356331016580445157674442815097597932017402}) + (proof:object{proof} {'proofA:p1, 'proofB:p2, 'proofC:p3}) + (inp [293440811465879871736579011234159205259, 82735329187654304797954025540247337640, 1125899906842623, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1]) + ) + (verify-proof proof inp) + ) + ) + diff --git a/pact-core-tests/pact-tests/strtoint.repl b/pact-core-tests/pact-tests/strtoint.repl new file mode 100644 index 000000000..39e39c768 --- /dev/null +++ b/pact-core-tests/pact-tests/strtoint.repl @@ -0,0 +1,21 @@ +(expect "str-to-int decimal identity - no base" (str-to-int "12345") 12345) +(expect "str-to-int hex identity" (str-to-int 16 "12345abcdef") 1251004370415) +(expect "str-to-int binary identity" (str-to-int 2 "101010111100110111101111000100100011010001010110") 188900967593046) +(expect "str-to-int roundtrip" (str-to-int 16 "12345abcdef") (str-to-int "1251004370415")) +(expect "str-to-int roundtrip" (str-to-int 2 "101010111100110111101111000100100011010001010110") (str-to-int "188900967593046")) +(expect "str-to-int roundtrip" (str-to-int 10 "12345") (str-to-int "12345")) +(expect-failure "str-to-int base == 1" "Base value must be" (str-to-int 1 "12345")) +(expect-failure "str-to-int base < 1" (str-to-int -1 "12345")) +(expect-failure "str-to-int base > 16" (str-to-int 17 "12345")) +(expect-failure "str-to-int empty string" (str-to-int "")) +(expect-failure "str-to-int char out of range with base" (str-to-int 8 "8")) +(expect-failure "str-to-int char out of range without base" (str-to-int "a")) + +(expect "str-to-int 64" 43981 (str-to-int 64 "q80")) + +(expect "int-to-str 2" "101010111100110111101111000100100011010001010110" + (int-to-str 2 188900967593046)) +(expect "int-to-str 10" "12345" (int-to-str 10 12345)) +(expect "int-to-str 16" "12345abcdef" (int-to-str 16 1251004370415)) +(expect "int-to-str 64" "q80" (int-to-str 64 43981)) +(expect-failure "int-to-str 17" (int-to-str 17 3245342)) diff --git a/pact-core/Pact/Core/IR/Desugar.hs b/pact-core/Pact/Core/IR/Desugar.hs index 876396462..19138aa44 100644 --- a/pact-core/Pact/Core/IR/Desugar.hs +++ b/pact-core/Pact/Core/IR/Desugar.hs @@ -817,10 +817,8 @@ renameType i = \case TyObject <$> resolveSchema pn Lisp.TyTable pn -> TyTable <$> resolveSchema pn - Lisp.TyPolyList -> - throwDesugarError (UnsupportedType "[any]") i - Lisp.TyPolyObject -> - throwDesugarError (UnsupportedType "object{any}") i + Lisp.TyPolyList -> pure TyAnyList + Lisp.TyPolyObject -> pure TyAnyObject where resolveSchema = \case TBN bn -> do diff --git a/pact-core/Pact/Core/IR/ModuleHashing.hs b/pact-core/Pact/Core/IR/ModuleHashing.hs index 2d2820706..821cb9e36 100644 --- a/pact-core/Pact/Core/IR/ModuleHashing.hs +++ b/pact-core/Pact/Core/IR/ModuleHashing.hs @@ -268,6 +268,8 @@ encodeType = \case TyObject sc -> "object" <> braces (encodeSchema sc) TyTable tbl -> "table" <> braces (encodeSchema tbl) TyCapToken -> "captoken" + TyAnyList -> "list" + TyAnyObject -> "object" encodeImport :: Import -> Builder encodeImport (Import mname mmh mimps) = parens $ diff --git a/pact-core/Pact/Core/PactValue.hs b/pact-core/Pact/Core/PactValue.hs index 03d625bca..954b9f46b 100644 --- a/pact-core/Pact/Core/PactValue.hs +++ b/pact-core/Pact/Core/PactValue.hs @@ -120,9 +120,11 @@ checkPvType ty = \case mcheck (f1, pv) (f2, t) | f1 == f2 = (f1,) <$> checkPvType t pv | otherwise = Nothing + TyAnyObject -> Just TyAnyObject _ -> Nothing PList l -> case ty of TyList t' | all (isJust . checkPvType t') l -> Just (TyList t') + TyAnyList -> Just TyAnyList _ -> Nothing PModRef (ModRef _orig ifs refined) -> case ty of TyModRef mn diff --git a/pact-core/Pact/Core/Type.hs b/pact-core/Pact/Core/Type.hs index 3cef5e59b..7e7f6a9e2 100644 --- a/pact-core/Pact/Core/Type.hs +++ b/pact-core/Pact/Core/Type.hs @@ -99,10 +99,14 @@ data Type -- ^ Built-in types | TyList Type -- ^ List aka [a] + | TyAnyList + -- ^ Any list | TyModRef ModuleName -- ^ Module references | TyObject Schema -- ^ Objects + | TyAnyObject + -- ^ Object with any schema | TyTable Schema -- ^ Tables | TyCapToken @@ -231,6 +235,8 @@ instance Pretty Type where let sc' = (\(k, v) -> pretty k <> ":" <> pretty v) <$> M.toList sc in "table" <> Pretty.braces (Pretty.hsep (Pretty.punctuate Pretty.comma sc')) TyCapToken -> "CAPTOKEN" + TyAnyList -> "list" + TyAnyObject -> "object" renderType :: Type -> Text renderType = \case @@ -245,6 +251,8 @@ renderType = \case let sc' = (\(k, v) -> _field k <> ":" <> renderType v) <$> M.toList sc in "table{" <> T.concat (intersperse ", " sc') <> "}" TyCapToken -> "CAPTOKEN" + TyAnyObject -> "object" + TyAnyList -> "list" makeLenses ''Arg makeLenses ''TypedArg From 9c5ec62d2bc682c11bf966e9cd5c2ff698fbc317 Mon Sep 17 00:00:00 2001 From: jmcardon Date: Sat, 9 Dec 2023 13:47:37 -0500 Subject: [PATCH 12/20] address comments --- pact-core/Pact/Core/Errors.hs | 18 +----------------- pact-core/Pact/Core/IR/Eval/RawBuiltin.hs | 12 +++++++----- 2 files changed, 8 insertions(+), 22 deletions(-) diff --git a/pact-core/Pact/Core/Errors.hs b/pact-core/Pact/Core/Errors.hs index c2dc6681d..23dfec5fa 100644 --- a/pact-core/Pact/Core/Errors.hs +++ b/pact-core/Pact/Core/Errors.hs @@ -333,6 +333,7 @@ data EvalError | DefineNamespaceError Text -- ^ Non-recoverable guard enforces. | ConstIsNotAPactValue QualifiedName + | PointNotOnCurve deriving Show @@ -439,23 +440,6 @@ instance Pretty EvalError where , "DefPactExec step: " <> pretty (_peStep pe + 1) ] e -> pretty (show e) - -- CannotUpgradeInterface _ -> error "" - -- ModuleGovernanceFailure _ -> error "" - -- DbOpFailure _ -> error "" - -- DynNameIsNotModRef _ -> error "" - -- ModuleDoesNotExist _ -> error "" - -- ExpectedModule _ -> error "" - -- HashNotBlessed _ _ -> error "" - -- CannotApplyPartialClosure -> error "" - -- ClosureAppliedToTooManyArgs -> error "" - -- FormIllegalWithinDefcap _ -> error "" - -- RunTimeTypecheckFailure _ _ -> error "" - -- NativeIsTopLevelOnly _ -> error "" - -- EventDoesNotMatchModule _ -> error "" - -- InvalidEventCap _ -> error "" - -- NestedDefpactsNotAdvanced _ -> error "" - -- ExpectedPactValue -> error "" - -- NotInDefPactExecution -> error "" instance Exception EvalError diff --git a/pact-core/Pact/Core/IR/Eval/RawBuiltin.hs b/pact-core/Pact/Core/IR/Eval/RawBuiltin.hs index 2e187a353..73b7d84ea 100644 --- a/pact-core/Pact/Core/IR/Eval/RawBuiltin.hs +++ b/pact-core/Pact/Core/IR/Eval/RawBuiltin.hs @@ -1706,7 +1706,7 @@ coreChainData info b cont handler _env = \case -- ------------------------- ensureOnCurve :: (Num p, Eq p, MonadEval b i m) => i -> CurvePoint p -> p -> m () -ensureOnCurve info p bp = unless (isOnCurve p bp) $ failInvariant info "Point not on curve" +ensureOnCurve info p bp = unless (isOnCurve p bp) $ throwExecutionError info PointNotOnCurve toG1 :: ObjectData PactValue -> Maybe G1 toG1 (ObjectData obj) = do @@ -1777,13 +1777,13 @@ zkScalaMult info b cont handler _env = \case case T.toLower ptTy of "g1" -> do p1' <- maybe (argsError info b args) pure $ toG1 (ObjectData p1) - unless (isOnCurve p1' b1) $ failInvariant info "Point not on curve" + ensureOnCurve info p1' b1 let p2' = multiply p1' scalar' ObjectData o = fromG1 p2' returnCEKValue cont handler (VObject o) "g2" -> do p1' <- maybe (argsError info b args) pure $ toG2 (ObjectData p1) - unless (isOnCurve p1' b2) $ failInvariant info "Point not on curve" + ensureOnCurve info p1' b2 let p2' = multiply p1' scalar' ObjectData o = fromG2 p2' returnCEKValue cont handler (VObject o) @@ -1800,14 +1800,16 @@ zkPointAddition info b cont handler _env = \case "g1" -> do p1' <- maybe (argsError info b args) pure $ toG1 (ObjectData p1) p2' <- maybe (argsError info b args) pure $ toG1 (ObjectData p2) - unless (isOnCurve p1' b1 && isOnCurve p2' b1) $ failInvariant info "Point not on curve" + ensureOnCurve info p1' b1 + ensureOnCurve info p2' b1 let p3' = add p1' p2' ObjectData o = fromG1 p3' returnCEKValue cont handler (VObject o) "g2" -> do p1' <- maybe (argsError info b args) pure $ toG2 (ObjectData p1) p2' <- maybe (argsError info b args) pure $ toG2 (ObjectData p2) - unless (isOnCurve p1' b2 && isOnCurve p2' b2) $ failInvariant info "Point not on curve" + ensureOnCurve info p1' b2 + ensureOnCurve info p2' b2 let p3' = add p1' p2' ObjectData o = fromG2 p3' returnCEKValue cont handler (VObject o) From c15e026cd512275352a1cb16c85d1d9eb77f5ae2 Mon Sep 17 00:00:00 2001 From: jmcardon Date: Sat, 9 Dec 2023 14:05:05 -0500 Subject: [PATCH 13/20] enable ops cases, fix tests --- pact-core-tests/pact-tests/ops.repl | 245 +++++++++++----------- pact-core/Pact/Core/IR/Desugar.hs | 9 + pact-core/Pact/Core/IR/Eval/RawBuiltin.hs | 5 +- 3 files changed, 134 insertions(+), 125 deletions(-) diff --git a/pact-core-tests/pact-tests/ops.repl b/pact-core-tests/pact-tests/ops.repl index a46b29d83..e356359d6 100644 --- a/pact-core-tests/pact-tests/ops.repl +++ b/pact-core-tests/pact-tests/ops.repl @@ -71,7 +71,7 @@ ; (expect-failure "<= decimal integer" (<= 11.0 11)) ; (expect-failure "> decimal integer" (> 11.0 10)) ; (expect-failure ">= decimal integer" (>= 12.0 11)) -; (expect "= decimal integer false" false (= 10.0 10)) +(expect "= decimal integer false" false (= 10.0 10)) ; (expect-failure "< integer decimal" (< 10 11.0)) ; (expect-failure "<= integer decimal" (<= 11 11.0)) @@ -98,8 +98,7 @@ (expect "= module{ix} module{ix}" true (= mx mx)) (expect "!= module{ix} module{ix}" true (!= my mx)) -(expect-failure "equality on module references") -; (expect-typecheck-failure "equality on module references implementing the incorrect interface" (= mx ny)) +(expect "!= module{ix} module{iy}" true (!= my ny)) "===== math" (expect "abs" 10.23 (abs -10.23)) @@ -119,7 +118,7 @@ (expect "sqrt 15" 3.87298334620741702138957407441921532154083251953125 (sqrt 15)) (expect "sqrt 15.0" 3.87298334620741702138957407441921532154083251953125 (sqrt 15.0)) -; "===== math.log" +"===== math.log" (expect-failure "log 0 0" (log 0 0)) ; (expect-typecheck-failure "log 0 0.0" (log 0 0.0)) (expect-failure "log 0 -0" (log 0 -0)) @@ -146,109 +145,109 @@ ; (expect-typecheck-failure "log 0.0 15" (log 0.0 15)) (expect "log 0.0 15.0" 0.0 (log 0.0 15.0)) -; (expect-failure "log -0 0" (log -0 0)) +(expect-failure "log -0 0" (log -0 0)) ; (expect-failure "log -0 0.0" (log -0 0.0)) -; (expect-failure "log -0 -0" (log -0 -0)) +(expect-failure "log -0 -0" (log -0 -0)) ; (expect-failure "log -0 -0.0" (log -0 -0.0)) -; (expect "log -0 1" 0 (log -0 1)) +(expect "log -0 1" 0 (log -0 1)) ; (expect "log -0 1.0" 0.0 (log -0 1.0)) -; (expect-failure "log -0 -1" (log -0 -1)) +(expect-failure "log -0 -1" (log -0 -1)) ; (expect-failure "log -0 -1.0" (log -0 -1.0)) -; (expect "log -0 16" 0 (log -0 16)) +(expect "log -0 16" 0 (log -0 16)) ; (expect "log -0 16.0" 0.0 (log -0 16.0)) -; (expect "log -0 15" 0 (log -0 15)) +(expect "log -0 15" 0 (log -0 15)) ; (expect "log -0 15.0" 0.0 (log -0 15.0)) ; (expect-failure "log -0.0 0" (log -0.0 0)) -; (expect-failure "log -0.0 0.0" (log -0.0 0.0)) +(expect-failure "log -0.0 0.0" (log -0.0 0.0)) ; (expect-failure "log -0.0 -0" (log -0.0 -0)) -; (expect-failure "log -0.0 -0.0" (log -0.0 -0.0)) +(expect-failure "log -0.0 -0.0" (log -0.0 -0.0)) ; (expect "log -0.0 1" 0.0 (log -0.0 1)) -; (expect "log -0.0 1.0" 0.0 (log -0.0 1.0)) +(expect "log -0.0 1.0" 0.0 (log -0.0 1.0)) ; (expect-failure "log -0.0 -1" (log -0.0 -1)) -; (expect-failure "log -0.0 -1.0" (log -0.0 -1.0)) +(expect-failure "log -0.0 -1.0" (log -0.0 -1.0)) ; (expect "log -0.0 16" 0.0 (log -0.0 16)) -; (expect "log -0.0 16.0" 0.0 (log -0.0 16.0)) +(expect "log -0.0 16.0" 0.0 (log -0.0 16.0)) ; (expect "log -0.0 15" 0.0 (log -0.0 15)) -; (expect "log -0.0 15.0" 0.0 (log -0.0 15.0)) +(expect "log -0.0 15.0" 0.0 (log -0.0 15.0)) -; (expect-failure "log 1 0" (log 1 0)) +(expect-failure "log 1 0" (log 1 0)) ; (expect-failure "log 1 0.0" (log 1 0.0)) -; (expect-failure "log 1 -0" (log 1 -0)) +(expect-failure "log 1 -0" (log 1 -0)) ; (expect-failure "log 1 -0.0" (log 1 -0.0)) -; (expect-failure "log 1 1" (log 1 1)) +(expect-failure "log 1 1" (log 1 1)) ; (expect-failure "log 1 1.0" (log 1 1.0)) -; (expect-failure "log 1 -1" (log 1 -1)) +(expect-failure "log 1 -1" (log 1 -1)) ; (expect-failure "log 1 -1.0" (log 1 -1.0)) -; (expect-failure "log 1 16" (log 1 16)) +(expect-failure "log 1 16" (log 1 16)) ; (expect-failure "log 1 16.0" (log 1 16.0)) -; (expect-failure "log 1 15" (log 1 15)) +(expect-failure "log 1 15" (log 1 15)) ; (expect-failure "log 1 15.0" (log 1 15.0)) ; (expect-failure "log 1.0 0" (log 1.0 0)) -; (expect-failure "log 1.0 0.0" (log 1.0 0.0)) +(expect-failure "log 1.0 0.0" (log 1.0 0.0)) ; (expect-failure "log 1.0 -0" (log 1.0 -0)) -; (expect-failure "log 1.0 -0.0" (log 1.0 -0.0)) +(expect-failure "log 1.0 -0.0" (log 1.0 -0.0)) ; (expect-failure "log 1.0 1" (log 1.0 1)) -; (expect-failure "log 1.0 1.0" (log 1.0 1.0)) +(expect-failure "log 1.0 1.0" (log 1.0 1.0)) ; (expect-failure "log 1.0 -1" (log 1.0 -1)) -; (expect-failure "log 1.0 -1.0" (log 1.0 -1.0)) +(expect-failure "log 1.0 -1.0" (log 1.0 -1.0)) ; (expect-failure "log 1.0 16" (log 1.0 16)) -; (expect-failure "log 1.0 16.0" (log 1.0 16.0)) +(expect-failure "log 1.0 16.0" (log 1.0 16.0)) ; (expect-failure "log 1.0 15" (log 1.0 15)) -; (expect-failure "log 1.0 15.0" (log 1.0 15.0)) +(expect-failure "log 1.0 15.0" (log 1.0 15.0)) -; (expect-failure "log -1 0" (log -1 0)) +(expect-failure "log -1 0" (log -1 0)) ; (expect-failure "log -1 0.0" (log -1 0.0)) -; (expect-failure "log -1 -0" (log -1 -0)) +(expect-failure "log -1 -0" (log -1 -0)) ; (expect-failure "log -1 -0.0" (log -1 -0.0)) -; (expect-failure "log -1 1" (log -1 1)) +(expect-failure "log -1 1" (log -1 1)) ; (expect-failure "log -1 1.0" (log -1 1.0)) -; (expect-failure "log -1 -1" (log -1 -1)) +(expect-failure "log -1 -1" (log -1 -1)) ; (expect-failure "log -1 -1.0" (log -1 -1.0)) -; (expect-failure "log -1 16" (log -1 16)) +(expect-failure "log -1 16" (log -1 16)) ; (expect-failure "log -1 16.0" (log -1 16.0)) -; (expect-failure "log -1 15" (log -1 15)) +(expect-failure "log -1 15" (log -1 15)) ; (expect-failure "log -1 15.0" (log -1 15.0)) ; (expect-failure "log -1.0 0" (log -1.0 0)) -; (expect-failure "log -1.0 0.0" (log -1.0 0.0)) +(expect-failure "log -1.0 0.0" (log -1.0 0.0)) ; (expect-failure "log -1.0 -0" (log -1.0 -0)) -; (expect-failure "log -1.0 -0.0" (log -1.0 -0.0)) +(expect-failure "log -1.0 -0.0" (log -1.0 -0.0)) ; (expect-failure "log -1.0 1" (log -1.0 1)) -; (expect-failure "log -1.0 1.0" (log -1.0 1.0)) +(expect-failure "log -1.0 1.0" (log -1.0 1.0)) ; (expect-failure "log -1.0 -1" (log -1.0 -1)) -; (expect-failure "log -1.0 -1.0" (log -1.0 -1.0)) +(expect-failure "log -1.0 -1.0" (log -1.0 -1.0)) ; (expect-failure "log -1.0 16" (log -1.0 16)) -; (expect-failure "log -1.0 16.0" (log -1.0 16.0)) +(expect-failure "log -1.0 16.0" (log -1.0 16.0)) ; (expect-failure "log -1.0 15" (log -1.0 15)) -; (expect-failure "log -1.0 15.0" (log -1.0 15.0)) +(expect-failure "log -1.0 15.0" (log -1.0 15.0)) ; (expect-failure "log 4.0 0" (log 4.0 0)) -; (expect-failure "log 4.0 0.0" (log 4.0 0.0)) +(expect-failure "log 4.0 0.0" (log 4.0 0.0)) ; (expect-failure "log 4.0 -0" (log 4.0 -0)) -; (expect-failure "log 4.0 -0.0" (log 4.0 -0.0)) +(expect-failure "log 4.0 -0.0" (log 4.0 -0.0)) ; (expect "log 4.0 1" 0.0 (log 4.0 1)) -; (expect "log 4.0 1.0" 0.0 (log 4.0 1.0)) +(expect "log 4.0 1.0" 0.0 (log 4.0 1.0)) ; (expect-failure "log 4.0 -1" (log 4.0 -1)) -; (expect-failure "log 4.0 -1.0" (log 4.0 -1.0)) +(expect-failure "log 4.0 -1.0" (log 4.0 -1.0)) ; (expect "log 4.0 16" 2.0 (log 4.0 16)) -; (expect "log 4.0 16.0" 2.0 (log 4.0 16.0)) +(expect "log 4.0 16.0" 2.0 (log 4.0 16.0)) ; (expect "log 4.0 15" 1.953445297804259350726852062507532536983489990234375 (log 4.0 15)) -; (expect "log 4.0 15.0" 1.953445297804259350726852062507532536983489990234375 (log 4.0 15.0)) +(expect "log 4.0 15.0" 1.953445297804259350726852062507532536983489990234375 (log 4.0 15.0)) ; (expect-failure "log -4.0 0" (log -4.0 0)) -; (expect-failure "log -4.0 0.0" (log -4.0 0.0)) +(expect-failure "log -4.0 0.0" (log -4.0 0.0)) ; (expect-failure "log -4.0 -0" (log -4.0 -0)) -; (expect-failure "log -4.0 -0.0" (log -4.0 -0.0)) +(expect-failure "log -4.0 -0.0" (log -4.0 -0.0)) ; (expect-failure "log -4.0 1" (log -4.0 1)) -; (expect-failure "log -4.0 1.0" (log -4.0 1.0)) +(expect-failure "log -4.0 1.0" (log -4.0 1.0)) ; (expect-failure "log -4.0 -1" (log -4.0 -1)) -; (expect-failure "log -4.0 -1.0" (log -4.0 -1.0)) +(expect-failure "log -4.0 -1.0" (log -4.0 -1.0)) ; (expect-failure "log -4.0 16" (log -4.0 16)) -; (expect-failure "log -4.0 16.0" (log -4.0 16.0)) +(expect-failure "log -4.0 16.0" (log -4.0 16.0)) ; (expect-failure "log -4.0 15" (log -4.0 15)) -; (expect-failure "log -4.0 15.0" (log -4.0 15.0)) +(expect-failure "log -4.0 15.0" (log -4.0 15.0)) "===== math.ln" (expect-failure "ln 0" (ln 0)) @@ -293,124 +292,124 @@ ; (expect-typecheck-failure "^ 0 15.0" (^ 0 15.0)) ; (expect "^ 0.0 0" 1.0 (^ 0.0 0)) -; (expect "^ 0.0 0.0" 1.0 (^ 0.0 0.0)) +(expect "^ 0.0 0.0" 1.0 (^ 0.0 0.0)) ; (expect "^ 0.0 -0" 1.0 (^ 0.0 -0)) -; (expect "^ 0.0 -0.0" 1.0 (^ 0.0 -0.0)) +(expect "^ 0.0 -0.0" 1.0 (^ 0.0 -0.0)) ; (expect "^ 0.0 1" 0.0 (^ 0.0 1)) -; (expect "^ 0.0 1.0" 0.0 (^ 0.0 1.0)) +(expect "^ 0.0 1.0" 0.0 (^ 0.0 1.0)) ; (expect-failure "^ 0.0 -1" (^ 0.0 -1)) -; (expect-failure "^ 0.0 -1.0" (^ 0.0 -1.0)) +(expect-failure "^ 0.0 -1.0" (^ 0.0 -1.0)) ; (expect "^ 0.0 16" 0.0 (^ 0.0 16)) -; (expect "^ 0.0 16.0" 0.0 (^ 0.0 16.0)) +(expect "^ 0.0 16.0" 0.0 (^ 0.0 16.0)) ; (expect "^ 0.0 15" 0.0 (^ 0.0 15)) -; (expect "^ 0.0 15.0" 0.0 (^ 0.0 15.0)) +(expect "^ 0.0 15.0" 0.0 (^ 0.0 15.0)) -; (expect "^ -0 0" 1 (^ -0 0)) +(expect "^ -0 0" 1 (^ -0 0)) ; (expect "^ -0 0.0" 1.0 (^ -0 0.0)) -; (expect "^ -0 -0" 1 (^ -0 -0)) +(expect "^ -0 -0" 1 (^ -0 -0)) ; (expect "^ -0 -0.0" 1.0 (^ -0 -0.0)) -; (expect "^ -0 1" 0 (^ -0 1)) +(expect "^ -0 1" 0 (^ -0 1)) ; (expect "^ -0 1.0" 0.0 (^ -0 1.0)) -; (expect-failure "^ -0 -1" (^ -0 -1)) +(expect-failure "^ -0 -1" (^ -0 -1)) ; (expect-failure "^ -0 -1.0" (^ -0 -1.0)) -; (expect "^ -0 16" 0 (^ -0 16)) +(expect "^ -0 16" 0 (^ -0 16)) ; (expect "^ -0 16.0" 0.0 (^ -0 16.0)) -; (expect "^ -0 15" 0 (^ -0 15)) +(expect "^ -0 15" 0 (^ -0 15)) ; (expect "^ -0 15.0" 0.0 (^ -0 15.0)) ; (expect "^ -0.0 0" 1.0 (^ -0.0 0)) -; (expect "^ -0.0 0.0" 1.0 (^ -0.0 0.0)) +(expect "^ -0.0 0.0" 1.0 (^ -0.0 0.0)) ; (expect "^ -0.0 -0" 1.0 (^ -0.0 -0)) -; (expect "^ -0.0 -0.0" 1.0 (^ -0.0 -0.0)) +(expect "^ -0.0 -0.0" 1.0 (^ -0.0 -0.0)) ; (expect "^ -0.0 1" 0.0 (^ -0.0 1)) -; (expect "^ -0.0 1.0" 0.0 (^ -0.0 1.0)) +(expect "^ -0.0 1.0" 0.0 (^ -0.0 1.0)) ; (expect-failure "^ -0.0 -1" (^ -0.0 -1)) -; (expect-failure "^ -0.0 -1.0" (^ -0.0 -1.0)) +(expect-failure "^ -0.0 -1.0" (^ -0.0 -1.0)) ; (expect "^ -0.0 16" 0.0 (^ -0.0 16)) -; (expect "^ -0.0 16.0" 0.0 (^ -0.0 16.0)) +(expect "^ -0.0 16.0" 0.0 (^ -0.0 16.0)) ; (expect "^ -0.0 15" 0.0 (^ -0.0 15)) -; (expect "^ -0.0 15.0" 0.0 (^ -0.0 15.0)) +(expect "^ -0.0 15.0" 0.0 (^ -0.0 15.0)) -; (expect "^ 1 0" 1 (^ 1 0)) +(expect "^ 1 0" 1 (^ 1 0)) ; (expect "^ 1 0.0" 1.0 (^ 1 0.0)) -; (expect "^ 1 -0" 1 (^ 1 -0)) +(expect "^ 1 -0" 1 (^ 1 -0)) ; (expect "^ 1 -0.0" 1.0 (^ 1 -0.0)) -; (expect "^ 1 1" 1 (^ 1 1)) +(expect "^ 1 1" 1 (^ 1 1)) ; (expect "^ 1 1.0" 1.0 (^ 1 1.0)) -; (expect-failure "^ 1 -1" (^ 1 -1)) +(expect-failure "^ 1 -1" (^ 1 -1)) ; (expect "^ 1 -1.0" 1.0 (^ 1 -1.0)) -; (expect "^ 1 16" 1 (^ 1 16)) +(expect "^ 1 16" 1 (^ 1 16)) ; (expect "^ 1 16.0" 1.0 (^ 1 16.0)) -; (expect "^ 1 15" 1 (^ 1 15)) +(expect "^ 1 15" 1 (^ 1 15)) ; (expect "^ 1 15.0" 1.0 (^ 1 15.0)) ; (expect "^ 1.0 0" 1.0 (^ 1.0 0)) -; (expect "^ 1.0 0.0" 1.0 (^ 1.0 0.0)) +(expect "^ 1.0 0.0" 1.0 (^ 1.0 0.0)) ; (expect "^ 1.0 -0" 1.0 (^ 1.0 -0)) -; (expect "^ 1.0 -0.0" 1.0 (^ 1.0 -0.0)) +(expect "^ 1.0 -0.0" 1.0 (^ 1.0 -0.0)) ; (expect "^ 1.0 1" 1.0 (^ 1.0 1)) -; (expect "^ 1.0 1.0" 1.0 (^ 1.0 1.0)) +(expect "^ 1.0 1.0" 1.0 (^ 1.0 1.0)) ; (expect "^ 1.0 -1" 1.0 (^ 1.0 -1)) -; (expect "^ 1.0 -1.0" 1.0 (^ 1.0 -1.0)) +(expect "^ 1.0 -1.0" 1.0 (^ 1.0 -1.0)) ; (expect "^ 1.0 16" 1.0 (^ 1.0 16)) -; (expect "^ 1.0 16.0" 1.0 (^ 1.0 16.0)) +(expect "^ 1.0 16.0" 1.0 (^ 1.0 16.0)) ; (expect "^ 1.0 15" 1.0 (^ 1.0 15)) -; (expect "^ 1.0 15.0" 1.0 (^ 1.0 15.0)) +(expect "^ 1.0 15.0" 1.0 (^ 1.0 15.0)) -; (expect "^ -1 0" 1 (^ -1 0)) +(expect "^ -1 0" 1 (^ -1 0)) ; (expect "^ -1 0.0" 1.0 (^ -1 0.0)) -; (expect "^ -1 -0" 1 (^ -1 -0)) +(expect "^ -1 -0" 1 (^ -1 -0)) ; (expect "^ -1 -0.0" 1.0 (^ -1 -0.0)) -; (expect "^ -1 1" -1 (^ -1 1)) +(expect "^ -1 1" -1 (^ -1 1)) ; (expect "^ -1 1.0" -1.0 (^ -1 1.0)) -; (expect-failure "^ -1 -1" (^ -1 -1)) +(expect-failure "^ -1 -1" (^ -1 -1)) ; (expect "^ -1 -1.0" -1.0 (^ -1 -1.0)) -; (expect "^ -1 16" 1 (^ -1 16)) +(expect "^ -1 16" 1 (^ -1 16)) ; (expect "^ -1 16.0" 1.0 (^ -1 16.0)) -; (expect "^ -1 15" -1 (^ -1 15)) +(expect "^ -1 15" -1 (^ -1 15)) ; (expect "^ -1 15.0" -1.0 (^ -1 15.0)) ; (expect "^ -1.0 0" 1.0 (^ -1.0 0)) -; (expect "^ -1.0 0.0" 1.0 (^ -1.0 0.0)) +(expect "^ -1.0 0.0" 1.0 (^ -1.0 0.0)) ; (expect "^ -1.0 -0" 1.0 (^ -1.0 -0)) -; (expect "^ -1.0 -0.0" 1.0 (^ -1.0 -0.0)) +(expect "^ -1.0 -0.0" 1.0 (^ -1.0 -0.0)) ; (expect "^ -1.0 1" -1.0 (^ -1.0 1)) -; (expect "^ -1.0 1.0" -1.0 (^ -1.0 1.0)) +(expect "^ -1.0 1.0" -1.0 (^ -1.0 1.0)) ; (expect "^ -1.0 -1" -1.0 (^ -1.0 -1)) -; (expect "^ -1.0 -1.0" -1.0 (^ -1.0 -1.0)) +(expect "^ -1.0 -1.0" -1.0 (^ -1.0 -1.0)) ; (expect "^ -1.0 16" 1.0 (^ -1.0 16)) -; (expect "^ -1.0 16.0" 1.0 (^ -1.0 16.0)) +(expect "^ -1.0 16.0" 1.0 (^ -1.0 16.0)) ; (expect "^ -1.0 15" -1.0 (^ -1.0 15)) -; (expect "^ -1.0 15.0" -1.0 (^ -1.0 15.0)) +(expect "^ -1.0 15.0" -1.0 (^ -1.0 15.0)) ; (expect "^ 4.0 0" 1.0 (^ 4.0 0)) -; (expect "^ 4.0 0.0" 1.0 (^ 4.0 0.0)) +(expect "^ 4.0 0.0" 1.0 (^ 4.0 0.0)) ; (expect "^ 4.0 -0" 1.0 (^ 4.0 -0)) -; (expect "^ 4.0 -0.0" 1.0 (^ 4.0 -0.0)) +(expect "^ 4.0 -0.0" 1.0 (^ 4.0 -0.0)) ; (expect "^ 4.0 1" 4.0 (^ 4.0 1)) -; (expect "^ 4.0 1.0" 4.0 (^ 4.0 1.0)) +(expect "^ 4.0 1.0" 4.0 (^ 4.0 1.0)) ; (expect "^ 4.0 -1" 0.25 (^ 4.0 -1)) -; (expect "^ 4.0 -1.0" 0.25 (^ 4.0 -1.0)) +(expect "^ 4.0 -1.0" 0.25 (^ 4.0 -1.0)) ; (expect "^ 4.0 16" 4294967296.0 (^ 4.0 16)) -; (expect "^ 4.0 16.0" 4294967296.0 (^ 4.0 16.0)) +(expect "^ 4.0 16.0" 4294967296.0 (^ 4.0 16.0)) ; (expect "^ 4.0 15" 1073741824.0 (^ 4.0 15)) -; (expect "^ 4.0 15.0" 1073741824.0 (^ 4.0 15.0)) +(expect "^ 4.0 15.0" 1073741824.0 (^ 4.0 15.0)) ; (expect "^ -4.0 0" 1.0 (^ -4.0 0)) (expect "^ -4.0 0.0" 1.0 (^ -4.0 0.0)) ; (expect "^ -4.0 -0" 1.0 (^ -4.0 -0)) (expect "^ -4.0 -0.0" 1.0 (^ -4.0 -0.0)) ; (expect "^ -4.0 1" -4.0 (^ -4.0 1)) -; (expect "^ -4.0 1.0" -4.0 (^ -4.0 1.0)) +(expect "^ -4.0 1.0" -4.0 (^ -4.0 1.0)) ; (expect "^ -4.0 -1" -0.25 (^ -4.0 -1)) -; (expect "^ -4.0 -1.0" -0.25 (^ -4.0 -1.0)) +(expect "^ -4.0 -1.0" -0.25 (^ -4.0 -1.0)) ; (expect "^ -4.0 16" 4294967296.0 (^ -4.0 16)) -; (expect "^ -4.0 16.0" 4294967296.0 (^ -4.0 16.0)) +(expect "^ -4.0 16.0" 4294967296.0 (^ -4.0 16.0)) ; (expect "^ -4.0 15" -1073741824.0 (^ -4.0 15)) -; (expect "^ -4.0 15.0" -1073741824.0 (^ -4.0 15.0)) +(expect "^ -4.0 15.0" -1073741824.0 (^ -4.0 15.0)) -; (expect "^ integer integer" 81 (^ 3 4)) -; (expect "^ decimal decimal" 9.0 (^ 81.0 0.5)) +(expect "^ integer integer" 81 (^ 3 4)) +(expect "^ decimal decimal" 9.0 (^ 81.0 0.5)) ; (expect "^ integer decimal" 9.0 (^ 81 0.5)) ; (expect "^ decimal integer" 15.625 (^ 2.5 3)) @@ -421,13 +420,13 @@ ; 15.034465284692086701747761395233132973944448512421004399685858401206740385711739229018307610943234609057822959334669087436253689423614206061665462283698768757790600552385430913941421707844383369633809803959413869974997415115322843838226312287673293352959835 ; 3.466120406090666777582519661568003549307295836842780244500133445635634490670936927006970368136648330889718447039413255137656971927890831071689768359173260960739254160211017410322799793419223796996260056081828170546988461285168124170297427792046640116184356)) -; "===== truncating" -; (expect "round" 100 (round 100.1)) -; (expect "ceiling" 101 (ceiling 100.001)) -; (expect "floor" 101 (ceiling 100.001)) -; (expect "round 3 prec" 100.124 (round 100.1239 3)) -; (expect "ceiling 2 prec" 101.95 (ceiling 101.9401 2)) -; (expect "floor 1 prec" 100.1 (ceiling 100.01 1)) +"===== truncating" +(expect "round" 100 (round 100.1)) +(expect "ceiling" 101 (ceiling 100.001)) +(expect "floor" 101 (ceiling 100.001)) +(expect "round 3 prec" 100.124 (round 100.1239 3)) +(expect "ceiling 2 prec" 101.95 (ceiling 101.9401 2)) +(expect "floor 1 prec" 100.1 (ceiling 100.01 1)) "===== list equality" (expect "= list list" true (= [1 2 3] [1 2 3])) @@ -463,8 +462,8 @@ (module tm G (defcap G () true) (defun mk (id) (create-module-guard id)) - ; (defpact p (id1 id2) - ; (step [(create-pact-guard id1) (create-pact-guard id2)])) + (defpact p (id1 id2) + (step [(create-pact-guard id1) (create-pact-guard id2)])) (defun ug (id) true) ) @@ -474,14 +473,14 @@ (expect "not != moduleGuard moduleGuard" false (!= (tm.mk "1") (tm.mk "1"))) (expect "!= moduleGuard moduleGuard" true (!= (tm.mk "2") (tm.mk "1"))) -; "===== pact guard equality" -; (env-hash "YQo") -; (let ((pgs (tm.p "1" "2"))) -; (expect "= pactGuard pactGuard" true (= (at 0 pgs) (at 0 pgs))) -; (expect "not = pactGuard pactGuard" false (= (at 1 pgs) (at 0 pgs))) -; (expect "not != pactGuard pactGuard" false (!= (at 0 pgs) (at 0 pgs))) -; (expect "!= pactGuard pactGuard" true (!= (at 1 pgs) (at 0 pgs))) -; ) +"===== pact guard equality" +(env-hash "YQo") +(let ((pgs (tm.p "1" "2"))) + (expect "= pactGuard pactGuard" true (= (at 0 pgs) (at 0 pgs))) + (expect "not = pactGuard pactGuard" false (= (at 1 pgs) (at 0 pgs))) + (expect "not != pactGuard pactGuard" false (!= (at 0 pgs) (at 0 pgs))) + (expect "!= pactGuard pactGuard" true (!= (at 1 pgs) (at 0 pgs))) + ) "===== userGuard equality" diff --git a/pact-core/Pact/Core/IR/Desugar.hs b/pact-core/Pact/Core/IR/Desugar.hs index 19138aa44..14ab96259 100644 --- a/pact-core/Pact/Core/IR/Desugar.hs +++ b/pact-core/Pact/Core/IR/Desugar.hs @@ -192,6 +192,15 @@ desugarAppArityRaw f i RawSelect [e1, e2, e3] = App (Builtin (f RawSelectWithFields) i) ([e1, e2, e3]) i desugarAppArityRaw f i RawSort [e1, e2] = App (Builtin (f RawSortObject) i) [e1, e2] i +-- Rounding functions +desugarAppArityRaw f i RawRound [e1, e2] = + App (Builtin (f RawRoundPrec) i) [e1, e2] i +desugarAppArityRaw f i RawCeiling [e1, e2] = + App (Builtin (f RawCeilingPrec) i) [e1, e2] i +desugarAppArityRaw f i RawFloor [e1, e2] = + App (Builtin (f RawFloorPrec) i) [e1, e2] i + + desugarAppArityRaw f i RawStrToInt [e1, e2] = App (Builtin (f RawStrToIntBase) i) [e1, e2] i desugarAppArityRaw f i RawReadMsg [] = diff --git a/pact-core/Pact/Core/IR/Eval/RawBuiltin.hs b/pact-core/Pact/Core/IR/Eval/RawBuiltin.hs index 73b7d84ea..6e9ebff29 100644 --- a/pact-core/Pact/Core/IR/Eval/RawBuiltin.hs +++ b/pact-core/Pact/Core/IR/Eval/RawBuiltin.hs @@ -148,8 +148,9 @@ rawLogBase info b cont handler _env = \case when (base < 0 || n <= 0) $ throwExecutionError info (ArithmeticException "Illegal log base") let base' = fromIntegral base :: Double n' = fromIntegral n - out = round (Musl.trans_logBase base' n') - returnCEKValue cont handler (VLiteral (LInteger out)) + result = Musl.trans_logBase base' n' + guardNanOrInf info result + returnCEKValue cont handler (VLiteral (LInteger (round result))) -- if i' == 0 then throwExecutionError' (ArithmeticException "div by zero") -- else returnCEKValue cont handler (VLiteral (LInteger (div i i'))) [VLiteral (LDecimal base), VLiteral (LDecimal arg)] -> do From 70145c58f7f2955deafbabdf497d7439990ccb6c Mon Sep 17 00:00:00 2001 From: jmcardon Date: Sat, 9 Dec 2023 15:32:29 -0500 Subject: [PATCH 14/20] more semantics --- pact-core/Pact/Core/Builtin.hs | 3 + pact-core/Pact/Core/IR/Desugar.hs | 22 +- .../Pact/Core/Repl/Runtime/ReplBuiltin.hs | 1 + pact-core/Pact/Core/Semantics.md | 229 +++++++++++++++++- 4 files changed, 238 insertions(+), 17 deletions(-) diff --git a/pact-core/Pact/Core/Builtin.hs b/pact-core/Pact/Core/Builtin.hs index 0fe399367..412dc03fc 100644 --- a/pact-core/Pact/Core/Builtin.hs +++ b/pact-core/Pact/Core/Builtin.hs @@ -548,6 +548,7 @@ data ReplBuiltins | RContinuePact | RContinuePactRollback | RContinuePactRollbackYield + | RContinuePactRollbackYieldObj | RPactState | RResetPactState deriving (Show, Enum, Bounded, Eq) @@ -579,6 +580,7 @@ instance IsBuiltin ReplBuiltins where RContinuePact -> 1 RContinuePactRollback -> 2 RContinuePactRollbackYield -> 3 + RContinuePactRollbackYieldObj -> 4 REnvExecConfig -> 1 REnvNamespacePolicy -> 2 -- RLoad -> 1 @@ -647,6 +649,7 @@ replBuiltinsToText = \case RContinuePact -> "continue-pact" RContinuePactRollback -> "continue-pact-with-rollback" RContinuePactRollbackYield -> "continue-pact-rollback-yield" + RContinuePactRollbackYieldObj -> "continue-pact-rollback-yield-object" REnvExecConfig -> "env-exec-config" REnvNamespacePolicy -> "env-namespace-policy" diff --git a/pact-core/Pact/Core/IR/Desugar.hs b/pact-core/Pact/Core/IR/Desugar.hs index 14ab96259..ad51fb18d 100644 --- a/pact-core/Pact/Core/IR/Desugar.hs +++ b/pact-core/Pact/Core/IR/Desugar.hs @@ -221,19 +221,27 @@ instance DesugarBuiltin (ReplBuiltin RawBuiltin) where over termBuiltin RBuiltinWrap $ desugarOperator i dsg desugarAppArity i (RBuiltinWrap b) ne = desugarAppArityRaw RBuiltinWrap i b ne - desugarAppArity i (RBuiltinRepl RExpect) ([e1, e2, e3]) | isn't _Lam e3 = + -- (expect ) + desugarAppArity i (RBuiltinRepl RExpect) ([e1, e2, e3]) | isn't _Nullary e3 = App (Builtin (RBuiltinRepl RExpect) i) ([e1, e2, suspendTerm e3]) i - desugarAppArity i (RBuiltinRepl RExpectFailure) [e1, e2] | isn't _Lam e2 = + -- (expect-failure ) + desugarAppArity i (RBuiltinRepl RExpectFailure) [e1, e2] | isn't _Nullary e2 = App (Builtin (RBuiltinRepl RExpectFailure) i) [e1, suspendTerm e2] i - desugarAppArity i (RBuiltinRepl RExpectFailure) [e1, e2, e3] | isn't _Lam e2 = + -- (expect-failure ) + desugarAppArity i (RBuiltinRepl RExpectFailure) [e1, e2, e3] | isn't _Nullary e2 = App (Builtin (RBuiltinRepl RExpectFailureMatch) i) [e1, e2, suspendTerm e3] i - desugarAppArity i (RBuiltinRepl RContinuePact) [e1, e2] | isn't _Lam e2 = - App (Builtin (RBuiltinRepl RContinuePactRollback) i) [e1, e2] i + -- (pact-state ) desugarAppArity i (RBuiltinRepl RPactState) [e1] = App (Builtin (RBuiltinRepl RResetPactState) i) [e1] i - desugarAppArity i (RBuiltinRepl RContinuePact) [e1, e2, e3] - | isn't _Lam e2 && isn't _Lam e3 = + -- (continue-pact ) + desugarAppArity i (RBuiltinRepl RContinuePact) [e1, e2] = + App (Builtin (RBuiltinRepl RContinuePactRollback) i) [e1, e2] i + -- (continue-pact ) + desugarAppArity i (RBuiltinRepl RContinuePact) [e1, e2, e3] = App (Builtin (RBuiltinRepl RContinuePactRollbackYield) i) [e1, e2, e3] i + -- (continue-pact ) + desugarAppArity i (RBuiltinRepl RContinuePact) [e1, e2, e3, e4] = + App (Builtin (RBuiltinRepl RContinuePactRollbackYieldObj) i) [e1, e2, e3, e4] i desugarAppArity i b ne = App (Builtin b i) ne i diff --git a/pact-core/Pact/Core/Repl/Runtime/ReplBuiltin.hs b/pact-core/Pact/Core/Repl/Runtime/ReplBuiltin.hs index a3e822ffc..aa869a562 100644 --- a/pact-core/Pact/Core/Repl/Runtime/ReplBuiltin.hs +++ b/pact-core/Pact/Core/Repl/Runtime/ReplBuiltin.hs @@ -397,3 +397,4 @@ replRawBuiltinRuntime = \case RContinuePactRollbackYield -> continuePact REnvExecConfig -> envExecConfig REnvNamespacePolicy -> envNamespacePolicy + RContinuePactRollbackYieldObj -> continuePact diff --git a/pact-core/Pact/Core/Semantics.md b/pact-core/Pact/Core/Semantics.md index 2b131995c..63355ea55 100644 --- a/pact-core/Pact/Core/Semantics.md +++ b/pact-core/Pact/Core/Semantics.md @@ -20,9 +20,8 @@ Bullet points that are not filled are potential tasks - [x] DefCaps - [x] DefSchemas - [x] DefTables -- [ ] Defpacts -- [ ] Internal defs produce the right dependency tree (Needs test) - +- [x] Defpacts +- [x] Internal defs produce the right dependency tree (Needs test) ### Module evaluation semantics - [x] Module governance eval (Note: the way we do this via interpretation is still not concrete) @@ -36,6 +35,8 @@ Bullet points that are not filled are potential tasks - [x] Defconst name resolution - [x] Defcap name resolution - [x] DefSchema name resolution +- [x] DefTable name resolution +- [x] DefPact name resolution ## Environment @@ -44,11 +45,11 @@ Bullet points that are not filled are potential tasks - [x] Pactdb in env - [x] Tx hash - [x] Execution Mode -- [ ] Pact Step +- [x] Pact Step - [x] Chain data - [ ] Gas ref (In eval env? Unsure whether this will be abstracted out via `MonadGas`) - [ ] Gas Env? Also not sure, see above ^ -- [ ] Runtime Flags +- [x] Runtime Flags - [ ] Warnings - [ ] SPV Support - [x] Purity (now in pactdb) @@ -59,17 +60,16 @@ Bullet points that are not filled are potential tasks - [x] Capabilities environment - [ ] Gas log - [x] Pact Events -- [ ] Defpact environment `PactExec` +- [x] Defpact environment `PactExec` ### Environment semantic changes - RefStore no longer in `EvalEnv`. We do not resolve natives that way, but we potentially could for repl natives in modules. It is TBD - `InRepl` flag is not necessary currently. This may change, but it serves as a way to fork on-chain errors in prod-pact. ## Intepreter -- [ ] Stable interpreter API +- [X] Stable interpreter API - [ ] EvalResult and EvalInput-type API - ## Base Builtins ### at @@ -182,7 +182,7 @@ TODO: Do we want this still??? DELETED FROM EXISTENCE ### list-modules -(potentially) DELETED FROM EXISTENCE +TODO: (potentially) DELETED FROM EXISTENCE ### make-list - [x] implemented @@ -197,7 +197,7 @@ DELETED FROM EXISTENCE - [ ] Gas ### pact-version -(potentially) DELETED FROM EXISTENCE +TODO: (potentially) DELETED FROM EXISTENCE ### public-chain-data - Todo: provide in base loaded @@ -637,3 +637,212 @@ TODO: do we need this as a native? - [x] implemented guard case - [x] implemented keyset name case - [ ] Gas + +## Capability Builtins + +### compose-capability +- [x] implemented +- [ ] Gas + +### emit-event +- [x] implemented +- [ ] Gas + +### enforce-guard +- [x] implemented (Same as enforce-keyset, basically they're an alias) +- [ ] Gas + +### install-capability +- [x] implemented +- [ ] Gas + +### require-capability +- [x] implemented +- [ ] Gas + +### with-capability +- [x] implemented +- [ ] Gas + +## SPV Builtins + +### verify-spv +- [ ] implemented +- [ ] Gas + +## Commitment builtins + +### decrypt-cc20p1305 +TODO: do we want this in core? Can we delete? +- [ ] implemented +- [ ] gas + +### validate-keypair +TODO: do we want this in core? Can we delete? +- [ ] implemented +- [ ] gas + +## Guard Builtins +### create-capability-guard +- [x] implemented +- [ ] Gas + +### create-module-guard +- [x] implemented +- [ ] Gas + +### create-pact-guard +- [x] implemented +- [ ] Gas + +### create-principal +- [x] implemented +- [ ] Gas + +### create-user-guard +- [x] implemented +- [x] executed as sys only +- [ ] Gas + +## is-principal +- [x] implemented +- [ ] Gas + +## keyset-ref-guard +- [x] implemented +- [ ] Gas + +## typeof-principal +- [x] implemented +- [ ] Gas + +## validate-principal +- [x] implemented +- [ ] Gas + +## Zk Builtins + +## pairing-check +- [x] implemented +- [x] ensure points that are tested are on the curve +- [ ] Gas + +## point-add +- [x] implemented +- [x] ensure points that are tested are on the curve +- [ ] Gas + +## scalar-mult +- [x] implemented +- [x] ensure points that are tested are on the curve +- [ ] Gas + +## REPL-only Builtins + +### begin-tx +- [x] implemented + +### bench +- [ ] implemented + +### commit-tx +- [x] implemented + +### continue=-pact +- [x] implemented all 4 overloads + +### env-data +- [x] implemented + +### env-dynref +TODO: may not be necessary with new fv +- [ ] implemented + +### env-enable-repl-natives +- [ ] implemented + +### env-entity +To be removed + +### env-events +- [x] implemented + +### env-exec-config +- [x] implemented + +### env-gas +- [ ] implemented + +### env-gaslimit +- [ ] implemented + +### env-gaslog +- [ ] implemented + +### env-gasmodel +- [ ] implemented + +### env-gasprice +- [ ] implemented + +### env-gasrate +- [ ] implemented + +### env-hash +- [x] implemented + +### env-keys +- [x] implemented + +### env-namespace-policy +- [x] implemented + +### env-sigs +- [x] implemented + + +### env-simulate-onchain +- [ ] This is a specific one related to error forking in pact. Likely we will implement it at a later date. + +### expect +- [x] implemented + +### expect-failure +- [x] implemented + +### expect-that +- [x] implemented + +### format-address +TODO: what are we doing about this? + +### load +- [x] implemented + +### mock-spv +- [ ] implemented + +### pact-state +- [x] implemented 1-arg +- [x] implemented 2-arg + +### print +- [x] implemented + +### rollback-tx +- [x] implemented + +### sig-keyset +- [x] implemented + +### test-capability +- [x] implemented + +### typecheck +- [ ] TODO: implement using new typed core + +### verify +- [ ] implemented + +### with-applied-env +DELETED. Unnecessary with core's arch. From f08ade3bdf3ccd06d39ea87b42ad1ef265e73c74 Mon Sep 17 00:00:00 2001 From: jmcardon Date: Sun, 10 Dec 2023 13:56:33 -0500 Subject: [PATCH 15/20] meta.repl and toplevel.repl --- .../Pact/Core/Test/LexerParserTests.hs | 2 +- pact-core-tests/pact-tests/meta.repl | 37 ++++++++++ pact-core-tests/pact-tests/pairing.repl | 13 ++-- pact-core-tests/pact-tests/parsing.repl | 62 ++++++++++++++++ pact-core-tests/pact-tests/poseidon-hash.repl | 10 +++ pact-core-tests/pact-tests/toplevel.repl | 70 +++++++++++++++++++ pact-core/Pact/Core/Builtin.hs | 2 +- pact-core/Pact/Core/IR/Desugar.hs | 26 +++---- pact-core/Pact/Core/IR/Eval/CEK.hs | 6 +- pact-core/Pact/Core/IR/Eval/RawBuiltin.hs | 6 +- pact-core/Pact/Core/IR/ModuleHashing.hs | 10 +-- pact-core/Pact/Core/IR/Term.hs | 7 +- pact-core/Pact/Core/ModRefs.hs | 7 +- pact-core/Pact/Core/PactValue.hs | 13 ++-- pact-core/Pact/Core/Syntax/LexUtils.hs | 2 + pact-core/Pact/Core/Syntax/Lexer.x | 1 + pact-core/Pact/Core/Syntax/ParseTree.hs | 34 +++++---- pact-core/Pact/Core/Syntax/Parser.y | 25 ++++--- pact-core/Pact/Core/Type.hs | 12 ++-- 19 files changed, 272 insertions(+), 73 deletions(-) create mode 100644 pact-core-tests/pact-tests/meta.repl create mode 100644 pact-core-tests/pact-tests/parsing.repl create mode 100644 pact-core-tests/pact-tests/poseidon-hash.repl create mode 100644 pact-core-tests/pact-tests/toplevel.repl diff --git a/pact-core-tests/Pact/Core/Test/LexerParserTests.hs b/pact-core-tests/Pact/Core/Test/LexerParserTests.hs index f6c06734a..cf641d41c 100644 --- a/pact-core-tests/Pact/Core/Test/LexerParserTests.hs +++ b/pact-core-tests/Pact/Core/Test/LexerParserTests.hs @@ -179,7 +179,7 @@ exprGen = Gen.recursive Gen.choice (Gen.constant . Lisp.TyPrim <$> [minBound ..]) [Lisp.TyList <$> typeGen ,pure Lisp.TyPolyList - ,Lisp.TyModRef <$> moduleNameGen + ,Lisp.TyModRef <$> Gen.list (Range.constant 1 5) moduleNameGen ,pure Lisp.TyGuard ,pure Lisp.TyKeyset ,Lisp.TyObject <$> parsedTyNameGen diff --git a/pact-core-tests/pact-tests/meta.repl b/pact-core-tests/pact-tests/meta.repl new file mode 100644 index 000000000..257c5b477 --- /dev/null +++ b/pact-core-tests/pact-tests/meta.repl @@ -0,0 +1,37 @@ +(define-keyset 'k (sig-keyset)) + +(module mod 'k + @doc "this defines mod" + @model [(property (do (crazy stuff)))] + + (defun foo () + @doc "foo the town" + 1) + + (defun foobar () + "docstrings work without @doc" + 2) + + (defun docmodel () + @doc "stuff" + @model [(property stuff)] + 3) + + (defun modeldoc () + @model [(property stuff) (invariant stuff2)] + @doc "stuff" + 4) + + (defconst BAR 1 @doc "barring disbelief") + + (defconst BAZ 2 "docstrings work without @doc") + + (defschema schema + @model [(property stuff)] a:integer) + + (defschema schema2 + "a schema" a:integer) + + (deftable tbl:{schema} @doc "a table") + (deftable tbl2:{schema2} "a table") +) diff --git a/pact-core-tests/pact-tests/pairing.repl b/pact-core-tests/pact-tests/pairing.repl index 5650e35ff..b9edd46d3 100644 --- a/pact-core-tests/pact-tests/pairing.repl +++ b/pact-core-tests/pact-tests/pairing.repl @@ -82,14 +82,13 @@ (let* ((curve-inf {'x:0, 'y:0}) - (vk_x (fold (point-add "g1") curve-inf (zip (scalar-mult 'g1) (drop 1 (at 'ic verifying-key)) input))) - (vk_x1 (point-add 'g1 vk_x (at 0 (at 'ic verifying-key)))) + (vk_x (fold (point-add "g1") curve-inf (zip (scalar-mult "g1") (drop 1 (at "ic" verifying-key)) input))) + (vk_x1 (point-add "g1" vk_x (at 0 (at "ic" verifying-key)))) ) - (pairing-check - [(negate-point-g1 (at 'proofA proof)) (at 'alfa1 verifying-key) vk_x1 (at 'proofC proof)] - [(at 'proofB proof) (at 'beta2 verifying-key) (at 'gamma2 verifying-key) (at 'delta2 verifying-key)] - ) - ) + (pairing-check + [(negate-point-g1 (at "proofA" proof)) (at 'alfa1 verifying-key) vk_x1 (at 'proofC proof)] + [(at 'proofB proof) (at 'beta2 verifying-key) (at 'gamma2 verifying-key) (at 'delta2 verifying-key)] + )) ) ) diff --git a/pact-core-tests/pact-tests/parsing.repl b/pact-core-tests/pact-tests/parsing.repl new file mode 100644 index 000000000..c7047222a --- /dev/null +++ b/pact-core-tests/pact-tests/parsing.repl @@ -0,0 +1,62 @@ +;; parsing.repl: success means forms in this file parsed successfully. +;; errors have to be handled via "bad" scripts in tests/pact/bad + +;; semicolon in expr +;; =========== +(+ 1 2 + ; + ) + +;; in-module productions +;; note this is parsed, compiled, and loaded, so not just parsing +;; =========== +(interface quux (defun f ())) + +(define-namespace 'bar (sig-keyset) (sig-keyset)) + +(namespace 'bar) + +(interface baz (defun f ())) + +(module mod-parse-test G + "test in-module parsing" + (defcap G () true) + + (defun defun-with-semicolon () + "parses with semicolon" + 1 + ; + ;; + ) + + (defun modref-types + ( ref:module{bar.baz, quux} ) + "test module ref parsing" + 1) + + ; (defun test-cond (a) + ; (cond ((< a 10) "a") + ; ((< a 20) "b") + ; ((< a 30) "c") + ; "d")) +) + + + + +;; semicolon in expr again +(+ 1 + ; This is fine + 2 + ) + + +(expect + "list equivalence with commas or without" + [1 "2" true (+ 3 4)] + [1, "2", true, (+ 3 4)]) + +; (expect +; "cond folds ifs correctly" +; "acbd" +; (fold (+) "" [(test-cond 1) (test-cond 21) (test-cond 11) (test-cond 31)])) diff --git a/pact-core-tests/pact-tests/poseidon-hash.repl b/pact-core-tests/pact-tests/poseidon-hash.repl new file mode 100644 index 000000000..aeabeb012 --- /dev/null +++ b/pact-core-tests/pact-tests/poseidon-hash.repl @@ -0,0 +1,10 @@ +;; Test poseidon-hash + +(expect "1 should equal 18586133768512220936620570745912940619677854269274689475585506675881198879027" 18586133768512220936620570745912940619677854269274689475585506675881198879027 (poseidon-hash-hack-a-chain 1)) +(expect "1 2 should equal 7853200120776062878684798364095072458815029376092732009249414926327459813530" 7853200120776062878684798364095072458815029376092732009249414926327459813530 (poseidon-hash-hack-a-chain 1 2)) +(expect "1 2 3 should equal 6542985608222806190361240322586112750744169038454362455181422643027100751666" 6542985608222806190361240322586112750744169038454362455181422643027100751666 (poseidon-hash-hack-a-chain 1 2 3)) +(expect "1 2 3 4 should equal 18821383157269793795438455681495246036402687001665670618754263018637548127333" 18821383157269793795438455681495246036402687001665670618754263018637548127333 (poseidon-hash-hack-a-chain 1 2 3 4)) +(expect "1 2 3 4 5 should equal 6183221330272524995739186171720101788151706631170188140075976616310159254464" 6183221330272524995739186171720101788151706631170188140075976616310159254464 (poseidon-hash-hack-a-chain 1 2 3 4 5)) +(expect "1 2 3 4 5 6 should equal 20400040500897583745843009878988256314335038853985262692600694741116813247201" 20400040500897583745843009878988256314335038853985262692600694741116813247201 (poseidon-hash-hack-a-chain 1 2 3 4 5 6)) +(expect "1 2 3 4 5 6 7 should equal 12748163991115452309045839028154629052133952896122405799815156419278439301912" 12748163991115452309045839028154629052133952896122405799815156419278439301912 (poseidon-hash-hack-a-chain 1 2 3 4 5 6 7)) +(expect "1 2 3 4 5 6 7 8 should equal 18604317144381847857886385684060986177838410221561136253933256952257712543953" 18604317144381847857886385684060986177838410221561136253933256952257712543953 (poseidon-hash-hack-a-chain 1 2 3 4 5 6 7 8)) diff --git a/pact-core-tests/pact-tests/toplevel.repl b/pact-core-tests/pact-tests/toplevel.repl new file mode 100644 index 000000000..0bef946fa --- /dev/null +++ b/pact-core-tests/pact-tests/toplevel.repl @@ -0,0 +1,70 @@ + +;; +;; toplevel.repl: test that toplevel-only builtins +;; fail in module context but work in non-module context. +;; MAINTENANCE NOTE: for every built-in created using "setTopLevelOnly", +;; please add both "success" and "failure" cases below. +;; + +(begin-tx) + +;; ease restrictions requiring namespaced keysets +;; define-keyset success case +(define-keyset 'k (sig-keyset)) + +(module toplevel 'k + (defschema tl a:integer) + + (deftable atable:{tl}) + (deftable atable-bad:{tl}) + + (defun bad-create-table (tbl) (create-table tbl)) + (defun bad-describe-table (tbl) (describe-table tbl)) + (defun bad-describe-keyset (k) (describe-keyset k)) + (defun bad-describe-module (m) (describe-module m)) + (defun bad-define-keyset (n k) (define-keyset n k)) + ; (defun bad-pact-version () (pact-version)) + ; (defun bad-list-modules () (list-modules)) + ; (defun bad-enforce-pact-version (v) (enforce-pact-version v)) + ) + +;; Success cases + +(create-table atable) +(commit-tx) +(describe-table toplevel.atable) +(describe-keyset 'k) +(describe-module "toplevel") +; (pact-version) +; (list-modules) +; (enforce-pact-version (pact-version)) +(use toplevel) + +;; failure cases + +(expect-failure "bad-create-table" (bad-create-table atable-bad)) +(expect-failure "bad-describe-table" (bad-describe-table atable)) +(expect-failure "bad-describe-keyset" (bad-describe-keyset 'k)) +(expect-failure "bad-describe-module" (bad-describe-module "toplevel")) +(expect-failure "bad-define-keyset" (bad-define-keyset 'j (sig-keyset))) +; (expect-failure "bad-pact-version" (bad-pact-version)) +; (expect-failure "bad-list-modules" (bad-list-modules)) +; (expect-failure "bad-enforce-pact-version" (bad-enforce-pact-version (pact-version))) + +; todo: enable repl natives +; (env-enable-repl-natives true) +(module repl-natives 'k + (defun f () (env-sigs [{'key: "bob",'caps: []}]))) +(expect + "env-sigs in module" + () + (f)) + +(env-data { 'b: "hello"}) +(expect + "env-data takes immediate, scoped effect" + 3 + (let ((a 1)) + (env-data { 'b: 2 }) ;; normally would not be in effect until next top-level + (+ a (read-integer "b")))) + diff --git a/pact-core/Pact/Core/Builtin.hs b/pact-core/Pact/Core/Builtin.hs index 412dc03fc..61d598616 100644 --- a/pact-core/Pact/Core/Builtin.hs +++ b/pact-core/Pact/Core/Builtin.hs @@ -575,7 +575,7 @@ instance IsBuiltin ReplBuiltins where RBeginNamedTx -> 1 RCommitTx -> 0 RRollbackTx -> 0 - RSigKeyset -> 1 + RSigKeyset -> 0 RTestCapability -> 1 RContinuePact -> 1 RContinuePactRollback -> 2 diff --git a/pact-core/Pact/Core/IR/Desugar.hs b/pact-core/Pact/Core/IR/Desugar.hs index ad51fb18d..88a54d530 100644 --- a/pact-core/Pact/Core/IR/Desugar.hs +++ b/pact-core/Pact/Core/IR/Desugar.hs @@ -401,13 +401,12 @@ desugarDefPact (Lisp.DefPact dpname margs rt (step:steps) _ _ i) = Just (mn,_) -> do let args' = toArg <$> margs steps' <- forM (step :| steps) \case - Lisp.Step s ms -> - Step <$> desugarLispTerm s <*> traverse (traverse desugarLispTerm) ms - Lisp.StepWithRollback s rb ms -> + Lisp.Step s _ -> + Step <$> desugarLispTerm s + Lisp.StepWithRollback s rb _ -> StepWithRollback <$> desugarLispTerm s <*> desugarLispTerm rb - <*> traverse (traverse desugarLispTerm) ms -- In DefPacts, last step is not allowed to rollback. when (hasRollback $ NE.last steps') $ @@ -702,12 +701,9 @@ defPactStepSCC -> Step ParsedName DesugarType b i -> Set Text defPactStepSCC mn cd = \case - Step step mSteps -> S.union (termSCC mn cd step) (stepsSCC mSteps) - StepWithRollback step rollback mSteps -> - S.unions $ stepsSCC mSteps : [termSCC mn cd step, termSCC mn cd rollback] - where - stepsSCC :: Maybe [Term ParsedName DesugarType b i] -> Set Text - stepsSCC = maybe S.empty (foldMap $ termSCC mn cd) + Step step -> termSCC mn cd step + StepWithRollback step rollback -> + S.unions $ [termSCC mn cd step, termSCC mn cd rollback] defSCC :: ModuleName @@ -828,7 +824,7 @@ renameType i = \case Lisp.TyList ty -> TyList <$> renameType i ty Lisp.TyModRef tmr -> - TyModRef tmr <$ resolveInterfaceName i tmr + TyModRef (S.fromList tmr) <$ traverse (resolveInterfaceName i) tmr Lisp.TyKeyset -> pure TyGuard Lisp.TyObject pn -> TyObject <$> resolveSchema pn @@ -978,10 +974,10 @@ renamePactStep => Step ParsedName DesugarType b i -> RenamerT b i m (Step Name Type b i) renamePactStep = \case - Step step mSteps -> - Step <$> renameTerm step <*> (traverse.traverse) renameTerm mSteps - StepWithRollback step rollback mSteps -> - StepWithRollback <$> renameTerm step <*> renameTerm rollback <*> (traverse.traverse) renameTerm mSteps + Step step -> + Step <$> renameTerm step + StepWithRollback step rollback -> + StepWithRollback <$> renameTerm step <*> renameTerm rollback renameDefPact :: (MonadEval b i m, DesugarBuiltin b) diff --git a/pact-core/Pact/Core/IR/Eval/CEK.hs b/pact-core/Pact/Core/IR/Eval/CEK.hs index 5c0016ea7..a0a91c3b9 100644 --- a/pact-core/Pact/Core/IR/Eval/CEK.hs +++ b/pact-core/Pact/Core/IR/Eval/CEK.hs @@ -121,7 +121,7 @@ evalCEK cont handler env (Var n info) = do Nothing -> throwExecutionError info (NameNotInScope (FullyQualifiedName mname (_nName n) mh)) NModRef m ifs -> case ifs of - [x] -> returnCEKValue cont handler (VModRef (ModRef m ifs (Just x))) + [x] -> returnCEKValue cont handler (VModRef (ModRef m ifs (Just (S.singleton x)))) [] -> throwExecutionError info (ModRefNotRefined (_nName n)) _ -> returnCEKValue cont handler (VModRef (ModRef m ifs Nothing)) NDynRef (DynamicRef dArg i) -> case RAList.lookup (view ceLocal env) i of @@ -306,7 +306,7 @@ applyPact i pc ps cont handler cenv nested = useEvalState esDefPactExec >>= \cas case (ps ^. psRollback, step) of (False, _) -> evalWithStackFrame i cont' handler cenv sf Nothing (ordinaryDefPactStepExec step) - (True, StepWithRollback _ rollbackExpr _) -> + (True, StepWithRollback _ rollbackExpr) -> evalWithStackFrame i cont' handler cenv sf Nothing rollbackExpr (True, Step{}) -> throwExecutionError i (DefPactStepHasNoRollback ps) _otherwise -> failInvariant i "DefPact not found" @@ -370,7 +370,7 @@ applyNestedPact i pc ps cont handler cenv = useEvalState esDefPactExec >>= \case case (ps ^. psRollback, step) of (False, _) -> evalWithStackFrame i cont' handler cenv' sf Nothing (ordinaryDefPactStepExec step) - (True, StepWithRollback _ rollbackExpr _) -> + (True, StepWithRollback _ rollbackExpr) -> evalWithStackFrame i cont' handler cenv' sf Nothing rollbackExpr (True, Step{}) -> throwExecutionError i (DefPactStepHasNoRollback ps) _otherwise -> failInvariant i "applyNestedPact: Expected a DefPact bot got something else" diff --git a/pact-core/Pact/Core/IR/Eval/RawBuiltin.hs b/pact-core/Pact/Core/IR/Eval/RawBuiltin.hs index 6e9ebff29..48d558aa4 100644 --- a/pact-core/Pact/Core/IR/Eval/RawBuiltin.hs +++ b/pact-core/Pact/Core/IR/Eval/RawBuiltin.hs @@ -1113,9 +1113,11 @@ defineKeySet' info cont handler env ksname newKs = do defineKeySet :: (IsBuiltin b, MonadEval b i m) => NativeFunction b i m defineKeySet info b cont handler env = \case - [VString ksname, VGuard (GKeyset ks)] -> + [VString ksname, VGuard (GKeyset ks)] -> do + enforceTopLevelOnly info b defineKeySet' info cont handler env ksname ks - [VString ksname] -> + [VString ksname] -> do + enforceTopLevelOnly info b readKeyset' ksname >>= \case Just newKs -> defineKeySet' info cont handler env ksname newKs diff --git a/pact-core/Pact/Core/IR/ModuleHashing.hs b/pact-core/Pact/Core/IR/ModuleHashing.hs index 821cb9e36..b633a9a50 100644 --- a/pact-core/Pact/Core/IR/ModuleHashing.hs +++ b/pact-core/Pact/Core/IR/ModuleHashing.hs @@ -67,8 +67,8 @@ updateDefHashes mname mhash = \case DCap $ over dcapTerm (updateTermHashes mname mhash) $ over (dcapMeta.dcMetaFqName) (updateFqNameHash mname mhash) d DPact d -> - let updateStep (Step e1 m) = Step (updateTermHashes mname mhash e1) m - updateStep (StepWithRollback e1 e2 m) = StepWithRollback (updateTermHashes mname mhash e1) (updateTermHashes mname mhash e2) m + let updateStep (Step e1) = Step (updateTermHashes mname mhash e1) + updateStep (StepWithRollback e1 e2) = StepWithRollback (updateTermHashes mname mhash e1) (updateTermHashes mname mhash e2) in DPact $ over dpSteps (fmap updateStep) d DTable d -> DTable d DSchema s -> DSchema s @@ -262,7 +262,7 @@ encodeType :: Type -> Builder encodeType = \case TyPrim p -> encodePrim p TyList l -> brackets (encodeType l) - TyModRef m -> "module" <> braces (T.encodeUtf8Builder (renderModuleName m)) + TyModRef m -> "module" <> braces (commaSep (T.encodeUtf8Builder . renderModuleName <$> S.toList m)) -- Todo: this seems potentially inefficient? -- Maybe we preserve schema names instead TyObject sc -> "object" <> braces (encodeSchema sc) @@ -375,8 +375,8 @@ encodeDefPact (DefPact dpn args rty steps _i) = parens $ "defpact" <+> encodeText dpn <> encodeTyAnn rty <+> encodeArgList args <+> hsep (encodeStep <$> NE.toList steps) where - encodeStep (Step t1 _) = parens ("step" <+> encodeTerm t1) - encodeStep (StepWithRollback t1 t2 _) = + encodeStep (Step t1) = parens ("step" <+> encodeTerm t1) + encodeStep (StepWithRollback t1 t2) = parens ("step-with-rollback" <+> encodeTerm t1 <+> encodeTerm t2) -- todo: defcap meta diff --git a/pact-core/Pact/Core/IR/Term.hs b/pact-core/Pact/Core/IR/Term.hs index 625566767..30ea11048 100644 --- a/pact-core/Pact/Core/IR/Term.hs +++ b/pact-core/Pact/Core/IR/Term.hs @@ -51,11 +51,10 @@ data Defun name ty builtin info } deriving (Show, Functor) data Step name ty builtin info - = Step (Term name ty builtin info) (Maybe [Term name ty builtin info]) + = Step (Term name ty builtin info) | StepWithRollback (Term name ty builtin info) (Term name ty builtin info) - (Maybe [Term name ty builtin info]) deriving (Show, Functor) hasRollback :: Step n t b i -> Bool @@ -63,8 +62,8 @@ hasRollback Step{} = False hasRollback StepWithRollback{} = True ordinaryDefPactStepExec :: Step name ty builtin info -> Term name ty builtin info -ordinaryDefPactStepExec (Step expr _) = expr -ordinaryDefPactStepExec (StepWithRollback expr _ _) = expr +ordinaryDefPactStepExec (Step expr) = expr +ordinaryDefPactStepExec (StepWithRollback expr _) = expr data ConstVal term = TermConst term diff --git a/pact-core/Pact/Core/ModRefs.hs b/pact-core/Pact/Core/ModRefs.hs index 8cb9f7166..5cd82cfc8 100644 --- a/pact-core/Pact/Core/ModRefs.hs +++ b/pact-core/Pact/Core/ModRefs.hs @@ -9,9 +9,12 @@ module Pact.Core.ModRefs ) where import Control.Lens + +import Data.Set(Set) import Pact.Core.Names import Pact.Core.Pretty +import qualified Data.Set as S -- | Original module reference data ModRef @@ -20,14 +23,14 @@ data ModRef -- ^ Original module , _mrImplemented :: [ModuleName] -- ^ All implemented interfaces - , _mrRefined :: Maybe ModuleName + , _mrRefined :: Maybe (Set ModuleName) -- ^ The "Selected" interface from a type refinement } deriving (Show) instance Pretty ModRef where pretty (ModRef _mn _imp mref) = case mref of - Just ref -> "module" <> braces (pretty ref) + Just ref -> "module" <> braces (pretty (S.toList ref)) Nothing -> "module" instance Eq ModRef where diff --git a/pact-core/Pact/Core/PactValue.hs b/pact-core/Pact/Core/PactValue.hs index 954b9f46b..40a96c599 100644 --- a/pact-core/Pact/Core/PactValue.hs +++ b/pact-core/Pact/Core/PactValue.hs @@ -31,6 +31,7 @@ import Data.Decimal(Decimal) import qualified Data.Vector as V import qualified Data.Map.Strict as M import qualified Pact.Time as PactTime +import qualified Data.Set as S import Pact.Core.Type import Pact.Core.Names @@ -87,7 +88,7 @@ synthesizePvType = \case PLiteral l -> typeOfLit l PList _ -> TyList TyUnit PGuard _ -> TyGuard - PModRef mr -> TyModRef (_mrModule mr) + PModRef mr -> TyModRef (S.fromList (_mrImplemented mr)) PObject f -> let tys = synthesizePvType <$> f in TyObject (Schema tys) @@ -126,11 +127,11 @@ checkPvType ty = \case TyList t' | all (isJust . checkPvType t') l -> Just (TyList t') TyAnyList -> Just TyAnyList _ -> Nothing - PModRef (ModRef _orig ifs refined) -> case ty of - TyModRef mn - | refined == Just mn -> Just (TyModRef mn) - | isJust refined -> Nothing - | mn `elem` ifs && refined == Nothing -> Just (TyModRef mn) + PModRef (ModRef _orig ifs refinedSet) -> case ty of + TyModRef mns + | Just rf <- refinedSet, mns `S.isSubsetOf` rf -> Just (TyModRef mns) + | isJust refinedSet -> Nothing + | mns `S.isSubsetOf` (S.fromList ifs) && refinedSet == Nothing -> Just (TyModRef mns) | otherwise -> Nothing _ -> Nothing PCapToken _ -> Nothing diff --git a/pact-core/Pact/Core/Syntax/LexUtils.hs b/pact-core/Pact/Core/Syntax/LexUtils.hs index d4f7d2c57..68e4c730b 100644 --- a/pact-core/Pact/Core/Syntax/LexUtils.hs +++ b/pact-core/Pact/Core/Syntax/LexUtils.hs @@ -120,6 +120,7 @@ data Token | TokenSuspend | TokenDynAcc | TokenBindAssign + | TokenInvariant -- Repl-specific tokens | TokenLoad -- Layout @@ -316,6 +317,7 @@ renderTokenText = \case TokenBindAssign -> ":=" TokenDynAcc -> "::" TokenProperty -> "property" + TokenInvariant -> "invariant" -- TokenEq -> "=" -- TokenNeq -> "!=" -- TokenGT -> ">" diff --git a/pact-core/Pact/Core/Syntax/Lexer.x b/pact-core/Pact/Core/Syntax/Lexer.x index c4ed5b040..74305db47 100644 --- a/pact-core/Pact/Core/Syntax/Lexer.x +++ b/pact-core/Pact/Core/Syntax/Lexer.x @@ -59,6 +59,7 @@ tokens :- defpact { token TokenDefPact } defproperty { token TokenDefProperty } property { token TokenProperty } + invariant { token TokenInvariant } interface { token TokenInterface } module { token TokenModule } bless { token TokenBless } diff --git a/pact-core/Pact/Core/Syntax/ParseTree.hs b/pact-core/Pact/Core/Syntax/ParseTree.hs index 60c36dd82..b1df17c08 100644 --- a/pact-core/Pact/Core/Syntax/ParseTree.hs +++ b/pact-core/Pact/Core/Syntax/ParseTree.hs @@ -42,7 +42,7 @@ data Type = TyPrim PrimType | TyList Type | TyPolyList - | TyModRef ModuleName + | TyModRef [ModuleName] | TyKeyset | TyObject ParsedTyName | TyTable ParsedTyName @@ -74,7 +74,7 @@ instance Pretty Type where pretty = \case TyPrim prim -> pretty prim TyList t -> brackets (pretty t) - TyModRef mn -> "module" <> braces (pretty mn) + TyModRef mn -> "module" <> braces (hsep (punctuate comma (pretty <$> mn))) TyPolyList -> "list" TyKeyset -> "keyset" TyObject qn -> "object" <> braces (pretty qn) @@ -105,7 +105,7 @@ data Defun i , _dfunRetType :: Maybe Type , _dfunTerm :: Expr i , _dfunDocs :: Maybe Text - , _dfunModel :: Maybe [Expr i] + , _dfunModel :: Maybe [FVFunModel i] , _dfunInfo :: i } deriving Show @@ -130,7 +130,7 @@ data DefCap i , _dcapRetType :: Maybe Type , _dcapTerm :: Expr i , _dcapDocs :: Maybe Text - , _dcapModel :: Maybe [Expr i] + , _dcapModel :: Maybe [FVFunModel i] , _dcapMeta :: Maybe DCapMeta , _dcapInfo :: i } deriving Show @@ -140,7 +140,7 @@ data DefSchema i { _dscName :: Text , _dscArgs :: [Arg] , _dscDocs :: Maybe Text - , _dscModel :: Maybe [Expr i] + , _dscModel :: Maybe [FVFunModel i] , _dscInfo :: i } deriving Show @@ -153,8 +153,8 @@ data DefTable i } deriving Show data PactStep i - = Step (Expr i) (Maybe [Expr i]) - | StepWithRollback (Expr i) (Expr i) (Maybe [Expr i]) + = Step (Expr i) (Maybe [FVFunModel i]) + | StepWithRollback (Expr i) (Expr i) (Maybe [FVFunModel i]) deriving Show data DefPact i @@ -164,7 +164,7 @@ data DefPact i , _dpRetType :: Maybe Type , _dpSteps :: [PactStep i] , _dpDocs :: Maybe Text - , _dpModel :: Maybe [Expr i] + , _dpModel :: Maybe [FVFunModel i] , _dpInfo :: i } deriving Show @@ -199,9 +199,19 @@ newtype Property i = Property (Expr i) deriving Show +newtype Invariant i + = Invariant (Expr i) + deriving Show + data FVModel i = FVDefProperty (DefProperty i) | FVProperty (Property i) + | FVInvariant (Invariant i) + deriving Show + +data FVFunModel i + = FVFunProperty (Property i) + | FVFunInvariant (Invariant i) deriving Show data Module i @@ -228,7 +238,7 @@ data Interface i , _ifDefns :: [IfDef i] , _ifImports :: [Import] , _ifDocs :: Maybe Text - , _ifModel :: Maybe [Expr i] + , _ifModel :: Maybe [FVFunModel i] , _ifInfo :: i } deriving Show @@ -238,7 +248,7 @@ data IfDefun i , _ifdArgs :: [MArg] , _ifdRetType :: Maybe Type , _ifdDocs :: Maybe Text - , _ifdModel :: Maybe [Expr i] + , _ifdModel :: Maybe [FVFunModel i] , _ifdInfo :: i } deriving Show @@ -248,7 +258,7 @@ data IfDefCap i , _ifdcArgs :: [MArg] , _ifdcRetType :: Maybe Type , _ifdcDocs :: Maybe Text - , _ifdcModel :: Maybe [Expr i] + , _ifdcModel :: Maybe [FVFunModel i] , _ifdcMeta :: Maybe DCapMeta , _ifdcInfo :: i } deriving Show @@ -259,7 +269,7 @@ data IfDefPact i , _ifdpArgs :: [MArg] , _ifdpRetType :: Maybe Type , _ifdpDocs :: Maybe Text - , _ifdpModel :: Maybe [Expr i] + , _ifdpModel :: Maybe [FVFunModel i] , _ifdpInfo :: i } deriving Show diff --git a/pact-core/Pact/Core/Syntax/Parser.y b/pact-core/Pact/Core/Syntax/Parser.y index 9e3e8c444..335ce8513 100644 --- a/pact-core/Pact/Core/Syntax/Parser.y +++ b/pact-core/Pact/Core/Syntax/Parser.y @@ -62,6 +62,7 @@ import Pact.Core.Syntax.LexUtils defpact { PosToken TokenDefPact _ } defprop { PosToken TokenDefProperty _} property { PosToken TokenProperty _ } + invariant { PosToken TokenInvariant _ } bless { PosToken TokenBless _} implements { PosToken TokenImplements _ } true { PosToken TokenTrue _ } @@ -174,6 +175,7 @@ DefProperties :: { [FVModel SpanInfo] } DefProperty :: { FVModel SpanInfo } : '(' defprop IDENT DPropArgList ')' { FVDefProperty (DefProperty (getIdent $3) (fst $4) (snd $4)) } | '(' property Expr ')' { FVProperty (Property $3) } + | '(' invariant Expr ')' { FVInvariant (Invariant $3) } -- This rule seems gnarly, but essentially -- happy needs to resolve whether the arglist is present or not @@ -255,7 +257,7 @@ Defun :: { SpanInfo -> ParsedDefun } { Defun (getIdent $2) (reverse $5) $3 $8 (fst $7) (snd $7) } Defschema :: { SpanInfo -> DefSchema SpanInfo } - : defschema IDENT MDocOrModel NEArgList + : defschema IDENT MDocOrModel ArgList { DefSchema (getIdent $2) (reverse $4) (fst $3) (snd $3) } Deftable :: { SpanInfo -> DefTable SpanInfo } @@ -310,10 +312,14 @@ ArgList :: { [Arg] } Type :: { Type } : '[' Type ']' { TyList $2 } - | module '{' ModQual '}' { TyModRef (mkModName $3) } + | module '{' ModuleNames '}' { TyModRef (reverse $3) } | IDENT '{' ParsedTyName '}' {% objType (_ptInfo $1) (getIdent $1) $3} | IDENT {% primType (_ptInfo $1) (getIdent $1) } +ModuleNames :: { [ModuleName] } + : ModuleNames ',' ModQual { (mkModName $3) : $1 } + | ModQual { [mkModName $1] } + -- Annotations DocAnn :: { Text } : docAnn STR { getStr $2 } @@ -321,18 +327,19 @@ DocAnn :: { Text } DocStr :: { Text } : STR { getStr $1 } -ModelExprs :: { [ParsedExpr] } - : ModelExprs Expr { $2:$1 } +ModelExprs :: { [FVFunModel SpanInfo] } + : ModelExprs '(' property Expr ')' { FVFunProperty (Property $4) :$1 } + | ModelExprs '(' invariant Expr ')' { FVFunInvariant (Invariant $4) :$1 } | {- empty -} { [] } -MModel :: { Maybe [Expr SpanInfo] } +MModel :: { Maybe [FVFunModel SpanInfo] } : ModelAnn { Just $1 } | {- empty -} { Nothing } -ModelAnn :: { [Expr SpanInfo] } +ModelAnn :: { [FVFunModel SpanInfo] } : modelAnn '[' ModelExprs ']' { reverse $3 } -MDocOrModel :: { (Maybe Text, Maybe [Expr SpanInfo])} +MDocOrModel :: { (Maybe Text, Maybe [FVFunModel SpanInfo])} : DocAnn ModelAnn { (Just $1, Just $2)} | ModelAnn DocAnn { (Just $2, Just $1) } | DocAnn { (Just $1, Nothing)} @@ -413,10 +420,6 @@ CapExpr :: { SpanInfo -> ParsedExpr } CapForm :: { CapForm SpanInfo } : withcap '(' ParsedName AppList ')' Block { WithCapability $3 (reverse $4) $6 } | c_usr_grd '(' ParsedName AppList ')' { CreateUserGuard $3 (reverse $4)} - -- | installcap '(' ParsedName AppList ')' { InstallCapability $3 $4 } - -- | reqcap '(' ParsedName AppList ')' { RequireCapability $3 $4 } - -- | composecap '(' ParsedName AppList ')' { ComposeCapability $3 $4 } - -- | emitevent '(' ParsedName AppList ')' { EmitEvent $3 $4 } LamArgs :: { [MArg] } : LamArgs IDENT ':' Type { (MArg (getIdent $2) (Just $4)):$1 } diff --git a/pact-core/Pact/Core/Type.hs b/pact-core/Pact/Core/Type.hs index 7e7f6a9e2..0554983b5 100644 --- a/pact-core/Pact/Core/Type.hs +++ b/pact-core/Pact/Core/Type.hs @@ -38,11 +38,13 @@ module Pact.Core.Type import Control.Lens import Data.List +import Data.Set(Set) import Data.Text(Text) import Data.Map.Strict(Map) import qualified Data.Text as T import qualified Data.Map.Strict as M +import qualified Data.Set as S import Pact.Core.Literal import Pact.Core.Names @@ -101,7 +103,7 @@ data Type -- ^ List aka [a] | TyAnyList -- ^ Any list - | TyModRef ModuleName + | TyModRef (Set ModuleName) -- ^ Module references | TyObject Schema -- ^ Objects @@ -226,8 +228,8 @@ instance Pretty Type where where liParens t@TyPrim{} = pretty t liParens t = Pretty.parens (pretty t) - TyModRef mr -> - "module" <> Pretty.braces (pretty mr) + TyModRef mrs -> + "module" <> Pretty.braces (Pretty.hsep (Pretty.punctuate Pretty.comma (pretty <$> S.toList mrs)) ) TyObject (Schema sc) -> let sc' = (\(k, v) -> pretty k <> ":" <> pretty v) <$> M.toList sc in "object" <> Pretty.braces (Pretty.hsep (Pretty.punctuate Pretty.comma sc')) @@ -243,7 +245,9 @@ renderType = \case TyPrim p -> renderPrimType p TyList t -> "[" <> renderType t <> "]" TyGuard -> "guard" - TyModRef mr -> "module" <> "{" <> renderModuleName mr <> "}" + TyModRef s -> + let s' = T.concat (intersperse ", " (renderModuleName <$> S.toList s)) + in "module" <> "{" <> s' <> "}" TyObject (Schema sc) -> let sc' = (\(k, v) -> _field k <> ":" <> renderType v) <$> M.toList sc in "object{" <> T.concat (intersperse ", " sc') <> "}" From 49eaf634842e15e8fcc3bfbb5fcb879f4f9ac36b Mon Sep 17 00:00:00 2001 From: jmcardon Date: Sun, 10 Dec 2023 15:00:59 -0500 Subject: [PATCH 16/20] leftpad and imports --- pact-core-tests/pact-tests/base64.repl | 14 +++-- pact-core-tests/pact-tests/imports.repl | 67 ++++++++++++++++++++++ pact-core-tests/pact-tests/leftpad.repl | 74 +++++++++++++++++++++++++ pact-core/Pact/Core/Errors.hs | 1 + pact-core/Pact/Core/Hash.hs | 16 +++++- pact-core/Pact/Core/IR/Desugar.hs | 29 +++++++--- pact-core/Pact/Core/Semantics.md | 3 +- pact-core/Pact/Core/Syntax/ParseTree.hs | 8 ++- pact-core/Pact/Core/Syntax/Parser.y | 2 +- 9 files changed, 197 insertions(+), 17 deletions(-) create mode 100644 pact-core-tests/pact-tests/imports.repl create mode 100644 pact-core-tests/pact-tests/leftpad.repl diff --git a/pact-core-tests/pact-tests/base64.repl b/pact-core-tests/pact-tests/base64.repl index b0850456c..e3a20ba19 100644 --- a/pact-core-tests/pact-tests/base64.repl +++ b/pact-core-tests/pact-tests/base64.repl @@ -22,24 +22,25 @@ (expect-failure "base64 decoding fails on non base64-encoded input" - ; "Could not decode string" + "Could not decode string" (base64-decode "aGVsbG8gd29ybGQh%")) (expect-failure "base64 decoding fails on garbage input 1" - ; "Could not decode string" + "Could not decode string" (base64-decode "aaa")) (expect-failure "base64 decoding fails on garbage input 2" - ; "Could not decode string" + "Could not decode string" (base64-decode "asdflk")) (expect-failure "base64 decoding fails on garbage input 3" - ; "Could not decode string" + "Could not decode string" (base64-decode "!@#$%&")) +; Todo: unicode escape codes? ; (expect-failure ; "base64 decoding fails on garbage input 4" ; "Could not decode string" @@ -49,3 +50,8 @@ ; "base64 decoding fails on garbage input 5" ; "Could not decode string" ; (base64-decode "+\x0000")) + +(expect-failure + "base64 decoding fails on non-canonical encodings" + "Could not base64-decode string" + (base64-decode "ZE==")) diff --git a/pact-core-tests/pact-tests/imports.repl b/pact-core-tests/pact-tests/imports.repl new file mode 100644 index 000000000..f97924db1 --- /dev/null +++ b/pact-core-tests/pact-tests/imports.repl @@ -0,0 +1,67 @@ +;; Positive unit tests for use/import-based forms +(begin-tx) +(module m G + (defcap G () true) + (defun f () true) +) +(commit-tx) +(begin-tx) +;; Show that empty imports work when hashes are +;; supplied. For a negative test, see: ./bad/bad-import-emptylist.pact +(module n H + (use m "AE_iUXehlMxeBhTp9E3w-lS1OXsp4ryqhG4iPJtlmGc" + []) + + (defcap H () true) + (defun g () true) +) + +(module o I + (use m [f]) + + (defcap I () true) + (defun h () true) +) + +(module p J + (use m "AE_iUXehlMxeBhTp9E3w-lS1OXsp4ryqhG4iPJtlmGc" + [f]) + + (defcap J () true) + (defun i () true) +) +(commit-tx) + +(begin-tx) +(interface iface + + (defschema p + flag:bool + other-field:string) + + (defconst pushin:object{p} {'flag:true, 'other-field:"future"}) + ) +(commit-tx) +(begin-tx) + +(module m g + + (use iface) + (defcap g () true) + + (defun get-pushin:object{p} () pushin) + (defconst obj2:object{p} {'flag:false, 'other-field:"yt"}) + ) + +(commit-tx) +;; Explicit imports +(begin-tx) +(module m g + + (use iface [p]) + (defcap g () true) + + (defconst obj2:object{p} {'flag:false, 'other-field:"yt"}) + ) + +(commit-tx) diff --git a/pact-core-tests/pact-tests/leftpad.repl b/pact-core-tests/pact-tests/leftpad.repl new file mode 100644 index 000000000..c47643b5c --- /dev/null +++ b/pact-core-tests/pact-tests/leftpad.repl @@ -0,0 +1,74 @@ +(begin-tx) +(define-keyset 'k (sig-keyset)) + +(module leftpad 'k + (defconst VERSION 1) + (defun left-pad (s i) + (+ (fold (+) "" (make-list i " ")) s))) + +(module impure 'k + (defconst VERSION 1) + (defschema foo-schema value:integer) + (deftable foo:{foo-schema}) + (defun ins (k v) (insert foo k v))) + +(create-table foo) + +(commit-tx) + +(begin-tx) + +(use leftpad) +(use impure) + +(module dep 'k + (defun dep-leftpad () (left-pad "hello" 3)) + (defun dep-impure (k v) (ins k { "value": v }))) + +(commit-tx) + +(begin-tx) + +(expect "leftpad works" " hello" (dep.dep-leftpad)) +(dep.dep-impure "a" 1) +(expect "impure works" { "value": 1 } (read impure.foo "a")) + +(rollback-tx) + +(begin-tx) + +(module leftpad 'k + (defconst VERSION 2) + (defun left-pad (s i) + (+ (fold (+) "" (make-list i " ")) s))) + +(module impure 'k + (defconst VERSION 2) + (defschema foo-schema value:integer) + (deftable foo:{foo-schema}) + (defun ins (k v) (insert foo k v))) + +(commit-tx) + +(begin-tx) + +(expect "leftpad works after update" " hello" (dep.dep-leftpad)) +(expect-failure "impure fails after update" (dep.dep-impure "b" 1)) + +(rollback-tx) + +(begin-tx) + +(use dep) + +(module impure 'k + (defconst VERSION 3) + (bless "o_4_FPBGezeMPBBnzTQd0iYLneAKxoKJeDkRpabBYxo") + (defschema foo-schema value:integer) + (deftable foo:{foo-schema}) + (defun ins (k v) (insert foo k v))) + +(commit-tx) + +(dep.dep-impure "b" 1) +(expect "impure works with blessed hash" { "value": 1 } (read impure.foo "b")) diff --git a/pact-core/Pact/Core/Errors.hs b/pact-core/Pact/Core/Errors.hs index 23dfec5fa..69c8bc1ac 100644 --- a/pact-core/Pact/Core/Errors.hs +++ b/pact-core/Pact/Core/Errors.hs @@ -149,6 +149,7 @@ data DesugarError | InvalidDefInSchemaPosition Text | InvalidDynamicInvoke Text | DuplicateDefinition Text + | InvalidBlessedHash Text deriving Show instance Exception DesugarError diff --git a/pact-core/Pact/Core/Hash.hs b/pact-core/Pact/Core/Hash.hs index e36768991..4c54c577f 100644 --- a/pact-core/Pact/Core/Hash.hs +++ b/pact-core/Pact/Core/Hash.hs @@ -27,6 +27,7 @@ module Pact.Core.Hash , defaultPactHash , placeholderHash , moduleHashToText +, parseModuleHash ) where import Control.DeepSeq @@ -73,9 +74,20 @@ pactInitialHash = initialHash pactHashLength :: Int pactHashLength = 32 -hash :: ByteString -> Hash -hash = Hash . toShort . ByteArray.convert . Crypto.hashWith Crypto.Blake2b_256 +unsafeBsToPactHash :: ByteString -> Hash +unsafeBsToPactHash = Hash . toShort + +unsafeBsToModuleHash :: ByteString -> ModuleHash +unsafeBsToModuleHash = ModuleHash . unsafeBsToPactHash +parseModuleHash :: Text -> Maybe ModuleHash +parseModuleHash t = case decodeBase64UrlUnpadded (T.encodeUtf8 t) of + Left{} -> Nothing + Right bs | B.length bs == pactHashLength -> Just (unsafeBsToModuleHash bs) + | otherwise -> Nothing + +hash :: ByteString -> Hash +hash = unsafeBsToPactHash . ByteArray.convert . Crypto.hashWith Crypto.Blake2b_256 -- hash :: forall h . Reifies h HashAlgo => ByteString -> TypedHash h -- hash = TypedHash . go diff --git a/pact-core/Pact/Core/IR/Desugar.hs b/pact-core/Pact/Core/IR/Desugar.hs index 88a54d530..162ec8875 100644 --- a/pact-core/Pact/Core/IR/Desugar.hs +++ b/pact-core/Pact/Core/IR/Desugar.hs @@ -517,17 +517,27 @@ desugarModule => Lisp.Module i -> RenamerT b i m (Module ParsedName DesugarType b i) desugarModule (Lisp.Module mname mgov extdecls defs _ _ i) = do - let (imports, blessed, implemented) = splitExts extdecls + (imports, blessed, implemented) <- splitExts extdecls defs' <- locally reCurrModule (const (Just (mname,[]))) $ traverse desugarDef (NE.toList defs) pure $ Module mname mgov defs' blessed imports implemented placeholderHash i where splitExts = split ([], S.empty, []) split (accI, accB, accImp) (h:hs) = case h of - -- todo: implement bless hashes - Lisp.ExtBless _ -> split (accI, accB, accImp) hs - Lisp.ExtImport imp -> split (imp:accI, accB, accImp) hs + -- Todo: likely safer functions are a better idea here + Lisp.ExtBless b -> case parseModuleHash b of + Nothing -> throwDesugarError (InvalidBlessedHash b) i + Just mh -> split (accI, S.insert mh accB, accImp) hs + Lisp.ExtImport imp -> do + imp' <- desugarImport i imp + split (imp':accI, accB, accImp) hs Lisp.ExtImplements mn -> split (accI, accB, mn:accImp) hs - split (a, b, c) [] = (reverse a, b, reverse c) + split (a, b, c) [] = pure (reverse a, b, reverse c) + +desugarImport :: MonadEval b i m => i -> Lisp.Import -> RenamerT b i m Import +desugarImport info (Lisp.Import mn (Just blessed) imported) = case parseModuleHash blessed of + Just mbh' -> pure (Import mn (Just mbh') imported) + Nothing -> throwDesugarError (InvalidBlessedHash blessed) info +desugarImport _ (Lisp.Import mn Nothing imported) = pure (Import mn Nothing imported) -- Todo: Interface hashing, either on source or -- the contents @@ -538,14 +548,17 @@ desugarInterface desugarInterface (Lisp.Interface ifn ifdefns imps _ _ info) = do defs' <- traverse desugarIfDef ifdefns let mhash = ModuleHash (Hash "placeholder") - pure $ Interface ifn defs' imps mhash info + imps' <- traverse (desugarImport info) imps + pure $ Interface ifn defs' imps' mhash info desugarUse :: (MonadEval b i m ) => i - -> Import + -> Lisp.Import -> RenamerT b i m Import -desugarUse i imp = imp <$ handleImport i mempty imp +desugarUse i imp = do + imp' <- desugarImport i imp + imp' <$ handleImport i mempty imp' ----------------------------------------------------------- -- Renaming diff --git a/pact-core/Pact/Core/Semantics.md b/pact-core/Pact/Core/Semantics.md index 63355ea55..8199d9753 100644 --- a/pact-core/Pact/Core/Semantics.md +++ b/pact-core/Pact/Core/Semantics.md @@ -752,7 +752,8 @@ TODO: do we want this in core? Can we delete? - [x] implemented all 4 overloads ### env-data -- [x] implemented +- [ ] TODO: string case? Do we want to parse json still??? what is the use case vs just an object? +- [x] implemented object case ### env-dynref TODO: may not be necessary with new fv diff --git a/pact-core/Pact/Core/Syntax/ParseTree.hs b/pact-core/Pact/Core/Syntax/ParseTree.hs index b1df17c08..c4499107b 100644 --- a/pact-core/Pact/Core/Syntax/ParseTree.hs +++ b/pact-core/Pact/Core/Syntax/ParseTree.hs @@ -18,7 +18,6 @@ import Pact.Core.Literal import Pact.Core.Names import Pact.Core.Pretty import Pact.Core.Type(PrimType(..)) -import Pact.Core.Imports import Pact.Core.Guards @@ -182,6 +181,13 @@ data Def i | DPact (DefPact i) deriving Show +data Import + = Import + { _impModuleName :: ModuleName + , _impModuleHash :: Maybe Text + , _impImported :: Maybe [Text] } + deriving Show + data ExtDecl = ExtBless Text | ExtImport Import diff --git a/pact-core/Pact/Core/Syntax/Parser.y b/pact-core/Pact/Core/Syntax/Parser.y index 335ce8513..4ff8cb542 100644 --- a/pact-core/Pact/Core/Syntax/Parser.y +++ b/pact-core/Pact/Core/Syntax/Parser.y @@ -26,7 +26,6 @@ import Pact.Core.Literal import Pact.Core.Builtin import Pact.Core.Type(PrimType(..)) import Pact.Core.Guards -import Pact.Core.Imports import Pact.Core.Errors import Pact.Core.Syntax.ParseTree import Pact.Core.Syntax.LexUtils @@ -194,6 +193,7 @@ Ext :: { ExtDecl } Use :: { (Import, SpanInfo) } : '(' import ModQual ImportList ')' { (Import (mkModName $3) Nothing $4, combineSpan (_ptInfo $1) (_ptInfo $5)) } + | '(' import ModQual STR ImportList ')' { (Import (mkModName $3) (Just (getStr $4)) $5, combineSpan (_ptInfo $1) (_ptInfo $6)) } Defs :: { [ParsedDef] } From 948076f2c55dd1ee078e95cc37cf0e9f7c262cfd Mon Sep 17 00:00:00 2001 From: jmcardon Date: Sun, 10 Dec 2023 17:55:28 -0500 Subject: [PATCH 17/20] remove comments --- crypto/Pact/Core/Crypto/Pairing.hs | 141 ----------------------- pact-core/Pact/Core/Environment/Utils.hs | 5 + 2 files changed, 5 insertions(+), 141 deletions(-) diff --git a/crypto/Pact/Core/Crypto/Pairing.hs b/crypto/Pact/Core/Crypto/Pairing.hs index a9b16f937..efe79137d 100644 --- a/crypto/Pact/Core/Crypto/Pairing.hs +++ b/crypto/Pact/Core/Crypto/Pairing.hs @@ -600,144 +600,3 @@ pairingCheck = go 1 | p1 == CurveInf || p2 == CurveInf = go acc rest | otherwise = go (acc * millerLoop p1 p2) rest go acc [] = finalExponentiate parameterHex acc == 1 - --- zkDefs :: NativeModule --- zkDefs = ("Zk", --- [ pointAdditionDef --- , scalarMultDef --- , pairingCheckDef --- ]) - --- | Pointwise addition on two points on the curve BN254, --- either from G1 or G2. --- pointAdditionDef :: NativeDef --- pointAdditionDef = --- defRNative "point-add" pactPointAdd (funType a [("type", tTyString), ("point1", a), ("point2", a)]) --- [ "(point-add 'g1 {'x: 1, 'y: 2} {'x: 1, 'y: 2})" --- ] "Add two points together that lie on the curve BN254. Point addition either in Fq or in Fq2" --- where --- a = mkTyVar "a" [] --- pactPointAdd :: RNativeFun e --- pactPointAdd i as@[TLiteral (LString ptTy) _ , TObject p1 _, (TObject p2 _) :: Term Name] = --- case T.toLower ptTy of --- "g1" -> do --- p1' <- toG1 i p1 --- p2' <- toG1 i p2 --- unless (isOnCurve p1' b1 && isOnCurve p2' b1) $ evalError' i "Point not on curve" --- _ <- computeGas (Right i) (GZKArgs (PointAdd ZKG1)) --- let p3' = add p1' p2' --- pure $ TObject (fromG1 p3') def --- "g2" -> do --- p1' <- toG2 i p1 --- p2' <- toG2 i p2 --- unless (isOnCurve p1' b2 && isOnCurve p2' b2) $ evalError' i "Point not on curve" --- _ <- computeGas (Right i) (GZKArgs (PointAdd ZKG2)) --- let p3' = add p1' p2' --- pure $ TObject (fromG2 p3') def --- _ -> argsError i as --- pactPointAdd i as = argsError i as - --- -- | Scalar multiplication of two points. --- scalarMultDef :: NativeDef --- scalarMultDef = --- defRNative "scalar-mult" scalarMul (funType a [("type", tTyString), ("point1", a), ("scalar", tTyInteger)]) --- [ "(scalar-mult 'g1 {'x: 1, 'y: 2} 2)" ] --- "Multiply a point that lies on the curve BN254 by an integer value" --- where --- a = mkTyVar "a" [] --- curveOrder :: Integer --- curveOrder = 21888242871839275222246405745257275088548364400416034343698204186575808495617 --- scalarMul :: RNativeFun e --- scalarMul i as@[TLiteral (LString ptTy) _ , TObject p1 _, (TLiteral (LInteger scalar) _) :: Term Name] = do --- let scalar' = scalar `mod` curveOrder --- case T.toLower ptTy of --- "g1" -> do --- p1' <- toG1 i p1 --- unless (isOnCurve p1' b1) $ evalError' i "Point not on curve" --- _ <- computeGas (Right i) (GZKArgs (ScalarMult ZKG1)) --- let p2' = multiply p1' scalar' --- pure $ TObject (fromG1 p2') def --- "g2" -> do --- p1' <- toG2 i p1 --- unless (isOnCurve p1' b2) $ evalError' i "Point not on curve" --- _ <- computeGas (Right i) (GZKArgs (ScalarMult ZKG2)) --- let p2' = multiply p1' scalar' --- pure $ TObject (fromG2 p2') def --- _ -> argsError i as --- scalarMul i as = argsError i as - --- pairingCheckDef :: NativeDef --- pairingCheckDef = --- defRNative "pairing-check" pairingCheck' (funType tTyBool [("points-g1", TyList a), ("points-g2", TyList b)]) --- [] --- "Perform pairing and final exponentiation points in G1 and G2 in BN254, check if the result is 1" --- where --- a = mkTyVar "a" [] --- b = mkTyVar "b" [] --- pairingCheck':: RNativeFun e --- pairingCheck' i [TList p1s _ _, TList p2s _ _] = do --- g1s <- traverse termToG1 $ G.toList p1s --- g2s <- traverse termToG2 $ G.toList p2s --- traverse_ (`ensureOnCurve` b1) g1s --- traverse_ (`ensureOnCurve` b2) g2s --- let pairs = zip g1s g2s --- _ <- computeGas (Right i) (GZKArgs (Pairing (length pairs))) --- pure $ toTerm $ pairingCheck pairs --- where --- ensureOnCurve :: (Num p, Eq p) => CurvePoint p -> p -> Eval e () --- ensureOnCurve p bp = unless (isOnCurve p bp) $ evalError' i "Point not on curve" --- termToG1 (TObject o _) = toG1 i o --- termToG1 _ = evalError' i "not a point" --- termToG2 (TObject o _) = toG2 i o --- termToG2 _ = evalError' i "not a point" --- pairingCheck' i as = argsError i as - --- toG1 :: ObjectData PactValue -> Maybe G1 --- toG1 (ObjectData obj) = do --- px <- fromIntegral <$> preview (ix (Name.Field "x") . _PLiteral . _LInteger) obj --- py <- fromIntegral <$> preview (ix (Name.Field "y") . _PLiteral . _LInteger) obj --- if px == 0 && py == 0 then pure CurveInf --- else pure (Point px py) - --- fromG1 :: G1 -> ObjectData PactValue --- fromG1 CurveInf = ObjectData pts --- where --- pts = M.fromList --- [ (Name.Field "x", PLiteral (LInteger 0)) --- , (Name.Field "y", PLiteral (LInteger 0))] --- fromG1 (Point x y) = ObjectData pts --- where --- pts = --- M.fromList --- [ (Name.Field "x", PLiteral (LInteger (fromIntegral x))) --- , (Name.Field "y", PLiteral (LInteger (fromIntegral y)))] - --- toG2 :: ObjectData PactValue -> Maybe G2 --- toG2 (ObjectData om) = do --- pxl <- preview (ix (Name.Field "x") . _PList) om --- px <- traverse (preview (_PLiteral . _LInteger . to fromIntegral)) pxl --- pyl <- preview (ix (Name.Field "y") . _PList) om --- py <- traverse (preview (_PLiteral . _LInteger . to fromIntegral)) pyl --- let px' = fromList (G.toList px) --- py' = fromList (G.toList py) --- if px' == 0 && py' == 0 then pure CurveInf --- else pure (Point px' py') - --- fromG2 :: G2 -> ObjectData PactValue --- fromG2 CurveInf = ObjectData pts --- where --- pts = --- M.fromList --- [ (Name.Field "x", PList (G.fromList [PLiteral (LInteger 0)])) --- , (Name.Field "y", PList (G.fromList [PLiteral (LInteger 0)]))] --- fromG2 (Point x y) = ObjectData pts --- where --- toPactPt (Extension e) = let --- elems' = fmap (PInteger . fromIntegral) (unPoly e) --- in PList elems' --- x' = toPactPt x --- y' = toPactPt y --- pts = --- M.fromList --- [ (Name.Field "x", x') --- , (Name.Field "y", y')] diff --git a/pact-core/Pact/Core/Environment/Utils.hs b/pact-core/Pact/Core/Environment/Utils.hs index 53dd52a8b..e986c61d9 100644 --- a/pact-core/Pact/Core/Environment/Utils.hs +++ b/pact-core/Pact/Core/Environment/Utils.hs @@ -216,6 +216,11 @@ checkSigCaps checkSigCaps sigs = do granted <- getAllStackCaps autos <- useEvalState (esCaps . csAutonomous) + -- Pretty much, what this means is: + -- if you installed a capability from code (using `install-capability`) + -- then we disable unscoped sigs. Why? + -- Because we do not want to allow the installation of managed caps with + -- resources when a user explicitly did not sign for it. pure $ M.filter (match (S.null autos) granted) sigs where match allowEmpty granted sigCaps = From 757856ed05d5004922e8e39799399214aa4b3524 Mon Sep 17 00:00:00 2001 From: jmcardon Date: Mon, 11 Dec 2023 11:33:12 -0500 Subject: [PATCH 18/20] start documenting productions + lexical syntax --- .../Pact/Core/Test/LexerParserTests.hs | 3 +- pact-core/Pact/Core/Semantics.md | 72 ++++++++++++++++++- pact-core/Pact/Core/Syntax/LexUtils.hs | 4 -- pact-core/Pact/Core/Syntax/Lexer.x | 3 - pact-core/Pact/Core/Syntax/Parser.y | 2 - 5 files changed, 73 insertions(+), 11 deletions(-) diff --git a/pact-core-tests/Pact/Core/Test/LexerParserTests.hs b/pact-core-tests/Pact/Core/Test/LexerParserTests.hs index cf641d41c..d8977546b 100644 --- a/pact-core-tests/Pact/Core/Test/LexerParserTests.hs +++ b/pact-core-tests/Pact/Core/Test/LexerParserTests.hs @@ -41,6 +41,8 @@ tokenGen = Gen.choice $ unary ++ [ TokenIdent <$> identGen, number, string] number = do n <- Gen.int $ Range.linear (-1000) 1000 pure . TokenNumber $ T.pack $ show n + -- Todo: maybe we separate into keyword + ident + -- and num and turn this into an enum bounded call unary = Gen.constant <$> [ TokenLet , TokenIf @@ -48,7 +50,6 @@ tokenGen = Gen.choice $ unary ++ [ TokenIdent <$> identGen, number, string] , TokenTry , TokenError , TokenModule - , TokenKeyGov , TokenCapGov , TokenInterface , TokenImport diff --git a/pact-core/Pact/Core/Semantics.md b/pact-core/Pact/Core/Semantics.md index 8199d9753..584c6fb4e 100644 --- a/pact-core/Pact/Core/Semantics.md +++ b/pact-core/Pact/Core/Semantics.md @@ -4,9 +4,79 @@ This document should serve as a record of known pact semantics, covering as much Bullet points that are not filled are potential tasks +## Pact Syntax + +EBNF of Pact, Roughly speaking + +### Legend +| Usage | Notation | Meaning | +| ------------- | :--------: | ------- | +| concatenation | | One token immediately follows another +| alternation | \| | One or the order +| optional | \[ ... \] | none or once +| repetition | \{ ... \} | none or many +| grouping | \( ... \) | Groups tokens to match + + +### Lexical Syntax + + +``` +lower ::= 'a' | ... | 'z' (Ascii only, no unicode lower case) +upper ::= 'A' | ... | 'Z' (Ascii only, no unicode lower case) +special-symbol ::= '%' | '#' | '+' | '-' | '_' | '&' | '$' | '@' + | '<' | '>' | '=' | '^' | '?' | '*' | '!' + | '|' | '/' | '~' +alpha ::= lower | upper +parens ::= '(' | ')' +brackets ::= '[' | ']' +braces ::= '{' | '}' +digit ::= '0' | ... | '9' +comment ::= ';' "any sequence of characters up until newline" +colon ::= ':' +bind-assign ::= ':' '=' +dot ::= '.' +comma ::= ',' +nl ::= "new line character" +IDENT ::= (alpha | special-symbol) {alpha | special-symbol | digit} +STRING ::= '"' {any character that is not a line break} '"' +TICKSTRING ::= '\'' alpha {alpha | digit | '-' | '_'} +``` + +### Keywords + +| | | | +| :--------: | :--------: | :--------: | +| let | let* | if | +| defun | defcap | defconst | +| defschema | deftable | defpact | +| defproperty | property | invariant | +| interface | module | bless | +| implements | use | true | +| false | lambda | and | +| or | load | @doc | +| @model | @event | @managed | +| step | step-with-rollback | enforce | +| enforce-one | with-capability | create-user-guard | +| try | error | progn | + +#### Productions +TODO: fill +``` + ::= { } + + ::= | | | + + ::= '(' module IDENT ')' + + ::= '(' interface IDENT ')' + +``` + + ## Modules -### Module Lexing and Parsing +### Module Lexing and Parsing Implementation - [x] `module` keyword - [x] Governance forms: keyed governance (via Keyset name string) or cap governance bare name resolution - [x] use, bless and implements forms diff --git a/pact-core/Pact/Core/Syntax/LexUtils.hs b/pact-core/Pact/Core/Syntax/LexUtils.hs index 68e4c730b..00abd2e7e 100644 --- a/pact-core/Pact/Core/Syntax/LexUtils.hs +++ b/pact-core/Pact/Core/Syntax/LexUtils.hs @@ -52,8 +52,6 @@ data Token | TokenTry | TokenError | TokenModule - | TokenKeyGov - | TokenCapGov | TokenInterface | TokenImport | TokenStep @@ -286,8 +284,6 @@ renderTokenText = \case TokenTry -> "try" TokenError -> "error" TokenModule -> "module" - TokenKeyGov -> "keyGov" - TokenCapGov -> "capGov" TokenInterface -> "interface" TokenImport -> "use" TokenStep -> "step" diff --git a/pact-core/Pact/Core/Syntax/Lexer.x b/pact-core/Pact/Core/Syntax/Lexer.x index 74305db47..07385efba 100644 --- a/pact-core/Pact/Core/Syntax/Lexer.x +++ b/pact-core/Pact/Core/Syntax/Lexer.x @@ -55,7 +55,6 @@ tokens :- defconst { token TokenDefConst } defschema { token TokenDefSchema } deftable { token TokenDefTable } - defcap { token TokenDefCap } defpact { token TokenDefPact } defproperty { token TokenDefProperty } property { token TokenProperty } @@ -67,8 +66,6 @@ tokens :- use { token TokenImport } true { token TokenTrue } false { token TokenFalse } - keyGov { token TokenKeyGov } - capGov { token TokenCapGov } lambda { token TokenLambda } and { token TokenAnd } diff --git a/pact-core/Pact/Core/Syntax/Parser.y b/pact-core/Pact/Core/Syntax/Parser.y index 4ff8cb542..38f506e46 100644 --- a/pact-core/Pact/Core/Syntax/Parser.y +++ b/pact-core/Pact/Core/Syntax/Parser.y @@ -51,8 +51,6 @@ import Pact.Core.Syntax.LexUtils module { PosToken TokenModule _ } interface { PosToken TokenInterface _ } import { PosToken TokenImport _ } - keygov { PosToken TokenKeyGov _ } - capgov { PosToken TokenCapGov _ } defun { PosToken TokenDefun _ } defcap { PosToken TokenDefCap _ } defconst { PosToken TokenDefConst _ } From f6fdd7f8f260262e2979a24aed88790626f938cf Mon Sep 17 00:00:00 2001 From: jmcardon Date: Mon, 11 Dec 2023 11:36:27 -0500 Subject: [PATCH 19/20] address comments --- pact-core/Pact/Core/Hash.hs | 9 --------- pact-core/Pact/Core/IR/Desugar.hs | 4 ---- 2 files changed, 13 deletions(-) diff --git a/pact-core/Pact/Core/Hash.hs b/pact-core/Pact/Core/Hash.hs index 4c54c577f..446d555ff 100644 --- a/pact-core/Pact/Core/Hash.hs +++ b/pact-core/Pact/Core/Hash.hs @@ -89,15 +89,6 @@ parseModuleHash t = case decodeBase64UrlUnpadded (T.encodeUtf8 t) of hash :: ByteString -> Hash hash = unsafeBsToPactHash . ByteArray.convert . Crypto.hashWith Crypto.Blake2b_256 --- hash :: forall h . Reifies h HashAlgo => ByteString -> TypedHash h --- hash = TypedHash . go --- where --- algo = reflect (Proxy :: Proxy h) --- go = case algo of --- Blake2b_256 -> ByteArray.convert . Crypto.hashWith Crypto.Blake2b_256 --- SHA3_256 -> ByteArray.convert . Crypto.hashWith Crypto.SHA3_256 --- {-# INLINE hash #-} - verifyHash :: Hash -> ByteString -> Either String Hash verifyHash h b = if hashed == h then Right h diff --git a/pact-core/Pact/Core/IR/Desugar.hs b/pact-core/Pact/Core/IR/Desugar.hs index 162ec8875..25876b59d 100644 --- a/pact-core/Pact/Core/IR/Desugar.hs +++ b/pact-core/Pact/Core/IR/Desugar.hs @@ -509,9 +509,6 @@ desugarDef = \case Lisp.DTable d -> DTable <$> desugarDefTable d Lisp.DPact d -> DPact <$> desugarDefPact d --- Todo: Module hashing, either on source or --- the contents --- Todo: governance desugarModule :: (MonadEval b i m, DesugarBuiltin b) => Lisp.Module i @@ -523,7 +520,6 @@ desugarModule (Lisp.Module mname mgov extdecls defs _ _ i) = do where splitExts = split ([], S.empty, []) split (accI, accB, accImp) (h:hs) = case h of - -- Todo: likely safer functions are a better idea here Lisp.ExtBless b -> case parseModuleHash b of Nothing -> throwDesugarError (InvalidBlessedHash b) i Just mh -> split (accI, S.insert mh accB, accImp) hs From 5a9b716aa9a161023ef94d04750f16cadc6f901b Mon Sep 17 00:00:00 2001 From: jmcardon Date: Mon, 11 Dec 2023 11:39:13 -0500 Subject: [PATCH 20/20] fix cabal file for poseidon tests --- pact-core-tests/Pact/Core/Test/LexerParserTests.hs | 1 - pact-core.cabal | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/pact-core-tests/Pact/Core/Test/LexerParserTests.hs b/pact-core-tests/Pact/Core/Test/LexerParserTests.hs index d8977546b..f5cc6a592 100644 --- a/pact-core-tests/Pact/Core/Test/LexerParserTests.hs +++ b/pact-core-tests/Pact/Core/Test/LexerParserTests.hs @@ -50,7 +50,6 @@ tokenGen = Gen.choice $ unary ++ [ TokenIdent <$> identGen, number, string] , TokenTry , TokenError , TokenModule - , TokenCapGov , TokenInterface , TokenImport , TokenDefun diff --git a/pact-core.cabal b/pact-core.cabal index ad81c96de..6be7a943a 100644 --- a/pact-core.cabal +++ b/pact-core.cabal @@ -294,3 +294,4 @@ test-suite core-tests , Pact.Core.Test.LexerParserTests , Pact.Core.Test.LexerTests , Pact.Core.Test.ZkTests + , Pact.Core.Test.PoseidonTests