Sunday, February 23, 2020

Programming an Ethereum Smart Contract with Vyper

and deploying it with MetaMask and MyEtherWallet (MEW)


Introduction

Ethereum has a vast amount of developer resources available, such that for a beginner its hard to know where to start.

If you go with the recommended approach you'd probably choose Solidity along with either JavaScript or golang. JavaScript and golang are traditionally the most well supported languages for the developer tooling around Ethereum. The original Ethereum node software, geth, is written in golang. There's a version of the Solidity smart contract compiler, solcjs, written in JavaScript, and available as a Node.js NPM package.

The other Smart Contract language that is supported by the Ethereum Foundation is Vyper. Vyper is a python-like language that was designed for security, simplicity and testability. In my view this makes Vyper ideal for a beginner. Vyper foregoes some of the power of Solidity (for example, class inheritance and function modifiers) in order to uphold the Vyper principles of being simple and secure.

In this article I'll be stepping you through creating a smart contract with the Vyper programming language, deploying it to the Ethereum test network, and then interacting with the contract - calling its two externally accessible functions. The contract deployment and contract interaction are achieved using two in-browser tools - MyEtherWallet (MEW) and MetaMask.


Background reading

Before you start I would highly recommend this article to get up to speed with the Ethereum ecosystem as a whole.
https://medium.com/@mattcondon/getting-up-to-speed-on-ethereum-63ed28821bbe
Its from 2017 but the content is still valid today.

Along with the Ethereum whitepaper, which is a must-read if you're a developer:
https://github.com/ethereum/wiki/wiki/White-Paper


Installing the Vyper compiler

There's a number of options available to you as documented here:
https://vyper.readthedocs.io/en/latest/installing-vyper.html

One of the simplest options is to install it using python's package manager (pip). I'll start by ensuring you have the python development environment setup correctly.


Installing a recent version of Python and Pip with Pyenv

If you don't have already have a recent version of Python installed, or don't even know, I would highly recommend that you start by installing pyenv. Pyenv is a tool for python version management.

I followed the Pyenv installation instructions for a MacOS installation via homebrew, but there are instructions for other OSes given.

After installing pyenv, you can install the latest version of python with

% pyenv install 3.8.0

You will now have an up to date version of both python and pip available from your terminal command prompt.

Check what version of python is installed:
% python -V

Output:
Python 3.8.0


Check what version of pip is installed:
% pip -V

Output:

pip 19.2.3 from /Users/hg/.pyenv/versions/3.8.0/lib/python3.8/site-packages/pip (python 3.8)


Installing the Vyper compiler

Once you have python and pip installed aready, you can install the Vyper compiler with:

% pip install vyper

Check what version of Vyper is installed:

% vyper --version

Output:
0.1.0b16+commit.5e4a94a



Writing a smart contract in Vyper

For the first contract, we're going to keep things very simple and go with a public storage contract.
All the contract does is stores a single number in its storage area, and implements two public accessor functions - a getter and a setter.

Use a text editor and open a new file named storage.vy

Note that vy is the file extension for Vyper source code.

Here's the Vyper code:

stored_data: uint256

@public
def set(new_value : uint256):
    self.stored_data = new_value

@public
@constant
def get() -> uint256:
    return self.stored_data


Line 1 declares a variable named 'stored_data' of type 'uint256'. This is the only thing that the contract will store on the blockchain.

Line 3 (def set...) declares the public set function, to update the 'stored_data' variable.

Line 9 (def get...) declares the public get function, to get the 'stored_data' variable.

Its important to note that these two functions get and set are marked public and so can be 'called' by anyone - by using Ethereum client software like MyEtherWallet, or programmatically via the web3 or by other library.

Calling a public function on a smart contract actually consists of sending a transaction to the deployed contract's address - but this is an implementation detail hidden that is hidden by client software or libraries.

Further reading about the structure of contracts in Vyper:
https://vyper.readthedocs.io/en/latest/structure-of-a-contract.html


Compiling the Vyper smart contract

To compile the contract into EVM bytecode:

% vyper -f bytecode storage.vy > storage.bin

To generate the ABI for the contract:

% vyper -f abi storage.vy > storage.abi

The ABI is a JSON format interface specification file, and it is needed to be able to interact with the smart contract (i.e. call its functions).


Deploy the smart contract to the Rinkeby test network

Install MetaMask

If you haven't already, now is a good time to install the MetaMask plugin/extension into your browser - https://metamask.io/
Setup MetaMask with a seed phrase and it will create an in-browser Ethereum wallet that you can use for real transactions, or in this case, test transactions.

When MetaMask is setup, at the top right you should see the network dropdown.

Change this to 'Rinkeby Test Network'. Press the DEPOSIT button, then press the GET ETHER button under the TEST FAUCET option.

