fix vendor folder
This commit is contained in:
parent
240b7f00bd
commit
a60e97ace6
1
go.mod
1
go.mod
|
@ -10,7 +10,6 @@ require (
|
|||
github.com/btcsuite/btcwallet/walletdb v1.1.0
|
||||
github.com/lightninglabs/neutrino v0.10.0
|
||||
github.com/muun/libwallet v0.1.4
|
||||
github.com/pkg/errors v0.8.1
|
||||
)
|
||||
|
||||
replace github.com/lightninglabs/neutrino => github.com/muun/neutrino v0.0.0-20190914162326-7082af0fa257
|
||||
|
|
1
go.sum
1
go.sum
|
@ -22,6 +22,7 @@ github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d h1:yJzD/yFppdVCf6
|
|||
github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg=
|
||||
github.com/btcsuite/btcwallet v0.10.0 h1:fFZncfYJ7VByePTGttzJc3qfCyDzU95ucZYk0M912lU=
|
||||
github.com/btcsuite/btcwallet v0.10.0/go.mod h1:4TqBEuceheGNdeLNrelliLHJzmXauMM2vtWfuy1pFiM=
|
||||
github.com/btcsuite/btcwallet v0.10.1-0.20191109031858-c49e7ef3ecf1/go.mod h1:4TqBEuceheGNdeLNrelliLHJzmXauMM2vtWfuy1pFiM=
|
||||
github.com/btcsuite/btcwallet/wallet/txauthor v1.0.0/go.mod h1:VufDts7bd/zs3GV13f/lXc/0lXrPnvxD/NvmpG/FEKU=
|
||||
github.com/btcsuite/btcwallet/wallet/txrules v1.0.0/go.mod h1:UwQE78yCerZ313EXZwEiu3jNAtfXj2n2+c8RWiE/WNA=
|
||||
github.com/btcsuite/btcwallet/wallet/txsizes v1.0.0/go.mod h1:pauEU8UuMFiThe5PB3EO+gO5kx87Me5NvdQDsTuq6cs=
|
||||
|
|
|
@ -36,10 +36,17 @@ var (
|
|||
// interface from crypto/elliptic.
|
||||
type KoblitzCurve struct {
|
||||
*elliptic.CurveParams
|
||||
q *big.Int
|
||||
|
||||
// q is the value (P+1)/4 used to compute the square root of field
|
||||
// elements.
|
||||
q *big.Int
|
||||
|
||||
H int // cofactor of the curve.
|
||||
halfOrder *big.Int // half the order N
|
||||
|
||||
// fieldB is the constant B of the curve as a fieldVal.
|
||||
fieldB *fieldVal
|
||||
|
||||
// byteSize is simply the bit size / 8 and is provided for convenience
|
||||
// since it is calculated repeatedly.
|
||||
byteSize int
|
||||
|
@ -879,12 +886,22 @@ func (curve *KoblitzCurve) ScalarBaseMult(k []byte) (*big.Int, *big.Int) {
|
|||
return curve.fieldJacobianToBigAffine(qx, qy, qz)
|
||||
}
|
||||
|
||||
// QPlus1Div4 returns the Q+1/4 constant for the curve for use in calculating
|
||||
// square roots via exponention.
|
||||
// QPlus1Div4 returns the (P+1)/4 constant for the curve for use in calculating
|
||||
// square roots via exponentiation.
|
||||
//
|
||||
// DEPRECATED: The actual value returned is (P+1)/4, where as the original
|
||||
// method name implies that this value is (((P+1)/4)+1)/4. This method is kept
|
||||
// to maintain backwards compatibility of the API. Use Q() instead.
|
||||
func (curve *KoblitzCurve) QPlus1Div4() *big.Int {
|
||||
return curve.q
|
||||
}
|
||||
|
||||
// Q returns the (P+1)/4 constant for the curve for use in calculating square
|
||||
// roots via exponentiation.
|
||||
func (curve *KoblitzCurve) Q() *big.Int {
|
||||
return curve.q
|
||||
}
|
||||
|
||||
var initonce sync.Once
|
||||
var secp256k1 KoblitzCurve
|
||||
|
||||
|
@ -917,6 +934,7 @@ func initS256() {
|
|||
big.NewInt(1)), big.NewInt(4))
|
||||
secp256k1.H = 1
|
||||
secp256k1.halfOrder = new(big.Int).Rsh(secp256k1.N, 1)
|
||||
secp256k1.fieldB = new(fieldVal).SetByteSlice(secp256k1.B.Bytes())
|
||||
|
||||
// Provided for convenience since this gets computed repeatedly.
|
||||
secp256k1.byteSize = secp256k1.BitSize / 8
|
||||
|
|
|
@ -102,6 +102,20 @@ const (
|
|||
fieldPrimeWordOne = 0x3ffffbf
|
||||
)
|
||||
|
||||
var (
|
||||
// fieldQBytes is the value Q = (P+1)/4 for the secp256k1 prime P. This
|
||||
// value is used to efficiently compute the square root of values in the
|
||||
// field via exponentiation. The value of Q in hex is:
|
||||
//
|
||||
// Q = 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffff0c
|
||||
fieldQBytes = []byte{
|
||||
0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0x0c,
|
||||
}
|
||||
)
|
||||
|
||||
// fieldVal implements optimized fixed-precision arithmetic over the
|
||||
// secp256k1 finite field. This means all arithmetic is performed modulo
|
||||
// 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f. It
|
||||
|
@ -1221,3 +1235,118 @@ func (f *fieldVal) Inverse() *fieldVal {
|
|||
f.Square().Square().Square().Square().Square() // f = a^(2^256 - 4294968320)
|
||||
return f.Mul(&a45) // f = a^(2^256 - 4294968275) = a^(p-2)
|
||||
}
|
||||
|
||||
// SqrtVal computes the square root of x modulo the curve's prime, and stores
|
||||
// the result in f. The square root is computed via exponentiation of x by the
|
||||
// value Q = (P+1)/4 using the curve's precomputed big-endian representation of
|
||||
// the Q. This method uses a modified version of square-and-multiply
|
||||
// exponentiation over secp256k1 fieldVals to operate on bytes instead of bits,
|
||||
// which offers better performance over both big.Int exponentiation and bit-wise
|
||||
// square-and-multiply.
|
||||
//
|
||||
// NOTE: This method only works when P is intended to be the secp256k1 prime and
|
||||
// is not constant time. The returned value is of magnitude 1, but is
|
||||
// denormalized.
|
||||
func (f *fieldVal) SqrtVal(x *fieldVal) *fieldVal {
|
||||
// The following computation iteratively computes x^((P+1)/4) = x^Q
|
||||
// using the recursive, piece-wise definition:
|
||||
//
|
||||
// x^n = (x^2)^(n/2) mod P if n is even
|
||||
// x^n = x(x^2)^(n-1/2) mod P if n is odd
|
||||
//
|
||||
// Given n in its big-endian representation b_k, ..., b_0, x^n can be
|
||||
// computed by defining the sequence r_k+1, ..., r_0, where:
|
||||
//
|
||||
// r_k+1 = 1
|
||||
// r_i = (r_i+1)^2 * x^b_i for i = k, ..., 0
|
||||
//
|
||||
// The final value r_0 = x^n.
|
||||
//
|
||||
// See https://en.wikipedia.org/wiki/Exponentiation_by_squaring for more
|
||||
// details.
|
||||
//
|
||||
// This can be further optimized, by observing that the value of Q in
|
||||
// secp256k1 has the value:
|
||||
//
|
||||
// Q = 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffff0c
|
||||
//
|
||||
// We can unroll the typical bit-wise interpretation of the
|
||||
// exponentiation algorithm above to instead operate on bytes.
|
||||
// This reduces the number of comparisons by an order of magnitude,
|
||||
// reducing the overhead of failed branch predictions and additional
|
||||
// comparisons in this method.
|
||||
//
|
||||
// Since there there are only 4 unique bytes of Q, this keeps the jump
|
||||
// table small without the need to handle all possible 8-bit values.
|
||||
// Further, we observe that 29 of the 32 bytes are 0xff; making the
|
||||
// first case handle 0xff therefore optimizes the hot path.
|
||||
f.SetInt(1)
|
||||
for _, b := range fieldQBytes {
|
||||
switch b {
|
||||
|
||||
// Most common case, where all 8 bits are set.
|
||||
case 0xff:
|
||||
f.Square().Mul(x)
|
||||
f.Square().Mul(x)
|
||||
f.Square().Mul(x)
|
||||
f.Square().Mul(x)
|
||||
f.Square().Mul(x)
|
||||
f.Square().Mul(x)
|
||||
f.Square().Mul(x)
|
||||
f.Square().Mul(x)
|
||||
|
||||
// First byte of Q (0x3f), where all but the top two bits are
|
||||
// set. Note that this case only applies six operations, since
|
||||
// the highest bit of Q resides in bit six of the first byte. We
|
||||
// ignore the first two bits, since squaring for these bits will
|
||||
// result in an invalid result. We forgo squaring f before the
|
||||
// first multiply, since 1^2 = 1.
|
||||
case 0x3f:
|
||||
f.Mul(x)
|
||||
f.Square().Mul(x)
|
||||
f.Square().Mul(x)
|
||||
f.Square().Mul(x)
|
||||
f.Square().Mul(x)
|
||||
f.Square().Mul(x)
|
||||
|
||||
// Byte 28 of Q (0xbf), where only bit 7 is unset.
|
||||
case 0xbf:
|
||||
f.Square().Mul(x)
|
||||
f.Square()
|
||||
f.Square().Mul(x)
|
||||
f.Square().Mul(x)
|
||||
f.Square().Mul(x)
|
||||
f.Square().Mul(x)
|
||||
f.Square().Mul(x)
|
||||
f.Square().Mul(x)
|
||||
|
||||
// Byte 31 of Q (0x0c), where only bits 3 and 4 are set.
|
||||
default:
|
||||
f.Square()
|
||||
f.Square()
|
||||
f.Square()
|
||||
f.Square()
|
||||
f.Square().Mul(x)
|
||||
f.Square().Mul(x)
|
||||
f.Square()
|
||||
f.Square()
|
||||
}
|
||||
}
|
||||
|
||||
return f
|
||||
}
|
||||
|
||||
// Sqrt computes the square root of f modulo the curve's prime, and stores the
|
||||
// result in f. The square root is computed via exponentiation of x by the value
|
||||
// Q = (P+1)/4 using the curve's precomputed big-endian representation of the Q.
|
||||
// This method uses a modified version of square-and-multiply exponentiation
|
||||
// over secp256k1 fieldVals to operate on bytes instead of bits, which offers
|
||||
// better performance over both big.Int exponentiation and bit-wise
|
||||
// square-and-multiply.
|
||||
//
|
||||
// NOTE: This method only works when P is intended to be the secp256k1 prime and
|
||||
// is not constant time. The returned value is of magnitude 1, but is
|
||||
// denormalized.
|
||||
func (f *fieldVal) Sqrt() *fieldVal {
|
||||
return f.SqrtVal(f)
|
||||
}
|
||||
|
|
|
@ -1,63 +0,0 @@
|
|||
// Copyright 2015 The btcsuite developers
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This file is ignored during the regular build due to the following build tag.
|
||||
// It is called by go generate and used to automatically generate pre-computed
|
||||
// tables used to accelerate operations.
|
||||
// +build ignore
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/zlib"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/btcsuite/btcd/btcec"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fi, err := os.Create("secp256k1.go")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer fi.Close()
|
||||
|
||||
// Compress the serialized byte points.
|
||||
serialized := btcec.S256().SerializedBytePoints()
|
||||
var compressed bytes.Buffer
|
||||
w := zlib.NewWriter(&compressed)
|
||||
if _, err := w.Write(serialized); err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
w.Close()
|
||||
|
||||
// Encode the compressed byte points with base64.
|
||||
encoded := make([]byte, base64.StdEncoding.EncodedLen(compressed.Len()))
|
||||
base64.StdEncoding.Encode(encoded, compressed.Bytes())
|
||||
|
||||
fmt.Fprintln(fi, "// Copyright (c) 2015 The btcsuite developers")
|
||||
fmt.Fprintln(fi, "// Use of this source code is governed by an ISC")
|
||||
fmt.Fprintln(fi, "// license that can be found in the LICENSE file.")
|
||||
fmt.Fprintln(fi)
|
||||
fmt.Fprintln(fi, "package btcec")
|
||||
fmt.Fprintln(fi)
|
||||
fmt.Fprintln(fi, "// Auto-generated file (see genprecomps.go)")
|
||||
fmt.Fprintln(fi, "// DO NOT EDIT")
|
||||
fmt.Fprintln(fi)
|
||||
fmt.Fprintf(fi, "var secp256k1BytePoints = %q\n", string(encoded))
|
||||
|
||||
a1, b1, a2, b2 := btcec.S256().EndomorphismVectors()
|
||||
fmt.Println("The following values are the computed linearly " +
|
||||
"independent vectors needed to make use of the secp256k1 " +
|
||||
"endomorphism:")
|
||||
fmt.Printf("a1: %x\n", a1)
|
||||
fmt.Printf("b1: %x\n", b1)
|
||||
fmt.Printf("a2: %x\n", a2)
|
||||
fmt.Printf("b2: %x\n", b2)
|
||||
}
|
|
@ -22,41 +22,40 @@ func isOdd(a *big.Int) bool {
|
|||
return a.Bit(0) == 1
|
||||
}
|
||||
|
||||
// decompressPoint decompresses a point on the given curve given the X point and
|
||||
// decompressPoint decompresses a point on the secp256k1 curve given the X point and
|
||||
// the solution to use.
|
||||
func decompressPoint(curve *KoblitzCurve, x *big.Int, ybit bool) (*big.Int, error) {
|
||||
// TODO: This will probably only work for secp256k1 due to
|
||||
// optimizations.
|
||||
func decompressPoint(curve *KoblitzCurve, bigX *big.Int, ybit bool) (*big.Int, error) {
|
||||
var x fieldVal
|
||||
x.SetByteSlice(bigX.Bytes())
|
||||
|
||||
// Y = +-sqrt(x^3 + B)
|
||||
x3 := new(big.Int).Mul(x, x)
|
||||
x3.Mul(x3, x)
|
||||
x3.Add(x3, curve.Params().B)
|
||||
x3.Mod(x3, curve.Params().P)
|
||||
// Compute x^3 + B mod p.
|
||||
var x3 fieldVal
|
||||
x3.SquareVal(&x).Mul(&x)
|
||||
x3.Add(curve.fieldB).Normalize()
|
||||
|
||||
// Now calculate sqrt mod p of x^3 + B
|
||||
// This code used to do a full sqrt based on tonelli/shanks,
|
||||
// but this was replaced by the algorithms referenced in
|
||||
// https://bitcointalk.org/index.php?topic=162805.msg1712294#msg1712294
|
||||
y := new(big.Int).Exp(x3, curve.QPlus1Div4(), curve.Params().P)
|
||||
|
||||
if ybit != isOdd(y) {
|
||||
y.Sub(curve.Params().P, y)
|
||||
var y fieldVal
|
||||
y.SqrtVal(&x3).Normalize()
|
||||
if ybit != y.IsOdd() {
|
||||
y.Negate(1).Normalize()
|
||||
}
|
||||
|
||||
// Check that y is a square root of x^3 + B.
|
||||
y2 := new(big.Int).Mul(y, y)
|
||||
y2.Mod(y2, curve.Params().P)
|
||||
if y2.Cmp(x3) != 0 {
|
||||
var y2 fieldVal
|
||||
y2.SquareVal(&y).Normalize()
|
||||
if !y2.Equals(&x3) {
|
||||
return nil, fmt.Errorf("invalid square root")
|
||||
}
|
||||
|
||||
// Verify that y-coord has expected parity.
|
||||
if ybit != isOdd(y) {
|
||||
if ybit != y.IsOdd() {
|
||||
return nil, fmt.Errorf("ybit doesn't match oddness")
|
||||
}
|
||||
|
||||
return y, nil
|
||||
return new(big.Int).SetBytes(y.Bytes()[:]), nil
|
||||
}
|
||||
|
||||
const (
|
||||
|
@ -102,6 +101,17 @@ func ParsePubKey(pubKeyStr []byte, curve *KoblitzCurve) (key *PublicKey, err err
|
|||
if format == pubkeyHybrid && ybit != isOdd(pubkey.Y) {
|
||||
return nil, fmt.Errorf("ybit doesn't match oddness")
|
||||
}
|
||||
|
||||
if pubkey.X.Cmp(pubkey.Curve.Params().P) >= 0 {
|
||||
return nil, fmt.Errorf("pubkey X parameter is >= to P")
|
||||
}
|
||||
if pubkey.Y.Cmp(pubkey.Curve.Params().P) >= 0 {
|
||||
return nil, fmt.Errorf("pubkey Y parameter is >= to P")
|
||||
}
|
||||
if !pubkey.Curve.IsOnCurve(pubkey.X, pubkey.Y) {
|
||||
return nil, fmt.Errorf("pubkey isn't on secp256k1 curve")
|
||||
}
|
||||
|
||||
case PubKeyBytesLenCompressed:
|
||||
// format is 0x2 | solution, <X coordinate>
|
||||
// solution determines which solution of the curve we use.
|
||||
|
@ -115,20 +125,12 @@ func ParsePubKey(pubKeyStr []byte, curve *KoblitzCurve) (key *PublicKey, err err
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
default: // wrong!
|
||||
return nil, fmt.Errorf("invalid pub key length %d",
|
||||
len(pubKeyStr))
|
||||
}
|
||||
|
||||
if pubkey.X.Cmp(pubkey.Curve.Params().P) >= 0 {
|
||||
return nil, fmt.Errorf("pubkey X parameter is >= to P")
|
||||
}
|
||||
if pubkey.Y.Cmp(pubkey.Curve.Params().P) >= 0 {
|
||||
return nil, fmt.Errorf("pubkey Y parameter is >= to P")
|
||||
}
|
||||
if !pubkey.Curve.IsOnCurve(pubkey.X, pubkey.Y) {
|
||||
return nil, fmt.Errorf("pubkey isn't on secp256k1 curve")
|
||||
}
|
||||
return &pubkey, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -276,7 +276,7 @@ func hashToInt(hash []byte, c elliptic.Curve) *big.Int {
|
|||
}
|
||||
|
||||
// recoverKeyFromSignature recovers a public key from the signature "sig" on the
|
||||
// given message hash "msg". Based on the algorithm found in section 5.1.5 of
|
||||
// given message hash "msg". Based on the algorithm found in section 4.1.6 of
|
||||
// SEC 1 Ver 2.0, page 47-48 (53 and 54 in the pdf). This performs the details
|
||||
// in the inner loop in Step 1. The counter provided is actually the j parameter
|
||||
// of the loop * 2 - on the first iteration of j we do the R case, else the -R
|
||||
|
|
|
@ -638,6 +638,7 @@ func NewSearchRawTransactionsCmd(address string, verbose, skip, count *int, vinE
|
|||
type SendRawTransactionCmd struct {
|
||||
HexTx string
|
||||
AllowHighFees *bool `jsonrpcdefault:"false"`
|
||||
MaxFeeRate *int32
|
||||
}
|
||||
|
||||
// NewSendRawTransactionCmd returns a new instance which can be used to issue a
|
||||
|
@ -652,6 +653,17 @@ func NewSendRawTransactionCmd(hexTx string, allowHighFees *bool) *SendRawTransac
|
|||
}
|
||||
}
|
||||
|
||||
// NewSendRawTransactionCmd returns a new instance which can be used to issue a
|
||||
// sendrawtransaction JSON-RPC command to a bitcoind node.
|
||||
//
|
||||
// A 0 maxFeeRate indicates that a maximum fee rate won't be enforced.
|
||||
func NewBitcoindSendRawTransactionCmd(hexTx string, maxFeeRate int32) *SendRawTransactionCmd {
|
||||
return &SendRawTransactionCmd{
|
||||
HexTx: hexTx,
|
||||
MaxFeeRate: &maxFeeRate,
|
||||
}
|
||||
}
|
||||
|
||||
// SetGenerateCmd defines the setgenerate JSON-RPC command.
|
||||
type SetGenerateCmd struct {
|
||||
Generate bool
|
||||
|
|
|
@ -90,28 +90,61 @@ type SoftForkDescription struct {
|
|||
// Bip9SoftForkDescription describes the current state of a defined BIP0009
|
||||
// version bits soft-fork.
|
||||
type Bip9SoftForkDescription struct {
|
||||
Status string `json:"status"`
|
||||
Bit uint8 `json:"bit"`
|
||||
StartTime int64 `json:"startTime"`
|
||||
Timeout int64 `json:"timeout"`
|
||||
Since int32 `json:"since"`
|
||||
Status string `json:"status"`
|
||||
Bit uint8 `json:"bit"`
|
||||
StartTime1 int64 `json:"startTime"`
|
||||
StartTime2 int64 `json:"start_time"`
|
||||
Timeout int64 `json:"timeout"`
|
||||
Since int32 `json:"since"`
|
||||
}
|
||||
|
||||
// StartTime returns the starting time of the softfork as a Unix epoch.
|
||||
func (d *Bip9SoftForkDescription) StartTime() int64 {
|
||||
if d.StartTime1 != 0 {
|
||||
return d.StartTime1
|
||||
}
|
||||
return d.StartTime2
|
||||
}
|
||||
|
||||
// SoftForks describes the current softforks enabled by the backend. Softforks
|
||||
// activated through BIP9 are grouped together separate from any other softforks
|
||||
// with different activation types.
|
||||
type SoftForks struct {
|
||||
SoftForks []*SoftForkDescription `json:"softforks"`
|
||||
Bip9SoftForks map[string]*Bip9SoftForkDescription `json:"bip9_softforks"`
|
||||
}
|
||||
|
||||
// UnifiedSoftForks describes a softforks in a general manner, irrespective of
|
||||
// its activation type. This was a format introduced by bitcoind v0.19.0
|
||||
type UnifiedSoftFork struct {
|
||||
Type string `json:"type"`
|
||||
BIP9SoftForkDescription *Bip9SoftForkDescription `json:"bip9"`
|
||||
Height int32 `json:"height"`
|
||||
Active bool `json:"active"`
|
||||
}
|
||||
|
||||
// UnifiedSoftForks describes the current softforks enabled the by the backend
|
||||
// in a unified manner, i.e, softforks with different activation types are
|
||||
// grouped together. This was a format introduced by bitcoind v0.19.0
|
||||
type UnifiedSoftForks struct {
|
||||
SoftForks map[string]*UnifiedSoftFork `json:"softforks"`
|
||||
}
|
||||
|
||||
// GetBlockChainInfoResult models the data returned from the getblockchaininfo
|
||||
// command.
|
||||
type GetBlockChainInfoResult struct {
|
||||
Chain string `json:"chain"`
|
||||
Blocks int32 `json:"blocks"`
|
||||
Headers int32 `json:"headers"`
|
||||
BestBlockHash string `json:"bestblockhash"`
|
||||
Difficulty float64 `json:"difficulty"`
|
||||
MedianTime int64 `json:"mediantime"`
|
||||
VerificationProgress float64 `json:"verificationprogress,omitempty"`
|
||||
Pruned bool `json:"pruned"`
|
||||
PruneHeight int32 `json:"pruneheight,omitempty"`
|
||||
ChainWork string `json:"chainwork,omitempty"`
|
||||
SoftForks []*SoftForkDescription `json:"softforks"`
|
||||
Bip9SoftForks map[string]*Bip9SoftForkDescription `json:"bip9_softforks"`
|
||||
Chain string `json:"chain"`
|
||||
Blocks int32 `json:"blocks"`
|
||||
Headers int32 `json:"headers"`
|
||||
BestBlockHash string `json:"bestblockhash"`
|
||||
Difficulty float64 `json:"difficulty"`
|
||||
MedianTime int64 `json:"mediantime"`
|
||||
VerificationProgress float64 `json:"verificationprogress,omitempty"`
|
||||
Pruned bool `json:"pruned"`
|
||||
PruneHeight int32 `json:"pruneheight,omitempty"`
|
||||
ChainWork string `json:"chainwork,omitempty"`
|
||||
*SoftForks
|
||||
*UnifiedSoftForks
|
||||
}
|
||||
|
||||
// GetBlockTemplateResultTx models the transactions field of the
|
||||
|
@ -265,6 +298,7 @@ type GetPeerInfoResult struct {
|
|||
type GetRawMempoolVerboseResult struct {
|
||||
Size int32 `json:"size"`
|
||||
Vsize int32 `json:"vsize"`
|
||||
Weight int32 `json:"weight"`
|
||||
Fee float64 `json:"fee"`
|
||||
Time int64 `json:"time"`
|
||||
Height int64 `json:"height"`
|
||||
|
@ -505,6 +539,7 @@ type TxRawResult struct {
|
|||
Hash string `json:"hash,omitempty"`
|
||||
Size int32 `json:"size,omitempty"`
|
||||
Vsize int32 `json:"vsize,omitempty"`
|
||||
Weight int32 `json:"weight,omitempty"`
|
||||
Version int32 `json:"version"`
|
||||
LockTime uint32 `json:"locktime"`
|
||||
Vin []Vin `json:"vin"`
|
||||
|
@ -523,6 +558,7 @@ type SearchRawTransactionsResult struct {
|
|||
Hash string `json:"hash"`
|
||||
Size string `json:"size"`
|
||||
Vsize string `json:"vsize"`
|
||||
Weight string `json:"weight"`
|
||||
Version int32 `json:"version"`
|
||||
LockTime uint32 `json:"locktime"`
|
||||
Vin []VinPrevOut `json:"vin"`
|
||||
|
|
|
@ -253,16 +253,15 @@ func (c *Client) GetDifficulty() (float64, error) {
|
|||
|
||||
// FutureGetBlockChainInfoResult is a promise to deliver the result of a
|
||||
// GetBlockChainInfoAsync RPC invocation (or an applicable error).
|
||||
type FutureGetBlockChainInfoResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns chain info
|
||||
// result provided by the server.
|
||||
func (r FutureGetBlockChainInfoResult) Receive() (*btcjson.GetBlockChainInfoResult, error) {
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
type FutureGetBlockChainInfoResult struct {
|
||||
client *Client
|
||||
Response chan *response
|
||||
}
|
||||
|
||||
// unmarshalPartialGetBlockChainInfoResult unmarshals the response into an
|
||||
// instance of GetBlockChainInfoResult without populating the SoftForks and
|
||||
// UnifiedSoftForks fields.
|
||||
func unmarshalPartialGetBlockChainInfoResult(res []byte) (*btcjson.GetBlockChainInfoResult, error) {
|
||||
var chainInfo btcjson.GetBlockChainInfoResult
|
||||
if err := json.Unmarshal(res, &chainInfo); err != nil {
|
||||
return nil, err
|
||||
|
@ -270,6 +269,59 @@ func (r FutureGetBlockChainInfoResult) Receive() (*btcjson.GetBlockChainInfoResu
|
|||
return &chainInfo, nil
|
||||
}
|
||||
|
||||
// unmarshalGetBlockChainInfoResultSoftForks properly unmarshals the softforks
|
||||
// related fields into the GetBlockChainInfoResult instance.
|
||||
func unmarshalGetBlockChainInfoResultSoftForks(chainInfo *btcjson.GetBlockChainInfoResult,
|
||||
version BackendVersion, res []byte) error {
|
||||
|
||||
switch version {
|
||||
// Versions of bitcoind on or after v0.19.0 use the unified format.
|
||||
case BitcoindPost19:
|
||||
var softForks btcjson.UnifiedSoftForks
|
||||
if err := json.Unmarshal(res, &softForks); err != nil {
|
||||
return err
|
||||
}
|
||||
chainInfo.UnifiedSoftForks = &softForks
|
||||
|
||||
// All other versions use the original format.
|
||||
default:
|
||||
var softForks btcjson.SoftForks
|
||||
if err := json.Unmarshal(res, &softForks); err != nil {
|
||||
return err
|
||||
}
|
||||
chainInfo.SoftForks = &softForks
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Receive waits for the response promised by the future and returns chain info
|
||||
// result provided by the server.
|
||||
func (r FutureGetBlockChainInfoResult) Receive() (*btcjson.GetBlockChainInfoResult, error) {
|
||||
res, err := receiveFuture(r.Response)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
chainInfo, err := unmarshalPartialGetBlockChainInfoResult(res)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Inspect the version to determine how we'll need to parse the
|
||||
// softforks from the response.
|
||||
version, err := r.client.BackendVersion()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = unmarshalGetBlockChainInfoResultSoftForks(chainInfo, version, res)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return chainInfo, nil
|
||||
}
|
||||
|
||||
// GetBlockChainInfoAsync returns an instance of a type that can be used to get
|
||||
// the result of the RPC at some future time by invoking the Receive function
|
||||
// on the returned instance.
|
||||
|
@ -277,7 +329,10 @@ func (r FutureGetBlockChainInfoResult) Receive() (*btcjson.GetBlockChainInfoResu
|
|||
// See GetBlockChainInfo for the blocking version and more details.
|
||||
func (c *Client) GetBlockChainInfoAsync() FutureGetBlockChainInfoResult {
|
||||
cmd := btcjson.NewGetBlockChainInfoCmd()
|
||||
return c.sendCmd(cmd)
|
||||
return FutureGetBlockChainInfoResult{
|
||||
client: c,
|
||||
Response: c.sendCmd(cmd),
|
||||
}
|
||||
}
|
||||
|
||||
// GetBlockChainInfo returns information related to the processing state of
|
||||
|
|
|
@ -19,6 +19,7 @@ import (
|
|||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
@ -103,6 +104,22 @@ type jsonRequest struct {
|
|||
responseChan chan *response
|
||||
}
|
||||
|
||||
// BackendVersion represents the version of the backend the client is currently
|
||||
// connected to.
|
||||
type BackendVersion uint8
|
||||
|
||||
const (
|
||||
// BitcoindPre19 represents a bitcoind version before 0.19.0.
|
||||
BitcoindPre19 BackendVersion = iota
|
||||
|
||||
// BitcoindPost19 represents a bitcoind version equal to or greater than
|
||||
// 0.19.0.
|
||||
BitcoindPost19
|
||||
|
||||
// Btcd represents a catch-all btcd version.
|
||||
Btcd
|
||||
)
|
||||
|
||||
// Client represents a Bitcoin RPC client which allows easy access to the
|
||||
// various RPC methods available on a Bitcoin RPC server. Each of the wrapper
|
||||
// functions handle the details of converting the passed and return types to and
|
||||
|
@ -129,6 +146,11 @@ type Client struct {
|
|||
// POST mode.
|
||||
httpClient *http.Client
|
||||
|
||||
// backendVersion is the version of the backend the client is currently
|
||||
// connected to. This should be retrieved through GetVersion.
|
||||
backendVersionMu sync.Mutex
|
||||
backendVersion *BackendVersion
|
||||
|
||||
// mtx is a mutex to protect access to connection related fields.
|
||||
mtx sync.Mutex
|
||||
|
||||
|
@ -659,6 +681,12 @@ out:
|
|||
log.Infof("Reestablished connection to RPC server %s",
|
||||
c.config.Host)
|
||||
|
||||
// Reset the version in case the backend was
|
||||
// disconnected due to an upgrade.
|
||||
c.backendVersionMu.Lock()
|
||||
c.backendVersion = nil
|
||||
c.backendVersionMu.Unlock()
|
||||
|
||||
// Reset the connection state and signal the reconnect
|
||||
// has happened.
|
||||
c.wsConn = wsConn
|
||||
|
@ -1332,3 +1360,84 @@ func (c *Client) Connect(tries int) error {
|
|||
// All connection attempts failed, so return the last error.
|
||||
return err
|
||||
}
|
||||
|
||||
const (
|
||||
// bitcoind19Str is the string representation of bitcoind v0.19.0.
|
||||
bitcoind19Str = "0.19.0"
|
||||
|
||||
// bitcoindVersionPrefix specifies the prefix included in every bitcoind
|
||||
// version exposed through GetNetworkInfo.
|
||||
bitcoindVersionPrefix = "/Satoshi:"
|
||||
|
||||
// bitcoindVersionSuffix specifies the suffix included in every bitcoind
|
||||
// version exposed through GetNetworkInfo.
|
||||
bitcoindVersionSuffix = "/"
|
||||
)
|
||||
|
||||
// parseBitcoindVersion parses the bitcoind version from its string
|
||||
// representation.
|
||||
func parseBitcoindVersion(version string) BackendVersion {
|
||||
// Trim the version of its prefix and suffix to determine the
|
||||
// appropriate version number.
|
||||
version = strings.TrimPrefix(
|
||||
strings.TrimSuffix(version, bitcoindVersionSuffix),
|
||||
bitcoindVersionPrefix,
|
||||
)
|
||||
switch {
|
||||
case version < bitcoind19Str:
|
||||
return BitcoindPre19
|
||||
default:
|
||||
return BitcoindPost19
|
||||
}
|
||||
}
|
||||
|
||||
// BackendVersion retrieves the version of the backend the client is currently
|
||||
// connected to.
|
||||
func (c *Client) BackendVersion() (BackendVersion, error) {
|
||||
c.backendVersionMu.Lock()
|
||||
defer c.backendVersionMu.Unlock()
|
||||
|
||||
if c.backendVersion != nil {
|
||||
return *c.backendVersion, nil
|
||||
}
|
||||
|
||||
// We'll start by calling GetInfo. This method doesn't exist for
|
||||
// bitcoind nodes as of v0.16.0, so we'll assume the client is connected
|
||||
// to a btcd backend if it does exist.
|
||||
info, err := c.GetInfo()
|
||||
|
||||
switch err := err.(type) {
|
||||
// Parse the btcd version and cache it.
|
||||
case nil:
|
||||
log.Debugf("Detected btcd version: %v", info.Version)
|
||||
version := Btcd
|
||||
c.backendVersion = &version
|
||||
return *c.backendVersion, nil
|
||||
|
||||
// Inspect the RPC error to ensure the method was not found, otherwise
|
||||
// we actually ran into an error.
|
||||
case *btcjson.RPCError:
|
||||
if err.Code != btcjson.ErrRPCMethodNotFound.Code {
|
||||
return 0, fmt.Errorf("unable to detect btcd version: "+
|
||||
"%v", err)
|
||||
}
|
||||
|
||||
default:
|
||||
return 0, fmt.Errorf("unable to detect btcd version: %v", err)
|
||||
}
|
||||
|
||||
// Since the GetInfo method was not found, we assume the client is
|
||||
// connected to a bitcoind backend, which exposes its version through
|
||||
// GetNetworkInfo.
|
||||
networkInfo, err := c.GetNetworkInfo()
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("unable to detect bitcoind version: %v", err)
|
||||
}
|
||||
|
||||
// Parse the bitcoind version and cache it.
|
||||
log.Debugf("Detected bitcoind version: %v", networkInfo.SubVersion)
|
||||
version := parseBitcoindVersion(networkInfo.SubVersion)
|
||||
c.backendVersion = &version
|
||||
|
||||
return *c.backendVersion, nil
|
||||
}
|
||||
|
|
|
@ -244,6 +244,43 @@ func (c *Client) Ping() error {
|
|||
return c.PingAsync().Receive()
|
||||
}
|
||||
|
||||
// FutureGetNetworkInfoResult is a future promise to deliver the result of a
|
||||
// GetNetworkInfoAsync RPC invocation (or an applicable error).
|
||||
type FutureGetNetworkInfoResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns data about
|
||||
// the current network.
|
||||
func (r FutureGetNetworkInfoResult) Receive() (*btcjson.GetNetworkInfoResult, error) {
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Unmarshal result as an array of getpeerinfo result objects.
|
||||
var networkInfo btcjson.GetNetworkInfoResult
|
||||
err = json.Unmarshal(res, &networkInfo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &networkInfo, nil
|
||||
}
|
||||
|
||||
// GetNetworkInfoAsync returns an instance of a type that can be used to get the
|
||||
// result of the RPC at some future time by invoking the Receive function on the
|
||||
// returned instance.
|
||||
//
|
||||
// See GetNetworkInfo for the blocking version and more details.
|
||||
func (c *Client) GetNetworkInfoAsync() FutureGetNetworkInfoResult {
|
||||
cmd := btcjson.NewGetNetworkInfoCmd()
|
||||
return c.sendCmd(cmd)
|
||||
}
|
||||
|
||||
// GetNetworkInfo returns data about the current network.
|
||||
func (c *Client) GetNetworkInfo() (*btcjson.GetNetworkInfoResult, error) {
|
||||
return c.GetNetworkInfoAsync().Receive()
|
||||
}
|
||||
|
||||
// FutureGetPeerInfoResult is a future promise to deliver the result of a
|
||||
// GetPeerInfoAsync RPC invocation (or an applicable error).
|
||||
type FutureGetPeerInfoResult chan *response
|
||||
|
|
|
@ -15,6 +15,12 @@ import (
|
|||
"github.com/btcsuite/btcutil"
|
||||
)
|
||||
|
||||
const (
|
||||
// defaultMaxFeeRate is the default maximum fee rate in sat/KB enforced
|
||||
// by bitcoind v0.19.0 or after for transaction broadcast.
|
||||
defaultMaxFeeRate = btcutil.SatoshiPerBitcoin / 10
|
||||
)
|
||||
|
||||
// SigHashType enumerates the available signature hashing types that the
|
||||
// SignRawTransaction function accepts.
|
||||
type SigHashType string
|
||||
|
@ -296,7 +302,31 @@ func (c *Client) SendRawTransactionAsync(tx *wire.MsgTx, allowHighFees bool) Fut
|
|||
txHex = hex.EncodeToString(buf.Bytes())
|
||||
}
|
||||
|
||||
cmd := btcjson.NewSendRawTransactionCmd(txHex, &allowHighFees)
|
||||
// Due to differences in the sendrawtransaction API for different
|
||||
// backends, we'll need to inspect our version and construct the
|
||||
// appropriate request.
|
||||
version, err := c.BackendVersion()
|
||||
if err != nil {
|
||||
return newFutureError(err)
|
||||
}
|
||||
|
||||
var cmd *btcjson.SendRawTransactionCmd
|
||||
switch version {
|
||||
// Starting from bitcoind v0.19.0, the MaxFeeRate field should be used.
|
||||
case BitcoindPost19:
|
||||
// Using a 0 MaxFeeRate is interpreted as a maximum fee rate not
|
||||
// being enforced by bitcoind.
|
||||
var maxFeeRate int32
|
||||
if !allowHighFees {
|
||||
maxFeeRate = defaultMaxFeeRate
|
||||
}
|
||||
cmd = btcjson.NewBitcoindSendRawTransactionCmd(txHex, maxFeeRate)
|
||||
|
||||
// Otherwise, use the AllowHighFees field.
|
||||
default:
|
||||
cmd = btcjson.NewSendRawTransactionCmd(txHex, &allowHighFees)
|
||||
}
|
||||
|
||||
return c.sendCmd(cmd)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,79 +0,0 @@
|
|||
// Copyright (c) 2015 The btcsuite developers
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//+build ignore
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
var (
|
||||
start = []byte(`// Copyright (c) 2015 The btcsuite developers
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// AUTOGENERATED by genalphabet.go; do not edit.
|
||||
|
||||
package base58
|
||||
|
||||
const (
|
||||
// alphabet is the modified base58 alphabet used by Bitcoin.
|
||||
alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
|
||||
|
||||
alphabetIdx0 = '1'
|
||||
)
|
||||
|
||||
var b58 = [256]byte{`)
|
||||
|
||||
end = []byte(`}`)
|
||||
|
||||
alphabet = []byte("123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz")
|
||||
tab = []byte("\t")
|
||||
invalid = []byte("255")
|
||||
comma = []byte(",")
|
||||
space = []byte(" ")
|
||||
nl = []byte("\n")
|
||||
)
|
||||
|
||||
func write(w io.Writer, b []byte) {
|
||||
_, err := w.Write(b)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
fi, err := os.Create("alphabet.go")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer fi.Close()
|
||||
|
||||
write(fi, start)
|
||||
write(fi, nl)
|
||||
for i := byte(0); i < 32; i++ {
|
||||
write(fi, tab)
|
||||
for j := byte(0); j < 8; j++ {
|
||||
idx := bytes.IndexByte(alphabet, i*8+j)
|
||||
if idx == -1 {
|
||||
write(fi, invalid)
|
||||
} else {
|
||||
write(fi, strconv.AppendInt(nil, int64(idx), 10))
|
||||
}
|
||||
write(fi, comma)
|
||||
if j != 7 {
|
||||
write(fi, space)
|
||||
}
|
||||
}
|
||||
write(fi, nl)
|
||||
}
|
||||
write(fi, end)
|
||||
write(fi, nl)
|
||||
}
|
|
@ -10,18 +10,19 @@ datastore. Package bdb is licensed under the copyfree ISC license.
|
|||
## Usage
|
||||
|
||||
This package is only a driver to the walletdb package and provides the database
|
||||
type of "bdb". The only parameter the Open and Create functions take is the
|
||||
database path as a string:
|
||||
type of "bdb". The only parameters the Open and Create functions take is the
|
||||
database path as a string, and an option for the database to not sync its
|
||||
freelist to disk as a bool:
|
||||
|
||||
```Go
|
||||
db, err := walletdb.Open("bdb", "path/to/database.db")
|
||||
db, err := walletdb.Open("bdb", "path/to/database.db", true)
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
```
|
||||
|
||||
```Go
|
||||
db, err := walletdb.Create("bdb", "path/to/database.db")
|
||||
db, err := walletdb.Create("bdb", "path/to/database.db", true)
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
|
|
@ -339,7 +339,7 @@ func fileExists(name string) bool {
|
|||
|
||||
// openDB opens the database at the provided path. walletdb.ErrDbDoesNotExist
|
||||
// is returned if the database doesn't exist and the create flag is not set.
|
||||
func openDB(dbPath string, create bool) (walletdb.DB, error) {
|
||||
func openDB(dbPath string, noFreelistSync bool, create bool) (walletdb.DB, error) {
|
||||
if !create && !fileExists(dbPath) {
|
||||
return nil, walletdb.ErrDbDoesNotExist
|
||||
}
|
||||
|
@ -347,7 +347,7 @@ func openDB(dbPath string, create bool) (walletdb.DB, error) {
|
|||
// Specify bbolt freelist options to reduce heap pressure in case the
|
||||
// freelist grows to be very large.
|
||||
options := &bbolt.Options{
|
||||
NoFreelistSync: true,
|
||||
NoFreelistSync: noFreelistSync,
|
||||
FreelistType: bbolt.FreelistMapType,
|
||||
}
|
||||
|
||||
|
|
|
@ -9,15 +9,16 @@ datastore.
|
|||
Usage
|
||||
|
||||
This package is only a driver to the walletdb package and provides the database
|
||||
type of "bdb". The only parameter the Open and Create functions take is the
|
||||
database path as a string:
|
||||
type of "bdb". The only parameters the Open and Create functions take is the
|
||||
database path as a string, and an option for the database to not sync its
|
||||
freelist to disk as a bool:
|
||||
|
||||
db, err := walletdb.Open("bdb", "path/to/database.db")
|
||||
db, err := walletdb.Open("bdb", "path/to/database.db", true)
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
db, err := walletdb.Create("bdb", "path/to/database.db")
|
||||
db, err := walletdb.Create("bdb", "path/to/database.db", true)
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
|
|
@ -15,41 +15,50 @@ const (
|
|||
)
|
||||
|
||||
// parseArgs parses the arguments from the walletdb Open/Create methods.
|
||||
func parseArgs(funcName string, args ...interface{}) (string, error) {
|
||||
if len(args) != 1 {
|
||||
return "", fmt.Errorf("invalid arguments to %s.%s -- "+
|
||||
"expected database path", dbType, funcName)
|
||||
func parseArgs(funcName string, args ...interface{}) (string, bool, error) {
|
||||
if len(args) != 2 {
|
||||
return "", false, fmt.Errorf("invalid arguments to %s.%s -- "+
|
||||
"expected database path and no-freelist-sync option",
|
||||
dbType, funcName)
|
||||
}
|
||||
|
||||
dbPath, ok := args[0].(string)
|
||||
if !ok {
|
||||
return "", fmt.Errorf("first argument to %s.%s is invalid -- "+
|
||||
"expected database path string", dbType, funcName)
|
||||
return "", false, fmt.Errorf("first argument to %s.%s is "+
|
||||
"invalid -- expected database path string", dbType,
|
||||
funcName)
|
||||
}
|
||||
|
||||
return dbPath, nil
|
||||
noFreelistSync, ok := args[1].(bool)
|
||||
if !ok {
|
||||
return "", false, fmt.Errorf("second argument to %s.%s is "+
|
||||
"invalid -- expected no-freelist-sync bool", dbType,
|
||||
funcName)
|
||||
}
|
||||
|
||||
return dbPath, noFreelistSync, nil
|
||||
}
|
||||
|
||||
// openDBDriver is the callback provided during driver registration that opens
|
||||
// an existing database for use.
|
||||
func openDBDriver(args ...interface{}) (walletdb.DB, error) {
|
||||
dbPath, err := parseArgs("Open", args...)
|
||||
dbPath, noFreelistSync, err := parseArgs("Open", args...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return openDB(dbPath, false)
|
||||
return openDB(dbPath, noFreelistSync, false)
|
||||
}
|
||||
|
||||
// createDBDriver is the callback provided during driver registration that
|
||||
// creates, initializes, and opens a database for use.
|
||||
func createDBDriver(args ...interface{}) (walletdb.DB, error) {
|
||||
dbPath, err := parseArgs("Create", args...)
|
||||
dbPath, noFreelistSync, err := parseArgs("Create", args...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return openDB(dbPath, true)
|
||||
return openDB(dbPath, noFreelistSync, true)
|
||||
}
|
||||
|
||||
func init() {
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package lnwire
|
||||
|
||||
import "io"
|
||||
import (
|
||||
"io"
|
||||
)
|
||||
|
||||
// CommitSig is sent by either side to stage any pending HTLC's in the
|
||||
// receiver's pending set into a new commitment state. Implicitly, the new
|
||||
|
@ -83,3 +85,11 @@ func (c *CommitSig) MaxPayloadLength(uint32) uint32 {
|
|||
// 32 + 64 + 2 + max_allowed_htlcs
|
||||
return MaxMessagePayload
|
||||
}
|
||||
|
||||
// TargetChanID returns the channel id of the link for which this message is
|
||||
// intended.
|
||||
//
|
||||
// NOTE: Part of lnd.LinkUpdater interface.
|
||||
func (c *CommitSig) TargetChanID() ChannelID {
|
||||
return c.ChanID
|
||||
}
|
||||
|
|
|
@ -1,41 +1,32 @@
|
|||
package lnwire
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"google.golang.org/grpc/codes"
|
||||
)
|
||||
|
||||
// ErrorCode represents the short error code for each of the defined errors
|
||||
// within the Lightning Network protocol spec.
|
||||
type ErrorCode uint8
|
||||
|
||||
// ToGrpcCode is used to generate gRPC specific code which will be propagated
|
||||
// to the ln rpc client. This code is used to have more detailed view of what
|
||||
// goes wrong and also in order to have the ability pragmatically determine the
|
||||
// error and take specific actions on the client side.
|
||||
func (e ErrorCode) ToGrpcCode() codes.Code {
|
||||
return (codes.Code)(e) + 100
|
||||
}
|
||||
// FundingError represents a set of errors that can be encountered and sent
|
||||
// during the funding workflow.
|
||||
type FundingError uint8
|
||||
|
||||
const (
|
||||
// ErrMaxPendingChannels is returned by remote peer when the number of
|
||||
// active pending channels exceeds their maximum policy limit.
|
||||
ErrMaxPendingChannels ErrorCode = 1
|
||||
ErrMaxPendingChannels FundingError = 1
|
||||
|
||||
// ErrSynchronizingChain is returned by a remote peer that receives a
|
||||
// channel update or a funding request while their still syncing to the
|
||||
// latest state of the blockchain.
|
||||
ErrSynchronizingChain ErrorCode = 2
|
||||
ErrSynchronizingChain FundingError = 2
|
||||
|
||||
// ErrChanTooLarge is returned by a remote peer that receives a
|
||||
// FundingOpen request for a channel that is above their current
|
||||
// soft-limit.
|
||||
ErrChanTooLarge ErrorCode = 3
|
||||
ErrChanTooLarge FundingError = 3
|
||||
)
|
||||
|
||||
// String returns a human readable version of the target ErrorCode.
|
||||
func (e ErrorCode) String() string {
|
||||
// String returns a human readable version of the target FundingError.
|
||||
func (e FundingError) String() string {
|
||||
switch e {
|
||||
case ErrMaxPendingChannels:
|
||||
return "Number of pending channels exceed maximum"
|
||||
|
@ -48,10 +39,10 @@ func (e ErrorCode) String() string {
|
|||
}
|
||||
}
|
||||
|
||||
// Error returns the human redable version of the target ErrorCode.
|
||||
// Error returns the human redable version of the target FundingError.
|
||||
//
|
||||
// Satisfies the Error interface.
|
||||
func (e ErrorCode) Error() string {
|
||||
// NOTE: Satisfies the Error interface.
|
||||
func (e FundingError) Error() string {
|
||||
return e.String()
|
||||
}
|
||||
|
||||
|
@ -65,8 +56,6 @@ type ErrorData []byte
|
|||
// format is purposefully general in order to allow expression of a wide array
|
||||
// of possible errors. Each Error message is directed at a particular open
|
||||
// channel referenced by ChannelPoint.
|
||||
//
|
||||
// TODO(roasbeef): remove the error code
|
||||
type Error struct {
|
||||
// ChanID references the active channel in which the error occurred
|
||||
// within. If the ChanID is all zeros, then this error applies to the
|
||||
|
@ -87,6 +76,18 @@ func NewError() *Error {
|
|||
// interface.
|
||||
var _ Message = (*Error)(nil)
|
||||
|
||||
// Error returns the string representation to Error.
|
||||
//
|
||||
// NOTE: Satisfies the error interface.
|
||||
func (c *Error) Error() string {
|
||||
errMsg := "non-ascii data"
|
||||
if isASCII(c.Data) {
|
||||
errMsg = string(c.Data)
|
||||
}
|
||||
|
||||
return fmt.Sprintf("chan_id=%v, err=%v", c.ChanID, errMsg)
|
||||
}
|
||||
|
||||
// Decode deserializes a serialized Error message stored in the passed
|
||||
// io.Reader observing the specified protocol version.
|
||||
//
|
||||
|
@ -125,3 +126,14 @@ func (c *Error) MaxPayloadLength(uint32) uint32 {
|
|||
// 32 + 2 + 65501
|
||||
return 65535
|
||||
}
|
||||
|
||||
// isASCII is a helper method that checks whether all bytes in `data` would be
|
||||
// printable ASCII characters if interpreted as a string.
|
||||
func isASCII(data []byte) bool {
|
||||
for _, c := range data {
|
||||
if c < 32 || c > 126 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
|
|
@ -46,6 +46,25 @@ const (
|
|||
// efficient network view reconciliation.
|
||||
GossipQueriesOptional FeatureBit = 7
|
||||
|
||||
// TLVOnionPayloadRequired is a feature bit that indicates a node is
|
||||
// able to decode the new TLV information included in the onion packet.
|
||||
TLVOnionPayloadRequired FeatureBit = 8
|
||||
|
||||
// TLVOnionPayloadRequired is an optional feature bit that indicates a
|
||||
// node is able to decode the new TLV information included in the onion
|
||||
// packet.
|
||||
TLVOnionPayloadOptional FeatureBit = 9
|
||||
|
||||
// StaticRemoteKeyRequired is a required feature bit that signals that
|
||||
// within one's commitment transaction, the key used for the remote
|
||||
// party's non-delay output should not be tweaked.
|
||||
StaticRemoteKeyRequired FeatureBit = 12
|
||||
|
||||
// StaticRemoteKeyOptional is an optional feature bit that signals that
|
||||
// within one's commitment transaction, the key used for the remote
|
||||
// party's non-delay output should not be tweaked.
|
||||
StaticRemoteKeyOptional FeatureBit = 13
|
||||
|
||||
// maxAllowedSize is a maximum allowed size of feature vector.
|
||||
//
|
||||
// NOTE: Within the protocol, the maximum allowed message size is 65535
|
||||
|
@ -76,7 +95,12 @@ var LocalFeatures = map[FeatureBit]string{
|
|||
// name. All known global feature bits must be assigned a name in this mapping.
|
||||
// Global features are those which are advertised to the entire network. A full
|
||||
// description of these feature bits is provided in the BOLT-09 specification.
|
||||
var GlobalFeatures map[FeatureBit]string
|
||||
var GlobalFeatures = map[FeatureBit]string{
|
||||
TLVOnionPayloadRequired: "tlv-onion",
|
||||
TLVOnionPayloadOptional: "tlv-onion",
|
||||
StaticRemoteKeyOptional: "static-remote-key",
|
||||
StaticRemoteKeyRequired: "static-remote-key",
|
||||
}
|
||||
|
||||
// RawFeatureVector represents a set of feature bits as defined in BOLT-09. A
|
||||
// RawFeatureVector itself just stores a set of bit flags but can be used to
|
||||
|
@ -115,6 +139,20 @@ func (fv *RawFeatureVector) Unset(feature FeatureBit) {
|
|||
// SerializeSize returns the number of bytes needed to represent feature vector
|
||||
// in byte format.
|
||||
func (fv *RawFeatureVector) SerializeSize() int {
|
||||
// We calculate byte-length via the largest bit index.
|
||||
return fv.serializeSize(8)
|
||||
}
|
||||
|
||||
// SerializeSize32 returns the number of bytes needed to represent feature
|
||||
// vector in base32 format.
|
||||
func (fv *RawFeatureVector) SerializeSize32() int {
|
||||
// We calculate base32-length via the largest bit index.
|
||||
return fv.serializeSize(5)
|
||||
}
|
||||
|
||||
// serializeSize returns the number of bytes required to encode the feature
|
||||
// vector using at most width bits per encoded byte.
|
||||
func (fv *RawFeatureVector) serializeSize(width int) int {
|
||||
// Find the largest feature bit index
|
||||
max := -1
|
||||
for feature := range fv.features {
|
||||
|
@ -127,8 +165,7 @@ func (fv *RawFeatureVector) SerializeSize() int {
|
|||
return 0
|
||||
}
|
||||
|
||||
// We calculate byte-length via the largest bit index
|
||||
return max/8 + 1
|
||||
return max/width + 1
|
||||
}
|
||||
|
||||
// Encode writes the feature vector in byte representation. Every feature
|
||||
|
@ -144,12 +181,25 @@ func (fv *RawFeatureVector) Encode(w io.Writer) error {
|
|||
return err
|
||||
}
|
||||
|
||||
return fv.encode(w, length, 8)
|
||||
}
|
||||
|
||||
// EncodeBase32 writes the feature vector in base32 representation. Every feature
|
||||
// encoded as a bit, and the bit vector is serialized using the least number of
|
||||
// bytes.
|
||||
func (fv *RawFeatureVector) EncodeBase32(w io.Writer) error {
|
||||
length := fv.SerializeSize32()
|
||||
return fv.encode(w, length, 5)
|
||||
}
|
||||
|
||||
// encode writes the feature vector
|
||||
func (fv *RawFeatureVector) encode(w io.Writer, length, width int) error {
|
||||
// Generate the data and write it.
|
||||
data := make([]byte, length)
|
||||
for feature := range fv.features {
|
||||
byteIndex := int(feature / 8)
|
||||
bitIndex := feature % 8
|
||||
data[length-byteIndex-1] |= 1 << bitIndex
|
||||
byteIndex := int(feature) / width
|
||||
bitIndex := int(feature) % width
|
||||
data[length-byteIndex-1] |= 1 << uint(bitIndex)
|
||||
}
|
||||
|
||||
_, err := w.Write(data)
|
||||
|
@ -168,6 +218,19 @@ func (fv *RawFeatureVector) Decode(r io.Reader) error {
|
|||
}
|
||||
length := binary.BigEndian.Uint16(l[:])
|
||||
|
||||
return fv.decode(r, int(length), 8)
|
||||
}
|
||||
|
||||
// DecodeBase32 reads the feature vector from its base32 representation. Every
|
||||
// feature encoded as a bit, and the bit vector is serialized using the least
|
||||
// number of bytes.
|
||||
func (fv *RawFeatureVector) DecodeBase32(r io.Reader, length int) error {
|
||||
return fv.decode(r, length, 5)
|
||||
}
|
||||
|
||||
// decode reads a feature vector from the next length bytes of the io.Reader,
|
||||
// assuming each byte has width feature bits encoded per byte.
|
||||
func (fv *RawFeatureVector) decode(r io.Reader, length, width int) error {
|
||||
// Read the feature vector data.
|
||||
data := make([]byte, length)
|
||||
if _, err := io.ReadFull(r, data); err != nil {
|
||||
|
@ -175,10 +238,10 @@ func (fv *RawFeatureVector) Decode(r io.Reader) error {
|
|||
}
|
||||
|
||||
// Set feature bits from parsed data.
|
||||
bitsNumber := len(data) * 8
|
||||
bitsNumber := len(data) * width
|
||||
for i := 0; i < bitsNumber; i++ {
|
||||
byteIndex := uint16(i / 8)
|
||||
bitIndex := uint(i % 8)
|
||||
byteIndex := int(i / width)
|
||||
bitIndex := uint(i % width)
|
||||
if (data[length-byteIndex-1]>>bitIndex)&1 == 1 {
|
||||
fv.Set(FeatureBit(i))
|
||||
}
|
||||
|
|
|
@ -117,12 +117,6 @@ func WriteElement(w io.Writer, element interface{}) error {
|
|||
if _, err := w.Write(b[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
case ErrorCode:
|
||||
var b [2]byte
|
||||
binary.BigEndian.PutUint16(b[:], uint16(e))
|
||||
if _, err := w.Write(b[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
case MilliSatoshi:
|
||||
var b [8]byte
|
||||
binary.BigEndian.PutUint64(b[:], uint64(e))
|
||||
|
@ -506,12 +500,6 @@ func ReadElement(r io.Reader, element interface{}) error {
|
|||
return err
|
||||
}
|
||||
*e = ChanUpdateChanFlags(b[0])
|
||||
case *ErrorCode:
|
||||
var b [2]byte
|
||||
if _, err := io.ReadFull(r, b[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
*e = ErrorCode(binary.BigEndian.Uint16(b[:]))
|
||||
case *uint32:
|
||||
var b [4]byte
|
||||
if _, err := io.ReadFull(r, b[:]); err != nil {
|
||||
|
|
|
@ -10,11 +10,6 @@ import (
|
|||
"unicode/utf8"
|
||||
)
|
||||
|
||||
var (
|
||||
startPort uint16 = 1024
|
||||
endPort uint16 = 49151
|
||||
)
|
||||
|
||||
// ErrUnknownAddrType is an error returned if we encounter an unknown address type
|
||||
// when parsing addresses.
|
||||
type ErrUnknownAddrType struct {
|
||||
|
|
|
@ -46,7 +46,7 @@ const (
|
|||
FlagUpdate FailCode = 0x1000
|
||||
)
|
||||
|
||||
// FailCode specifies the precise reason that an upstream HTLC was cancelled.
|
||||
// FailCode specifies the precise reason that an upstream HTLC was canceled.
|
||||
// Each UpdateFailHTLC message carries a FailCode which is to be passed
|
||||
// backwards, encrypted at each step back to the source of the HTLC within the
|
||||
// route.
|
||||
|
@ -55,29 +55,29 @@ type FailCode uint16
|
|||
// The currently defined onion failure types within this current version of the
|
||||
// Lightning protocol.
|
||||
const (
|
||||
CodeNone FailCode = 0
|
||||
CodeInvalidRealm = FlagBadOnion | 1
|
||||
CodeTemporaryNodeFailure = FlagNode | 2
|
||||
CodePermanentNodeFailure = FlagPerm | FlagNode | 2
|
||||
CodeRequiredNodeFeatureMissing = FlagPerm | FlagNode | 3
|
||||
CodeInvalidOnionVersion = FlagBadOnion | FlagPerm | 4
|
||||
CodeInvalidOnionHmac = FlagBadOnion | FlagPerm | 5
|
||||
CodeInvalidOnionKey = FlagBadOnion | FlagPerm | 6
|
||||
CodeTemporaryChannelFailure = FlagUpdate | 7
|
||||
CodePermanentChannelFailure = FlagPerm | 8
|
||||
CodeRequiredChannelFeatureMissing = FlagPerm | 9
|
||||
CodeUnknownNextPeer = FlagPerm | 10
|
||||
CodeAmountBelowMinimum = FlagUpdate | 11
|
||||
CodeFeeInsufficient = FlagUpdate | 12
|
||||
CodeIncorrectCltvExpiry = FlagUpdate | 13
|
||||
CodeExpiryTooSoon = FlagUpdate | 14
|
||||
CodeChannelDisabled = FlagUpdate | 20
|
||||
CodeUnknownPaymentHash = FlagPerm | 15
|
||||
CodeIncorrectPaymentAmount = FlagPerm | 16
|
||||
CodeFinalExpiryTooSoon FailCode = 17
|
||||
CodeFinalIncorrectCltvExpiry FailCode = 18
|
||||
CodeFinalIncorrectHtlcAmount FailCode = 19
|
||||
CodeExpiryTooFar FailCode = 21
|
||||
CodeNone FailCode = 0
|
||||
CodeInvalidRealm = FlagBadOnion | 1
|
||||
CodeTemporaryNodeFailure = FlagNode | 2
|
||||
CodePermanentNodeFailure = FlagPerm | FlagNode | 2
|
||||
CodeRequiredNodeFeatureMissing = FlagPerm | FlagNode | 3
|
||||
CodeInvalidOnionVersion = FlagBadOnion | FlagPerm | 4
|
||||
CodeInvalidOnionHmac = FlagBadOnion | FlagPerm | 5
|
||||
CodeInvalidOnionKey = FlagBadOnion | FlagPerm | 6
|
||||
CodeTemporaryChannelFailure = FlagUpdate | 7
|
||||
CodePermanentChannelFailure = FlagPerm | 8
|
||||
CodeRequiredChannelFeatureMissing = FlagPerm | 9
|
||||
CodeUnknownNextPeer = FlagPerm | 10
|
||||
CodeAmountBelowMinimum = FlagUpdate | 11
|
||||
CodeFeeInsufficient = FlagUpdate | 12
|
||||
CodeIncorrectCltvExpiry = FlagUpdate | 13
|
||||
CodeExpiryTooSoon = FlagUpdate | 14
|
||||
CodeChannelDisabled = FlagUpdate | 20
|
||||
CodeIncorrectOrUnknownPaymentDetails = FlagPerm | 15
|
||||
CodeIncorrectPaymentAmount = FlagPerm | 16
|
||||
CodeFinalExpiryTooSoon FailCode = 17
|
||||
CodeFinalIncorrectCltvExpiry FailCode = 18
|
||||
CodeFinalIncorrectHtlcAmount FailCode = 19
|
||||
CodeExpiryTooFar FailCode = 21
|
||||
)
|
||||
|
||||
// String returns the string representation of the failure code.
|
||||
|
@ -134,8 +134,8 @@ func (c FailCode) String() string {
|
|||
case CodeChannelDisabled:
|
||||
return "ChannelDisabled"
|
||||
|
||||
case CodeUnknownPaymentHash:
|
||||
return "UnknownPaymentHash"
|
||||
case CodeIncorrectOrUnknownPaymentDetails:
|
||||
return "IncorrectOrUnknownPaymentDetails"
|
||||
|
||||
case CodeFinalExpiryTooSoon:
|
||||
return "FinalExpiryTooSoon"
|
||||
|
@ -317,7 +317,7 @@ func (f *FailIncorrectPaymentAmount) Error() string {
|
|||
return f.Code().String()
|
||||
}
|
||||
|
||||
// FailUnknownPaymentHash is returned for two reasons:
|
||||
// FailIncorrectDetails is returned for two reasons:
|
||||
//
|
||||
// 1) if the payment hash has already been paid, the final node MAY treat the
|
||||
// payment hash as unknown, or may succeed in accepting the HTLC. If the
|
||||
|
@ -330,42 +330,56 @@ func (f *FailIncorrectPaymentAmount) Error() string {
|
|||
// gross overpayment.
|
||||
//
|
||||
// NOTE: May only be returned by the final node in the path.
|
||||
type FailUnknownPaymentHash struct {
|
||||
type FailIncorrectDetails struct {
|
||||
// amount is the value of the extended HTLC.
|
||||
amount MilliSatoshi
|
||||
|
||||
// height is the block height when the htlc was received.
|
||||
height uint32
|
||||
}
|
||||
|
||||
// NewFailUnknownPaymentHash makes a new instance of the FailUnknownPaymentHash
|
||||
// error bound to the specified HTLC amount.
|
||||
func NewFailUnknownPaymentHash(amt MilliSatoshi) *FailUnknownPaymentHash {
|
||||
return &FailUnknownPaymentHash{
|
||||
// NewFailIncorrectDetails makes a new instance of the FailIncorrectDetails
|
||||
// error bound to the specified HTLC amount and acceptance height.
|
||||
func NewFailIncorrectDetails(amt MilliSatoshi,
|
||||
height uint32) *FailIncorrectDetails {
|
||||
|
||||
return &FailIncorrectDetails{
|
||||
amount: amt,
|
||||
height: height,
|
||||
}
|
||||
}
|
||||
|
||||
// Amount is the value of the extended HTLC.
|
||||
func (f *FailUnknownPaymentHash) Amount() MilliSatoshi {
|
||||
func (f *FailIncorrectDetails) Amount() MilliSatoshi {
|
||||
return f.amount
|
||||
}
|
||||
|
||||
// Height is the block height when the htlc was received.
|
||||
func (f *FailIncorrectDetails) Height() uint32 {
|
||||
return f.height
|
||||
}
|
||||
|
||||
// Code returns the failure unique code.
|
||||
//
|
||||
// NOTE: Part of the FailureMessage interface.
|
||||
func (f *FailUnknownPaymentHash) Code() FailCode {
|
||||
return CodeUnknownPaymentHash
|
||||
func (f *FailIncorrectDetails) Code() FailCode {
|
||||
return CodeIncorrectOrUnknownPaymentDetails
|
||||
}
|
||||
|
||||
// Returns a human readable string describing the target FailureMessage.
|
||||
//
|
||||
// NOTE: Implements the error interface.
|
||||
func (f *FailUnknownPaymentHash) Error() string {
|
||||
return fmt.Sprintf("UnknownPaymentHash(amt=%v)", f.amount)
|
||||
func (f *FailIncorrectDetails) Error() string {
|
||||
return fmt.Sprintf(
|
||||
"%v(amt=%v, height=%v)", CodeIncorrectOrUnknownPaymentDetails,
|
||||
f.amount, f.height,
|
||||
)
|
||||
}
|
||||
|
||||
// Decode decodes the failure from bytes stream.
|
||||
//
|
||||
// NOTE: Part of the Serializable interface.
|
||||
func (f *FailUnknownPaymentHash) Decode(r io.Reader, pver uint32) error {
|
||||
func (f *FailIncorrectDetails) Decode(r io.Reader, pver uint32) error {
|
||||
err := ReadElement(r, &f.amount)
|
||||
switch {
|
||||
// This is an optional tack on that was added later in the protocol. As
|
||||
|
@ -379,14 +393,25 @@ func (f *FailUnknownPaymentHash) Decode(r io.Reader, pver uint32) error {
|
|||
return err
|
||||
}
|
||||
|
||||
// At a later stage, the height field was also tacked on. We need to
|
||||
// check for io.EOF here as well.
|
||||
err = ReadElement(r, &f.height)
|
||||
switch {
|
||||
case err == io.EOF:
|
||||
return nil
|
||||
|
||||
case err != nil:
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Encode writes the failure in bytes stream.
|
||||
//
|
||||
// NOTE: Part of the Serializable interface.
|
||||
func (f *FailUnknownPaymentHash) Encode(w io.Writer, pver uint32) error {
|
||||
return WriteElement(w, f.amount)
|
||||
func (f *FailIncorrectDetails) Encode(w io.Writer, pver uint32) error {
|
||||
return WriteElements(w, f.amount, f.height)
|
||||
}
|
||||
|
||||
// FailFinalExpiryTooSoon is returned if the cltv_expiry is too low, the final
|
||||
|
@ -1113,10 +1138,16 @@ func DecodeFailure(r io.Reader, pver uint32) (FailureMessage, error) {
|
|||
|
||||
dataReader := bytes.NewReader(failureData)
|
||||
|
||||
return DecodeFailureMessage(dataReader, pver)
|
||||
}
|
||||
|
||||
// DecodeFailureMessage decodes just the failure message, ignoring any padding
|
||||
// that may be present at the end.
|
||||
func DecodeFailureMessage(r io.Reader, pver uint32) (FailureMessage, error) {
|
||||
// Once we have the failure data, we can obtain the failure code from
|
||||
// the first two bytes of the buffer.
|
||||
var codeBytes [2]byte
|
||||
if _, err := io.ReadFull(dataReader, codeBytes[:]); err != nil {
|
||||
if _, err := io.ReadFull(r, codeBytes[:]); err != nil {
|
||||
return nil, fmt.Errorf("unable to read failure code: %v", err)
|
||||
}
|
||||
failCode := FailCode(binary.BigEndian.Uint16(codeBytes[:]))
|
||||
|
@ -1132,10 +1163,9 @@ func DecodeFailure(r io.Reader, pver uint32) (FailureMessage, error) {
|
|||
// well.
|
||||
switch f := failure.(type) {
|
||||
case Serializable:
|
||||
if err := f.Decode(dataReader, pver); err != nil {
|
||||
if err := f.Decode(r, pver); err != nil {
|
||||
return nil, fmt.Errorf("unable to decode error "+
|
||||
"update (type=%T, len_bytes=%v, bytes=%x): %v",
|
||||
failure, failureLength, failureData[:], err)
|
||||
"update (type=%T): %v", failure, err)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1147,26 +1177,11 @@ func DecodeFailure(r io.Reader, pver uint32) (FailureMessage, error) {
|
|||
func EncodeFailure(w io.Writer, failure FailureMessage, pver uint32) error {
|
||||
var failureMessageBuffer bytes.Buffer
|
||||
|
||||
// First, we'll write out the error code itself into the failure
|
||||
// buffer.
|
||||
var codeBytes [2]byte
|
||||
code := uint16(failure.Code())
|
||||
binary.BigEndian.PutUint16(codeBytes[:], code)
|
||||
_, err := failureMessageBuffer.Write(codeBytes[:])
|
||||
err := EncodeFailureMessage(&failureMessageBuffer, failure, pver)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Next, some message have an additional message payload, if this is
|
||||
// one of those types, then we'll also encode the error payload as
|
||||
// well.
|
||||
switch failure := failure.(type) {
|
||||
case Serializable:
|
||||
if err := failure.Encode(&failureMessageBuffer, pver); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// The combined size of this message must be below the max allowed
|
||||
// failure message length.
|
||||
failureMessage := failureMessageBuffer.Bytes()
|
||||
|
@ -1187,6 +1202,32 @@ func EncodeFailure(w io.Writer, failure FailureMessage, pver uint32) error {
|
|||
)
|
||||
}
|
||||
|
||||
// EncodeFailureMessage encodes just the failure message without adding a length
|
||||
// and padding the message for the onion protocol.
|
||||
func EncodeFailureMessage(w io.Writer, failure FailureMessage, pver uint32) error {
|
||||
// First, we'll write out the error code itself into the failure
|
||||
// buffer.
|
||||
var codeBytes [2]byte
|
||||
code := uint16(failure.Code())
|
||||
binary.BigEndian.PutUint16(codeBytes[:], code)
|
||||
_, err := w.Write(codeBytes[:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Next, some message have an additional message payload, if this is
|
||||
// one of those types, then we'll also encode the error payload as
|
||||
// well.
|
||||
switch failure := failure.(type) {
|
||||
case Serializable:
|
||||
if err := failure.Encode(w, pver); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// makeEmptyOnionError creates a new empty onion error of the proper concrete
|
||||
// type based on the passed failure code.
|
||||
func makeEmptyOnionError(code FailCode) (FailureMessage, error) {
|
||||
|
@ -1212,8 +1253,8 @@ func makeEmptyOnionError(code FailCode) (FailureMessage, error) {
|
|||
case CodeUnknownNextPeer:
|
||||
return &FailUnknownNextPeer{}, nil
|
||||
|
||||
case CodeUnknownPaymentHash:
|
||||
return &FailUnknownPaymentHash{}, nil
|
||||
case CodeIncorrectOrUnknownPaymentDetails:
|
||||
return &FailIncorrectDetails{}, nil
|
||||
|
||||
case CodeIncorrectPaymentAmount:
|
||||
return &FailIncorrectPaymentAmount{}, nil
|
||||
|
|
|
@ -81,3 +81,11 @@ func (c *RevokeAndAck) MaxPayloadLength(uint32) uint32 {
|
|||
// 32 + 32 + 33
|
||||
return 97
|
||||
}
|
||||
|
||||
// TargetChanID returns the channel id of the link for which this message is
|
||||
// intended.
|
||||
//
|
||||
// NOTE: Part of lnd.LinkUpdater interface.
|
||||
func (c *RevokeAndAck) TargetChanID() ChannelID {
|
||||
return c.ChanID
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package lnwire
|
||||
|
||||
import "io"
|
||||
import (
|
||||
"io"
|
||||
)
|
||||
|
||||
// OnionPacketSize is the size of the serialized Sphinx onion packet included
|
||||
// in each UpdateAddHTLC message. The breakdown of the onion packet is as
|
||||
|
@ -107,3 +109,11 @@ func (c *UpdateAddHTLC) MaxPayloadLength(uint32) uint32 {
|
|||
// 1450
|
||||
return 32 + 8 + 4 + 8 + 32 + 1366
|
||||
}
|
||||
|
||||
// TargetChanID returns the channel id of the link for which this message is
|
||||
// intended.
|
||||
//
|
||||
// NOTE: Part of lnd.LinkUpdater interface.
|
||||
func (c *UpdateAddHTLC) TargetChanID() ChannelID {
|
||||
return c.ChanID
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package lnwire
|
||||
|
||||
import "io"
|
||||
import (
|
||||
"io"
|
||||
)
|
||||
|
||||
// OpaqueReason is an opaque encrypted byte slice that encodes the exact
|
||||
// failure reason and additional some supplemental data. The contents of this
|
||||
|
@ -83,3 +85,11 @@ func (c *UpdateFailHTLC) MaxPayloadLength(uint32) uint32 {
|
|||
|
||||
return length
|
||||
}
|
||||
|
||||
// TargetChanID returns the channel id of the link for which this message is
|
||||
// intended.
|
||||
//
|
||||
// NOTE: Part of lnd.LinkUpdater interface.
|
||||
func (c *UpdateFailHTLC) TargetChanID() ChannelID {
|
||||
return c.ChanID
|
||||
}
|
||||
|
|
|
@ -73,3 +73,11 @@ func (c *UpdateFailMalformedHTLC) MaxPayloadLength(uint32) uint32 {
|
|||
// 32 + 8 + 32 + 2
|
||||
return 74
|
||||
}
|
||||
|
||||
// TargetChanID returns the channel id of the link for which this message is
|
||||
// intended.
|
||||
//
|
||||
// NOTE: Part of lnd.LinkUpdater interface.
|
||||
func (c *UpdateFailMalformedHTLC) TargetChanID() ChannelID {
|
||||
return c.ChanID
|
||||
}
|
||||
|
|
|
@ -68,3 +68,11 @@ func (c *UpdateFee) MaxPayloadLength(uint32) uint32 {
|
|||
// 32 + 4
|
||||
return 36
|
||||
}
|
||||
|
||||
// TargetChanID returns the channel id of the link for which this message is
|
||||
// intended.
|
||||
//
|
||||
// NOTE: Part of lnd.LinkUpdater interface.
|
||||
func (c *UpdateFee) TargetChanID() ChannelID {
|
||||
return c.ChanID
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package lnwire
|
||||
|
||||
import "io"
|
||||
import (
|
||||
"io"
|
||||
)
|
||||
|
||||
// UpdateFulfillHTLC is sent by Alice to Bob when she wishes to settle a
|
||||
// particular HTLC referenced by its HTLCKey within a specific active channel
|
||||
|
@ -76,3 +78,11 @@ func (c *UpdateFulfillHTLC) MaxPayloadLength(uint32) uint32 {
|
|||
// 32 + 8 + 32
|
||||
return 72
|
||||
}
|
||||
|
||||
// TargetChanID returns the channel id of the link for which this message is
|
||||
// intended.
|
||||
//
|
||||
// NOTE: Part of lnd.LinkUpdater interface.
|
||||
func (c *UpdateFulfillHTLC) TargetChanID() ChannelID {
|
||||
return c.ChanID
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package zpay32
|
|||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
@ -67,6 +68,24 @@ const (
|
|||
|
||||
// fieldTypeC contains an optional requested final CLTV delta.
|
||||
fieldTypeC = 24
|
||||
|
||||
// fieldType9 contains one or more bytes for signaling features
|
||||
// supported or required by the receiver.
|
||||
fieldType9 = 5
|
||||
|
||||
// maxInvoiceLength is the maximum total length an invoice can have.
|
||||
// This is chosen to be the maximum number of bytes that can fit into a
|
||||
// single QR code: https://en.wikipedia.org/wiki/QR_code#Storage
|
||||
maxInvoiceLength = 7089
|
||||
)
|
||||
|
||||
var (
|
||||
// InvoiceFeatures holds the set of all known feature bits that are
|
||||
// exposed as BOLT 11 features.
|
||||
InvoiceFeatures = map[lnwire.FeatureBit]string{}
|
||||
|
||||
// ErrInvoiceTooLarge is returned when an invoice exceeds maxInvoiceLength.
|
||||
ErrInvoiceTooLarge = errors.New("invoice is too large")
|
||||
)
|
||||
|
||||
// MessageSigner is passed to the Encode method to provide a signature
|
||||
|
@ -146,6 +165,10 @@ type Invoice struct {
|
|||
//
|
||||
// NOTE: This is optional.
|
||||
RouteHints [][]HopHint
|
||||
|
||||
// Features represents an optional field used to signal optional or
|
||||
// required support for features by the receiver.
|
||||
Features *lnwire.FeatureVector
|
||||
}
|
||||
|
||||
// Amount is a functional option that allows callers of NewInvoice to set the
|
||||
|
@ -249,6 +272,12 @@ func NewInvoice(net *chaincfg.Params, paymentHash [32]byte,
|
|||
func Decode(invoice string, net *chaincfg.Params) (*Invoice, error) {
|
||||
decodedInvoice := Invoice{}
|
||||
|
||||
// Before bech32 decoding the invoice, make sure that it is not too large.
|
||||
// This is done as an anti-DoS measure since bech32 decoding is expensive.
|
||||
if len(invoice) > maxInvoiceLength {
|
||||
return nil, ErrInvoiceTooLarge
|
||||
}
|
||||
|
||||
// Decode the invoice using the modified bech32 decoder.
|
||||
hrp, data, err := decodeBech32(invoice)
|
||||
if err != nil {
|
||||
|
@ -453,6 +482,12 @@ func (invoice *Invoice) Encode(signer MessageSigner) (string, error) {
|
|||
return "", err
|
||||
}
|
||||
|
||||
// Before returning, check that the bech32 encoded string is not greater
|
||||
// than our largest supported invoice size.
|
||||
if len(b32) > maxInvoiceLength {
|
||||
return "", ErrInvoiceTooLarge
|
||||
}
|
||||
|
||||
return b32, nil
|
||||
}
|
||||
|
||||
|
@ -504,21 +539,6 @@ func validateInvoice(invoice *Invoice) error {
|
|||
return fmt.Errorf("neither description nor description hash set")
|
||||
}
|
||||
|
||||
// We'll restrict invoices to include up to 20 different private route
|
||||
// hints. We do this to avoid overly large invoices.
|
||||
if len(invoice.RouteHints) > 20 {
|
||||
return fmt.Errorf("too many private routes: %d",
|
||||
len(invoice.RouteHints))
|
||||
}
|
||||
|
||||
// Each route hint can have at most 20 hops.
|
||||
for i, routeHint := range invoice.RouteHints {
|
||||
if len(routeHint) > 20 {
|
||||
return fmt.Errorf("route hint %d has too many extra "+
|
||||
"hops: %d", i, len(routeHint))
|
||||
}
|
||||
}
|
||||
|
||||
// Check that we support the field lengths.
|
||||
if len(invoice.PaymentHash) != 32 {
|
||||
return fmt.Errorf("unsupported payment hash length: %d",
|
||||
|
@ -663,6 +683,14 @@ func parseTaggedFields(invoice *Invoice, fields []byte, net *chaincfg.Params) er
|
|||
}
|
||||
|
||||
invoice.RouteHints = append(invoice.RouteHints, routeHint)
|
||||
case fieldType9:
|
||||
if invoice.Features != nil {
|
||||
// We skip the field if we have already seen a
|
||||
// supported one.
|
||||
continue
|
||||
}
|
||||
|
||||
invoice.Features, err = parseFeatures(base32Data)
|
||||
default:
|
||||
// Ignore unknown type.
|
||||
}
|
||||
|
@ -848,6 +876,7 @@ func parseRouteHint(data []byte) ([]HopHint, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
// Check that base256Data is a multiple of hopHintLen.
|
||||
if len(base256Data)%hopHintLen != 0 {
|
||||
return nil, fmt.Errorf("expected length multiple of %d bytes, "+
|
||||
"got %d", hopHintLen, len(base256Data))
|
||||
|
@ -874,6 +903,25 @@ func parseRouteHint(data []byte) ([]HopHint, error) {
|
|||
return routeHint, nil
|
||||
}
|
||||
|
||||
// parseFeatures decodes any feature bits directly from the base32
|
||||
// representation.
|
||||
func parseFeatures(data []byte) (*lnwire.FeatureVector, error) {
|
||||
rawFeatures := lnwire.NewRawFeatureVector()
|
||||
err := rawFeatures.DecodeBase32(bytes.NewReader(data), len(data))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
fv := lnwire.NewFeatureVector(rawFeatures, InvoiceFeatures)
|
||||
unknownFeatures := fv.UnknownRequiredFeatures()
|
||||
if len(unknownFeatures) > 0 {
|
||||
return nil, fmt.Errorf("invoice contains unknown required "+
|
||||
"features: %v", unknownFeatures)
|
||||
}
|
||||
|
||||
return fv, nil
|
||||
}
|
||||
|
||||
// writeTaggedFields writes the non-nil tagged fields of the Invoice to the
|
||||
// base32 buffer.
|
||||
func writeTaggedFields(bufferBase32 *bytes.Buffer, invoice *Invoice) error {
|
||||
|
@ -1011,7 +1059,7 @@ func writeTaggedFields(bufferBase32 *bytes.Buffer, invoice *Invoice) error {
|
|||
pubKeyBase32, err := bech32.ConvertBits(
|
||||
invoice.Destination.SerializeCompressed(), 8, 5, true)
|
||||
if err != nil {
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
if len(pubKeyBase32) != pubKeyBase32Len {
|
||||
|
@ -1024,6 +1072,18 @@ func writeTaggedFields(bufferBase32 *bytes.Buffer, invoice *Invoice) error {
|
|||
return err
|
||||
}
|
||||
}
|
||||
if invoice.Features != nil && invoice.Features.SerializeSize32() > 0 {
|
||||
var b bytes.Buffer
|
||||
err := invoice.Features.RawFeatureVector.EncodeBase32(&b)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = writeTaggedField(bufferBase32, fieldType9, b.Bytes())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -1,189 +0,0 @@
|
|||
//+build ignore
|
||||
|
||||
// compression_generate.go is meant to run with go generate. It will use
|
||||
// go/{importer,types} to track down all the RR struct types. Then for each type
|
||||
// it will look to see if there are (compressible) names, if so it will add that
|
||||
// type to compressionLenHelperType and comressionLenSearchType which "fake" the
|
||||
// compression so that Len() is fast.
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"go/format"
|
||||
"go/importer"
|
||||
"go/types"
|
||||
"log"
|
||||
"os"
|
||||
)
|
||||
|
||||
var packageHdr = `
|
||||
// *** DO NOT MODIFY ***
|
||||
// AUTOGENERATED BY go generate from compress_generate.go
|
||||
|
||||
package dns
|
||||
|
||||
`
|
||||
|
||||
// getTypeStruct will take a type and the package scope, and return the
|
||||
// (innermost) struct if the type is considered a RR type (currently defined as
|
||||
// those structs beginning with a RR_Header, could be redefined as implementing
|
||||
// the RR interface). The bool return value indicates if embedded structs were
|
||||
// resolved.
|
||||
func getTypeStruct(t types.Type, scope *types.Scope) (*types.Struct, bool) {
|
||||
st, ok := t.Underlying().(*types.Struct)
|
||||
if !ok {
|
||||
return nil, false
|
||||
}
|
||||
if st.Field(0).Type() == scope.Lookup("RR_Header").Type() {
|
||||
return st, false
|
||||
}
|
||||
if st.Field(0).Anonymous() {
|
||||
st, _ := getTypeStruct(st.Field(0).Type(), scope)
|
||||
return st, true
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Import and type-check the package
|
||||
pkg, err := importer.Default().Import("github.com/miekg/dns")
|
||||
fatalIfErr(err)
|
||||
scope := pkg.Scope()
|
||||
|
||||
var domainTypes []string // Types that have a domain name in them (either compressible or not).
|
||||
var cdomainTypes []string // Types that have a compressible domain name in them (subset of domainType)
|
||||
Names:
|
||||
for _, name := range scope.Names() {
|
||||
o := scope.Lookup(name)
|
||||
if o == nil || !o.Exported() {
|
||||
continue
|
||||
}
|
||||
st, _ := getTypeStruct(o.Type(), scope)
|
||||
if st == nil {
|
||||
continue
|
||||
}
|
||||
if name == "PrivateRR" {
|
||||
continue
|
||||
}
|
||||
|
||||
if scope.Lookup("Type"+o.Name()) == nil && o.Name() != "RFC3597" {
|
||||
log.Fatalf("Constant Type%s does not exist.", o.Name())
|
||||
}
|
||||
|
||||
for i := 1; i < st.NumFields(); i++ {
|
||||
if _, ok := st.Field(i).Type().(*types.Slice); ok {
|
||||
if st.Tag(i) == `dns:"domain-name"` {
|
||||
domainTypes = append(domainTypes, o.Name())
|
||||
continue Names
|
||||
}
|
||||
if st.Tag(i) == `dns:"cdomain-name"` {
|
||||
cdomainTypes = append(cdomainTypes, o.Name())
|
||||
domainTypes = append(domainTypes, o.Name())
|
||||
continue Names
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
switch {
|
||||
case st.Tag(i) == `dns:"domain-name"`:
|
||||
domainTypes = append(domainTypes, o.Name())
|
||||
continue Names
|
||||
case st.Tag(i) == `dns:"cdomain-name"`:
|
||||
cdomainTypes = append(cdomainTypes, o.Name())
|
||||
domainTypes = append(domainTypes, o.Name())
|
||||
continue Names
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
b := &bytes.Buffer{}
|
||||
b.WriteString(packageHdr)
|
||||
|
||||
// compressionLenHelperType - all types that have domain-name/cdomain-name can be used for compressing names
|
||||
|
||||
fmt.Fprint(b, "func compressionLenHelperType(c map[string]int, r RR) {\n")
|
||||
fmt.Fprint(b, "switch x := r.(type) {\n")
|
||||
for _, name := range domainTypes {
|
||||
o := scope.Lookup(name)
|
||||
st, _ := getTypeStruct(o.Type(), scope)
|
||||
|
||||
fmt.Fprintf(b, "case *%s:\n", name)
|
||||
for i := 1; i < st.NumFields(); i++ {
|
||||
out := func(s string) { fmt.Fprintf(b, "compressionLenHelper(c, x.%s)\n", st.Field(i).Name()) }
|
||||
|
||||
if _, ok := st.Field(i).Type().(*types.Slice); ok {
|
||||
switch st.Tag(i) {
|
||||
case `dns:"domain-name"`:
|
||||
fallthrough
|
||||
case `dns:"cdomain-name"`:
|
||||
// For HIP we need to slice over the elements in this slice.
|
||||
fmt.Fprintf(b, `for i := range x.%s {
|
||||
compressionLenHelper(c, x.%s[i])
|
||||
}
|
||||
`, st.Field(i).Name(), st.Field(i).Name())
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
switch {
|
||||
case st.Tag(i) == `dns:"cdomain-name"`:
|
||||
fallthrough
|
||||
case st.Tag(i) == `dns:"domain-name"`:
|
||||
out(st.Field(i).Name())
|
||||
}
|
||||
}
|
||||
}
|
||||
fmt.Fprintln(b, "}\n}\n\n")
|
||||
|
||||
// compressionLenSearchType - search cdomain-tags types for compressible names.
|
||||
|
||||
fmt.Fprint(b, "func compressionLenSearchType(c map[string]int, r RR) (int, bool) {\n")
|
||||
fmt.Fprint(b, "switch x := r.(type) {\n")
|
||||
for _, name := range cdomainTypes {
|
||||
o := scope.Lookup(name)
|
||||
st, _ := getTypeStruct(o.Type(), scope)
|
||||
|
||||
fmt.Fprintf(b, "case *%s:\n", name)
|
||||
j := 1
|
||||
for i := 1; i < st.NumFields(); i++ {
|
||||
out := func(s string, j int) {
|
||||
fmt.Fprintf(b, "k%d, ok%d := compressionLenSearch(c, x.%s)\n", j, j, st.Field(i).Name())
|
||||
}
|
||||
|
||||
// There are no slice types with names that can be compressed.
|
||||
|
||||
switch {
|
||||
case st.Tag(i) == `dns:"cdomain-name"`:
|
||||
out(st.Field(i).Name(), j)
|
||||
j++
|
||||
}
|
||||
}
|
||||
k := "k1"
|
||||
ok := "ok1"
|
||||
for i := 2; i < j; i++ {
|
||||
k += fmt.Sprintf(" + k%d", i)
|
||||
ok += fmt.Sprintf(" && ok%d", i)
|
||||
}
|
||||
fmt.Fprintf(b, "return %s, %s\n", k, ok)
|
||||
}
|
||||
fmt.Fprintln(b, "}\nreturn 0, false\n}\n\n")
|
||||
|
||||
// gofmt
|
||||
res, err := format.Source(b.Bytes())
|
||||
if err != nil {
|
||||
b.WriteTo(os.Stderr)
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
f, err := os.Create("zcompress.go")
|
||||
fatalIfErr(err)
|
||||
defer f.Close()
|
||||
f.Write(res)
|
||||
}
|
||||
|
||||
func fatalIfErr(err error) {
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
|
@ -1,349 +0,0 @@
|
|||
//+build ignore
|
||||
|
||||
// msg_generate.go is meant to run with go generate. It will use
|
||||
// go/{importer,types} to track down all the RR struct types. Then for each type
|
||||
// it will generate pack/unpack methods based on the struct tags. The generated source is
|
||||
// written to zmsg.go, and is meant to be checked into git.
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"go/format"
|
||||
"go/importer"
|
||||
"go/types"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var packageHdr = `
|
||||
// *** DO NOT MODIFY ***
|
||||
// AUTOGENERATED BY go generate from msg_generate.go
|
||||
|
||||
package dns
|
||||
|
||||
`
|
||||
|
||||
// getTypeStruct will take a type and the package scope, and return the
|
||||
// (innermost) struct if the type is considered a RR type (currently defined as
|
||||
// those structs beginning with a RR_Header, could be redefined as implementing
|
||||
// the RR interface). The bool return value indicates if embedded structs were
|
||||
// resolved.
|
||||
func getTypeStruct(t types.Type, scope *types.Scope) (*types.Struct, bool) {
|
||||
st, ok := t.Underlying().(*types.Struct)
|
||||
if !ok {
|
||||
return nil, false
|
||||
}
|
||||
if st.Field(0).Type() == scope.Lookup("RR_Header").Type() {
|
||||
return st, false
|
||||
}
|
||||
if st.Field(0).Anonymous() {
|
||||
st, _ := getTypeStruct(st.Field(0).Type(), scope)
|
||||
return st, true
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Import and type-check the package
|
||||
pkg, err := importer.Default().Import("github.com/miekg/dns")
|
||||
fatalIfErr(err)
|
||||
scope := pkg.Scope()
|
||||
|
||||
// Collect actual types (*X)
|
||||
var namedTypes []string
|
||||
for _, name := range scope.Names() {
|
||||
o := scope.Lookup(name)
|
||||
if o == nil || !o.Exported() {
|
||||
continue
|
||||
}
|
||||
if st, _ := getTypeStruct(o.Type(), scope); st == nil {
|
||||
continue
|
||||
}
|
||||
if name == "PrivateRR" {
|
||||
continue
|
||||
}
|
||||
|
||||
// Check if corresponding TypeX exists
|
||||
if scope.Lookup("Type"+o.Name()) == nil && o.Name() != "RFC3597" {
|
||||
log.Fatalf("Constant Type%s does not exist.", o.Name())
|
||||
}
|
||||
|
||||
namedTypes = append(namedTypes, o.Name())
|
||||
}
|
||||
|
||||
b := &bytes.Buffer{}
|
||||
b.WriteString(packageHdr)
|
||||
|
||||
fmt.Fprint(b, "// pack*() functions\n\n")
|
||||
for _, name := range namedTypes {
|
||||
o := scope.Lookup(name)
|
||||
st, _ := getTypeStruct(o.Type(), scope)
|
||||
|
||||
fmt.Fprintf(b, "func (rr *%s) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {\n", name)
|
||||
fmt.Fprint(b, `off, err := rr.Hdr.pack(msg, off, compression, compress)
|
||||
if err != nil {
|
||||
return off, err
|
||||
}
|
||||
headerEnd := off
|
||||
`)
|
||||
for i := 1; i < st.NumFields(); i++ {
|
||||
o := func(s string) {
|
||||
fmt.Fprintf(b, s, st.Field(i).Name())
|
||||
fmt.Fprint(b, `if err != nil {
|
||||
return off, err
|
||||
}
|
||||
`)
|
||||
}
|
||||
|
||||
if _, ok := st.Field(i).Type().(*types.Slice); ok {
|
||||
switch st.Tag(i) {
|
||||
case `dns:"-"`: // ignored
|
||||
case `dns:"txt"`:
|
||||
o("off, err = packStringTxt(rr.%s, msg, off)\n")
|
||||
case `dns:"opt"`:
|
||||
o("off, err = packDataOpt(rr.%s, msg, off)\n")
|
||||
case `dns:"nsec"`:
|
||||
o("off, err = packDataNsec(rr.%s, msg, off)\n")
|
||||
case `dns:"domain-name"`:
|
||||
o("off, err = packDataDomainNames(rr.%s, msg, off, compression, compress)\n")
|
||||
default:
|
||||
log.Fatalln(name, st.Field(i).Name(), st.Tag(i))
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
switch {
|
||||
case st.Tag(i) == `dns:"-"`: // ignored
|
||||
case st.Tag(i) == `dns:"cdomain-name"`:
|
||||
o("off, err = PackDomainName(rr.%s, msg, off, compression, compress)\n")
|
||||
case st.Tag(i) == `dns:"domain-name"`:
|
||||
o("off, err = PackDomainName(rr.%s, msg, off, compression, false)\n")
|
||||
case st.Tag(i) == `dns:"a"`:
|
||||
o("off, err = packDataA(rr.%s, msg, off)\n")
|
||||
case st.Tag(i) == `dns:"aaaa"`:
|
||||
o("off, err = packDataAAAA(rr.%s, msg, off)\n")
|
||||
case st.Tag(i) == `dns:"uint48"`:
|
||||
o("off, err = packUint48(rr.%s, msg, off)\n")
|
||||
case st.Tag(i) == `dns:"txt"`:
|
||||
o("off, err = packString(rr.%s, msg, off)\n")
|
||||
|
||||
case strings.HasPrefix(st.Tag(i), `dns:"size-base32`): // size-base32 can be packed just like base32
|
||||
fallthrough
|
||||
case st.Tag(i) == `dns:"base32"`:
|
||||
o("off, err = packStringBase32(rr.%s, msg, off)\n")
|
||||
|
||||
case strings.HasPrefix(st.Tag(i), `dns:"size-base64`): // size-base64 can be packed just like base64
|
||||
fallthrough
|
||||
case st.Tag(i) == `dns:"base64"`:
|
||||
o("off, err = packStringBase64(rr.%s, msg, off)\n")
|
||||
|
||||
case strings.HasPrefix(st.Tag(i), `dns:"size-hex:SaltLength`):
|
||||
// directly write instead of using o() so we get the error check in the correct place
|
||||
field := st.Field(i).Name()
|
||||
fmt.Fprintf(b, `// Only pack salt if value is not "-", i.e. empty
|
||||
if rr.%s != "-" {
|
||||
off, err = packStringHex(rr.%s, msg, off)
|
||||
if err != nil {
|
||||
return off, err
|
||||
}
|
||||
}
|
||||
`, field, field)
|
||||
continue
|
||||
case strings.HasPrefix(st.Tag(i), `dns:"size-hex`): // size-hex can be packed just like hex
|
||||
fallthrough
|
||||
case st.Tag(i) == `dns:"hex"`:
|
||||
o("off, err = packStringHex(rr.%s, msg, off)\n")
|
||||
|
||||
case st.Tag(i) == `dns:"octet"`:
|
||||
o("off, err = packStringOctet(rr.%s, msg, off)\n")
|
||||
case st.Tag(i) == "":
|
||||
switch st.Field(i).Type().(*types.Basic).Kind() {
|
||||
case types.Uint8:
|
||||
o("off, err = packUint8(rr.%s, msg, off)\n")
|
||||
case types.Uint16:
|
||||
o("off, err = packUint16(rr.%s, msg, off)\n")
|
||||
case types.Uint32:
|
||||
o("off, err = packUint32(rr.%s, msg, off)\n")
|
||||
case types.Uint64:
|
||||
o("off, err = packUint64(rr.%s, msg, off)\n")
|
||||
case types.String:
|
||||
o("off, err = packString(rr.%s, msg, off)\n")
|
||||
default:
|
||||
log.Fatalln(name, st.Field(i).Name())
|
||||
}
|
||||
default:
|
||||
log.Fatalln(name, st.Field(i).Name(), st.Tag(i))
|
||||
}
|
||||
}
|
||||
// We have packed everything, only now we know the rdlength of this RR
|
||||
fmt.Fprintln(b, "rr.Header().Rdlength = uint16(off-headerEnd)")
|
||||
fmt.Fprintln(b, "return off, nil }\n")
|
||||
}
|
||||
|
||||
fmt.Fprint(b, "// unpack*() functions\n\n")
|
||||
for _, name := range namedTypes {
|
||||
o := scope.Lookup(name)
|
||||
st, _ := getTypeStruct(o.Type(), scope)
|
||||
|
||||
fmt.Fprintf(b, "func unpack%s(h RR_Header, msg []byte, off int) (RR, int, error) {\n", name)
|
||||
fmt.Fprintf(b, "rr := new(%s)\n", name)
|
||||
fmt.Fprint(b, "rr.Hdr = h\n")
|
||||
fmt.Fprint(b, `if noRdata(h) {
|
||||
return rr, off, nil
|
||||
}
|
||||
var err error
|
||||
rdStart := off
|
||||
_ = rdStart
|
||||
|
||||
`)
|
||||
for i := 1; i < st.NumFields(); i++ {
|
||||
o := func(s string) {
|
||||
fmt.Fprintf(b, s, st.Field(i).Name())
|
||||
fmt.Fprint(b, `if err != nil {
|
||||
return rr, off, err
|
||||
}
|
||||
`)
|
||||
}
|
||||
|
||||
// size-* are special, because they reference a struct member we should use for the length.
|
||||
if strings.HasPrefix(st.Tag(i), `dns:"size-`) {
|
||||
structMember := structMember(st.Tag(i))
|
||||
structTag := structTag(st.Tag(i))
|
||||
switch structTag {
|
||||
case "hex":
|
||||
fmt.Fprintf(b, "rr.%s, off, err = unpackStringHex(msg, off, off + int(rr.%s))\n", st.Field(i).Name(), structMember)
|
||||
case "base32":
|
||||
fmt.Fprintf(b, "rr.%s, off, err = unpackStringBase32(msg, off, off + int(rr.%s))\n", st.Field(i).Name(), structMember)
|
||||
case "base64":
|
||||
fmt.Fprintf(b, "rr.%s, off, err = unpackStringBase64(msg, off, off + int(rr.%s))\n", st.Field(i).Name(), structMember)
|
||||
default:
|
||||
log.Fatalln(name, st.Field(i).Name(), st.Tag(i))
|
||||
}
|
||||
fmt.Fprint(b, `if err != nil {
|
||||
return rr, off, err
|
||||
}
|
||||
`)
|
||||
continue
|
||||
}
|
||||
|
||||
if _, ok := st.Field(i).Type().(*types.Slice); ok {
|
||||
switch st.Tag(i) {
|
||||
case `dns:"-"`: // ignored
|
||||
case `dns:"txt"`:
|
||||
o("rr.%s, off, err = unpackStringTxt(msg, off)\n")
|
||||
case `dns:"opt"`:
|
||||
o("rr.%s, off, err = unpackDataOpt(msg, off)\n")
|
||||
case `dns:"nsec"`:
|
||||
o("rr.%s, off, err = unpackDataNsec(msg, off)\n")
|
||||
case `dns:"domain-name"`:
|
||||
o("rr.%s, off, err = unpackDataDomainNames(msg, off, rdStart + int(rr.Hdr.Rdlength))\n")
|
||||
default:
|
||||
log.Fatalln(name, st.Field(i).Name(), st.Tag(i))
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
switch st.Tag(i) {
|
||||
case `dns:"-"`: // ignored
|
||||
case `dns:"cdomain-name"`:
|
||||
fallthrough
|
||||
case `dns:"domain-name"`:
|
||||
o("rr.%s, off, err = UnpackDomainName(msg, off)\n")
|
||||
case `dns:"a"`:
|
||||
o("rr.%s, off, err = unpackDataA(msg, off)\n")
|
||||
case `dns:"aaaa"`:
|
||||
o("rr.%s, off, err = unpackDataAAAA(msg, off)\n")
|
||||
case `dns:"uint48"`:
|
||||
o("rr.%s, off, err = unpackUint48(msg, off)\n")
|
||||
case `dns:"txt"`:
|
||||
o("rr.%s, off, err = unpackString(msg, off)\n")
|
||||
case `dns:"base32"`:
|
||||
o("rr.%s, off, err = unpackStringBase32(msg, off, rdStart + int(rr.Hdr.Rdlength))\n")
|
||||
case `dns:"base64"`:
|
||||
o("rr.%s, off, err = unpackStringBase64(msg, off, rdStart + int(rr.Hdr.Rdlength))\n")
|
||||
case `dns:"hex"`:
|
||||
o("rr.%s, off, err = unpackStringHex(msg, off, rdStart + int(rr.Hdr.Rdlength))\n")
|
||||
case `dns:"octet"`:
|
||||
o("rr.%s, off, err = unpackStringOctet(msg, off)\n")
|
||||
case "":
|
||||
switch st.Field(i).Type().(*types.Basic).Kind() {
|
||||
case types.Uint8:
|
||||
o("rr.%s, off, err = unpackUint8(msg, off)\n")
|
||||
case types.Uint16:
|
||||
o("rr.%s, off, err = unpackUint16(msg, off)\n")
|
||||
case types.Uint32:
|
||||
o("rr.%s, off, err = unpackUint32(msg, off)\n")
|
||||
case types.Uint64:
|
||||
o("rr.%s, off, err = unpackUint64(msg, off)\n")
|
||||
case types.String:
|
||||
o("rr.%s, off, err = unpackString(msg, off)\n")
|
||||
default:
|
||||
log.Fatalln(name, st.Field(i).Name())
|
||||
}
|
||||
default:
|
||||
log.Fatalln(name, st.Field(i).Name(), st.Tag(i))
|
||||
}
|
||||
// If we've hit len(msg) we return without error.
|
||||
if i < st.NumFields()-1 {
|
||||
fmt.Fprintf(b, `if off == len(msg) {
|
||||
return rr, off, nil
|
||||
}
|
||||
`)
|
||||
}
|
||||
}
|
||||
fmt.Fprintf(b, "return rr, off, err }\n\n")
|
||||
}
|
||||
// Generate typeToUnpack map
|
||||
fmt.Fprintln(b, "var typeToUnpack = map[uint16]func(RR_Header, []byte, int) (RR, int, error){")
|
||||
for _, name := range namedTypes {
|
||||
if name == "RFC3597" {
|
||||
continue
|
||||
}
|
||||
fmt.Fprintf(b, "Type%s: unpack%s,\n", name, name)
|
||||
}
|
||||
fmt.Fprintln(b, "}\n")
|
||||
|
||||
// gofmt
|
||||
res, err := format.Source(b.Bytes())
|
||||
if err != nil {
|
||||
b.WriteTo(os.Stderr)
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// write result
|
||||
f, err := os.Create("zmsg.go")
|
||||
fatalIfErr(err)
|
||||
defer f.Close()
|
||||
f.Write(res)
|
||||
}
|
||||
|
||||
// structMember will take a tag like dns:"size-base32:SaltLength" and return the last part of this string.
|
||||
func structMember(s string) string {
|
||||
fields := strings.Split(s, ":")
|
||||
if len(fields) == 0 {
|
||||
return ""
|
||||
}
|
||||
f := fields[len(fields)-1]
|
||||
// f should have a closing "
|
||||
if len(f) > 1 {
|
||||
return f[:len(f)-1]
|
||||
}
|
||||
return f
|
||||
}
|
||||
|
||||
// structTag will take a tag like dns:"size-base32:SaltLength" and return base32.
|
||||
func structTag(s string) string {
|
||||
fields := strings.Split(s, ":")
|
||||
if len(fields) < 2 {
|
||||
return ""
|
||||
}
|
||||
return fields[1][len("\"size-"):]
|
||||
}
|
||||
|
||||
func fatalIfErr(err error) {
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
|
@ -1,271 +0,0 @@
|
|||
//+build ignore
|
||||
|
||||
// types_generate.go is meant to run with go generate. It will use
|
||||
// go/{importer,types} to track down all the RR struct types. Then for each type
|
||||
// it will generate conversion tables (TypeToRR and TypeToString) and banal
|
||||
// methods (len, Header, copy) based on the struct tags. The generated source is
|
||||
// written to ztypes.go, and is meant to be checked into git.
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"go/format"
|
||||
"go/importer"
|
||||
"go/types"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
var skipLen = map[string]struct{}{
|
||||
"NSEC": {},
|
||||
"NSEC3": {},
|
||||
"OPT": {},
|
||||
"CSYNC": {},
|
||||
}
|
||||
|
||||
var packageHdr = `
|
||||
// *** DO NOT MODIFY ***
|
||||
// AUTOGENERATED BY go generate from types_generate.go
|
||||
|
||||
package dns
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"net"
|
||||
)
|
||||
|
||||
`
|
||||
|
||||
var TypeToRR = template.Must(template.New("TypeToRR").Parse(`
|
||||
// TypeToRR is a map of constructors for each RR type.
|
||||
var TypeToRR = map[uint16]func() RR{
|
||||
{{range .}}{{if ne . "RFC3597"}} Type{{.}}: func() RR { return new({{.}}) },
|
||||
{{end}}{{end}} }
|
||||
|
||||
`))
|
||||
|
||||
var typeToString = template.Must(template.New("typeToString").Parse(`
|
||||
// TypeToString is a map of strings for each RR type.
|
||||
var TypeToString = map[uint16]string{
|
||||
{{range .}}{{if ne . "NSAPPTR"}} Type{{.}}: "{{.}}",
|
||||
{{end}}{{end}} TypeNSAPPTR: "NSAP-PTR",
|
||||
}
|
||||
|
||||
`))
|
||||
|
||||
var headerFunc = template.Must(template.New("headerFunc").Parse(`
|
||||
{{range .}} func (rr *{{.}}) Header() *RR_Header { return &rr.Hdr }
|
||||
{{end}}
|
||||
|
||||
`))
|
||||
|
||||
// getTypeStruct will take a type and the package scope, and return the
|
||||
// (innermost) struct if the type is considered a RR type (currently defined as
|
||||
// those structs beginning with a RR_Header, could be redefined as implementing
|
||||
// the RR interface). The bool return value indicates if embedded structs were
|
||||
// resolved.
|
||||
func getTypeStruct(t types.Type, scope *types.Scope) (*types.Struct, bool) {
|
||||
st, ok := t.Underlying().(*types.Struct)
|
||||
if !ok {
|
||||
return nil, false
|
||||
}
|
||||
if st.Field(0).Type() == scope.Lookup("RR_Header").Type() {
|
||||
return st, false
|
||||
}
|
||||
if st.Field(0).Anonymous() {
|
||||
st, _ := getTypeStruct(st.Field(0).Type(), scope)
|
||||
return st, true
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Import and type-check the package
|
||||
pkg, err := importer.Default().Import("github.com/miekg/dns")
|
||||
fatalIfErr(err)
|
||||
scope := pkg.Scope()
|
||||
|
||||
// Collect constants like TypeX
|
||||
var numberedTypes []string
|
||||
for _, name := range scope.Names() {
|
||||
o := scope.Lookup(name)
|
||||
if o == nil || !o.Exported() {
|
||||
continue
|
||||
}
|
||||
b, ok := o.Type().(*types.Basic)
|
||||
if !ok || b.Kind() != types.Uint16 {
|
||||
continue
|
||||
}
|
||||
if !strings.HasPrefix(o.Name(), "Type") {
|
||||
continue
|
||||
}
|
||||
name := strings.TrimPrefix(o.Name(), "Type")
|
||||
if name == "PrivateRR" {
|
||||
continue
|
||||
}
|
||||
numberedTypes = append(numberedTypes, name)
|
||||
}
|
||||
|
||||
// Collect actual types (*X)
|
||||
var namedTypes []string
|
||||
for _, name := range scope.Names() {
|
||||
o := scope.Lookup(name)
|
||||
if o == nil || !o.Exported() {
|
||||
continue
|
||||
}
|
||||
if st, _ := getTypeStruct(o.Type(), scope); st == nil {
|
||||
continue
|
||||
}
|
||||
if name == "PrivateRR" {
|
||||
continue
|
||||
}
|
||||
|
||||
// Check if corresponding TypeX exists
|
||||
if scope.Lookup("Type"+o.Name()) == nil && o.Name() != "RFC3597" {
|
||||
log.Fatalf("Constant Type%s does not exist.", o.Name())
|
||||
}
|
||||
|
||||
namedTypes = append(namedTypes, o.Name())
|
||||
}
|
||||
|
||||
b := &bytes.Buffer{}
|
||||
b.WriteString(packageHdr)
|
||||
|
||||
// Generate TypeToRR
|
||||
fatalIfErr(TypeToRR.Execute(b, namedTypes))
|
||||
|
||||
// Generate typeToString
|
||||
fatalIfErr(typeToString.Execute(b, numberedTypes))
|
||||
|
||||
// Generate headerFunc
|
||||
fatalIfErr(headerFunc.Execute(b, namedTypes))
|
||||
|
||||
// Generate len()
|
||||
fmt.Fprint(b, "// len() functions\n")
|
||||
for _, name := range namedTypes {
|
||||
if _, ok := skipLen[name]; ok {
|
||||
continue
|
||||
}
|
||||
o := scope.Lookup(name)
|
||||
st, isEmbedded := getTypeStruct(o.Type(), scope)
|
||||
if isEmbedded {
|
||||
continue
|
||||
}
|
||||
fmt.Fprintf(b, "func (rr *%s) len() int {\n", name)
|
||||
fmt.Fprintf(b, "l := rr.Hdr.len()\n")
|
||||
for i := 1; i < st.NumFields(); i++ {
|
||||
o := func(s string) { fmt.Fprintf(b, s, st.Field(i).Name()) }
|
||||
|
||||
if _, ok := st.Field(i).Type().(*types.Slice); ok {
|
||||
switch st.Tag(i) {
|
||||
case `dns:"-"`:
|
||||
// ignored
|
||||
case `dns:"cdomain-name"`, `dns:"domain-name"`, `dns:"txt"`:
|
||||
o("for _, x := range rr.%s { l += len(x) + 1 }\n")
|
||||
default:
|
||||
log.Fatalln(name, st.Field(i).Name(), st.Tag(i))
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
switch {
|
||||
case st.Tag(i) == `dns:"-"`:
|
||||
// ignored
|
||||
case st.Tag(i) == `dns:"cdomain-name"`, st.Tag(i) == `dns:"domain-name"`:
|
||||
o("l += len(rr.%s) + 1\n")
|
||||
case st.Tag(i) == `dns:"octet"`:
|
||||
o("l += len(rr.%s)\n")
|
||||
case strings.HasPrefix(st.Tag(i), `dns:"size-base64`):
|
||||
fallthrough
|
||||
case st.Tag(i) == `dns:"base64"`:
|
||||
o("l += base64.StdEncoding.DecodedLen(len(rr.%s))\n")
|
||||
case strings.HasPrefix(st.Tag(i), `dns:"size-hex`):
|
||||
fallthrough
|
||||
case st.Tag(i) == `dns:"hex"`:
|
||||
o("l += len(rr.%s)/2 + 1\n")
|
||||
case st.Tag(i) == `dns:"a"`:
|
||||
o("l += net.IPv4len // %s\n")
|
||||
case st.Tag(i) == `dns:"aaaa"`:
|
||||
o("l += net.IPv6len // %s\n")
|
||||
case st.Tag(i) == `dns:"txt"`:
|
||||
o("for _, t := range rr.%s { l += len(t) + 1 }\n")
|
||||
case st.Tag(i) == `dns:"uint48"`:
|
||||
o("l += 6 // %s\n")
|
||||
case st.Tag(i) == "":
|
||||
switch st.Field(i).Type().(*types.Basic).Kind() {
|
||||
case types.Uint8:
|
||||
o("l++ // %s\n")
|
||||
case types.Uint16:
|
||||
o("l += 2 // %s\n")
|
||||
case types.Uint32:
|
||||
o("l += 4 // %s\n")
|
||||
case types.Uint64:
|
||||
o("l += 8 // %s\n")
|
||||
case types.String:
|
||||
o("l += len(rr.%s) + 1\n")
|
||||
default:
|
||||
log.Fatalln(name, st.Field(i).Name())
|
||||
}
|
||||
default:
|
||||
log.Fatalln(name, st.Field(i).Name(), st.Tag(i))
|
||||
}
|
||||
}
|
||||
fmt.Fprintf(b, "return l }\n")
|
||||
}
|
||||
|
||||
// Generate copy()
|
||||
fmt.Fprint(b, "// copy() functions\n")
|
||||
for _, name := range namedTypes {
|
||||
o := scope.Lookup(name)
|
||||
st, isEmbedded := getTypeStruct(o.Type(), scope)
|
||||
if isEmbedded {
|
||||
continue
|
||||
}
|
||||
fmt.Fprintf(b, "func (rr *%s) copy() RR {\n", name)
|
||||
fields := []string{"*rr.Hdr.copyHeader()"}
|
||||
for i := 1; i < st.NumFields(); i++ {
|
||||
f := st.Field(i).Name()
|
||||
if sl, ok := st.Field(i).Type().(*types.Slice); ok {
|
||||
t := sl.Underlying().String()
|
||||
t = strings.TrimPrefix(t, "[]")
|
||||
if strings.Contains(t, ".") {
|
||||
splits := strings.Split(t, ".")
|
||||
t = splits[len(splits)-1]
|
||||
}
|
||||
fmt.Fprintf(b, "%s := make([]%s, len(rr.%s)); copy(%s, rr.%s)\n",
|
||||
f, t, f, f, f)
|
||||
fields = append(fields, f)
|
||||
continue
|
||||
}
|
||||
if st.Field(i).Type().String() == "net.IP" {
|
||||
fields = append(fields, "copyIP(rr."+f+")")
|
||||
continue
|
||||
}
|
||||
fields = append(fields, "rr."+f)
|
||||
}
|
||||
fmt.Fprintf(b, "return &%s{%s}\n", name, strings.Join(fields, ","))
|
||||
fmt.Fprintf(b, "}\n")
|
||||
}
|
||||
|
||||
// gofmt
|
||||
res, err := format.Source(b.Bytes())
|
||||
if err != nil {
|
||||
b.WriteTo(os.Stderr)
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// write result
|
||||
f, err := os.Create("ztypes.go")
|
||||
fatalIfErr(err)
|
||||
defer f.Close()
|
||||
f.Write(res)
|
||||
}
|
||||
|
||||
func fatalIfErr(err error) {
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
Microsoft Reference Source License (Ms-RSL)
|
||||
===========================================
|
||||
|
||||
This license governs use of the accompanying software. If you use the software,
|
||||
you accept this license. If you do not accept the license, do not use the
|
||||
software.
|
||||
|
||||
1. Definitions
|
||||
--------------
|
||||
|
||||
The terms "reproduce", "reproduction" and "distribution" have the same meaning
|
||||
here as under U.S. copyright law.
|
||||
|
||||
"You" means the licensee of the software.
|
||||
|
||||
"Your company" means the company you worked for when you downloaded the
|
||||
software.
|
||||
|
||||
"Reference use" means use of the software within your company as a reference, in
|
||||
read only form, for the sole purposes of debugging your products, maintaining
|
||||
your products, or enhancing the interoperability of your products with the
|
||||
software, and specifically excludes the right to distribute the software outside
|
||||
of your company.
|
||||
|
||||
Licensed patents" means any Licensor patent claims which read directly on the
|
||||
software as distributed by the Licensor under this license.
|
||||
|
||||
2. Grant of Rights
|
||||
------------------
|
||||
|
||||
(A) Copyright Grant - Subject to the terms of this license, the Licensor grants
|
||||
you a non-transferable, non-exclusive, worldwide, royalty-free copyright license
|
||||
to reproduce the software for reference use.
|
||||
|
||||
(B) Patent Grant - Subject to the terms of this license, the Licensor grants you
|
||||
a non-transferable, non-exclusive, worldwide, royalty-free patent license under
|
||||
licensed patents for reference use.
|
||||
|
||||
3. Limitations
|
||||
--------------
|
||||
|
||||
(A) No Trademark License - This license does not grant you any rights to use the
|
||||
Licensor's name, logo, or trademarks.
|
||||
|
||||
(B) If you begin patent litigation against the Licensor over patents that you
|
||||
think may apply to the software (including a cross-claim or counterclaim in a
|
||||
lawsuit), your license to the software ends automatically.
|
||||
|
||||
(C) The software is licensed "as-is." You bear the risk of using it. The
|
||||
Licensor gives no express warranties, guarantees or conditions. You may have
|
||||
additional consumer rights under your local laws which this license cannot
|
||||
change. To the extent permitted under your local laws, the Licensor excludes the
|
||||
implied warranties of merchantability, fitness for a particular purpose and
|
||||
non-infringement.
|
|
@ -24,7 +24,6 @@ func CreateAddressV2(userKey, muunKey *HDPublicKey) (MuunAddress, error) {
|
|||
address: address.String(),
|
||||
version: addressV2,
|
||||
derivationPath: userKey.Path,
|
||||
redeemScript: script,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,6 @@ func CreateAddressV3(userKey, muunKey *HDPublicKey) (MuunAddress, error) {
|
|||
address: address.EncodeAddress(),
|
||||
version: addressV3,
|
||||
derivationPath: userKey.Path,
|
||||
redeemScript: redeemScript,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -48,7 +47,6 @@ func addUserSignatureInputV3(input Input, index int, tx *wire.MsgTx, privateKey
|
|||
return nil, errors.Errorf("muun signature must be present")
|
||||
}
|
||||
|
||||
|
||||
witnessScript, err := createWitnessScriptV3(privateKey.PublicKey(), muunKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -77,7 +75,7 @@ func signInputV3(input Input, index int, tx *wire.MsgTx, userKey *HDPublicKey, m
|
|||
|
||||
redeemScript, err := createRedeemScriptV3(userKey, muunKey)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to build reedem script for signing")
|
||||
return nil, errors.Wrapf(err, "failed to build reedem script for signing")
|
||||
}
|
||||
|
||||
return signNonNativeSegwitInput(input, index, tx, signingKey, redeemScript, witnessScript)
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
package libwallet
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
|
||||
"github.com/btcsuite/btcutil"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
)
|
||||
|
||||
func CreateAddressV4(userKey, muunKey *HDPublicKey) (MuunAddress, error) {
|
||||
|
||||
witnessScript, err := createWitnessScriptV4(userKey, muunKey)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to generate witness script v4")
|
||||
}
|
||||
witnessScript256 := sha256.Sum256(witnessScript)
|
||||
|
||||
address, err := btcutil.NewAddressWitnessScriptHash(witnessScript256[:], userKey.Network.network)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &muunAddress{
|
||||
address: address.EncodeAddress(),
|
||||
version: addressV4,
|
||||
derivationPath: userKey.Path,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func createWitnessScriptV4(userKey, muunKey *HDPublicKey) ([]byte, error) {
|
||||
// createRedeemScriptV2 creates a valid script for V2, V3 and V4 schemes
|
||||
return createRedeemScriptV2(userKey, muunKey)
|
||||
}
|
||||
|
||||
func addUserSignatureInputV4(input Input, index int, tx *wire.MsgTx, privateKey *HDPrivateKey, muunKey *HDPublicKey) (*wire.TxIn, error) {
|
||||
|
||||
if len(input.MuunSignature()) == 0 {
|
||||
return nil, errors.Errorf("muun signature must be present")
|
||||
}
|
||||
|
||||
witnessScript, err := createWitnessScriptV4(privateKey.PublicKey(), muunKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sig, err := signInputV4(input, index, tx, privateKey.PublicKey(), muunKey, privateKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
zeroByteArray := []byte{}
|
||||
|
||||
txInput := tx.TxIn[index]
|
||||
txInput.Witness = wire.TxWitness{zeroByteArray, sig, input.MuunSignature(), witnessScript}
|
||||
|
||||
return txInput, nil
|
||||
}
|
||||
|
||||
func signInputV4(input Input, index int, tx *wire.MsgTx, userKey *HDPublicKey, muunKey *HDPublicKey,
|
||||
signingKey *HDPrivateKey) ([]byte, error) {
|
||||
|
||||
witnessScript, err := createWitnessScriptV4(userKey, muunKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return signNativeSegwitInput(input, index, tx, signingKey, witnessScript)
|
||||
}
|
|
@ -13,20 +13,27 @@ import (
|
|||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// These constants are here for clients usage.
|
||||
const (
|
||||
AddressVersionSwapsV1 = 101
|
||||
AddressVersionSwapsV2 = 102
|
||||
)
|
||||
|
||||
type AddressVersion int
|
||||
|
||||
const (
|
||||
addressV1 AddressVersion = 1
|
||||
addressV2 AddressVersion = 2
|
||||
addressV3 AddressVersion = 3
|
||||
addressSubmarineSwap AddressVersion = 101
|
||||
addressV1 AddressVersion = 1
|
||||
addressV2 AddressVersion = 2
|
||||
addressV3 AddressVersion = 3
|
||||
addressV4 AddressVersion = 4
|
||||
addressSubmarineSwapV1 AddressVersion = AddressVersionSwapsV1
|
||||
addressSubmarineSwapV2 AddressVersion = AddressVersionSwapsV2
|
||||
)
|
||||
|
||||
type muunAddress struct {
|
||||
version AddressVersion
|
||||
derivationPath string
|
||||
address string
|
||||
redeemScript []byte
|
||||
}
|
||||
|
||||
func newMuunAddress(version AddressVersion, userPublicKey, muunPublicKey *HDPublicKey) (MuunAddress, error) {
|
||||
|
@ -41,8 +48,12 @@ func newMuunAddress(version AddressVersion, userPublicKey, muunPublicKey *HDPubl
|
|||
return CreateAddressV2(userPublicKey, muunPublicKey)
|
||||
case addressV3:
|
||||
return CreateAddressV3(userPublicKey, muunPublicKey)
|
||||
case addressSubmarineSwap:
|
||||
return CreateAddressSubmarineSwap(userPublicKey)
|
||||
case addressV4:
|
||||
return CreateAddressV4(userPublicKey, muunPublicKey)
|
||||
case addressSubmarineSwapV1:
|
||||
return nil, errors.Errorf("can't manually create a submarine swap v1 address")
|
||||
case addressSubmarineSwapV2:
|
||||
return nil, errors.Errorf("can't manually create a submarine swap v2 address")
|
||||
}
|
||||
|
||||
return nil, errors.Errorf("unknown version %v", version)
|
||||
|
@ -60,10 +71,6 @@ func (a *muunAddress) Address() string {
|
|||
return a.address
|
||||
}
|
||||
|
||||
func (a *muunAddress) RedeemScript() []byte {
|
||||
return a.redeemScript
|
||||
}
|
||||
|
||||
// MuunPaymentURI is muun's uri struct
|
||||
type MuunPaymentURI struct {
|
||||
Address string
|
||||
|
@ -127,7 +134,7 @@ func GetPaymentURI(address string, network *Network) (*MuunPaymentURI, error) {
|
|||
invoice, err := ParseInvoice(queryValues["lightning"][0], network)
|
||||
|
||||
if err == nil {
|
||||
return &MuunPaymentURI{Invoice:invoice}, nil
|
||||
return &MuunPaymentURI{Invoice: invoice}, nil
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -240,9 +247,7 @@ func getAddressFromScript(script []byte, network *Network) (string, error) {
|
|||
func normalizeAddress(rawAddress string) string {
|
||||
newAddress := rawAddress
|
||||
|
||||
if strings.Contains(newAddress, muunScheme) {
|
||||
newAddress = strings.Replace(newAddress, muunScheme, bitcoinScheme, 1)
|
||||
}
|
||||
newAddress = strings.Replace(newAddress, muunScheme, bitcoinScheme, 1)
|
||||
|
||||
if !strings.Contains(newAddress, bitcoinScheme) {
|
||||
newAddress = bitcoinScheme + rawAddress
|
||||
|
|
|
@ -55,22 +55,6 @@ func (m *Output) XXX_DiscardUnknown() {
|
|||
|
||||
var xxx_messageInfo_Output proto.InternalMessageInfo
|
||||
|
||||
const Default_Output_Amount uint64 = 0
|
||||
|
||||
func (m *Output) GetAmount() uint64 {
|
||||
if m != nil && m.Amount != nil {
|
||||
return *m.Amount
|
||||
}
|
||||
return Default_Output_Amount
|
||||
}
|
||||
|
||||
func (m *Output) GetScript() []byte {
|
||||
if m != nil {
|
||||
return m.Script
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type PaymentDetails struct {
|
||||
Network *string `protobuf:"bytes,1,opt,name=network,def=main" json:"network,omitempty"`
|
||||
Outputs []*Output `protobuf:"bytes,2,rep,name=outputs" json:"outputs,omitempty"`
|
||||
|
@ -153,13 +137,6 @@ func (m *PaymentDetails) GetPaymentUrl() string {
|
|||
return ""
|
||||
}
|
||||
|
||||
func (m *PaymentDetails) GetMerchantData() []byte {
|
||||
if m != nil {
|
||||
return m.MerchantData
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type PaymentRequest struct {
|
||||
PaymentDetailsVersion *uint32 `protobuf:"varint,1,opt,name=payment_details_version,json=paymentDetailsVersion,def=1" json:"payment_details_version,omitempty"`
|
||||
PkiType *string `protobuf:"bytes,2,opt,name=pki_type,json=pkiType,def=none" json:"pki_type,omitempty"`
|
||||
|
@ -213,26 +190,6 @@ func (m *PaymentRequest) GetPkiType() string {
|
|||
return Default_PaymentRequest_PkiType
|
||||
}
|
||||
|
||||
func (m *PaymentRequest) GetPkiData() []byte {
|
||||
if m != nil {
|
||||
return m.PkiData
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *PaymentRequest) GetSerializedPaymentDetails() []byte {
|
||||
if m != nil {
|
||||
return m.SerializedPaymentDetails
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *PaymentRequest) GetSignature() []byte {
|
||||
if m != nil {
|
||||
return m.Signature
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type X509Certificates struct {
|
||||
Certificate [][]byte `protobuf:"bytes,1,rep,name=certificate" json:"certificate,omitempty"`
|
||||
|
@ -308,12 +265,6 @@ func (m *Payment) XXX_DiscardUnknown() {
|
|||
|
||||
var xxx_messageInfo_Payment proto.InternalMessageInfo
|
||||
|
||||
func (m *Payment) GetMerchantData() []byte {
|
||||
if m != nil {
|
||||
return m.MerchantData
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Payment) GetTransactions() [][]byte {
|
||||
if m != nil {
|
||||
|
@ -369,13 +320,6 @@ func (m *PaymentACK) XXX_DiscardUnknown() {
|
|||
|
||||
var xxx_messageInfo_PaymentACK proto.InternalMessageInfo
|
||||
|
||||
func (m *PaymentACK) GetPayment() *Payment {
|
||||
if m != nil {
|
||||
return m.Payment
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *PaymentACK) GetMemo() string {
|
||||
if m != nil && m.Memo != nil {
|
||||
return *m.Memo
|
||||
|
|
|
@ -3,10 +3,11 @@ module github.com/muun/libwallet
|
|||
go 1.12
|
||||
|
||||
require (
|
||||
github.com/btcsuite/btcd v0.0.0-20190824003749-130ea5bddde3
|
||||
github.com/btcsuite/btcd v0.20.1-beta
|
||||
github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d
|
||||
github.com/go-errors/errors v1.0.1
|
||||
github.com/golang/protobuf v1.3.2
|
||||
github.com/lightningnetwork/lnd v0.7.1-beta-rc2
|
||||
github.com/lightningnetwork/lnd v0.8.0-beta
|
||||
github.com/pkg/errors v0.8.1
|
||||
golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7
|
||||
)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
git.schwanenlied.me/yawning/bsaes.git v0.0.0-20180720073208-c0276d75487e/go.mod h1:BWqTsj8PgcPriQJGl7el20J/7TuT1d/hSyFDXMEpoEo=
|
||||
github.com/NebulousLabs/fastrand v0.0.0-20180208210444-3cf7173006a0/go.mod h1:Bdzq+51GR4/0DIhaICZEOm+OHvXGwwB2trKZ8B4Y6eQ=
|
||||
github.com/NebulousLabs/fastrand v0.0.0-20181203155948-6fb6489aac4e/go.mod h1:Bdzq+51GR4/0DIhaICZEOm+OHvXGwwB2trKZ8B4Y6eQ=
|
||||
github.com/NebulousLabs/go-upnp v0.0.0-20180202185039-29b680b06c82/go.mod h1:GbuBk21JqF+driLX3XtJYNZjGa45YDoa9IqCTzNSfEc=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/Yawning/aez v0.0.0-20180114000226-4dad034d9db2/go.mod h1:9pIqrY6SXNL8vjRQE5Hd/OL5GyK/9MrGUWs87z/eFfk=
|
||||
|
@ -10,25 +10,22 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuy
|
|||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps=
|
||||
github.com/btcsuite/btcd v0.0.0-20180823030728-d81d8877b8f3/go.mod h1:Dmm/EzmjnCiweXmzRIAiUWCInVmPgjkzgv5k4tVyXiQ=
|
||||
github.com/btcsuite/btcd v0.0.0-20181130015935-7d2daa5bfef2/go.mod h1:Jr9bmNVGZ7TH2Ux1QuP0ec+yGgh0gE9FIlkzQiI5bR0=
|
||||
github.com/btcsuite/btcd v0.0.0-20190213025234-306aecffea32/go.mod h1:DrZx5ec/dmnfpw9KyYoQyYo7d0KEvTkk/5M/vbZjAr8=
|
||||
github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI=
|
||||
github.com/btcsuite/btcd v0.0.0-20190605094302-a0d1e3e36d50/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI=
|
||||
github.com/btcsuite/btcd v0.0.0-20190629003639-c26ffa870fd8/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI=
|
||||
github.com/btcsuite/btcd v0.0.0-20190824003749-130ea5bddde3 h1:A/EVblehb75cUgXA5njHPn0kLAsykn6mJGz7rnmW5W0=
|
||||
github.com/btcsuite/btcd v0.0.0-20190824003749-130ea5bddde3/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI=
|
||||
github.com/btcsuite/btcd v0.20.0-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ=
|
||||
github.com/btcsuite/btcd v0.20.1-beta h1:Ik4hyJqN8Jfyv3S4AGBOmyouMsYE3EdYODkMbQjwPGw=
|
||||
github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ=
|
||||
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo=
|
||||
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA=
|
||||
github.com/btcsuite/btcutil v0.0.0-20180706230648-ab6388e0c60a/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg=
|
||||
github.com/btcsuite/btcutil v0.0.0-20190207003914-4c204d697803/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg=
|
||||
github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d h1:yJzD/yFppdVCf6ApMkVy8cUxV0XrxdP9rVf6D87/Mng=
|
||||
github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg=
|
||||
github.com/btcsuite/btcwallet v0.0.0-20180904010540-284e2e0e696e33d5be388f7f3d9a26db703e0c06/go.mod h1:/d7QHZsfUAruXuBhyPITqoYOmJ+nq35qPsJjz/aSpCg=
|
||||
github.com/btcsuite/btcwallet v0.0.0-20190313032608-acf3b04b0273/go.mod h1:mkOYY8/psBiL5E+Wb0V7M0o+N7NXi2SZJz6+RKkncIc=
|
||||
github.com/btcsuite/btcwallet v0.0.0-20190319010515-89ab2044f962/go.mod h1:qMi4jGpAO6YRsd81RYDG7o5pBIGqN9faCioJdagLu64=
|
||||
github.com/btcsuite/btcwallet v0.0.0-20190712034938-7a3a3e82cbb6/go.mod h1:sXVxjjP5YeWqWsiQbQDXvAw6J6Qvr8swu7MONoNaF9k=
|
||||
github.com/btcsuite/btcwallet v0.10.0/go.mod h1:4TqBEuceheGNdeLNrelliLHJzmXauMM2vtWfuy1pFiM=
|
||||
github.com/btcsuite/btcwallet/wallet/txauthor v1.0.0/go.mod h1:VufDts7bd/zs3GV13f/lXc/0lXrPnvxD/NvmpG/FEKU=
|
||||
github.com/btcsuite/btcwallet/wallet/txrules v1.0.0/go.mod h1:UwQE78yCerZ313EXZwEiu3jNAtfXj2n2+c8RWiE/WNA=
|
||||
github.com/btcsuite/btcwallet/wallet/txsizes v1.0.0/go.mod h1:pauEU8UuMFiThe5PB3EO+gO5kx87Me5NvdQDsTuq6cs=
|
||||
github.com/btcsuite/btcwallet/walletdb v1.0.0/go.mod h1:bZTy9RyYZh9fLnSua+/CD48TJtYJSHjjYcSaszuxCCk=
|
||||
github.com/btcsuite/btcwallet/walletdb v1.1.0/go.mod h1:bZTy9RyYZh9fLnSua+/CD48TJtYJSHjjYcSaszuxCCk=
|
||||
github.com/btcsuite/btcwallet/wtxmgr v1.0.0/go.mod h1:vc4gBprll6BP0UJ+AIGDaySoc7MdAmZf8kelfNb8CFY=
|
||||
github.com/btcsuite/fastsha256 v0.0.0-20160815193821-637e65642941/go.mod h1:QcFA8DZHtuIAdYKCq/BzELOaznRsCvwf4zTPmaYwaig=
|
||||
github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg=
|
||||
github.com/btcsuite/golangcrypto v0.0.0-20150304025918-53f62d9b43e8/go.mod h1:tYvUd8KLhm/oXvUeSEs2VlLghFjQt9+ZaF9ghH0JNjc=
|
||||
|
@ -40,12 +37,12 @@ github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtE
|
|||
github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs=
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/coreos/bbolt v0.0.0-20180223184059-7ee3ded59d4835e10f3e7d0f7603c42aa5e83820/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
||||
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
||||
github.com/coreos/bbolt v1.3.3/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
||||
github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
||||
github.com/frankban/quicktest v1.2.2/go.mod h1:Qh/WofXFeiAFII1aEBu529AtJo6Zg2VHscnEsbBnJ20=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w=
|
||||
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
|
||||
|
@ -57,11 +54,11 @@ github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7a
|
|||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/protobuf v0.0.0-20180821051752-b27b920f9e71/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/google/go-cmp v0.2.1-0.20190312032427-6f77996f0c42/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||
github.com/grpc-ecosystem/grpc-gateway v0.0.0-20170724004829-f2862b476edc/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw=
|
||||
|
@ -71,11 +68,11 @@ github.com/jackpal/go-nat-pmp v0.0.0-20170405195558-28a68d0c24ad/go.mod h1:QPH04
|
|||
github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||
github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ=
|
||||
github.com/juju/clock v0.0.0-20180808021310-bab88fc67299/go.mod h1:nD0vlnrUjcjJhqN5WuCWZyzfd5AHZAC9/ajvbSx69xA=
|
||||
github.com/juju/errors v0.0.0-20181118221551-089d3ea4e4d5/go.mod h1:W54LbzXuIE0boCoNJfwqpmkKJ1O4TCTZMetAt6jGk7Q=
|
||||
github.com/juju/loggo v0.0.0-20180524022052-584905176618/go.mod h1:vgyd7OREkbtVEN/8IXZe5Ooef3LQePvuBm9UWj6ZL8U=
|
||||
github.com/juju/clock v0.0.0-20190205081909-9c5c9712527c/go.mod h1:nD0vlnrUjcjJhqN5WuCWZyzfd5AHZAC9/ajvbSx69xA=
|
||||
github.com/juju/errors v0.0.0-20190806202954-0232dcc7464d/go.mod h1:W54LbzXuIE0boCoNJfwqpmkKJ1O4TCTZMetAt6jGk7Q=
|
||||
github.com/juju/loggo v0.0.0-20190526231331-6e530bcce5d8/go.mod h1:vgyd7OREkbtVEN/8IXZe5Ooef3LQePvuBm9UWj6ZL8U=
|
||||
github.com/juju/retry v0.0.0-20180821225755-9058e192b216/go.mod h1:OohPQGsr4pnxwD5YljhQ+TZnuVRYpa5irjugL1Yuif4=
|
||||
github.com/juju/testing v0.0.0-20180920084828-472a3e8b2073/go.mod h1:63prj8cnj0tU0S9OHjGJn+b1h0ZghCndfnbQolrYTwA=
|
||||
github.com/juju/testing v0.0.0-20190723135506-ce30eb24acd2/go.mod h1:63prj8cnj0tU0S9OHjGJn+b1h0ZghCndfnbQolrYTwA=
|
||||
github.com/juju/utils v0.0.0-20180820210520-bf9cc5bdd62d/go.mod h1:6/KLg8Wz/y2KVGWEpkK9vMNGkOnu4k/cqs8Z1fKjTOk=
|
||||
github.com/juju/version v0.0.0-20180108022336-b64dbd566305/go.mod h1:kE8gK5X0CImdr7qpSKl3xB2PmpySSmfj7zVbkZFs81U=
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
|
@ -87,18 +84,13 @@ github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFB
|
|||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/lightninglabs/gozmq v0.0.0-20180324010646-462a8a753885/go.mod h1:KUh15naRlx/TmUMFS/p4JJrCrE6F7RGF7rsnvuu45E4=
|
||||
github.com/lightninglabs/gozmq v0.0.0-20190710231225-cea2a031735d/go.mod h1:vxmQPeIQxPf6Jf9rM8R+B4rKBqLA2AjttNxkFBL2Plk=
|
||||
github.com/lightninglabs/neutrino v0.0.0-20181017011010-4d6069299130/go.mod h1:KJq43Fu9ceitbJsSXMILcT4mGDNI/crKmPIkDOZXFyM=
|
||||
github.com/lightninglabs/neutrino v0.0.0-20190213031021-ae4583a89cfb/go.mod h1:g6cMQd+hfAU8pQTJAdjm6/EQREhupyd22f+CL0qYFOE=
|
||||
github.com/lightninglabs/neutrino v0.0.0-20190313035638-e1ad4c33fb18/go.mod h1:v6tz6jbuAubTrRpX8ke2KH9sJxml8KlPQTKgo9mAp1Q=
|
||||
github.com/lightninglabs/neutrino v0.0.0-20190725230401-ddf667a8b5c4/go.mod h1:vzLU75ll8qbRJIzW5dvK/UXtR9c2FecJ6VNOM8chyVM=
|
||||
github.com/lightningnetwork/lightning-onion v0.0.0-20190703000913-ecc936dc56c9/go.mod h1:Sooe/CoCqa85JxqHV+IBR2HW+6t2Cv+36awSmoccswM=
|
||||
github.com/lightningnetwork/lnd v0.7.1-beta-rc2 h1:N0AuHo4wI6TogabvOfpwg1LkR3RxGCvqYq0Wb7GL+ck=
|
||||
github.com/lightningnetwork/lnd v0.7.1-beta-rc2/go.mod h1:ODASBFcJwVlb4aqO3m090whpP2kfA9zEvmG/pj+fOfg=
|
||||
github.com/lightninglabs/neutrino v0.10.0/go.mod h1:C3KhCMk1Mcx3j8v0qRVWM1Ow6rIJSvSPnUAq00ZNAfk=
|
||||
github.com/lightningnetwork/lightning-onion v0.0.0-20190909101754-850081b08b6a/go.mod h1:rigfi6Af/KqsF7Za0hOgcyq2PNH4AN70AaMRxcJkff4=
|
||||
github.com/lightningnetwork/lnd v0.8.0-beta h1:HmmhSRTq48qobqQF8YLqNa8eKU8dDBNbWWpr2VzycJM=
|
||||
github.com/lightningnetwork/lnd v0.8.0-beta/go.mod h1:nq06y2BDv7vwWeMmwgB7P3pT7/Uj7sGf5FzHISVD6t4=
|
||||
github.com/lightningnetwork/lnd/queue v1.0.1/go.mod h1:vaQwexir73flPW43Mrm7JOgJHmcEFBWWSl9HlyASoms=
|
||||
github.com/lightningnetwork/lnd/ticker v1.0.0/go.mod h1:iaLXJiVgI1sPANIF2qYYUJXjoksPNvGNYowB8aRbpX0=
|
||||
github.com/ltcsuite/ltcd v0.0.0-20190101042124-f37f8bf35796 h1:sjOGyegMIhvgfq5oaue6Td+hxZuf3tDC8lAPrFldqFw=
|
||||
github.com/ltcsuite/ltcd v0.0.0-20190101042124-f37f8bf35796/go.mod h1:3p7ZTf9V1sNPI5H8P3NkTFF4LuwMdPl2DodF60qAKqY=
|
||||
github.com/ltcsuite/ltcutil v0.0.0-20181217130922-17f3b04680b6/go.mod h1:8Vg/LTOO0KYa/vlHWJ6XZAevPQThGH5sufO0Hrou/lA=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
|
@ -123,19 +115,16 @@ github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8
|
|||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/tv42/zbase32 v0.0.0-20160707012821-501572607d02/go.mod h1:tHlrkM198S068ZqfrO6S8HsoJq2bF3ETfTL+kt4tInY=
|
||||
github.com/urfave/cli v1.18.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||
go.etcd.io/bbolt v1.3.0/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190103213133-ff983b9c42bc/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7 h1:0hQKqeLdqlt5iIwVOBErRisrHJAN57yOiPRQItI20fU=
|
||||
|
@ -144,7 +133,6 @@ golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL
|
|||
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180821023952-922f4815f713/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
|
@ -156,16 +144,15 @@ golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAG
|
|||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180821140842-3b58ed4ad339/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190102155601-82a175fd1598/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
|
@ -173,18 +160,16 @@ golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGm
|
|||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190201180003-4b09977fb922/go.mod h1:L3J43x8/uS+qIUoksaLKe6OS3nUKxOKuIFz1sl2/jx4=
|
||||
google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||
google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
|
||||
google.golang.org/grpc v1.18.0 h1:IZl7mfBGfbhYx2p2rKRtYgDFw6SBz+kclmxYrCksPPA=
|
||||
google.golang.org/grpc v1.18.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/errgo.v1 v1.0.0/go.mod h1:CxwszS/Xz1C49Ucd2i6Zil5UToP1EmyrFhKaMVbg1mk=
|
||||
gopkg.in/errgo.v1 v1.0.1/go.mod h1:3NjfXwocQRYAPTq4/fzX+CwUhPRcR/azYRhj8G+LqMo=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/macaroon-bakery.v2 v2.0.1/go.mod h1:B4/T17l+ZWGwxFSZQmlBwp25x+og7OkhETfr3S9MbIA=
|
||||
gopkg.in/macaroon.v2 v2.0.0/go.mod h1:+I6LnTMkm/uV5ew/0nsulNjL16SK4+C8yDmRUzHR17I=
|
||||
gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
|
||||
gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
|
|
|
@ -39,9 +39,9 @@ func NewHDPrivateKeyFromBytes(rawKey, chainCode []byte, network *Network) (*HDPr
|
|||
|
||||
// NewHDPrivateKeyFromString creates an HD priv key from a base58-encoded string
|
||||
// If the parsed key is public, it returns an error
|
||||
func NewHDPrivateKeyFromString(str, path string) (*HDPrivateKey, error) {
|
||||
func NewHDPrivateKeyFromString(str, path string, network *Network) (*HDPrivateKey, error) {
|
||||
|
||||
key, network, err := keyFromString(str)
|
||||
key, _, err := keyFromString(str)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -18,9 +18,9 @@ type HDPublicKey struct {
|
|||
|
||||
// NewHDPublicKeyFromString creates an HD pub key from a base58-encoded string
|
||||
// If the parsed key is private, it returns an error
|
||||
func NewHDPublicKeyFromString(str, path string) (*HDPublicKey, error) {
|
||||
func NewHDPublicKeyFromString(str, path string, network *Network) (*HDPublicKey, error) {
|
||||
|
||||
key, network, err := keyFromString(str)
|
||||
key, _, err := keyFromString(str)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ func ParseInvoice(invoice string, network *Network) (*Invoice, error) {
|
|||
|
||||
if strings.HasPrefix(strings.ToLower(invoice), lightningScheme) {
|
||||
// Remove lightning scheme from rawInvoice
|
||||
invoice = invoice[len(lightningScheme):len(invoice)]
|
||||
invoice = invoice[len(lightningScheme):]
|
||||
}
|
||||
|
||||
parsedInvoice, err := zpay32.Decode(invoice, network.network)
|
||||
|
|
|
@ -64,7 +64,7 @@ func KeyEncrypt(key *HDPrivateKey, passphrase string) (string, error) {
|
|||
}
|
||||
|
||||
// KeyDecrypt decrypts a key encrypted with KeyEncrypt
|
||||
func KeyDecrypt(value, passphrase string) (*DecryptedKey, error) {
|
||||
func KeyDecrypt(value, passphrase string, network *Network) (*DecryptedKey, error) {
|
||||
|
||||
elements := strings.Split(value, seperator)
|
||||
|
||||
|
@ -126,7 +126,7 @@ func KeyDecrypt(value, passphrase string) (*DecryptedKey, error) {
|
|||
encodedPrivateKey := string(decryptedBytes[:])
|
||||
path := string(pathBytes[:])
|
||||
|
||||
privateKey, err := NewHDPrivateKeyFromString(encodedPrivateKey, path)
|
||||
privateKey, err := NewHDPrivateKeyFromString(encodedPrivateKey, path, network)
|
||||
if err != nil {
|
||||
return nil, errors.New("KeyCrypter: failed to decode pk: " + err.Error())
|
||||
}
|
||||
|
|
|
@ -25,19 +25,29 @@ type Outpoint interface {
|
|||
Amount() int64
|
||||
}
|
||||
|
||||
type InputSubmarineSwap interface {
|
||||
type InputSubmarineSwapV1 interface {
|
||||
RefundAddress() string
|
||||
PaymentHash256() []byte
|
||||
ServerPublicKey() []byte
|
||||
LockTime() int64
|
||||
}
|
||||
|
||||
type InputSubmarineSwapV2 interface {
|
||||
PaymentHash256() []byte
|
||||
UserPublicKey() []byte
|
||||
MuunPublicKey() []byte
|
||||
ServerPublicKey() []byte
|
||||
BlocksForExpiration() int64
|
||||
ServerSignature() []byte
|
||||
}
|
||||
|
||||
type Input interface {
|
||||
OutPoint() Outpoint
|
||||
Address() MuunAddress
|
||||
UserSignature() []byte
|
||||
MuunSignature() []byte
|
||||
SubmarineSwap() InputSubmarineSwap
|
||||
SubmarineSwapV1() InputSubmarineSwapV1
|
||||
SubmarineSwapV2() InputSubmarineSwapV2
|
||||
}
|
||||
|
||||
type PartiallySignedTransaction struct {
|
||||
|
@ -93,8 +103,12 @@ func (p *PartiallySignedTransaction) Sign(key *HDPrivateKey, muunKey *HDPublicKe
|
|||
txIn, err = addUserSignatureInputV2(input, i, p.tx, derivedKey, derivedMuunKey)
|
||||
case addressV3:
|
||||
txIn, err = addUserSignatureInputV3(input, i, p.tx, derivedKey, derivedMuunKey)
|
||||
case addressSubmarineSwap:
|
||||
txIn, err = addUserSignatureInputSubmarineSwap(input, i, p.tx, derivedKey, derivedMuunKey)
|
||||
case addressV4:
|
||||
txIn, err = addUserSignatureInputV4(input, i, p.tx, derivedKey, derivedMuunKey)
|
||||
case addressSubmarineSwapV1:
|
||||
txIn, err = addUserSignatureInputSubmarineSwapV1(input, i, p.tx, derivedKey, derivedMuunKey)
|
||||
case addressSubmarineSwapV2:
|
||||
txIn, err = addUserSignatureInputSubmarineSwapV2(input, i, p.tx, derivedKey, derivedMuunKey)
|
||||
default:
|
||||
return nil, errors.Errorf("cant sign transaction of version %v", input.Address().Version())
|
||||
}
|
||||
|
@ -141,8 +155,12 @@ func (p *PartiallySignedTransaction) MuunSignatureForInput(index int, userKey *H
|
|||
return signInputV2(input, index, p.tx, derivedUserKey, derivedMuunKey.PublicKey(), derivedMuunKey)
|
||||
case addressV3:
|
||||
return signInputV3(input, index, p.tx, derivedUserKey, derivedMuunKey.PublicKey(), derivedMuunKey)
|
||||
case addressSubmarineSwap:
|
||||
return nil, errors.New("cant sign arbitrary submarine swap inputs")
|
||||
case addressV4:
|
||||
return signInputV4(input, index, p.tx, derivedUserKey, derivedMuunKey.PublicKey(), derivedMuunKey)
|
||||
case addressSubmarineSwapV1:
|
||||
return nil, errors.New("cant sign arbitrary submarine swap v1 inputs")
|
||||
case addressSubmarineSwapV2:
|
||||
return nil, errors.New("cant sign arbitrary submarine swap v2 inputs")
|
||||
}
|
||||
|
||||
return nil, errors.New("unknown address scheme")
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package libwallet
|
||||
|
||||
import (
|
||||
hash "golang.org/x/crypto/ripemd160"
|
||||
hash "golang.org/x/crypto/ripemd160" //lint:ignore SA1019 using deprecated hash function for compatibility
|
||||
)
|
||||
|
||||
func ripemd160(data []byte) []byte {
|
||||
|
|
|
@ -8,6 +8,22 @@ import (
|
|||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func signNativeSegwitInput(input Input, index int, tx *wire.MsgTx, privateKey *HDPrivateKey, witnessScript []byte) ([]byte, error) {
|
||||
|
||||
privKey, err := privateKey.key.ECPrivKey()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to produce EC priv key for signing")
|
||||
}
|
||||
|
||||
sigHashes := txscript.NewTxSigHashes(tx)
|
||||
sig, err := txscript.RawTxInWitnessSignature(tx, sigHashes, index, input.OutPoint().Amount(), witnessScript, txscript.SigHashAll, privKey)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to sign V4 input")
|
||||
}
|
||||
|
||||
return sig, nil
|
||||
}
|
||||
|
||||
func createNonNativeSegwitRedeemScript(witnessScript []byte) ([]byte, error) {
|
||||
witnessScriptHash := sha256.Sum256(witnessScript)
|
||||
|
||||
|
|
|
@ -1,14 +1,7 @@
|
|||
package libwallet
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
|
||||
"github.com/btcsuite/btcd/txscript"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/btcsuite/btcutil"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/go-errors/errors"
|
||||
)
|
||||
|
||||
type SubmarineSwap interface {
|
||||
|
@ -26,190 +19,33 @@ type SubmarineSwapReceiver interface {
|
|||
}
|
||||
|
||||
type SubmarineSwapFundingOutput interface {
|
||||
ScriptVersion() int64
|
||||
|
||||
OutputAddress() string
|
||||
OutputAmount() int64
|
||||
ConfirmationsNeeded() int
|
||||
UserLockTime() int64
|
||||
UserRefundAddress() MuunAddress
|
||||
ServerPaymentHashInHex() string
|
||||
ServerPublicKeyInHex() string
|
||||
|
||||
UserLockTime() int64
|
||||
|
||||
// v1 only
|
||||
UserRefundAddress() MuunAddress
|
||||
|
||||
// v2 only
|
||||
ExpirationInBlocks() int64
|
||||
UserPublicKey() *HDPublicKey
|
||||
MuunPublicKey() *HDPublicKey
|
||||
}
|
||||
|
||||
func CreateAddressSubmarineSwap(publicKey *HDPublicKey) (MuunAddress, error) {
|
||||
pubkey, err := btcutil.NewAddressPubKey(publicKey.Raw(), publicKey.Network.network)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
func ValidateSubmarineSwap(rawInvoice string, userPublicKey *HDPublicKey, muunPublicKey *HDPublicKey, swap SubmarineSwap, originalExpirationInBlocks int64, network *Network) error {
|
||||
|
||||
switch AddressVersion(swap.FundingOutput().ScriptVersion()) {
|
||||
case addressSubmarineSwapV1:
|
||||
return ValidateSubmarineSwapV1(rawInvoice, userPublicKey, muunPublicKey, swap, network)
|
||||
case addressSubmarineSwapV2:
|
||||
return ValidateSubmarineSwapV2(rawInvoice, userPublicKey, muunPublicKey, swap, originalExpirationInBlocks, network)
|
||||
}
|
||||
|
||||
pubkeyHash := pubkey.AddressPubKeyHash()
|
||||
address := pubkeyHash.String()
|
||||
|
||||
return &muunAddress{address: address, version: addressSubmarineSwap, derivationPath: publicKey.Path}, nil
|
||||
}
|
||||
|
||||
func addUserSignatureInputSubmarineSwap(input Input, index int, tx *wire.MsgTx, privateKey *HDPrivateKey,
|
||||
muunKey *HDPublicKey) (*wire.TxIn, error) {
|
||||
|
||||
submarineSwap := input.SubmarineSwap()
|
||||
if submarineSwap == nil {
|
||||
return nil, errors.Errorf("submarine swap data is nil for ss input")
|
||||
}
|
||||
|
||||
witnessScript, err := createWitnessScriptSubmarineSwap(submarineSwap.RefundAddress(),
|
||||
submarineSwap.PaymentHash256(),
|
||||
submarineSwap.ServerPublicKey(),
|
||||
submarineSwap.LockTime(),
|
||||
privateKey.Network)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
redeemScript, err := createNonNativeSegwitRedeemScript(witnessScript)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to build reedem script for signing")
|
||||
}
|
||||
|
||||
sig, err := signNonNativeSegwitInput(input, index, tx, privateKey, redeemScript, witnessScript)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
txInput := tx.TxIn[index]
|
||||
txInput.Witness = wire.TxWitness{sig, privateKey.PublicKey().Raw(), witnessScript}
|
||||
|
||||
return txInput, nil
|
||||
}
|
||||
|
||||
func createRedeemScriptSubmarineSwapForUser(publicKey *HDPublicKey) {
|
||||
|
||||
}
|
||||
|
||||
func createWitnessScriptSubmarineSwap(refundAddress string, paymentHash []byte, swapServerPubKey []byte, lockTime int64, network *Network) ([]byte, error) {
|
||||
|
||||
// It turns out that the payment hash present in an invoice is just the SHA256 of the
|
||||
// payment preimage, so we still have to do a pass of RIPEMD160 before pushing it to the
|
||||
// script
|
||||
paymentHash160 := ripemd160(paymentHash)
|
||||
decodedRefundAddress, err := btcutil.DecodeAddress(refundAddress, network.network)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "refund address is invalid")
|
||||
}
|
||||
|
||||
refundAddressHash := decodedRefundAddress.ScriptAddress()
|
||||
|
||||
builder := txscript.NewScriptBuilder()
|
||||
builder.AddOp(txscript.OP_DUP)
|
||||
|
||||
// Condition to decide which branch to follow:
|
||||
builder.AddOp(txscript.OP_HASH160).
|
||||
AddData(paymentHash160).
|
||||
AddOp(txscript.OP_EQUAL)
|
||||
|
||||
// SubmarineSwap service spending script, for successful LN payments:
|
||||
builder.AddOp(txscript.OP_IF).
|
||||
AddOp(txscript.OP_DROP).
|
||||
AddData(swapServerPubKey)
|
||||
|
||||
// User spending script, for failed LN payments:
|
||||
builder.AddOp(txscript.OP_ELSE).
|
||||
AddInt64(lockTime).
|
||||
AddOp(txscript.OP_CHECKLOCKTIMEVERIFY).
|
||||
AddOp(txscript.OP_DROP).
|
||||
AddOp(txscript.OP_DUP).
|
||||
AddOp(txscript.OP_HASH160).
|
||||
AddData(refundAddressHash).
|
||||
AddOp(txscript.OP_EQUALVERIFY)
|
||||
|
||||
// Final verification for both branches:
|
||||
builder.AddOp(txscript.OP_ENDIF).
|
||||
AddOp(txscript.OP_CHECKSIG)
|
||||
|
||||
return builder.Script()
|
||||
}
|
||||
|
||||
func ValidateSubmarineSwap(rawInvoice string, userPublicKey *HDPublicKey, muunPublicKey *HDPublicKey, swap SubmarineSwap, network *Network) error {
|
||||
|
||||
invoice, err := ParseInvoice(rawInvoice, network)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to decode invoice")
|
||||
}
|
||||
|
||||
// Check the payment hash matches
|
||||
|
||||
serverPaymentHash, err := hex.DecodeString(swap.FundingOutput().ServerPaymentHashInHex())
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "server payment hash is not valid hex")
|
||||
}
|
||||
|
||||
if !bytes.Equal(invoice.PaymentHash[:], serverPaymentHash) {
|
||||
return errors.Errorf("payment hash doesn't match %v != %v", invoice.PaymentHash, swap.FundingOutput().ServerPaymentHashInHex())
|
||||
}
|
||||
|
||||
// TODO: check that timelock is acceptable
|
||||
|
||||
// Validate that the refund address is one we can derive
|
||||
|
||||
swapRefundAddress := swap.FundingOutput().UserRefundAddress()
|
||||
derivedUserKey, err := userPublicKey.DeriveTo(swapRefundAddress.DerivationPath())
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to derive user key")
|
||||
}
|
||||
derivedMuunKey, err := muunPublicKey.DeriveTo(swapRefundAddress.DerivationPath())
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to derive muun key")
|
||||
}
|
||||
|
||||
refundAddress, err := newMuunAddress(AddressVersion(swapRefundAddress.Version()), derivedUserKey, derivedMuunKey)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to generate refund address")
|
||||
}
|
||||
|
||||
if refundAddress.Address() != swapRefundAddress.Address() {
|
||||
return errors.Errorf("refund address doesn't match generated (%v != %v)", swapRefundAddress.Address(), refundAddress.Address())
|
||||
}
|
||||
|
||||
// Check the swap's witness script is a valid swap script
|
||||
|
||||
serverPubKey, err := hex.DecodeString(swap.FundingOutput().ServerPublicKeyInHex())
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "server pub key is not hex")
|
||||
}
|
||||
|
||||
witnessScript, err := createWitnessScriptSubmarineSwap(
|
||||
swapRefundAddress.Address(),
|
||||
serverPaymentHash,
|
||||
serverPubKey,
|
||||
swap.FundingOutput().UserLockTime(),
|
||||
network)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to compute witness script")
|
||||
}
|
||||
|
||||
redeemScript, err := createNonNativeSegwitRedeemScript(witnessScript)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to build redeem script")
|
||||
}
|
||||
|
||||
address, err := btcutil.NewAddressScriptHash(redeemScript, network.network)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to build address for swap script")
|
||||
}
|
||||
|
||||
if address.EncodeAddress() != swap.FundingOutput().OutputAddress() {
|
||||
return errors.Errorf("address for swap script mismatch (%v != %v)", address.EncodeAddress(), swap.FundingOutput().OutputAddress())
|
||||
}
|
||||
|
||||
if len(swap.PreimageInHex()) > 0 {
|
||||
preimage, err := hex.DecodeString(swap.PreimageInHex())
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "preimagehex is not actually hex 🤔")
|
||||
}
|
||||
|
||||
calculatedPaymentHash := sha256.Sum256(preimage)
|
||||
if !bytes.Equal(invoice.PaymentHash[:], calculatedPaymentHash[:]) {
|
||||
return errors.Errorf("payment hash doesn't match preimage (%v != hash(%v)", invoice.PaymentHash, swap.PreimageInHex())
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
return errors.Errorf("unknown swap version %v", swap.FundingOutput().ScriptVersion())
|
||||
}
|
||||
|
|
|
@ -0,0 +1,180 @@
|
|||
package libwallet
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
|
||||
"github.com/btcsuite/btcd/txscript"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/btcsuite/btcutil"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func addUserSignatureInputSubmarineSwapV1(input Input, index int, tx *wire.MsgTx, privateKey *HDPrivateKey,
|
||||
muunKey *HDPublicKey) (*wire.TxIn, error) {
|
||||
|
||||
submarineSwap := input.SubmarineSwapV1()
|
||||
if submarineSwap == nil {
|
||||
return nil, errors.Errorf("submarine swap data is nil for ss input")
|
||||
}
|
||||
|
||||
witnessScript, err := createWitnessScriptSubmarineSwapV1(submarineSwap.RefundAddress(),
|
||||
submarineSwap.PaymentHash256(),
|
||||
submarineSwap.ServerPublicKey(),
|
||||
submarineSwap.LockTime(),
|
||||
privateKey.Network)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
redeemScript, err := createNonNativeSegwitRedeemScript(witnessScript)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to build reedem script for signing")
|
||||
}
|
||||
|
||||
sig, err := signNonNativeSegwitInput(input, index, tx, privateKey, redeemScript, witnessScript)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
txInput := tx.TxIn[index]
|
||||
txInput.Witness = wire.TxWitness{sig, privateKey.PublicKey().Raw(), witnessScript}
|
||||
|
||||
return txInput, nil
|
||||
}
|
||||
|
||||
//lint:ignore U1000 unused function for consistency with other schemes
|
||||
func createRedeemScriptSubmarineSwapForUser(publicKey *HDPublicKey) {
|
||||
|
||||
}
|
||||
|
||||
func createWitnessScriptSubmarineSwapV1(refundAddress string, paymentHash []byte, swapServerPubKey []byte, lockTime int64, network *Network) ([]byte, error) {
|
||||
|
||||
// It turns out that the payment hash present in an invoice is just the SHA256 of the
|
||||
// payment preimage, so we still have to do a pass of RIPEMD160 before pushing it to the
|
||||
// script
|
||||
paymentHash160 := ripemd160(paymentHash)
|
||||
decodedRefundAddress, err := btcutil.DecodeAddress(refundAddress, network.network)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "refund address is invalid")
|
||||
}
|
||||
|
||||
refundAddressHash := decodedRefundAddress.ScriptAddress()
|
||||
|
||||
builder := txscript.NewScriptBuilder()
|
||||
builder.AddOp(txscript.OP_DUP)
|
||||
|
||||
// Condition to decide which branch to follow:
|
||||
builder.AddOp(txscript.OP_HASH160).
|
||||
AddData(paymentHash160).
|
||||
AddOp(txscript.OP_EQUAL)
|
||||
|
||||
// SubmarineSwap service spending script, for successful LN payments:
|
||||
builder.AddOp(txscript.OP_IF).
|
||||
AddOp(txscript.OP_DROP).
|
||||
AddData(swapServerPubKey)
|
||||
|
||||
// User spending script, for failed LN payments:
|
||||
builder.AddOp(txscript.OP_ELSE).
|
||||
AddInt64(lockTime).
|
||||
AddOp(txscript.OP_CHECKLOCKTIMEVERIFY).
|
||||
AddOp(txscript.OP_DROP).
|
||||
AddOp(txscript.OP_DUP).
|
||||
AddOp(txscript.OP_HASH160).
|
||||
AddData(refundAddressHash).
|
||||
AddOp(txscript.OP_EQUALVERIFY)
|
||||
|
||||
// Final verification for both branches:
|
||||
builder.AddOp(txscript.OP_ENDIF).
|
||||
AddOp(txscript.OP_CHECKSIG)
|
||||
|
||||
return builder.Script()
|
||||
}
|
||||
|
||||
func ValidateSubmarineSwapV1(rawInvoice string, userPublicKey *HDPublicKey, muunPublicKey *HDPublicKey, swap SubmarineSwap, network *Network) error {
|
||||
|
||||
invoice, err := ParseInvoice(rawInvoice, network)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to decode invoice")
|
||||
}
|
||||
|
||||
// Check the payment hash matches
|
||||
|
||||
serverPaymentHash, err := hex.DecodeString(swap.FundingOutput().ServerPaymentHashInHex())
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "server payment hash is not valid hex")
|
||||
}
|
||||
|
||||
if !bytes.Equal(invoice.PaymentHash[:], serverPaymentHash) {
|
||||
return errors.Errorf("payment hash doesn't match %v != %v", invoice.PaymentHash, swap.FundingOutput().ServerPaymentHashInHex())
|
||||
}
|
||||
|
||||
// TODO: check that timelock is acceptable
|
||||
|
||||
// Validate that the refund address is one we can derive
|
||||
|
||||
swapRefundAddress := swap.FundingOutput().UserRefundAddress()
|
||||
derivedUserKey, err := userPublicKey.DeriveTo(swapRefundAddress.DerivationPath())
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to derive user key")
|
||||
}
|
||||
derivedMuunKey, err := muunPublicKey.DeriveTo(swapRefundAddress.DerivationPath())
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to derive muun key")
|
||||
}
|
||||
|
||||
refundAddress, err := newMuunAddress(AddressVersion(swapRefundAddress.Version()), derivedUserKey, derivedMuunKey)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to generate refund address")
|
||||
}
|
||||
|
||||
if refundAddress.Address() != swapRefundAddress.Address() {
|
||||
return errors.Errorf("refund address doesn't match generated (%v != %v)", swapRefundAddress.Address(), refundAddress.Address())
|
||||
}
|
||||
|
||||
// Check the swap's witness script is a valid swap script
|
||||
|
||||
serverPubKey, err := hex.DecodeString(swap.FundingOutput().ServerPublicKeyInHex())
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "server pub key is not hex")
|
||||
}
|
||||
|
||||
witnessScript, err := createWitnessScriptSubmarineSwapV1(
|
||||
swapRefundAddress.Address(),
|
||||
serverPaymentHash,
|
||||
serverPubKey,
|
||||
swap.FundingOutput().UserLockTime(),
|
||||
network)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to compute witness script")
|
||||
}
|
||||
|
||||
redeemScript, err := createNonNativeSegwitRedeemScript(witnessScript)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to build redeem script")
|
||||
}
|
||||
|
||||
address, err := btcutil.NewAddressScriptHash(redeemScript, network.network)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to build address for swap script")
|
||||
}
|
||||
|
||||
if address.EncodeAddress() != swap.FundingOutput().OutputAddress() {
|
||||
return errors.Errorf("address for swap script mismatch (%v != %v)", address.EncodeAddress(), swap.FundingOutput().OutputAddress())
|
||||
}
|
||||
|
||||
if len(swap.PreimageInHex()) > 0 {
|
||||
preimage, err := hex.DecodeString(swap.PreimageInHex())
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "preimagehex is not actually hex 🤔")
|
||||
}
|
||||
|
||||
calculatedPaymentHash := sha256.Sum256(preimage)
|
||||
if !bytes.Equal(invoice.PaymentHash[:], calculatedPaymentHash[:]) {
|
||||
return errors.Errorf("payment hash doesn't match preimage (%v != hash(%v)", invoice.PaymentHash, swap.PreimageInHex())
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,231 @@
|
|||
package libwallet
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
|
||||
"github.com/btcsuite/btcd/txscript"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/btcsuite/btcutil"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func addUserSignatureInputSubmarineSwapV2(input Input, index int, tx *wire.MsgTx, privateKey *HDPrivateKey,
|
||||
muunKey *HDPublicKey) (*wire.TxIn, error) {
|
||||
|
||||
submarineSwap := input.SubmarineSwapV2()
|
||||
if submarineSwap == nil {
|
||||
return nil, errors.Errorf("submarine swap data is nil for ss input")
|
||||
}
|
||||
|
||||
if len(submarineSwap.ServerSignature()) == 0 {
|
||||
return nil, errors.Errorf("Swap server must provide signature")
|
||||
}
|
||||
|
||||
witnessScript, err := createWitnessScriptSubmarineSwapV2(
|
||||
submarineSwap.PaymentHash256(),
|
||||
submarineSwap.UserPublicKey(),
|
||||
submarineSwap.MuunPublicKey(),
|
||||
submarineSwap.ServerPublicKey(),
|
||||
submarineSwap.BlocksForExpiration())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sig, err := signNativeSegwitInput(input, index, tx, privateKey, witnessScript)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
txInput := tx.TxIn[index]
|
||||
txInput.Witness = wire.TxWitness{
|
||||
sig,
|
||||
submarineSwap.ServerSignature(),
|
||||
witnessScript,
|
||||
}
|
||||
|
||||
return txInput, nil
|
||||
}
|
||||
|
||||
func createWitnessScriptSubmarineSwapV2(paymentHash, userPubKey, muunPubKey, swapServerPubKey []byte, blocksForExpiration int64) ([]byte, error) {
|
||||
|
||||
// It turns out that the payment hash present in an invoice is just the SHA256 of the
|
||||
// payment preimage, so we still have to do a pass of RIPEMD160 before pushing it to the
|
||||
// script
|
||||
paymentHash160 := ripemd160(paymentHash)
|
||||
muunPublicKeyHash160 := btcutil.Hash160(muunPubKey)
|
||||
|
||||
// Equivalent miniscript (http://bitcoin.sipa.be/miniscript/):
|
||||
// or(
|
||||
// and(pk(userPublicKey), pk(swapServerPublicKey)),
|
||||
// or(
|
||||
// and(pk(swapServerPublicKey), hash160(swapPaymentHash160)),
|
||||
// and(pk(userPublicKey), and(pk(muunPublicKey), older(numBlocksForExpiration)))
|
||||
// )
|
||||
// )
|
||||
//
|
||||
// However, we differ in that the size of the script was heavily optimized for spending the
|
||||
// first two branches (the collaborative close and the unilateral close by swapper), which
|
||||
// are the most probable to be used.
|
||||
|
||||
builder := txscript.NewScriptBuilder().
|
||||
// Push the user public key to the second position of the stack
|
||||
AddData(userPubKey).
|
||||
AddOp(txscript.OP_SWAP).
|
||||
|
||||
// Check whether the first stack item was a valid swap server signature
|
||||
AddData(swapServerPubKey).
|
||||
AddOp(txscript.OP_CHECKSIG).
|
||||
|
||||
// If the swap server signature was correct
|
||||
AddOp(txscript.OP_IF).
|
||||
AddOp(txscript.OP_SWAP).
|
||||
|
||||
// Check whether the second stack item was the payment preimage
|
||||
AddOp(txscript.OP_DUP).
|
||||
AddOp(txscript.OP_HASH160).
|
||||
AddData(paymentHash160).
|
||||
AddOp(txscript.OP_EQUAL).
|
||||
|
||||
// If the preimage was correct
|
||||
AddOp(txscript.OP_IF).
|
||||
// We are done, leave just one true-ish item in the stack (there're 2
|
||||
// remaining items)
|
||||
AddOp(txscript.OP_DROP).
|
||||
|
||||
// If the second stack item wasn't a valid payment preimage
|
||||
AddOp(txscript.OP_ELSE).
|
||||
|
||||
// Validate that the second stack item was a valid user signature
|
||||
AddOp(txscript.OP_SWAP).
|
||||
AddOp(txscript.OP_CHECKSIG).
|
||||
AddOp(txscript.OP_ENDIF).
|
||||
|
||||
// If the first stack item wasn't a valid server signature
|
||||
AddOp(txscript.OP_ELSE).
|
||||
// Validate that the blockchain height is big enough
|
||||
AddInt64(blocksForExpiration).
|
||||
AddOp(txscript.OP_CHECKSEQUENCEVERIFY).
|
||||
AddOp(txscript.OP_DROP).
|
||||
|
||||
// Validate that the second stack item was a valid user signature
|
||||
AddOp(txscript.OP_CHECKSIGVERIFY).
|
||||
|
||||
// Validate that the third stack item was the muun public key
|
||||
AddOp(txscript.OP_DUP).
|
||||
AddOp(txscript.OP_HASH160).
|
||||
AddData(muunPublicKeyHash160).
|
||||
AddOp(txscript.OP_EQUALVERIFY).
|
||||
|
||||
// Notice that instead of directly pushing the public key here and checking the
|
||||
// signature P2PK-style, we pushed the hash of the public key, and require an
|
||||
// extra stack item with the actual public key, verifying the signature and
|
||||
// public key P2PKH-style.
|
||||
//
|
||||
// This trick reduces the on-chain footprint of the muun key from 33 bytes to
|
||||
// 20 bytes for the collaborative, and swap server's non-collaborative branches,
|
||||
// which are the most frequent ones.
|
||||
|
||||
// Validate that the fourth stack item was a valid server signature
|
||||
AddOp(txscript.OP_CHECKSIG).
|
||||
AddOp(txscript.OP_ENDIF)
|
||||
|
||||
return builder.Script()
|
||||
}
|
||||
|
||||
func ValidateSubmarineSwapV2(rawInvoice string, userPublicKey *HDPublicKey, muunPublicKey *HDPublicKey, swap SubmarineSwap, originalExpirationInBlocks int64, network *Network) error {
|
||||
|
||||
fundingOutput := swap.FundingOutput()
|
||||
|
||||
invoice, err := ParseInvoice(rawInvoice, network)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to decode invoice")
|
||||
}
|
||||
|
||||
// Check the payment hash matches
|
||||
|
||||
serverPaymentHash, err := hex.DecodeString(fundingOutput.ServerPaymentHashInHex())
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "server payment hash is not valid hex")
|
||||
}
|
||||
|
||||
if !bytes.Equal(invoice.PaymentHash[:], serverPaymentHash) {
|
||||
return errors.Errorf("payment hash doesn't match %v != %v", invoice.PaymentHash, fundingOutput.ServerPaymentHashInHex())
|
||||
}
|
||||
|
||||
destination, err := hex.DecodeString(swap.Receiver().PublicKey())
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "destination is not valid hex")
|
||||
}
|
||||
|
||||
if !bytes.Equal(invoice.Destination[:], destination) {
|
||||
return errors.Errorf("destination doesnt match %v != %v", invoice.Destination, swap.Receiver().PublicKey())
|
||||
}
|
||||
|
||||
if fundingOutput.ExpirationInBlocks() != originalExpirationInBlocks {
|
||||
return errors.Errorf("expiration in blocks doesnt match %v != %v", originalExpirationInBlocks, fundingOutput.ExpirationInBlocks())
|
||||
}
|
||||
|
||||
// Validate that we can derive the addresses involved
|
||||
derivationPath := fundingOutput.UserPublicKey().Path
|
||||
|
||||
derivedUserKey, err := userPublicKey.DeriveTo(derivationPath)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to derive user key")
|
||||
}
|
||||
|
||||
if !bytes.Equal(derivedUserKey.Raw(), fundingOutput.UserPublicKey().Raw()) {
|
||||
return errors.Errorf("user pub keys dont match %v != %v", derivedUserKey.String(), fundingOutput.UserPublicKey().String())
|
||||
}
|
||||
|
||||
derivedMuunKey, err := muunPublicKey.DeriveTo(derivationPath)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to derive muun key")
|
||||
}
|
||||
|
||||
if !bytes.Equal(derivedMuunKey.Raw(), fundingOutput.MuunPublicKey().Raw()) {
|
||||
return errors.Errorf("muun pub keys dont match %v != %v", derivedMuunKey.String(), fundingOutput.MuunPublicKey().String())
|
||||
}
|
||||
|
||||
// Check the swap's witness script is a valid swap script
|
||||
|
||||
serverPubKey, err := hex.DecodeString(swap.FundingOutput().ServerPublicKeyInHex())
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "server pub key is not hex")
|
||||
}
|
||||
|
||||
witnessScript, err := createWitnessScriptSubmarineSwapV2(
|
||||
serverPaymentHash,
|
||||
derivedUserKey.Raw(),
|
||||
derivedMuunKey.Raw(),
|
||||
serverPubKey,
|
||||
swap.FundingOutput().ExpirationInBlocks())
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to compute witness script")
|
||||
}
|
||||
|
||||
witnessScriptHash := sha256.Sum256(witnessScript)
|
||||
address, err := btcutil.NewAddressWitnessScriptHash(witnessScriptHash[:], network.network)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to build address for swap script")
|
||||
}
|
||||
|
||||
if address.EncodeAddress() != swap.FundingOutput().OutputAddress() {
|
||||
return errors.Errorf("address for swap script mismatch (%v != %v)", address.EncodeAddress(), swap.FundingOutput().OutputAddress())
|
||||
}
|
||||
|
||||
if len(swap.PreimageInHex()) > 0 {
|
||||
preimage, err := hex.DecodeString(swap.PreimageInHex())
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "preimagehex is not actually hex 🤔")
|
||||
}
|
||||
|
||||
calculatedPaymentHash := sha256.Sum256(preimage)
|
||||
if !bytes.Equal(invoice.PaymentHash[:], calculatedPaymentHash[:]) {
|
||||
return errors.Errorf("payment hash doesn't match preimage (%v != hash(%v)", invoice.PaymentHash, swap.PreimageInHex())
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -1,61 +0,0 @@
|
|||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
// mkasm_darwin.go generates assembly trampolines to call libSystem routines from Go.
|
||||
//This program must be run after mksyscall.go.
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func main() {
|
||||
in1, err := ioutil.ReadFile("syscall_darwin.go")
|
||||
if err != nil {
|
||||
log.Fatalf("can't open syscall_darwin.go: %s", err)
|
||||
}
|
||||
arch := os.Args[1]
|
||||
in2, err := ioutil.ReadFile(fmt.Sprintf("syscall_darwin_%s.go", arch))
|
||||
if err != nil {
|
||||
log.Fatalf("can't open syscall_darwin_%s.go: %s", arch, err)
|
||||
}
|
||||
in3, err := ioutil.ReadFile(fmt.Sprintf("zsyscall_darwin_%s.go", arch))
|
||||
if err != nil {
|
||||
log.Fatalf("can't open zsyscall_darwin_%s.go: %s", arch, err)
|
||||
}
|
||||
in := string(in1) + string(in2) + string(in3)
|
||||
|
||||
trampolines := map[string]bool{}
|
||||
|
||||
var out bytes.Buffer
|
||||
|
||||
fmt.Fprintf(&out, "// go run mkasm_darwin.go %s\n", strings.Join(os.Args[1:], " "))
|
||||
fmt.Fprintf(&out, "// Code generated by the command above; DO NOT EDIT.\n")
|
||||
fmt.Fprintf(&out, "\n")
|
||||
fmt.Fprintf(&out, "// +build go1.12\n")
|
||||
fmt.Fprintf(&out, "\n")
|
||||
fmt.Fprintf(&out, "#include \"textflag.h\"\n")
|
||||
for _, line := range strings.Split(in, "\n") {
|
||||
if !strings.HasPrefix(line, "func ") || !strings.HasSuffix(line, "_trampoline()") {
|
||||
continue
|
||||
}
|
||||
fn := line[5 : len(line)-13]
|
||||
if !trampolines[fn] {
|
||||
trampolines[fn] = true
|
||||
fmt.Fprintf(&out, "TEXT ·%s_trampoline(SB),NOSPLIT,$0-0\n", fn)
|
||||
fmt.Fprintf(&out, "\tJMP\t%s(SB)\n", fn)
|
||||
}
|
||||
}
|
||||
err = ioutil.WriteFile(fmt.Sprintf("zsyscall_darwin_%s.s", arch), out.Bytes(), 0644)
|
||||
if err != nil {
|
||||
log.Fatalf("can't write zsyscall_darwin_%s.s: %s", arch, err)
|
||||
}
|
||||
}
|
|
@ -1,122 +0,0 @@
|
|||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
// mkpost processes the output of cgo -godefs to
|
||||
// modify the generated types. It is used to clean up
|
||||
// the sys API in an architecture specific manner.
|
||||
//
|
||||
// mkpost is run after cgo -godefs; see README.md.
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"go/format"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Get the OS and architecture (using GOARCH_TARGET if it exists)
|
||||
goos := os.Getenv("GOOS")
|
||||
goarch := os.Getenv("GOARCH_TARGET")
|
||||
if goarch == "" {
|
||||
goarch = os.Getenv("GOARCH")
|
||||
}
|
||||
// Check that we are using the Docker-based build system if we should be.
|
||||
if goos == "linux" {
|
||||
if os.Getenv("GOLANG_SYS_BUILD") != "docker" {
|
||||
os.Stderr.WriteString("In the Docker-based build system, mkpost should not be called directly.\n")
|
||||
os.Stderr.WriteString("See README.md\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
b, err := ioutil.ReadAll(os.Stdin)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
if goos == "aix" {
|
||||
// Replace type of Atim, Mtim and Ctim by Timespec in Stat_t
|
||||
// to avoid having both StTimespec and Timespec.
|
||||
sttimespec := regexp.MustCompile(`_Ctype_struct_st_timespec`)
|
||||
b = sttimespec.ReplaceAll(b, []byte("Timespec"))
|
||||
}
|
||||
|
||||
// Intentionally export __val fields in Fsid and Sigset_t
|
||||
valRegex := regexp.MustCompile(`type (Fsid|Sigset_t) struct {(\s+)X__(bits|val)(\s+\S+\s+)}`)
|
||||
b = valRegex.ReplaceAll(b, []byte("type $1 struct {${2}Val$4}"))
|
||||
|
||||
// Intentionally export __fds_bits field in FdSet
|
||||
fdSetRegex := regexp.MustCompile(`type (FdSet) struct {(\s+)X__fds_bits(\s+\S+\s+)}`)
|
||||
b = fdSetRegex.ReplaceAll(b, []byte("type $1 struct {${2}Bits$3}"))
|
||||
|
||||
// If we have empty Ptrace structs, we should delete them. Only s390x emits
|
||||
// nonempty Ptrace structs.
|
||||
ptraceRexexp := regexp.MustCompile(`type Ptrace((Psw|Fpregs|Per) struct {\s*})`)
|
||||
b = ptraceRexexp.ReplaceAll(b, nil)
|
||||
|
||||
// Replace the control_regs union with a blank identifier for now.
|
||||
controlRegsRegex := regexp.MustCompile(`(Control_regs)\s+\[0\]uint64`)
|
||||
b = controlRegsRegex.ReplaceAll(b, []byte("_ [0]uint64"))
|
||||
|
||||
// Remove fields that are added by glibc
|
||||
// Note that this is unstable as the identifers are private.
|
||||
removeFieldsRegex := regexp.MustCompile(`X__glibc\S*`)
|
||||
b = removeFieldsRegex.ReplaceAll(b, []byte("_"))
|
||||
|
||||
// Convert [65]int8 to [65]byte in Utsname members to simplify
|
||||
// conversion to string; see golang.org/issue/20753
|
||||
convertUtsnameRegex := regexp.MustCompile(`((Sys|Node|Domain)name|Release|Version|Machine)(\s+)\[(\d+)\]u?int8`)
|
||||
b = convertUtsnameRegex.ReplaceAll(b, []byte("$1$3[$4]byte"))
|
||||
|
||||
// Convert [1024]int8 to [1024]byte in Ptmget members
|
||||
convertPtmget := regexp.MustCompile(`([SC]n)(\s+)\[(\d+)\]u?int8`)
|
||||
b = convertPtmget.ReplaceAll(b, []byte("$1[$3]byte"))
|
||||
|
||||
// Remove spare fields (e.g. in Statx_t)
|
||||
spareFieldsRegex := regexp.MustCompile(`X__spare\S*`)
|
||||
b = spareFieldsRegex.ReplaceAll(b, []byte("_"))
|
||||
|
||||
// Remove cgo padding fields
|
||||
removePaddingFieldsRegex := regexp.MustCompile(`Pad_cgo_\d+`)
|
||||
b = removePaddingFieldsRegex.ReplaceAll(b, []byte("_"))
|
||||
|
||||
// Remove padding, hidden, or unused fields
|
||||
removeFieldsRegex = regexp.MustCompile(`\b(X_\S+|Padding)`)
|
||||
b = removeFieldsRegex.ReplaceAll(b, []byte("_"))
|
||||
|
||||
// Remove the first line of warning from cgo
|
||||
b = b[bytes.IndexByte(b, '\n')+1:]
|
||||
// Modify the command in the header to include:
|
||||
// mkpost, our own warning, and a build tag.
|
||||
replacement := fmt.Sprintf(`$1 | go run mkpost.go
|
||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
||||
|
||||
// +build %s,%s`, goarch, goos)
|
||||
cgoCommandRegex := regexp.MustCompile(`(cgo -godefs .*)`)
|
||||
b = cgoCommandRegex.ReplaceAll(b, []byte(replacement))
|
||||
|
||||
// Rename Stat_t time fields
|
||||
if goos == "freebsd" && goarch == "386" {
|
||||
// Hide Stat_t.[AMCB]tim_ext fields
|
||||
renameStatTimeExtFieldsRegex := regexp.MustCompile(`[AMCB]tim_ext`)
|
||||
b = renameStatTimeExtFieldsRegex.ReplaceAll(b, []byte("_"))
|
||||
}
|
||||
renameStatTimeFieldsRegex := regexp.MustCompile(`([AMCB])(?:irth)?time?(?:spec)?\s+(Timespec|StTimespec)`)
|
||||
b = renameStatTimeFieldsRegex.ReplaceAll(b, []byte("${1}tim ${2}"))
|
||||
|
||||
// gofmt
|
||||
b, err = format.Source(b)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
os.Stdout.Write(b)
|
||||
}
|
|
@ -1,407 +0,0 @@
|
|||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
/*
|
||||
This program reads a file containing function prototypes
|
||||
(like syscall_darwin.go) and generates system call bodies.
|
||||
The prototypes are marked by lines beginning with "//sys"
|
||||
and read like func declarations if //sys is replaced by func, but:
|
||||
* The parameter lists must give a name for each argument.
|
||||
This includes return parameters.
|
||||
* The parameter lists must give a type for each argument:
|
||||
the (x, y, z int) shorthand is not allowed.
|
||||
* If the return parameter is an error number, it must be named errno.
|
||||
|
||||
A line beginning with //sysnb is like //sys, except that the
|
||||
goroutine will not be suspended during the execution of the system
|
||||
call. This must only be used for system calls which can never
|
||||
block, as otherwise the system call could cause all goroutines to
|
||||
hang.
|
||||
*/
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
b32 = flag.Bool("b32", false, "32bit big-endian")
|
||||
l32 = flag.Bool("l32", false, "32bit little-endian")
|
||||
plan9 = flag.Bool("plan9", false, "plan9")
|
||||
openbsd = flag.Bool("openbsd", false, "openbsd")
|
||||
netbsd = flag.Bool("netbsd", false, "netbsd")
|
||||
dragonfly = flag.Bool("dragonfly", false, "dragonfly")
|
||||
arm = flag.Bool("arm", false, "arm") // 64-bit value should use (even, odd)-pair
|
||||
tags = flag.String("tags", "", "build tags")
|
||||
filename = flag.String("output", "", "output file name (standard output if omitted)")
|
||||
)
|
||||
|
||||
// cmdLine returns this programs's commandline arguments
|
||||
func cmdLine() string {
|
||||
return "go run mksyscall.go " + strings.Join(os.Args[1:], " ")
|
||||
}
|
||||
|
||||
// buildTags returns build tags
|
||||
func buildTags() string {
|
||||
return *tags
|
||||
}
|
||||
|
||||
// Param is function parameter
|
||||
type Param struct {
|
||||
Name string
|
||||
Type string
|
||||
}
|
||||
|
||||
// usage prints the program usage
|
||||
func usage() {
|
||||
fmt.Fprintf(os.Stderr, "usage: go run mksyscall.go [-b32 | -l32] [-tags x,y] [file ...]\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// parseParamList parses parameter list and returns a slice of parameters
|
||||
func parseParamList(list string) []string {
|
||||
list = strings.TrimSpace(list)
|
||||
if list == "" {
|
||||
return []string{}
|
||||
}
|
||||
return regexp.MustCompile(`\s*,\s*`).Split(list, -1)
|
||||
}
|
||||
|
||||
// parseParam splits a parameter into name and type
|
||||
func parseParam(p string) Param {
|
||||
ps := regexp.MustCompile(`^(\S*) (\S*)$`).FindStringSubmatch(p)
|
||||
if ps == nil {
|
||||
fmt.Fprintf(os.Stderr, "malformed parameter: %s\n", p)
|
||||
os.Exit(1)
|
||||
}
|
||||
return Param{ps[1], ps[2]}
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Get the OS and architecture (using GOARCH_TARGET if it exists)
|
||||
goos := os.Getenv("GOOS")
|
||||
if goos == "" {
|
||||
fmt.Fprintln(os.Stderr, "GOOS not defined in environment")
|
||||
os.Exit(1)
|
||||
}
|
||||
goarch := os.Getenv("GOARCH_TARGET")
|
||||
if goarch == "" {
|
||||
goarch = os.Getenv("GOARCH")
|
||||
}
|
||||
|
||||
// Check that we are using the Docker-based build system if we should
|
||||
if goos == "linux" {
|
||||
if os.Getenv("GOLANG_SYS_BUILD") != "docker" {
|
||||
fmt.Fprintf(os.Stderr, "In the Docker-based build system, mksyscall should not be called directly.\n")
|
||||
fmt.Fprintf(os.Stderr, "See README.md\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
flag.Usage = usage
|
||||
flag.Parse()
|
||||
if len(flag.Args()) <= 0 {
|
||||
fmt.Fprintf(os.Stderr, "no files to parse provided\n")
|
||||
usage()
|
||||
}
|
||||
|
||||
endianness := ""
|
||||
if *b32 {
|
||||
endianness = "big-endian"
|
||||
} else if *l32 {
|
||||
endianness = "little-endian"
|
||||
}
|
||||
|
||||
libc := false
|
||||
if goos == "darwin" && strings.Contains(buildTags(), ",go1.12") {
|
||||
libc = true
|
||||
}
|
||||
trampolines := map[string]bool{}
|
||||
|
||||
text := ""
|
||||
for _, path := range flag.Args() {
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
s := bufio.NewScanner(file)
|
||||
for s.Scan() {
|
||||
t := s.Text()
|
||||
t = strings.TrimSpace(t)
|
||||
t = regexp.MustCompile(`\s+`).ReplaceAllString(t, ` `)
|
||||
nonblock := regexp.MustCompile(`^\/\/sysnb `).FindStringSubmatch(t)
|
||||
if regexp.MustCompile(`^\/\/sys `).FindStringSubmatch(t) == nil && nonblock == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// Line must be of the form
|
||||
// func Open(path string, mode int, perm int) (fd int, errno error)
|
||||
// Split into name, in params, out params.
|
||||
f := regexp.MustCompile(`^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*((?i)SYS_[A-Z0-9_]+))?$`).FindStringSubmatch(t)
|
||||
if f == nil {
|
||||
fmt.Fprintf(os.Stderr, "%s:%s\nmalformed //sys declaration\n", path, t)
|
||||
os.Exit(1)
|
||||
}
|
||||
funct, inps, outps, sysname := f[2], f[3], f[4], f[5]
|
||||
|
||||
// ClockGettime doesn't have a syscall number on Darwin, only generate libc wrappers.
|
||||
if goos == "darwin" && !libc && funct == "ClockGettime" {
|
||||
continue
|
||||
}
|
||||
|
||||
// Split argument lists on comma.
|
||||
in := parseParamList(inps)
|
||||
out := parseParamList(outps)
|
||||
|
||||
// Try in vain to keep people from editing this file.
|
||||
// The theory is that they jump into the middle of the file
|
||||
// without reading the header.
|
||||
text += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n"
|
||||
|
||||
// Go function header.
|
||||
outDecl := ""
|
||||
if len(out) > 0 {
|
||||
outDecl = fmt.Sprintf(" (%s)", strings.Join(out, ", "))
|
||||
}
|
||||
text += fmt.Sprintf("func %s(%s)%s {\n", funct, strings.Join(in, ", "), outDecl)
|
||||
|
||||
// Check if err return available
|
||||
errvar := ""
|
||||
for _, param := range out {
|
||||
p := parseParam(param)
|
||||
if p.Type == "error" {
|
||||
errvar = p.Name
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Prepare arguments to Syscall.
|
||||
var args []string
|
||||
n := 0
|
||||
for _, param := range in {
|
||||
p := parseParam(param)
|
||||
if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil {
|
||||
args = append(args, "uintptr(unsafe.Pointer("+p.Name+"))")
|
||||
} else if p.Type == "string" && errvar != "" {
|
||||
text += fmt.Sprintf("\tvar _p%d *byte\n", n)
|
||||
text += fmt.Sprintf("\t_p%d, %s = BytePtrFromString(%s)\n", n, errvar, p.Name)
|
||||
text += fmt.Sprintf("\tif %s != nil {\n\t\treturn\n\t}\n", errvar)
|
||||
args = append(args, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n))
|
||||
n++
|
||||
} else if p.Type == "string" {
|
||||
fmt.Fprintf(os.Stderr, path+":"+funct+" uses string arguments, but has no error return\n")
|
||||
text += fmt.Sprintf("\tvar _p%d *byte\n", n)
|
||||
text += fmt.Sprintf("\t_p%d, _ = BytePtrFromString(%s)\n", n, p.Name)
|
||||
args = append(args, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n))
|
||||
n++
|
||||
} else if regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type) != nil {
|
||||
// Convert slice into pointer, length.
|
||||
// Have to be careful not to take address of &a[0] if len == 0:
|
||||
// pass dummy pointer in that case.
|
||||
// Used to pass nil, but some OSes or simulators reject write(fd, nil, 0).
|
||||
text += fmt.Sprintf("\tvar _p%d unsafe.Pointer\n", n)
|
||||
text += fmt.Sprintf("\tif len(%s) > 0 {\n\t\t_p%d = unsafe.Pointer(&%s[0])\n\t}", p.Name, n, p.Name)
|
||||
text += fmt.Sprintf(" else {\n\t\t_p%d = unsafe.Pointer(&_zero)\n\t}\n", n)
|
||||
args = append(args, fmt.Sprintf("uintptr(_p%d)", n), fmt.Sprintf("uintptr(len(%s))", p.Name))
|
||||
n++
|
||||
} else if p.Type == "int64" && (*openbsd || *netbsd) {
|
||||
args = append(args, "0")
|
||||
if endianness == "big-endian" {
|
||||
args = append(args, fmt.Sprintf("uintptr(%s>>32)", p.Name), fmt.Sprintf("uintptr(%s)", p.Name))
|
||||
} else if endianness == "little-endian" {
|
||||
args = append(args, fmt.Sprintf("uintptr(%s)", p.Name), fmt.Sprintf("uintptr(%s>>32)", p.Name))
|
||||
} else {
|
||||
args = append(args, fmt.Sprintf("uintptr(%s)", p.Name))
|
||||
}
|
||||
} else if p.Type == "int64" && *dragonfly {
|
||||
if regexp.MustCompile(`^(?i)extp(read|write)`).FindStringSubmatch(funct) == nil {
|
||||
args = append(args, "0")
|
||||
}
|
||||
if endianness == "big-endian" {
|
||||
args = append(args, fmt.Sprintf("uintptr(%s>>32)", p.Name), fmt.Sprintf("uintptr(%s)", p.Name))
|
||||
} else if endianness == "little-endian" {
|
||||
args = append(args, fmt.Sprintf("uintptr(%s)", p.Name), fmt.Sprintf("uintptr(%s>>32)", p.Name))
|
||||
} else {
|
||||
args = append(args, fmt.Sprintf("uintptr(%s)", p.Name))
|
||||
}
|
||||
} else if (p.Type == "int64" || p.Type == "uint64") && endianness != "" {
|
||||
if len(args)%2 == 1 && *arm {
|
||||
// arm abi specifies 64-bit argument uses
|
||||
// (even, odd) pair
|
||||
args = append(args, "0")
|
||||
}
|
||||
if endianness == "big-endian" {
|
||||
args = append(args, fmt.Sprintf("uintptr(%s>>32)", p.Name), fmt.Sprintf("uintptr(%s)", p.Name))
|
||||
} else {
|
||||
args = append(args, fmt.Sprintf("uintptr(%s)", p.Name), fmt.Sprintf("uintptr(%s>>32)", p.Name))
|
||||
}
|
||||
} else {
|
||||
args = append(args, fmt.Sprintf("uintptr(%s)", p.Name))
|
||||
}
|
||||
}
|
||||
|
||||
// Determine which form to use; pad args with zeros.
|
||||
asm := "Syscall"
|
||||
if nonblock != nil {
|
||||
if errvar == "" && goos == "linux" {
|
||||
asm = "RawSyscallNoError"
|
||||
} else {
|
||||
asm = "RawSyscall"
|
||||
}
|
||||
} else {
|
||||
if errvar == "" && goos == "linux" {
|
||||
asm = "SyscallNoError"
|
||||
}
|
||||
}
|
||||
if len(args) <= 3 {
|
||||
for len(args) < 3 {
|
||||
args = append(args, "0")
|
||||
}
|
||||
} else if len(args) <= 6 {
|
||||
asm += "6"
|
||||
for len(args) < 6 {
|
||||
args = append(args, "0")
|
||||
}
|
||||
} else if len(args) <= 9 {
|
||||
asm += "9"
|
||||
for len(args) < 9 {
|
||||
args = append(args, "0")
|
||||
}
|
||||
} else {
|
||||
fmt.Fprintf(os.Stderr, "%s:%s too many arguments to system call\n", path, funct)
|
||||
}
|
||||
|
||||
// System call number.
|
||||
if sysname == "" {
|
||||
sysname = "SYS_" + funct
|
||||
sysname = regexp.MustCompile(`([a-z])([A-Z])`).ReplaceAllString(sysname, `${1}_$2`)
|
||||
sysname = strings.ToUpper(sysname)
|
||||
}
|
||||
|
||||
var libcFn string
|
||||
if libc {
|
||||
asm = "syscall_" + strings.ToLower(asm[:1]) + asm[1:] // internal syscall call
|
||||
sysname = strings.TrimPrefix(sysname, "SYS_") // remove SYS_
|
||||
sysname = strings.ToLower(sysname) // lowercase
|
||||
if sysname == "getdirentries64" {
|
||||
// Special case - libSystem name and
|
||||
// raw syscall name don't match.
|
||||
sysname = "__getdirentries64"
|
||||
}
|
||||
libcFn = sysname
|
||||
sysname = "funcPC(libc_" + sysname + "_trampoline)"
|
||||
}
|
||||
|
||||
// Actual call.
|
||||
arglist := strings.Join(args, ", ")
|
||||
call := fmt.Sprintf("%s(%s, %s)", asm, sysname, arglist)
|
||||
|
||||
// Assign return values.
|
||||
body := ""
|
||||
ret := []string{"_", "_", "_"}
|
||||
doErrno := false
|
||||
for i := 0; i < len(out); i++ {
|
||||
p := parseParam(out[i])
|
||||
reg := ""
|
||||
if p.Name == "err" && !*plan9 {
|
||||
reg = "e1"
|
||||
ret[2] = reg
|
||||
doErrno = true
|
||||
} else if p.Name == "err" && *plan9 {
|
||||
ret[0] = "r0"
|
||||
ret[2] = "e1"
|
||||
break
|
||||
} else {
|
||||
reg = fmt.Sprintf("r%d", i)
|
||||
ret[i] = reg
|
||||
}
|
||||
if p.Type == "bool" {
|
||||
reg = fmt.Sprintf("%s != 0", reg)
|
||||
}
|
||||
if p.Type == "int64" && endianness != "" {
|
||||
// 64-bit number in r1:r0 or r0:r1.
|
||||
if i+2 > len(out) {
|
||||
fmt.Fprintf(os.Stderr, "%s:%s not enough registers for int64 return\n", path, funct)
|
||||
}
|
||||
if endianness == "big-endian" {
|
||||
reg = fmt.Sprintf("int64(r%d)<<32 | int64(r%d)", i, i+1)
|
||||
} else {
|
||||
reg = fmt.Sprintf("int64(r%d)<<32 | int64(r%d)", i+1, i)
|
||||
}
|
||||
ret[i] = fmt.Sprintf("r%d", i)
|
||||
ret[i+1] = fmt.Sprintf("r%d", i+1)
|
||||
}
|
||||
if reg != "e1" || *plan9 {
|
||||
body += fmt.Sprintf("\t%s = %s(%s)\n", p.Name, p.Type, reg)
|
||||
}
|
||||
}
|
||||
if ret[0] == "_" && ret[1] == "_" && ret[2] == "_" {
|
||||
text += fmt.Sprintf("\t%s\n", call)
|
||||
} else {
|
||||
if errvar == "" && goos == "linux" {
|
||||
// raw syscall without error on Linux, see golang.org/issue/22924
|
||||
text += fmt.Sprintf("\t%s, %s := %s\n", ret[0], ret[1], call)
|
||||
} else {
|
||||
text += fmt.Sprintf("\t%s, %s, %s := %s\n", ret[0], ret[1], ret[2], call)
|
||||
}
|
||||
}
|
||||
text += body
|
||||
|
||||
if *plan9 && ret[2] == "e1" {
|
||||
text += "\tif int32(r0) == -1 {\n"
|
||||
text += "\t\terr = e1\n"
|
||||
text += "\t}\n"
|
||||
} else if doErrno {
|
||||
text += "\tif e1 != 0 {\n"
|
||||
text += "\t\terr = errnoErr(e1)\n"
|
||||
text += "\t}\n"
|
||||
}
|
||||
text += "\treturn\n"
|
||||
text += "}\n\n"
|
||||
|
||||
if libc && !trampolines[libcFn] {
|
||||
// some system calls share a trampoline, like read and readlen.
|
||||
trampolines[libcFn] = true
|
||||
// Declare assembly trampoline.
|
||||
text += fmt.Sprintf("func libc_%s_trampoline()\n", libcFn)
|
||||
// Assembly trampoline calls the libc_* function, which this magic
|
||||
// redirects to use the function from libSystem.
|
||||
text += fmt.Sprintf("//go:linkname libc_%s libc_%s\n", libcFn, libcFn)
|
||||
text += fmt.Sprintf("//go:cgo_import_dynamic libc_%s %s \"/usr/lib/libSystem.B.dylib\"\n", libcFn, libcFn)
|
||||
text += "\n"
|
||||
}
|
||||
}
|
||||
if err := s.Err(); err != nil {
|
||||
fmt.Fprintf(os.Stderr, err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
file.Close()
|
||||
}
|
||||
fmt.Printf(srcTemplate, cmdLine(), buildTags(), text)
|
||||
}
|
||||
|
||||
const srcTemplate = `// %s
|
||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
||||
|
||||
// +build %s
|
||||
|
||||
package unix
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
var _ syscall.Errno
|
||||
|
||||
%s
|
||||
`
|
|
@ -1,415 +0,0 @@
|
|||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
/*
|
||||
This program reads a file containing function prototypes
|
||||
(like syscall_aix.go) and generates system call bodies.
|
||||
The prototypes are marked by lines beginning with "//sys"
|
||||
and read like func declarations if //sys is replaced by func, but:
|
||||
* The parameter lists must give a name for each argument.
|
||||
This includes return parameters.
|
||||
* The parameter lists must give a type for each argument:
|
||||
the (x, y, z int) shorthand is not allowed.
|
||||
* If the return parameter is an error number, it must be named err.
|
||||
* If go func name needs to be different than its libc name,
|
||||
* or the function is not in libc, name could be specified
|
||||
* at the end, after "=" sign, like
|
||||
//sys getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (err error) = libsocket.getsockopt
|
||||
*/
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
b32 = flag.Bool("b32", false, "32bit big-endian")
|
||||
l32 = flag.Bool("l32", false, "32bit little-endian")
|
||||
aix = flag.Bool("aix", false, "aix")
|
||||
tags = flag.String("tags", "", "build tags")
|
||||
)
|
||||
|
||||
// cmdLine returns this programs's commandline arguments
|
||||
func cmdLine() string {
|
||||
return "go run mksyscall_aix_ppc.go " + strings.Join(os.Args[1:], " ")
|
||||
}
|
||||
|
||||
// buildTags returns build tags
|
||||
func buildTags() string {
|
||||
return *tags
|
||||
}
|
||||
|
||||
// Param is function parameter
|
||||
type Param struct {
|
||||
Name string
|
||||
Type string
|
||||
}
|
||||
|
||||
// usage prints the program usage
|
||||
func usage() {
|
||||
fmt.Fprintf(os.Stderr, "usage: go run mksyscall_aix_ppc.go [-b32 | -l32] [-tags x,y] [file ...]\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// parseParamList parses parameter list and returns a slice of parameters
|
||||
func parseParamList(list string) []string {
|
||||
list = strings.TrimSpace(list)
|
||||
if list == "" {
|
||||
return []string{}
|
||||
}
|
||||
return regexp.MustCompile(`\s*,\s*`).Split(list, -1)
|
||||
}
|
||||
|
||||
// parseParam splits a parameter into name and type
|
||||
func parseParam(p string) Param {
|
||||
ps := regexp.MustCompile(`^(\S*) (\S*)$`).FindStringSubmatch(p)
|
||||
if ps == nil {
|
||||
fmt.Fprintf(os.Stderr, "malformed parameter: %s\n", p)
|
||||
os.Exit(1)
|
||||
}
|
||||
return Param{ps[1], ps[2]}
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Usage = usage
|
||||
flag.Parse()
|
||||
if len(flag.Args()) <= 0 {
|
||||
fmt.Fprintf(os.Stderr, "no files to parse provided\n")
|
||||
usage()
|
||||
}
|
||||
|
||||
endianness := ""
|
||||
if *b32 {
|
||||
endianness = "big-endian"
|
||||
} else if *l32 {
|
||||
endianness = "little-endian"
|
||||
}
|
||||
|
||||
pack := ""
|
||||
text := ""
|
||||
cExtern := "/*\n#include <stdint.h>\n#include <stddef.h>\n"
|
||||
for _, path := range flag.Args() {
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
s := bufio.NewScanner(file)
|
||||
for s.Scan() {
|
||||
t := s.Text()
|
||||
t = strings.TrimSpace(t)
|
||||
t = regexp.MustCompile(`\s+`).ReplaceAllString(t, ` `)
|
||||
if p := regexp.MustCompile(`^package (\S+)$`).FindStringSubmatch(t); p != nil && pack == "" {
|
||||
pack = p[1]
|
||||
}
|
||||
nonblock := regexp.MustCompile(`^\/\/sysnb `).FindStringSubmatch(t)
|
||||
if regexp.MustCompile(`^\/\/sys `).FindStringSubmatch(t) == nil && nonblock == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// Line must be of the form
|
||||
// func Open(path string, mode int, perm int) (fd int, err error)
|
||||
// Split into name, in params, out params.
|
||||
f := regexp.MustCompile(`^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*(?:(\w*)\.)?(\w*))?$`).FindStringSubmatch(t)
|
||||
if f == nil {
|
||||
fmt.Fprintf(os.Stderr, "%s:%s\nmalformed //sys declaration\n", path, t)
|
||||
os.Exit(1)
|
||||
}
|
||||
funct, inps, outps, modname, sysname := f[2], f[3], f[4], f[5], f[6]
|
||||
|
||||
// Split argument lists on comma.
|
||||
in := parseParamList(inps)
|
||||
out := parseParamList(outps)
|
||||
|
||||
inps = strings.Join(in, ", ")
|
||||
outps = strings.Join(out, ", ")
|
||||
|
||||
// Try in vain to keep people from editing this file.
|
||||
// The theory is that they jump into the middle of the file
|
||||
// without reading the header.
|
||||
text += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n"
|
||||
|
||||
// Check if value return, err return available
|
||||
errvar := ""
|
||||
retvar := ""
|
||||
rettype := ""
|
||||
for _, param := range out {
|
||||
p := parseParam(param)
|
||||
if p.Type == "error" {
|
||||
errvar = p.Name
|
||||
} else {
|
||||
retvar = p.Name
|
||||
rettype = p.Type
|
||||
}
|
||||
}
|
||||
|
||||
// System call name.
|
||||
if sysname == "" {
|
||||
sysname = funct
|
||||
}
|
||||
sysname = regexp.MustCompile(`([a-z])([A-Z])`).ReplaceAllString(sysname, `${1}_$2`)
|
||||
sysname = strings.ToLower(sysname) // All libc functions are lowercase.
|
||||
|
||||
cRettype := ""
|
||||
if rettype == "unsafe.Pointer" {
|
||||
cRettype = "uintptr_t"
|
||||
} else if rettype == "uintptr" {
|
||||
cRettype = "uintptr_t"
|
||||
} else if regexp.MustCompile(`^_`).FindStringSubmatch(rettype) != nil {
|
||||
cRettype = "uintptr_t"
|
||||
} else if rettype == "int" {
|
||||
cRettype = "int"
|
||||
} else if rettype == "int32" {
|
||||
cRettype = "int"
|
||||
} else if rettype == "int64" {
|
||||
cRettype = "long long"
|
||||
} else if rettype == "uint32" {
|
||||
cRettype = "unsigned int"
|
||||
} else if rettype == "uint64" {
|
||||
cRettype = "unsigned long long"
|
||||
} else {
|
||||
cRettype = "int"
|
||||
}
|
||||
if sysname == "exit" {
|
||||
cRettype = "void"
|
||||
}
|
||||
|
||||
// Change p.Types to c
|
||||
var cIn []string
|
||||
for _, param := range in {
|
||||
p := parseParam(param)
|
||||
if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil {
|
||||
cIn = append(cIn, "uintptr_t")
|
||||
} else if p.Type == "string" {
|
||||
cIn = append(cIn, "uintptr_t")
|
||||
} else if regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type) != nil {
|
||||
cIn = append(cIn, "uintptr_t", "size_t")
|
||||
} else if p.Type == "unsafe.Pointer" {
|
||||
cIn = append(cIn, "uintptr_t")
|
||||
} else if p.Type == "uintptr" {
|
||||
cIn = append(cIn, "uintptr_t")
|
||||
} else if regexp.MustCompile(`^_`).FindStringSubmatch(p.Type) != nil {
|
||||
cIn = append(cIn, "uintptr_t")
|
||||
} else if p.Type == "int" {
|
||||
cIn = append(cIn, "int")
|
||||
} else if p.Type == "int32" {
|
||||
cIn = append(cIn, "int")
|
||||
} else if p.Type == "int64" {
|
||||
cIn = append(cIn, "long long")
|
||||
} else if p.Type == "uint32" {
|
||||
cIn = append(cIn, "unsigned int")
|
||||
} else if p.Type == "uint64" {
|
||||
cIn = append(cIn, "unsigned long long")
|
||||
} else {
|
||||
cIn = append(cIn, "int")
|
||||
}
|
||||
}
|
||||
|
||||
if funct != "fcntl" && funct != "FcntlInt" && funct != "readlen" && funct != "writelen" {
|
||||
if sysname == "select" {
|
||||
// select is a keyword of Go. Its name is
|
||||
// changed to c_select.
|
||||
cExtern += "#define c_select select\n"
|
||||
}
|
||||
// Imports of system calls from libc
|
||||
cExtern += fmt.Sprintf("%s %s", cRettype, sysname)
|
||||
cIn := strings.Join(cIn, ", ")
|
||||
cExtern += fmt.Sprintf("(%s);\n", cIn)
|
||||
}
|
||||
|
||||
// So file name.
|
||||
if *aix {
|
||||
if modname == "" {
|
||||
modname = "libc.a/shr_64.o"
|
||||
} else {
|
||||
fmt.Fprintf(os.Stderr, "%s: only syscall using libc are available\n", funct)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
strconvfunc := "C.CString"
|
||||
|
||||
// Go function header.
|
||||
if outps != "" {
|
||||
outps = fmt.Sprintf(" (%s)", outps)
|
||||
}
|
||||
if text != "" {
|
||||
text += "\n"
|
||||
}
|
||||
|
||||
text += fmt.Sprintf("func %s(%s)%s {\n", funct, strings.Join(in, ", "), outps)
|
||||
|
||||
// Prepare arguments to Syscall.
|
||||
var args []string
|
||||
n := 0
|
||||
argN := 0
|
||||
for _, param := range in {
|
||||
p := parseParam(param)
|
||||
if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil {
|
||||
args = append(args, "C.uintptr_t(uintptr(unsafe.Pointer("+p.Name+")))")
|
||||
} else if p.Type == "string" && errvar != "" {
|
||||
text += fmt.Sprintf("\t_p%d := uintptr(unsafe.Pointer(%s(%s)))\n", n, strconvfunc, p.Name)
|
||||
args = append(args, fmt.Sprintf("C.uintptr_t(_p%d)", n))
|
||||
n++
|
||||
} else if p.Type == "string" {
|
||||
fmt.Fprintf(os.Stderr, path+":"+funct+" uses string arguments, but has no error return\n")
|
||||
text += fmt.Sprintf("\t_p%d := uintptr(unsafe.Pointer(%s(%s)))\n", n, strconvfunc, p.Name)
|
||||
args = append(args, fmt.Sprintf("C.uintptr_t(_p%d)", n))
|
||||
n++
|
||||
} else if m := regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type); m != nil {
|
||||
// Convert slice into pointer, length.
|
||||
// Have to be careful not to take address of &a[0] if len == 0:
|
||||
// pass nil in that case.
|
||||
text += fmt.Sprintf("\tvar _p%d *%s\n", n, m[1])
|
||||
text += fmt.Sprintf("\tif len(%s) > 0 {\n\t\t_p%d = &%s[0]\n\t}\n", p.Name, n, p.Name)
|
||||
args = append(args, fmt.Sprintf("C.uintptr_t(uintptr(unsafe.Pointer(_p%d)))", n))
|
||||
n++
|
||||
text += fmt.Sprintf("\tvar _p%d int\n", n)
|
||||
text += fmt.Sprintf("\t_p%d = len(%s)\n", n, p.Name)
|
||||
args = append(args, fmt.Sprintf("C.size_t(_p%d)", n))
|
||||
n++
|
||||
} else if p.Type == "int64" && endianness != "" {
|
||||
if endianness == "big-endian" {
|
||||
args = append(args, fmt.Sprintf("uintptr(%s>>32)", p.Name), fmt.Sprintf("uintptr(%s)", p.Name))
|
||||
} else {
|
||||
args = append(args, fmt.Sprintf("uintptr(%s)", p.Name), fmt.Sprintf("uintptr(%s>>32)", p.Name))
|
||||
}
|
||||
n++
|
||||
} else if p.Type == "bool" {
|
||||
text += fmt.Sprintf("\tvar _p%d uint32\n", n)
|
||||
text += fmt.Sprintf("\tif %s {\n\t\t_p%d = 1\n\t} else {\n\t\t_p%d = 0\n\t}\n", p.Name, n, n)
|
||||
args = append(args, fmt.Sprintf("_p%d", n))
|
||||
} else if regexp.MustCompile(`^_`).FindStringSubmatch(p.Type) != nil {
|
||||
args = append(args, fmt.Sprintf("C.uintptr_t(uintptr(%s))", p.Name))
|
||||
} else if p.Type == "unsafe.Pointer" {
|
||||
args = append(args, fmt.Sprintf("C.uintptr_t(uintptr(%s))", p.Name))
|
||||
} else if p.Type == "int" {
|
||||
if (argN == 2) && ((funct == "readlen") || (funct == "writelen")) {
|
||||
args = append(args, fmt.Sprintf("C.size_t(%s)", p.Name))
|
||||
} else if argN == 0 && funct == "fcntl" {
|
||||
args = append(args, fmt.Sprintf("C.uintptr_t(%s)", p.Name))
|
||||
} else if (argN == 2) && ((funct == "fcntl") || (funct == "FcntlInt")) {
|
||||
args = append(args, fmt.Sprintf("C.uintptr_t(%s)", p.Name))
|
||||
} else {
|
||||
args = append(args, fmt.Sprintf("C.int(%s)", p.Name))
|
||||
}
|
||||
} else if p.Type == "int32" {
|
||||
args = append(args, fmt.Sprintf("C.int(%s)", p.Name))
|
||||
} else if p.Type == "int64" {
|
||||
args = append(args, fmt.Sprintf("C.longlong(%s)", p.Name))
|
||||
} else if p.Type == "uint32" {
|
||||
args = append(args, fmt.Sprintf("C.uint(%s)", p.Name))
|
||||
} else if p.Type == "uint64" {
|
||||
args = append(args, fmt.Sprintf("C.ulonglong(%s)", p.Name))
|
||||
} else if p.Type == "uintptr" {
|
||||
args = append(args, fmt.Sprintf("C.uintptr_t(%s)", p.Name))
|
||||
} else {
|
||||
args = append(args, fmt.Sprintf("C.int(%s)", p.Name))
|
||||
}
|
||||
argN++
|
||||
}
|
||||
|
||||
// Actual call.
|
||||
arglist := strings.Join(args, ", ")
|
||||
call := ""
|
||||
if sysname == "exit" {
|
||||
if errvar != "" {
|
||||
call += "er :="
|
||||
} else {
|
||||
call += ""
|
||||
}
|
||||
} else if errvar != "" {
|
||||
call += "r0,er :="
|
||||
} else if retvar != "" {
|
||||
call += "r0,_ :="
|
||||
} else {
|
||||
call += ""
|
||||
}
|
||||
if sysname == "select" {
|
||||
// select is a keyword of Go. Its name is
|
||||
// changed to c_select.
|
||||
call += fmt.Sprintf("C.c_%s(%s)", sysname, arglist)
|
||||
} else {
|
||||
call += fmt.Sprintf("C.%s(%s)", sysname, arglist)
|
||||
}
|
||||
|
||||
// Assign return values.
|
||||
body := ""
|
||||
for i := 0; i < len(out); i++ {
|
||||
p := parseParam(out[i])
|
||||
reg := ""
|
||||
if p.Name == "err" {
|
||||
reg = "e1"
|
||||
} else {
|
||||
reg = "r0"
|
||||
}
|
||||
if reg != "e1" {
|
||||
body += fmt.Sprintf("\t%s = %s(%s)\n", p.Name, p.Type, reg)
|
||||
}
|
||||
}
|
||||
|
||||
// verify return
|
||||
if sysname != "exit" && errvar != "" {
|
||||
if regexp.MustCompile(`^uintptr`).FindStringSubmatch(cRettype) != nil {
|
||||
body += "\tif (uintptr(r0) ==^uintptr(0) && er != nil) {\n"
|
||||
body += fmt.Sprintf("\t\t%s = er\n", errvar)
|
||||
body += "\t}\n"
|
||||
} else {
|
||||
body += "\tif (r0 ==-1 && er != nil) {\n"
|
||||
body += fmt.Sprintf("\t\t%s = er\n", errvar)
|
||||
body += "\t}\n"
|
||||
}
|
||||
} else if errvar != "" {
|
||||
body += "\tif (er != nil) {\n"
|
||||
body += fmt.Sprintf("\t\t%s = er\n", errvar)
|
||||
body += "\t}\n"
|
||||
}
|
||||
|
||||
text += fmt.Sprintf("\t%s\n", call)
|
||||
text += body
|
||||
|
||||
text += "\treturn\n"
|
||||
text += "}\n"
|
||||
}
|
||||
if err := s.Err(); err != nil {
|
||||
fmt.Fprintf(os.Stderr, err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
file.Close()
|
||||
}
|
||||
imp := ""
|
||||
if pack != "unix" {
|
||||
imp = "import \"golang.org/x/sys/unix\"\n"
|
||||
|
||||
}
|
||||
fmt.Printf(srcTemplate, cmdLine(), buildTags(), pack, cExtern, imp, text)
|
||||
}
|
||||
|
||||
const srcTemplate = `// %s
|
||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
||||
|
||||
// +build %s
|
||||
|
||||
package %s
|
||||
|
||||
|
||||
%s
|
||||
*/
|
||||
import "C"
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
|
||||
%s
|
||||
|
||||
%s
|
||||
`
|
|
@ -1,614 +0,0 @@
|
|||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
/*
|
||||
This program reads a file containing function prototypes
|
||||
(like syscall_aix.go) and generates system call bodies.
|
||||
The prototypes are marked by lines beginning with "//sys"
|
||||
and read like func declarations if //sys is replaced by func, but:
|
||||
* The parameter lists must give a name for each argument.
|
||||
This includes return parameters.
|
||||
* The parameter lists must give a type for each argument:
|
||||
the (x, y, z int) shorthand is not allowed.
|
||||
* If the return parameter is an error number, it must be named err.
|
||||
* If go func name needs to be different than its libc name,
|
||||
* or the function is not in libc, name could be specified
|
||||
* at the end, after "=" sign, like
|
||||
//sys getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (err error) = libsocket.getsockopt
|
||||
|
||||
|
||||
This program will generate three files and handle both gc and gccgo implementation:
|
||||
- zsyscall_aix_ppc64.go: the common part of each implementation (error handler, pointer creation)
|
||||
- zsyscall_aix_ppc64_gc.go: gc part with //go_cgo_import_dynamic and a call to syscall6
|
||||
- zsyscall_aix_ppc64_gccgo.go: gccgo part with C function and conversion to C type.
|
||||
|
||||
The generated code looks like this
|
||||
|
||||
zsyscall_aix_ppc64.go
|
||||
func asyscall(...) (n int, err error) {
|
||||
// Pointer Creation
|
||||
r1, e1 := callasyscall(...)
|
||||
// Type Conversion
|
||||
// Error Handler
|
||||
return
|
||||
}
|
||||
|
||||
zsyscall_aix_ppc64_gc.go
|
||||
//go:cgo_import_dynamic libc_asyscall asyscall "libc.a/shr_64.o"
|
||||
//go:linkname libc_asyscall libc_asyscall
|
||||
var asyscall syscallFunc
|
||||
|
||||
func callasyscall(...) (r1 uintptr, e1 Errno) {
|
||||
r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_asyscall)), "nb_args", ... )
|
||||
return
|
||||
}
|
||||
|
||||
zsyscall_aix_ppc64_ggcgo.go
|
||||
|
||||
// int asyscall(...)
|
||||
|
||||
import "C"
|
||||
|
||||
func callasyscall(...) (r1 uintptr, e1 Errno) {
|
||||
r1 = uintptr(C.asyscall(...))
|
||||
e1 = syscall.GetErrno()
|
||||
return
|
||||
}
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
b32 = flag.Bool("b32", false, "32bit big-endian")
|
||||
l32 = flag.Bool("l32", false, "32bit little-endian")
|
||||
aix = flag.Bool("aix", false, "aix")
|
||||
tags = flag.String("tags", "", "build tags")
|
||||
)
|
||||
|
||||
// cmdLine returns this programs's commandline arguments
|
||||
func cmdLine() string {
|
||||
return "go run mksyscall_aix_ppc64.go " + strings.Join(os.Args[1:], " ")
|
||||
}
|
||||
|
||||
// buildTags returns build tags
|
||||
func buildTags() string {
|
||||
return *tags
|
||||
}
|
||||
|
||||
// Param is function parameter
|
||||
type Param struct {
|
||||
Name string
|
||||
Type string
|
||||
}
|
||||
|
||||
// usage prints the program usage
|
||||
func usage() {
|
||||
fmt.Fprintf(os.Stderr, "usage: go run mksyscall_aix_ppc64.go [-b32 | -l32] [-tags x,y] [file ...]\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// parseParamList parses parameter list and returns a slice of parameters
|
||||
func parseParamList(list string) []string {
|
||||
list = strings.TrimSpace(list)
|
||||
if list == "" {
|
||||
return []string{}
|
||||
}
|
||||
return regexp.MustCompile(`\s*,\s*`).Split(list, -1)
|
||||
}
|
||||
|
||||
// parseParam splits a parameter into name and type
|
||||
func parseParam(p string) Param {
|
||||
ps := regexp.MustCompile(`^(\S*) (\S*)$`).FindStringSubmatch(p)
|
||||
if ps == nil {
|
||||
fmt.Fprintf(os.Stderr, "malformed parameter: %s\n", p)
|
||||
os.Exit(1)
|
||||
}
|
||||
return Param{ps[1], ps[2]}
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Usage = usage
|
||||
flag.Parse()
|
||||
if len(flag.Args()) <= 0 {
|
||||
fmt.Fprintf(os.Stderr, "no files to parse provided\n")
|
||||
usage()
|
||||
}
|
||||
|
||||
endianness := ""
|
||||
if *b32 {
|
||||
endianness = "big-endian"
|
||||
} else if *l32 {
|
||||
endianness = "little-endian"
|
||||
}
|
||||
|
||||
pack := ""
|
||||
// GCCGO
|
||||
textgccgo := ""
|
||||
cExtern := "/*\n#include <stdint.h>\n"
|
||||
// GC
|
||||
textgc := ""
|
||||
dynimports := ""
|
||||
linknames := ""
|
||||
var vars []string
|
||||
// COMMON
|
||||
textcommon := ""
|
||||
for _, path := range flag.Args() {
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
s := bufio.NewScanner(file)
|
||||
for s.Scan() {
|
||||
t := s.Text()
|
||||
t = strings.TrimSpace(t)
|
||||
t = regexp.MustCompile(`\s+`).ReplaceAllString(t, ` `)
|
||||
if p := regexp.MustCompile(`^package (\S+)$`).FindStringSubmatch(t); p != nil && pack == "" {
|
||||
pack = p[1]
|
||||
}
|
||||
nonblock := regexp.MustCompile(`^\/\/sysnb `).FindStringSubmatch(t)
|
||||
if regexp.MustCompile(`^\/\/sys `).FindStringSubmatch(t) == nil && nonblock == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// Line must be of the form
|
||||
// func Open(path string, mode int, perm int) (fd int, err error)
|
||||
// Split into name, in params, out params.
|
||||
f := regexp.MustCompile(`^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*(?:(\w*)\.)?(\w*))?$`).FindStringSubmatch(t)
|
||||
if f == nil {
|
||||
fmt.Fprintf(os.Stderr, "%s:%s\nmalformed //sys declaration\n", path, t)
|
||||
os.Exit(1)
|
||||
}
|
||||
funct, inps, outps, modname, sysname := f[2], f[3], f[4], f[5], f[6]
|
||||
|
||||
// Split argument lists on comma.
|
||||
in := parseParamList(inps)
|
||||
out := parseParamList(outps)
|
||||
|
||||
inps = strings.Join(in, ", ")
|
||||
outps = strings.Join(out, ", ")
|
||||
|
||||
if sysname == "" {
|
||||
sysname = funct
|
||||
}
|
||||
|
||||
onlyCommon := false
|
||||
if funct == "readlen" || funct == "writelen" || funct == "FcntlInt" || funct == "FcntlFlock" {
|
||||
// This function call another syscall which is already implemented.
|
||||
// Therefore, the gc and gccgo part must not be generated.
|
||||
onlyCommon = true
|
||||
}
|
||||
|
||||
// Try in vain to keep people from editing this file.
|
||||
// The theory is that they jump into the middle of the file
|
||||
// without reading the header.
|
||||
|
||||
textcommon += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n"
|
||||
if !onlyCommon {
|
||||
textgccgo += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n"
|
||||
textgc += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n"
|
||||
}
|
||||
|
||||
// Check if value return, err return available
|
||||
errvar := ""
|
||||
rettype := ""
|
||||
for _, param := range out {
|
||||
p := parseParam(param)
|
||||
if p.Type == "error" {
|
||||
errvar = p.Name
|
||||
} else {
|
||||
rettype = p.Type
|
||||
}
|
||||
}
|
||||
|
||||
sysname = regexp.MustCompile(`([a-z])([A-Z])`).ReplaceAllString(sysname, `${1}_$2`)
|
||||
sysname = strings.ToLower(sysname) // All libc functions are lowercase.
|
||||
|
||||
// GCCGO Prototype return type
|
||||
cRettype := ""
|
||||
if rettype == "unsafe.Pointer" {
|
||||
cRettype = "uintptr_t"
|
||||
} else if rettype == "uintptr" {
|
||||
cRettype = "uintptr_t"
|
||||
} else if regexp.MustCompile(`^_`).FindStringSubmatch(rettype) != nil {
|
||||
cRettype = "uintptr_t"
|
||||
} else if rettype == "int" {
|
||||
cRettype = "int"
|
||||
} else if rettype == "int32" {
|
||||
cRettype = "int"
|
||||
} else if rettype == "int64" {
|
||||
cRettype = "long long"
|
||||
} else if rettype == "uint32" {
|
||||
cRettype = "unsigned int"
|
||||
} else if rettype == "uint64" {
|
||||
cRettype = "unsigned long long"
|
||||
} else {
|
||||
cRettype = "int"
|
||||
}
|
||||
if sysname == "exit" {
|
||||
cRettype = "void"
|
||||
}
|
||||
|
||||
// GCCGO Prototype arguments type
|
||||
var cIn []string
|
||||
for i, param := range in {
|
||||
p := parseParam(param)
|
||||
if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil {
|
||||
cIn = append(cIn, "uintptr_t")
|
||||
} else if p.Type == "string" {
|
||||
cIn = append(cIn, "uintptr_t")
|
||||
} else if regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type) != nil {
|
||||
cIn = append(cIn, "uintptr_t", "size_t")
|
||||
} else if p.Type == "unsafe.Pointer" {
|
||||
cIn = append(cIn, "uintptr_t")
|
||||
} else if p.Type == "uintptr" {
|
||||
cIn = append(cIn, "uintptr_t")
|
||||
} else if regexp.MustCompile(`^_`).FindStringSubmatch(p.Type) != nil {
|
||||
cIn = append(cIn, "uintptr_t")
|
||||
} else if p.Type == "int" {
|
||||
if (i == 0 || i == 2) && funct == "fcntl" {
|
||||
// These fcntl arguments needs to be uintptr to be able to call FcntlInt and FcntlFlock
|
||||
cIn = append(cIn, "uintptr_t")
|
||||
} else {
|
||||
cIn = append(cIn, "int")
|
||||
}
|
||||
|
||||
} else if p.Type == "int32" {
|
||||
cIn = append(cIn, "int")
|
||||
} else if p.Type == "int64" {
|
||||
cIn = append(cIn, "long long")
|
||||
} else if p.Type == "uint32" {
|
||||
cIn = append(cIn, "unsigned int")
|
||||
} else if p.Type == "uint64" {
|
||||
cIn = append(cIn, "unsigned long long")
|
||||
} else {
|
||||
cIn = append(cIn, "int")
|
||||
}
|
||||
}
|
||||
|
||||
if !onlyCommon {
|
||||
// GCCGO Prototype Generation
|
||||
// Imports of system calls from libc
|
||||
if sysname == "select" {
|
||||
// select is a keyword of Go. Its name is
|
||||
// changed to c_select.
|
||||
cExtern += "#define c_select select\n"
|
||||
}
|
||||
cExtern += fmt.Sprintf("%s %s", cRettype, sysname)
|
||||
cIn := strings.Join(cIn, ", ")
|
||||
cExtern += fmt.Sprintf("(%s);\n", cIn)
|
||||
}
|
||||
// GC Library name
|
||||
if modname == "" {
|
||||
modname = "libc.a/shr_64.o"
|
||||
} else {
|
||||
fmt.Fprintf(os.Stderr, "%s: only syscall using libc are available\n", funct)
|
||||
os.Exit(1)
|
||||
}
|
||||
sysvarname := fmt.Sprintf("libc_%s", sysname)
|
||||
|
||||
if !onlyCommon {
|
||||
// GC Runtime import of function to allow cross-platform builds.
|
||||
dynimports += fmt.Sprintf("//go:cgo_import_dynamic %s %s \"%s\"\n", sysvarname, sysname, modname)
|
||||
// GC Link symbol to proc address variable.
|
||||
linknames += fmt.Sprintf("//go:linkname %s %s\n", sysvarname, sysvarname)
|
||||
// GC Library proc address variable.
|
||||
vars = append(vars, sysvarname)
|
||||
}
|
||||
|
||||
strconvfunc := "BytePtrFromString"
|
||||
strconvtype := "*byte"
|
||||
|
||||
// Go function header.
|
||||
if outps != "" {
|
||||
outps = fmt.Sprintf(" (%s)", outps)
|
||||
}
|
||||
if textcommon != "" {
|
||||
textcommon += "\n"
|
||||
}
|
||||
|
||||
textcommon += fmt.Sprintf("func %s(%s)%s {\n", funct, strings.Join(in, ", "), outps)
|
||||
|
||||
// Prepare arguments tocall.
|
||||
var argscommon []string // Arguments in the common part
|
||||
var argscall []string // Arguments for call prototype
|
||||
var argsgc []string // Arguments for gc call (with syscall6)
|
||||
var argsgccgo []string // Arguments for gccgo call (with C.name_of_syscall)
|
||||
n := 0
|
||||
argN := 0
|
||||
for _, param := range in {
|
||||
p := parseParam(param)
|
||||
if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil {
|
||||
argscommon = append(argscommon, fmt.Sprintf("uintptr(unsafe.Pointer(%s))", p.Name))
|
||||
argscall = append(argscall, fmt.Sprintf("%s uintptr", p.Name))
|
||||
argsgc = append(argsgc, p.Name)
|
||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(%s)", p.Name))
|
||||
} else if p.Type == "string" && errvar != "" {
|
||||
textcommon += fmt.Sprintf("\tvar _p%d %s\n", n, strconvtype)
|
||||
textcommon += fmt.Sprintf("\t_p%d, %s = %s(%s)\n", n, errvar, strconvfunc, p.Name)
|
||||
textcommon += fmt.Sprintf("\tif %s != nil {\n\t\treturn\n\t}\n", errvar)
|
||||
|
||||
argscommon = append(argscommon, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n))
|
||||
argscall = append(argscall, fmt.Sprintf("_p%d uintptr ", n))
|
||||
argsgc = append(argsgc, fmt.Sprintf("_p%d", n))
|
||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(_p%d)", n))
|
||||
n++
|
||||
} else if p.Type == "string" {
|
||||
fmt.Fprintf(os.Stderr, path+":"+funct+" uses string arguments, but has no error return\n")
|
||||
textcommon += fmt.Sprintf("\tvar _p%d %s\n", n, strconvtype)
|
||||
textcommon += fmt.Sprintf("\t_p%d, %s = %s(%s)\n", n, errvar, strconvfunc, p.Name)
|
||||
textcommon += fmt.Sprintf("\tif %s != nil {\n\t\treturn\n\t}\n", errvar)
|
||||
|
||||
argscommon = append(argscommon, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n))
|
||||
argscall = append(argscall, fmt.Sprintf("_p%d uintptr", n))
|
||||
argsgc = append(argsgc, fmt.Sprintf("_p%d", n))
|
||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(_p%d)", n))
|
||||
n++
|
||||
} else if m := regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type); m != nil {
|
||||
// Convert slice into pointer, length.
|
||||
// Have to be careful not to take address of &a[0] if len == 0:
|
||||
// pass nil in that case.
|
||||
textcommon += fmt.Sprintf("\tvar _p%d *%s\n", n, m[1])
|
||||
textcommon += fmt.Sprintf("\tif len(%s) > 0 {\n\t\t_p%d = &%s[0]\n\t}\n", p.Name, n, p.Name)
|
||||
argscommon = append(argscommon, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n), fmt.Sprintf("len(%s)", p.Name))
|
||||
argscall = append(argscall, fmt.Sprintf("_p%d uintptr", n), fmt.Sprintf("_lenp%d int", n))
|
||||
argsgc = append(argsgc, fmt.Sprintf("_p%d", n), fmt.Sprintf("uintptr(_lenp%d)", n))
|
||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(_p%d)", n), fmt.Sprintf("C.size_t(_lenp%d)", n))
|
||||
n++
|
||||
} else if p.Type == "int64" && endianness != "" {
|
||||
fmt.Fprintf(os.Stderr, path+":"+funct+" uses int64 with 32 bits mode. Case not yet implemented\n")
|
||||
} else if p.Type == "bool" {
|
||||
fmt.Fprintf(os.Stderr, path+":"+funct+" uses bool. Case not yet implemented\n")
|
||||
} else if regexp.MustCompile(`^_`).FindStringSubmatch(p.Type) != nil || p.Type == "unsafe.Pointer" {
|
||||
argscommon = append(argscommon, fmt.Sprintf("uintptr(%s)", p.Name))
|
||||
argscall = append(argscall, fmt.Sprintf("%s uintptr", p.Name))
|
||||
argsgc = append(argsgc, p.Name)
|
||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(%s)", p.Name))
|
||||
} else if p.Type == "int" {
|
||||
if (argN == 0 || argN == 2) && ((funct == "fcntl") || (funct == "FcntlInt") || (funct == "FcntlFlock")) {
|
||||
// These fcntl arguments need to be uintptr to be able to call FcntlInt and FcntlFlock
|
||||
argscommon = append(argscommon, fmt.Sprintf("uintptr(%s)", p.Name))
|
||||
argscall = append(argscall, fmt.Sprintf("%s uintptr", p.Name))
|
||||
argsgc = append(argsgc, p.Name)
|
||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(%s)", p.Name))
|
||||
|
||||
} else {
|
||||
argscommon = append(argscommon, p.Name)
|
||||
argscall = append(argscall, fmt.Sprintf("%s int", p.Name))
|
||||
argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name))
|
||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.int(%s)", p.Name))
|
||||
}
|
||||
} else if p.Type == "int32" {
|
||||
argscommon = append(argscommon, p.Name)
|
||||
argscall = append(argscall, fmt.Sprintf("%s int32", p.Name))
|
||||
argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name))
|
||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.int(%s)", p.Name))
|
||||
} else if p.Type == "int64" {
|
||||
argscommon = append(argscommon, p.Name)
|
||||
argscall = append(argscall, fmt.Sprintf("%s int64", p.Name))
|
||||
argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name))
|
||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.longlong(%s)", p.Name))
|
||||
} else if p.Type == "uint32" {
|
||||
argscommon = append(argscommon, p.Name)
|
||||
argscall = append(argscall, fmt.Sprintf("%s uint32", p.Name))
|
||||
argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name))
|
||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.uint(%s)", p.Name))
|
||||
} else if p.Type == "uint64" {
|
||||
argscommon = append(argscommon, p.Name)
|
||||
argscall = append(argscall, fmt.Sprintf("%s uint64", p.Name))
|
||||
argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name))
|
||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.ulonglong(%s)", p.Name))
|
||||
} else if p.Type == "uintptr" {
|
||||
argscommon = append(argscommon, p.Name)
|
||||
argscall = append(argscall, fmt.Sprintf("%s uintptr", p.Name))
|
||||
argsgc = append(argsgc, p.Name)
|
||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(%s)", p.Name))
|
||||
} else {
|
||||
argscommon = append(argscommon, fmt.Sprintf("int(%s)", p.Name))
|
||||
argscall = append(argscall, fmt.Sprintf("%s int", p.Name))
|
||||
argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name))
|
||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.int(%s)", p.Name))
|
||||
}
|
||||
argN++
|
||||
}
|
||||
nargs := len(argsgc)
|
||||
|
||||
// COMMON function generation
|
||||
argscommonlist := strings.Join(argscommon, ", ")
|
||||
callcommon := fmt.Sprintf("call%s(%s)", sysname, argscommonlist)
|
||||
ret := []string{"_", "_"}
|
||||
body := ""
|
||||
doErrno := false
|
||||
for i := 0; i < len(out); i++ {
|
||||
p := parseParam(out[i])
|
||||
reg := ""
|
||||
if p.Name == "err" {
|
||||
reg = "e1"
|
||||
ret[1] = reg
|
||||
doErrno = true
|
||||
} else {
|
||||
reg = "r0"
|
||||
ret[0] = reg
|
||||
}
|
||||
if p.Type == "bool" {
|
||||
reg = fmt.Sprintf("%s != 0", reg)
|
||||
}
|
||||
if reg != "e1" {
|
||||
body += fmt.Sprintf("\t%s = %s(%s)\n", p.Name, p.Type, reg)
|
||||
}
|
||||
}
|
||||
if ret[0] == "_" && ret[1] == "_" {
|
||||
textcommon += fmt.Sprintf("\t%s\n", callcommon)
|
||||
} else {
|
||||
textcommon += fmt.Sprintf("\t%s, %s := %s\n", ret[0], ret[1], callcommon)
|
||||
}
|
||||
textcommon += body
|
||||
|
||||
if doErrno {
|
||||
textcommon += "\tif e1 != 0 {\n"
|
||||
textcommon += "\t\terr = errnoErr(e1)\n"
|
||||
textcommon += "\t}\n"
|
||||
}
|
||||
textcommon += "\treturn\n"
|
||||
textcommon += "}\n"
|
||||
|
||||
if onlyCommon {
|
||||
continue
|
||||
}
|
||||
|
||||
// CALL Prototype
|
||||
callProto := fmt.Sprintf("func call%s(%s) (r1 uintptr, e1 Errno) {\n", sysname, strings.Join(argscall, ", "))
|
||||
|
||||
// GC function generation
|
||||
asm := "syscall6"
|
||||
if nonblock != nil {
|
||||
asm = "rawSyscall6"
|
||||
}
|
||||
|
||||
if len(argsgc) <= 6 {
|
||||
for len(argsgc) < 6 {
|
||||
argsgc = append(argsgc, "0")
|
||||
}
|
||||
} else {
|
||||
fmt.Fprintf(os.Stderr, "%s: too many arguments to system call", funct)
|
||||
os.Exit(1)
|
||||
}
|
||||
argsgclist := strings.Join(argsgc, ", ")
|
||||
callgc := fmt.Sprintf("%s(uintptr(unsafe.Pointer(&%s)), %d, %s)", asm, sysvarname, nargs, argsgclist)
|
||||
|
||||
textgc += callProto
|
||||
textgc += fmt.Sprintf("\tr1, _, e1 = %s\n", callgc)
|
||||
textgc += "\treturn\n}\n"
|
||||
|
||||
// GCCGO function generation
|
||||
argsgccgolist := strings.Join(argsgccgo, ", ")
|
||||
var callgccgo string
|
||||
if sysname == "select" {
|
||||
// select is a keyword of Go. Its name is
|
||||
// changed to c_select.
|
||||
callgccgo = fmt.Sprintf("C.c_%s(%s)", sysname, argsgccgolist)
|
||||
} else {
|
||||
callgccgo = fmt.Sprintf("C.%s(%s)", sysname, argsgccgolist)
|
||||
}
|
||||
textgccgo += callProto
|
||||
textgccgo += fmt.Sprintf("\tr1 = uintptr(%s)\n", callgccgo)
|
||||
textgccgo += "\te1 = syscall.GetErrno()\n"
|
||||
textgccgo += "\treturn\n}\n"
|
||||
}
|
||||
if err := s.Err(); err != nil {
|
||||
fmt.Fprintf(os.Stderr, err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
file.Close()
|
||||
}
|
||||
imp := ""
|
||||
if pack != "unix" {
|
||||
imp = "import \"golang.org/x/sys/unix\"\n"
|
||||
|
||||
}
|
||||
|
||||
// Print zsyscall_aix_ppc64.go
|
||||
err := ioutil.WriteFile("zsyscall_aix_ppc64.go",
|
||||
[]byte(fmt.Sprintf(srcTemplate1, cmdLine(), buildTags(), pack, imp, textcommon)),
|
||||
0644)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Print zsyscall_aix_ppc64_gc.go
|
||||
vardecls := "\t" + strings.Join(vars, ",\n\t")
|
||||
vardecls += " syscallFunc"
|
||||
err = ioutil.WriteFile("zsyscall_aix_ppc64_gc.go",
|
||||
[]byte(fmt.Sprintf(srcTemplate2, cmdLine(), buildTags(), pack, imp, dynimports, linknames, vardecls, textgc)),
|
||||
0644)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Print zsyscall_aix_ppc64_gccgo.go
|
||||
err = ioutil.WriteFile("zsyscall_aix_ppc64_gccgo.go",
|
||||
[]byte(fmt.Sprintf(srcTemplate3, cmdLine(), buildTags(), pack, cExtern, imp, textgccgo)),
|
||||
0644)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
const srcTemplate1 = `// %s
|
||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
||||
|
||||
// +build %s
|
||||
|
||||
package %s
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
|
||||
%s
|
||||
|
||||
%s
|
||||
`
|
||||
const srcTemplate2 = `// %s
|
||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
||||
|
||||
// +build %s
|
||||
// +build !gccgo
|
||||
|
||||
package %s
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
%s
|
||||
%s
|
||||
%s
|
||||
type syscallFunc uintptr
|
||||
|
||||
var (
|
||||
%s
|
||||
)
|
||||
|
||||
// Implemented in runtime/syscall_aix.go.
|
||||
func rawSyscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
|
||||
func syscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
|
||||
|
||||
%s
|
||||
`
|
||||
const srcTemplate3 = `// %s
|
||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
||||
|
||||
// +build %s
|
||||
// +build gccgo
|
||||
|
||||
package %s
|
||||
|
||||
%s
|
||||
*/
|
||||
import "C"
|
||||
import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
|
||||
%s
|
||||
|
||||
%s
|
||||
`
|
|
@ -1,335 +0,0 @@
|
|||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
/*
|
||||
This program reads a file containing function prototypes
|
||||
(like syscall_solaris.go) and generates system call bodies.
|
||||
The prototypes are marked by lines beginning with "//sys"
|
||||
and read like func declarations if //sys is replaced by func, but:
|
||||
* The parameter lists must give a name for each argument.
|
||||
This includes return parameters.
|
||||
* The parameter lists must give a type for each argument:
|
||||
the (x, y, z int) shorthand is not allowed.
|
||||
* If the return parameter is an error number, it must be named err.
|
||||
* If go func name needs to be different than its libc name,
|
||||
* or the function is not in libc, name could be specified
|
||||
* at the end, after "=" sign, like
|
||||
//sys getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (err error) = libsocket.getsockopt
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
b32 = flag.Bool("b32", false, "32bit big-endian")
|
||||
l32 = flag.Bool("l32", false, "32bit little-endian")
|
||||
tags = flag.String("tags", "", "build tags")
|
||||
)
|
||||
|
||||
// cmdLine returns this programs's commandline arguments
|
||||
func cmdLine() string {
|
||||
return "go run mksyscall_solaris.go " + strings.Join(os.Args[1:], " ")
|
||||
}
|
||||
|
||||
// buildTags returns build tags
|
||||
func buildTags() string {
|
||||
return *tags
|
||||
}
|
||||
|
||||
// Param is function parameter
|
||||
type Param struct {
|
||||
Name string
|
||||
Type string
|
||||
}
|
||||
|
||||
// usage prints the program usage
|
||||
func usage() {
|
||||
fmt.Fprintf(os.Stderr, "usage: go run mksyscall_solaris.go [-b32 | -l32] [-tags x,y] [file ...]\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// parseParamList parses parameter list and returns a slice of parameters
|
||||
func parseParamList(list string) []string {
|
||||
list = strings.TrimSpace(list)
|
||||
if list == "" {
|
||||
return []string{}
|
||||
}
|
||||
return regexp.MustCompile(`\s*,\s*`).Split(list, -1)
|
||||
}
|
||||
|
||||
// parseParam splits a parameter into name and type
|
||||
func parseParam(p string) Param {
|
||||
ps := regexp.MustCompile(`^(\S*) (\S*)$`).FindStringSubmatch(p)
|
||||
if ps == nil {
|
||||
fmt.Fprintf(os.Stderr, "malformed parameter: %s\n", p)
|
||||
os.Exit(1)
|
||||
}
|
||||
return Param{ps[1], ps[2]}
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Usage = usage
|
||||
flag.Parse()
|
||||
if len(flag.Args()) <= 0 {
|
||||
fmt.Fprintf(os.Stderr, "no files to parse provided\n")
|
||||
usage()
|
||||
}
|
||||
|
||||
endianness := ""
|
||||
if *b32 {
|
||||
endianness = "big-endian"
|
||||
} else if *l32 {
|
||||
endianness = "little-endian"
|
||||
}
|
||||
|
||||
pack := ""
|
||||
text := ""
|
||||
dynimports := ""
|
||||
linknames := ""
|
||||
var vars []string
|
||||
for _, path := range flag.Args() {
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
s := bufio.NewScanner(file)
|
||||
for s.Scan() {
|
||||
t := s.Text()
|
||||
t = strings.TrimSpace(t)
|
||||
t = regexp.MustCompile(`\s+`).ReplaceAllString(t, ` `)
|
||||
if p := regexp.MustCompile(`^package (\S+)$`).FindStringSubmatch(t); p != nil && pack == "" {
|
||||
pack = p[1]
|
||||
}
|
||||
nonblock := regexp.MustCompile(`^\/\/sysnb `).FindStringSubmatch(t)
|
||||
if regexp.MustCompile(`^\/\/sys `).FindStringSubmatch(t) == nil && nonblock == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// Line must be of the form
|
||||
// func Open(path string, mode int, perm int) (fd int, err error)
|
||||
// Split into name, in params, out params.
|
||||
f := regexp.MustCompile(`^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*(?:(\w*)\.)?(\w*))?$`).FindStringSubmatch(t)
|
||||
if f == nil {
|
||||
fmt.Fprintf(os.Stderr, "%s:%s\nmalformed //sys declaration\n", path, t)
|
||||
os.Exit(1)
|
||||
}
|
||||
funct, inps, outps, modname, sysname := f[2], f[3], f[4], f[5], f[6]
|
||||
|
||||
// Split argument lists on comma.
|
||||
in := parseParamList(inps)
|
||||
out := parseParamList(outps)
|
||||
|
||||
inps = strings.Join(in, ", ")
|
||||
outps = strings.Join(out, ", ")
|
||||
|
||||
// Try in vain to keep people from editing this file.
|
||||
// The theory is that they jump into the middle of the file
|
||||
// without reading the header.
|
||||
text += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n"
|
||||
|
||||
// So file name.
|
||||
if modname == "" {
|
||||
modname = "libc"
|
||||
}
|
||||
|
||||
// System call name.
|
||||
if sysname == "" {
|
||||
sysname = funct
|
||||
}
|
||||
|
||||
// System call pointer variable name.
|
||||
sysvarname := fmt.Sprintf("proc%s", sysname)
|
||||
|
||||
strconvfunc := "BytePtrFromString"
|
||||
strconvtype := "*byte"
|
||||
|
||||
sysname = strings.ToLower(sysname) // All libc functions are lowercase.
|
||||
|
||||
// Runtime import of function to allow cross-platform builds.
|
||||
dynimports += fmt.Sprintf("//go:cgo_import_dynamic libc_%s %s \"%s.so\"\n", sysname, sysname, modname)
|
||||
// Link symbol to proc address variable.
|
||||
linknames += fmt.Sprintf("//go:linkname %s libc_%s\n", sysvarname, sysname)
|
||||
// Library proc address variable.
|
||||
vars = append(vars, sysvarname)
|
||||
|
||||
// Go function header.
|
||||
outlist := strings.Join(out, ", ")
|
||||
if outlist != "" {
|
||||
outlist = fmt.Sprintf(" (%s)", outlist)
|
||||
}
|
||||
if text != "" {
|
||||
text += "\n"
|
||||
}
|
||||
text += fmt.Sprintf("func %s(%s)%s {\n", funct, strings.Join(in, ", "), outlist)
|
||||
|
||||
// Check if err return available
|
||||
errvar := ""
|
||||
for _, param := range out {
|
||||
p := parseParam(param)
|
||||
if p.Type == "error" {
|
||||
errvar = p.Name
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// Prepare arguments to Syscall.
|
||||
var args []string
|
||||
n := 0
|
||||
for _, param := range in {
|
||||
p := parseParam(param)
|
||||
if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil {
|
||||
args = append(args, "uintptr(unsafe.Pointer("+p.Name+"))")
|
||||
} else if p.Type == "string" && errvar != "" {
|
||||
text += fmt.Sprintf("\tvar _p%d %s\n", n, strconvtype)
|
||||
text += fmt.Sprintf("\t_p%d, %s = %s(%s)\n", n, errvar, strconvfunc, p.Name)
|
||||
text += fmt.Sprintf("\tif %s != nil {\n\t\treturn\n\t}\n", errvar)
|
||||
args = append(args, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n))
|
||||
n++
|
||||
} else if p.Type == "string" {
|
||||
fmt.Fprintf(os.Stderr, path+":"+funct+" uses string arguments, but has no error return\n")
|
||||
text += fmt.Sprintf("\tvar _p%d %s\n", n, strconvtype)
|
||||
text += fmt.Sprintf("\t_p%d, _ = %s(%s)\n", n, strconvfunc, p.Name)
|
||||
args = append(args, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n))
|
||||
n++
|
||||
} else if s := regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type); s != nil {
|
||||
// Convert slice into pointer, length.
|
||||
// Have to be careful not to take address of &a[0] if len == 0:
|
||||
// pass nil in that case.
|
||||
text += fmt.Sprintf("\tvar _p%d *%s\n", n, s[1])
|
||||
text += fmt.Sprintf("\tif len(%s) > 0 {\n\t\t_p%d = &%s[0]\n\t}\n", p.Name, n, p.Name)
|
||||
args = append(args, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n), fmt.Sprintf("uintptr(len(%s))", p.Name))
|
||||
n++
|
||||
} else if p.Type == "int64" && endianness != "" {
|
||||
if endianness == "big-endian" {
|
||||
args = append(args, fmt.Sprintf("uintptr(%s>>32)", p.Name), fmt.Sprintf("uintptr(%s)", p.Name))
|
||||
} else {
|
||||
args = append(args, fmt.Sprintf("uintptr(%s)", p.Name), fmt.Sprintf("uintptr(%s>>32)", p.Name))
|
||||
}
|
||||
} else if p.Type == "bool" {
|
||||
text += fmt.Sprintf("\tvar _p%d uint32\n", n)
|
||||
text += fmt.Sprintf("\tif %s {\n\t\t_p%d = 1\n\t} else {\n\t\t_p%d = 0\n\t}\n", p.Name, n, n)
|
||||
args = append(args, fmt.Sprintf("uintptr(_p%d)", n))
|
||||
n++
|
||||
} else {
|
||||
args = append(args, fmt.Sprintf("uintptr(%s)", p.Name))
|
||||
}
|
||||
}
|
||||
nargs := len(args)
|
||||
|
||||
// Determine which form to use; pad args with zeros.
|
||||
asm := "sysvicall6"
|
||||
if nonblock != nil {
|
||||
asm = "rawSysvicall6"
|
||||
}
|
||||
if len(args) <= 6 {
|
||||
for len(args) < 6 {
|
||||
args = append(args, "0")
|
||||
}
|
||||
} else {
|
||||
fmt.Fprintf(os.Stderr, "%s: too many arguments to system call\n", path)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Actual call.
|
||||
arglist := strings.Join(args, ", ")
|
||||
call := fmt.Sprintf("%s(uintptr(unsafe.Pointer(&%s)), %d, %s)", asm, sysvarname, nargs, arglist)
|
||||
|
||||
// Assign return values.
|
||||
body := ""
|
||||
ret := []string{"_", "_", "_"}
|
||||
doErrno := false
|
||||
for i := 0; i < len(out); i++ {
|
||||
p := parseParam(out[i])
|
||||
reg := ""
|
||||
if p.Name == "err" {
|
||||
reg = "e1"
|
||||
ret[2] = reg
|
||||
doErrno = true
|
||||
} else {
|
||||
reg = fmt.Sprintf("r%d", i)
|
||||
ret[i] = reg
|
||||
}
|
||||
if p.Type == "bool" {
|
||||
reg = fmt.Sprintf("%d != 0", reg)
|
||||
}
|
||||
if p.Type == "int64" && endianness != "" {
|
||||
// 64-bit number in r1:r0 or r0:r1.
|
||||
if i+2 > len(out) {
|
||||
fmt.Fprintf(os.Stderr, "%s: not enough registers for int64 return\n", path)
|
||||
os.Exit(1)
|
||||
}
|
||||
if endianness == "big-endian" {
|
||||
reg = fmt.Sprintf("int64(r%d)<<32 | int64(r%d)", i, i+1)
|
||||
} else {
|
||||
reg = fmt.Sprintf("int64(r%d)<<32 | int64(r%d)", i+1, i)
|
||||
}
|
||||
ret[i] = fmt.Sprintf("r%d", i)
|
||||
ret[i+1] = fmt.Sprintf("r%d", i+1)
|
||||
}
|
||||
if reg != "e1" {
|
||||
body += fmt.Sprintf("\t%s = %s(%s)\n", p.Name, p.Type, reg)
|
||||
}
|
||||
}
|
||||
if ret[0] == "_" && ret[1] == "_" && ret[2] == "_" {
|
||||
text += fmt.Sprintf("\t%s\n", call)
|
||||
} else {
|
||||
text += fmt.Sprintf("\t%s, %s, %s := %s\n", ret[0], ret[1], ret[2], call)
|
||||
}
|
||||
text += body
|
||||
|
||||
if doErrno {
|
||||
text += "\tif e1 != 0 {\n"
|
||||
text += "\t\terr = e1\n"
|
||||
text += "\t}\n"
|
||||
}
|
||||
text += "\treturn\n"
|
||||
text += "}\n"
|
||||
}
|
||||
if err := s.Err(); err != nil {
|
||||
fmt.Fprintf(os.Stderr, err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
file.Close()
|
||||
}
|
||||
imp := ""
|
||||
if pack != "unix" {
|
||||
imp = "import \"golang.org/x/sys/unix\"\n"
|
||||
|
||||
}
|
||||
vardecls := "\t" + strings.Join(vars, ",\n\t")
|
||||
vardecls += " syscallFunc"
|
||||
fmt.Printf(srcTemplate, cmdLine(), buildTags(), pack, imp, dynimports, linknames, vardecls, text)
|
||||
}
|
||||
|
||||
const srcTemplate = `// %s
|
||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
||||
|
||||
// +build %s
|
||||
|
||||
package %s
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
%s
|
||||
%s
|
||||
%s
|
||||
var (
|
||||
%s
|
||||
)
|
||||
|
||||
%s
|
||||
`
|
|
@ -1,355 +0,0 @@
|
|||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
// Parse the header files for OpenBSD and generate a Go usable sysctl MIB.
|
||||
//
|
||||
// Build a MIB with each entry being an array containing the level, type and
|
||||
// a hash that will contain additional entries if the current entry is a node.
|
||||
// We then walk this MIB and create a flattened sysctl name to OID hash.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
goos, goarch string
|
||||
)
|
||||
|
||||
// cmdLine returns this programs's commandline arguments.
|
||||
func cmdLine() string {
|
||||
return "go run mksysctl_openbsd.go " + strings.Join(os.Args[1:], " ")
|
||||
}
|
||||
|
||||
// buildTags returns build tags.
|
||||
func buildTags() string {
|
||||
return fmt.Sprintf("%s,%s", goarch, goos)
|
||||
}
|
||||
|
||||
// reMatch performs regular expression match and stores the substring slice to value pointed by m.
|
||||
func reMatch(re *regexp.Regexp, str string, m *[]string) bool {
|
||||
*m = re.FindStringSubmatch(str)
|
||||
if *m != nil {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type nodeElement struct {
|
||||
n int
|
||||
t string
|
||||
pE *map[string]nodeElement
|
||||
}
|
||||
|
||||
var (
|
||||
debugEnabled bool
|
||||
mib map[string]nodeElement
|
||||
node *map[string]nodeElement
|
||||
nodeMap map[string]string
|
||||
sysCtl []string
|
||||
)
|
||||
|
||||
var (
|
||||
ctlNames1RE = regexp.MustCompile(`^#define\s+(CTL_NAMES)\s+{`)
|
||||
ctlNames2RE = regexp.MustCompile(`^#define\s+(CTL_(.*)_NAMES)\s+{`)
|
||||
ctlNames3RE = regexp.MustCompile(`^#define\s+((.*)CTL_NAMES)\s+{`)
|
||||
netInetRE = regexp.MustCompile(`^netinet/`)
|
||||
netInet6RE = regexp.MustCompile(`^netinet6/`)
|
||||
netRE = regexp.MustCompile(`^net/`)
|
||||
bracesRE = regexp.MustCompile(`{.*}`)
|
||||
ctlTypeRE = regexp.MustCompile(`{\s+"(\w+)",\s+(CTLTYPE_[A-Z]+)\s+}`)
|
||||
fsNetKernRE = regexp.MustCompile(`^(fs|net|kern)_`)
|
||||
)
|
||||
|
||||
func debug(s string) {
|
||||
if debugEnabled {
|
||||
fmt.Fprintln(os.Stderr, s)
|
||||
}
|
||||
}
|
||||
|
||||
// Walk the MIB and build a sysctl name to OID mapping.
|
||||
func buildSysctl(pNode *map[string]nodeElement, name string, oid []int) {
|
||||
lNode := pNode // local copy of pointer to node
|
||||
var keys []string
|
||||
for k := range *lNode {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
|
||||
for _, key := range keys {
|
||||
nodename := name
|
||||
if name != "" {
|
||||
nodename += "."
|
||||
}
|
||||
nodename += key
|
||||
|
||||
nodeoid := append(oid, (*pNode)[key].n)
|
||||
|
||||
if (*pNode)[key].t == `CTLTYPE_NODE` {
|
||||
if _, ok := nodeMap[nodename]; ok {
|
||||
lNode = &mib
|
||||
ctlName := nodeMap[nodename]
|
||||
for _, part := range strings.Split(ctlName, ".") {
|
||||
lNode = ((*lNode)[part]).pE
|
||||
}
|
||||
} else {
|
||||
lNode = (*pNode)[key].pE
|
||||
}
|
||||
buildSysctl(lNode, nodename, nodeoid)
|
||||
} else if (*pNode)[key].t != "" {
|
||||
oidStr := []string{}
|
||||
for j := range nodeoid {
|
||||
oidStr = append(oidStr, fmt.Sprintf("%d", nodeoid[j]))
|
||||
}
|
||||
text := "\t{ \"" + nodename + "\", []_C_int{ " + strings.Join(oidStr, ", ") + " } }, \n"
|
||||
sysCtl = append(sysCtl, text)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Get the OS (using GOOS_TARGET if it exist)
|
||||
goos = os.Getenv("GOOS_TARGET")
|
||||
if goos == "" {
|
||||
goos = os.Getenv("GOOS")
|
||||
}
|
||||
// Get the architecture (using GOARCH_TARGET if it exists)
|
||||
goarch = os.Getenv("GOARCH_TARGET")
|
||||
if goarch == "" {
|
||||
goarch = os.Getenv("GOARCH")
|
||||
}
|
||||
// Check if GOOS and GOARCH environment variables are defined
|
||||
if goarch == "" || goos == "" {
|
||||
fmt.Fprintf(os.Stderr, "GOARCH or GOOS not defined in environment\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
mib = make(map[string]nodeElement)
|
||||
headers := [...]string{
|
||||
`sys/sysctl.h`,
|
||||
`sys/socket.h`,
|
||||
`sys/tty.h`,
|
||||
`sys/malloc.h`,
|
||||
`sys/mount.h`,
|
||||
`sys/namei.h`,
|
||||
`sys/sem.h`,
|
||||
`sys/shm.h`,
|
||||
`sys/vmmeter.h`,
|
||||
`uvm/uvmexp.h`,
|
||||
`uvm/uvm_param.h`,
|
||||
`uvm/uvm_swap_encrypt.h`,
|
||||
`ddb/db_var.h`,
|
||||
`net/if.h`,
|
||||
`net/if_pfsync.h`,
|
||||
`net/pipex.h`,
|
||||
`netinet/in.h`,
|
||||
`netinet/icmp_var.h`,
|
||||
`netinet/igmp_var.h`,
|
||||
`netinet/ip_ah.h`,
|
||||
`netinet/ip_carp.h`,
|
||||
`netinet/ip_divert.h`,
|
||||
`netinet/ip_esp.h`,
|
||||
`netinet/ip_ether.h`,
|
||||
`netinet/ip_gre.h`,
|
||||
`netinet/ip_ipcomp.h`,
|
||||
`netinet/ip_ipip.h`,
|
||||
`netinet/pim_var.h`,
|
||||
`netinet/tcp_var.h`,
|
||||
`netinet/udp_var.h`,
|
||||
`netinet6/in6.h`,
|
||||
`netinet6/ip6_divert.h`,
|
||||
`netinet6/pim6_var.h`,
|
||||
`netinet/icmp6.h`,
|
||||
`netmpls/mpls.h`,
|
||||
}
|
||||
|
||||
ctls := [...]string{
|
||||
`kern`,
|
||||
`vm`,
|
||||
`fs`,
|
||||
`net`,
|
||||
//debug /* Special handling required */
|
||||
`hw`,
|
||||
//machdep /* Arch specific */
|
||||
`user`,
|
||||
`ddb`,
|
||||
//vfs /* Special handling required */
|
||||
`fs.posix`,
|
||||
`kern.forkstat`,
|
||||
`kern.intrcnt`,
|
||||
`kern.malloc`,
|
||||
`kern.nchstats`,
|
||||
`kern.seminfo`,
|
||||
`kern.shminfo`,
|
||||
`kern.timecounter`,
|
||||
`kern.tty`,
|
||||
`kern.watchdog`,
|
||||
`net.bpf`,
|
||||
`net.ifq`,
|
||||
`net.inet`,
|
||||
`net.inet.ah`,
|
||||
`net.inet.carp`,
|
||||
`net.inet.divert`,
|
||||
`net.inet.esp`,
|
||||
`net.inet.etherip`,
|
||||
`net.inet.gre`,
|
||||
`net.inet.icmp`,
|
||||
`net.inet.igmp`,
|
||||
`net.inet.ip`,
|
||||
`net.inet.ip.ifq`,
|
||||
`net.inet.ipcomp`,
|
||||
`net.inet.ipip`,
|
||||
`net.inet.mobileip`,
|
||||
`net.inet.pfsync`,
|
||||
`net.inet.pim`,
|
||||
`net.inet.tcp`,
|
||||
`net.inet.udp`,
|
||||
`net.inet6`,
|
||||
`net.inet6.divert`,
|
||||
`net.inet6.ip6`,
|
||||
`net.inet6.icmp6`,
|
||||
`net.inet6.pim6`,
|
||||
`net.inet6.tcp6`,
|
||||
`net.inet6.udp6`,
|
||||
`net.mpls`,
|
||||
`net.mpls.ifq`,
|
||||
`net.key`,
|
||||
`net.pflow`,
|
||||
`net.pfsync`,
|
||||
`net.pipex`,
|
||||
`net.rt`,
|
||||
`vm.swapencrypt`,
|
||||
//vfsgenctl /* Special handling required */
|
||||
}
|
||||
|
||||
// Node name "fixups"
|
||||
ctlMap := map[string]string{
|
||||
"ipproto": "net.inet",
|
||||
"net.inet.ipproto": "net.inet",
|
||||
"net.inet6.ipv6proto": "net.inet6",
|
||||
"net.inet6.ipv6": "net.inet6.ip6",
|
||||
"net.inet.icmpv6": "net.inet6.icmp6",
|
||||
"net.inet6.divert6": "net.inet6.divert",
|
||||
"net.inet6.tcp6": "net.inet.tcp",
|
||||
"net.inet6.udp6": "net.inet.udp",
|
||||
"mpls": "net.mpls",
|
||||
"swpenc": "vm.swapencrypt",
|
||||
}
|
||||
|
||||
// Node mappings
|
||||
nodeMap = map[string]string{
|
||||
"net.inet.ip.ifq": "net.ifq",
|
||||
"net.inet.pfsync": "net.pfsync",
|
||||
"net.mpls.ifq": "net.ifq",
|
||||
}
|
||||
|
||||
mCtls := make(map[string]bool)
|
||||
for _, ctl := range ctls {
|
||||
mCtls[ctl] = true
|
||||
}
|
||||
|
||||
for _, header := range headers {
|
||||
debug("Processing " + header)
|
||||
file, err := os.Open(filepath.Join("/usr/include", header))
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "%v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
s := bufio.NewScanner(file)
|
||||
for s.Scan() {
|
||||
var sub []string
|
||||
if reMatch(ctlNames1RE, s.Text(), &sub) ||
|
||||
reMatch(ctlNames2RE, s.Text(), &sub) ||
|
||||
reMatch(ctlNames3RE, s.Text(), &sub) {
|
||||
if sub[1] == `CTL_NAMES` {
|
||||
// Top level.
|
||||
node = &mib
|
||||
} else {
|
||||
// Node.
|
||||
nodename := strings.ToLower(sub[2])
|
||||
ctlName := ""
|
||||
if reMatch(netInetRE, header, &sub) {
|
||||
ctlName = "net.inet." + nodename
|
||||
} else if reMatch(netInet6RE, header, &sub) {
|
||||
ctlName = "net.inet6." + nodename
|
||||
} else if reMatch(netRE, header, &sub) {
|
||||
ctlName = "net." + nodename
|
||||
} else {
|
||||
ctlName = nodename
|
||||
ctlName = fsNetKernRE.ReplaceAllString(ctlName, `$1.`)
|
||||
}
|
||||
|
||||
if val, ok := ctlMap[ctlName]; ok {
|
||||
ctlName = val
|
||||
}
|
||||
if _, ok := mCtls[ctlName]; !ok {
|
||||
debug("Ignoring " + ctlName + "...")
|
||||
continue
|
||||
}
|
||||
|
||||
// Walk down from the top of the MIB.
|
||||
node = &mib
|
||||
for _, part := range strings.Split(ctlName, ".") {
|
||||
if _, ok := (*node)[part]; !ok {
|
||||
debug("Missing node " + part)
|
||||
(*node)[part] = nodeElement{n: 0, t: "", pE: &map[string]nodeElement{}}
|
||||
}
|
||||
node = (*node)[part].pE
|
||||
}
|
||||
}
|
||||
|
||||
// Populate current node with entries.
|
||||
i := -1
|
||||
for !strings.HasPrefix(s.Text(), "}") {
|
||||
s.Scan()
|
||||
if reMatch(bracesRE, s.Text(), &sub) {
|
||||
i++
|
||||
}
|
||||
if !reMatch(ctlTypeRE, s.Text(), &sub) {
|
||||
continue
|
||||
}
|
||||
(*node)[sub[1]] = nodeElement{n: i, t: sub[2], pE: &map[string]nodeElement{}}
|
||||
}
|
||||
}
|
||||
}
|
||||
err = s.Err()
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "%v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
file.Close()
|
||||
}
|
||||
buildSysctl(&mib, "", []int{})
|
||||
|
||||
sort.Strings(sysCtl)
|
||||
text := strings.Join(sysCtl, "")
|
||||
|
||||
fmt.Printf(srcTemplate, cmdLine(), buildTags(), text)
|
||||
}
|
||||
|
||||
const srcTemplate = `// %s
|
||||
// Code generated by the command above; DO NOT EDIT.
|
||||
|
||||
// +build %s
|
||||
|
||||
package unix
|
||||
|
||||
type mibentry struct {
|
||||
ctlname string
|
||||
ctloid []_C_int
|
||||
}
|
||||
|
||||
var sysctlMib = []mibentry {
|
||||
%s
|
||||
}
|
||||
`
|
|
@ -1,190 +0,0 @@
|
|||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
// Generate system call table for DragonFly, NetBSD,
|
||||
// FreeBSD, OpenBSD or Darwin from master list
|
||||
// (for example, /usr/src/sys/kern/syscalls.master or
|
||||
// sys/syscall.h).
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
goos, goarch string
|
||||
)
|
||||
|
||||
// cmdLine returns this programs's commandline arguments
|
||||
func cmdLine() string {
|
||||
return "go run mksysnum.go " + strings.Join(os.Args[1:], " ")
|
||||
}
|
||||
|
||||
// buildTags returns build tags
|
||||
func buildTags() string {
|
||||
return fmt.Sprintf("%s,%s", goarch, goos)
|
||||
}
|
||||
|
||||
func checkErr(err error) {
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "%v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
// source string and substring slice for regexp
|
||||
type re struct {
|
||||
str string // source string
|
||||
sub []string // matched sub-string
|
||||
}
|
||||
|
||||
// Match performs regular expression match
|
||||
func (r *re) Match(exp string) bool {
|
||||
r.sub = regexp.MustCompile(exp).FindStringSubmatch(r.str)
|
||||
if r.sub != nil {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// fetchFile fetches a text file from URL
|
||||
func fetchFile(URL string) io.Reader {
|
||||
resp, err := http.Get(URL)
|
||||
checkErr(err)
|
||||
defer resp.Body.Close()
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
checkErr(err)
|
||||
return strings.NewReader(string(body))
|
||||
}
|
||||
|
||||
// readFile reads a text file from path
|
||||
func readFile(path string) io.Reader {
|
||||
file, err := os.Open(os.Args[1])
|
||||
checkErr(err)
|
||||
return file
|
||||
}
|
||||
|
||||
func format(name, num, proto string) string {
|
||||
name = strings.ToUpper(name)
|
||||
// There are multiple entries for enosys and nosys, so comment them out.
|
||||
nm := re{str: name}
|
||||
if nm.Match(`^SYS_E?NOSYS$`) {
|
||||
name = fmt.Sprintf("// %s", name)
|
||||
}
|
||||
if name == `SYS_SYS_EXIT` {
|
||||
name = `SYS_EXIT`
|
||||
}
|
||||
return fmt.Sprintf(" %s = %s; // %s\n", name, num, proto)
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Get the OS (using GOOS_TARGET if it exist)
|
||||
goos = os.Getenv("GOOS_TARGET")
|
||||
if goos == "" {
|
||||
goos = os.Getenv("GOOS")
|
||||
}
|
||||
// Get the architecture (using GOARCH_TARGET if it exists)
|
||||
goarch = os.Getenv("GOARCH_TARGET")
|
||||
if goarch == "" {
|
||||
goarch = os.Getenv("GOARCH")
|
||||
}
|
||||
// Check if GOOS and GOARCH environment variables are defined
|
||||
if goarch == "" || goos == "" {
|
||||
fmt.Fprintf(os.Stderr, "GOARCH or GOOS not defined in environment\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
file := strings.TrimSpace(os.Args[1])
|
||||
var syscalls io.Reader
|
||||
if strings.HasPrefix(file, "https://") || strings.HasPrefix(file, "http://") {
|
||||
// Download syscalls.master file
|
||||
syscalls = fetchFile(file)
|
||||
} else {
|
||||
syscalls = readFile(file)
|
||||
}
|
||||
|
||||
var text, line string
|
||||
s := bufio.NewScanner(syscalls)
|
||||
for s.Scan() {
|
||||
t := re{str: line}
|
||||
if t.Match(`^(.*)\\$`) {
|
||||
// Handle continuation
|
||||
line = t.sub[1]
|
||||
line += strings.TrimLeft(s.Text(), " \t")
|
||||
} else {
|
||||
// New line
|
||||
line = s.Text()
|
||||
}
|
||||
t = re{str: line}
|
||||
if t.Match(`\\$`) {
|
||||
continue
|
||||
}
|
||||
t = re{str: line}
|
||||
|
||||
switch goos {
|
||||
case "dragonfly":
|
||||
if t.Match(`^([0-9]+)\s+STD\s+({ \S+\s+(\w+).*)$`) {
|
||||
num, proto := t.sub[1], t.sub[2]
|
||||
name := fmt.Sprintf("SYS_%s", t.sub[3])
|
||||
text += format(name, num, proto)
|
||||
}
|
||||
case "freebsd":
|
||||
if t.Match(`^([0-9]+)\s+\S+\s+(?:(?:NO)?STD|COMPAT10)\s+({ \S+\s+(\w+).*)$`) {
|
||||
num, proto := t.sub[1], t.sub[2]
|
||||
name := fmt.Sprintf("SYS_%s", t.sub[3])
|
||||
text += format(name, num, proto)
|
||||
}
|
||||
case "openbsd":
|
||||
if t.Match(`^([0-9]+)\s+STD\s+(NOLOCK\s+)?({ \S+\s+\*?(\w+).*)$`) {
|
||||
num, proto, name := t.sub[1], t.sub[3], t.sub[4]
|
||||
text += format(name, num, proto)
|
||||
}
|
||||
case "netbsd":
|
||||
if t.Match(`^([0-9]+)\s+((STD)|(NOERR))\s+(RUMP\s+)?({\s+\S+\s*\*?\s*\|(\S+)\|(\S*)\|(\w+).*\s+})(\s+(\S+))?$`) {
|
||||
num, proto, compat := t.sub[1], t.sub[6], t.sub[8]
|
||||
name := t.sub[7] + "_" + t.sub[9]
|
||||
if t.sub[11] != "" {
|
||||
name = t.sub[7] + "_" + t.sub[11]
|
||||
}
|
||||
name = strings.ToUpper(name)
|
||||
if compat == "" || compat == "13" || compat == "30" || compat == "50" {
|
||||
text += fmt.Sprintf(" %s = %s; // %s\n", name, num, proto)
|
||||
}
|
||||
}
|
||||
case "darwin":
|
||||
if t.Match(`^#define\s+SYS_(\w+)\s+([0-9]+)`) {
|
||||
name, num := t.sub[1], t.sub[2]
|
||||
name = strings.ToUpper(name)
|
||||
text += fmt.Sprintf(" SYS_%s = %s;\n", name, num)
|
||||
}
|
||||
default:
|
||||
fmt.Fprintf(os.Stderr, "unrecognized GOOS=%s\n", goos)
|
||||
os.Exit(1)
|
||||
|
||||
}
|
||||
}
|
||||
err := s.Err()
|
||||
checkErr(err)
|
||||
|
||||
fmt.Printf(template, cmdLine(), buildTags(), text)
|
||||
}
|
||||
|
||||
const template = `// %s
|
||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
||||
|
||||
// +build %s
|
||||
|
||||
package unix
|
||||
|
||||
const(
|
||||
%s)`
|
|
@ -1,237 +0,0 @@
|
|||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
// +build aix
|
||||
|
||||
/*
|
||||
Input to cgo -godefs. See also mkerrors.sh and mkall.sh
|
||||
*/
|
||||
|
||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
||||
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
||||
|
||||
package unix
|
||||
|
||||
/*
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/limits.h>
|
||||
#include <sys/un.h>
|
||||
#include <utime.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <sys/poll.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/statfs.h>
|
||||
#include <sys/termio.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <termios.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/icmp6.h>
|
||||
|
||||
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
enum {
|
||||
sizeofPtr = sizeof(void*),
|
||||
};
|
||||
|
||||
union sockaddr_all {
|
||||
struct sockaddr s1; // this one gets used for fields
|
||||
struct sockaddr_in s2; // these pad it out
|
||||
struct sockaddr_in6 s3;
|
||||
struct sockaddr_un s4;
|
||||
struct sockaddr_dl s5;
|
||||
};
|
||||
|
||||
struct sockaddr_any {
|
||||
struct sockaddr addr;
|
||||
char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)];
|
||||
};
|
||||
|
||||
*/
|
||||
import "C"
|
||||
|
||||
// Machine characteristics
|
||||
|
||||
const (
|
||||
SizeofPtr = C.sizeofPtr
|
||||
SizeofShort = C.sizeof_short
|
||||
SizeofInt = C.sizeof_int
|
||||
SizeofLong = C.sizeof_long
|
||||
SizeofLongLong = C.sizeof_longlong
|
||||
PathMax = C.PATH_MAX
|
||||
)
|
||||
|
||||
// Basic types
|
||||
|
||||
type (
|
||||
_C_short C.short
|
||||
_C_int C.int
|
||||
_C_long C.long
|
||||
_C_long_long C.longlong
|
||||
)
|
||||
|
||||
type off64 C.off64_t
|
||||
type off C.off_t
|
||||
type Mode_t C.mode_t
|
||||
|
||||
// Time
|
||||
|
||||
type Timespec C.struct_timespec
|
||||
|
||||
type Timeval C.struct_timeval
|
||||
|
||||
type Timeval32 C.struct_timeval32
|
||||
|
||||
type Timex C.struct_timex
|
||||
|
||||
type Time_t C.time_t
|
||||
|
||||
type Tms C.struct_tms
|
||||
|
||||
type Utimbuf C.struct_utimbuf
|
||||
|
||||
type Timezone C.struct_timezone
|
||||
|
||||
// Processes
|
||||
|
||||
type Rusage C.struct_rusage
|
||||
|
||||
type Rlimit C.struct_rlimit64
|
||||
|
||||
type Pid_t C.pid_t
|
||||
|
||||
type _Gid_t C.gid_t
|
||||
|
||||
type dev_t C.dev_t
|
||||
|
||||
// Files
|
||||
|
||||
type Stat_t C.struct_stat
|
||||
|
||||
type StatxTimestamp C.struct_statx_timestamp
|
||||
|
||||
type Statx_t C.struct_statx
|
||||
|
||||
type Dirent C.struct_dirent
|
||||
|
||||
// Sockets
|
||||
|
||||
type RawSockaddrInet4 C.struct_sockaddr_in
|
||||
|
||||
type RawSockaddrInet6 C.struct_sockaddr_in6
|
||||
|
||||
type RawSockaddrUnix C.struct_sockaddr_un
|
||||
|
||||
type RawSockaddrDatalink C.struct_sockaddr_dl
|
||||
|
||||
type RawSockaddr C.struct_sockaddr
|
||||
|
||||
type RawSockaddrAny C.struct_sockaddr_any
|
||||
|
||||
type _Socklen C.socklen_t
|
||||
|
||||
type Cmsghdr C.struct_cmsghdr
|
||||
|
||||
type ICMPv6Filter C.struct_icmp6_filter
|
||||
|
||||
type Iovec C.struct_iovec
|
||||
|
||||
type IPMreq C.struct_ip_mreq
|
||||
|
||||
type IPv6Mreq C.struct_ipv6_mreq
|
||||
|
||||
type IPv6MTUInfo C.struct_ip6_mtuinfo
|
||||
|
||||
type Linger C.struct_linger
|
||||
|
||||
type Msghdr C.struct_msghdr
|
||||
|
||||
const (
|
||||
SizeofSockaddrInet4 = C.sizeof_struct_sockaddr_in
|
||||
SizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
||||
SizeofSockaddrAny = C.sizeof_struct_sockaddr_any
|
||||
SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un
|
||||
SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl
|
||||
SizeofLinger = C.sizeof_struct_linger
|
||||
SizeofIPMreq = C.sizeof_struct_ip_mreq
|
||||
SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq
|
||||
SizeofIPv6MTUInfo = C.sizeof_struct_ip6_mtuinfo
|
||||
SizeofMsghdr = C.sizeof_struct_msghdr
|
||||
SizeofCmsghdr = C.sizeof_struct_cmsghdr
|
||||
SizeofICMPv6Filter = C.sizeof_struct_icmp6_filter
|
||||
)
|
||||
|
||||
// Routing and interface messages
|
||||
|
||||
const (
|
||||
SizeofIfMsghdr = C.sizeof_struct_if_msghdr
|
||||
)
|
||||
|
||||
type IfMsgHdr C.struct_if_msghdr
|
||||
|
||||
// Misc
|
||||
|
||||
type FdSet C.fd_set
|
||||
|
||||
type Utsname C.struct_utsname
|
||||
|
||||
type Ustat_t C.struct_ustat
|
||||
|
||||
type Sigset_t C.sigset_t
|
||||
|
||||
const (
|
||||
AT_FDCWD = C.AT_FDCWD
|
||||
AT_REMOVEDIR = C.AT_REMOVEDIR
|
||||
AT_SYMLINK_NOFOLLOW = C.AT_SYMLINK_NOFOLLOW
|
||||
)
|
||||
|
||||
// Terminal handling
|
||||
|
||||
type Termios C.struct_termios
|
||||
|
||||
type Termio C.struct_termio
|
||||
|
||||
type Winsize C.struct_winsize
|
||||
|
||||
//poll
|
||||
|
||||
type PollFd struct {
|
||||
Fd int32
|
||||
Events uint16
|
||||
Revents uint16
|
||||
}
|
||||
|
||||
const (
|
||||
POLLERR = C.POLLERR
|
||||
POLLHUP = C.POLLHUP
|
||||
POLLIN = C.POLLIN
|
||||
POLLNVAL = C.POLLNVAL
|
||||
POLLOUT = C.POLLOUT
|
||||
POLLPRI = C.POLLPRI
|
||||
POLLRDBAND = C.POLLRDBAND
|
||||
POLLRDNORM = C.POLLRDNORM
|
||||
POLLWRBAND = C.POLLWRBAND
|
||||
POLLWRNORM = C.POLLWRNORM
|
||||
)
|
||||
|
||||
//flock_t
|
||||
|
||||
type Flock_t C.struct_flock64
|
||||
|
||||
// Statfs
|
||||
|
||||
type Fsid_t C.struct_fsid_t
|
||||
type Fsid64_t C.struct_fsid64_t
|
||||
|
||||
type Statfs_t C.struct_statfs
|
||||
|
||||
const RNDGETENTCNT = 0x80045200
|
|
@ -1,283 +0,0 @@
|
|||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
/*
|
||||
Input to cgo -godefs. See README.md
|
||||
*/
|
||||
|
||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
||||
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
||||
|
||||
package unix
|
||||
|
||||
/*
|
||||
#define __DARWIN_UNIX03 0
|
||||
#define KERNEL
|
||||
#define _DARWIN_USE_64_BIT_INODE
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <poll.h>
|
||||
#include <signal.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
#include <mach/mach.h>
|
||||
#include <mach/message.h>
|
||||
#include <sys/event.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/signal.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <sys/wait.h>
|
||||
#include <net/bpf.h>
|
||||
#include <net/if.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <net/if_var.h>
|
||||
#include <net/route.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/icmp6.h>
|
||||
#include <netinet/tcp.h>
|
||||
|
||||
enum {
|
||||
sizeofPtr = sizeof(void*),
|
||||
};
|
||||
|
||||
union sockaddr_all {
|
||||
struct sockaddr s1; // this one gets used for fields
|
||||
struct sockaddr_in s2; // these pad it out
|
||||
struct sockaddr_in6 s3;
|
||||
struct sockaddr_un s4;
|
||||
struct sockaddr_dl s5;
|
||||
};
|
||||
|
||||
struct sockaddr_any {
|
||||
struct sockaddr addr;
|
||||
char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)];
|
||||
};
|
||||
|
||||
*/
|
||||
import "C"
|
||||
|
||||
// Machine characteristics
|
||||
|
||||
const (
|
||||
SizeofPtr = C.sizeofPtr
|
||||
SizeofShort = C.sizeof_short
|
||||
SizeofInt = C.sizeof_int
|
||||
SizeofLong = C.sizeof_long
|
||||
SizeofLongLong = C.sizeof_longlong
|
||||
)
|
||||
|
||||
// Basic types
|
||||
|
||||
type (
|
||||
_C_short C.short
|
||||
_C_int C.int
|
||||
_C_long C.long
|
||||
_C_long_long C.longlong
|
||||
)
|
||||
|
||||
// Time
|
||||
|
||||
type Timespec C.struct_timespec
|
||||
|
||||
type Timeval C.struct_timeval
|
||||
|
||||
type Timeval32 C.struct_timeval32
|
||||
|
||||
// Processes
|
||||
|
||||
type Rusage C.struct_rusage
|
||||
|
||||
type Rlimit C.struct_rlimit
|
||||
|
||||
type _Gid_t C.gid_t
|
||||
|
||||
// Files
|
||||
|
||||
type Stat_t C.struct_stat64
|
||||
|
||||
type Statfs_t C.struct_statfs64
|
||||
|
||||
type Flock_t C.struct_flock
|
||||
|
||||
type Fstore_t C.struct_fstore
|
||||
|
||||
type Radvisory_t C.struct_radvisory
|
||||
|
||||
type Fbootstraptransfer_t C.struct_fbootstraptransfer
|
||||
|
||||
type Log2phys_t C.struct_log2phys
|
||||
|
||||
type Fsid C.struct_fsid
|
||||
|
||||
type Dirent C.struct_dirent
|
||||
|
||||
// Sockets
|
||||
|
||||
type RawSockaddrInet4 C.struct_sockaddr_in
|
||||
|
||||
type RawSockaddrInet6 C.struct_sockaddr_in6
|
||||
|
||||
type RawSockaddrUnix C.struct_sockaddr_un
|
||||
|
||||
type RawSockaddrDatalink C.struct_sockaddr_dl
|
||||
|
||||
type RawSockaddr C.struct_sockaddr
|
||||
|
||||
type RawSockaddrAny C.struct_sockaddr_any
|
||||
|
||||
type _Socklen C.socklen_t
|
||||
|
||||
type Linger C.struct_linger
|
||||
|
||||
type Iovec C.struct_iovec
|
||||
|
||||
type IPMreq C.struct_ip_mreq
|
||||
|
||||
type IPv6Mreq C.struct_ipv6_mreq
|
||||
|
||||
type Msghdr C.struct_msghdr
|
||||
|
||||
type Cmsghdr C.struct_cmsghdr
|
||||
|
||||
type Inet4Pktinfo C.struct_in_pktinfo
|
||||
|
||||
type Inet6Pktinfo C.struct_in6_pktinfo
|
||||
|
||||
type IPv6MTUInfo C.struct_ip6_mtuinfo
|
||||
|
||||
type ICMPv6Filter C.struct_icmp6_filter
|
||||
|
||||
const (
|
||||
SizeofSockaddrInet4 = C.sizeof_struct_sockaddr_in
|
||||
SizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
||||
SizeofSockaddrAny = C.sizeof_struct_sockaddr_any
|
||||
SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un
|
||||
SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl
|
||||
SizeofLinger = C.sizeof_struct_linger
|
||||
SizeofIPMreq = C.sizeof_struct_ip_mreq
|
||||
SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq
|
||||
SizeofMsghdr = C.sizeof_struct_msghdr
|
||||
SizeofCmsghdr = C.sizeof_struct_cmsghdr
|
||||
SizeofInet4Pktinfo = C.sizeof_struct_in_pktinfo
|
||||
SizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo
|
||||
SizeofIPv6MTUInfo = C.sizeof_struct_ip6_mtuinfo
|
||||
SizeofICMPv6Filter = C.sizeof_struct_icmp6_filter
|
||||
)
|
||||
|
||||
// Ptrace requests
|
||||
|
||||
const (
|
||||
PTRACE_TRACEME = C.PT_TRACE_ME
|
||||
PTRACE_CONT = C.PT_CONTINUE
|
||||
PTRACE_KILL = C.PT_KILL
|
||||
)
|
||||
|
||||
// Events (kqueue, kevent)
|
||||
|
||||
type Kevent_t C.struct_kevent
|
||||
|
||||
// Select
|
||||
|
||||
type FdSet C.fd_set
|
||||
|
||||
// Routing and interface messages
|
||||
|
||||
const (
|
||||
SizeofIfMsghdr = C.sizeof_struct_if_msghdr
|
||||
SizeofIfData = C.sizeof_struct_if_data
|
||||
SizeofIfaMsghdr = C.sizeof_struct_ifa_msghdr
|
||||
SizeofIfmaMsghdr = C.sizeof_struct_ifma_msghdr
|
||||
SizeofIfmaMsghdr2 = C.sizeof_struct_ifma_msghdr2
|
||||
SizeofRtMsghdr = C.sizeof_struct_rt_msghdr
|
||||
SizeofRtMetrics = C.sizeof_struct_rt_metrics
|
||||
)
|
||||
|
||||
type IfMsghdr C.struct_if_msghdr
|
||||
|
||||
type IfData C.struct_if_data
|
||||
|
||||
type IfaMsghdr C.struct_ifa_msghdr
|
||||
|
||||
type IfmaMsghdr C.struct_ifma_msghdr
|
||||
|
||||
type IfmaMsghdr2 C.struct_ifma_msghdr2
|
||||
|
||||
type RtMsghdr C.struct_rt_msghdr
|
||||
|
||||
type RtMetrics C.struct_rt_metrics
|
||||
|
||||
// Berkeley packet filter
|
||||
|
||||
const (
|
||||
SizeofBpfVersion = C.sizeof_struct_bpf_version
|
||||
SizeofBpfStat = C.sizeof_struct_bpf_stat
|
||||
SizeofBpfProgram = C.sizeof_struct_bpf_program
|
||||
SizeofBpfInsn = C.sizeof_struct_bpf_insn
|
||||
SizeofBpfHdr = C.sizeof_struct_bpf_hdr
|
||||
)
|
||||
|
||||
type BpfVersion C.struct_bpf_version
|
||||
|
||||
type BpfStat C.struct_bpf_stat
|
||||
|
||||
type BpfProgram C.struct_bpf_program
|
||||
|
||||
type BpfInsn C.struct_bpf_insn
|
||||
|
||||
type BpfHdr C.struct_bpf_hdr
|
||||
|
||||
// Terminal handling
|
||||
|
||||
type Termios C.struct_termios
|
||||
|
||||
type Winsize C.struct_winsize
|
||||
|
||||
// fchmodat-like syscalls.
|
||||
|
||||
const (
|
||||
AT_FDCWD = C.AT_FDCWD
|
||||
AT_REMOVEDIR = C.AT_REMOVEDIR
|
||||
AT_SYMLINK_FOLLOW = C.AT_SYMLINK_FOLLOW
|
||||
AT_SYMLINK_NOFOLLOW = C.AT_SYMLINK_NOFOLLOW
|
||||
)
|
||||
|
||||
// poll
|
||||
|
||||
type PollFd C.struct_pollfd
|
||||
|
||||
const (
|
||||
POLLERR = C.POLLERR
|
||||
POLLHUP = C.POLLHUP
|
||||
POLLIN = C.POLLIN
|
||||
POLLNVAL = C.POLLNVAL
|
||||
POLLOUT = C.POLLOUT
|
||||
POLLPRI = C.POLLPRI
|
||||
POLLRDBAND = C.POLLRDBAND
|
||||
POLLRDNORM = C.POLLRDNORM
|
||||
POLLWRBAND = C.POLLWRBAND
|
||||
POLLWRNORM = C.POLLWRNORM
|
||||
)
|
||||
|
||||
// uname
|
||||
|
||||
type Utsname C.struct_utsname
|
||||
|
||||
// Clockinfo
|
||||
|
||||
const SizeofClockinfo = C.sizeof_struct_clockinfo
|
||||
|
||||
type Clockinfo C.struct_clockinfo
|
|
@ -1,263 +0,0 @@
|
|||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
/*
|
||||
Input to cgo -godefs. See README.md
|
||||
*/
|
||||
|
||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
||||
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
||||
|
||||
package unix
|
||||
|
||||
/*
|
||||
#define KERNEL
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <poll.h>
|
||||
#include <signal.h>
|
||||
#include <termios.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/event.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/signal.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <sys/wait.h>
|
||||
#include <net/bpf.h>
|
||||
#include <net/if.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <net/route.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/icmp6.h>
|
||||
#include <netinet/tcp.h>
|
||||
|
||||
enum {
|
||||
sizeofPtr = sizeof(void*),
|
||||
};
|
||||
|
||||
union sockaddr_all {
|
||||
struct sockaddr s1; // this one gets used for fields
|
||||
struct sockaddr_in s2; // these pad it out
|
||||
struct sockaddr_in6 s3;
|
||||
struct sockaddr_un s4;
|
||||
struct sockaddr_dl s5;
|
||||
};
|
||||
|
||||
struct sockaddr_any {
|
||||
struct sockaddr addr;
|
||||
char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)];
|
||||
};
|
||||
|
||||
*/
|
||||
import "C"
|
||||
|
||||
// Machine characteristics
|
||||
|
||||
const (
|
||||
SizeofPtr = C.sizeofPtr
|
||||
SizeofShort = C.sizeof_short
|
||||
SizeofInt = C.sizeof_int
|
||||
SizeofLong = C.sizeof_long
|
||||
SizeofLongLong = C.sizeof_longlong
|
||||
)
|
||||
|
||||
// Basic types
|
||||
|
||||
type (
|
||||
_C_short C.short
|
||||
_C_int C.int
|
||||
_C_long C.long
|
||||
_C_long_long C.longlong
|
||||
)
|
||||
|
||||
// Time
|
||||
|
||||
type Timespec C.struct_timespec
|
||||
|
||||
type Timeval C.struct_timeval
|
||||
|
||||
// Processes
|
||||
|
||||
type Rusage C.struct_rusage
|
||||
|
||||
type Rlimit C.struct_rlimit
|
||||
|
||||
type _Gid_t C.gid_t
|
||||
|
||||
// Files
|
||||
|
||||
type Stat_t C.struct_stat
|
||||
|
||||
type Statfs_t C.struct_statfs
|
||||
|
||||
type Flock_t C.struct_flock
|
||||
|
||||
type Dirent C.struct_dirent
|
||||
|
||||
type Fsid C.struct_fsid
|
||||
|
||||
// File system limits
|
||||
|
||||
const (
|
||||
PathMax = C.PATH_MAX
|
||||
)
|
||||
|
||||
// Sockets
|
||||
|
||||
type RawSockaddrInet4 C.struct_sockaddr_in
|
||||
|
||||
type RawSockaddrInet6 C.struct_sockaddr_in6
|
||||
|
||||
type RawSockaddrUnix C.struct_sockaddr_un
|
||||
|
||||
type RawSockaddrDatalink C.struct_sockaddr_dl
|
||||
|
||||
type RawSockaddr C.struct_sockaddr
|
||||
|
||||
type RawSockaddrAny C.struct_sockaddr_any
|
||||
|
||||
type _Socklen C.socklen_t
|
||||
|
||||
type Linger C.struct_linger
|
||||
|
||||
type Iovec C.struct_iovec
|
||||
|
||||
type IPMreq C.struct_ip_mreq
|
||||
|
||||
type IPv6Mreq C.struct_ipv6_mreq
|
||||
|
||||
type Msghdr C.struct_msghdr
|
||||
|
||||
type Cmsghdr C.struct_cmsghdr
|
||||
|
||||
type Inet6Pktinfo C.struct_in6_pktinfo
|
||||
|
||||
type IPv6MTUInfo C.struct_ip6_mtuinfo
|
||||
|
||||
type ICMPv6Filter C.struct_icmp6_filter
|
||||
|
||||
const (
|
||||
SizeofSockaddrInet4 = C.sizeof_struct_sockaddr_in
|
||||
SizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
||||
SizeofSockaddrAny = C.sizeof_struct_sockaddr_any
|
||||
SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un
|
||||
SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl
|
||||
SizeofLinger = C.sizeof_struct_linger
|
||||
SizeofIPMreq = C.sizeof_struct_ip_mreq
|
||||
SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq
|
||||
SizeofMsghdr = C.sizeof_struct_msghdr
|
||||
SizeofCmsghdr = C.sizeof_struct_cmsghdr
|
||||
SizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo
|
||||
SizeofIPv6MTUInfo = C.sizeof_struct_ip6_mtuinfo
|
||||
SizeofICMPv6Filter = C.sizeof_struct_icmp6_filter
|
||||
)
|
||||
|
||||
// Ptrace requests
|
||||
|
||||
const (
|
||||
PTRACE_TRACEME = C.PT_TRACE_ME
|
||||
PTRACE_CONT = C.PT_CONTINUE
|
||||
PTRACE_KILL = C.PT_KILL
|
||||
)
|
||||
|
||||
// Events (kqueue, kevent)
|
||||
|
||||
type Kevent_t C.struct_kevent
|
||||
|
||||
// Select
|
||||
|
||||
type FdSet C.fd_set
|
||||
|
||||
// Routing and interface messages
|
||||
|
||||
const (
|
||||
SizeofIfMsghdr = C.sizeof_struct_if_msghdr
|
||||
SizeofIfData = C.sizeof_struct_if_data
|
||||
SizeofIfaMsghdr = C.sizeof_struct_ifa_msghdr
|
||||
SizeofIfmaMsghdr = C.sizeof_struct_ifma_msghdr
|
||||
SizeofIfAnnounceMsghdr = C.sizeof_struct_if_announcemsghdr
|
||||
SizeofRtMsghdr = C.sizeof_struct_rt_msghdr
|
||||
SizeofRtMetrics = C.sizeof_struct_rt_metrics
|
||||
)
|
||||
|
||||
type IfMsghdr C.struct_if_msghdr
|
||||
|
||||
type IfData C.struct_if_data
|
||||
|
||||
type IfaMsghdr C.struct_ifa_msghdr
|
||||
|
||||
type IfmaMsghdr C.struct_ifma_msghdr
|
||||
|
||||
type IfAnnounceMsghdr C.struct_if_announcemsghdr
|
||||
|
||||
type RtMsghdr C.struct_rt_msghdr
|
||||
|
||||
type RtMetrics C.struct_rt_metrics
|
||||
|
||||
// Berkeley packet filter
|
||||
|
||||
const (
|
||||
SizeofBpfVersion = C.sizeof_struct_bpf_version
|
||||
SizeofBpfStat = C.sizeof_struct_bpf_stat
|
||||
SizeofBpfProgram = C.sizeof_struct_bpf_program
|
||||
SizeofBpfInsn = C.sizeof_struct_bpf_insn
|
||||
SizeofBpfHdr = C.sizeof_struct_bpf_hdr
|
||||
)
|
||||
|
||||
type BpfVersion C.struct_bpf_version
|
||||
|
||||
type BpfStat C.struct_bpf_stat
|
||||
|
||||
type BpfProgram C.struct_bpf_program
|
||||
|
||||
type BpfInsn C.struct_bpf_insn
|
||||
|
||||
type BpfHdr C.struct_bpf_hdr
|
||||
|
||||
// Terminal handling
|
||||
|
||||
type Termios C.struct_termios
|
||||
|
||||
type Winsize C.struct_winsize
|
||||
|
||||
// fchmodat-like syscalls.
|
||||
|
||||
const (
|
||||
AT_FDCWD = C.AT_FDCWD
|
||||
AT_SYMLINK_NOFOLLOW = C.AT_SYMLINK_NOFOLLOW
|
||||
)
|
||||
|
||||
// poll
|
||||
|
||||
type PollFd C.struct_pollfd
|
||||
|
||||
const (
|
||||
POLLERR = C.POLLERR
|
||||
POLLHUP = C.POLLHUP
|
||||
POLLIN = C.POLLIN
|
||||
POLLNVAL = C.POLLNVAL
|
||||
POLLOUT = C.POLLOUT
|
||||
POLLPRI = C.POLLPRI
|
||||
POLLRDBAND = C.POLLRDBAND
|
||||
POLLRDNORM = C.POLLRDNORM
|
||||
POLLWRBAND = C.POLLWRBAND
|
||||
POLLWRNORM = C.POLLWRNORM
|
||||
)
|
||||
|
||||
// Uname
|
||||
|
||||
type Utsname C.struct_utsname
|
|
@ -1,400 +0,0 @@
|
|||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
/*
|
||||
Input to cgo -godefs. See README.md
|
||||
*/
|
||||
|
||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
||||
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
||||
|
||||
package unix
|
||||
|
||||
/*
|
||||
#define _WANT_FREEBSD11_STAT 1
|
||||
#define _WANT_FREEBSD11_STATFS 1
|
||||
#define _WANT_FREEBSD11_DIRENT 1
|
||||
#define _WANT_FREEBSD11_KEVENT 1
|
||||
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <poll.h>
|
||||
#include <signal.h>
|
||||
#include <termios.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/capsicum.h>
|
||||
#include <sys/event.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/signal.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <sys/wait.h>
|
||||
#include <net/bpf.h>
|
||||
#include <net/if.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <net/route.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/icmp6.h>
|
||||
#include <netinet/tcp.h>
|
||||
|
||||
enum {
|
||||
sizeofPtr = sizeof(void*),
|
||||
};
|
||||
|
||||
union sockaddr_all {
|
||||
struct sockaddr s1; // this one gets used for fields
|
||||
struct sockaddr_in s2; // these pad it out
|
||||
struct sockaddr_in6 s3;
|
||||
struct sockaddr_un s4;
|
||||
struct sockaddr_dl s5;
|
||||
};
|
||||
|
||||
struct sockaddr_any {
|
||||
struct sockaddr addr;
|
||||
char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)];
|
||||
};
|
||||
|
||||
// This structure is a duplicate of if_data on FreeBSD 8-STABLE.
|
||||
// See /usr/include/net/if.h.
|
||||
struct if_data8 {
|
||||
u_char ifi_type;
|
||||
u_char ifi_physical;
|
||||
u_char ifi_addrlen;
|
||||
u_char ifi_hdrlen;
|
||||
u_char ifi_link_state;
|
||||
u_char ifi_spare_char1;
|
||||
u_char ifi_spare_char2;
|
||||
u_char ifi_datalen;
|
||||
u_long ifi_mtu;
|
||||
u_long ifi_metric;
|
||||
u_long ifi_baudrate;
|
||||
u_long ifi_ipackets;
|
||||
u_long ifi_ierrors;
|
||||
u_long ifi_opackets;
|
||||
u_long ifi_oerrors;
|
||||
u_long ifi_collisions;
|
||||
u_long ifi_ibytes;
|
||||
u_long ifi_obytes;
|
||||
u_long ifi_imcasts;
|
||||
u_long ifi_omcasts;
|
||||
u_long ifi_iqdrops;
|
||||
u_long ifi_noproto;
|
||||
u_long ifi_hwassist;
|
||||
// FIXME: these are now unions, so maybe need to change definitions?
|
||||
#undef ifi_epoch
|
||||
time_t ifi_epoch;
|
||||
#undef ifi_lastchange
|
||||
struct timeval ifi_lastchange;
|
||||
};
|
||||
|
||||
// This structure is a duplicate of if_msghdr on FreeBSD 8-STABLE.
|
||||
// See /usr/include/net/if.h.
|
||||
struct if_msghdr8 {
|
||||
u_short ifm_msglen;
|
||||
u_char ifm_version;
|
||||
u_char ifm_type;
|
||||
int ifm_addrs;
|
||||
int ifm_flags;
|
||||
u_short ifm_index;
|
||||
struct if_data8 ifm_data;
|
||||
};
|
||||
*/
|
||||
import "C"
|
||||
|
||||
// Machine characteristics
|
||||
|
||||
const (
|
||||
SizeofPtr = C.sizeofPtr
|
||||
SizeofShort = C.sizeof_short
|
||||
SizeofInt = C.sizeof_int
|
||||
SizeofLong = C.sizeof_long
|
||||
SizeofLongLong = C.sizeof_longlong
|
||||
)
|
||||
|
||||
// Basic types
|
||||
|
||||
type (
|
||||
_C_short C.short
|
||||
_C_int C.int
|
||||
_C_long C.long
|
||||
_C_long_long C.longlong
|
||||
)
|
||||
|
||||
// Time
|
||||
|
||||
type Timespec C.struct_timespec
|
||||
|
||||
type Timeval C.struct_timeval
|
||||
|
||||
// Processes
|
||||
|
||||
type Rusage C.struct_rusage
|
||||
|
||||
type Rlimit C.struct_rlimit
|
||||
|
||||
type _Gid_t C.gid_t
|
||||
|
||||
// Files
|
||||
|
||||
const (
|
||||
_statfsVersion = C.STATFS_VERSION
|
||||
_dirblksiz = C.DIRBLKSIZ
|
||||
)
|
||||
|
||||
type Stat_t C.struct_stat
|
||||
|
||||
type stat_freebsd11_t C.struct_freebsd11_stat
|
||||
|
||||
type Statfs_t C.struct_statfs
|
||||
|
||||
type statfs_freebsd11_t C.struct_freebsd11_statfs
|
||||
|
||||
type Flock_t C.struct_flock
|
||||
|
||||
type Dirent C.struct_dirent
|
||||
|
||||
type dirent_freebsd11 C.struct_freebsd11_dirent
|
||||
|
||||
type Fsid C.struct_fsid
|
||||
|
||||
// File system limits
|
||||
|
||||
const (
|
||||
PathMax = C.PATH_MAX
|
||||
)
|
||||
|
||||
// Advice to Fadvise
|
||||
|
||||
const (
|
||||
FADV_NORMAL = C.POSIX_FADV_NORMAL
|
||||
FADV_RANDOM = C.POSIX_FADV_RANDOM
|
||||
FADV_SEQUENTIAL = C.POSIX_FADV_SEQUENTIAL
|
||||
FADV_WILLNEED = C.POSIX_FADV_WILLNEED
|
||||
FADV_DONTNEED = C.POSIX_FADV_DONTNEED
|
||||
FADV_NOREUSE = C.POSIX_FADV_NOREUSE
|
||||
)
|
||||
|
||||
// Sockets
|
||||
|
||||
type RawSockaddrInet4 C.struct_sockaddr_in
|
||||
|
||||
type RawSockaddrInet6 C.struct_sockaddr_in6
|
||||
|
||||
type RawSockaddrUnix C.struct_sockaddr_un
|
||||
|
||||
type RawSockaddrDatalink C.struct_sockaddr_dl
|
||||
|
||||
type RawSockaddr C.struct_sockaddr
|
||||
|
||||
type RawSockaddrAny C.struct_sockaddr_any
|
||||
|
||||
type _Socklen C.socklen_t
|
||||
|
||||
type Linger C.struct_linger
|
||||
|
||||
type Iovec C.struct_iovec
|
||||
|
||||
type IPMreq C.struct_ip_mreq
|
||||
|
||||
type IPMreqn C.struct_ip_mreqn
|
||||
|
||||
type IPv6Mreq C.struct_ipv6_mreq
|
||||
|
||||
type Msghdr C.struct_msghdr
|
||||
|
||||
type Cmsghdr C.struct_cmsghdr
|
||||
|
||||
type Inet6Pktinfo C.struct_in6_pktinfo
|
||||
|
||||
type IPv6MTUInfo C.struct_ip6_mtuinfo
|
||||
|
||||
type ICMPv6Filter C.struct_icmp6_filter
|
||||
|
||||
const (
|
||||
SizeofSockaddrInet4 = C.sizeof_struct_sockaddr_in
|
||||
SizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
||||
SizeofSockaddrAny = C.sizeof_struct_sockaddr_any
|
||||
SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un
|
||||
SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl
|
||||
SizeofLinger = C.sizeof_struct_linger
|
||||
SizeofIPMreq = C.sizeof_struct_ip_mreq
|
||||
SizeofIPMreqn = C.sizeof_struct_ip_mreqn
|
||||
SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq
|
||||
SizeofMsghdr = C.sizeof_struct_msghdr
|
||||
SizeofCmsghdr = C.sizeof_struct_cmsghdr
|
||||
SizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo
|
||||
SizeofIPv6MTUInfo = C.sizeof_struct_ip6_mtuinfo
|
||||
SizeofICMPv6Filter = C.sizeof_struct_icmp6_filter
|
||||
)
|
||||
|
||||
// Ptrace requests
|
||||
|
||||
const (
|
||||
PTRACE_ATTACH = C.PT_ATTACH
|
||||
PTRACE_CONT = C.PT_CONTINUE
|
||||
PTRACE_DETACH = C.PT_DETACH
|
||||
PTRACE_GETFPREGS = C.PT_GETFPREGS
|
||||
PTRACE_GETFSBASE = C.PT_GETFSBASE
|
||||
PTRACE_GETLWPLIST = C.PT_GETLWPLIST
|
||||
PTRACE_GETNUMLWPS = C.PT_GETNUMLWPS
|
||||
PTRACE_GETREGS = C.PT_GETREGS
|
||||
PTRACE_GETXSTATE = C.PT_GETXSTATE
|
||||
PTRACE_IO = C.PT_IO
|
||||
PTRACE_KILL = C.PT_KILL
|
||||
PTRACE_LWPEVENTS = C.PT_LWP_EVENTS
|
||||
PTRACE_LWPINFO = C.PT_LWPINFO
|
||||
PTRACE_SETFPREGS = C.PT_SETFPREGS
|
||||
PTRACE_SETREGS = C.PT_SETREGS
|
||||
PTRACE_SINGLESTEP = C.PT_STEP
|
||||
PTRACE_TRACEME = C.PT_TRACE_ME
|
||||
)
|
||||
|
||||
const (
|
||||
PIOD_READ_D = C.PIOD_READ_D
|
||||
PIOD_WRITE_D = C.PIOD_WRITE_D
|
||||
PIOD_READ_I = C.PIOD_READ_I
|
||||
PIOD_WRITE_I = C.PIOD_WRITE_I
|
||||
)
|
||||
|
||||
const (
|
||||
PL_FLAG_BORN = C.PL_FLAG_BORN
|
||||
PL_FLAG_EXITED = C.PL_FLAG_EXITED
|
||||
PL_FLAG_SI = C.PL_FLAG_SI
|
||||
)
|
||||
|
||||
const (
|
||||
TRAP_BRKPT = C.TRAP_BRKPT
|
||||
TRAP_TRACE = C.TRAP_TRACE
|
||||
)
|
||||
|
||||
type PtraceLwpInfoStruct C.struct_ptrace_lwpinfo
|
||||
|
||||
type __Siginfo C.struct___siginfo
|
||||
|
||||
type Sigset_t C.sigset_t
|
||||
|
||||
type Reg C.struct_reg
|
||||
|
||||
type FpReg C.struct_fpreg
|
||||
|
||||
type PtraceIoDesc C.struct_ptrace_io_desc
|
||||
|
||||
// Events (kqueue, kevent)
|
||||
|
||||
type Kevent_t C.struct_kevent_freebsd11
|
||||
|
||||
// Select
|
||||
|
||||
type FdSet C.fd_set
|
||||
|
||||
// Routing and interface messages
|
||||
|
||||
const (
|
||||
sizeofIfMsghdr = C.sizeof_struct_if_msghdr
|
||||
SizeofIfMsghdr = C.sizeof_struct_if_msghdr8
|
||||
sizeofIfData = C.sizeof_struct_if_data
|
||||
SizeofIfData = C.sizeof_struct_if_data8
|
||||
SizeofIfaMsghdr = C.sizeof_struct_ifa_msghdr
|
||||
SizeofIfmaMsghdr = C.sizeof_struct_ifma_msghdr
|
||||
SizeofIfAnnounceMsghdr = C.sizeof_struct_if_announcemsghdr
|
||||
SizeofRtMsghdr = C.sizeof_struct_rt_msghdr
|
||||
SizeofRtMetrics = C.sizeof_struct_rt_metrics
|
||||
)
|
||||
|
||||
type ifMsghdr C.struct_if_msghdr
|
||||
|
||||
type IfMsghdr C.struct_if_msghdr8
|
||||
|
||||
type ifData C.struct_if_data
|
||||
|
||||
type IfData C.struct_if_data8
|
||||
|
||||
type IfaMsghdr C.struct_ifa_msghdr
|
||||
|
||||
type IfmaMsghdr C.struct_ifma_msghdr
|
||||
|
||||
type IfAnnounceMsghdr C.struct_if_announcemsghdr
|
||||
|
||||
type RtMsghdr C.struct_rt_msghdr
|
||||
|
||||
type RtMetrics C.struct_rt_metrics
|
||||
|
||||
// Berkeley packet filter
|
||||
|
||||
const (
|
||||
SizeofBpfVersion = C.sizeof_struct_bpf_version
|
||||
SizeofBpfStat = C.sizeof_struct_bpf_stat
|
||||
SizeofBpfZbuf = C.sizeof_struct_bpf_zbuf
|
||||
SizeofBpfProgram = C.sizeof_struct_bpf_program
|
||||
SizeofBpfInsn = C.sizeof_struct_bpf_insn
|
||||
SizeofBpfHdr = C.sizeof_struct_bpf_hdr
|
||||
SizeofBpfZbufHeader = C.sizeof_struct_bpf_zbuf_header
|
||||
)
|
||||
|
||||
type BpfVersion C.struct_bpf_version
|
||||
|
||||
type BpfStat C.struct_bpf_stat
|
||||
|
||||
type BpfZbuf C.struct_bpf_zbuf
|
||||
|
||||
type BpfProgram C.struct_bpf_program
|
||||
|
||||
type BpfInsn C.struct_bpf_insn
|
||||
|
||||
type BpfHdr C.struct_bpf_hdr
|
||||
|
||||
type BpfZbufHeader C.struct_bpf_zbuf_header
|
||||
|
||||
// Terminal handling
|
||||
|
||||
type Termios C.struct_termios
|
||||
|
||||
type Winsize C.struct_winsize
|
||||
|
||||
// fchmodat-like syscalls.
|
||||
|
||||
const (
|
||||
AT_FDCWD = C.AT_FDCWD
|
||||
AT_REMOVEDIR = C.AT_REMOVEDIR
|
||||
AT_SYMLINK_FOLLOW = C.AT_SYMLINK_FOLLOW
|
||||
AT_SYMLINK_NOFOLLOW = C.AT_SYMLINK_NOFOLLOW
|
||||
)
|
||||
|
||||
// poll
|
||||
|
||||
type PollFd C.struct_pollfd
|
||||
|
||||
const (
|
||||
POLLERR = C.POLLERR
|
||||
POLLHUP = C.POLLHUP
|
||||
POLLIN = C.POLLIN
|
||||
POLLINIGNEOF = C.POLLINIGNEOF
|
||||
POLLNVAL = C.POLLNVAL
|
||||
POLLOUT = C.POLLOUT
|
||||
POLLPRI = C.POLLPRI
|
||||
POLLRDBAND = C.POLLRDBAND
|
||||
POLLRDNORM = C.POLLRDNORM
|
||||
POLLWRBAND = C.POLLWRBAND
|
||||
POLLWRNORM = C.POLLWRNORM
|
||||
)
|
||||
|
||||
// Capabilities
|
||||
|
||||
type CapRights C.struct_cap_rights
|
||||
|
||||
// Uname
|
||||
|
||||
type Utsname C.struct_utsname
|
|
@ -1,290 +0,0 @@
|
|||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
/*
|
||||
Input to cgo -godefs. See README.md
|
||||
*/
|
||||
|
||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
||||
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
||||
|
||||
package unix
|
||||
|
||||
/*
|
||||
#define KERNEL
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <poll.h>
|
||||
#include <signal.h>
|
||||
#include <termios.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/event.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/signal.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <sys/wait.h>
|
||||
#include <net/bpf.h>
|
||||
#include <net/if.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <net/route.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/icmp6.h>
|
||||
#include <netinet/tcp.h>
|
||||
|
||||
enum {
|
||||
sizeofPtr = sizeof(void*),
|
||||
};
|
||||
|
||||
union sockaddr_all {
|
||||
struct sockaddr s1; // this one gets used for fields
|
||||
struct sockaddr_in s2; // these pad it out
|
||||
struct sockaddr_in6 s3;
|
||||
struct sockaddr_un s4;
|
||||
struct sockaddr_dl s5;
|
||||
};
|
||||
|
||||
struct sockaddr_any {
|
||||
struct sockaddr addr;
|
||||
char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)];
|
||||
};
|
||||
|
||||
*/
|
||||
import "C"
|
||||
|
||||
// Machine characteristics
|
||||
|
||||
const (
|
||||
SizeofPtr = C.sizeofPtr
|
||||
SizeofShort = C.sizeof_short
|
||||
SizeofInt = C.sizeof_int
|
||||
SizeofLong = C.sizeof_long
|
||||
SizeofLongLong = C.sizeof_longlong
|
||||
)
|
||||
|
||||
// Basic types
|
||||
|
||||
type (
|
||||
_C_short C.short
|
||||
_C_int C.int
|
||||
_C_long C.long
|
||||
_C_long_long C.longlong
|
||||
)
|
||||
|
||||
// Time
|
||||
|
||||
type Timespec C.struct_timespec
|
||||
|
||||
type Timeval C.struct_timeval
|
||||
|
||||
// Processes
|
||||
|
||||
type Rusage C.struct_rusage
|
||||
|
||||
type Rlimit C.struct_rlimit
|
||||
|
||||
type _Gid_t C.gid_t
|
||||
|
||||
// Files
|
||||
|
||||
type Stat_t C.struct_stat
|
||||
|
||||
type Statfs_t C.struct_statfs
|
||||
|
||||
type Flock_t C.struct_flock
|
||||
|
||||
type Dirent C.struct_dirent
|
||||
|
||||
type Fsid C.fsid_t
|
||||
|
||||
// File system limits
|
||||
|
||||
const (
|
||||
PathMax = C.PATH_MAX
|
||||
)
|
||||
|
||||
// Advice to Fadvise
|
||||
|
||||
const (
|
||||
FADV_NORMAL = C.POSIX_FADV_NORMAL
|
||||
FADV_RANDOM = C.POSIX_FADV_RANDOM
|
||||
FADV_SEQUENTIAL = C.POSIX_FADV_SEQUENTIAL
|
||||
FADV_WILLNEED = C.POSIX_FADV_WILLNEED
|
||||
FADV_DONTNEED = C.POSIX_FADV_DONTNEED
|
||||
FADV_NOREUSE = C.POSIX_FADV_NOREUSE
|
||||
)
|
||||
|
||||
// Sockets
|
||||
|
||||
type RawSockaddrInet4 C.struct_sockaddr_in
|
||||
|
||||
type RawSockaddrInet6 C.struct_sockaddr_in6
|
||||
|
||||
type RawSockaddrUnix C.struct_sockaddr_un
|
||||
|
||||
type RawSockaddrDatalink C.struct_sockaddr_dl
|
||||
|
||||
type RawSockaddr C.struct_sockaddr
|
||||
|
||||
type RawSockaddrAny C.struct_sockaddr_any
|
||||
|
||||
type _Socklen C.socklen_t
|
||||
|
||||
type Linger C.struct_linger
|
||||
|
||||
type Iovec C.struct_iovec
|
||||
|
||||
type IPMreq C.struct_ip_mreq
|
||||
|
||||
type IPv6Mreq C.struct_ipv6_mreq
|
||||
|
||||
type Msghdr C.struct_msghdr
|
||||
|
||||
type Cmsghdr C.struct_cmsghdr
|
||||
|
||||
type Inet6Pktinfo C.struct_in6_pktinfo
|
||||
|
||||
type IPv6MTUInfo C.struct_ip6_mtuinfo
|
||||
|
||||
type ICMPv6Filter C.struct_icmp6_filter
|
||||
|
||||
const (
|
||||
SizeofSockaddrInet4 = C.sizeof_struct_sockaddr_in
|
||||
SizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
||||
SizeofSockaddrAny = C.sizeof_struct_sockaddr_any
|
||||
SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un
|
||||
SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl
|
||||
SizeofLinger = C.sizeof_struct_linger
|
||||
SizeofIPMreq = C.sizeof_struct_ip_mreq
|
||||
SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq
|
||||
SizeofMsghdr = C.sizeof_struct_msghdr
|
||||
SizeofCmsghdr = C.sizeof_struct_cmsghdr
|
||||
SizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo
|
||||
SizeofIPv6MTUInfo = C.sizeof_struct_ip6_mtuinfo
|
||||
SizeofICMPv6Filter = C.sizeof_struct_icmp6_filter
|
||||
)
|
||||
|
||||
// Ptrace requests
|
||||
|
||||
const (
|
||||
PTRACE_TRACEME = C.PT_TRACE_ME
|
||||
PTRACE_CONT = C.PT_CONTINUE
|
||||
PTRACE_KILL = C.PT_KILL
|
||||
)
|
||||
|
||||
// Events (kqueue, kevent)
|
||||
|
||||
type Kevent_t C.struct_kevent
|
||||
|
||||
// Select
|
||||
|
||||
type FdSet C.fd_set
|
||||
|
||||
// Routing and interface messages
|
||||
|
||||
const (
|
||||
SizeofIfMsghdr = C.sizeof_struct_if_msghdr
|
||||
SizeofIfData = C.sizeof_struct_if_data
|
||||
SizeofIfaMsghdr = C.sizeof_struct_ifa_msghdr
|
||||
SizeofIfAnnounceMsghdr = C.sizeof_struct_if_announcemsghdr
|
||||
SizeofRtMsghdr = C.sizeof_struct_rt_msghdr
|
||||
SizeofRtMetrics = C.sizeof_struct_rt_metrics
|
||||
)
|
||||
|
||||
type IfMsghdr C.struct_if_msghdr
|
||||
|
||||
type IfData C.struct_if_data
|
||||
|
||||
type IfaMsghdr C.struct_ifa_msghdr
|
||||
|
||||
type IfAnnounceMsghdr C.struct_if_announcemsghdr
|
||||
|
||||
type RtMsghdr C.struct_rt_msghdr
|
||||
|
||||
type RtMetrics C.struct_rt_metrics
|
||||
|
||||
type Mclpool C.struct_mclpool
|
||||
|
||||
// Berkeley packet filter
|
||||
|
||||
const (
|
||||
SizeofBpfVersion = C.sizeof_struct_bpf_version
|
||||
SizeofBpfStat = C.sizeof_struct_bpf_stat
|
||||
SizeofBpfProgram = C.sizeof_struct_bpf_program
|
||||
SizeofBpfInsn = C.sizeof_struct_bpf_insn
|
||||
SizeofBpfHdr = C.sizeof_struct_bpf_hdr
|
||||
)
|
||||
|
||||
type BpfVersion C.struct_bpf_version
|
||||
|
||||
type BpfStat C.struct_bpf_stat
|
||||
|
||||
type BpfProgram C.struct_bpf_program
|
||||
|
||||
type BpfInsn C.struct_bpf_insn
|
||||
|
||||
type BpfHdr C.struct_bpf_hdr
|
||||
|
||||
type BpfTimeval C.struct_bpf_timeval
|
||||
|
||||
// Terminal handling
|
||||
|
||||
type Termios C.struct_termios
|
||||
|
||||
type Winsize C.struct_winsize
|
||||
|
||||
type Ptmget C.struct_ptmget
|
||||
|
||||
// fchmodat-like syscalls.
|
||||
|
||||
const (
|
||||
AT_FDCWD = C.AT_FDCWD
|
||||
AT_SYMLINK_FOLLOW = C.AT_SYMLINK_FOLLOW
|
||||
AT_SYMLINK_NOFOLLOW = C.AT_SYMLINK_NOFOLLOW
|
||||
)
|
||||
|
||||
// poll
|
||||
|
||||
type PollFd C.struct_pollfd
|
||||
|
||||
const (
|
||||
POLLERR = C.POLLERR
|
||||
POLLHUP = C.POLLHUP
|
||||
POLLIN = C.POLLIN
|
||||
POLLNVAL = C.POLLNVAL
|
||||
POLLOUT = C.POLLOUT
|
||||
POLLPRI = C.POLLPRI
|
||||
POLLRDBAND = C.POLLRDBAND
|
||||
POLLRDNORM = C.POLLRDNORM
|
||||
POLLWRBAND = C.POLLWRBAND
|
||||
POLLWRNORM = C.POLLWRNORM
|
||||
)
|
||||
|
||||
// Sysctl
|
||||
|
||||
type Sysctlnode C.struct_sysctlnode
|
||||
|
||||
// Uname
|
||||
|
||||
type Utsname C.struct_utsname
|
||||
|
||||
// Clockinfo
|
||||
|
||||
const SizeofClockinfo = C.sizeof_struct_clockinfo
|
||||
|
||||
type Clockinfo C.struct_clockinfo
|
|
@ -1,283 +0,0 @@
|
|||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
/*
|
||||
Input to cgo -godefs. See README.md
|
||||
*/
|
||||
|
||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
||||
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
||||
|
||||
package unix
|
||||
|
||||
/*
|
||||
#define KERNEL
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <poll.h>
|
||||
#include <signal.h>
|
||||
#include <termios.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/event.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/signal.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <sys/wait.h>
|
||||
#include <uvm/uvmexp.h>
|
||||
#include <net/bpf.h>
|
||||
#include <net/if.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <net/route.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/icmp6.h>
|
||||
#include <netinet/tcp.h>
|
||||
|
||||
enum {
|
||||
sizeofPtr = sizeof(void*),
|
||||
};
|
||||
|
||||
union sockaddr_all {
|
||||
struct sockaddr s1; // this one gets used for fields
|
||||
struct sockaddr_in s2; // these pad it out
|
||||
struct sockaddr_in6 s3;
|
||||
struct sockaddr_un s4;
|
||||
struct sockaddr_dl s5;
|
||||
};
|
||||
|
||||
struct sockaddr_any {
|
||||
struct sockaddr addr;
|
||||
char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)];
|
||||
};
|
||||
|
||||
*/
|
||||
import "C"
|
||||
|
||||
// Machine characteristics
|
||||
|
||||
const (
|
||||
SizeofPtr = C.sizeofPtr
|
||||
SizeofShort = C.sizeof_short
|
||||
SizeofInt = C.sizeof_int
|
||||
SizeofLong = C.sizeof_long
|
||||
SizeofLongLong = C.sizeof_longlong
|
||||
)
|
||||
|
||||
// Basic types
|
||||
|
||||
type (
|
||||
_C_short C.short
|
||||
_C_int C.int
|
||||
_C_long C.long
|
||||
_C_long_long C.longlong
|
||||
)
|
||||
|
||||
// Time
|
||||
|
||||
type Timespec C.struct_timespec
|
||||
|
||||
type Timeval C.struct_timeval
|
||||
|
||||
// Processes
|
||||
|
||||
type Rusage C.struct_rusage
|
||||
|
||||
type Rlimit C.struct_rlimit
|
||||
|
||||
type _Gid_t C.gid_t
|
||||
|
||||
// Files
|
||||
|
||||
type Stat_t C.struct_stat
|
||||
|
||||
type Statfs_t C.struct_statfs
|
||||
|
||||
type Flock_t C.struct_flock
|
||||
|
||||
type Dirent C.struct_dirent
|
||||
|
||||
type Fsid C.fsid_t
|
||||
|
||||
// File system limits
|
||||
|
||||
const (
|
||||
PathMax = C.PATH_MAX
|
||||
)
|
||||
|
||||
// Sockets
|
||||
|
||||
type RawSockaddrInet4 C.struct_sockaddr_in
|
||||
|
||||
type RawSockaddrInet6 C.struct_sockaddr_in6
|
||||
|
||||
type RawSockaddrUnix C.struct_sockaddr_un
|
||||
|
||||
type RawSockaddrDatalink C.struct_sockaddr_dl
|
||||
|
||||
type RawSockaddr C.struct_sockaddr
|
||||
|
||||
type RawSockaddrAny C.struct_sockaddr_any
|
||||
|
||||
type _Socklen C.socklen_t
|
||||
|
||||
type Linger C.struct_linger
|
||||
|
||||
type Iovec C.struct_iovec
|
||||
|
||||
type IPMreq C.struct_ip_mreq
|
||||
|
||||
type IPv6Mreq C.struct_ipv6_mreq
|
||||
|
||||
type Msghdr C.struct_msghdr
|
||||
|
||||
type Cmsghdr C.struct_cmsghdr
|
||||
|
||||
type Inet6Pktinfo C.struct_in6_pktinfo
|
||||
|
||||
type IPv6MTUInfo C.struct_ip6_mtuinfo
|
||||
|
||||
type ICMPv6Filter C.struct_icmp6_filter
|
||||
|
||||
const (
|
||||
SizeofSockaddrInet4 = C.sizeof_struct_sockaddr_in
|
||||
SizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
||||
SizeofSockaddrAny = C.sizeof_struct_sockaddr_any
|
||||
SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un
|
||||
SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl
|
||||
SizeofLinger = C.sizeof_struct_linger
|
||||
SizeofIPMreq = C.sizeof_struct_ip_mreq
|
||||
SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq
|
||||
SizeofMsghdr = C.sizeof_struct_msghdr
|
||||
SizeofCmsghdr = C.sizeof_struct_cmsghdr
|
||||
SizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo
|
||||
SizeofIPv6MTUInfo = C.sizeof_struct_ip6_mtuinfo
|
||||
SizeofICMPv6Filter = C.sizeof_struct_icmp6_filter
|
||||
)
|
||||
|
||||
// Ptrace requests
|
||||
|
||||
const (
|
||||
PTRACE_TRACEME = C.PT_TRACE_ME
|
||||
PTRACE_CONT = C.PT_CONTINUE
|
||||
PTRACE_KILL = C.PT_KILL
|
||||
)
|
||||
|
||||
// Events (kqueue, kevent)
|
||||
|
||||
type Kevent_t C.struct_kevent
|
||||
|
||||
// Select
|
||||
|
||||
type FdSet C.fd_set
|
||||
|
||||
// Routing and interface messages
|
||||
|
||||
const (
|
||||
SizeofIfMsghdr = C.sizeof_struct_if_msghdr
|
||||
SizeofIfData = C.sizeof_struct_if_data
|
||||
SizeofIfaMsghdr = C.sizeof_struct_ifa_msghdr
|
||||
SizeofIfAnnounceMsghdr = C.sizeof_struct_if_announcemsghdr
|
||||
SizeofRtMsghdr = C.sizeof_struct_rt_msghdr
|
||||
SizeofRtMetrics = C.sizeof_struct_rt_metrics
|
||||
)
|
||||
|
||||
type IfMsghdr C.struct_if_msghdr
|
||||
|
||||
type IfData C.struct_if_data
|
||||
|
||||
type IfaMsghdr C.struct_ifa_msghdr
|
||||
|
||||
type IfAnnounceMsghdr C.struct_if_announcemsghdr
|
||||
|
||||
type RtMsghdr C.struct_rt_msghdr
|
||||
|
||||
type RtMetrics C.struct_rt_metrics
|
||||
|
||||
type Mclpool C.struct_mclpool
|
||||
|
||||
// Berkeley packet filter
|
||||
|
||||
const (
|
||||
SizeofBpfVersion = C.sizeof_struct_bpf_version
|
||||
SizeofBpfStat = C.sizeof_struct_bpf_stat
|
||||
SizeofBpfProgram = C.sizeof_struct_bpf_program
|
||||
SizeofBpfInsn = C.sizeof_struct_bpf_insn
|
||||
SizeofBpfHdr = C.sizeof_struct_bpf_hdr
|
||||
)
|
||||
|
||||
type BpfVersion C.struct_bpf_version
|
||||
|
||||
type BpfStat C.struct_bpf_stat
|
||||
|
||||
type BpfProgram C.struct_bpf_program
|
||||
|
||||
type BpfInsn C.struct_bpf_insn
|
||||
|
||||
type BpfHdr C.struct_bpf_hdr
|
||||
|
||||
type BpfTimeval C.struct_bpf_timeval
|
||||
|
||||
// Terminal handling
|
||||
|
||||
type Termios C.struct_termios
|
||||
|
||||
type Winsize C.struct_winsize
|
||||
|
||||
// fchmodat-like syscalls.
|
||||
|
||||
const (
|
||||
AT_FDCWD = C.AT_FDCWD
|
||||
AT_SYMLINK_FOLLOW = C.AT_SYMLINK_FOLLOW
|
||||
AT_SYMLINK_NOFOLLOW = C.AT_SYMLINK_NOFOLLOW
|
||||
)
|
||||
|
||||
// poll
|
||||
|
||||
type PollFd C.struct_pollfd
|
||||
|
||||
const (
|
||||
POLLERR = C.POLLERR
|
||||
POLLHUP = C.POLLHUP
|
||||
POLLIN = C.POLLIN
|
||||
POLLNVAL = C.POLLNVAL
|
||||
POLLOUT = C.POLLOUT
|
||||
POLLPRI = C.POLLPRI
|
||||
POLLRDBAND = C.POLLRDBAND
|
||||
POLLRDNORM = C.POLLRDNORM
|
||||
POLLWRBAND = C.POLLWRBAND
|
||||
POLLWRNORM = C.POLLWRNORM
|
||||
)
|
||||
|
||||
// Signal Sets
|
||||
|
||||
type Sigset_t C.sigset_t
|
||||
|
||||
// Uname
|
||||
|
||||
type Utsname C.struct_utsname
|
||||
|
||||
// Uvmexp
|
||||
|
||||
const SizeofUvmexp = C.sizeof_struct_uvmexp
|
||||
|
||||
type Uvmexp C.struct_uvmexp
|
||||
|
||||
// Clockinfo
|
||||
|
||||
const SizeofClockinfo = C.sizeof_struct_clockinfo
|
||||
|
||||
type Clockinfo C.struct_clockinfo
|
|
@ -1,266 +0,0 @@
|
|||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
/*
|
||||
Input to cgo -godefs. See README.md
|
||||
*/
|
||||
|
||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
||||
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
||||
|
||||
package unix
|
||||
|
||||
/*
|
||||
#define KERNEL
|
||||
// These defines ensure that builds done on newer versions of Solaris are
|
||||
// backwards-compatible with older versions of Solaris and
|
||||
// OpenSolaris-based derivatives.
|
||||
#define __USE_SUNOS_SOCKETS__ // msghdr
|
||||
#define __USE_LEGACY_PROTOTYPES__ // iovec
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <netdb.h>
|
||||
#include <limits.h>
|
||||
#include <poll.h>
|
||||
#include <signal.h>
|
||||
#include <termios.h>
|
||||
#include <termio.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/signal.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/statvfs.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/times.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/wait.h>
|
||||
#include <net/bpf.h>
|
||||
#include <net/if.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <net/route.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/icmp6.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <ustat.h>
|
||||
#include <utime.h>
|
||||
|
||||
enum {
|
||||
sizeofPtr = sizeof(void*),
|
||||
};
|
||||
|
||||
union sockaddr_all {
|
||||
struct sockaddr s1; // this one gets used for fields
|
||||
struct sockaddr_in s2; // these pad it out
|
||||
struct sockaddr_in6 s3;
|
||||
struct sockaddr_un s4;
|
||||
struct sockaddr_dl s5;
|
||||
};
|
||||
|
||||
struct sockaddr_any {
|
||||
struct sockaddr addr;
|
||||
char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)];
|
||||
};
|
||||
|
||||
*/
|
||||
import "C"
|
||||
|
||||
// Machine characteristics
|
||||
|
||||
const (
|
||||
SizeofPtr = C.sizeofPtr
|
||||
SizeofShort = C.sizeof_short
|
||||
SizeofInt = C.sizeof_int
|
||||
SizeofLong = C.sizeof_long
|
||||
SizeofLongLong = C.sizeof_longlong
|
||||
PathMax = C.PATH_MAX
|
||||
MaxHostNameLen = C.MAXHOSTNAMELEN
|
||||
)
|
||||
|
||||
// Basic types
|
||||
|
||||
type (
|
||||
_C_short C.short
|
||||
_C_int C.int
|
||||
_C_long C.long
|
||||
_C_long_long C.longlong
|
||||
)
|
||||
|
||||
// Time
|
||||
|
||||
type Timespec C.struct_timespec
|
||||
|
||||
type Timeval C.struct_timeval
|
||||
|
||||
type Timeval32 C.struct_timeval32
|
||||
|
||||
type Tms C.struct_tms
|
||||
|
||||
type Utimbuf C.struct_utimbuf
|
||||
|
||||
// Processes
|
||||
|
||||
type Rusage C.struct_rusage
|
||||
|
||||
type Rlimit C.struct_rlimit
|
||||
|
||||
type _Gid_t C.gid_t
|
||||
|
||||
// Files
|
||||
|
||||
type Stat_t C.struct_stat
|
||||
|
||||
type Flock_t C.struct_flock
|
||||
|
||||
type Dirent C.struct_dirent
|
||||
|
||||
// Filesystems
|
||||
|
||||
type _Fsblkcnt_t C.fsblkcnt_t
|
||||
|
||||
type Statvfs_t C.struct_statvfs
|
||||
|
||||
// Sockets
|
||||
|
||||
type RawSockaddrInet4 C.struct_sockaddr_in
|
||||
|
||||
type RawSockaddrInet6 C.struct_sockaddr_in6
|
||||
|
||||
type RawSockaddrUnix C.struct_sockaddr_un
|
||||
|
||||
type RawSockaddrDatalink C.struct_sockaddr_dl
|
||||
|
||||
type RawSockaddr C.struct_sockaddr
|
||||
|
||||
type RawSockaddrAny C.struct_sockaddr_any
|
||||
|
||||
type _Socklen C.socklen_t
|
||||
|
||||
type Linger C.struct_linger
|
||||
|
||||
type Iovec C.struct_iovec
|
||||
|
||||
type IPMreq C.struct_ip_mreq
|
||||
|
||||
type IPv6Mreq C.struct_ipv6_mreq
|
||||
|
||||
type Msghdr C.struct_msghdr
|
||||
|
||||
type Cmsghdr C.struct_cmsghdr
|
||||
|
||||
type Inet6Pktinfo C.struct_in6_pktinfo
|
||||
|
||||
type IPv6MTUInfo C.struct_ip6_mtuinfo
|
||||
|
||||
type ICMPv6Filter C.struct_icmp6_filter
|
||||
|
||||
const (
|
||||
SizeofSockaddrInet4 = C.sizeof_struct_sockaddr_in
|
||||
SizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
||||
SizeofSockaddrAny = C.sizeof_struct_sockaddr_any
|
||||
SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un
|
||||
SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl
|
||||
SizeofLinger = C.sizeof_struct_linger
|
||||
SizeofIPMreq = C.sizeof_struct_ip_mreq
|
||||
SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq
|
||||
SizeofMsghdr = C.sizeof_struct_msghdr
|
||||
SizeofCmsghdr = C.sizeof_struct_cmsghdr
|
||||
SizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo
|
||||
SizeofIPv6MTUInfo = C.sizeof_struct_ip6_mtuinfo
|
||||
SizeofICMPv6Filter = C.sizeof_struct_icmp6_filter
|
||||
)
|
||||
|
||||
// Select
|
||||
|
||||
type FdSet C.fd_set
|
||||
|
||||
// Misc
|
||||
|
||||
type Utsname C.struct_utsname
|
||||
|
||||
type Ustat_t C.struct_ustat
|
||||
|
||||
const (
|
||||
AT_FDCWD = C.AT_FDCWD
|
||||
AT_SYMLINK_NOFOLLOW = C.AT_SYMLINK_NOFOLLOW
|
||||
AT_SYMLINK_FOLLOW = C.AT_SYMLINK_FOLLOW
|
||||
AT_REMOVEDIR = C.AT_REMOVEDIR
|
||||
AT_EACCESS = C.AT_EACCESS
|
||||
)
|
||||
|
||||
// Routing and interface messages
|
||||
|
||||
const (
|
||||
SizeofIfMsghdr = C.sizeof_struct_if_msghdr
|
||||
SizeofIfData = C.sizeof_struct_if_data
|
||||
SizeofIfaMsghdr = C.sizeof_struct_ifa_msghdr
|
||||
SizeofRtMsghdr = C.sizeof_struct_rt_msghdr
|
||||
SizeofRtMetrics = C.sizeof_struct_rt_metrics
|
||||
)
|
||||
|
||||
type IfMsghdr C.struct_if_msghdr
|
||||
|
||||
type IfData C.struct_if_data
|
||||
|
||||
type IfaMsghdr C.struct_ifa_msghdr
|
||||
|
||||
type RtMsghdr C.struct_rt_msghdr
|
||||
|
||||
type RtMetrics C.struct_rt_metrics
|
||||
|
||||
// Berkeley packet filter
|
||||
|
||||
const (
|
||||
SizeofBpfVersion = C.sizeof_struct_bpf_version
|
||||
SizeofBpfStat = C.sizeof_struct_bpf_stat
|
||||
SizeofBpfProgram = C.sizeof_struct_bpf_program
|
||||
SizeofBpfInsn = C.sizeof_struct_bpf_insn
|
||||
SizeofBpfHdr = C.sizeof_struct_bpf_hdr
|
||||
)
|
||||
|
||||
type BpfVersion C.struct_bpf_version
|
||||
|
||||
type BpfStat C.struct_bpf_stat
|
||||
|
||||
type BpfProgram C.struct_bpf_program
|
||||
|
||||
type BpfInsn C.struct_bpf_insn
|
||||
|
||||
type BpfTimeval C.struct_bpf_timeval
|
||||
|
||||
type BpfHdr C.struct_bpf_hdr
|
||||
|
||||
// Terminal handling
|
||||
|
||||
type Termios C.struct_termios
|
||||
|
||||
type Termio C.struct_termio
|
||||
|
||||
type Winsize C.struct_winsize
|
||||
|
||||
// poll
|
||||
|
||||
type PollFd C.struct_pollfd
|
||||
|
||||
const (
|
||||
POLLERR = C.POLLERR
|
||||
POLLHUP = C.POLLHUP
|
||||
POLLIN = C.POLLIN
|
||||
POLLNVAL = C.POLLNVAL
|
||||
POLLOUT = C.POLLOUT
|
||||
POLLPRI = C.POLLPRI
|
||||
POLLRDBAND = C.POLLRDBAND
|
||||
POLLRDNORM = C.POLLRDNORM
|
||||
POLLWRBAND = C.POLLWRBAND
|
||||
POLLWRNORM = C.POLLWRNORM
|
||||
)
|
|
@ -1 +0,0 @@
|
|||
Google Inc.
|
|
@ -1,202 +0,0 @@
|
|||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
|
@ -1,62 +0,0 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2017 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package codes
|
||||
|
||||
import "strconv"
|
||||
|
||||
func (c Code) String() string {
|
||||
switch c {
|
||||
case OK:
|
||||
return "OK"
|
||||
case Canceled:
|
||||
return "Canceled"
|
||||
case Unknown:
|
||||
return "Unknown"
|
||||
case InvalidArgument:
|
||||
return "InvalidArgument"
|
||||
case DeadlineExceeded:
|
||||
return "DeadlineExceeded"
|
||||
case NotFound:
|
||||
return "NotFound"
|
||||
case AlreadyExists:
|
||||
return "AlreadyExists"
|
||||
case PermissionDenied:
|
||||
return "PermissionDenied"
|
||||
case ResourceExhausted:
|
||||
return "ResourceExhausted"
|
||||
case FailedPrecondition:
|
||||
return "FailedPrecondition"
|
||||
case Aborted:
|
||||
return "Aborted"
|
||||
case OutOfRange:
|
||||
return "OutOfRange"
|
||||
case Unimplemented:
|
||||
return "Unimplemented"
|
||||
case Internal:
|
||||
return "Internal"
|
||||
case Unavailable:
|
||||
return "Unavailable"
|
||||
case DataLoss:
|
||||
return "DataLoss"
|
||||
case Unauthenticated:
|
||||
return "Unauthenticated"
|
||||
default:
|
||||
return "Code(" + strconv.FormatInt(int64(c), 10) + ")"
|
||||
}
|
||||
}
|
|
@ -1,197 +0,0 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2014 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// Package codes defines the canonical error codes used by gRPC. It is
|
||||
// consistent across various languages.
|
||||
package codes // import "google.golang.org/grpc/codes"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// A Code is an unsigned 32-bit error code as defined in the gRPC spec.
|
||||
type Code uint32
|
||||
|
||||
const (
|
||||
// OK is returned on success.
|
||||
OK Code = 0
|
||||
|
||||
// Canceled indicates the operation was canceled (typically by the caller).
|
||||
Canceled Code = 1
|
||||
|
||||
// Unknown error. An example of where this error may be returned is
|
||||
// if a Status value received from another address space belongs to
|
||||
// an error-space that is not known in this address space. Also
|
||||
// errors raised by APIs that do not return enough error information
|
||||
// may be converted to this error.
|
||||
Unknown Code = 2
|
||||
|
||||
// InvalidArgument indicates client specified an invalid argument.
|
||||
// Note that this differs from FailedPrecondition. It indicates arguments
|
||||
// that are problematic regardless of the state of the system
|
||||
// (e.g., a malformed file name).
|
||||
InvalidArgument Code = 3
|
||||
|
||||
// DeadlineExceeded means operation expired before completion.
|
||||
// For operations that change the state of the system, this error may be
|
||||
// returned even if the operation has completed successfully. For
|
||||
// example, a successful response from a server could have been delayed
|
||||
// long enough for the deadline to expire.
|
||||
DeadlineExceeded Code = 4
|
||||
|
||||
// NotFound means some requested entity (e.g., file or directory) was
|
||||
// not found.
|
||||
NotFound Code = 5
|
||||
|
||||
// AlreadyExists means an attempt to create an entity failed because one
|
||||
// already exists.
|
||||
AlreadyExists Code = 6
|
||||
|
||||
// PermissionDenied indicates the caller does not have permission to
|
||||
// execute the specified operation. It must not be used for rejections
|
||||
// caused by exhausting some resource (use ResourceExhausted
|
||||
// instead for those errors). It must not be
|
||||
// used if the caller cannot be identified (use Unauthenticated
|
||||
// instead for those errors).
|
||||
PermissionDenied Code = 7
|
||||
|
||||
// ResourceExhausted indicates some resource has been exhausted, perhaps
|
||||
// a per-user quota, or perhaps the entire file system is out of space.
|
||||
ResourceExhausted Code = 8
|
||||
|
||||
// FailedPrecondition indicates operation was rejected because the
|
||||
// system is not in a state required for the operation's execution.
|
||||
// For example, directory to be deleted may be non-empty, an rmdir
|
||||
// operation is applied to a non-directory, etc.
|
||||
//
|
||||
// A litmus test that may help a service implementor in deciding
|
||||
// between FailedPrecondition, Aborted, and Unavailable:
|
||||
// (a) Use Unavailable if the client can retry just the failing call.
|
||||
// (b) Use Aborted if the client should retry at a higher-level
|
||||
// (e.g., restarting a read-modify-write sequence).
|
||||
// (c) Use FailedPrecondition if the client should not retry until
|
||||
// the system state has been explicitly fixed. E.g., if an "rmdir"
|
||||
// fails because the directory is non-empty, FailedPrecondition
|
||||
// should be returned since the client should not retry unless
|
||||
// they have first fixed up the directory by deleting files from it.
|
||||
// (d) Use FailedPrecondition if the client performs conditional
|
||||
// REST Get/Update/Delete on a resource and the resource on the
|
||||
// server does not match the condition. E.g., conflicting
|
||||
// read-modify-write on the same resource.
|
||||
FailedPrecondition Code = 9
|
||||
|
||||
// Aborted indicates the operation was aborted, typically due to a
|
||||
// concurrency issue like sequencer check failures, transaction aborts,
|
||||
// etc.
|
||||
//
|
||||
// See litmus test above for deciding between FailedPrecondition,
|
||||
// Aborted, and Unavailable.
|
||||
Aborted Code = 10
|
||||
|
||||
// OutOfRange means operation was attempted past the valid range.
|
||||
// E.g., seeking or reading past end of file.
|
||||
//
|
||||
// Unlike InvalidArgument, this error indicates a problem that may
|
||||
// be fixed if the system state changes. For example, a 32-bit file
|
||||
// system will generate InvalidArgument if asked to read at an
|
||||
// offset that is not in the range [0,2^32-1], but it will generate
|
||||
// OutOfRange if asked to read from an offset past the current
|
||||
// file size.
|
||||
//
|
||||
// There is a fair bit of overlap between FailedPrecondition and
|
||||
// OutOfRange. We recommend using OutOfRange (the more specific
|
||||
// error) when it applies so that callers who are iterating through
|
||||
// a space can easily look for an OutOfRange error to detect when
|
||||
// they are done.
|
||||
OutOfRange Code = 11
|
||||
|
||||
// Unimplemented indicates operation is not implemented or not
|
||||
// supported/enabled in this service.
|
||||
Unimplemented Code = 12
|
||||
|
||||
// Internal errors. Means some invariants expected by underlying
|
||||
// system has been broken. If you see one of these errors,
|
||||
// something is very broken.
|
||||
Internal Code = 13
|
||||
|
||||
// Unavailable indicates the service is currently unavailable.
|
||||
// This is a most likely a transient condition and may be corrected
|
||||
// by retrying with a backoff.
|
||||
//
|
||||
// See litmus test above for deciding between FailedPrecondition,
|
||||
// Aborted, and Unavailable.
|
||||
Unavailable Code = 14
|
||||
|
||||
// DataLoss indicates unrecoverable data loss or corruption.
|
||||
DataLoss Code = 15
|
||||
|
||||
// Unauthenticated indicates the request does not have valid
|
||||
// authentication credentials for the operation.
|
||||
Unauthenticated Code = 16
|
||||
|
||||
_maxCode = 17
|
||||
)
|
||||
|
||||
var strToCode = map[string]Code{
|
||||
`"OK"`: OK,
|
||||
`"CANCELLED"`:/* [sic] */ Canceled,
|
||||
`"UNKNOWN"`: Unknown,
|
||||
`"INVALID_ARGUMENT"`: InvalidArgument,
|
||||
`"DEADLINE_EXCEEDED"`: DeadlineExceeded,
|
||||
`"NOT_FOUND"`: NotFound,
|
||||
`"ALREADY_EXISTS"`: AlreadyExists,
|
||||
`"PERMISSION_DENIED"`: PermissionDenied,
|
||||
`"RESOURCE_EXHAUSTED"`: ResourceExhausted,
|
||||
`"FAILED_PRECONDITION"`: FailedPrecondition,
|
||||
`"ABORTED"`: Aborted,
|
||||
`"OUT_OF_RANGE"`: OutOfRange,
|
||||
`"UNIMPLEMENTED"`: Unimplemented,
|
||||
`"INTERNAL"`: Internal,
|
||||
`"UNAVAILABLE"`: Unavailable,
|
||||
`"DATA_LOSS"`: DataLoss,
|
||||
`"UNAUTHENTICATED"`: Unauthenticated,
|
||||
}
|
||||
|
||||
// UnmarshalJSON unmarshals b into the Code.
|
||||
func (c *Code) UnmarshalJSON(b []byte) error {
|
||||
// From json.Unmarshaler: By convention, to approximate the behavior of
|
||||
// Unmarshal itself, Unmarshalers implement UnmarshalJSON([]byte("null")) as
|
||||
// a no-op.
|
||||
if string(b) == "null" {
|
||||
return nil
|
||||
}
|
||||
if c == nil {
|
||||
return fmt.Errorf("nil receiver passed to UnmarshalJSON")
|
||||
}
|
||||
|
||||
if ci, err := strconv.ParseUint(string(b), 10, 32); err == nil {
|
||||
if ci >= _maxCode {
|
||||
return fmt.Errorf("invalid code: %q", ci)
|
||||
}
|
||||
|
||||
*c = Code(ci)
|
||||
return nil
|
||||
}
|
||||
|
||||
if jc, ok := strToCode[string(b)]; ok {
|
||||
*c = jc
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("invalid code: %q", string(b))
|
||||
}
|
|
@ -1,18 +1,18 @@
|
|||
# github.com/aead/siphash v1.0.1
|
||||
github.com/aead/siphash
|
||||
# github.com/btcsuite/btcd v0.0.0-20190824003749-130ea5bddde3
|
||||
# github.com/btcsuite/btcd v0.20.1-beta
|
||||
github.com/btcsuite/btcd/addrmgr
|
||||
github.com/btcsuite/btcd/blockchain
|
||||
github.com/btcsuite/btcd/btcec
|
||||
github.com/btcsuite/btcd/btcjson
|
||||
github.com/btcsuite/btcd/chaincfg
|
||||
github.com/btcsuite/btcd/chaincfg/chainhash
|
||||
github.com/btcsuite/btcd/connmgr
|
||||
github.com/btcsuite/btcd/database
|
||||
github.com/btcsuite/btcd/peer
|
||||
github.com/btcsuite/btcd/rpcclient
|
||||
github.com/btcsuite/btcd/txscript
|
||||
github.com/btcsuite/btcd/wire
|
||||
github.com/btcsuite/btcd/btcec
|
||||
github.com/btcsuite/btcd/addrmgr
|
||||
github.com/btcsuite/btcd/blockchain
|
||||
github.com/btcsuite/btcd/connmgr
|
||||
github.com/btcsuite/btcd/peer
|
||||
github.com/btcsuite/btcd/database
|
||||
# github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f
|
||||
github.com/btcsuite/btclog
|
||||
# github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d
|
||||
|
@ -22,12 +22,12 @@ github.com/btcsuite/btcutil/bech32
|
|||
github.com/btcsuite/btcutil/gcs
|
||||
github.com/btcsuite/btcutil/gcs/builder
|
||||
github.com/btcsuite/btcutil/hdkeychain
|
||||
# github.com/btcsuite/btcwallet v0.0.0-20190911065739-d5cdeb4b91b0
|
||||
# github.com/btcsuite/btcwallet v0.10.0
|
||||
github.com/btcsuite/btcwallet/chain
|
||||
github.com/btcsuite/btcwallet/waddrmgr
|
||||
github.com/btcsuite/btcwallet/internal/zero
|
||||
github.com/btcsuite/btcwallet/snacl
|
||||
# github.com/btcsuite/btcwallet/walletdb v1.0.0
|
||||
github.com/btcsuite/btcwallet/waddrmgr
|
||||
# github.com/btcsuite/btcwallet/walletdb v1.1.0
|
||||
github.com/btcsuite/btcwallet/walletdb
|
||||
github.com/btcsuite/btcwallet/walletdb/bdb
|
||||
github.com/btcsuite/btcwallet/walletdb/migration
|
||||
|
@ -49,21 +49,21 @@ github.com/golang/protobuf/proto
|
|||
github.com/kkdai/bstream
|
||||
# github.com/lightninglabs/gozmq v0.0.0-20190710231225-cea2a031735d
|
||||
github.com/lightninglabs/gozmq
|
||||
# github.com/lightninglabs/neutrino v0.0.0-20190910092203-46d9c1c55f44 => github.com/muun/neutrino v0.0.0-20190914162326-7082af0fa257
|
||||
# github.com/lightninglabs/neutrino v0.10.0 => github.com/muun/neutrino v0.0.0-20190914162326-7082af0fa257
|
||||
github.com/lightninglabs/neutrino
|
||||
github.com/lightninglabs/neutrino/headerfs
|
||||
github.com/lightninglabs/neutrino/banman
|
||||
github.com/lightninglabs/neutrino/blockntfns
|
||||
github.com/lightninglabs/neutrino/cache
|
||||
github.com/lightninglabs/neutrino/cache/lru
|
||||
github.com/lightninglabs/neutrino/chainsync
|
||||
github.com/lightninglabs/neutrino/filterdb
|
||||
github.com/lightninglabs/neutrino/headerfs
|
||||
github.com/lightninglabs/neutrino/headerlist
|
||||
github.com/lightninglabs/neutrino/pushtx
|
||||
# github.com/lightningnetwork/lnd v0.7.1-beta-rc2
|
||||
github.com/lightningnetwork/lnd/zpay32
|
||||
# github.com/lightningnetwork/lnd v0.8.0-beta
|
||||
github.com/lightningnetwork/lnd/lnwire
|
||||
github.com/lightningnetwork/lnd/tor
|
||||
github.com/lightningnetwork/lnd/zpay32
|
||||
# github.com/lightningnetwork/lnd/queue v1.0.1
|
||||
github.com/lightningnetwork/lnd/queue
|
||||
# github.com/lightningnetwork/lnd/ticker v1.0.0
|
||||
|
@ -71,23 +71,21 @@ github.com/lightningnetwork/lnd/ticker
|
|||
# github.com/miekg/dns v0.0.0-20171125082028-79bfde677fa8
|
||||
github.com/miekg/dns
|
||||
github.com/miekg/dns/internal/socket
|
||||
# github.com/muun/libwallet v0.1.2
|
||||
# github.com/muun/libwallet v0.1.4
|
||||
github.com/muun/libwallet
|
||||
# github.com/pkg/errors v0.8.1
|
||||
github.com/pkg/errors
|
||||
# golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7
|
||||
golang.org/x/crypto/ripemd160
|
||||
golang.org/x/crypto/scrypt
|
||||
golang.org/x/crypto/pbkdf2
|
||||
golang.org/x/crypto/nacl/secretbox
|
||||
golang.org/x/crypto/internal/subtle
|
||||
golang.org/x/crypto/nacl/secretbox
|
||||
golang.org/x/crypto/pbkdf2
|
||||
golang.org/x/crypto/poly1305
|
||||
golang.org/x/crypto/ripemd160
|
||||
golang.org/x/crypto/salsa20/salsa
|
||||
golang.org/x/crypto/scrypt
|
||||
# golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3
|
||||
golang.org/x/net/proxy
|
||||
golang.org/x/net/internal/socks
|
||||
golang.org/x/net/proxy
|
||||
# golang.org/x/sys v0.0.0-20190904154756-749cb33beabd
|
||||
golang.org/x/sys/unix
|
||||
golang.org/x/sys/cpu
|
||||
# google.golang.org/grpc v1.18.0
|
||||
google.golang.org/grpc/codes
|
||||
golang.org/x/sys/unix
|
||||
|
|
Loading…
Reference in New Issue