コード例 #1
0
ファイル: cli.py プロジェクト: tfart/neo-python-core
def create_wallet():
    private_key = bytes(Random.get_random_bytes(32))
    keypair = KeyPair(priv_key=private_key)
    return {
        "private_key": keypair.Export(),
        "address": keypair.GetAddress()
    }
コード例 #2
0
    def test_sign_and_verify(self):
        privkey = KeyPair.PrivateKeyFromWIF(
            "L44B5gGEpqEDRS9vVPz7QT35jcBG2r3CZwSwQ4fCewXAhAhqGVpP")
        keypair = KeyPair(privkey)
        hashdata = b'aabbcc'

        keypair_signature = Crypto.Sign(hashdata, bytes(keypair.PrivateKey))
        keypair_signature2 = Crypto.Default().Sign(hashdata,
                                                   bytes(keypair.PrivateKey))
        self.assertEqual(keypair_signature, keypair_signature2)

        verification_result = Crypto.VerifySignature(hashdata.decode('utf8'),
                                                     keypair_signature,
                                                     keypair.PublicKey)
        verification_result2 = Crypto.Default().VerifySignature(
            hashdata.decode('utf8'), keypair_signature, keypair.PublicKey)
        self.assertEqual(verification_result, verification_result2)
        self.assertTrue(verification_result)

        # verify with compressed key
        verification_result3 = Crypto.VerifySignature(
            hashdata.decode('utf8'), keypair_signature,
            binascii.unhexlify(keypair.PublicKey.encode_point(True)))
        self.assertTrue(verification_result3)

        # this should fail because the signature will not match the input data
        verification_result = Crypto.VerifySignature(b'aabb',
                                                     keypair_signature,
                                                     keypair.PublicKey)
        self.assertFalse(verification_result)
コード例 #3
0
 def test_should_export_valid_wif_key(self):
     kp = KeyPair(
         binascii.unhexlify(
             "cbf4b9f70470856bb4f40f80b87edb90865997ffee6df315ab166d713af433a5"
         ))
     wif = kp.Export()
     self.assertEqual(
         wif, "L44B5gGEpqEDRS9vVPz7QT35jcBG2r3CZwSwQ4fCewXAhAhqGVpP")
コード例 #4
0
 def test_should_export_valid_nep2_key(self):
     kp = KeyPair(
         binascii.unhexlify(
             "cbf4b9f70470856bb4f40f80b87edb90865997ffee6df315ab166d713af433a5"
         ))
     nep2_key = kp.ExportNEP2("TestingOneTwoThree")
     self.assertEqual(
         nep2_key,
         "6PYVPVe1fQznphjbUxXP9KZJqPMVnVwCx5s5pr5axRJ8uHkMtZg97eT5kL")
コード例 #5
0
    def test_should_throw_error_on_too_short_passphrase(self):
        kp = KeyPair(
            binascii.unhexlify(
                "cbf4b9f70470856bb4f40f80b87edb90865997ffee6df315ab166d713af433a5"
            ))
        with self.assertRaises(ValueError) as context:
            kp.ExportNEP2("x")

        self.assertIn('Passphrase must have a minimum', str(context.exception))
コード例 #6
0
    def test_publickey_to_scripthash(self):
        expected_scripthash = binascii.unhexlify(
            '79ecf967a02f9bdbd147fc97b18efd7877d27f78')
        priv_key = KeyPair.PrivateKeyFromWIF(
            'L44B5gGEpqEDRS9vVPz7QT35jcBG2r3CZwSwQ4fCewXAhAhqGVpP')
        kp = KeyPair(priv_key=priv_key)
        pub_bytes = kp.PublicKey.encode_point(True)

        result = Helper.pubkey_to_pubhash(pub_bytes)
        self.assertEqual(result, expected_scripthash)
コード例 #7
0
ファイル: crypto_utils.py プロジェクト: ansrivas/pyswitcheo
def get_private_key_from_wif(wif):
    """Fetch the private key from a wif represented in string format.

    Args:
        wif (str) : wif from which we need to extract the private key

    Returns:
        private key in bytearray format
    """
    pk = KeyPair.PrivateKeyFromWIF(wif)
    return KeyPair(pk).PrivateKey