After opening https://www.rinkeby.io/#stats use the 'Crypto Faucet' button on the left and follow the instructions. The minimum option (3 ETH) will be more than enough for test purposes and to deploy this contract.

The second thing you'll need to do is to setup MyEtherWallet (MEW). This will let you deploy and interact with your smart contract.


Setup MyEtherWallet (MEW)

Go to https://www.myetherwallet.com and setup the seed phrase.

Now you'll need to give MyEtherWallet (MEW) access to your MetaMask wallet, which contains the 3 ETH for testing.

Go to https://www.myetherwallet.com/access-my-wallet and press the browser extension option.

It should come up with a 'Access via MetaMask' window, and you'll need to grant it permission. Press the 'Access My Wallet' button.


Deploy the smart contract

Inside MyEtherWallet (MEW), press the left hand side option 'Contract' then 'Deploy Contract'.

From the terminal, issue this command:

% cat storage.bin

Output:
0x6100f456600436101561000d576100ea565b600035601c52740100000000000000000000000000000000000000006020526f7fffffffffffffffffffffffffffffff6040527fffffffffffffffffffffffffffffffff8000000000000000000000000000000060605274012a05f1fffffffffffffffffffffffffdabf41c006080527ffffffffffffffffffffffffed5fa0e000000000000000000000000000000000060a0526360fe47b160005114156100c25734156100ba57600080fd5b600435600055005b636d4ce63c60005114156100e95734156100db57600080fd5b60005460005260206000f350005b5b60006000fd5b6100046100f4036100046000396100046100f4036000f3

Using the mouse, copy the contents of the file from the terminal prompt.

Inside MEW, paste the copied text contents into the bytecode field.

On the terminal again, issue this command:

% cat storage.abi

Output:
[{"name": "set", "outputs": [], "inputs": [{"type": "uint256", "name": "new_value"}], "constant": false, "payable": false, "type": "function", "gas": 35315}, {"name": "get", "outputs": [{"type": "uint256", "name": "out"}], "inputs": [], "constant": true, "payable": false, "type": "function", "gas": 1181}]


Using the mouse, copy the contents of the file from the terminal prompt.

Inside MEW, paste the copied text contents into the ABI/JSON field.

Enter a name for your contract, e.g. 'storage1'.

Press the 'Sign Transaction' button.

MetaMask will open up a window where you'll be able to confirm the deployment of your contract.

You'll see the gas fee and total.
You can press on the data tab and you'll see the bytecode that you pasted earlier.

Press the Confirm button to proceed with the deployment of your contract.

You may need to wait several seconds for the transaction to be confirmed at this point.
MetaMask should give you a successful deployment popup and link you to the transaction on etherscan.io.
E.g.
https://rinkeby.etherscan.io/tx/0x36663b338ab0eaa7d7cdd91aa5abacdc273757ff56b81221d76a2ff0aedc9860

Here you can see the address of your newly deployed contract. In my case it is here:
https://rinkeby.etherscan.io/address/0x7baad2f634d6bde84916e7d6db40ca2e502eaff6


Side note on contract addresses

Contract addresses are calculated deterministically, based on the account that created it. They are based on the nonce value of your account. So it is possible to know in advance what the contract address will be, if necessary.

Details here: https://ethereum.stackexchange.com/questions/760/how-is-the-address-of-an-ethereum-contract-computed


Interacting with the smart contract

Now that your contract is deployed, its time to interact with it - call its get and set functions.

The get function can be called 'for free' - it doesn't cost any gas, because its just returning the current state of the blockchain.
Calling the 'set' fuction however must be paid for in gas, because by calling it you are actually changing the current state of the blockchain.

Go back to MEW and navigate to the left hand side 'Contract' option then 'Interact with Contract'.

Paste your newly created contract address into the 'Contract Address' field.

In the ABI/JSON field, past your ABI file contents.

Press the Continue button.

There's a dropdown which shows 'Select an item'. This lists all of the public functions on the smart contract. There's only two available - get and set.

Choose get first, it will execute immediately and show the result being 0. 0 is the default value for uninitialised storage in Ethereum.

Now choose 'set' from the dropdown.

Enter the required value into the new_value field, e.g. 88.

Leave the Value in ETH as 0.

Press the 'Write' button.

MetaMask will open up a window where you'll be able to confirm your contract interaction.
What you're actually doing here is sending a transaction to the contract with a value in the data field - the data specifies to the EVM which function is being called (set) and the value of the parameter to it (88).

Press the confirm button.

You may need to wait several seconds for the transaction to be confirmed.

MetaMask should give you a confirmed transaction popup and link you to the transaction on etherscan.io.
E.g.
https://rinkeby.etherscan.io/tx/0x42af3501fff6ddd67a97cc52c94565f149f4d7f985d223523cebae2efc693bbb

