From 592f5da5209ef4c4fba6f4cd7e3a27191e0a7200 Mon Sep 17 00:00:00 2001 From: Chris Gianelloni Date: Sat, 2 Sep 2023 14:18:10 -0400 Subject: [PATCH] feat: stubbed tx Signed-off-by: Chris Gianelloni --- .github/workflows/golangci-lint.yml | 2 +- Dockerfile | 3 +- cmd/bluefin/main.go | 4 + go.mod | 6 +- go.sum | 11 +- internal/config/config.go | 2 +- internal/tx/tx.go | 185 ++++++++++++++++++++++++++++ internal/worker/worker.go | 4 +- 8 files changed, 209 insertions(+), 8 deletions(-) create mode 100644 internal/tx/tx.go diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml index 02a504f..e08d4e6 100644 --- a/.github/workflows/golangci-lint.yml +++ b/.github/workflows/golangci-lint.yml @@ -18,7 +18,7 @@ jobs: name: lint strategy: matrix: - go-version: [1.19.x] + go-version: [1.20.x] platform: [ubuntu-latest, macos-latest] runs-on: ${{ matrix.platform }} steps: diff --git a/Dockerfile b/Dockerfile index 4f9e47f..2da9101 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,5 @@ -FROM ghcr.io/blinklabs-io/go:1.19.12-1 AS build +# FROM ghcr.io/blinklabs-io/go:1.19.12-1 AS build +FROM cgr.dev/chainguard/go AS build WORKDIR /code COPY . . diff --git a/cmd/bluefin/main.go b/cmd/bluefin/main.go index 32306f7..4fc57e3 100644 --- a/cmd/bluefin/main.go +++ b/cmd/bluefin/main.go @@ -26,6 +26,7 @@ import ( "github.com/blinklabs-io/bluefin/internal/logging" "github.com/blinklabs-io/bluefin/internal/miner" "github.com/blinklabs-io/bluefin/internal/storage" + "github.com/blinklabs-io/bluefin/internal/tx" "github.com/blinklabs-io/bluefin/internal/version" "github.com/blinklabs-io/bluefin/internal/wallet" ) @@ -68,6 +69,9 @@ func main() { bursa := wallet.GetWallet() logger.Infof("loaded mnemonic for address: %s", bursa.PaymentAddress) + // Fake Tx + tx.SendTx() + // Start indexer logger.Infof("starting indexer on %s", cfg.Indexer.Network) if err := indexer.GetIndexer().Start(); err != nil { diff --git a/go.mod b/go.mod index 154c6c7..d7706a6 100644 --- a/go.mod +++ b/go.mod @@ -1,8 +1,10 @@ module github.com/blinklabs-io/bluefin -go 1.19 +go 1.20 require ( + github.com/Salvionied/apollo v1.0.3 + github.com/Salvionied/cbor/v2 v2.6.0 github.com/blinklabs-io/bursa v0.2.0 github.com/blinklabs-io/gouroboros v0.52.0 github.com/blinklabs-io/snek v0.9.0 @@ -45,7 +47,9 @@ require ( go.opencensus.io v0.22.5 // indirect go.uber.org/multierr v1.10.0 // indirect golang.org/x/crypto v0.12.0 // indirect + golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 // indirect golang.org/x/net v0.10.0 // indirect golang.org/x/sys v0.11.0 // indirect + golang.org/x/text v0.12.0 // indirect google.golang.org/protobuf v1.28.1 // indirect ) diff --git a/go.sum b/go.sum index a97fe4d..1cd9640 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,9 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/Salvionied/apollo v1.0.3 h1:M33+acwHDVlysUUqstVaJMhTQnyQpv0rnqHCwluMTBQ= +github.com/Salvionied/apollo v1.0.3/go.mod h1:OBwLhqLcjLE3pwYi0Z/oC2/9I1vpGLZGkstzDBOX6TI= +github.com/Salvionied/cbor/v2 v2.6.0 h1:OEwlZLiodLdNeM9wFoSydLvj6/rHRaxu5G8VzwXSeuY= +github.com/Salvionied/cbor/v2 v2.6.0/go.mod h1:oFxaUo/mQ5sG1k459nzctGdYa80jy0ZqZ9pln9C/fGw= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= github.com/blinklabs-io/bursa v0.2.0 h1:C14bkl+bB7jamH4E5LqNpGxvXjSBl1YMaU+E9Z3rx2c= @@ -57,8 +61,8 @@ github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEW github.com/google/flatbuffers v1.12.1 h1:MVlul7pQNoDzWRLTw5imwYsl+usrS1TXG2H4jg6ImGw= github.com/google/flatbuffers v1.12.1/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jinzhu/copier v0.4.0 h1:w3ciUoD19shMCRargcpm0cm91ytaBhDvuRpz1ODO/U8= @@ -111,6 +115,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk= golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 h1:k/i9J1pBpvlfR+9QsetwPyERsqu1GIbi967PQMq3Ivc= +golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= @@ -146,6 +152,8 @@ golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc= +golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -156,7 +164,6 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= diff --git a/internal/config/config.go b/internal/config/config.go index 235935b..aa19ebf 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -100,7 +100,7 @@ var globalConfig = &Config{ ListenPort: 8081, }, Indexer: IndexerConfig{ - Network: "mainnet", + Network: "mainnet", }, Storage: StorageConfig{ // TODO: pick a better location diff --git a/internal/tx/tx.go b/internal/tx/tx.go new file mode 100644 index 0000000..333b78e --- /dev/null +++ b/internal/tx/tx.go @@ -0,0 +1,185 @@ +// Copyright 2023 Blink Labs, LLC. +// +// 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 tx + +import ( + "encoding/hex" + + "github.com/Salvionied/apollo" + serAddress "github.com/Salvionied/apollo/serialization/Address" + "github.com/Salvionied/apollo/serialization/Key" + "github.com/Salvionied/apollo/serialization/PlutusData" + "github.com/Salvionied/apollo/serialization/Redeemer" + "github.com/Salvionied/apollo/serialization/UTxO" + "github.com/Salvionied/cbor/v2" + + "github.com/blinklabs-io/bluefin/internal/config" + "github.com/blinklabs-io/bluefin/internal/logging" + "github.com/blinklabs-io/bluefin/internal/miner" + "github.com/blinklabs-io/bluefin/internal/wallet" +) + +func SendTx() { + createTx([][]byte{}) +} + +func createTx(utxosBytes [][]byte) { + cfg := config.GetConfig() + logger := logging.GetLogger() + bursa := wallet.GetWallet() + + // TODO: get these from elsewhere + validatorHash := "123456" // from genesis + currentTipSlotNumber := 1234 + refInputHash := "01751095ea408a3ebe6083b4de4de8a24b635085183ab8a2ac76273ef8fff5dd" + refInputId := 0 + ValidatorOutRef := UTxO.UTxO{} + Nonce := "12345" + blockData := miner.BlockData{} + + pdInterlink := PlutusData.PlutusIndefArray{} + for _, val := range blockData.Interlink { + pdInterlink = append(pdInterlink, PlutusData.PlutusData{ + PlutusDataType: PlutusData.PlutusBytes, + Value: val}) + } + targetHash, err := hex.DecodeString(blockData.TargetHash) + if err != nil { + panic(err) + } + utxoBytes := []byte("foo") + + pd := PlutusData.PlutusData{ + TagNr: 121, + PlutusDataType: PlutusData.PlutusArray, + Value: PlutusData.PlutusIndefArray{ + PlutusData.PlutusData{ + PlutusDataType: PlutusData.PlutusInt, + Value: blockData.BlockNumber + 1}, + PlutusData.PlutusData{ + PlutusDataType: PlutusData.PlutusBytes, + Value: targetHash}, + PlutusData.PlutusData{ + PlutusDataType: PlutusData.PlutusInt, + Value: blockData.LeadingZeros}, + PlutusData.PlutusData{ + PlutusDataType: PlutusData.PlutusInt, + Value: blockData.DifficultyNumber}, + PlutusData.PlutusData{ + PlutusDataType: PlutusData.PlutusInt, + Value: blockData.EpochTime}, //NEEDS FIXING + PlutusData.PlutusData{ + PlutusDataType: PlutusData.PlutusInt, + Value: blockData.RealTimeNow + 90000}, + PlutusData.PlutusData{ + PlutusDataType: PlutusData.PlutusBytes, + Value: []byte(blockData.Message)}, + PlutusData.PlutusData{ + PlutusDataType: PlutusData.PlutusArray, + Value: pdInterlink}, + }} + + marshaled, _ := cbor.Marshal(pd) + postDatum := PlutusData.PlutusData{ + PlutusDataType: PlutusData.PlutusArray, + Value: []PlutusData.PlutusData{ + PlutusData.PlutusData{ + PlutusDataType: PlutusData.PlutusInt, + Value: 1, + }, + PlutusData.PlutusData{ + PlutusDataType: PlutusData.PlutusBytes, + TagNr: 24, + Value: marshaled, + }}} + + // TODO: apollo + contractAddress, _ := serAddress.DecodeAddress(cfg.Indexer.ScriptAddress) + myAddress, _ := serAddress.DecodeAddress(bursa.PaymentAddress) + cc := apollo.NewEmptyBackend() + apollob := apollo.New(&cc) + apollob = apollob. + SetWalletFromBech32(bursa.PaymentAddress). + SetWalletAsChangeAddress() + var utxos []UTxO.UTxO + for u := range utxoBytes { + var utxo UTxO.UTxO + str, _ := hex.DecodeString(string(u)) + _ = cbor.Unmarshal(str, &utxo) + utxos = append(utxos, utxo) + } + apollob = apollob.AddLoadedUTxOs(utxos...) + apollob = apollob. + PayToContract(contractAddress, &postDatum, int(ValidatorOutRef.Output.Lovelace()), true, apollo.NewUnit(validatorHash, "lord tuna", 1)). + SetTtl(int64(currentTipSlotNumber+180000)). + PayToAddress(myAddress, 2000000, apollo.NewUnit(validatorHash, "TUNA", 5000000000)). + SetValidityStart(int64(currentTipSlotNumber)).MintAssetsWithRedeemer( + apollo.NewUnit(validatorHash, "TUNA", 5000000000), + Redeemer.Redeemer{ + Tag: Redeemer.MINT, + Index: 0, + Data: PlutusData.PlutusData{ + PlutusDataType: PlutusData.PlutusArray, + TagNr: 121, + Value: PlutusData.PlutusIndefArray{}, + }, + }). + AddReferenceInput(refInputHash, refInputId). + CollectFrom( + ValidatorOutRef, + Redeemer.Redeemer{ + Tag: Redeemer.SPEND, + Data: PlutusData.PlutusData{ + PlutusDataType: PlutusData.PlutusArray, + TagNr: 122, + Value: PlutusData.PlutusIndefArray{ + PlutusData.PlutusData{ + PlutusDataType: PlutusData.PlutusBytes, + Value: Nonce, + }}, + }, + }, + ) + tx, err := apollob.Complete() + if err != nil { + panic(err) + } + + // TODO: get the proper type from apollo + vKeyBytes, err := hex.DecodeString(bursa.PaymentVKey.CborHex) + if err != nil { + panic(err) + } + sKeyBytes, err := hex.DecodeString(bursa.PaymentSKey.CborHex) + if err != nil { + panic(err) + } + vkey := Key.VerificationKey{Payload: vKeyBytes} + skey := Key.SigningKey{Payload: sKeyBytes} + tx = tx.SignWithSkey(vkey, skey) + logger.Infof("submitting block...") + txId, err := SendToSubmitAPI(tx.GetTx().Bytes()) + if err != nil { + panic(err) + } + + logger.Infof("fake tx id %s from %s to %s", txId, myAddress.String(), contractAddress.String()) +} + +func SendToSubmitAPI(cborBytes []byte) (string, error) { + logger := logging.GetLogger() + logger.Infof("debug: %s", cborBytes) + return "", nil +} diff --git a/internal/worker/worker.go b/internal/worker/worker.go index 8f8a19f..ec160ce 100644 --- a/internal/worker/worker.go +++ b/internal/worker/worker.go @@ -53,7 +53,7 @@ func (m *Manager) Start(params WorkerParams) { default: break } - // TODO + // TODO: miner here randVal := rand.Intn(100) if randVal == 42 { logger.Infof("worker %d found result", workerIdx) @@ -70,7 +70,7 @@ func (m *Manager) Start(params WorkerParams) { case <-m.doneChan: return case result := <-m.resultChan: - // TODO: do something useful with result + // TODO: send to tx worker // TODO: let the indexer receiving an update to the script's UTxOs restart the workers logger.Infof("result = %#v", result) // Restart workers as a simple test