コード例 #8
0
    def test_should_export_valid_nep2_key_with_emoji_pwd(self):
        pwd = "hellö♥️"
        privkey = "03eb20a711f93c04459000c62cc235f9e9da82382206b812b07fd2f81779aa42"

        # expected outputs
        target_address = "AXQUduANGZF4e7wDazVAtyRLHwMounaUMA"
        target_encrypted_key = "6PYWdv8bP9vbfGsNnjzDawCoXCYpk4rnWG8xTZrvdzx6FjB6jv4H9MM586"

        kp = KeyPair(binascii.unhexlify(privkey))
        nep2_key = kp.ExportNEP2(pwd)
        self.assertEqual(nep2_key, target_encrypted_key)
        self.assertEqual(kp.GetAddress(), target_address)
コード例 #9
0
def create_wallet():
    private_key = bytes(Random.get_random_bytes(32))
    keypair = KeyPair(priv_key=private_key)
    public_key = keypair.PublicKey.encode_point(True)
    address = keypair.GetAddress()
    script_hash = address_to_scripthash(address)
    return {
        "private_key": keypair.Export(),
        "address": address,
        "script_hash": "0x{}".format(script_hash[::-1].hex()),
        "public_key": public_key.decode("utf-8")
    }
コード例 #10
0
def nep2_to_wallet(NEP2, passphrase):
    private_key = KeyPair.PrivateKeyFromNEP2(NEP2, passphrase)
    keypair = KeyPair(priv_key=private_key)
    public_key = keypair.PublicKey.encode_point(True)
    address = keypair.GetAddress()
    script_hash = address_to_scripthash(address)
    return {
        "private_key": keypair.Export(),
        "address": address,
        "script_hash": "0x{}".format(script_hash[::-1].hex()),
        "public_key": public_key.decode("utf-8")
    }
コード例 #11
0
ファイル: crypto_utils.py プロジェクト: ansrivas/pyswitcheo
def get_script_hash_from_wif(wif):
    """Fetch the script hash of the public key from a wif represented in string format.

    Args:
        wif (str) : wif from which we need to extract the public key script hash

    Returns:
        public key script hash in string format
    """
    pk = KeyPair.PrivateKeyFromWIF(wif)
    keypair = KeyPair(pk)
    logger.debug("Public Address is {}".format(keypair.GetAddress()))
    return get_script_hash_from_address(keypair.GetAddress())
コード例 #12
0
 def new_wallet(self, request):
     request.setHeader('Content-Type', 'application/json')
     private_key = bytes(Random.get_random_bytes(32))
     key = KeyPair(priv_key=private_key)
     return json.dumps(
         {
             'public_key': str(key.PublicKey.encode_point(True), 'utf-8'),
             'public_key_hash': key.PublicKeyHash.ToString(),
             'private_key': key.PrivateKey.hex(),
             'wif': key.Export(),
             'address': key.GetAddress()
         },
         indent=4,
         sort_keys=True)
コード例 #13
0
    def execute(self, arguments):
        wallet = PromptData.Wallet

        if len(arguments) != 1:
            print("Please specify the required parameter")
            return False

        nep2_key = arguments[0]
        passphrase = prompt("[key password] ", is_password=True)

        try:
            kp = KeyPair.PrivateKeyFromNEP2(nep2_key, passphrase)
        except ValueError as e:
            print(str(e))
            return False

        try:
            key = wallet.CreateKey(kp)
            print(f"Imported key: {nep2_key}")
            pub_key = key.PublicKey.encode_point(True).decode('utf-8')
            print(f"Pubkey: {pub_key}")
            print(f"Address: {key.GetAddress()}")

        except Exception as e:
            # couldn't find an exact call that throws this but it was in the old code. Leaving it in for now.
            print(f"Key creation error: {str(e)}")
            return False
コード例 #14
0
    def test_long_private_key(self):
        # Taken from the neo-python UserWallet test
        priv_key = b'[\\\x8c\xdc\xb3/\x8e\'\x8e\x11\x1a\x0b\xf5\x8e\xbbF9\x88\x02K\xb4\xe2P\xaaC\x10\xb4\x02R\x03\x0b`\xdd\xc4\x99[\xac\x00)\x8b"s\x1d\xe7\xa8?\xa4\x9d\xed*\xce\xeai\xfa=\xd8r\x93p \xc8\xa9\xb6\xc6ad\xf6V\x9b#\xdfX\xc5Ltnv\x84%\x1a\x17e:K2\xf1\xb4JW\x03\xfd\xad\x94\x8eu]'
        kp = KeyPair(priv_key)

        expected_result = b'025b5c8cdcb32f8e278e111a0bf58ebb463988024bb4e250aa4310b40252030b60'
        self.assertEqual(expected_result, kp.PublicKey.encode_point(True))