Press the "Press to see more" link at the bottom of this page on etherscan.io to see the detail of the function call you made.

Go back to MEW and this time select the 'get' from the dropdown.

Confirm that the value you set is now reflected by the get.

You have now successfully deployed an Ethereum smart contract written in Vyper, and interacted with it using MetaMask and MyEtherWallet (MEW).

Congratulations!


Final notes - can you modify a smart contract?

Note that once a smart contract is deployed, you can't modify it; it is immutable and exists on the Ethereum blockchain forever.

If you need to modify or update the contract, you'll need to deploy the updated code to a new contract address.

There are various techniques for handling contract "upgrades" including migrating the existing storage. There's a good article here on this topic: https://mixbytes.io/blog/storage-upgradable-ethereum-smart-contracts

Note also that a contract can destroy itself (along with its storage), via the selfdestruct() function, as documented here: https://vyper.readthedocs.io/en/v0.1.0-beta.15/built-in-functions.html#selfdestruct

Once destroyed, the contract and its storage are removed from that block onwards. After destruction, it is technically still possible to see the historical contract bytecode and storage, which exists on earlier blocks of the Ethereum blockchain.


Follow @dodgy_coder

Saturday, February 8, 2020

Programming Bitcoin Cash (BCH) with the NBitcoin .NET library and C#

The NBitcoin library is the most active and well supported library in .NET for working with Bitcoin and other similar cryptocurrencies.

NBitcoin fully supports Bitcoin Cash (BCH), however the ebook and programming guide examples focus solely on Bitcoin Core (BTC).

The problem you encounter when following the NBitcoin guide is firstly that the QBitNinja API only supports Bitcoin Core and secondly that broadcasting the transaction seems to require either running a full local node or using the QBitNinja API.

In this tutorial I'll show you how to spend your Bitcoin Cash using the NBitcoin library running under dotnet core, without the need for running a full local node or for accessing the QBitNinja API.

The program you write here will create a new transaction, sign it with your private key, and broadcast it to the Bitcoin Cash network.


Dotnet core
is the preferred programming environment for NBitcoin. Dotnet core is open source and runs under the Linux, MacOSX and Windows operating systems.

Bitcoin Cash is the ideal cryptocurrency for experimenting with programming APIs and libraries - you can send small transactions for very low fees, typically for a fraction of one US cent.


Step 1: Project Setup

Follow the setup guide as normal:
https://programmingblockchain.gitbook.io/programmingblockchain/introduction/project_setup

The rest of these steps 2-12 below loosely follow the "Spend Your Coin" guide:
https://programmingblockchain.gitbook.io/programmingblockchain/bitcoin_transfer/spend_your_coin

Its not absolutely required, but for a more complete and in depth understanding, I would recommend you read through the "Spend Your Coin" guide above (with the knowledge that it applies to Bitcoin Core) before proceeding with the rest of the below steps.


Step 2: Add support for Bitcoin Cash

On the command line:

dotnet add package NBitcoin.Altcoins

The code - add these using statements to the top of the C# source file.

using NBitcoin;
using NBitcoin.Altcoins;
using NBitcoin.Protocol;


And at the beginning of the program, add this:

// Important Note - this is not test code.
// It is going to run in production (called the "mainnet").
var network = NBitcoin.Altcoins.BCash.Instance.Mainnet;



Step 3: (Optional) Generate a new private key and address

The below code snippet generates a new BCH private key and BCH address using the NBitcoin library.
  
// Generate a random private key.
Key rawPrivateKey = new Key();

// The private key, also known as the Bitcoin secret or the WIF (Wallet Interchange Format).
// If you intend to use it, make sure you save the below somewhere safe!
BitcoinSecret privateKey = rawPrivateKey.GetBitcoinSecret(network);
Console.WriteLine("privateKey = " + privateKey);
Console.WriteLine("address (from privateKey) = " + privateKey.GetAddress(ScriptPubKeyType.Legacy));


Alternatively you can generate a new private key and address using BCH wallet software.


Step 4: Setup the variables for your private keys and addresses

To spend your Bitcoin Cash, you'll need to know the private keys of both the "destination" BCH address and the "from" BCH address.
The "from" BCH address is also known as the input address or the outpoint to spend.

Here's the code to setup the address and private keys of both the "destination" address and the "from" address.

// Destination - private key and address. The destination of the new transaction we are creating.
// Note: its not strictly necessary for creating the transaction to have the private key of the destination,
// but its better to add it here so that you know that you have access to it, and that the money won't be 'lost'.
var privateKey = new BitcoinSecret("PASTE_YOUR_DESTINATION_ADDRESS_PRIVATE_KEY_HERE", network);
Console.WriteLine("dest privateKey = " + privateKey);
var address = privateKey.GetAddress(ScriptPubKeyType.Legacy);
Console.WriteLine("dest address = " + address);
Console.WriteLine("dest address scriptPubKey= " + address.ScriptPubKey);

