Migration Notes
Last updated
Was this helpful?
Last updated
Was this helpful?
The older preimage-based introspection/covenants have been replaced with the newly supported native introspection/covenants. This has significant consequences for any existing covenant contracts, but in general this native introspection makes covenants more accessible, flexible and efficient. See below for a list of changes. In some cases there is no one to one mapping between the old introspection and the new introspection methods, so the logic of the smart contracts will need to be refactored as well.
Most importantly, it is now possible to access specific data for all individual inputs and outputs, rather than e.g. working with hashes of the outputs (tx.hashOutputs
). This offers more flexibility around the data you want to enforce. For more information about this new native introspection functionality, refer to the section of the documentation, the and the .
tx.version
and tx.locktime
used to be bytes4
, but are now int
.
tx.hashtype
has been removed and can no longer be accessed.
tx.hashPrevouts
and tx.outpoint
have been removed. Instead, the outpoints of individual inputs can be accessed with tx.inputs[i].outpointTransactionHash
and tx.inputs[i].outpointIndex
. The index of the active input can be accessed with this.activeInputIndex
.
tx.hashSequence
and tx.sequence
have been removed. Instead, the sequence numbers of individual inputs can be accessed with tx.inputs[i].sequenceNumber
. The index of the active input can be accessed with this.activeInputIndex
.
tx.bytecode
has been renamed to this.activeBytecode
tx.value
has been removed. Instead, the value of individual inputs can be accessed with tx.inputs[i].value
. The index of the active input can be accessed with this.activeInputIndex
.
tx.hashOutputs
has been removed. Instead, the value and locking bytecode of individual outputs can be accessed separately with tx.outputs[i].value
and tx.outputs[i].lockingBytecode
.
Additionally, it is now possible to access the number of inputs and outputs with tx.inputs.length
and tx.outputs.length
. It is also possible to access individual inputs' locking bytecode and unlocking bytecode with tx.inputs[i].lockingBytecode
and tx.inputs[i].unlockingBytecode
. It is also no longer a requirement to have a signature check somewhere in the contract in order to use this introspection/covenant functionality.
OutputP2PKH
, OutputP2SH
and OutputNullData
have been replaced by LockingBytecodeP2PKH
, LockingBytecodeP2SH
and LockingBytecodeNullData
respectively. These new classes only produce the locking bytecode, rather than the full output (including value). This means that the locking bytecode and value of outputs need to be checked separately.
Casting from sig
to datasig
has been removed since that was only useful for old-style covenants. If, for any reason, you do want to cast a sig to a datasig you will need to manually cut the hashtype
off the end and update datasig(s)
to s.split(s.length - 1)[0]
.
Since the new covenant functionality is very different from the existing, it may be useful to see a complex covenant contract refactored from the old way to the new way.
```solidity title="Mecenas.cash v0.6.0" pragma cashscript ^0.6.0;
contract Mecenas(bytes20 recipient, bytes20 funder, int pledge, int period) { function receive(pubkey pk, sig s) { require(checkSig(s, pk)); require(tx.age >= period);
}
The exports for library usage of cashc
have been updated. All utility-type exports have been moved to the @cashscript/utils
package, but they are still accessible from the utils
export from cashc
. Note that the recommended use of cashc
is still the CLI, not the NPM package.
In v0.5 you could encode a string like this:
While for v0.6 you'd need to use the utils
export or @cashscript/utils
:
Compilation functions used to be exported as part of the CashCompiler
object, but are now exported as standalone functions.
In v0.5 compilation looked like this:
In v0.6, this needs to be changed to this:
The CashScript SDK no longer depends on cashc
and no longer exports the CashCompiler
object. This reflects the recommended usage where the CLI is used for compilation and the artifact JSON is saved. Then this artifact JSON can be imported into the CashScript SDK. If you prefer to compile your contracts from code, you need to add cashc
as a dependency and use its compilation functionality.
The contract instantiation flow has been refactored to enable compatibility with more BCH libraries and simplify the different classes involved.
In v0.4 a contract could be compiled or imported using Contract.compile()
or Contract.import()
, which returned a Contract object. On that Contract object contract.new(...args)
could be called, which returned an Instance object. In the v0.5 release, the Contract and Instance objects have been merged and simplified, while the compilation has been extracted into its own class.
In v0.4, contract instantiation looked like this:
In v0.5, this needs to be changed to look like this:
Transaction object's .send()
function now returns either a libauth Transaction or raw hex string rather than a BITBOX Transaction. If it is necessary, the raw hex string can be imported into libraries such as BITBOX to achieve similar functionality as before.
In v0.4.1, Sig
was deprecated in favour of SignatureTemplate
. In v0.5.0, the deprecated class has been removed. All occurrences of Sig
should be replaced with SignatureTemplate
.
In v0.3, casting an int
type to a bytes
would perform an NUM2BIN
operation, padding the value to 8 bytes. This made bytes(10)
equivalent to bytes8(10)
. From v0.4.0 onwards, casting to an unbounded bytes
type is only a semantic cast, indicating that the int
value should be treated as a bytes
value.
If you need the old behaviour, you should change all occurrences of bytes(x)
to bytes8(x)
.
The entire Transaction
flow has been refactored to a more fluent chained TransactionBuilder API.
All occurrences of .send(to, amount)
should be replaced with .to(to, amount).send()
.
All occurrences of .send(outputs)
should be replaced with .to(outputs).send()
.
Alternatively, the list of outputs
can be split up between several .to()
calls.
If any of the outputs contain opReturn
outputs, these should be added separately using .withOpReturn(chunks)
The same transformations are applicable to all .meep()
calls.
The meep()
function previously logged the meep command automatically, but now it returns the command as a string, so you should console.log()
the command separately.
All transaction options previously included in the TxOptions
object should now be provided using chained functions.
The time
option should be provided using the .withTime(time)
function.
The age
option should be provided using the .withAge(age)
function.
The fee
option should be provided using the .withHardcodedFee(fee)
function.
The minChange
option should be provided using the .withMinChange(minChange)
function.
In v0.2.2, Contract.fromCashFile()
and Contract.fromArtifact()
were deprecated in favour of Contract.compile()
and Contract.import()
. In v0.4.0, the deprecated functions have been removed.
All occurrences of Contract.fromCashFile()
should be replaced with Contract.compile()
.
All occurrences of Contract.fromArtifact()
should be replaced with Contract.import()
.
See the for an overview of other new changes.
See the for an overview of other new changes.