コード例 #15
0
ファイル: switcheo.py プロジェクト: hieudoan2609/Equalizer
 def __init__(self,
              api_net=MAIN_NET,
              fees=0.0015,
              private_key=None,
              fee_token_name=None,
              discount=0.5):
     """
     Create new Switcheo exchange with url, fee rate and private key
     :param api_net:
     :param fees:
     :param private_key:
     """
     self.url = Switcheo._API_URL[api_net]
     self.tokens = []
     self.pairs = []
     self.contracts = []
     self.fees = fees
     self.fee_token_name = fee_token_name
     self.fee_token = None
     self.key_pair = None
     self.discount = discount
     self.client = AuthenticatedClient(api_url=self.url)
     if private_key:
         try:
             self.key_pair = KeyPair(bytes.fromhex(private_key))
         except:
             self.key_pair = None
             print(
                 "No or incorrect private key. Equalizer changes to view only mode"
             )
コード例 #16
0
ファイル: main.py プロジェクト: rph8/neopanda
def runRawTransaction(operation, args):
    invocation_tx = InvocationTransaction()

    smartcontract_scripthash = UInt160.ParseString(CONTRACT_HASH)
    sb = ScriptBuilder()
    sb.EmitAppCallWithOperationAndArgs(
        smartcontract_scripthash,
        operation,
        args)
    invocation_tx.Script = binascii.unhexlify(sb.ToArray())

    wallet = UserWallet.Create(
        'neo-privnet.wallet', to_aes_key('coz'), generate_default_key=False)
    private_key = KeyPair.PrivateKeyFromWIF(
        "KxDgvEKzgSBPPfuVfw67oPQBSjidEiqTHURKSDL1R7yGaGYAeYnr")

    wallet.CreateKey(private_key)
    context = ContractParametersContext(invocation_tx)
    wallet.Sign(context)

    invocation_tx.scripts = context.GetScripts()
    raw_tx = invocation_tx.ToArray()

    payload = {"jsonrpc": "2.0", "id": 1,
               "method": "sendrawtransaction",
               "params": [raw_tx.decode("ascii")]}

    res = requests.post(
        "http://neo-nodes:30333/testNeoConnection", json=payload)
    print("received POST result")
    print(res.status_code)
    result = res.text
    print(result)
    return result
コード例 #17
0
    def test_should_throw_error_on_invalid_password(self):
        nep2_key = "6PYVPVe1fQznphjbUxXP9KZJqPMVnVwCx5s5pr5axRJ8uHkMtZg97eT5kL"
        pwd = "invalid-pwd"
        with self.assertRaises(ValueError) as context:
            KeyPair.PrivateKeyFromNEP2(nep2_key, pwd)

        self.assertEqual('Wrong passphrase', str(context.exception))
コード例 #18
0
 def test_should_work(self):
     nep2_key = "6PYVPVe1fQznphjbUxXP9KZJqPMVnVwCx5s5pr5axRJ8uHkMtZg97eT5kL"
     pwd = "TestingOneTwoThree"
     should_equal_private_key = b"cbf4b9f70470856bb4f40f80b87edb90865997ffee6df315ab166d713af433a5"
     privkey = KeyPair.PrivateKeyFromNEP2(nep2_key, pwd)
     privkey_hex = binascii.hexlify(privkey)
     self.assertEqual(privkey_hex, should_equal_private_key)
コード例 #19
0
 def test_should_work(self):
     privkey = KeyPair.PrivateKeyFromWIF(
         "L44B5gGEpqEDRS9vVPz7QT35jcBG2r3CZwSwQ4fCewXAhAhqGVpP")
     self.assertEqual(
         binascii.hexlify(privkey),
         b"cbf4b9f70470856bb4f40f80b87edb90865997ffee6df315ab166d713af433a5"
     )