// Input Transaction - private key and address. The from address.
var inPrivateKey = new BitcoinSecret("PASTE_YOUR_FROM_ADDRESS_PRIVATE_KEY_HERE", network);
var inAddress = inPrivateKey.GetAddress(ScriptPubKeyType.Legacy);
Console.WriteLine("inPrivateKey = " + inPrivateKey);
Console.WriteLine("inAddress = " + inAddress);
Console.WriteLine("inAddress scriptPubKey= " + inAddress.ScriptPubKey);


You can run the program now to make sure its working - on the command line:

dotnet run


Step 5: Determine the Transaction ID of the "from" address

Now you need to determine the transaction ID and index number of your "from" address by looking at the transaction in a blockchain explorer and plugging in the correct TxId and index number below.

// Determine the previous output that will be spent, as the Input to our new transaction.
// For example:

// https://explorer.bitcoin.com/bch/tx/292f70e71f8bc2e94b7c0ac46c4e89371dc59b821639de67376f6f0b09544d92
string txInIdString = "292f70e71f8bc2e94b7c0ac46c4e89371dc59b821639de67376f6f0b09544d92";
uint txOutIndex = 0; // <== Ensure this index is correct!
OutPoint outPointToSpend = OutPoint.Parse(txInIdString + ":" + txOutIndex);



Step 6: Create the new transaction

var transaction = Transaction.Create(network);
transaction.Inputs.Add(new TxIn()
{
    PrevOut = outPointToSpend
});



Step 7: Setup the amount to spend and the miner fee

// Suggested miner fee for this transaction, as of February 2020,
// is 0.000003 BCH or around USD 0.001 (a tenth of a cent).
// Check recent blocks for guidance.

var minerFee = new Money(0.000003m, MoneyUnit.BTC);  

// Replace below with your amount.
// It is the total unspent amount of the "from" address.
var txInAmount = new Money(0.0021m, MoneyUnit.BTC);

// Move to the destination address.

var spendAmount = txInAmount - minerFee;
transaction.Outputs.Add(spendAmount, address.ScriptPubKey);


Step 8: Add a message to the transaction, using the OP_RETURN template (max 80 characters)

var message = "Test 1: using the NBitcoin library to move Bitcoin Cash. BCH Rocks!";
var bytes = Encoding.UTF8.GetBytes(message);
transaction.Outputs.Add(Money.Zero, TxNullDataTemplate.Instance.GenerateScriptPubKey(bytes));



Step 9: Sign the transaction

// Get the ScriptPubKey from the private key of the outPointToSpend.
transaction.Inputs[0].ScriptSig = inAddress.ScriptPubKey;

// Sign the transaction with the input private key.
var txInId = uint256.Parse(txInIdString);
var inCoin = new Coin(txInId, txOutIndex, txInAmount, inAddress.ScriptPubKey);
transaction.Sign(inPrivateKey, inCoin);



Step 10: Determine the TxId of your transaction, which is just its hash

Console.WriteLine("New TxId: " + transaction.GetHash());

Now is a good time to run the code and check its all working. From the command line:

dotnet run


Step 11: Broadcast your transaction to the Bitcoin Cash network

This is the final step and should only be attempted if your program runs fine up to step 10.

Before you run it, confirm your amount to spend is correct.

//
// Connect to a BCH node and broadcast the transaction.
// See here for the DNS Seed list:
// https://github.com/Bitcoin-ABC/bitcoin-abc/blob/master/src/chainparams.cpp

//
using (var node = Node.Connect(network, "seed.bchd.cash:8333"))
{
    // Say hello to the node.
    node.VersionHandshake();

    // Advertise your transaction (send just the hash).
    node.SendMessage(new InvPayload(InventoryType.MSG_TX, transaction.GetHash()));

    // Send the contents of the transaction.
    node.SendMessage(new TxPayload(transaction));

    // Wait for the message to be sent.
    Thread.Sleep(5000);
}


Run your program the command line:

dotnet run


Step 12: That's it, well done for making it to the end!!

If everything went well, your new transaction was accepted by the Bitcoin Cash network, and it will show up in a block explorer such as this one:

https://explorer.bitcoin.com/bch/tx/3ecf0f0dafd26e8d788b59a433bf00e1c3c079e82dada5111e899c87a75dadff

Replace the above TxId with yours from step 10.

Your new transaction will be listed initially as having 0 confirmations, which means its in the mempool.

Now you just need to wait for your transaction to be confirmed. This will happen as soon as the next block is mined and your transaction gets added to that block by the winning miner.


Follow @dodgy_coder

Tuesday, October 1, 2019

