Transaction.fromBuffer constructor

Transaction.fromBuffer(
  1. Uint8List buffer, {
  2. bool noStrict = false,
})

Implementation

factory Transaction.fromBuffer(
  Uint8List buffer, {
  bool noStrict = false,
}) {
  var offset = 0;
  // Any changes made to the ByteData will also change the buffer, and vice versa.
  // https://api.dart.dev/stable/2.7.1/dart-typed_data/ByteBuffer/asByteData.html
  ByteData bytes = buffer.buffer.asByteData();

  int readUInt8() {
    final i = bytes.getUint8(offset);
    offset++;
    return i;
  }

  int readUInt32() {
    final i = bytes.getUint32(offset, Endian.little);
    offset += 4;
    return i;
  }

  int readInt32() {
    final i = bytes.getInt32(offset, Endian.little);
    offset += 4;
    return i;
  }

  int readUInt64() {
    final i = bytes.getUint64(offset, Endian.little);
    offset += 8;
    return i;
  }

  Uint8List readSlice(n) {
    offset += n as int;
    return buffer.sublist(offset - n, offset);
  }

  int readVarInt() {
    final vi = varuint.decode(buffer, offset);
    offset += varuint.encodingLength(vi);
    return vi;
  }

  Uint8List readVarSlice() {
    return readSlice(readVarInt());
  }

  List<Uint8List> readVector() {
    var count = readVarInt();
    List<Uint8List> vector = [];
    for (var i = 0; i < count; ++i) {
      vector.add(readVarSlice());
    }
    return vector;
  }

  final tx = new Transaction();
  tx.version = readInt32();

  final marker = readUInt8();
  final flag = readUInt8();

  var hasWitnesses = false;
  if (marker == ADVANCED_TRANSACTION_MARKER &&
      flag == ADVANCED_TRANSACTION_FLAG) {
    hasWitnesses = true;
  } else {
    offset -= 2; // Reset offset if not segwit tx
  }

  final vinLen = readVarInt();
  for (var i = 0; i < vinLen; ++i) {
    tx.ins.add(new Input(
        hash: readSlice(32),
        index: readUInt32(),
        script: readVarSlice(),
        sequence: readUInt32()));
  }

  final voutLen = readVarInt();
  for (var i = 0; i < voutLen; ++i) {
    tx.outs.add(new Output(value: readUInt64(), script: readVarSlice()));
  }

  if (hasWitnesses) {
    for (var i = 0; i < vinLen; ++i) {
      tx.ins[i].witness = readVector();
    }
  }

  tx.locktime = readUInt32();

  if (noStrict) return tx;

  if (offset != buffer.length)
    throw new ArgumentError('Transaction has unexpected data');

  return tx;
}