コード例 #20
0
def create_raw_sc_method_call_tx(
    source_address,
    source_address_wif,
    smartcontract_scripthash,
    smartcontract_method,
    smartcontract_method_args,
):
    source_script_hash = address_to_scripthash(source_address)

    # start by creating a base InvocationTransaction
    # the inputs, outputs and Type do not have to be set anymore.
    invocation_tx = InvocationTransaction()

    # often times smart contract developers use the function ``CheckWitness`` to determine if the transaction is signed by somebody eligible of calling a certain method
    # in order to pass that check you want to add the corresponding script_hash as a transaction attribute (this is generally the script_hash of the public key you use for signing)
    # Note that for public functions like the NEP-5 'getBalance' and alike this would not be needed, but it doesn't hurt either
    invocation_tx.Attributes.append(
        TransactionAttribute(usage=TransactionAttributeUsage.Script,
                             data=source_script_hash))

    smartcontract_scripthash = UInt160.ParseString(smartcontract_scripthash)
    # next we need to build a 'script' that gets executed against the smart contract.
    # this is basically the script that calls the entry point of the contract with the necessary parameters
    sb = ScriptBuilder()

    # call the method on the contract (assumes contract address is a NEP-5 token)
    sb.EmitAppCallWithOperationAndArgs(
        smartcontract_scripthash,
        smartcontract_method,
        smartcontract_method_args,
    )
    invocation_tx.Script = binascii.unhexlify(sb.ToArray())

    # at this point we've build our unsigned transaction and it's time to sign it before we get the raw output that we can send to the network via RPC
    # we need to create a Wallet instance for helping us with signing
    wallet = UserWallet.Create('path',
                               to_aes_key('mypassword'),
                               generate_default_key=False)

    # if you have a WIF use the following
    # this WIF comes from the `neo-test1-w.wallet` fixture wallet
    private_key = KeyPair.PrivateKeyFromWIF(source_address_wif)

    # if you have a NEP2 encrypted key use the following instead
    # private_key = KeyPair.PrivateKeyFromNEP2("NEP2 key string", "password string")

    # we add the key to our wallet
    wallet.CreateKey(private_key)

    # and now we're ready to sign
    context = ContractParametersContext(invocation_tx)
    wallet.Sign(context)

    invocation_tx.scripts = context.GetScripts()
    raw_tx = invocation_tx.ToArray()

    print(raw_tx)

    return raw_tx.decode()
コード例 #21
0
    def test_fail_to_determine_plublic_key(self, patched_priv_to_pubkey):
        # https://github.com/vbuterin/pybitcointools/blob/aeb0a2bbb8bbfe421432d776c649650eaeb882a5/bitcoin/main.py#L291
        patched_priv_to_pubkey.side_effect = Exception("Invalid privkey")

        with self.assertRaises(Exception) as context:
            KeyPair(bytes(32 * 'A', 'utf8'))
        self.assertEqual('Could not determine public key',
                         str(context.exception))
コード例 #22
0
    def test_c(self):

        key = KeyPair(priv_key=self.decrypted_pk)

        self.assertEqual(key.PublicKey.x, self.pubkey_x)
        self.assertEqual(key.PublicKey.y, self.pubkey_y)

        self.assertEqual(key.PublicKey.encode_point(True), self.pubkey_encoded)
        self.assertEqual(key.PublicKey.encode_point(False), self.pubkey_not_comp)

        self.assertIsInstance(key.PublicKeyHash, UInt160)

        self.assertEqual(key.PublicKeyHash.ToBytes(), self.pubkeyhash)
        self.assertEqual(key.Export(), self.wif)

        private_key_from_wif = KeyPair.PrivateKeyFromWIF(self.wif)

        self.assertEqual(private_key_from_wif, self.pk)
コード例 #23
0
    def test_publickey_to_redeemscript_to_scripthash_to_address(self):
        # NEP 2 testvector
        expected_redeemscript = binascii.unhexlify(
            '21026241e7e26b38bb7154b8ad49458b97fb1c4797443dc921c5ca5774f511a2bbfcac'
        )
        expected_scripthash = binascii.unhexlify(
            '79ecf967a02f9bdbd147fc97b18efd7877d27f78')
        expected_address = 'AStZHy8E6StCqYQbzMqi4poH7YNDHQKxvt'

        priv_key = KeyPair.PrivateKeyFromWIF(
            'L44B5gGEpqEDRS9vVPz7QT35jcBG2r3CZwSwQ4fCewXAhAhqGVpP')
        kp = KeyPair(priv_key=priv_key)
        pub_bytes = kp.PublicKey.encode_point(True)
        redeemscript = Helper.pubkey_to_redeem(pub_bytes)
        scripthash = Helper.redeem_to_scripthash(redeemscript)
        address = Helper.scripthash_to_address(scripthash)

        self.assertEqual(redeemscript, expected_redeemscript)
        self.assertEqual(scripthash, expected_scripthash)
        self.assertEqual(address, expected_address)