Counter overflows and clock drift bugs in aircraft and missile defense systems

A counter overflow bug happens when an unsigned integer variable storing a counter reaches its maximum value; when its already at the maximum, as soon as one more value gets added to it, the variable will reset back to 0 and continue counting up from there. If the rest of the software is not expecting this counter reset, it can result in system failures. So the longer the system is running for, the nearer the system will get to a counter overflow event.

Clock drift bugs happen when an internal timer/clock gets calculated incorrectly, causing it to slowly drift out of sync with real time. The longer the system is running, the more the clock drifts and the bigger the error gets. When real time clocks are out of sync, all sorts of downstream calculations can become inaccurate.

Both of these types of bugs typically have a workaround that requires the operator to reboot the system every X hours or days.

Both counter overflows and clock drift bugs can occur in production systems when system testing didn't include a "soak test" - where you keep the system running for a very long period, typically measured in days rather than hours. The failure to pick up the bug during system testing means that a production system gets deployed with a bug, and the only workaround becomes a regular reboot of the system.

The kicker - these type of bugs have been happening in safety critical systems for at least the past 28 years

One of the most publicized cases was the failure of a Patriot missile defense system in 1991, in which the system failed to track an incoming Scud missile, due to a drifting and out of sync clock. Tragically, this particular failure resulted in the death of 28 U.S. soldiers based at a U.S. barracks near to Dhahran, Saudi Arabia. The workaround for this bug was to reboot the system every 8 hours, but unfortunately this had not been communicated to the base in time to avoid the disaster.

Another well known case was the counter overflow in the Boeing 787 Dreamliner firmware (2015), which meant the aircraft had to be rebooted once every 248 days to avoid a counter overflow bug.

The most recent case was an internal timer bug in the Airbus A350 firmware (2019), which requires that the aircraft be rebooted once every 149 hours. 

Avoiding bugs in safety critical systems  

Avionics systems are among the most complex things ever built by man. There's one leading example of a successful avionics project which was built from scratch targeting high quality and zero defects. Its the Boeing 777 - Boeing's first fly-by-wire aircraft.
For the 777, Boeing decided early on to standardize on the Ada programming language, at a time when using C was the norm. Compilers for Ada had been certified as correct, and the language itself included several safety features, such as design by contract and extremely strong typing.

Ada itself came about as a way to standardize all of the programming languages in use by the U.S. Department of Defense - before Ada they were using some 450 different programming languages. Ada was originally designed to be used for embedded and real time systems.

Ronald Ostrowski, Boeing's director of Engineering, claimed that the Boeing 777 was the most tested airplane of its time. For more than 12 months before its maiden flight, Boeing tested the 777's avionics and flight-control systems continuously - 24hrs - 7days - in laboratories simulating millions of flights. 

The 777 first entered commercial service with United Airlines on 7th June, 1995. It has since received more orders than any other wide-body airliner. The 777 is one of Boeing's best-selling models; by 2018 it had become the most-produced Boeing wide-body jet, surpassing the legendary Boeing 747.

Further reading - Boeing flies on 99% Ada

Follow @dodgy_coder

Saturday, September 28, 2019

Review of Shopify - from a developer's point of view

I setup this online shop over a couple of weekends - Chow Slow - Slow Feeder Dog Bowls. After launch I continued to make various improvements and optimisations to the presentation and content of the site. Since launch three months ago, the online shop has so far taken 72 orders.

The eCommerce SaaS product Shopify was used to build the site, on the Basic Shopify (monthly) plan.

Here below are my opinions on Shopify:

Shopify - Good points

  • Many payment options - I chose the Shopify Payments option. It accepts Apple Pay and Google Pay when on a mobile browser for example. You can tell that Shopify have extensive experience with taking payments - everything is really polished.
  • Test mode works well for putting through test credit card orders and seeing the customer experience end to end. Can also password protect the site while its under development.
  • The free themes are good and can be customised for most online shops. I used the free "Minimal" theme and then customised the layout of the home page, added several pages and added a blog.
  • Great optimisations and layouts which work well on mobile. More than 60% of the traffic for the site comes from a smartphone browser as opposed to a traditional desktop browser.
  • Really useful "Timeline" admin feature on the customer and order admin pages - see all the interactions that have happened with a customer in a simple timeline display, with a timestamp shown on each interaction.
  • Excellent "Conversion Summary" admin feature - see the site behaviour of your customer from when they first visited your site to when they bought something.
  • Comprehensive "Fraud Analysis" admin feature - for orders paid by Credit Card - recommendation of whether the transaction is likely fraudulent or not: probability shown as low, medium, or high.
  • Ability for customers to sign up with either their mobile phone number or email address. Shopify automatically sends communications to the customer using either mobile SMS or by email.
  • Easy to add social media accounts, which then automatically appear on the site footer.
  • Products are easy to configure and easy to change in terms of page title and content.
  • Ability to edit raw HTML in most places.
  • Easy to setup a custom domain, with TLS/SSL included (which just works).
  • There are SEO optimisations and settings available at a page level. You can change the page title, meta description and URL.
  • Integration with Google Analytics is excellent - the 'Advanced eCommerce' option should be turned on - it results in a data going straight into GA for your conversions and sales.
  • Page load time is good - bulk of the home page loads typically in 2-3 seconds.
  • A comprehensive API for writing custom integrations with other backend software and systems.
Shopify - Bad points
  • Marketing integrations - Facebook Ads for example - difficult and error prone to setup. Facebook Ads never worked for me after many headaches trying to setup. The marketing integrations seem like a quick way to lose money fast.
  • Inability to structure the Products, Pages and Blog sections to be within a custom sub-folders structure (as is typically recommended to silo a website for SEO purposes).
  • Checkout page customization is limited to Shopify Plus users.
  • Checkout script editor is limited to Shopify Plus, so any custom logic to apply discounts has to be done through plugins.
  • API is rate limited - will be fine for most users however ERP systems which run via batch processing or via polling may have issues. You need to implement everything as event driven webhooks rather than by polling the Shopify API.
Shopify - Areas for improvement
  • I'm not convinced of the need for many of the Shopify apps (plug-ins) that get automatically suggested. I have a feeling that they will result in bigger page sizes and slower load times. I have not needed to use any apps yet.
  • Its sometimes hard to find the relevant place for a setting - whether under preferences of the online shop or under settings of the account itself. I should probably make more use of the search bar at the top for this in the future.
Shopify - Conclusion

I highly recommend Shopify for setting up an online shop. When launching, your focus will be taken up with gaining your first customers, online marketing and the delivery process, so having a solid full featured website behind you is crucial.




A bit more about our online shop - Chow Slow - Slow Feeder Dog Bowls

I setup the site for my wife, who runs the business day to day. She handles the processing of orders and deliveries. We came up with the idea of selling to this niche market after finding out about this type of product in 2018. Our pet beagle (Ripley) had an issue of regular regurgitation due to eating too quickly. The slow feeder bowl product solved his problem and results in more relaxed meal times every day.



Follow @dodgy_coder

Thursday, April 18, 2019

Inactive/Failing Mobile Apps: The Many Benefits of Regular App Updates

This article applies mainly to mobile apps which are not in active development. It applies equally to mobile apps on the public app stores and also to enterprise mobile apps which get distributed via other means (such as MDM software).

Example scenario of an inactive/failing app:
  • The active marketing of your app that happened at launch has now stopped
  • Your app's last update was several months ago
  • The uninstallation rate has started rising above your installation rate month on month

A way to prevent this happening is to release regular app updates, even when there are no major changes to your app's code.



Benefits of releasing regular app updates:

  • Gain new users; many users look at the last release date on the app store page before downloading your app. Anything over a year old can be immediately rejected as out of date.
  • Prevent uninstalls; seeing your app has been updated on their phone keeps it in the user's mindshare, so they know you are still actively developing it.
  • Update the dependencies; you will likely have several dependencies on open source libraries and mobile SDKs. The more often you release, the more often these can be updated too.
  • Update the toolchain; Xcode / Android Studio / Visual Studio get updated once every month or two. Same applies to hybrid and cross platform toolchains such as Unity, Ionic and Xamarin.
  • Update the store listing; since you're doing a build, take the opportunity to review and tweak the store listing and screenshots. Apple's App Store Connect website and Android's Google Play Console get updated regularly with enhancements you can take advantage of.
  • Less build issues; there will be a lower chance of a major build issue if you regularly update your toolchain and its dependencies. In my experience, the longer you wait between app builds and releases, the greater the chance of a major build issue the next time.
  • Source control change visibility; the project is kept active in terms of source control history; especially relevant if its an open source project with other potential developers able to see the change history on github or bitbucket.
  • Developer benefits; you don't end up with a legacy mobile app that noone can get building anymore.

What if there are no significant changes to your code?
  • Have the dependencies or toolchain been updated? If yes, that means your app has gained some potential bug fixes and enhancements for free - just by doing a build.
  • There's always some minor refactoring you can do to make small improvements to your codebase. Just spend a couple of hours if that's all you can spare.
  • The release note; just use the standard "Bug fixes, performance and stability improvements" if you can't think of anything else.

How often to release?
  • The more often the better.
  • Aim for a regular release cycle of between 1-3 months.

Further reading

Distribution of Android apps per download range
https://www.statista.com/statistics/269884/android-app-downloads/

Download distribution of Android apps, and lifetime growth rates per download range
https://www.appbrain.com/stats/android-app-downloads