コード例 #24
0
    def test_neon_sig(self):

        key = KeyPair(priv_key=self.nmpk)

        hhex = hashlib.sha256(binascii.unhexlify(self.nmsg)).hexdigest()

        self.assertEqual(hhex, self.hashhex)

        sig = Crypto.Sign(self.nmsg, key.PrivateKey)

        self.assertEqual(sig.hex(), self.neon_sig)
コード例 #25
0
def SendBlog(wallet, tx, fee=Fixed8.Zero(), from_addr=None, privatekey=None):
    wallet_tx = wallet.MakeTransaction(tx=tx,
                                       fee=fee,
                                       use_standard=False,
                                       from_addr=from_addr)
    # wallet_tx = tx
    if wallet_tx:
        context = ContractParametersContext(wallet_tx)
        if privatekey != None:
            prikey = KeyPair.PrivateKeyFromWIF(privatekey)
            kp = KeyPair(prikey)
            wallet.Sign(context, kp)
        else:
            wallet.Sign(context)

        if context.Completed:

            wallet_tx.scripts = context.GetScripts()

            relayed = False

            #            print("SENDING TX: %s " % json.dumps(wallet_tx.ToJson(), indent=4))

            relayed = NodeLeader.Instance().Relay(wallet_tx)
            print("Tx: %s " % wallet_tx.ToJson())
            if relayed:
                print("Relayed Tx: %s " % wallet_tx.Hash.ToString())

                wallet.SaveTransaction(wallet_tx)

                return wallet_tx
            else:
                print("Could not relay tx %s " % wallet_tx.Hash.ToString())
        else:

            print("Incomplete signature")

    else:
        print("Insufficient funds")

    return False
コード例 #26
0
def example2():
    source_address = "AJQ6FoaSXDFzA6wLnyZ1nFN7SGSN2oNTc3"
    source_script_hash = address_to_scripthash(source_address)

    # start by creating a base InvocationTransaction
    # the inputs, outputs and Type do not have to be set anymore.
    invocation_tx = InvocationTransaction()

    # Since we are building a raw transaction, we will add the raw_tx flag

    invocation_tx.raw_tx = True

    # often times smart contract developers use the function ``CheckWitness`` to determine if the transaction is signed by somebody eligible of calling a certain method
    # in order to pass that check you want to add the corresponding script_hash as a transaction attribute (this is generally the script_hash of the public key you use for signing)
    # Note that for public functions like the NEP-5 'getBalance' and alike this would not be needed, but it doesn't hurt either
    invocation_tx.Attributes.append(
        TransactionAttribute(usage=TransactionAttributeUsage.Script,
                             data=source_script_hash))

    # next we need to build a 'script' that gets executed against the smart contract.
    # this is basically the script that calls the entry point of the contract with the necessary parameters
    smartcontract_scripthash = UInt160.ParseString(
        "31730cc9a1844891a3bafd1aa929a4142860d8d3")
    sb = ScriptBuilder()
    # call the NEP-5 `name` method on the contract (assumes contract address is a NEP-5 token)
    sb.EmitAppCallWithOperation(smartcontract_scripthash, 'name')
    invocation_tx.Script = binascii.unhexlify(sb.ToArray())

    # at this point we've build our unsigned transaction and it's time to sign it before we get the raw output that we can send to the network via RPC
    # we need to create a Wallet instance for helping us with signing
    wallet = UserWallet.Create('path',
                               to_aes_key('mypassword'),
                               generate_default_key=False)

    # if you have a WIF use the following
    # this WIF comes from the `neo-test1-w.wallet` fixture wallet
    private_key = KeyPair.PrivateKeyFromWIF(
        "Ky94Rq8rb1z8UzTthYmy1ApbZa9xsKTvQCiuGUZJZbaDJZdkvLRV")

    # if you have a NEP2 encrypted key use the following instead
    # private_key = KeyPair.PrivateKeyFromNEP2("NEP2 key string", "password string")

    # we add the key to our wallet
    wallet.CreateKey(private_key)

    # and now we're ready to sign
    context = ContractParametersContext(invocation_tx)
    wallet.Sign(context)

    invocation_tx.scripts = context.GetScripts()
    raw_tx = invocation_tx.ToArray()

    return raw_tx