Statistics about the release schedule of apps on the Apple app store
https://stories.appbot.co/how-often-should-you-update-your-app-9405b85a967c

Best practices for Apple app store updates
https://developer.apple.com/app-store/app-updates/


Follow @dodgy_coder

Subscribe to posts via RSS


Sunday, September 18, 2016

Lightweight IoT Command and Control

Many hobbyist IoT projects running on the Raspberry Pi (RPi) require a webserver running on the RPi which receives requests from a browser, where the client using the browser is connected either to the local WiFi network, or possibly (via a port forwarding setup), connected to the public Internet.

An alternative that is easy to setup, lightweight and low cost is one that makes use of Amazon's SQS (Simple Queue Service) to setup two queues. One queue is for commands - from a mobile application to the RPi. Another queue is for responses - from the RPi back to the mobile application. It results in a simple and easy to secure solution available over the public Internet. It requires no port forwarding - both endpoints make use of a client connection to Amazon AWS. Given the small amount of messages needed for typical hobbyist project, the SQS component will be covered by the AWS free tier.

Here's the high level design of the system ...

Lightweight IoT Command and Control
On the Raspberry Pi, a lightweight application is running that makes use of the excellent Python boto3 AWS SDK library. It is always waiting for a command to arrive in the command queue. As soon as it receives a command, it processes it and adds a response to the response queue.