コード例 #27
0
 def get_data_from_wif(self, request, wif):
     request.setHeader('Content-Type', 'application/json')
     try:
         print("get_data_from_wif ", wif)
         private_key = KeyPair.PrivateKeyFromWIF(wif)
         key = KeyPair(priv_key=private_key)
         return json.dumps(
             {
                 'public_key': str(key.PublicKey.encode_point(True),
                                   'utf-8'),
                 'public_key_hash': key.PublicKeyHash.ToString(),
                 'private_key': key.PrivateKey.hex(),
                 'wif': key.Export(),
                 'address': key.GetAddress()
             },
             indent=4,
             sort_keys=True)
     except Exception as e:
         return self.format_message(
             "Error: Could not get data from wif %s " % (wif))
     return self.format_message("Could not get data from wif %s " % (wif))
コード例 #28
0
    def test_6_import_wif(self):

        wallet = self.GetWallet1()

        key_to_import = 'L3MBUkKU5kYg16KSZnqcaTj2pG5ei3fN9A4X7rxXys18GBDa3bH8'

        prikey = KeyPair.PrivateKeyFromWIF(key_to_import)
        keypair = wallet.CreateKey(prikey)

        key_out = keypair.PublicKey.encode_point(True).decode('utf-8')

        self.assertEqual(key_out, '03f3a3b5a4d873933fc7f4b53113e8eb999fb20038271fbbb10255585670c3c312')
コード例 #29
0
    def test_b(self):

        key = KeyPair(priv_key=self.pk)

        contract = Contract.CreateSignatureContract(key.PublicKey)

        self.assertEqual(binascii.unhexlify(contract.Script), self.contract_script)
        self.assertEqual(contract.ScriptHash.ToBytes(), self.contract_script_hash)

        self.assertEqual(contract.Address, self.contract_address)

        self.assertEqual(contract.PublicKeyHash, key.PublicKeyHash)
        self.assertEqual(contract.PublicKeyHash.ToBytes(), self.pubkeyhash)
コード例 #30
0
    def claim_initial_neo(self, target_address):
        wallets = []
        i = 0
        tx_json = None
        dbloops = []

        print("Signing new transaction with 3 of 4 node keys...")
        for pkey, wif in nodekeys.items():
            walletpath = "wallet{}.db3".format(i + 1)
            if os.path.exists(walletpath):
                os.remove(walletpath)
            wallet = UserWallet.Create(path=walletpath,
                                       password=to_aes_key(self.wallet_pwd))
            wallets.append(wallet)

            print("Importing node private key to to {}".format(walletpath))
            prikey = KeyPair.PrivateKeyFromWIF(wif)
            wallet.CreateKey(prikey)

            print("Importing multi-sig contract to {}".format(walletpath))
            keys = list(nodekeys.keys())
            pubkey_script_hash = Crypto.ToScriptHash(pkey, unhex=True)
            verification_contract = Contract.CreateMultiSigContract(
                pubkey_script_hash, 3, keys)
            wallet.AddContract(verification_contract)
            print("Added multi-sig contract address %s to wallet" %
                  verification_contract.Address)

            dbloop = task.LoopingCall(wallet.ProcessBlocks)
            dbloop.start(1)
            dbloops.append(dbloop)

            # print("Wallet %s " % json.dumps(wallet.ToJson(), indent=4))

            if i == 0:
                print(
                    "Creating spend transaction to {}".format(target_address))
                tx_json = self.send_neo(wallet, multisig_addr, target_address,
                                        '100000000')
                if tx_json is None:
                    break
            else:
                tx_json = self.sign_and_finish(wallet, tx_json)

            if tx_json == 'success':
                print(
                    "Finished, {} should now own all the NEO on the private network."
                    .format(target_address))
                break
            i += 1