On the mobile device an Android application is running that makes use of the AWS Mobile SDK for Android. When the user presses a command button, such as 'Open Garage Door', it adds a command to the command queue, and asynchronously waits for a response to arrive in the response queue. When it receives a response (e.g. the command's success or failure status), it updates the app's user interface.

Saturday, January 2, 2016

Custom domain for Azure Web Apps using FreeDNS

The below steps go through setting up a custom domain name on your Azure Web App, using the FreeDNS service from NameCheap. Both the www subdomain www.yourdomainhere.com and the naked yourdomainhere.com will be setup.

I have an Azure S1 Small Instance App Service Plan on which I'm running 4 web apps. Originally I had planned to use Azure DNS, to keep everything within the same cloud service, but after some initial attempts formed the opinion that Azure DNS isn't mature enough yet to host production web sites. Azure DNS can currently only be administered from within Azure Powershell - that in itself was enough to put me off using it. If you need to make a quick change to a DNS record, you don't want to be having to run Powershell to do it. Microsoft are working on adding Azure DNS to the Azure Portal, but at the moment it's not available.

I have a couple of domains through NameCheap and for those and a couple of others (with CrazyDomains) I decided to use NameCheap's DNS service.  Even when your domain is not registered through NameCheap, they still offer a free DNS service, called FreeDNS.

Note that in the below steps, yourwebappname and yourdomainhere.com should of course be replaced with your specific names.


Step 1. Reduce the TTLs to 5 minutes

Note: you only need to perform this step if you're porting from an existing DNS provider. No need to do this if you're setting up a new web app on a new domain.

Within your current DNS service, setup all the TTL settings (Time To Live) on the DNS records to the minimum (typically 300 seconds, or 5 minutes). This may help in having the DNS changes propagate faster.

After this is done, try to get a full DNS zone file listing. When you port the DNS records to FreeDNS it will help ensure that you don't miss anything. My previous VPS and DNS provider was Linode and I was porting a few web apps from Linode over to Azure web apps.


Step 2. Ensure your Azure web app is running

Ensure your web app is published and running ok at http://yourwebappname.azurewebsites.net


Step 3. Find the IPv4 address of your Azure web app

From a windows cmd.exe prompt ...

C:\> nslookup yourwebappname.azurewebsites.net

Server:  UnKnown
Address:  192.168.1.1

Non-authoritative answer:
Name:    waws-prod-xxx-xxx.cloudapp.net
Address:  1.2.3.4
Aliases: 
yourwebappname.azurewebsites.net
          waws-prod-xxx-xxx.vip.azurewebsites.windows.net


The nslookup command will provide you with your web app's IPv4 address. This is shown in the second Address field above, e.g. 1.2.3.4. I am running an Azure S1 Small Instance App Service Plan. I believe this method still applies to other plans including shared instance plans.

Note that if your web app is restarted or stopped this may result in it being assigned a different IP address. Be aware of this when using naked domain URLs (without the www prefix) since these rely on the A record being configured for the correct IP address of your web app (as per step 6).


Step 4. Setup FreeDNS

On the NameCheap FreeDNS page, enter yourdomainhere.com and click 'Get DNS'. If its eligible, then click 'Add to Cart', then click 'Set up DNS'.

You get this message from NameCheap :-

N.B. don't go ahead and set the nameservers just yet, that step will come later.

    yourdomainhere.com
    Congratulations! Your domain/ sub-domain is added to our DNS service.
    Please set the nameservers of your domain/ sub-domain to

        freedns1.registrar-servers.com
        freedns2.registrar-servers.com
        freedns3.registrar-servers.com
        freedns4.registrar-servers.com
        freedns5.registrar-servers.com

    Our system will periodically monitor your domain's DNS setting and will activate your domain once it is pointing to our servers.

   

Step 5. Verify ownership of your domain

In NameCheap, on the Domain List page, once the yourdomainhere.com is listed as active, then need to click on "Authorize DNS" link...

Select the required email, such as admin@yourdomainhere.com to use as the auth email.

On the domain page, the redirect domain setting will show "Your FreeDNS domain is waiting for Authorization or Verification by domain owner."

In the received email, click on the embedded hyperlink and then on the webpage, click the "I AUTHORIZE" hyperlink.

A message should display "Host has been successfully activated".


Step 6. Setup the FreeDNS records

At this step you'll setup all of the DNS records for your domain.
For all of these I left them with the default TTL setting of 'Automatic'.
In NameCheap, on the Domain List page, click the MANAGE button next to your domain, then click on the Advanced DNS tab.

In the Host records, add the A record with the IP that was returned in step 3.

Type  Host  Value            TTL
A     @     1.2.3.4          Automatic


Add any required TXT records (often used for verification).

Add the 3 CNAME records required to verify ownership of the domain to Azure.

1. Set HOST to awverify
    Set Target to awverify.yourwebappname.azurewebsites.net

2. Set HOST to awverify.www
    Set Target to awverify.yourwebappname.azurewebsites.net

3. Set HOST to www
    Set Target to yourwebappname.azurewebsites.net
  
If required, set the mail setting to Custom MX and add the MX server records...
For example if you have Gmail enabled on the domain you'd use these MX records...

Set Mail to Custom MX

Host        Type Priority      Mail server name
@            MX     20         ALT1.ASPMX.L.GOOGLE.COM.
@            MX     10         ASPMX.L.GOOGLE.COM.
@            MX     20         ALT2.ASPMX.L.GOOGLE.COM.
@            MX     30         ASPMX2.GOOGLEMAIL.COM.
@            MX     30         ASPMX3.GOOGLEMAIL.COM.

  
  
Step 7. Change the DNS nameservers using your registrar

For the case when your registrar is not NameCheap, you'll need to point the nameservers for the domain to the FreeDNS nameservers.

Log into your registrar's website and set the following nameservers, removing the existing nameservers if required ...

        freedns1.registrar-servers.com
        freedns2.registrar-servers.com
        freedns3.registrar-servers.com
        freedns4.registrar-servers.com
        freedns5.registrar-servers.com



Step 8. Wait for the DNS nameserver change to propagate

You can check whether the changes have propagated yet using nslookup from the windows command line ...

C:\> nslookup yourdomainhere.com
C:\> nslookup www.
yourdomainhere.com
C:\> nslookup awverify.
yourdomainhere.com
C:\> nslookup awverify.www.
yourdomainhere.com

Use nslookup in interactive mode for MX and TXT record lookups ...


C:\> nslookup

set q=mx

yourdomainhere.com

set q=txt

yourdomainhere.com

exit


Or you can also use these great online tools for checking the DNS propagation ...

    http://www.whatsmydns.net
    https://www.ultratools.com/tools/dnsLookup

Or on Linux I believe the command is: dig yourdomainhere.com

   
Step 9. Bring the domains into your web app using the Azure Portal

In the Azure portal, go to yourwebappname Web App -> Settings -> Custom Domains and SSL -> Bring External Domains

Enter yourdomainhere.com into the field, and then press tab. Wait for it to verify your CNAME records.

In the next field, enter www.yourdomainhere.com and press tab again. Wait for it to verify your CNAME records.

It should succeed as you tab out of each field, and after you click the save button at the top, it should report "Updating hostname bindings".


Step 10. Test in a browser

Open both www.yourdomainhere.com and yourdomainhere.com in a browser and confirm that they load ok.

Turn on the browser's web developer tools (Network tab) to check that all the components of the web app are loading with HTTP 200 OK status, and are resolving to the new IP address.

Its normal to experience some issues for the first several hours after changing nameservers, for example you may see the domain resolve to the old name server settings or flipping back and forth from new to old. Usually this will settle down after a few hours. It can be caused by the browser caching DNS results, something I've noticed particularly bad in Firefox sometimes. You may also need to flush the DNS cache on the computer you are using.


Flush the DNS cache in windows via:

C:\> ipconfig /flushdns


Other references ...

There is some additional Azure related information in the below post about this subject:
https://azure.microsoft.com/en-us/documentation/articles/web-sites-custom-domain-name/



Follow @dodgy_coder


Subscribe to posts via RSS